view ueda/unet-utils/unet2pads.c @ 34:bc465afed423

unet2pads: exit with an error if the pads_parttype is missing on any component
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sat, 08 Aug 2015 23:23:55 +0000
parents 2af4a85daf89
children a0d227fc9569
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "../libunet/unetrd.h"
#include "../libunet/nethash.h"

extern struct net *enter_net_object();
extern struct net *find_net_by_name();
extern struct net *net_list_head;

static char *input_filename, *output_filename;
static struct unetrd_state rdstate;
static struct unetrd_out rdout;
static FILE *tempFILE, *outFILE;
static int no_parttype_errors;

struct netextra {
	struct	netmember *head;
	struct	netmember **tailp;
};

struct netmember {
	char	*name;
	struct	netmember *next;
};

static FILE *
tempfile()
{
	char template[16];
	register int fd;
	register FILE *f;

	strcpy(template, "/tmp/uedaXXXXXX");
	fd = mkstemp(template);
	if (fd < 0) {
		perror("mkstemp");
		exit(1);
	}
	unlink(template);
	f = fdopen(fd, "r+w");
	if (!f) {
		perror("fdopen");
		exit(1);
	}
	return(f);
}

static void
dump_tempfile()
{
	register FILE *inf = tempFILE;
	register FILE *outf = outFILE;
	register int c;

	rewind(inf);
	while ((c = getc(inf)) != EOF)
		putc(c, outf);
	fclose(inf);
}

static void
process_pin_connect(compname)
	char *compname;
{
	register struct net *n;
	register struct netextra *nx;
	register struct netmember *nm;

	n = find_net_by_name(rdout.connect_to_net);
	nx = (struct netextra *)(n + 1);
	nm = (struct netmember *) malloc(sizeof(struct netmember) +
					 strlen(compname) +
					 strlen(rdout.objname) + 2);
	if (!nm) {
		perror("malloc");
		exit(1);
	}
	nm->name = (char *)(nm + 1);
	sprintf(nm->name, "%s.%s", compname, rdout.objname);
	nm->next = 0;
	*nx->tailp = nm;
	nx->tailp = &nm->next;
}

static void
process_component()
{
	char compname[64];
	int parttype_seen = 0;

	strcpy(compname, rdout.objname);
	for (;;) {
		if (!read_unet_line(&rdstate, &rdout)) {
			fprintf(stderr, "%s error: EOF in COMPONENT block\n",
				input_filename);
			exit(1);
		}
		if (rdout.typecode == UNETOBJ_CLOSINGBRACE)
			break;
		switch(rdout.typecode) {
		case UNETOBJ_PRIMITIVE:
		case UNETOBJ_ALTNAME:
			continue;
		case UNETOBJ_ATTR:
			if (strcmp(rdout.objname, "pads_parttype"))
				continue;
			if (parttype_seen) {
				fprintf(stderr,
		"%s lind %d: duplicate ATTR pads_parttype for COMPONENT %s\n",
					input_filename, rdstate.lineno,
					compname);
				exit(1);
			}
			fprintf(tempFILE, "%s %s\n", compname,
				rdout.attr_value);
			parttype_seen = 1;
			continue;
		case UNETOBJ_PIN:
			if (rdout.connect_to_net)
				process_pin_connect(compname);
			continue;
		case UNETOBJ_PINMAP:
			fprintf(stderr,
		"%s line %d: PINMAP objects not expected in unet2pads input\n",
				input_filename, rdstate.lineno);
			exit(1);
		default:
			fprintf(stderr,
		"%s line %d: object type %s unexpected in COMPONENT block\n",
				input_filename, rdstate.lineno, rdout.keyword);
			exit(1);
		}
	}
	if (!parttype_seen) {
		fprintf(stderr,
			"error: component %s has no pads_parttype set\n",
			compname);
		no_parttype_errors++;
	}
}

static void
process_input_unet()
{
	struct net *n;
	struct netextra *nx;

	open_unet_input_file(input_filename, &rdstate);
	while (read_unet_line(&rdstate, &rdout)) {
		switch(rdout.typecode) {
		case UNETOBJ_CLOSINGBRACE:
			fprintf(stderr,
		"%s line %d: unexpected '}' outside of component block\n",
				input_filename, rdstate.lineno);
			exit(1);
		case UNETOBJ_NET:
			n = enter_net_object(rdout.objname,
						sizeof(struct netextra));
			nx = (struct netextra *)(n + 1);
			nx->head = 0;
			nx->tailp = &nx->head;
			continue;
		case UNETOBJ_COMPONENT:
			if (!tempFILE)
				tempFILE = tempfile();
			process_component();
			continue;
		case UNETOBJ_STARPOINT:
			fprintf(stderr,
"error: STARPOINT objects not expected in unet2pads input (%s line %d)\n",
				input_filename, rdstate.lineno);
			exit(1);
		default:
			fprintf(stderr,
				"%s line %d: unexpected object type %s\n",
				input_filename, rdstate.lineno, rdout.keyword);
			exit(1);
		}
	}
	if (!tempFILE) {
		fprintf(stderr, "error: no components found in %s input!\n",
			input_filename);
		exit(1);
	}
}

static void
output_nets()
{
	struct net *n;
	struct netextra *nx;
	register struct netmember *nm;
	int linelen;

	fputs("*NET*\n", outFILE);
	for (n = net_list_head; n; n = n->nextinlist) {
		nx = (struct netextra *)(n + 1);
		fprintf(outFILE, "*SIG* %s\n", n->name);
		linelen = 0;
		for (nm = nx->head; nm; nm = nm->next) {
			if (linelen && linelen + strlen(nm->name) + 1 > 79) {
				putc('\n', outFILE);
				linelen = 0;
			}
			if (linelen) {
				putc(' ', outFILE);
				linelen++;
			}
			fputs(nm->name, outFILE);
			linelen += strlen(nm->name);
		}
		if (linelen)
			putc('\n', outFILE);
	}
}

static void
generate_output()
{
	if (output_filename) {
		outFILE = fopen(output_filename, "w");
		if (!outFILE) {
			perror(output_filename);
			exit(1);
		}
	} else
		outFILE = stdout;
	fputs("!PADS-POWERPCB-V3.0-MILS! DESIGN DATABASE ASCII FILE 2.0\n\n",
		outFILE);
	fputs("*PART*       ITEMS\n", outFILE);
	dump_tempfile();
	putc('\n', outFILE);
	output_nets();
	fputs("\n*END*     OF ASCII OUTPUT FILE\n", outFILE);
	if (outFILE != stdout)
		fclose(outFILE);
}

main(argc, argv)
	char **argv;
{
	if (argc < 2 || argc > 3) {
		fprintf(stderr, "usage: %s input.unet [output.unet]\n",
			argv[0]);
		exit(1);
	}
	input_filename = argv[1];
	output_filename = argv[2];
	process_input_unet();
	if (no_parttype_errors)
		exit(1);
	generate_output();
	exit(0);
}