From 64f80e84a2b4d0fec87bc5ca8b31360029d8773b Mon Sep 17 00:00:00 2001 From: werner Date: Sun, 16 Aug 2009 04:12:37 +0000 Subject: [PATCH] Columns and loops can now be entered in one step as var = val, val, ... - moved definition of expr_result from expr.c to fpd.y - new header file fpd.h with all the things fpd.l and fpd.y export - edit_var already calls edit_nothing, so there's no need to call it before - added rapid entry option for loops, variables, and columns: var = val, ... git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5459 99fdad57-331a-0410-800a-d7fa5415bdb3 --- TODO | 1 + expr.c | 48 +++++++++++++++++++++++++++++----- expr.h | 5 ++++ fpd.h | 32 +++++++++++++++++++++++ fpd.l | 8 ++++++ fpd.y | 28 +++++++++++++++++--- fped.c | 4 +-- gui_frame.c | 72 ++++++++++++++++++++++++++++++++++++++++++--------- gui_status.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gui_status.h | 4 +++ 10 files changed, 249 insertions(+), 26 deletions(-) create mode 100644 fpd.h diff --git a/TODO b/TODO index 2863ffa..ec9f086 100644 --- a/TODO +++ b/TODO @@ -26,6 +26,7 @@ Bugs: - default silk width has no business being hard-coded in obj.c - undelete only works if not much has changed since the deletion - focus should return to canvas if nobody else wants it +- whenever we call parse_* for input parsing, we may leak lots of expressions Code cleanup: - merge edit_unique with edit_name diff --git a/expr.c b/expr.c index 08e3f07..f81ce1a 100644 --- a/expr.c +++ b/expr.c @@ -18,6 +18,7 @@ #include "error.h" #include "obj.h" #include "unparse.h" +#include "fpd.h" #include "expr.h" @@ -449,13 +450,6 @@ struct expr *new_num(struct num num) /* ----- expression-only parser -------------------------------------------- */ -void scan_expr(const char *s); -int yyparse(void); - - -struct expr *expr_result; - - struct expr *parse_expr(const char *s) { scan_expr(s); @@ -487,3 +481,43 @@ void free_expr(struct expr *expr) vacate_op(expr); free(expr); } + + +/* ----- var = value, ... shortcut ----------------------------------------- */ + + +int parse_var(const char *s, const char **id, struct value **values, + int max_values) +{ + const struct value *value; + int n; + + scan_var(s); + if (yyparse()) + return -1; + if (id) + *id = var_id; + if (values) + *values = var_value_list; + n = 0; + for (value = var_value_list; value; value = value->next) + n++; + if (max_values == -1 || n <= max_values) + return n; + free_values(var_value_list, 0); + return -1; +} + + +void free_values(struct value *values, int keep_expr) +{ + struct value *next; + + while (values) { + next = values->next; + if (!keep_expr) + free_expr(values->expr); + free(values); + values = next; + } +} diff --git a/expr.h b/expr.h index fd6c104..a8a704c 100644 --- a/expr.h +++ b/expr.h @@ -22,6 +22,7 @@ struct frame; struct expr; +struct value; enum num_type { nt_none, @@ -137,4 +138,8 @@ struct expr *new_num(struct num num); struct expr *parse_expr(const char *s); void free_expr(struct expr *expr); +int parse_var(const char *s, const char **id, struct value **values, + int max_values); +void free_values(struct value *values, int keep_expr); + #endif /* !EXPR_H */ diff --git a/fpd.h b/fpd.h new file mode 100644 index 0000000..c2c7a87 --- /dev/null +++ b/fpd.h @@ -0,0 +1,32 @@ +/* + * fpd.c - Things fpd.l and fpd.y export + * + * 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. + */ + + +#ifndef FPD_H +#define FPD_H + +#include "expr.h" +#include "obj.h" + + +extern struct expr *expr_result; +extern const char *var_id; +extern struct value *var_value_list; + + +void scan_empty(void); +void scan_expr(const char *s); +void scan_var(const char *s); + +int yyparse(void); + +#endif /* !FPD_H */ diff --git a/fpd.l b/fpd.l index ae42c23..e6d4857 100644 --- a/fpd.l +++ b/fpd.l @@ -19,6 +19,7 @@ #include "expr.h" #include "error.h" #include "meas.h" +#include "fpd.h" #include "y.tab.h" @@ -41,6 +42,13 @@ void scan_expr(const char *s) yy_scan_string(s); } + +void scan_var(const char *s) +{ + start_token = START_VAR; + yy_scan_string(s); +} + %} diff --git a/fpd.y b/fpd.y index 8d0ca36..b55f9ea 100644 --- a/fpd.y +++ b/fpd.y @@ -19,9 +19,13 @@ #include "expr.h" #include "obj.h" #include "meas.h" +#include "fpd.h" -extern struct expr *expr_result; +struct expr *expr_result; +const char *var_id; +struct value *var_value_list; + static struct frame *curr_frame; static struct table *curr_table; @@ -149,7 +153,7 @@ static struct obj *new_obj(enum obj_type type) }; -%token START_FPD START_EXPR +%token START_FPD START_EXPR START_VAR %token TOK_SET TOK_LOOP TOK_PART TOK_FRAME TOK_TABLE TOK_VEC %token TOK_PAD TOK_RPAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC %token TOK_MEAS TOK_MEASX TOK_MEASY @@ -162,7 +166,7 @@ static struct obj *new_obj(enum obj_type type) %type table %type vars var %type rows -%type row value +%type row value opt_value_list %type vec base qbase %type obj meas %type expr opt_expr add_expr mult_expr unary_expr primary_expr @@ -178,7 +182,6 @@ all: root_frame = zalloc_type(struct frame); set_frame(root_frame); } - fpd { root_frame->prev = last_frame; @@ -191,6 +194,11 @@ all: { expr_result = $2; } + | START_VAR ID opt_value_list + { + var_id = $2; + var_value_list = $3; + } ; fpd: @@ -652,3 +660,15 @@ primary_expr: $$ = $2; } ; + +/* special sub-grammar */ + +opt_value_list: + { + $$ = NULL; + } + | '=' row + { + $$ = $2; + } + ; diff --git a/fped.c b/fped.c index e608bc9..79afb99 100644 --- a/fped.c +++ b/fped.c @@ -22,11 +22,9 @@ #include "inst.h" #include "file.h" #include "gui.h" +#include "fpd.h" -extern void scan_empty(void); -extern int yyparse(void); - char *save_file_name = NULL; diff --git a/gui_frame.c b/gui_frame.c index 5ae2501..079ad06 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -451,7 +451,8 @@ static void add_sep(GtkWidget *box, int size) /* ----- variable name editor ---------------------------------------------- */ -static int find_var_in_frame(const struct frame *frame, const char *name) +static int find_var_in_frame(const struct frame *frame, const char *name, + const struct var *self) { const struct table *table; const struct loop *loop; @@ -459,10 +460,10 @@ static int find_var_in_frame(const struct frame *frame, const char *name) for (table = frame->tables; table; table = table->next) for (var = table->vars; var; var = var->next) - if (!strcmp(var->name, name)) + if (var != self && !strcmp(var->name, name)) return 1; for (loop = frame->loops; loop; loop = loop->next) - if (!strcmp(loop->var.name, name)) + if (&loop->var != self && !strcmp(loop->var.name, name)) return 1; return 0; } @@ -474,7 +475,7 @@ static int validate_var_name(const char *s, void *ctx) if (!is_id(s)) return 0; - return !find_var_in_frame(var->frame, s); + return !find_var_in_frame(var->frame, s, var); } @@ -486,14 +487,17 @@ static void unselect_var(void *data) } -static void edit_var(struct var *var) +static void edit_var(struct var *var, + void (*set_values)(void *user, const struct value *values, int n_values), + void *user, int max_values) { inst_select_outside(var, unselect_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); + edit_unique_with_values(&var->name, validate_var_name, var, + set_values, user, max_values); } @@ -549,6 +553,29 @@ static GtkWidget *add_activator(GtkWidget *hbox, int active, /* ----- assignments ------------------------------------------------------- */ +static void set_col_values(void *user, const struct value *values, + int n_values) +{ + struct var *var = user; + struct table *table = var->table; + struct value *value; + const struct var *walk; + struct row **row; + + row = &table->rows; + while (values) { + if (!*row) + add_row_here(table, row); + value = (*row)->values; + for (walk = table->vars; walk != var; walk = walk->next) + value = value->next; + value->expr = values->expr; + values = values->next; + row = &(*row)->next; + } +} + + static gboolean assignment_var_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -556,8 +583,7 @@ static gboolean assignment_var_select_event(GtkWidget *widget, switch (event->button) { case 1: - edit_nothing(); - edit_var(var); + edit_var(var, set_col_values, var, -1); break; case 3: pop_up_single_var(var, event); @@ -642,8 +668,7 @@ static gboolean table_var_select_event(GtkWidget *widget, switch (event->button) { case 1: - edit_nothing(); - edit_var(var); + edit_var(var, set_col_values, var, -1); break; case 3: pop_up_table_var(var, event); @@ -750,6 +775,30 @@ static void build_table(GtkWidget *vbox, struct frame *frame, /* ----- loops ------------------------------------------------------------- */ +static void set_loop_values(void *user, const struct value *values, + int n_values) +{ + struct loop *loop = user; + + switch (n_values) { + case 2: + if (loop->to.expr) + free_expr(loop->to.expr); + loop->to.expr = values->next->expr; + /* fall through */ + case 1: + if (loop->from.expr) + free_expr(loop->from.expr); + loop->from.expr = values->expr; + break; + case 0: + break; + default: + abort(); + } +} + + static gboolean loop_var_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -757,8 +806,7 @@ static gboolean loop_var_select_event(GtkWidget *widget, switch (event->button) { case 1: - edit_nothing(); - edit_var(&loop->var); + edit_var(&loop->var, set_loop_values, loop, 2); break; case 3: pop_up_loop_var(loop, event); diff --git a/gui_status.c b/gui_status.c index 9519629..016cbeb 100644 --- a/gui_status.c +++ b/gui_status.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -341,6 +342,78 @@ void edit_unique_null(const char **s, } +/* ----- unique field (variable) optionally followed by values ------------- */ + + +struct edit_unique_with_values_ctx { + const char **s; + int (*validate)(const char *s, void *ctx); + void *ctx; + void (*set_values)(void *user, const struct value *values, + int n_values); + void *user; + int max_values; +}; + + +static enum edit_status unique_with_values_status(const char *s, void *ctx) +{ + const struct edit_unique_with_values_ctx *unique_ctx = ctx; + const char *id; + int n; + + if (!strcmp(s, *unique_ctx->s)) + return es_unchanged; + status_begin_reporting(); + n = parse_var(s, &id, NULL, unique_ctx->max_values); + if (n < 0) + return es_bad; + return !unique_ctx->validate || + unique_ctx->validate(id, unique_ctx->ctx) ? es_good : es_bad; +} + + +static void unique_with_values_store(const char *s, void *ctx) +{ + const struct edit_unique_with_values_ctx *unique_ctx = ctx; + struct value *values; + int n; + + status_begin_reporting(); + n = parse_var(s, unique_ctx->s, &values, unique_ctx->max_values); + if (!n) + return; + assert(n >= 0); + assert(unique_ctx->max_values == -1 || n <= unique_ctx->max_values); + unique_ctx->set_values(unique_ctx->user, values, n); + free_values(values, 1); +} + + +static struct edit_ops edit_ops_unique_with_values = { + .retrieve = unique_retrieve, + .status = unique_with_values_status, + .store = unique_with_values_store, +}; + + +void edit_unique_with_values(const char **s, + int (*validate)(const char *s, void *ctx), void *ctx, + void (*set_values)(void *user, const struct value *values, int n_values), + void *user, int max_values) +{ + static struct edit_unique_with_values_ctx unique_ctx; + + unique_ctx.s = s; + unique_ctx.validate = validate; + unique_ctx.ctx = ctx; + unique_ctx.set_values = set_values; + unique_ctx.user = user; + unique_ctx.max_values = max_values; + setup_edit(status_entry, &edit_ops_unique_with_values, &unique_ctx); +} + + /* ----- string fields ----------------------------------------------------- */ diff --git a/gui_status.h b/gui_status.h index 27f8ab0..bffb218 100644 --- a/gui_status.h +++ b/gui_status.h @@ -24,6 +24,10 @@ void edit_unique(const char **s, int (*validate)(const char *s, void *ctx), void *ctx); void edit_unique_null(const char **s, int (*validate)(const char *s, void *ctx), void *ctx); +void edit_unique_with_values(const char **s, + int (*validate)(const char *s, void *ctx), void *ctx, + void (*set_values)(void *user, const struct value *values, int n_values), + void *user, int max_values); void edit_name(char **s, int (*validate)(const char *s, void *ctx), void *ctx); void edit_expr(struct expr **expr); void edit_x(struct expr **expr);