FreeCalypso > hg > ueda-linux
diff ueda/libueda/readmcl.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 20 Jul 2015 00:24:37 +0000 |
parents | |
children | c91e7a30fab3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ueda/libueda/readmcl.c Mon Jul 20 00:24:37 2015 +0000 @@ -0,0 +1,260 @@ +/* + * This is the MCL parser for the uEDA suite. + */ + +#include <stdio.h> +#include <ctype.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; + +read_MCL() +{ + register char *cp, *name, *value; + + mclf = fopen(MCLfile, "r"); + if (!mclf) { + perror(MCLfile); + exit(1); + } + + for (lineno = 0, curcomp = NULL; getline(); ) { + /* 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(); +} + +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 +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 +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 +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 +getline() +{ + 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); +}