FreeCalypso > hg > ueda-linux
view ueda/libuschem/graphsym_load.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 | cd92449fdb51 |
children |
line wrap: on
line source
/* * The black magic of loading/prescanning gschem-based uschem symbols */ #include <ctype.h> #include <stdio.h> #include <strings.h> #include "graphsym.h" extern char *malloc(); extern char *copystr(); #define MAXLINE 256 static struct graphsym *symstruct; static FILE *inf; static int lineno; static struct graphsym_pindef **pintail; read_symbol_file(gs, f) struct graphsym *gs; FILE *f; { symstruct = gs; inf = f; lineno = 0; pintail = &gs->gs_pins; mymain(); if (!gs->gs_npins) { fprintf(stderr, "%s: symbol has no pins (invalid)\n", gs->gs_pathname); exit(1); } } static mymain() { char line[MAXLINE]; register char *cp; register int c; while (getline(line)) { if (line[0] == '%') /* PS-like comments */ continue; if (line[0] == '\0') /* allow blank lines too */ continue; if (!isalpha(line[0])) { inv: fprintf(stderr, "%s: line %d: invalid symbol data\n", symstruct->gs_pathname, lineno); exit(1); } for (cp = line; isalpha(*cp); cp++) ; if (!isspace(*cp)) goto inv; *cp++ = '\0'; while (isspace(*cp)) cp++; if (!strcmp(line, "PS")) { if (strcmp(cp, "{")) goto inv; skip_ps_block(); continue; } else if (strlen(line) != 1) goto inv; line[1] = ' '; /* dispatch by single-char type */ switch (line[0]) { case 'v': continue; /* ignore */ /* simple graphics */ case 'L': case 'B': case 'V': case 'A': /* ignore at this stage too */ continue; case 'P': handle_pin(line, lineno); continue; case 'T': handle_T_obj(line, lineno); continue; default: goto inv; } } } static handle_pin(objline, objlineno) char *objline; { int numparams[7]; char junkline[MAXLINE]; register struct graphsym_pindef *pin; parse_numline(objline, objlineno, numparams, 7); pin = (struct graphsym_pindef *) malloc(sizeof(struct graphsym_pindef)); if (!pin) { perror("malloc"); exit(1); } bzero(pin, sizeof(struct graphsym_pindef)); if (numparams[6]) { pin->gspd_x = numparams[2]; pin->gspd_y = numparams[3]; } else { pin->gspd_x = numparams[0]; pin->gspd_y = numparams[1]; } *pintail = pin; pintail = &pin->gspd_next; symstruct->gs_npins++; if (!getline(junkline) || strcmp(junkline, "{")) { fprintf(stderr, "%s: line %d: P line must be followed by '{' line\n", symstruct->gs_pathname, objlineno); exit(1); } read_pin_attrs(pin, objlineno); } static read_pin_attrs(pin, objlineno) struct graphsym_pindef *pin; { char line[MAXLINE]; int Tline_parsed[9]; register char *cp; for (;;) { if (!getline(line)) { badeof: fprintf(stderr, "%s: EOF in pin attribute block\n", symstruct->gs_pathname); exit(1); } if (line[0] == '%') /* PS-like comments */ continue; if (line[0] == '\0') /* allow blank lines too */ continue; if (line[0] == '}') return; if (!isalpha(line[0])) { inv: fprintf(stderr, "%s: line %d: invalid symbol data\n", symstruct->gs_pathname, lineno); exit(1); } for (cp = line; isalpha(*cp); cp++) ; if (!isspace(*cp)) goto inv; *cp++ = '\0'; if (!strcmp(line, "attr")) { while (isspace(*cp)) cp++; handle_attr(pin, cp); continue; } else if (strcmp(line, "T")) { fprintf(stderr, "%s: line %d: wrong object type in pin attribute block\n", symstruct->gs_pathname, lineno); exit(1); } line[1] = ' '; parse_numline(line, lineno, Tline_parsed, 9); if (Tline_parsed[8] < 1) { fprintf(stderr, "%s: line %d: T object: num_lines<1!\n", symstruct->gs_pathname, lineno); exit(1); } if (Tline_parsed[8] > 1) { fprintf(stderr, "%s: line %d: multiline text object in attribute block not supported\n", symstruct->gs_pathname, lineno); exit(1); } if (!getline(line)) goto badeof; handle_attr(pin, line); } } static handle_attr(pin, line) register struct graphsym_pindef *pin; register char *line; { register char *cp; cp = index(line, '='); if (!cp) return; *cp++ = '\0'; if (!*cp) /* avoid null string values */ return; if (!strcmp(line, "pinname")) { if (pin->gspd_pinname) { dup: fprintf(stderr, "%s: line %d: duplicate %s attribute (ignored)\n", symstruct->gs_pathname, lineno, line); return; } pin->gspd_pinname = copystr(cp); } else if (!strcmp(line, "pinnumber")) { if (pin->gspd_pinnumber) goto dup; pin->gspd_pinnumber = copystr(cp); if (!strcmp(cp, "%d")) symstruct->gs_varpins++; } else if (!strcmp(line, "forcenet")) { if (pin->gspd_forcenet) goto dup; pin->gspd_forcenet = copystr(cp); symstruct->gs_forcenets++; } } static handle_T_obj(objline, objlineno) char *objline; { int numparams[9]; char junkline[MAXLINE]; register int i; parse_numline(objline, objlineno, numparams, 9); if (numparams[8] < 1) { fprintf(stderr, "%s: line %d: T object: num_lines<1!\n", symstruct->gs_pathname, objlineno); exit(1); } for (i = numparams[8]; i; i--) { if (!getline(junkline)) { fprintf(stderr, "%s: EOF in T object\n", symstruct->gs_pathname); exit(1); } } } static parse_numline(line, lineno, numarray, nfields) char *line; int lineno; int *numarray; int nfields; { register char *cp, *np; register int i; for (i = 0, cp = line+1; i < nfields; i++) { if (!isspace(*cp)) { inv: fprintf(stderr, "%s: line %d: invalid numeric line\n", symstruct->gs_pathname, lineno); exit(1); } while (isspace(*cp)) cp++; np = cp; if (*cp == '-') cp++; if (!isdigit(*cp)) goto inv; while (isdigit(*cp)) cp++; numarray[i] = atoi(np); } if (*cp) goto inv; } static getline(linebuf) char *linebuf; { register char *cp; if (fgets(linebuf, MAXLINE, inf) == NULL) return(0); lineno++; /* strip trailing newline or other whitespace */ cp = index(linebuf, '\0'); while (cp > linebuf && isspace(cp[-1])) cp--; *cp = '\0'; return(1); } static skip_ps_block() { register int c, n; for (n = 0; n >= 0; ) { c = getc(inf); switch (c) { case EOF: badeof: fprintf(stderr, "%s: EOF in a PS block\n", symstruct->gs_pathname); exit(1); case '%': for (;;) { c = getc(inf); if (c == EOF) goto badeof; if (c == '\n') break; } /* FALL THRU */ case '\n': lineno++; continue; case '(': skip_over_ps_string(); continue; case ')': fprintf(stderr, "%s: line %d: unmatched \')\' in a PS block", symstruct->gs_pathname, lineno); exit(1); case '{': n++; continue; case '}': n--; continue; } } c = getc(inf); if (c != '\n') { fprintf(stderr, "%s: line %d: '}' closing PS block must be directly followed by newline\n", symstruct->gs_pathname, lineno); exit(1); } lineno++; } static skip_over_ps_string() { register int c, n; for (n = 1; n > 0; ) { c = getc(inf); switch (c) { case EOF: badeof: fprintf(stderr, "%s: EOF in a PS block\n", symstruct->gs_pathname); exit(1); case '\n': lineno++; continue; case '(': n++; continue; case ')': n--; continue; case '\\': c = getc(inf); if (c == EOF) goto badeof; if (c == '\n') lineno++; continue; } } }