FreeCalypso > hg > ueda-linux
comparison ueda/libuschem/graphsym_load.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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:cd92449fdb51 |
|---|---|
| 1 /* | |
| 2 * The black magic of loading/prescanning gschem-based uschem symbols | |
| 3 */ | |
| 4 | |
| 5 #include <ctype.h> | |
| 6 #include <stdio.h> | |
| 7 #include <strings.h> | |
| 8 #include "graphsym.h" | |
| 9 | |
| 10 extern char *malloc(); | |
| 11 extern char *copystr(); | |
| 12 | |
| 13 #define MAXLINE 256 | |
| 14 | |
| 15 static struct graphsym *symstruct; | |
| 16 static FILE *inf; | |
| 17 static int lineno; | |
| 18 static struct graphsym_pindef **pintail; | |
| 19 | |
| 20 read_symbol_file(gs, f) | |
| 21 struct graphsym *gs; | |
| 22 FILE *f; | |
| 23 { | |
| 24 symstruct = gs; | |
| 25 inf = f; | |
| 26 lineno = 0; | |
| 27 pintail = &gs->gs_pins; | |
| 28 mymain(); | |
| 29 if (!gs->gs_npins) { | |
| 30 fprintf(stderr, "%s: symbol has no pins (invalid)\n", | |
| 31 gs->gs_pathname); | |
| 32 exit(1); | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 static | |
| 37 mymain() | |
| 38 { | |
| 39 char line[MAXLINE]; | |
| 40 register char *cp; | |
| 41 register int c; | |
| 42 | |
| 43 while (getline(line)) { | |
| 44 if (line[0] == '%') /* PS-like comments */ | |
| 45 continue; | |
| 46 if (line[0] == '\0') /* allow blank lines too */ | |
| 47 continue; | |
| 48 if (!isalpha(line[0])) { | |
| 49 inv: fprintf(stderr, "%s: line %d: invalid symbol data\n", | |
| 50 symstruct->gs_pathname, lineno); | |
| 51 exit(1); | |
| 52 } | |
| 53 for (cp = line; isalpha(*cp); cp++) | |
| 54 ; | |
| 55 if (!isspace(*cp)) | |
| 56 goto inv; | |
| 57 *cp++ = '\0'; | |
| 58 while (isspace(*cp)) | |
| 59 cp++; | |
| 60 if (!strcmp(line, "PS")) { | |
| 61 if (strcmp(cp, "{")) | |
| 62 goto inv; | |
| 63 skip_ps_block(); | |
| 64 continue; | |
| 65 } else if (strlen(line) != 1) | |
| 66 goto inv; | |
| 67 line[1] = ' '; | |
| 68 /* dispatch by single-char type */ | |
| 69 switch (line[0]) { | |
| 70 case 'v': | |
| 71 continue; /* ignore */ | |
| 72 /* simple graphics */ | |
| 73 case 'L': | |
| 74 case 'B': | |
| 75 case 'V': | |
| 76 case 'A': | |
| 77 /* ignore at this stage too */ | |
| 78 continue; | |
| 79 case 'P': | |
| 80 handle_pin(line, lineno); | |
| 81 continue; | |
| 82 case 'T': | |
| 83 handle_T_obj(line, lineno); | |
| 84 continue; | |
| 85 default: | |
| 86 goto inv; | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 static | |
| 92 handle_pin(objline, objlineno) | |
| 93 char *objline; | |
| 94 { | |
| 95 int numparams[7]; | |
| 96 char junkline[MAXLINE]; | |
| 97 register struct graphsym_pindef *pin; | |
| 98 | |
| 99 parse_numline(objline, objlineno, numparams, 7); | |
| 100 pin = (struct graphsym_pindef *) malloc(sizeof(struct graphsym_pindef)); | |
| 101 if (!pin) { | |
| 102 perror("malloc"); | |
| 103 exit(1); | |
| 104 } | |
| 105 bzero(pin, sizeof(struct graphsym_pindef)); | |
| 106 if (numparams[6]) { | |
| 107 pin->gspd_x = numparams[2]; | |
| 108 pin->gspd_y = numparams[3]; | |
| 109 } else { | |
| 110 pin->gspd_x = numparams[0]; | |
| 111 pin->gspd_y = numparams[1]; | |
| 112 } | |
| 113 *pintail = pin; | |
| 114 pintail = &pin->gspd_next; | |
| 115 symstruct->gs_npins++; | |
| 116 if (!getline(junkline) || strcmp(junkline, "{")) { | |
| 117 fprintf(stderr, | |
| 118 "%s: line %d: P line must be followed by '{' line\n", | |
| 119 symstruct->gs_pathname, objlineno); | |
| 120 exit(1); | |
| 121 } | |
| 122 read_pin_attrs(pin, objlineno); | |
| 123 } | |
| 124 | |
| 125 static | |
| 126 read_pin_attrs(pin, objlineno) | |
| 127 struct graphsym_pindef *pin; | |
| 128 { | |
| 129 char line[MAXLINE]; | |
| 130 int Tline_parsed[9]; | |
| 131 register char *cp; | |
| 132 | |
| 133 for (;;) { | |
| 134 if (!getline(line)) { | |
| 135 badeof: fprintf(stderr, "%s: EOF in pin attribute block\n", | |
| 136 symstruct->gs_pathname); | |
| 137 exit(1); | |
| 138 } | |
| 139 if (line[0] == '%') /* PS-like comments */ | |
| 140 continue; | |
| 141 if (line[0] == '\0') /* allow blank lines too */ | |
| 142 continue; | |
| 143 if (line[0] == '}') | |
| 144 return; | |
| 145 if (!isalpha(line[0])) { | |
| 146 inv: fprintf(stderr, "%s: line %d: invalid symbol data\n", | |
| 147 symstruct->gs_pathname, lineno); | |
| 148 exit(1); | |
| 149 } | |
| 150 for (cp = line; isalpha(*cp); cp++) | |
| 151 ; | |
| 152 if (!isspace(*cp)) | |
| 153 goto inv; | |
| 154 *cp++ = '\0'; | |
| 155 if (!strcmp(line, "attr")) { | |
| 156 while (isspace(*cp)) | |
| 157 cp++; | |
| 158 handle_attr(pin, cp); | |
| 159 continue; | |
| 160 } else if (strcmp(line, "T")) { | |
| 161 fprintf(stderr, | |
| 162 "%s: line %d: wrong object type in pin attribute block\n", | |
| 163 symstruct->gs_pathname, lineno); | |
| 164 exit(1); | |
| 165 } | |
| 166 line[1] = ' '; | |
| 167 parse_numline(line, lineno, Tline_parsed, 9); | |
| 168 if (Tline_parsed[8] < 1) { | |
| 169 fprintf(stderr, "%s: line %d: T object: num_lines<1!\n", | |
| 170 symstruct->gs_pathname, lineno); | |
| 171 exit(1); | |
| 172 } | |
| 173 if (Tline_parsed[8] > 1) { | |
| 174 fprintf(stderr, | |
| 175 "%s: line %d: multiline text object in attribute block not supported\n", | |
| 176 symstruct->gs_pathname, lineno); | |
| 177 exit(1); | |
| 178 } | |
| 179 if (!getline(line)) | |
| 180 goto badeof; | |
| 181 handle_attr(pin, line); | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 static | |
| 186 handle_attr(pin, line) | |
| 187 register struct graphsym_pindef *pin; | |
| 188 register char *line; | |
| 189 { | |
| 190 register char *cp; | |
| 191 | |
| 192 cp = index(line, '='); | |
| 193 if (!cp) | |
| 194 return; | |
| 195 *cp++ = '\0'; | |
| 196 if (!*cp) /* avoid null string values */ | |
| 197 return; | |
| 198 if (!strcmp(line, "pinname")) { | |
| 199 if (pin->gspd_pinname) { | |
| 200 dup: fprintf(stderr, | |
| 201 "%s: line %d: duplicate %s attribute (ignored)\n", | |
| 202 symstruct->gs_pathname, lineno, line); | |
| 203 return; | |
| 204 } | |
| 205 pin->gspd_pinname = copystr(cp); | |
| 206 } else if (!strcmp(line, "pinnumber")) { | |
| 207 if (pin->gspd_pinnumber) | |
| 208 goto dup; | |
| 209 pin->gspd_pinnumber = copystr(cp); | |
| 210 if (!strcmp(cp, "%d")) | |
| 211 symstruct->gs_varpins++; | |
| 212 } else if (!strcmp(line, "forcenet")) { | |
| 213 if (pin->gspd_forcenet) | |
| 214 goto dup; | |
| 215 pin->gspd_forcenet = copystr(cp); | |
| 216 symstruct->gs_forcenets++; | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 static | |
| 221 handle_T_obj(objline, objlineno) | |
| 222 char *objline; | |
| 223 { | |
| 224 int numparams[9]; | |
| 225 char junkline[MAXLINE]; | |
| 226 register int i; | |
| 227 | |
| 228 parse_numline(objline, objlineno, numparams, 9); | |
| 229 if (numparams[8] < 1) { | |
| 230 fprintf(stderr, "%s: line %d: T object: num_lines<1!\n", | |
| 231 symstruct->gs_pathname, objlineno); | |
| 232 exit(1); | |
| 233 } | |
| 234 for (i = numparams[8]; i; i--) { | |
| 235 if (!getline(junkline)) { | |
| 236 fprintf(stderr, "%s: EOF in T object\n", | |
| 237 symstruct->gs_pathname); | |
| 238 exit(1); | |
| 239 } | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 static | |
| 244 parse_numline(line, lineno, numarray, nfields) | |
| 245 char *line; | |
| 246 int lineno; | |
| 247 int *numarray; | |
| 248 int nfields; | |
| 249 { | |
| 250 register char *cp, *np; | |
| 251 register int i; | |
| 252 | |
| 253 for (i = 0, cp = line+1; i < nfields; i++) { | |
| 254 if (!isspace(*cp)) { | |
| 255 inv: fprintf(stderr, "%s: line %d: invalid numeric line\n", | |
| 256 symstruct->gs_pathname, lineno); | |
| 257 exit(1); | |
| 258 } | |
| 259 while (isspace(*cp)) | |
| 260 cp++; | |
| 261 np = cp; | |
| 262 if (*cp == '-') | |
| 263 cp++; | |
| 264 if (!isdigit(*cp)) | |
| 265 goto inv; | |
| 266 while (isdigit(*cp)) | |
| 267 cp++; | |
| 268 numarray[i] = atoi(np); | |
| 269 } | |
| 270 if (*cp) | |
| 271 goto inv; | |
| 272 } | |
| 273 | |
| 274 static | |
| 275 getline(linebuf) | |
| 276 char *linebuf; | |
| 277 { | |
| 278 register char *cp; | |
| 279 | |
| 280 if (fgets(linebuf, MAXLINE, inf) == NULL) | |
| 281 return(0); | |
| 282 lineno++; | |
| 283 /* strip trailing newline or other whitespace */ | |
| 284 cp = index(linebuf, '\0'); | |
| 285 while (cp > linebuf && isspace(cp[-1])) | |
| 286 cp--; | |
| 287 *cp = '\0'; | |
| 288 return(1); | |
| 289 } | |
| 290 | |
| 291 static | |
| 292 skip_ps_block() | |
| 293 { | |
| 294 register int c, n; | |
| 295 | |
| 296 for (n = 0; n >= 0; ) { | |
| 297 c = getc(inf); | |
| 298 switch (c) { | |
| 299 case EOF: | |
| 300 badeof: fprintf(stderr, "%s: EOF in a PS block\n", | |
| 301 symstruct->gs_pathname); | |
| 302 exit(1); | |
| 303 case '%': | |
| 304 for (;;) { | |
| 305 c = getc(inf); | |
| 306 if (c == EOF) | |
| 307 goto badeof; | |
| 308 if (c == '\n') | |
| 309 break; | |
| 310 } | |
| 311 /* FALL THRU */ | |
| 312 case '\n': | |
| 313 lineno++; | |
| 314 continue; | |
| 315 case '(': | |
| 316 skip_over_ps_string(); | |
| 317 continue; | |
| 318 case ')': | |
| 319 fprintf(stderr, | |
| 320 "%s: line %d: unmatched \')\' in a PS block", | |
| 321 symstruct->gs_pathname, lineno); | |
| 322 exit(1); | |
| 323 case '{': | |
| 324 n++; | |
| 325 continue; | |
| 326 case '}': | |
| 327 n--; | |
| 328 continue; | |
| 329 } | |
| 330 } | |
| 331 c = getc(inf); | |
| 332 if (c != '\n') { | |
| 333 fprintf(stderr, | |
| 334 "%s: line %d: '}' closing PS block must be directly followed by newline\n", | |
| 335 symstruct->gs_pathname, lineno); | |
| 336 exit(1); | |
| 337 } | |
| 338 lineno++; | |
| 339 } | |
| 340 | |
| 341 static | |
| 342 skip_over_ps_string() | |
| 343 { | |
| 344 register int c, n; | |
| 345 | |
| 346 for (n = 1; n > 0; ) { | |
| 347 c = getc(inf); | |
| 348 switch (c) { | |
| 349 case EOF: | |
| 350 badeof: fprintf(stderr, "%s: EOF in a PS block\n", | |
| 351 symstruct->gs_pathname); | |
| 352 exit(1); | |
| 353 case '\n': | |
| 354 lineno++; | |
| 355 continue; | |
| 356 case '(': | |
| 357 n++; | |
| 358 continue; | |
| 359 case ')': | |
| 360 n--; | |
| 361 continue; | |
| 362 case '\\': | |
| 363 c = getc(inf); | |
| 364 if (c == EOF) | |
| 365 goto badeof; | |
| 366 if (c == '\n') | |
| 367 lineno++; | |
| 368 continue; | |
| 369 } | |
| 370 } | |
| 371 } |
