/* * lib.c - Parse Eeschema .lib file * * Written 2016 by Werner Almesberger * Copyright 2016 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 #include #include "fig.h" #include "lib.h" struct obj { enum obj_type { obj_poly, obj_rect, obj_circ, obj_arc, obj_text, obj_pin, } type; unsigned unit; unsigned convert; union { struct poly { int thick; char fill; int points; int *x; int *y; } poly; struct { int thick; char fill; int sx, sy; int ex, ey; } rect; struct { int x, y; int r; int thick; char fill; } circ; struct { char orient; int x, y; int dim; char *s; } text; struct { char *name; char *number; int x, y; int length; char orient; int number_size; int name_size; char etype; // @@@ shape } pin; } u; struct obj *next; }; struct comp { const char *name; struct obj *objs; struct comp *next; }; static struct comp *comps = NULL; static struct comp **next_comp = &comps; static struct obj **next_obj; static inline int mx(int x, int y, int m[6]) { return m[0] + x * m[1] + y * m[2]; } static inline int my(int x, int y, int m[6]) { return m[3] + x * m[4] + y * m[5]; } static void draw_poly(const struct poly *poly, int m[6]) { int n = poly->points; int x[n]; int y[n]; int i; for (i = 0; i != n; i++) { x[i] = mx(poly->x[i], poly->y[i], m); y[i] = my(poly->x[i], poly->y[i], m); } fig_poly(n, x, y); } static void draw(const struct obj *obj, int m[6]) { switch (obj->type) { case obj_poly: draw_poly(&obj->u.poly, m); break; case obj_rect: fig_rect(mx(obj->u.rect.sx, obj->u.rect.sy, m), my(obj->u.rect.sx, obj->u.rect.sy, m), mx(obj->u.rect.ex, obj->u.rect.ey, m), my(obj->u.rect.ex, obj->u.rect.ey, m)); // @@@ break; case obj_circ: break; case obj_text: break; case obj_pin: break; default: abort(); } } void lib_exec(const char *name, unsigned unit, int m[4]) { const struct comp *comp; const struct obj *obj; for (comp = comps; comp; comp = comp->next) if (!strcmp(comp->name, name)) goto found; fprintf(stderr, "\"%s\" not found\n", name); exit(1); found: for (obj = comp->objs; obj; obj = obj->next) { if (obj->unit && obj->unit != unit) continue; draw(obj, m); } } static bool parse_poly(struct obj *obj, const char *line, int points) { int i, n; obj->u.poly.points = points; obj->u.poly.x = malloc(sizeof(int) * points); obj->u.poly.y = malloc(sizeof(int) * points); for (i = 0; i != points; i++) { if (sscanf(line, "%d %d %n", obj->u.poly.x + i, obj->u.poly.y + i, &n) != 2) return 0; line += n; } if (sscanf(line, "%c", &obj->u.poly.fill) != 1) return 0; return 1; } bool lib_parse(struct lib_ctx *ctx, const char *line) { int n = 0; char *s; unsigned points; struct comp *comp; struct obj *obj; ctx->lineno++; switch (ctx->state) { case lib_skip: if (sscanf(line, "DEF %ms", &s) == 1) { ctx->state = lib_def; comp = malloc(sizeof(struct comp)); if (*s == '~') s++; comp->name = s; comp->objs = NULL; comp->next = NULL; *next_comp = comp; next_comp = &comp->next; next_obj = &comp->objs; return 1; } return 1; case lib_def: if (sscanf(line, "DRAW%n", &n) == 0 && n) { ctx->state = lib_draw; return 1; } return 1; case lib_draw: if (sscanf(line, "ENDDRAW%n", &n) == 0 && n) { ctx->state = lib_skip; return 1; } obj = malloc(sizeof(struct obj)); obj->next = NULL; *next_obj = obj; next_obj = &obj->next; if (sscanf(line, "P %u %u %u %u %n", &points, &obj->unit, &obj->convert, &obj->u.poly.thick, &n) == 4) { obj->type = obj_poly; if (parse_poly(obj, line + n, points)) return 1; break; } if (sscanf(line, "S %d %d %d %d %u %u %d %c", &obj->u.rect.sx, &obj->u.rect.sy, &obj->u.rect.ex, &obj->u.rect.ey, &obj->unit, &obj->convert, &obj->u.rect.thick, &obj->u.rect.fill) == 8) { obj->type = obj_rect; return 1; } if (sscanf(line, "C %d %d %d %u %u %d %c", &obj->u.circ.x, &obj->u.circ.y, &obj->u.circ.r, &obj->unit, &obj->convert, &obj->u.circ.thick, &obj->u.circ.fill) == 7) { obj->type = obj_circ; return 1; } if (sscanf(line, "A %n", &n) == 0 && n) { obj->type = obj_arc; return 1; // @@@ } if (sscanf(line, "T %c %d %d %d %u %u %ms", &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, &obj->u.text.dim, &obj->unit, &obj->convert, &obj->u.text.s) == 7) { obj->type = obj_text; return 1; } if (sscanf(line, "X %ms %ms %d %d %d %c %d %d %u %u %c", &obj->u.pin.name, &obj->u.pin.number, &obj->u.pin.x, &obj->u.pin.y, &obj->u.pin.length, &obj->u.pin.orient, &obj->u.pin.number_size, &obj->u.pin.name_size, &obj->unit, &obj->convert, &obj->u.pin.etype) == 11) { obj->type = obj_pin; return 1; } break; default: abort(); } fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); exit(1); } void lib_init(struct lib_ctx *ctx) { ctx->state = lib_skip; ctx->lineno++; }