1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-04 23:37:33 +02:00
fped/unparse.c
werner 386a9fd50b - added support for string constants to unparse()
- implemented eval_str
- expand() now tries to obtain a string
- added example fbga.fpd to demonstrate use of strings
- when invoked with an inexisting file, fped now starts with an empty model,
  instead of getting confused 
- we now religiously call edit_nothing before adding fields to edit, so that
  we won't create a loop through edit-next



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5421 99fdad57-331a-0410-800a-d7fa5415bdb3
2009-08-11 23:26:38 +00:00

114 lines
2.5 KiB
C

/*
* unparse.c - Dump an expression tree into a string
*
* Written 2009 by Werner Almesberger
* Copyright 2009 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* This is crazily inefficient but who cares :-)
*/
#include <stdlib.h>
#include <stdio.h>
#include "util.h"
#include "expr.h"
#include "unparse.h"
enum prec {
prec_add,
prec_mult,
prec_unary,
prec_primary,
};
static int precedence(op_type op)
{
if (op == op_add || op == op_sub)
return prec_add;
if (op == op_mult || op == op_div)
return prec_mult;
if (op == op_minus)
return prec_unary;
if (op == op_num || op == op_string || op == op_var)
return prec_primary;
abort();
}
static char *merge3(char *a, const char *op, char *b)
{
char *buf;
buf = alloc_size(strlen(op)+strlen(a)+strlen(b)+1);
sprintf(buf, "%s%s%s", a, op, b);
free(a);
free(b);
return buf;
}
static char *merge2(const char *op, char *a)
{
char *buf;
buf = alloc_size(strlen(op)+strlen(a)+1);
sprintf(buf, "%s%s", op, a);
free(a);
return buf;
}
static char *unparse_op(const struct expr *expr, enum prec prec)
{
char tmp[100];
char *buf, *temp;
if (prec > precedence(expr->op)) {
temp = unparse_op(expr, prec_add);
buf = alloc_size(strlen(temp)+3);
sprintf(buf, "(%s)", temp);
free(temp);
return buf;
}
if (expr->op == op_num) {
snprintf(tmp, sizeof(tmp), "%lg%s",
expr->u.num.n, str_unit(expr->u.num));
return stralloc(tmp);
}
if (expr->op == op_string)
return stralloc_printf("\"%s\"", expr->u.str);
if (expr->op == op_var)
return stralloc(expr->u.var);
if (expr->op == op_minus)
return merge2("-", unparse_op(expr->u.op.a, prec_add));
if (expr->op == op_add)
return merge3(unparse_op(expr->u.op.a, prec_add), "+",
unparse_op(expr->u.op.b, prec_add));
if (expr->op == op_sub)
return merge3(unparse_op(expr->u.op.a, prec_add), "-",
unparse_op(expr->u.op.b, prec_mult));
if (expr->op == op_mult)
return merge3(unparse_op(expr->u.op.a, prec_mult), "*",
unparse_op(expr->u.op.b, prec_mult));
if (expr->op == op_div)
return merge3(unparse_op(expr->u.op.a, prec_mult), "/",
unparse_op(expr->u.op.b, prec_primary));
abort();
}
char *unparse(const struct expr *expr)
{
return expr ? unparse_op(expr, prec_add) : stralloc("");
}