From 386a9fd50b7bccac878840a6d2736cf9d11c76ad Mon Sep 17 00:00:00 2001 From: werner Date: Tue, 11 Aug 2009 23:26:38 +0000 Subject: [PATCH] - 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 --- TODO | 3 +++ expr.c | 72 ++++++++++++++++++++++++++++++++++++++++++----------- expr.h | 8 +++++- fbga.fpd | 52 ++++++++++++++++++++++++++++++++++++++ file.c | 28 ++++++++++++++------- file.h | 5 ++++ fped.c | 8 ++++-- gui_frame.c | 20 ++++++++++++--- unparse.c | 4 ++- 9 files changed, 170 insertions(+), 30 deletions(-) create mode 100644 fbga.fpd diff --git a/TODO b/TODO index 31acefe..96c48d0 100644 --- a/TODO +++ b/TODO @@ -39,6 +39,9 @@ Code cleanup: - code organization is very poor. E.g., functions belonging to the different items (pads, silk objects, vectors, etc.) should be grouped by item, not by type of function, similar to how some things are now with gui_meas.c +- eval_string_var should be merged into eval_var and the result should be a + struct num (?) that can contain both types. This also means changing all the + ops to handle/reject strings. Open decisions: - Q: should loop be (start, last) or (start, iterations) ? or start ... last ? diff --git a/expr.c b/expr.c index 3e3d580..08e3f07 100644 --- a/expr.c +++ b/expr.c @@ -154,6 +154,38 @@ struct num eval_var(const struct frame *frame, const char *name) } +static const char *eval_string_var(const struct frame *frame, const char *name) +{ + const struct table *table; + const struct loop *loop; + const struct value *value; + struct var *var; + const char *res; + + for (table = frame->tables; table; table = table->next) { + value = table->curr_row->values; + for (var = table->vars; var; var = var->next) { + if (var->name == name) { + if (var->visited) + return NULL; + var->visited = 1; + res = eval_str(value->expr, frame); + var->visited = 0; + return res; + + } + value = value->next; + } + } + for (loop = frame->loops; loop; loop = loop->next) + if (loop->var.name == name) + return NULL; + if (frame->curr_parent) + return eval_string_var(frame->curr_parent, name); + return NULL; +} + + struct num op_var(const struct expr *self, const struct frame *frame) { struct num res; @@ -307,9 +339,13 @@ struct expr *binary_op(op_type op, struct expr *a, struct expr *b) } -char *eval_str(const struct frame *frame, const struct expr *expr) +const char *eval_str(const struct expr *expr, const struct frame *frame) { - abort(); + if (expr->op == op_string) + return expr->u.str; + if (expr->op == op_var) + return eval_string_var(frame, expr->u.var); + return NULL; } @@ -329,7 +365,7 @@ char *expand(const char *name, const struct frame *frame) char num_buf[100]; /* enough :-) */ const char *s, *s0; char *var; - const char *var_unique; + const char *var_unique, *value_string; struct num value; int i, value_len; @@ -366,18 +402,24 @@ char *expand(const char *name, const struct frame *frame) continue; var_unique = unique(var); free(var); - value = eval_var(frame, var_unique); - if (is_undef(value)) { - fail("undefined variable \"%s\"", var_unique); - goto fail; + value_string = eval_string_var(frame, var_unique); + if (value_string) + value_len = strlen(value_string); + else { + value = eval_var(frame, var_unique); + if (is_undef(value)) { + fail("undefined variable \"%s\"", var_unique); + goto fail; + } + value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s", + value.n, str_unit(value)); + value_string = num_buf; } - value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s", - value.n, str_unit(value)); len += value_len; buf = realloc(buf, len+1); if (!buf) abort(); - strcpy(buf+i, num_buf); + strcpy(buf+i, value_string); i += value_len; } buf[i] = 0; @@ -410,6 +452,7 @@ struct expr *new_num(struct num num) void scan_expr(const char *s); int yyparse(void); + struct expr *expr_result; @@ -422,14 +465,15 @@ struct expr *parse_expr(const char *s) static void vacate_op(struct expr *expr) { - if (expr->op == &op_num || expr->op == &op_var) + if (expr->op == op_num || expr->op == op_string || + expr->op == op_var) return; - if (expr->op == &op_minus) { + if (expr->op == op_minus) { free_expr(expr->u.op.a); return; } - if (expr->op == &op_add || expr->op == &op_sub || - expr->op == &op_mult || expr->op == &op_div) { + if (expr->op == op_add || expr->op == op_sub || + expr->op == op_mult || expr->op == op_div) { free_expr(expr->u.op.a); free_expr(expr->u.op.b); return; diff --git a/expr.h b/expr.h index 3276dbb..fd6c104 100644 --- a/expr.h +++ b/expr.h @@ -121,7 +121,13 @@ struct expr *new_op(op_type op); struct expr *binary_op(op_type op, struct expr *a, struct expr *b); struct num eval_var(const struct frame *frame, const char *name); -char *eval_str(const struct frame *frame, const struct expr *expr); + +/* + * eval_str returns NULL if the result isn't a string. Evaluation may then + * be attempted with eval_num, and the result can be converted accordingly. + */ +const char *eval_str(const struct expr *expr, const struct frame *frame); + struct num eval_num(const struct expr *expr, const struct frame *frame); /* if frame == NULL, we only check the syntax without expanding */ diff --git a/fbga.fpd b/fbga.fpd new file mode 100644 index 0000000..6f887b1 --- /dev/null +++ b/fbga.fpd @@ -0,0 +1,52 @@ +/* MACHINE-GENERATED ! */ + +frame pad { + set Px = 0.5mm + + set Py = 0.5mm + + set cname = col+1 + + __0: vec @(col*1mm-Px/2, row*-1mm-Py/2) + __1: vec .(0mm, Py) + __2: vec __0(Px, 0mm) + pad "$rname$cname" __1 __2 +} + +frame inner { + loop col = c0, c1 + + frame pad @ +} + +frame last { + loop col = 4, 5 + + frame pad @ +} + +frame first { + loop col = 0, 1 + + frame pad @ +} + +part "Fake_BGA" +table + { row, rname, c0, c1 } + { 0, "A", 2, 3 } + { 1, "B", 2, 3 } + { 2, "C", 9, 0 } + { 3, "D", 9, 0 } + { 4, "E", 2, 3 } + { 5, "F", 2, 3 } + +frame last @ +frame first @ +frame inner @ +measy pad.__0 -> pad.__1 0.2mm +measy pad.__0 -> pad.__0 0.5mm +measx pad.__0 -> pad.__2 -0.3mm +measx pad.__0 -> pad.__0 -0.6mm +measy pad.__0 >> pad.__1 0.8mm +measx pad.__0 >> pad.__2 -0.9mm diff --git a/file.c b/file.c index 2547e42..0422557 100644 --- a/file.c +++ b/file.c @@ -47,6 +47,19 @@ char *set_extension(const char *name, const char *ext) } +int file_exists(const char *name) +{ + struct stat st; + + if (stat(name, &st) >= 0) + return 1; + if (errno == ENOENT) + return 0; + perror(name); + return -1; +} + + int save_to(const char *name, int (*fn)(FILE *file)) { FILE *file; @@ -73,8 +86,7 @@ void save_with_backup(const char *name, int (*fn)(FILE *file)) char *s = stralloc(name); char *back, *tmp; char *slash, *dot; - int n; - struct stat st; + int n, res; /* save to temporary file */ @@ -99,14 +111,12 @@ void save_with_backup(const char *name, int (*fn)(FILE *file)) while (1) { back = stralloc_printf("%s~%d%s%s", s, n, dot ? "." : "", dot ? dot+1 : ""); - if (stat(back, &st) < 0) { - if (errno == ENOENT) - break; - perror(back); - free(back); - return; - } + res = file_exists(back); + if (!res) + break; free(back); + if (res < 0) + return; n++; } if (rename(name, back) < 0) { diff --git a/file.h b/file.h index d201258..95995ec 100644 --- a/file.h +++ b/file.h @@ -17,6 +17,11 @@ #include +/* + * Returns -1 on error. + */ +int file_exists(const char *name); + char *set_extension(const char *name, const char *ext); int save_to(const char *name, int (*fn)(FILE *file)); void save_with_backup(const char *name, int (*fn)(FILE *file)); diff --git a/fped.c b/fped.c index 284b8b0..e608bc9 100644 --- a/fped.c +++ b/fped.c @@ -32,8 +32,12 @@ char *save_file_name = NULL; static void load_file(const char *name) { - reporter = report_parse_error; - run_cpp_on_file(name); + if (file_exists(name) == 1) { + reporter = report_parse_error; + run_cpp_on_file(name); + } else { + scan_empty(); + } (void) yyparse(); } diff --git a/gui_frame.c b/gui_frame.c index 7cd4194..d228bce 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -487,6 +487,7 @@ static void edit_var(struct var *var) label_in_box_bg(var->widget, COLOR_VAR_EDITING); status_set_type_entry("name ="); status_set_name("%s", var->name); + edit_nothing(); edit_unique(&var->name, validate_var_name, var); } @@ -508,6 +509,7 @@ static void edit_value(struct value *value) { inst_select_outside(value, unselect_value); label_in_box_bg(value->widget, COLOR_EXPR_EDITING); + edit_nothing(); edit_expr(&value->expr); } @@ -549,6 +551,7 @@ static gboolean assignment_var_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_var(var); break; case 3: @@ -566,6 +569,7 @@ static gboolean assignment_value_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_value(value); break; } @@ -633,6 +637,7 @@ static gboolean table_var_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_var(var); break; case 3: @@ -650,9 +655,11 @@ static gboolean table_value_select_event(GtkWidget *widget, switch (event->button) { case 1: - if (!value->row || value->row->table->active_row == value->row) + if (!value->row || + value->row->table->active_row == value->row) { + edit_nothing(); edit_value(value); - else { + } else { select_row(value->row); change_world(); } @@ -745,6 +752,7 @@ static gboolean loop_var_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_var(&loop->var); break; case 3: @@ -762,6 +770,7 @@ static gboolean loop_from_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_value(&loop->from); break; } @@ -776,6 +785,7 @@ static gboolean loop_to_select_event(GtkWidget *widget, switch (event->button) { case 1: + edit_nothing(); edit_value(&loop->to); break; } @@ -940,6 +950,7 @@ static gboolean part_name_edit_event(GtkWidget *widget, GdkEventButton *event, label_in_box_bg(widget, COLOR_PART_NAME_EDITING); status_set_type_entry("part ="); status_set_name("%s", part_name); + edit_nothing(); edit_name(&part_name, validate_part_name, NULL); break; } @@ -1001,6 +1012,7 @@ static void edit_frame(struct frame *frame) label_in_box_bg(frame->label, COLOR_FRAME_EDITING); status_set_type_entry("name ="); status_set_name("%s", frame->name); + edit_nothing(); edit_unique(&frame->name, validate_frame_name, frame); } @@ -1025,8 +1037,10 @@ static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event, if (active_frame != frame) select_frame(frame); else { - if (active_frame->name) + if (active_frame->name) { + edit_nothing(); edit_frame(frame); + } } break; case 3: diff --git a/unparse.c b/unparse.c index b28a1dd..f0b5996 100644 --- a/unparse.c +++ b/unparse.c @@ -38,7 +38,7 @@ static int precedence(op_type op) return prec_mult; if (op == op_minus) return prec_unary; - if (op == op_num || op == op_var) + if (op == op_num || op == op_string || op == op_var) return prec_primary; abort(); } @@ -85,6 +85,8 @@ static char *unparse_op(const struct expr *expr, enum prec prec) 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)