From cdcd2f36b395fdb1bdec3a213dbbdadccc6c248d Mon Sep 17 00:00:00 2001 From: werner Date: Wed, 5 Aug 2009 10:35:48 +0000 Subject: [PATCH] - started functions to dump .fpd files (automatic labeling doesn't quite work yet) - don't pass argc, argv to gui_main. They've been harvested before. git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5388 99fdad57-331a-0410-800a-d7fa5415bdb3 --- Makefile | 2 +- TODO | 2 + delete.h | 2 +- dump.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dump.h | 22 ++++ fped.c | 5 +- gui.c | 2 +- gui.h | 2 +- 8 files changed, 358 insertions(+), 5 deletions(-) create mode 100644 dump.c create mode 100644 dump.h diff --git a/Makefile b/Makefile index bb2c6ad..6a5a12c 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ # OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ - unparse.o \ + unparse.o dump.o \ cpp.o lex.yy.o y.tab.o \ gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \ gui_tools.o diff --git a/TODO b/TODO index 505a048..18ba2be 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,7 @@ Missing features: - add KiCad output - add postscript output - add option to include/omit helper vecs and frames (display and postscript) +- define part name Error detection: - eliminate duplicate instances @@ -15,6 +16,7 @@ Error detection: Style: - make column of entry field greedily consume all unallocated space - status area looks awful +- status area bounces when something becomes editable Bugs: - default silk width has no business being hard-coded in obj.c diff --git a/delete.h b/delete.h index 993a664..85495f7 100644 --- a/delete.h +++ b/delete.h @@ -23,4 +23,4 @@ int delete_obj(struct obj *obj); int destroy(void); int undelete(void); -#endif /* !OBJ_H */ +#endif /* !DELETE_H */ diff --git a/dump.c b/dump.c new file mode 100644 index 0000000..9e8195d --- /dev/null +++ b/dump.c @@ -0,0 +1,326 @@ +/* + * dump.c - Dump objects in the native FPD format + * + * 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. + */ + + +#include +#include + +#include "util.h" +#include "unparse.h" +#include "obj.h" +#include "dump.h" + + +/* ----- variables --------------------------------------------------------- */ + + +static void dump_var(FILE *file, const struct table *table, + const char *indent) +{ + char *s; + + s = unparse(table->rows->values->expr); + fprintf(file, "%sset %s = %s\n\n", indent, table->vars->name, s); + free(s); +} + + +static void dump_table(FILE *file, const struct table *table, + const char *indent) +{ + const struct var *var; + const struct row *row; + const struct value *value; + char *s; + + if (table->vars && !table->vars->next && + table->rows && !table->rows->next) { + dump_var(file, table, indent); + return; + } + fprintf(file, "%stable\n%s {", indent, indent); + for (var = table->vars; var; var = var->next) + fprintf(file, "%s %s", var == table->vars ? "" : ",", + var->name); + fprintf(file, " }\n"); + for (row = table->rows; row; row = row->next) { + fprintf(file, "%s {", indent); + for (value = row->values; value; value = value->next) { + s = unparse(value->expr); + fprintf(file, "%s %s", + value == row->values? "" : ",", s); + free(s); + } + fprintf(file, " }\n"); + } + fprintf(file, "\n"); +} + + +static void dump_loop(FILE *file, const struct loop *loop, const char *indent) +{ + char *from, *to; + + from = unparse(loop->from.expr); + to = unparse(loop->to.expr); + fprintf(file, "%sloop %s = %s, %s\n\n", + indent, loop->var.name, from, to); + free(from); + free(to); +} + + +/* ----- vectors and objects ----------------------------------------------- */ + + +static char *base_name(const struct vec *vec, const struct vec *base) +{ + const struct vec *walk; + int n; + + if (!base) + return stralloc("@"); + if (vec && base->next == vec) + return stralloc("."); + if (base->name) + return stralloc(base->name); + n = 0; + for (walk = base->frame->vecs; walk != base; walk = walk->next) + n++; + return stralloc_printf("_%s_%d", + base->frame->name ? base->frame->name : "", n); +} + + +static char *obj_base_name(const struct vec *base, const struct vec *prev) +{ + if (base && base == prev) + return stralloc("."); + return base_name(NULL, base); +} + + +static int n_vec_refs(const struct vec *vec) +{ + const struct vec *walk; + int n; + + if (!vec->n_refs) + return 0; + n = 0; + for (walk = vec->frame->vecs; walk; walk = walk->next) + if (walk->base == vec) + n++; + return n; +} + + +/* + * "need" operates in two modes: + * + * - if "prev" is non-NULL, we're looking for objects that need to be put after + * the current vector (in "prev"). Only those objects need to be put there + * that have at least one base that isn't the frame's origin or already has a + * name. + * + * - if "prev" is NULL, we're at the end of the frame. We have already used all + * the . references we could, so now we have to find out which objects + * haven't been dumped yet. "need" still returns the ones that had a need to + * be dumped. Again, that's those that have at least one possible "." base. + * Since this "." base will have been used by now, the object must have been + * dumped. + */ + +static int need(const struct vec *base, const struct vec *prev) +{ + if (!base) + return 0; + if (base->name) + return 0; + if (prev) + return base == prev; + return 1; +} + + +static void dump_obj(FILE *file, const struct obj *obj, const char *indent, + const struct vec *prev) +{ + char *base, *s1, *s2, *s3; + int n; + + n = need(obj->base, prev); + + switch (obj->type) { + case ot_frame: + break; + case ot_line: + n |= need(obj->u.line.other, prev); + break; + case ot_rect: + n |= need(obj->u.rect.other, prev); + break; + case ot_pad: + n |= need(obj->u.pad.other, prev); + break; + case ot_arc: + n |= need(obj->u.arc.start, prev); + n |= need(obj->u.arc.end, prev); + break; + case ot_meas: + n |= need(obj->u.meas.other, prev); + break; + default: + abort(); + } + + if (prev ? !n : n) + return; + + base = obj_base_name(obj->base, prev); + switch (obj->type) { + case ot_frame: + fprintf(file, "%sframe %s %s\n", + indent, obj->u.frame.ref->name, base); + break; + case ot_line: + s1 = obj_base_name(obj->u.line.other, prev); + s2 = unparse(obj->u.line.width); + fprintf(file, "%sline %s %s %s\n", indent, base, s1, s2); + free(s1); + free(s2); + break; + case ot_rect: + s1 = obj_base_name(obj->u.rect.other, prev); + s2 = unparse(obj->u.rect.width); + fprintf(file, "%srect %s %s %s\n", indent, base, s1, s2); + free(s1); + free(s2); + break; + case ot_pad: + s1 = obj_base_name(obj->u.pad.other, prev); + fprintf(file, "%spad \"%s\" %s %s\n", indent, + obj->u.pad.name, base, s1); + free(s1); + break; + case ot_arc: + s1 = obj_base_name(obj->u.arc.start, prev); + s3 = unparse(obj->u.arc.width); + if (obj->u.arc.start == obj->u.arc.end) { + fprintf(file, "%scirc %s %s %s\n", + indent, base, s1, s3); + } else { + s2 = obj_base_name(obj->u.arc.end, prev); + fprintf(file, "%sarc %s %s %s %s\n", indent, + base, s1, s2, s3); + free(s2); + } + free(s1); + free(s3); + break; + case ot_meas: + s1 = obj_base_name(obj->u.meas.other, prev); + s2 = unparse(obj->u.meas.offset); + fprintf(file, "%smeas %s %s %s\n", indent, base, s1, s2); + free(s1); + free(s2); + break; + default: + abort(); + } + free(base); +} + + +/* + * Tricky logic ahead: when dumping a vector, we search for a vectors that + * depends on that vector for ".". If we find one, we dump it immediately after + * this vector. + */ + +static void recurse_vec(FILE *file, const struct vec *vec, const char *indent) +{ + const struct vec *next; + const struct obj *obj; + char *base, *x, *y; + + base = base_name(vec, vec->base); + x = unparse(vec->x); + y = unparse(vec->y); + if (vec->name) + fprintf(file, "%s%s: vec %s(%s, %s)\n", + indent, vec->name, base, x, y); + else + fprintf(file, "%svec %s(%s, %s)\n", indent, base, x, y); + free(base); + free(x); + free(y); + + for (obj = vec->frame->objs; obj; obj = obj->next) + dump_obj(file, obj, indent, vec); + if (n_vec_refs(vec) == 1) { + for (next = vec->next; next->base != vec; next = next->next); + recurse_vec(file, next, indent); + } +} + + +static void dump_vecs(FILE *file, const struct vec *vecs, const char *indent) +{ + const struct vec *vec; + + for (vec = vecs; vec; vec = vec->next) + if (!vec->base || n_vec_refs(vec->base) != 1) + recurse_vec(file, vec, indent); +} + + +/* ----- frames ------------------------------------------------------------ */ + + +static void dump_frame(FILE *file, const struct frame *frame, + const char *indent) +{ + const struct table *table; + const struct loop *loop; + const struct obj *obj; + + for (table = frame->tables; table; table = table->next) + dump_table(file, table, indent); + for (loop = frame->loops; loop; loop = loop->next) + dump_loop(file, loop, indent); + dump_vecs(file, frame->vecs, indent); + for (obj = frame->objs; obj; obj = obj->next) + dump_obj(file, obj, indent, NULL); +} + + +/* ----- file -------------------------------------------------------------- */ + + +int dump(FILE *file) +{ + const struct frame *frame; + + fprintf(file, "/* MACHINE-GENERATED ! */\n\n"); + for (frame = frames; frame; frame = frame->next) { + if (!frame->name) + dump_frame(file, frame, ""); + else { + fprintf(file, "frame %s {\n", frame->name); + dump_frame(file, frame, "\t"); + fprintf(file, "}\n\n"); + } + } + fflush(file); + return !ferror(file); +} diff --git a/dump.h b/dump.h new file mode 100644 index 0000000..2ff46f3 --- /dev/null +++ b/dump.h @@ -0,0 +1,22 @@ +/* + * dump.h - Dump objects in the native FPD format + * + * 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 DUMP_H +#define DUMP_H + +#include + + +int dump(FILE *file); + +#endif /* !DUMP_H */ diff --git a/fped.c b/fped.c index 82c2dd0..d1cd9f7 100644 --- a/fped.c +++ b/fped.c @@ -50,8 +50,11 @@ int main(int argc, char **argv) if (!instantiate()) return 1; // inst_debug(); - error = gui_main(argc, argv); + error = gui_main(); if (error) return error; + +// dump(stdout); + return 0; } diff --git a/gui.c b/gui.c index b5dbbab..682e03a 100644 --- a/gui.c +++ b/gui.c @@ -678,7 +678,7 @@ int gui_init(int *argc, char ***argv) } -int gui_main(int argc, char **argv) +int gui_main(void) { root = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER); diff --git a/gui.h b/gui.h index 71437d3..8be6593 100644 --- a/gui.h +++ b/gui.h @@ -24,6 +24,6 @@ extern GtkWidget *root; void change_world(void); int gui_init(int *argc, char ***argv); -int gui_main(int argc, char **argv); +int gui_main(void); #endif /* !GUI_H */