view ueda/utils/cutelements.c @ 80:df98a82b807e

ueda-mkbom refdes list output: refdes range detection implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 23 Feb 2017 18:54:47 +0000
parents e2130f1ef720
children
line wrap: on
line source

/*
 * This program cuts the "elements PCB" constructed by the
 * ueda-getfps | ueda-runm4 pipeline into one file per element.
 *
 * Alternatively, this program can also be used to extract all elements
 * out of any PCB layout file.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

char *inputname;
FILE *inf;
int lineno, in_element, parencount;
FILE *elemf;

char *
do_element_line(cp)
	register char *cp;
{
	char copybuf[1024];
	char opench, closech;
	char *fields[11], *pcbname;
	int nfields;
	register int c;
	char *err;

	if (in_element) {
		fprintf(stderr, "%s: line %d: nested Element\n", inputname,
			lineno);
		exit(1);
	}
	if (parencount) {
		fprintf(stderr,
			"%s: line %d: Element not at the top nesting level\n",
			inputname, lineno);
		exit(1);
	}

	while (isspace(*cp))
		cp++;
	opench = *cp++;
	switch (opench) {
	case '(':
		closech = ')';
		break;
	case '[':
		closech = ']';
		break;
	default:
		err = "no valid opening char";
inv:		fprintf(stderr, "%s: line %d: invalid Element line: %s\n",
			inputname, lineno, err);
		exit(1);
	}

	strcpy(copybuf, cp);
	cp = copybuf;

	for (nfields = 0; ; ) {
		while (isspace(*cp))
			cp++;
		if (!*cp) {
badeol:			err = "missing closing char";
			goto inv;
		}
		if (*cp == closech) {
			cp++;
			break;
		}
		if (nfields >= 11) {
			err = "too many fields";
			goto inv;
		}
		if (*cp == '\"') {
			cp++;
			for (fields[nfields++] = cp; c = *cp; cp++)
				if (c == '\"')
					break;
		} else {
			fields[nfields++] = cp;
			while ((c = *cp) && !isspace(c) && c != closech)
				cp++;
		}
		if (!c)
			goto badeol;
		*cp++ = '\0';
		if (c == closech)
			break;
	}

	switch (nfields) {
	case 7:
		pcbname = fields[1];
		break;
	case 8:
	case 9:
	case 11:
		pcbname = fields[2];
		break;
	default:
		err = "unrecognized format";
		goto inv;
	}
	open_element(pcbname);

	return(cp);
}

open_element(name)
	register char *name;
{
	elemf = fopen(name, "w");
	if (!elemf) {
		fprintf(stderr, "cannot create file: %s\n", name);
		exit(1);
	}
	in_element = 1;
}

main(argc, argv)
	char **argv;
{
	char linebuf[1024];
	register char *cp;

	if (argc > 2) {
		fprintf(stderr, "usage: %s [collection_file]\n", argv[0]);
		exit(1);
	}
	if (argc == 2) {
		inputname = argv[1];
		inf = fopen(inputname, "r");
		if (!inf) {
			perror(inputname);
			exit(1);
		}
	} else {
		inputname = "stdin";
		inf = stdin;
	}

	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
		for (cp = linebuf; isspace(*cp); cp++)
			;
		if (!strncmp(cp, "Element", 7) &&
		    (cp[7] == '(' || cp[7] == '[' || isspace(cp[7])))
			cp = do_element_line(cp + 7);
		if (in_element)
			fputs(linebuf, elemf);
		scan_parens(cp);
	}

	if (parencount || in_element) {
		fprintf(stderr, "%s: unclosed structure(s) at the end\n",
			inputname);
		exit(1);
	}
	exit(0);
}

scan_parens(line)
	char *line;
{
	register char *cp;
	register int c;

	for (cp = line; c = *cp; cp++) {
		if (c == '\'' && cp[1] && cp[2] == '\'') {
			cp += 2;
			continue;
		}
		if (c == '(' || c == '[')
			parencount++;
		else if (c == ')' || c == ']') {
			parencount--;
			if (parencount < 0) {
				fprintf(stderr,
					"%s: line %d: negative paren count\n",
					inputname, lineno);
				exit(1);
			}
			if ((parencount == 0) && in_element) {
				fclose(elemf);
				in_element = 0;
			}
		} else if (c == '#')
			return;
	}
}