diff ueda/libuschem/rdschem_parse.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/rdschem_parse.c	Mon Jul 20 00:24:37 2015 +0000
@@ -0,0 +1,696 @@
+/*
+ * uschem schematic parser
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <strings.h>
+#include "schemstruct.h"
+#include "parserint.h"
+
+extern char *copystr();
+
+extern struct schem_parse_state schem_parse_state;
+
+extern struct schemobj *parser_alloc_obj();
+extern struct decoration *parser_alloc_decor();
+extern struct netpoint *parser_alloc_netpoint();
+extern struct xypair parse_drawing_size_spec();
+extern struct graphblock *rdschem_graphblock();
+
+rdschem_parse_schemline()
+{
+	register int t;
+	struct xypair drawing_size;
+
+	t = rdschem_token();
+	if (t != STRING || strcmp(schem_parse_state.string, "Schem")) {
+		fprintf(stderr,
+		"%s is not a uschem schematic (doesn't begin with Schem)\n",
+			schem_parse_state.schem->orig_filename);
+		exit(1);
+	}
+
+	t = rdschem_token();
+	if (t != STRING)
+inv:		rdschem_error("Schem line: syntax error");
+	if (!strcmp(schem_parse_state.string, "graph")) {
+		schem_parse_state.schem->is_graph = 1;
+		t = rdschem_token();
+		if (t != STRING && t != QSTRING)
+			goto inv;
+		drawing_size =
+			parse_drawing_size_spec(schem_parse_state.string);
+		schem_parse_state.schem->graph_xsize = drawing_size.x;
+		schem_parse_state.schem->graph_ysize = drawing_size.y;
+	} else if (!strcmp(schem_parse_state.string, "nograph"))
+		schem_parse_state.schem->is_graph = 0;
+	else
+		goto inv;
+
+	t = rdschem_token();
+	if (t != ';')
+		goto inv;
+}
+
+static struct decoration *
+parse_decor_attr()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_ATTR);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(attribute definition decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("attribute name may not be a null string");
+	decor->decorattr_name = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != '=')
+		goto syntaxerr;
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+		goto syntaxerr;
+	if (!schem_parse_state.string[0])
+		rdschem_error("attribute value may not be a null string");
+	decor->decorattr_value = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != ')')
+		goto syntaxerr;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_displayattr()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_DISPLAYATTR);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(DisplayAttr decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("attribute name may not be a null string");
+	decor->decordisp_attr = copystr(schem_parse_state.string);
+	decor->decordisp_x = parse_number();
+	decor->decordisp_y = parse_number();
+	decor->decordisp_ptsize = parse_number();
+	decor->decordisp_rotate = parse_number();
+	decor->decordisp_alignment = parse_number();
+	t = rdschem_token();
+	if (t != ';')
+		goto syntaxerr;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_displaynetname()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_DISPLAYNETNAME);
+	decor->decordisp_x = parse_number();
+	decor->decordisp_y = parse_number();
+	decor->decordisp_ptsize = parse_number();
+	decor->decordisp_rotate = parse_number();
+	decor->decordisp_alignment = parse_number();
+	t = rdschem_token();
+	if (t != ';')
+		rdschem_error("(DisplayNetName decoration) syntax error");
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_pintonet()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_PINTONET);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(PinToNet decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("pin ID may not be a null string");
+	if (!strcmp(schem_parse_state.string, "#"))
+		rdschem_error("pin ID \"#\" is invalid");
+	decor->decorpincon_pin = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+		goto syntaxerr;
+	if (!schem_parse_state.string[0])
+		rdschem_error("net name may not be a null string");
+	decor->decorpincon_netname = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != ';')
+		goto syntaxerr;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_noconnect()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_NOCONNECT);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(NoConnect decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("pin ID may not be a null string");
+	if (!strcmp(schem_parse_state.string, "#"))
+		rdschem_error("pin ID \"#\" is invalid");
+	decor->decorpincon_pin = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != ';')
+		goto syntaxerr;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_symonpin()
+{
+	register struct decoration *decor;
+	register int t;
+
+	decor = parser_alloc_decor(DECOR_TYPE_SYMONPIN);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(SymOnPin decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("pin ID may not be a null string");
+	if (!strcmp(schem_parse_state.string, "#"))
+		rdschem_error("pin ID \"#\" is invalid");
+	decor->decorpinsym_pin = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+		goto syntaxerr;
+	if (!schem_parse_state.string[0])
+		rdschem_error("graphical symbol name may not be a null string");
+	decor->decorpinsym_symname = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) {
+		decor->decorpinsym_mirror = 1;
+		t = rdschem_token();
+	}
+	if (t != ';')
+		goto syntaxerr;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_graphblock(type)
+{
+	register int t;
+	register struct decoration *decor;
+	register struct graphblock *blk;
+
+	t = rdschem_token();
+	if (t != '{')
+	    rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'");
+	blk = rdschem_graphblock(type);
+	decor = parser_alloc_decor(DECOR_TYPE_GRAPHBLOCK);
+	decor->decorgraph_body = blk;
+	schem_parse_state.schem->has_graphblocks = 1;
+	return(decor);
+}
+
+static struct decoration *
+parse_decor_comment()
+{
+	register int t;
+	register struct decoration *decor;
+
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(Comment decoration) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("schematic comment may not be a null string");
+	decor = parser_alloc_decor(DECOR_TYPE_COMMENT);
+	decor->decorcomment_text = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != ';')
+		goto syntaxerr;
+	return(decor);
+}
+
+struct decoration *
+rdschem_parse_decor_block()
+{
+	struct decoration *decor, *head, **tailp;
+	register int t;
+	char errbuf[256];
+
+	for (head = NULL, tailp = &head; ; ) {
+		t = rdschem_token();
+		switch (t) {
+		case 0:
+			rdschem_error("EOF in a decoration block");
+		case '(':
+			decor = parse_decor_attr();
+			goto addit;
+		case ';':
+			/* "null statement" */
+			continue;
+		case '}':
+			return(head);
+		}
+		if (t != STRING)
+		    rdschem_error("syntax error: decoration keyword expected");
+		if (!strcmp(schem_parse_state.string, "DisplayAttr"))
+			decor = parse_decor_displayattr();
+		else if (!strcmp(schem_parse_state.string, "DisplayNetName"))
+			decor = parse_decor_displaynetname();
+		else if (!strcmp(schem_parse_state.string, "PinToNet"))
+			decor = parse_decor_pintonet();
+		else if (!strcmp(schem_parse_state.string, "NoConnect"))
+			decor = parse_decor_noconnect();
+		else if (!strcmp(schem_parse_state.string, "SymOnPin"))
+			decor = parse_decor_symonpin();
+		else if (!strcmp(schem_parse_state.string, "GraphBlockG"))
+			decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_GSCHEM);
+		else if (!strcmp(schem_parse_state.string, "GraphBlockPS"))
+			decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_PS);
+		else if (!strcmp(schem_parse_state.string, "Comment"))
+			decor = parse_decor_comment();
+		else {
+			sprintf(errbuf,
+				"%s is not a recognized decoration keyword",
+				schem_parse_state.string);
+			rdschem_error(errbuf);
+		}
+addit:		*tailp = decor;
+		tailp = &decor->decor_next;
+	}
+}
+
+rdschem_parse_object()
+{
+	register int t;
+	char errbuf[256];
+
+	t = rdschem_token();
+	if (!t)			/* EOF aka end of schematic */
+		return(1);
+	if (t == ';')		/* "null statement" */
+		return(0);
+	if (t != STRING)
+		rdschem_error("syntax error: object keyword expected");
+
+	if (!strcmp(schem_parse_state.string, "Component"))
+		return(rdschem_parse_compinst());
+	if (!strcmp(schem_parse_state.string, "GraphSym"))
+		return(rdschem_parse_graphsym());
+	if (!strcmp(schem_parse_state.string, "Net"))
+		return(rdschem_parse_net());
+	if (!strcmp(schem_parse_state.string, "GraphNet"))
+		return(rdschem_parse_graphnet());
+	if (!strcmp(schem_parse_state.string, "NetLine"))
+		return(rdschem_parse_netline());
+	if (!strcmp(schem_parse_state.string, "BusSeg"))
+		return(rdschem_parse_busseg());
+	if (!strcmp(schem_parse_state.string, "GraphBlockG"))
+		return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_GSCHEM));
+	if (!strcmp(schem_parse_state.string, "GraphBlockPS"))
+		return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_PS));
+	if (!strcmp(schem_parse_state.string, "Comment"))
+		return(rdschem_parse_comment_obj());
+
+	sprintf(errbuf, "%s is not a recognized object keyword",
+		schem_parse_state.string);
+	rdschem_error(errbuf);
+}
+
+rdschem_parse_compinst()
+{
+	register int t;
+	register struct schemobj *obj;
+
+	obj = parser_alloc_obj(OBJTYPE_COMPINST);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(Component object) syntax error");
+	if (!schem_parse_state.string[0])
+	    rdschem_error("component instance name may not be a null string");
+	obj->compobj_instname = copystr(schem_parse_state.string);
+
+	t = rdschem_token();
+	if (t == STRING && !strcmp(schem_parse_state.string, "graph")) {
+		obj->compobj_isgraph = 1;
+		t = rdschem_token();
+		if (t != STRING && t != QSTRING)
+			goto syntaxerr;
+		if (!schem_parse_state.string[0])
+		rdschem_error("graphical symbol name may not be a null string");
+		obj->compobj_graph_symname = copystr(schem_parse_state.string);
+		obj->compobj_x = parse_number();
+		obj->compobj_y = parse_number();
+		t = rdschem_token();
+		if (t == STRING && !strcmp(schem_parse_state.string, "rot")) {
+			obj->compobj_rotate = parse_number();
+			t = rdschem_token();
+		}
+		if (t == STRING && !strcmp(schem_parse_state.string, "mirror")){
+			obj->compobj_mirror = 1;
+			t = rdschem_token();
+		}
+	}
+
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+
+	if (t != ';')
+		goto syntaxerr;
+	parser_add_object(obj);
+	return(0);
+}
+
+rdschem_parse_graphsym()
+{
+	register int t;
+	register struct schemobj *obj;
+
+	obj = parser_alloc_obj(OBJTYPE_GRAPHSYM);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(GraphSym object) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("graphical symbol name may not be a null string");
+	obj->compobj_graph_symname = copystr(schem_parse_state.string);
+
+	obj->compobj_x = parse_number();
+	obj->compobj_y = parse_number();
+	t = rdschem_token();
+	if (t == STRING && !strcmp(schem_parse_state.string, "rot")) {
+		obj->compobj_rotate = parse_number();
+		t = rdschem_token();
+	}
+	if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) {
+		obj->compobj_mirror = 1;
+		t = rdschem_token();
+	}
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+
+	if (t != ';')
+		goto syntaxerr;
+	parser_add_object(obj);
+	return(0);
+}
+
+rdschem_parse_net()
+{
+	register int t;
+	register struct schemobj *obj;
+	register struct netpoint *netpt;
+	struct netpoint *head, **tailp;
+
+	obj = parser_alloc_obj(OBJTYPE_NET);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(Net object) syntax error");
+	if (schem_parse_state.string[0])
+		obj->netobj_netname = copystr(schem_parse_state.string);
+
+	head = NULL;
+	tailp = &head;
+	for (;;) {
+		t = rdschem_token();
+		if (t == ';' || t == '{')
+			break;
+		if (t != STRING && t != QSTRING)
+			goto syntaxerr;
+		if (!schem_parse_state.string[0])
+			goto syntaxerr;
+		netpt = parser_alloc_netpoint(NETPT_TYPE_PIN);
+		netpt->netpt_pin_nameref = copystr(schem_parse_state.string);
+		*tailp = netpt;
+		tailp = &netpt->netpt_next;
+	}
+	obj->netobj_points = head;
+
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+	if (t != ';')
+		goto syntaxerr;
+
+	if (obj->netobj_points)
+		parser_add_object(obj);
+	else {
+		fprintf(stderr, "%s: line %d: null Net object ignored\n",
+			schem_parse_state.schem->orig_filename,
+			schem_parse_state.lineno);
+		free(obj);
+	}
+	return(0);
+}
+
+static struct xypair
+parse_coord_pair()
+{
+	register int t;
+	struct xypair retval;
+
+	retval.x = parse_number();
+	t = rdschem_token();
+	if (t != ',')
+syntaxerr:	rdschem_error("syntax error in coordinate pair");
+	retval.y = parse_number();
+	t = rdschem_token();
+	if (t != ')')
+		goto syntaxerr;
+	return(retval);
+}
+
+static struct netpoint *
+parse_graphnet_point()
+{
+	register int t;
+	register struct netpoint *netpt;
+	struct xypair coord_pair;
+
+	t = rdschem_token();
+	if (t == '(') {
+		netpt = parser_alloc_netpoint(NETPT_TYPE_POINT);
+		coord_pair = parse_coord_pair();
+		netpt->netpt_x = coord_pair.x;
+		netpt->netpt_y = coord_pair.y;
+		netpt->netpt_coord_valid = 1;
+		return(netpt);
+	} else if (t == STRING && !strcmp(schem_parse_state.string, "Pin")) {
+		netpt = parser_alloc_netpoint(NETPT_TYPE_PIN);
+		t = rdschem_token();
+		if (t == '(') {
+			coord_pair = parse_coord_pair();
+			netpt->netpt_x = coord_pair.x;
+			netpt->netpt_y = coord_pair.y;
+			netpt->netpt_coord_valid = 1;
+			t = rdschem_token();
+		}
+		if (t == '=') {
+			t = rdschem_token();
+			if (t != STRING && t != QSTRING ||
+			    !schem_parse_state.string[0])
+		rdschem_error("syntax error: pin name reference expected");
+			netpt->netpt_pin_nameref =
+				copystr(schem_parse_state.string);
+		} else if (netpt->netpt_coord_valid)
+			schem_parse_state.pushback_token = t;
+		else
+			rdschem_error("syntax error: Pin must be followed by coordinates or name reference");
+		return(netpt);
+	} else if (t == STRING && !strcmp(schem_parse_state.string, "Tjoin")) {
+		netpt = parser_alloc_netpoint(NETPT_TYPE_TJOIN);
+		t = rdschem_token();
+		if (t != '(')
+	rdschem_error("syntax error: Tjoin must be followed by coordinates");
+		coord_pair = parse_coord_pair();
+		netpt->netpt_x = coord_pair.x;
+		netpt->netpt_y = coord_pair.y;
+		netpt->netpt_coord_valid = 1;
+		return(netpt);
+	} else if (t == STRING && !strcmp(schem_parse_state.string, "Pseudo")) {
+		netpt = parser_alloc_netpoint(NETPT_TYPE_PSEUDO);
+		t = rdschem_token();
+		if (t != '(')
+	rdschem_error("syntax error: Pseudo must be followed by coordinates");
+		coord_pair = parse_coord_pair();
+		netpt->netpt_x = coord_pair.x;
+		netpt->netpt_y = coord_pair.y;
+		netpt->netpt_coord_valid = 1;
+		return(netpt);
+	}
+	schem_parse_state.pushback_token = t;
+	return(NULL);
+}
+
+rdschem_parse_graphnet()
+{
+	register int t;
+	register struct schemobj *obj;
+	register struct netpoint *netpt;
+	struct netpoint *head, **tailp;
+
+	obj = parser_alloc_obj(OBJTYPE_GRAPHNET);
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(GraphNet object) syntax error");
+	if (schem_parse_state.string[0])
+		obj->netobj_netname = copystr(schem_parse_state.string);
+
+	head = NULL;
+	tailp = &head;
+	for (;;) {
+		netpt = parse_graphnet_point();
+		if (!netpt)
+			break;
+		*tailp = netpt;
+		tailp = &netpt->netpt_next;
+	}
+	obj->netobj_points = head;
+
+	t = rdschem_token();
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+	if (t != ';')
+		goto syntaxerr;
+
+	if (obj->netobj_points)
+		parser_add_object(obj);
+	else {
+		fprintf(stderr, "%s: line %d: null GraphNet object ignored\n",
+			schem_parse_state.schem->orig_filename,
+			schem_parse_state.lineno);
+		free(obj);
+	}
+	return(0);
+}
+
+rdschem_parse_netline()
+{
+	register int t;
+	register struct schemobj *obj;
+	struct xypair coord_pair;
+
+	obj = parser_alloc_obj(OBJTYPE_NETLINE);
+
+	t = rdschem_token();
+	if (t != '(')
+syntaxerr:	rdschem_error("(NetLine object) syntax error");
+	coord_pair = parse_coord_pair();
+	obj->lineobj_x1 = coord_pair.x;
+	obj->lineobj_y1 = coord_pair.y;
+	t = rdschem_token();
+	if (t != '(')
+		goto syntaxerr;
+	coord_pair = parse_coord_pair();
+	obj->lineobj_x2 = coord_pair.x;
+	obj->lineobj_y2 = coord_pair.y;
+
+	t = rdschem_token();
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+	if (t != ';')
+		goto syntaxerr;
+	parser_add_object(obj);
+	return(0);
+}
+
+rdschem_parse_busseg()
+{
+	register int t;
+	register struct schemobj *obj;
+	struct xypair coord_pair;
+
+	obj = parser_alloc_obj(OBJTYPE_BUSSEG);
+
+	t = rdschem_token();
+	if (t != '(')
+syntaxerr:	rdschem_error("(BusSeg object) syntax error");
+	coord_pair = parse_coord_pair();
+	obj->lineobj_x1 = coord_pair.x;
+	obj->lineobj_y1 = coord_pair.y;
+	t = rdschem_token();
+	if (t != '(')
+		goto syntaxerr;
+	coord_pair = parse_coord_pair();
+	obj->lineobj_x2 = coord_pair.x;
+	obj->lineobj_y2 = coord_pair.y;
+
+	t = rdschem_token();
+	if (t == '{') {
+		obj->obj_decorations = rdschem_parse_decor_block();
+		t = rdschem_token();
+	}
+	if (t != ';')
+		goto syntaxerr;
+	parser_add_object(obj);
+	return(0);
+}
+
+rdschem_parse_graphblock_obj(type)
+{
+	register int t;
+	register struct schemobj *obj;
+	register struct graphblock *blk;
+
+	t = rdschem_token();
+	if (t != '{')
+	    rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'");
+	blk = rdschem_graphblock(type);
+	obj = parser_alloc_obj(OBJTYPE_GRAPHBLOCK);
+	obj->graphblockobj_body = blk;
+	parser_add_object(obj);
+	schem_parse_state.schem->has_graphblocks = 1;
+	return(0);
+}
+
+rdschem_parse_comment_obj()
+{
+	register int t;
+	register struct schemobj *obj;
+
+	t = rdschem_token();
+	if (t != STRING && t != QSTRING)
+syntaxerr:	rdschem_error("(Comment object) syntax error");
+	if (!schem_parse_state.string[0])
+		rdschem_error("schematic comment may not be a null string");
+	obj = parser_alloc_obj(OBJTYPE_COMMENT);
+	obj->commentobj_text = copystr(schem_parse_state.string);
+	t = rdschem_token();
+	if (t != ';')
+		goto syntaxerr;
+	parser_add_object(obj);
+	return(0);
+}
+
+static int
+parse_number()
+{
+	register int t;
+	char errbuf[256];
+
+	t = rdschem_token();
+	if (t != STRING)
+		rdschem_error("syntax error (number expected)");
+	if (!string_is_valid_decnum(schem_parse_state.string)) {
+		sprintf(errbuf, "\"%s\" is not a valid decimal number",
+			schem_parse_state.string);
+		rdschem_error(errbuf);
+	}
+	return(atoi(schem_parse_state.string));
+}