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;
+		}
+	}
+}