diff ueda/libueda/readmcl.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 c91e7a30fab3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ueda/libueda/readmcl.c	Mon Jul 20 00:24:37 2015 +0000
@@ -0,0 +1,260 @@
+/*
+ * This is the MCL parser for the uEDA suite.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <strings.h>
+#include "mcl.h"
+
+extern char *copystr();
+
+#define	MAX_COMPS	1024
+#define	MAX_PARTDEFS	128
+#define	MAX_ATTRS	2048
+#define	MAX_REFDES_ON_LINE	16
+
+char *MCLfile = "MCL";
+
+/* the following vars capture the distilled output of the parser */
+struct component components[MAX_COMPS], partdefs[MAX_PARTDEFS];
+int ncomponents, npartdefs;
+static struct attrib attrs[MAX_ATTRS];
+static int nattrs;
+
+/* the following static vars are used only in the reading & parsing process */
+static FILE *mclf;
+static char line[1024];		/* size arbitrary, sizeof used in the code */
+static int lineno;
+
+static struct component *curcomp;
+static char *curcomp_refdes[MAX_REFDES_ON_LINE];
+static int curcomp_nrefdes;
+
+read_MCL()
+{
+	register char *cp, *name, *value;
+
+	mclf = fopen(MCLfile, "r");
+	if (!mclf) {
+		perror(MCLfile);
+		exit(1);
+	}
+
+	for (lineno = 0, curcomp = NULL; getline(); ) {
+		/* ignore blank lines and comments */
+		if (line[0] == '\0' || line[0] == '#')
+			continue;
+		if (!strncmp(line, "part", 4) && isspace(line[4])) {
+			finish_component();
+			setup_partdef(line + 5);
+		} else if (!isspace(line[0])) {	/* refdes */
+			finish_component();
+			parse_refdes_list();
+			if (ncomponents >= MAX_COMPS) {
+				fprintf(stderr,
+					"%s: line %d: too many components\n",
+					MCLfile, lineno);
+				exit(1);
+			}
+			curcomp = components + ncomponents;
+			curcomp->name = curcomp_refdes[0];
+			curcomp->attrs = attrs + nattrs;
+			curcomp->nattrs = 0;
+			ncomponents++;
+		} else {			/* attribute */
+			for (cp = line; isspace(*cp); cp++)
+				;
+			name = cp;
+			cp = index(cp, '=');
+			if (!cp) {
+invattr:			fprintf(stderr,
+				    "%s: line %d: invalid attribute line\n",
+					MCLfile, lineno);
+				exit(1);
+			}
+			*cp = '\0';
+			value = cp + 1;
+			if (name[0] == '\0')
+				goto invattr;
+			if (!curcomp) {
+				fprintf(stderr,
+			"%s: line %d: attribute listed without a component\n",
+					MCLfile, lineno);
+				exit(1);
+			}
+			if (value[0] == '\0') {
+				fprintf(stderr,
+				"%s: line %d: attribute must have a value\n",
+					MCLfile, lineno);
+				exit(1);
+			}
+			if (nattrs >= MAX_ATTRS) {
+				fprintf(stderr,
+					"%s: line %d: too many attributes\n",
+					MCLfile, lineno);
+				exit(1);
+			}
+			attrs[nattrs].name = copystr(name);
+			attrs[nattrs].value = copystr(value);
+			nattrs++;
+			curcomp->nattrs++;
+			if (!strcmp(name, "part"))
+				handle_part_ref(value);
+		}
+	}
+	fclose(mclf);
+	finish_component();
+}
+
+static
+setup_partdef(np)
+	register char *np;
+{
+	register char *cp;
+
+	while (isspace(*np))
+		np++;
+	cp = index(np, ':');
+	if (!cp || cp == np || cp[1]) {
+		fprintf(stderr, "%s: line %d: invalid part definition\n",
+			MCLfile, lineno);
+		exit(1);
+	}
+	*cp = '\0';
+	if (npartdefs >= MAX_PARTDEFS) {
+		fprintf(stderr, "%s: line %d: too many part definitions\n",
+			MCLfile, lineno);
+		exit(1);
+	}
+	curcomp = partdefs + npartdefs;
+	curcomp->name = copystr(np);
+	curcomp->attrs = attrs + nattrs;
+	curcomp->nattrs = 0;
+	npartdefs++;
+	curcomp_nrefdes = 0;
+}
+
+static
+parse_refdes_list()
+{
+	int i;
+	register char *cp, *np;
+	register int c;
+
+	for (cp = line, i = 0; ; ) {
+		if (!isupper(*cp)) {
+inv:			fprintf(stderr, "%s: line %d: invalid refdes line\n",
+				MCLfile, lineno);
+			exit(1);
+		}
+		for (np = cp; isalnum(*cp); cp++)
+			;
+		c = *cp;
+		if (c != ':' && c != ',')
+			goto inv;
+		*cp++ = '\0';
+		curcomp_refdes[i++] = copystr(np);
+		if (c == ':')
+			break;
+	}
+	curcomp_nrefdes = i;
+	if (*cp)
+		goto inv;
+}
+
+static
+finish_component()
+{
+	extern char *get_comp_attr();
+
+	if (curcomp_nrefdes == 0)
+		return;			/* nothing to do for part defs */
+	if (!curcomp->partdef &&
+		(get_comp_attr(curcomp, "manufacturer") &&
+		 get_comp_attr(curcomp, "manufacturer_part_number") ||
+		 get_comp_attr(curcomp, "bom_part_title")))
+			curcomp->partdef = curcomp;	/* self-defines part */
+	if (curcomp_nrefdes > 1)
+		clone_component();
+}
+
+static
+clone_component()
+{
+	register int i;
+	register struct component *newcomp;
+
+	for (i = 1; i < curcomp_nrefdes; i++) {
+		if (ncomponents >= MAX_COMPS) {
+			fprintf(stderr, "%s: %s: too many components\n",
+				MCLfile, curcomp_refdes[i]);
+			exit(1);
+		}
+		newcomp = components + ncomponents;
+		bcopy(curcomp, newcomp, sizeof(struct component));
+		newcomp->name = curcomp_refdes[i];
+		ncomponents++;
+	}
+}
+
+static
+handle_part_ref(partname)
+	char *partname;
+{
+	register struct component *part;
+	register int i;
+
+	if (curcomp_nrefdes == 0) {
+	    fprintf(stderr,
+	    "%s: line %d: can't use a part reference in a part definition!\n",
+			MCLfile, lineno);
+	    exit(1);
+	}
+	if (!strcmp(partname, "none")) {
+		curcomp->partdef = NULL;
+		return;
+	}
+	if (!strcmp(partname, "yes")) {
+		curcomp->partdef = curcomp;	/* self-defines the part */
+		return;
+	}
+	for (part = partdefs, i = 0; i < npartdefs; part++, i++)
+		if (!strcmp(part->name, partname)) {
+gotit:			curcomp->partdef = part;
+			return;
+		}
+	/* can also refer to a previous component that self-defines a part */
+	for (part = components, i = 0; i < ncomponents-1; part++, i++)
+		if (!strcmp(part->name, partname)) {
+			if (part->partdef == part)
+				goto gotit;
+			else {
+				fprintf(stderr,
+"%s: line %d: can't use %s as a part because it doesn't define a part\n",
+					MCLfile, lineno, partname);
+				exit(1);
+			}
+		}
+	fprintf(stderr, "%s: line %d: part %s not defined\n", MCLfile, lineno,
+			partname);
+	exit(1);
+}
+
+static
+getline()
+{
+	register char *cp;
+
+	if (fgets(line, sizeof line, mclf) == NULL)
+		return(0);
+	lineno++;
+	/* strip trailing comments and whitespace */
+	cp = index(line, '#');
+	if (!cp)
+		cp = index(line, '\0');
+	while (cp > line && isspace(cp[-1]))
+		cp--;
+	*cp = '\0';
+	return(1);
+}