FreeCalypso > hg > ueda-linux
view ueda/libueda/readmcl.c @ 139:bf188727e606
donl-rename-parts reader: no tEDAx-style escapes
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 07 Sep 2020 04:25:11 +0000 |
parents | c91e7a30fab3 |
children |
line wrap: on
line source
/* * This is the MCL parser for the uEDA suite. */ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "mcl.h" extern char *copystr(); #define MAX_COMPS 1024 #define MAX_PARTDEFS 128 #define MAX_ATTRS 2048 #define MAX_REFDES_ON_LINE 16 char *MCLfile = "MCL"; /* the following vars capture the distilled output of the parser */ struct component components[MAX_COMPS], partdefs[MAX_PARTDEFS]; int ncomponents, npartdefs; static struct attrib attrs[MAX_ATTRS]; static int nattrs; /* the following static vars are used only in the reading & parsing process */ static FILE *mclf; static char line[1024]; /* size arbitrary, sizeof used in the code */ static int lineno; static struct component *curcomp; static char *curcomp_refdes[MAX_REFDES_ON_LINE]; static int curcomp_nrefdes; static setup_partdef(np) register char *np; { register char *cp; while (isspace(*np)) np++; cp = index(np, ':'); if (!cp || cp == np || cp[1]) { fprintf(stderr, "%s: line %d: invalid part definition\n", MCLfile, lineno); exit(1); } *cp = '\0'; if (npartdefs >= MAX_PARTDEFS) { fprintf(stderr, "%s: line %d: too many part definitions\n", MCLfile, lineno); exit(1); } curcomp = partdefs + npartdefs; curcomp->name = copystr(np); curcomp->attrs = attrs + nattrs; curcomp->nattrs = 0; npartdefs++; curcomp_nrefdes = 0; } static parse_refdes_list() { int i; register char *cp, *np; register int c; for (cp = line, i = 0; ; ) { if (!isupper(*cp)) { inv: fprintf(stderr, "%s: line %d: invalid refdes line\n", MCLfile, lineno); exit(1); } for (np = cp; isalnum(*cp); cp++) ; c = *cp; if (c != ':' && c != ',') goto inv; *cp++ = '\0'; curcomp_refdes[i++] = copystr(np); if (c == ':') break; } curcomp_nrefdes = i; if (*cp) goto inv; } static clone_component() { register int i; register struct component *newcomp; for (i = 1; i < curcomp_nrefdes; i++) { if (ncomponents >= MAX_COMPS) { fprintf(stderr, "%s: %s: too many components\n", MCLfile, curcomp_refdes[i]); exit(1); } newcomp = components + ncomponents; bcopy(curcomp, newcomp, sizeof(struct component)); newcomp->name = curcomp_refdes[i]; ncomponents++; } } static finish_component() { extern char *get_comp_attr(); if (curcomp_nrefdes == 0) return; /* nothing to do for part defs */ if (!curcomp->partdef && (get_comp_attr(curcomp, "manufacturer") && get_comp_attr(curcomp, "manufacturer_part_number") || get_comp_attr(curcomp, "bom_part_title"))) curcomp->partdef = curcomp; /* self-defines part */ if (curcomp_nrefdes > 1) clone_component(); } static handle_part_ref(partname) char *partname; { register struct component *part; register int i; if (curcomp_nrefdes == 0) { fprintf(stderr, "%s: line %d: can't use a part reference in a part definition!\n", MCLfile, lineno); exit(1); } if (!strcmp(partname, "none")) { curcomp->partdef = NULL; return; } if (!strcmp(partname, "yes")) { curcomp->partdef = curcomp; /* self-defines the part */ return; } for (part = partdefs, i = 0; i < npartdefs; part++, i++) if (!strcmp(part->name, partname)) { gotit: curcomp->partdef = part; return; } /* can also refer to a previous component that self-defines a part */ for (part = components, i = 0; i < ncomponents-1; part++, i++) if (!strcmp(part->name, partname)) { if (part->partdef == part) goto gotit; else { fprintf(stderr, "%s: line %d: can't use %s as a part because it doesn't define a part\n", MCLfile, lineno, partname); exit(1); } } fprintf(stderr, "%s: line %d: part %s not defined\n", MCLfile, lineno, partname); exit(1); } static get_line() { register char *cp; if (fgets(line, sizeof line, mclf) == NULL) return(0); lineno++; /* strip trailing comments and whitespace */ cp = index(line, '#'); if (!cp) cp = index(line, '\0'); while (cp > line && isspace(cp[-1])) cp--; *cp = '\0'; return(1); } read_MCL() { register char *cp, *name, *value; mclf = fopen(MCLfile, "r"); if (!mclf) { perror(MCLfile); exit(1); } for (lineno = 0, curcomp = NULL; get_line(); ) { /* ignore blank lines and comments */ if (line[0] == '\0' || line[0] == '#') continue; if (!strncmp(line, "part", 4) && isspace(line[4])) { finish_component(); setup_partdef(line + 5); } else if (!isspace(line[0])) { /* refdes */ finish_component(); parse_refdes_list(); if (ncomponents >= MAX_COMPS) { fprintf(stderr, "%s: line %d: too many components\n", MCLfile, lineno); exit(1); } curcomp = components + ncomponents; curcomp->name = curcomp_refdes[0]; curcomp->attrs = attrs + nattrs; curcomp->nattrs = 0; ncomponents++; } else { /* attribute */ for (cp = line; isspace(*cp); cp++) ; name = cp; cp = index(cp, '='); if (!cp) { invattr: fprintf(stderr, "%s: line %d: invalid attribute line\n", MCLfile, lineno); exit(1); } *cp = '\0'; value = cp + 1; if (name[0] == '\0') goto invattr; if (!curcomp) { fprintf(stderr, "%s: line %d: attribute listed without a component\n", MCLfile, lineno); exit(1); } if (value[0] == '\0') { fprintf(stderr, "%s: line %d: attribute must have a value\n", MCLfile, lineno); exit(1); } if (nattrs >= MAX_ATTRS) { fprintf(stderr, "%s: line %d: too many attributes\n", MCLfile, lineno); exit(1); } attrs[nattrs].name = copystr(name); attrs[nattrs].value = copystr(value); nattrs++; curcomp->nattrs++; if (!strcmp(name, "part")) handle_part_ref(value); } } fclose(mclf); finish_component(); }