FreeCalypso > hg > ueda-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:cd92449fdb51 |
|---|---|
| 1 /* | |
| 2 * This is the MCL parser for the uEDA suite. | |
| 3 */ | |
| 4 | |
| 5 #include <stdio.h> | |
| 6 #include <ctype.h> | |
| 7 #include <strings.h> | |
| 8 #include "mcl.h" | |
| 9 | |
| 10 extern char *copystr(); | |
| 11 | |
| 12 #define MAX_COMPS 1024 | |
| 13 #define MAX_PARTDEFS 128 | |
| 14 #define MAX_ATTRS 2048 | |
| 15 #define MAX_REFDES_ON_LINE 16 | |
| 16 | |
| 17 char *MCLfile = "MCL"; | |
| 18 | |
| 19 /* the following vars capture the distilled output of the parser */ | |
| 20 struct component components[MAX_COMPS], partdefs[MAX_PARTDEFS]; | |
| 21 int ncomponents, npartdefs; | |
| 22 static struct attrib attrs[MAX_ATTRS]; | |
| 23 static int nattrs; | |
| 24 | |
| 25 /* the following static vars are used only in the reading & parsing process */ | |
| 26 static FILE *mclf; | |
| 27 static char line[1024]; /* size arbitrary, sizeof used in the code */ | |
| 28 static int lineno; | |
| 29 | |
| 30 static struct component *curcomp; | |
| 31 static char *curcomp_refdes[MAX_REFDES_ON_LINE]; | |
| 32 static int curcomp_nrefdes; | |
| 33 | |
| 34 read_MCL() | |
| 35 { | |
| 36 register char *cp, *name, *value; | |
| 37 | |
| 38 mclf = fopen(MCLfile, "r"); | |
| 39 if (!mclf) { | |
| 40 perror(MCLfile); | |
| 41 exit(1); | |
| 42 } | |
| 43 | |
| 44 for (lineno = 0, curcomp = NULL; getline(); ) { | |
| 45 /* ignore blank lines and comments */ | |
| 46 if (line[0] == '\0' || line[0] == '#') | |
| 47 continue; | |
| 48 if (!strncmp(line, "part", 4) && isspace(line[4])) { | |
| 49 finish_component(); | |
| 50 setup_partdef(line + 5); | |
| 51 } else if (!isspace(line[0])) { /* refdes */ | |
| 52 finish_component(); | |
| 53 parse_refdes_list(); | |
| 54 if (ncomponents >= MAX_COMPS) { | |
| 55 fprintf(stderr, | |
| 56 "%s: line %d: too many components\n", | |
| 57 MCLfile, lineno); | |
| 58 exit(1); | |
| 59 } | |
| 60 curcomp = components + ncomponents; | |
| 61 curcomp->name = curcomp_refdes[0]; | |
| 62 curcomp->attrs = attrs + nattrs; | |
| 63 curcomp->nattrs = 0; | |
| 64 ncomponents++; | |
| 65 } else { /* attribute */ | |
| 66 for (cp = line; isspace(*cp); cp++) | |
| 67 ; | |
| 68 name = cp; | |
| 69 cp = index(cp, '='); | |
| 70 if (!cp) { | |
| 71 invattr: fprintf(stderr, | |
| 72 "%s: line %d: invalid attribute line\n", | |
| 73 MCLfile, lineno); | |
| 74 exit(1); | |
| 75 } | |
| 76 *cp = '\0'; | |
| 77 value = cp + 1; | |
| 78 if (name[0] == '\0') | |
| 79 goto invattr; | |
| 80 if (!curcomp) { | |
| 81 fprintf(stderr, | |
| 82 "%s: line %d: attribute listed without a component\n", | |
| 83 MCLfile, lineno); | |
| 84 exit(1); | |
| 85 } | |
| 86 if (value[0] == '\0') { | |
| 87 fprintf(stderr, | |
| 88 "%s: line %d: attribute must have a value\n", | |
| 89 MCLfile, lineno); | |
| 90 exit(1); | |
| 91 } | |
| 92 if (nattrs >= MAX_ATTRS) { | |
| 93 fprintf(stderr, | |
| 94 "%s: line %d: too many attributes\n", | |
| 95 MCLfile, lineno); | |
| 96 exit(1); | |
| 97 } | |
| 98 attrs[nattrs].name = copystr(name); | |
| 99 attrs[nattrs].value = copystr(value); | |
| 100 nattrs++; | |
| 101 curcomp->nattrs++; | |
| 102 if (!strcmp(name, "part")) | |
| 103 handle_part_ref(value); | |
| 104 } | |
| 105 } | |
| 106 fclose(mclf); | |
| 107 finish_component(); | |
| 108 } | |
| 109 | |
| 110 static | |
| 111 setup_partdef(np) | |
| 112 register char *np; | |
| 113 { | |
| 114 register char *cp; | |
| 115 | |
| 116 while (isspace(*np)) | |
| 117 np++; | |
| 118 cp = index(np, ':'); | |
| 119 if (!cp || cp == np || cp[1]) { | |
| 120 fprintf(stderr, "%s: line %d: invalid part definition\n", | |
| 121 MCLfile, lineno); | |
| 122 exit(1); | |
| 123 } | |
| 124 *cp = '\0'; | |
| 125 if (npartdefs >= MAX_PARTDEFS) { | |
| 126 fprintf(stderr, "%s: line %d: too many part definitions\n", | |
| 127 MCLfile, lineno); | |
| 128 exit(1); | |
| 129 } | |
| 130 curcomp = partdefs + npartdefs; | |
| 131 curcomp->name = copystr(np); | |
| 132 curcomp->attrs = attrs + nattrs; | |
| 133 curcomp->nattrs = 0; | |
| 134 npartdefs++; | |
| 135 curcomp_nrefdes = 0; | |
| 136 } | |
| 137 | |
| 138 static | |
| 139 parse_refdes_list() | |
| 140 { | |
| 141 int i; | |
| 142 register char *cp, *np; | |
| 143 register int c; | |
| 144 | |
| 145 for (cp = line, i = 0; ; ) { | |
| 146 if (!isupper(*cp)) { | |
| 147 inv: fprintf(stderr, "%s: line %d: invalid refdes line\n", | |
| 148 MCLfile, lineno); | |
| 149 exit(1); | |
| 150 } | |
| 151 for (np = cp; isalnum(*cp); cp++) | |
| 152 ; | |
| 153 c = *cp; | |
| 154 if (c != ':' && c != ',') | |
| 155 goto inv; | |
| 156 *cp++ = '\0'; | |
| 157 curcomp_refdes[i++] = copystr(np); | |
| 158 if (c == ':') | |
| 159 break; | |
| 160 } | |
| 161 curcomp_nrefdes = i; | |
| 162 if (*cp) | |
| 163 goto inv; | |
| 164 } | |
| 165 | |
| 166 static | |
| 167 finish_component() | |
| 168 { | |
| 169 extern char *get_comp_attr(); | |
| 170 | |
| 171 if (curcomp_nrefdes == 0) | |
| 172 return; /* nothing to do for part defs */ | |
| 173 if (!curcomp->partdef && | |
| 174 (get_comp_attr(curcomp, "manufacturer") && | |
| 175 get_comp_attr(curcomp, "manufacturer_part_number") || | |
| 176 get_comp_attr(curcomp, "bom_part_title"))) | |
| 177 curcomp->partdef = curcomp; /* self-defines part */ | |
| 178 if (curcomp_nrefdes > 1) | |
| 179 clone_component(); | |
| 180 } | |
| 181 | |
| 182 static | |
| 183 clone_component() | |
| 184 { | |
| 185 register int i; | |
| 186 register struct component *newcomp; | |
| 187 | |
| 188 for (i = 1; i < curcomp_nrefdes; i++) { | |
| 189 if (ncomponents >= MAX_COMPS) { | |
| 190 fprintf(stderr, "%s: %s: too many components\n", | |
| 191 MCLfile, curcomp_refdes[i]); | |
| 192 exit(1); | |
| 193 } | |
| 194 newcomp = components + ncomponents; | |
| 195 bcopy(curcomp, newcomp, sizeof(struct component)); | |
| 196 newcomp->name = curcomp_refdes[i]; | |
| 197 ncomponents++; | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 static | |
| 202 handle_part_ref(partname) | |
| 203 char *partname; | |
| 204 { | |
| 205 register struct component *part; | |
| 206 register int i; | |
| 207 | |
| 208 if (curcomp_nrefdes == 0) { | |
| 209 fprintf(stderr, | |
| 210 "%s: line %d: can't use a part reference in a part definition!\n", | |
| 211 MCLfile, lineno); | |
| 212 exit(1); | |
| 213 } | |
| 214 if (!strcmp(partname, "none")) { | |
| 215 curcomp->partdef = NULL; | |
| 216 return; | |
| 217 } | |
| 218 if (!strcmp(partname, "yes")) { | |
| 219 curcomp->partdef = curcomp; /* self-defines the part */ | |
| 220 return; | |
| 221 } | |
| 222 for (part = partdefs, i = 0; i < npartdefs; part++, i++) | |
| 223 if (!strcmp(part->name, partname)) { | |
| 224 gotit: curcomp->partdef = part; | |
| 225 return; | |
| 226 } | |
| 227 /* can also refer to a previous component that self-defines a part */ | |
| 228 for (part = components, i = 0; i < ncomponents-1; part++, i++) | |
| 229 if (!strcmp(part->name, partname)) { | |
| 230 if (part->partdef == part) | |
| 231 goto gotit; | |
| 232 else { | |
| 233 fprintf(stderr, | |
| 234 "%s: line %d: can't use %s as a part because it doesn't define a part\n", | |
| 235 MCLfile, lineno, partname); | |
| 236 exit(1); | |
| 237 } | |
| 238 } | |
| 239 fprintf(stderr, "%s: line %d: part %s not defined\n", MCLfile, lineno, | |
| 240 partname); | |
| 241 exit(1); | |
| 242 } | |
| 243 | |
| 244 static | |
| 245 getline() | |
| 246 { | |
| 247 register char *cp; | |
| 248 | |
| 249 if (fgets(line, sizeof line, mclf) == NULL) | |
| 250 return(0); | |
| 251 lineno++; | |
| 252 /* strip trailing comments and whitespace */ | |
| 253 cp = index(line, '#'); | |
| 254 if (!cp) | |
| 255 cp = index(line, '\0'); | |
| 256 while (cp > line && isspace(cp[-1])) | |
| 257 cp--; | |
| 258 *cp = '\0'; | |
| 259 return(1); | |
| 260 } |
