diff ueda/uschem-print/gschemcode.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/uschem-print/gschemcode.c	Mon Jul 20 00:24:37 2015 +0000
@@ -0,0 +1,484 @@
+/*
+ * We print gschem code in two places: symbols and graphblocks.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <strings.h>
+#include "../libuschem/graphsym.h"
+#include "../libuschem/schemstruct.h"
+
+static char leftstr[] = "/left";
+static char rightstr[] = "/right";
+static char topstr[] = "/top";
+static char bottomstr[] = "/bottom";
+static char ctrstr[] = "/ctr";
+
+char *gschem_text_halign[9] =  {leftstr,  leftstr,  leftstr,
+				ctrstr,   ctrstr,   ctrstr,
+				rightstr, rightstr, rightstr};
+char *gschem_text_valign[9] =  {bottomstr,ctrstr,   topstr,
+				bottomstr,ctrstr,   topstr,
+				bottomstr,ctrstr,   topstr};
+
+#define	MAXLINE		256
+
+static FILE *inf;
+static char *pathname;
+static int lineno;
+static int issym, in_pinblock;
+static int linewidth, dashed;
+static int font_ptsize;
+static int varpin_count;
+
+print_gschem_code_sym(file, sym)
+	FILE *file;
+	struct graphsym *sym;
+{
+	inf = file;
+	pathname = sym->gs_pathname;
+	lineno = 0;
+	issym = 1;
+	mymain();
+}
+
+print_gschem_code_graphblk(file, blk, orig_filename)
+	FILE *file;
+	struct graphblock *blk;
+	char *orig_filename;
+{
+	inf = file;
+	pathname = orig_filename;
+	lineno = blk->lineno;
+	issym = 0;
+	fseek(inf, blk->offset, 0);
+	mymain();
+}
+
+static
+mymain()
+{
+	char line[MAXLINE];
+	register char *cp;
+	register int c;
+
+	in_pinblock = 0;
+	linewidth = -1;
+	dashed = 0;
+	font_ptsize = 0;
+	varpin_count = 0;
+	while (getline(line)) {
+		switch (line[0]) {
+		case '%':		/* PS-like comments */
+		case '\0':		/* allow blank lines too */
+			continue;
+		case '{':
+			in_pinblock++;
+			continue;
+		case '}':
+			if (!in_pinblock)
+				return;
+			in_pinblock--;
+			continue;
+		}
+		if (!isalpha(line[0])) {
+inv:			fprintf(stderr, "%s: line %d: invalid gschem code\n",
+				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;
+			do_ps_block();
+			/* be safe about the graphics state */
+			linewidth = -1;
+			font_ptsize = 0;
+			continue;
+		} else if (strlen(line) != 1)
+			continue;	/* ignore these */
+		line[1] = ' ';
+		/* dispatch by single-char type */
+		switch (line[0]) {
+		case 'v':
+			continue;	/* ignore */
+		/* simple graphics */
+		case 'L':
+			do_line(line);
+			continue;
+		case 'B':
+			do_box(line);
+			continue;
+		case 'V':
+			do_circle(line);
+			continue;
+		case 'A':
+			do_arc(line);
+			continue;
+		case 'P':
+			handle_pin(line);
+			continue;
+		case 'T':
+			handle_T_obj(line, lineno);
+			continue;
+		default:
+			goto inv;
+		}
+	}
+}
+
+static
+do_line(objline)
+	char *objline;
+{
+	int numparams[10];
+
+	parse_numline(objline, lineno, numparams, 10);
+	if (setdash(numparams[7], numparams[8], numparams[9]) < 0)
+		return;
+	setlinewidth(numparams[5]);
+	emit_coordpair(numparams[0], numparams[1]);
+	fputs("moveto ", stdout);
+	emit_coordpair(numparams[2], numparams[3]);
+	puts("lineto stroke");
+}
+
+static
+do_box(objline)
+	char *objline;
+{
+	int numparams[16];
+
+	parse_numline(objline, lineno, numparams, 16);
+	switch (numparams[10]) {
+	case 0:
+		if (setdash(numparams[7], numparams[8], numparams[9]) < 0)
+			return;
+		setlinewidth(numparams[5]);
+		emit_coordpair(numparams[0], numparams[1]);
+		emit_coordpair(numparams[2], numparams[3]);
+		puts("rectstroke");
+		return;
+	case 1:
+		emit_coordpair(numparams[0], numparams[1]);
+		emit_coordpair(numparams[2], numparams[3]);
+		puts("rectfill");
+		return;
+	default:
+		fprintf(stderr,
+		"%s: line %d: fill type %d not implemented; object omitted\n",
+			pathname, lineno, numparams[10]);
+	}
+}
+
+static
+do_circle(objline)
+	char *objline;
+{
+	int numparams[15];
+
+	parse_numline(objline, lineno, numparams, 15);
+	switch (numparams[9]) {
+	case 0:
+		if (setdash(numparams[6], numparams[7], numparams[8]) < 0)
+			return;
+		setlinewidth(numparams[4]);
+		emit_coordpair(numparams[0], numparams[1]);
+		printf("%d circlestroke\n", numparams[2]);
+		return;
+	case 1:
+		emit_coordpair(numparams[0], numparams[1]);
+		printf("%d circlefill\n", numparams[2]);
+		return;
+	default:
+		fprintf(stderr,
+		"%s: line %d: fill type %d not implemented; object omitted\n",
+			pathname, lineno, numparams[9]);
+	}
+}
+
+static
+do_arc(objline)
+	char *objline;
+{
+	int numparams[11];
+
+	parse_numline(objline, lineno, numparams, 11);
+	if (!numparams[4])	/* degenerate? */
+		return;		/* ignore those */
+	if (setdash(numparams[8], numparams[9], numparams[10]) < 0)
+		return;
+	setlinewidth(numparams[6]);
+	puts("newpath");
+	emit_coordpair(numparams[0], numparams[1]);
+	printf("%d %d %d%s%s arc stroke\n", numparams[2], numparams[3],
+		numparams[3] + numparams[4], numparams[4] > 0 ? "" : " exch",
+		issym ? " mirrorarc" : "");
+}
+
+static
+setlinewidth(newval)
+{
+	if (newval != linewidth) {
+		linewidth = newval;
+		if (linewidth)
+			printf("%d setlinewidth\n", linewidth);
+		else
+			puts("defaultlinewidth setlinewidth");
+	}
+	return(0);
+}
+
+static
+setdash(dashstyle, dashlength, dashspace)
+{
+	switch (dashstyle) {
+	case 0:
+		if (dashed) {
+			puts("setsolid");
+			dashed = 0;
+		}
+		return(0);
+	case 2:
+		printf("[%d %d] 0 setdash\n", dashlength, dashspace);
+		dashed = 1;
+		return(0);
+	default:
+		fprintf(stderr,
+		"%s: line %d: dash style %d not implemented; object omitted\n",
+			pathname, lineno, dashstyle);
+		return(-1);
+	}
+}
+
+static
+emit_coordpair(x, y)
+{
+	printf("%d%s %d ", x, issym ? " mirror" : "", y);
+}
+
+static
+handle_pin(objline)
+	char *objline;
+{
+	int numparams[7];
+
+	parse_numline(objline, lineno, numparams, 7);
+	printf("%d mirror %d %d mirror %d drawpin\n", numparams[0],
+		numparams[1], numparams[2], numparams[3]);
+}
+
+static
+handle_T_obj(objline, objlineno)
+	char *objline;
+{
+	int numparams[9];
+	char textline[MAXLINE];
+	register int i;
+	register char *cp;
+	int readystr, isvarpin;
+
+	parse_numline(objline, objlineno, numparams, 9);
+	if (numparams[8] < 1) {
+		fprintf(stderr, "%s: line %d: T object: num_lines<1!\n",
+			pathname, objlineno);
+		exit(1);
+	}
+	if (numparams[8] > 1)
+		fprintf(stderr,
+		"warning: multiline T objects not implemented (found in %s)\n",
+			pathname);
+	for (i = numparams[8]; i; i--) {
+		if (!getline(textline)) {
+			fprintf(stderr, "%s: EOF in T object\n", pathname);
+			exit(1);
+		}
+		if (!numparams[4])	/* visible? */
+			continue;	/* nope */
+		isvarpin = 0;
+		if (issym) {
+			readystr = 0;
+			cp = index(textline, '=');
+			if (cp) {
+				cp++;
+				if (!in_pinblock)	/* we don't print */
+					continue;	/* top level attrs */
+				if (!strcmp(cp, "%d"))
+					isvarpin = 1;
+			} else
+				cp = textline;
+		} else {
+			cp = textline;
+			readystr = (cp[0] == '(');
+		}
+		if (numparams[7] < 0 || numparams[7] > 8) {
+			fprintf(stderr,
+			"%s: line %d: T object: alignment %d is invalid\n",
+				pathname, objlineno, numparams[7]);
+			continue;
+		}
+		if (font_ptsize != numparams[3]) {
+			font_ptsize = numparams[3];
+			printf("/Helvetica %d selisofnt\n", font_ptsize);
+		}
+		if (isvarpin)
+			printf("pins %d get", varpin_count++);
+		else if (readystr)
+			fputs(cp, stdout);
+		else
+			emit_ps_string(cp);
+		printf(" %s%s %s %d ", gschem_text_halign[numparams[7]],
+			issym ? " mirrortext" : "",
+			gschem_text_valign[numparams[7]], numparams[6]);
+		emit_coordpair(numparams[0], numparams[1]);
+		puts("Tshow");
+	}
+}
+
+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",
+				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
+do_ps_block()
+{
+	register int c, n;
+
+	for (n = 0; ; ) {
+		c = getc(inf);
+		switch (c) {
+		case EOF:
+badeof:			fprintf(stderr, "%s: EOF in a PS block\n", pathname);
+			exit(1);
+		case '%':
+			for (;;) {
+				c = getc(inf);
+				if (c == EOF)
+					goto badeof;
+				if (c == '\n')
+					break;
+			}
+			/* FALL THRU */
+		case '\n':
+			putchar(c);
+			lineno++;
+			continue;
+		case '(':
+			putchar(c);
+			skip_over_ps_string();
+			continue;
+		case ')':
+			fprintf(stderr,
+				"%s: line %d: unmatched \')\' in a PS block",
+				pathname, lineno);
+			exit(1);
+		case '{':
+			putchar(c);
+			n++;
+			continue;
+		case '}':
+			if (!n)
+				goto out;
+			putchar(c);
+			n--;
+			continue;
+		default:
+			putchar(c);
+			continue;
+		}
+	}
+out:	c = getc(inf);
+	if (c != '\n') {
+		fprintf(stderr,
+"%s: line %d: '}' closing PS block must be directly followed by newline\n",
+			pathname, lineno);
+		exit(1);
+	}
+	lineno++;
+	putchar(c);
+}
+
+static
+skip_over_ps_string()
+{
+	register int c, n;
+
+	for (n = 1; n > 0; ) {
+		c = getc(inf);
+		if (c == EOF) {
+badeof:			fprintf(stderr, "%s: EOF in a PS block\n", pathname);
+			exit(1);
+		}
+		putchar(c);
+		switch (c) {
+		case '\n':
+			lineno++;
+			continue;
+		case '(':
+			n++;
+			continue;
+		case ')':
+			n--;
+			continue;
+		case '\\':
+			c = getc(inf);
+			if (c == EOF)
+				goto badeof;
+			putchar(c);
+			if (c == '\n')
+				lineno++;
+			continue;
+		}
+	}
+}