diff --git a/README b/README index 9be9541..d59e060 100644 --- a/README +++ b/README @@ -555,3 +555,34 @@ b: vec @(1mm, 0mm) measx "width = " a >> b 0mm would print "width = 1mm" + + +Experimental: debugging directives +---------------------------------- + +For debugging and regression tests, fped supports the following commands +that mimick the effect of GUI operations: + +%del +%move [] +%print +%dump +%exit + +%del and %move take as their first argument the name of the vector or +object to manipulate. For this purpose, also objects can be labeled. + +Object labels behave like vector labels and share the same name space. +They are not shown anywhere in the GUI. + +%move sets an anchor point to the vector named as its last argument. +The anchor point is identified by index as follows: + +anchor index vec/frame line/rect/pad arc measurement +-------------- --------- ------------- ------------ ----------- +0 (or omitted) base first point center low point +1 - second point end of arc high point +2 - - start of arc - + +%dump writes the footprint definition in the fped language to standard +output. %exit immediately exits fped, without invoking the GUI. diff --git a/dump.c b/dump.c index cce64b2..bbd71bd 100644 --- a/dump.c +++ b/dump.c @@ -1,8 +1,8 @@ /* * dump.c - Dump objects in the native FPD format * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 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 @@ -484,8 +484,11 @@ static void dump_frame(FILE *file, struct frame *frame, const char *indent) order = order_frame(frame); for (item = order; item->vec || item->obj; item++) { if (item->obj) { + fprintf(file, "%s", indent); + if (item->obj->name) + fprintf(file, "%s: ", item->obj->name); s = print_obj(item->obj, item->vec); - fprintf(file, "%s%s\n", indent, s); + fprintf(file, "%s\n", s); } else { s1 = print_label(item->vec); s = print_vec(item->vec); diff --git a/expr.c b/expr.c index 19aca0c..c8535c2 100644 --- a/expr.c +++ b/expr.c @@ -55,7 +55,7 @@ const char *str_unit(struct num n) char buf[20]; /* @@@ plenty */ if (n.exponent == 0) - return stralloc(""); + return ""; switch (n.type) { case nt_mm: unit = "mm"; diff --git a/fpd.l b/fpd.l index b9dc821..4f79dae 100644 --- a/fpd.l +++ b/fpd.l @@ -121,6 +121,17 @@ SP [\t ]* "unit" { BEGIN(NOKEYWORD); return TOK_UNIT; } +"%del" { BEGIN(NOKEYWORD); + return TOK_DBG_DEL; } +"%move" { BEGIN(NOKEYWORD); + return TOK_DBG_MOVE; } +"%print" { BEGIN(NOKEYWORD); + return TOK_DBG_PRINT; } +"%dump" { BEGIN(NOKEYWORD); + return TOK_DBG_DUMP; } +"%exit" { BEGIN(NOKEYWORD); + return TOK_DBG_EXIT; } + [a-zA-Z_][a-zA-Z_0-9]*: { *strchr(yytext, ':') = 0; yylval.id = unique(yytext); return LABEL; } diff --git a/fpd.y b/fpd.y index 2d4e962..ce4d2e2 100644 --- a/fpd.y +++ b/fpd.y @@ -21,6 +21,7 @@ #include "obj.h" #include "meas.h" #include "gui_status.h" +#include "dump.h" #include "fpd.h" @@ -68,6 +69,27 @@ static struct vec *find_vec(const struct frame *frame, const char *name) } +static struct obj *find_obj(const struct frame *frame, const char *name) +{ + struct obj *obj; + + for (obj = frame->objs; obj; obj = obj->next) + if (obj->name == name) + return obj; + return NULL; +} + + +static int find_label(const struct frame *frame, const char *name) +{ + if (find_vec(frame, name)) + return 1; + if (find_obj(frame, name)) + return 1; + return 0; +} + + static struct var *find_var(const struct frame *frame, const char *name) { const struct table *table; @@ -145,6 +167,7 @@ static struct obj *new_obj(enum obj_type type) obj = alloc_type(struct obj); obj->type = type; + obj->name = NULL; obj->frame = curr_frame; obj->next = NULL; obj->lineno = lineno; @@ -152,6 +175,80 @@ static struct obj *new_obj(enum obj_type type) } +static int dbg_delete(const char *name) +{ + struct vec *vec; + struct obj *obj; + + vec = find_vec(curr_frame, name); + if (vec) { + delete_vec(vec); + return 1; + } + obj = find_obj(curr_frame, name); + if (obj) { + delete_obj(obj); + return 1; + } + yyerrorf("unknown item \"%s\"", name); + return 0; +} + + +static int dbg_move(const char *name, int anchor, const char *dest) +{ + struct vec *to, *vec; + struct obj *obj; + struct vec **anchors[3]; + int n_anchors; + + to = find_vec(curr_frame, dest); + if (!to) { + yyerrorf("unknown vector \"%s\"", dest); + return 0; + } + vec = find_vec(curr_frame, name); + if (vec) { + if (anchor) { + yyerrorf("invalid anchor (%d > 0)", anchor); + return 0; + } + vec->base = to; + return 1; + } + obj = find_obj(curr_frame, name); + if (!obj) { + yyerrorf("unknown item \"%s\"", name); + return 0; + } + n_anchors = obj_anchors(obj, anchors); + if (anchor >= n_anchors) { + yyerrorf("invalid anchor (%d > %d)", anchor, n_anchors-1); + return 0; + } + *anchors[anchor] = to; + return 1; +} + + +static int dbg_print(const struct expr *expr) +{ + const char *s; + struct num num; + + s = eval_str(expr, curr_frame); + if (s) { + printf("%s\n", s); + return 1; + } + num = eval_num(expr, curr_frame); + if (is_undef(num)) + return 0; + printf("%lg%s\n", num.n, str_unit(num)); + return 1; +} + + %} @@ -181,6 +278,8 @@ static struct obj *new_obj(enum obj_type type) %token TOK_PAD TOK_RPAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC %token TOK_MEAS TOK_MEASX TOK_MEASY TOK_UNIT %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED +%token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_PRINT TOK_DBG_DUMP +%token TOK_DBG_EXIT %token NUMBER %token STRING @@ -191,8 +290,9 @@ static struct obj *new_obj(enum obj_type type) %type rows %type row value opt_value_list %type vec base qbase -%type obj meas +%type object obj meas %type expr opt_expr add_expr mult_expr unary_expr primary_expr +%type opt_num %type opt_string %type pad_type %type meas_type @@ -323,16 +423,46 @@ frame_item: | vec | LABEL vec { - if (find_vec(curr_frame, $1)) { - yyerrorf("duplicate vector \"%s\"", $1); + if (find_label(curr_frame, $1)) { + yyerrorf("duplicate label \"%s\"", $1); YYABORT; } $2->name = $1; } - | obj + | object + | LABEL object { - *next_obj = $1; - next_obj = &$1->next; + if (find_label(curr_frame, $1)) { + yyerrorf("duplicate label \"%s\"", $1); + YYABORT; + } + $2->name = $1; + } + | TOK_DBG_DEL ID + { + if (!dbg_delete($2)) + YYABORT; + } + | TOK_DBG_MOVE ID opt_num ID + { + if (!dbg_move($2, $3.n, $4)) + YYABORT; + } + | TOK_DBG_PRINT expr + { + if (!dbg_print($2)) + YYABORT; + } + | TOK_DBG_DUMP + { + if (!dump(stdout)) { + perror("stdout"); + exit(1); + } + } + | TOK_DBG_EXIT + { + exit(0); } ; @@ -478,6 +608,15 @@ base: } ; +object: + obj + { + $$ = $1; + *next_obj = $1; + next_obj = &$1->next; + } + ; + obj: TOK_PAD STRING base base pad_type { @@ -650,6 +789,16 @@ meas_op: } ; +opt_num: + { + $$.n = 0; + } + | NUMBER + { + $$ = $1; + } + ; + opt_string: { $$ = NULL; diff --git a/inst.c b/inst.c index b9dee56..02e7883 100644 --- a/inst.c +++ b/inst.c @@ -421,7 +421,11 @@ struct vec *inst_get_vec(const struct inst *inst) int inst_anchors(struct inst *inst, struct vec ***anchors) { - return inst->ops->anchors ? inst->ops->anchors(inst, anchors) : 0; + if (inst->vec) { + anchors[0] = &inst->vec->base; + return 1; + } + return obj_anchors(inst->obj, anchors); } @@ -658,13 +662,6 @@ static struct inst *find_point_vec(struct inst *self, struct coord pos) } -static int vec_op_anchors(struct inst *inst, struct vec ***anchors) -{ - anchors[0] = &inst->vec->base; - return 1; -} - - /* * When instantiating and when dumping, we assume that bases appear in the * frame->vecs list before vectors using them. A move may change this order. @@ -729,7 +726,6 @@ static struct inst_ops vec_ops = { .distance = gui_dist_vec, .select = vec_op_select, .find_point = find_point_vec, - .anchors = vec_op_anchors, .draw_move = draw_move_vec, .do_move_to = do_move_to_vec, }; @@ -765,21 +761,10 @@ static void line_op_select(struct inst *self) } -static int line_op_anchors(struct inst *inst, struct vec ***anchors) -{ - struct obj *obj = inst->obj; - - anchors[0] = &obj->base; - anchors[1] = &obj->u.rect.other; - return 2; -} - - static struct inst_ops line_ops = { .draw = gui_draw_line, .distance = gui_dist_line, .select = line_op_select, - .anchors = line_op_anchors, .draw_move = draw_move_line, }; @@ -820,7 +805,6 @@ static struct inst_ops rect_ops = { .draw = gui_draw_rect, .distance = gui_dist_rect, .select = rect_op_select, - .anchors = line_op_anchors, .draw_move = draw_move_rect, }; @@ -874,21 +858,10 @@ static void pad_op_select(struct inst *self) } -static int pad_op_anchors(struct inst *inst, struct vec ***anchors) -{ - struct obj *obj = inst->obj; - - anchors[0] = &obj->base; - anchors[1] = &obj->u.pad.other; - return 2; -} - - static struct inst_ops pad_ops = { .draw = gui_draw_pad, .distance = gui_dist_pad, .select = pad_op_select, - .anchors = pad_op_anchors, .draw_move = draw_move_pad, }; @@ -906,7 +879,6 @@ static struct inst_ops rpad_ops = { .draw = gui_draw_rpad, .distance = gui_dist_pad, /* @@@ */ .select = rpad_op_select, - .anchors = pad_op_anchors, .draw_move = draw_move_rpad, }; @@ -951,26 +923,10 @@ static void arc_op_select(struct inst *self) } -static int arc_op_anchors(struct inst *inst, struct vec ***anchors) -{ - struct obj *obj = inst->obj; - - /* - * Put end point first so that this is what we grab if dragging a - * circle (thereby turning it into an arc). - */ - anchors[0] = &obj->base; - anchors[1] = &obj->u.arc.end; - anchors[2] = &obj->u.arc.start; - return 3; -} - - static struct inst_ops arc_ops = { .draw = gui_draw_arc, .distance = gui_dist_arc, .select = arc_op_select, - .anchors = arc_op_anchors, .draw_move = draw_move_arc, .do_move_to = do_move_to_arc, }; @@ -1022,21 +978,10 @@ static void meas_op_select(struct inst *self) } -static int meas_op_anchors(struct inst *inst, struct vec ***anchors) -{ - struct obj *obj = inst->obj; - - anchors[0] = &obj->base; - anchors[1] = &obj->u.meas.high; - return 2; -} - - static struct inst_ops meas_ops = { .draw = gui_draw_meas, .distance = gui_dist_meas, .select = meas_op_select, - .anchors = meas_op_anchors, .begin_drag_move= begin_drag_move_meas, .find_point = find_point_meas_move, .draw_move = draw_move_meas, @@ -1146,19 +1091,11 @@ static void frame_op_select(struct inst *self) } -static int frame_op_anchors(struct inst *inst, struct vec ***anchors) -{ - anchors[0] = &inst->obj->base; - return 1; -} - - static struct inst_ops frame_ops = { .draw = gui_draw_frame, .hover = gui_hover_frame, .distance = gui_dist_frame, .select = frame_op_select, - .anchors = frame_op_anchors, .draw_move = draw_move_frame, }; diff --git a/inst.h b/inst.h index ead6f00..3cd2c7d 100644 --- a/inst.h +++ b/inst.h @@ -61,7 +61,6 @@ struct inst_ops { unit_type (*distance)(struct inst *self, struct coord pos, unit_type scale); void (*select)(struct inst *self); - int (*anchors)(struct inst *self, struct vec ***anchors); void (*begin_drag_move)(struct inst *from, int i); struct inst *(*find_point)(struct inst *self, struct coord pos); struct pix_buf *(*draw_move)(struct inst *inst, diff --git a/obj.c b/obj.c index 89ccd72..22f2ad5 100644 --- a/obj.c +++ b/obj.c @@ -96,6 +96,39 @@ void search_inst(const struct inst *inst) } +/* ----- Get the list of anchors of an object ------------------------------ */ + + +int obj_anchors(struct obj *obj, struct vec ***anchors) +{ + anchors[0] = &obj->base; + switch (obj->type) { + case ot_frame: + return 1; + case ot_rect: + case ot_line: + anchors[1] = &obj->u.rect.other; + return 2; + case ot_pad: + anchors[1] = &obj->u.pad.other; + return 2; + case ot_meas: + anchors[1] = &obj->u.meas.high; + return 2; + case ot_arc: + /* + * Put end point first so that this is what we grab if dragging + * a circle (thereby turning it into an arc). + */ + anchors[1] = &obj->u.arc.end; + anchors[2] = &obj->u.arc.start; + return 3; + default: + abort(); + } +} + + /* ----- Instantiation ----------------------------------------------------- */ diff --git a/obj.h b/obj.h index 83a215a..7b54e73 100644 --- a/obj.h +++ b/obj.h @@ -205,6 +205,7 @@ struct arc { struct obj { enum obj_type type; + const char *name; /* NULL if anonymous */ union { struct frame_ref frame; struct rect rect; @@ -251,6 +252,8 @@ void find_inst(const struct inst *inst); void search_inst(const struct inst *inst); +int obj_anchors(struct obj *obj, struct vec ***anchors); + int instantiate(void); void obj_cleanup(void);