FreeCalypso > hg > ueda-linux
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ueda/libuschem/graphsym_load.c Mon Jul 20 00:24:37 2015 +0000 @@ -0,0 +1,371 @@ +/* + * 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; + } + } +}