From 5d392d1097b7ada7d5a72bf81a142067d647a1af Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Sun, 31 Jul 2016 20:10:45 -0300 Subject: [PATCH] sch2fig/: recursively parse sub-sheets --- sch2fig/TODO | 2 +- sch2fig/main.c | 10 +---- sch2fig/sch-parse.c | 94 ++++++++++++++++++++++++++++++++++++++++---- sch2fig/sch-render.c | 4 +- sch2fig/sch.h | 22 +++++++++-- 5 files changed, 109 insertions(+), 23 deletions(-) diff --git a/sch2fig/TODO b/sch2fig/TODO index c070d8f..8f42ef0 100644 --- a/sch2fig/TODO +++ b/sch2fig/TODO @@ -1,5 +1,5 @@ - better text size guessing also for FIG -- recursing into sheets:; use base path as starting point +- let user to enable/disable recursion; communicate sheet boundaries to backend - unify alignment, direction - support fonts attributes ? - support line thickness ? diff --git a/sch2fig/main.c b/sch2fig/main.c index db8cf85..dfba99f 100644 --- a/sch2fig/main.c +++ b/sch2fig/main.c @@ -24,12 +24,6 @@ #include "sch.h" -static bool do_sch_parse(void *user, const char *line) -{ - return sch_parse(user, line); -} - - static bool do_lib_parse(void *user, const char *line) { return lib_parse(user, line); @@ -81,9 +75,9 @@ int main(int argc, char **argv) } sch_init(&sch_ctx); - file_read(argv[argc - 1], do_sch_parse, &sch_ctx); + sch_parse(&sch_ctx, argv[argc - 1]); gfx_init(&fig_ops, template, n_vars, vars); //gfx_init(&cairo_ops, template, n_vars, vars); - sch_render(&sch_ctx); + sch_render(sch_ctx.sheets); gfx_end(); } diff --git a/sch2fig/sch-parse.c b/sch2fig/sch-parse.c index e43bdef..afe2891 100644 --- a/sch2fig/sch-parse.c +++ b/sch2fig/sch-parse.c @@ -15,11 +15,13 @@ #include #include #include +#include #include #include #include "util.h" #include "dwg.h" +#include "file.h" #include "lib.h" #include "sch.h" @@ -266,18 +268,78 @@ static void submit_obj(struct sch_ctx *ctx, enum sch_obj_type type) obj = alloc_type(struct sch_obj); *obj = ctx->obj; obj->type = type; - obj->next = ctx->objs; - ctx->objs = obj; + obj->next = NULL; + + *ctx->next_obj = obj; + ctx->next_obj = &obj->next; } -bool sch_parse(struct sch_ctx *ctx, const char *line) +static struct sheet *new_sheet(struct sch_ctx *ctx) { + struct sheet *sheet; + + sheet = alloc_type(struct sheet); + sheet->objs = NULL; + sheet->next = NULL; + + ctx->next_obj = &sheet->objs; + + *ctx->next_sheet = sheet; + ctx->next_sheet = &sheet->next; + + return sheet; +} + + +static bool parse_line(void *user, const char *line); + + +static void recurse_sheet(struct sch_ctx *ctx) +{ + struct sch_obj **saved_next_obj = ctx->next_obj; + const char *parent = ctx->file->name; + char *tmp = NULL; + struct sch_file dsc = { + .name = ctx->obj.u.sheet.file, + .lineno = 0, + .parent = ctx->file, + }; + + /* @@@ clean this up */ + + if (access(dsc.name, R_OK)) { + const char *slash; + + slash = strrchr(parent, '/'); + if (slash) { + unsigned len = slash + 1 - parent; + + tmp = alloc_size(len + strlen(dsc.name) + 1); + memcpy(tmp, parent, len); + strcpy(tmp + len, dsc.name); + dsc.name = tmp; + } + } + + new_sheet(ctx); + ctx->file = &dsc; + ctx->state = sch_descr; + file_read(dsc.name, parse_line, ctx); + ctx->file = dsc.parent; + ctx->next_obj = saved_next_obj; + free(tmp); +} + + +static bool parse_line(void *user, const char *line) +{ + struct sch_ctx *ctx = user; struct sch_obj *obj = &ctx->obj; int n = 0; char *s; - ctx->lineno++; + ctx->file->lineno++; switch (ctx->state) { case sch_basic: @@ -423,8 +485,9 @@ bool sch_parse(struct sch_ctx *ctx, const char *line) break; case sch_sheet: if (sscanf(line, "$EndSheet%n", &n) == 0 && n) { - ctx->state = sch_basic; submit_obj(ctx, sch_obj_sheet); + recurse_sheet(ctx); + ctx->state = sch_basic; return 1; } if (sscanf(line, "S %d %d %u %u", @@ -467,14 +530,29 @@ bool sch_parse(struct sch_ctx *ctx, const char *line) default: abort(); } - fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); + fprintf(stderr, "%s:%u: cannot parse\n\"%s\"\n", + ctx->file->name, ctx->file->lineno, line); exit(1); } +void sch_parse(struct sch_ctx *ctx, const char *file) +{ + struct sch_file dsc = { + .name = file, + .lineno = 0, + .parent = NULL, + }; + + ctx->file = &dsc; + file_read(file, parse_line, ctx); +} + + void sch_init(struct sch_ctx *ctx) { ctx->state = sch_descr; - ctx->objs = NULL; - ctx->lineno = 0; + ctx->sheets = NULL; + ctx->next_sheet = &ctx->sheets; + new_sheet(ctx); } diff --git a/sch2fig/sch-render.c b/sch2fig/sch-render.c index d9590bf..b1b9311 100644 --- a/sch2fig/sch-render.c +++ b/sch2fig/sch-render.c @@ -129,11 +129,11 @@ static void render_sheet(const struct sch_obj *obj, } -void sch_render(const struct sch_ctx *ctx) +void sch_render(const struct sheet *sheet) { const struct sch_obj *obj; - for (obj = ctx->objs; obj; obj = obj->next) + for (obj = sheet->objs; obj; obj = obj->next) switch (obj->type) { case sch_obj_wire: { diff --git a/sch2fig/sch.h b/sch2fig/sch.h index 4a1441e..ea9825c 100644 --- a/sch2fig/sch.h +++ b/sch2fig/sch.h @@ -86,20 +86,34 @@ struct sch_obj { struct sch_obj *next; }; +struct sheet { + struct sch_obj *objs; + struct sheet *next; +}; + +struct sch_file { + const char *name; + int lineno; + struct sch_file *parent; +}; + struct sch_ctx { enum sch_state state; struct sch_obj obj; - struct sch_obj *objs; + struct sch_obj **next_obj; - unsigned lineno; + struct sheet *sheets; + struct sheet **next_sheet; + + struct sch_file *file; }; void decode_alignment(struct text *txt, char hor, char vert); -void sch_render(const struct sch_ctx *ctx); -bool sch_parse(struct sch_ctx *ctx, const char *line); +void sch_render(const struct sheet *sheet); +void sch_parse(struct sch_ctx *ctx, const char *line); void sch_init(struct sch_ctx *ctx); #endif /* !SCH_H */