view ueda/uschem-utils/rewrite.c @ 142:7bdce91da1a5

unet-excise utility added
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 19 Sep 2020 22:50:24 +0000
parents cd92449fdb51
children
line wrap: on
line source

/*
 * This program reads a uschem schematic into core and then writes it back out.
 * -g options converts NetLines to GraphNets and then preens/canonicalizes
 * all GraphNets, otherwise just exercises the parser & writer code in
 * libuschem.
 */

#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <strings.h>
#include "../libuschem/schemstruct.h"
#include "../libuschem/graphsym.h"

extern int optind;
extern char *optarg;
extern char *malloc();

extern struct schem *read_schem();
extern struct netpoint *parser_alloc_netpoint();
extern struct graphsym_pininst *find_pin_by_coord();

struct schem *schem;
char *outfile;
int replace_orig;
int gflag, Oflag;

char *
mk_temp_newfilename()
{
	int len;
	register char *str;

	len = strlen(schem->orig_filename) + 5;
	str = malloc(len);
	if (!str) {
		perror("malloc");
		exit(1);
	}
	sprintf(str, "%s.new", schem->orig_filename);
	return(str);
}

main(argc, argv)
	char **argv;
{
	register int c;
	int fd;
	FILE *outf;

	while ((c = getopt(argc, argv, "gI:o:O")) != EOF)
		switch (c) {
		case 'g':
			gflag++;
			break;
		case 'I':
			add_symfile_dir(optarg);
			break;
		case 'o':
			outfile = optarg;
			break;
		case 'O':
			Oflag++;
			break;
		default:
usage:			fprintf(stderr, "usage: %s [-o newfile] schemfile\n",
				argv[0]);
			exit(1);
		}
	if (!argv[optind])
		goto usage;

	schem = read_schem(argv[optind]);
	if (!outfile) {
		outfile = mk_temp_newfilename();
		replace_orig = 1;
	}

	if (gflag) {
		if (hash_component_instances(schem) < 0)
			exit(1);
		set_default_sympath();
		load_graphsyms(schem);
		if (instantiate_graphsym_pins(schem, 1) < 0 && !Oflag)
			exit(1);
		convert_netlines_to_graphnets();
		if (preen_graphnets(schem, 1, 1, 0, 1) < 0)
			exit(1);
	}

	c = O_WRONLY | O_CREAT;
	if (replace_orig)
		c |= O_EXCL;
	else
		c |= O_TRUNC;
	fd = open(outfile, c, 0644);
	if (fd < 0) {
		perror(outfile);
		exit(1);
	}
	outf = fdopen(fd, "w");
	if (!outf) {
		perror("fdopen");
		exit(1);
	}
	write_schem(schem, outf);
	fclose(outf);
	if (replace_orig)
		rename(outfile, schem->orig_filename);
	exit(0);
}

convert_netlines_to_graphnets()
{
	register struct schemobj *obj;

	for (obj = schem->obj_next; obj != (struct schemobj *)schem;
	     obj = obj->obj_next)
		if (obj->obj_type == OBJTYPE_NETLINE)
			convert_netline(obj);
}

convert_netline(obj)
	register struct schemobj *obj;
{
	register struct netpoint *end1, *end2;

	end1 = parser_alloc_netpoint(NETPT_TYPE_POINT);
	end1->netpt_x = obj->lineobj_x1;
	end1->netpt_y = obj->lineobj_y1;
	end1->netpt_coord_valid = 1;
	pinify_netpoint(end1);
	end2 = parser_alloc_netpoint(NETPT_TYPE_POINT);
	end2->netpt_x = obj->lineobj_x2;
	end2->netpt_y = obj->lineobj_y2;
	end2->netpt_coord_valid = 1;
	pinify_netpoint(end2);
	end1->netpt_next = end2;
	obj->obj_type = OBJTYPE_GRAPHNET;
	obj->netobj_points = end1;
	obj->netobj_netname = NULL;
	if (!extend_new_graphnet(obj)) {
		end1->netpt_next = NULL;
		end2->netpt_next = end1;
		obj->netobj_points = end2;
		extend_new_graphnet(obj);
	}
	convert_netline_decors(obj);
}

pinify_netpoint(netpt)
	register struct netpoint *netpt;
{
	register struct graphsym_pininst *pin;

	pin = find_pin_by_coord(schem, netpt->netpt_x, netpt->netpt_y);
	if (!pin)
		return;
	switch (pin->compinst->obj_type) {
	case OBJTYPE_COMPINST:
		netpt->netpt_type = NETPT_TYPE_PIN;
		return;
	case OBJTYPE_GRAPHSYM:
		netpt->netpt_type = NETPT_TYPE_PSEUDO;
		return;
	}
}

convert_netline_decors(obj)
	struct schemobj *obj;
{
	register struct decoration *decor;
	struct decoration **np;

	for (np = &obj->obj_decorations; decor = *np; ) {
		switch (decor->decor_type) {
		case DECOR_TYPE_ATTR:
			if (strcmp(decor->decorattr_name, "netname"))
				break;
			if (obj->netobj_netname &&
			  strcmp(obj->netobj_netname, decor->decorattr_value)) {
				fprintf(stderr,
					"%s: line %d: net name conflict\n",
					schem->orig_filename,
					decor->decor_lineno);
				exit(1);
			}
			obj->netobj_netname = decor->decorattr_value;
			/* drop the decoration */
			*np = decor->decor_next;
			continue;
		case DECOR_TYPE_DISPLAYATTR:
			if (!strcmp(decor->decordisp_attr, "netname"))
				decor->decor_type = DECOR_TYPE_DISPLAYNETNAME;
			break;
		}
		np = &decor->decor_next;
	}
}

struct netpoint *
convert_netline_to_netpt(gn, nlobj, whichend)
	struct schemobj *gn;
	register struct schemobj *nlobj;
	int whichend;
{
	register struct netpoint *netpt;

	netpt = parser_alloc_netpoint(NETPT_TYPE_POINT);
	switch (whichend) {
	case 1:
		netpt->netpt_x = nlobj->lineobj_x1;
		netpt->netpt_y = nlobj->lineobj_y1;
		break;
	case 2:
		netpt->netpt_x = nlobj->lineobj_x2;
		netpt->netpt_y = nlobj->lineobj_y2;
		break;
	}
	netpt->netpt_coord_valid = 1;
	pinify_netpoint(netpt);
	netconvert_append_decors(gn, nlobj);
	schemobj_unlink(nlobj);
	return(netpt);
}

extend_new_graphnet(gn)
	struct schemobj *gn;
{
	register struct schemobj *obj;
	register struct netpoint *tail, *new;
	int success = 0;

	tail = gn->netobj_points->netpt_next;
loop:	for (obj = gn->obj_next; obj != (struct schemobj *)schem;
	     obj = obj->obj_next) {
		if (obj->obj_type != OBJTYPE_NETLINE)
			continue;
		if (obj->lineobj_x1 == tail->netpt_x &&
		    obj->lineobj_y1 == tail->netpt_y) {
			new = convert_netline_to_netpt(gn, obj, 2);
			tail->netpt_next = new;
			tail = new;
			success = 1;
			goto loop;
		}
		if (obj->lineobj_x2 == tail->netpt_x &&
		    obj->lineobj_y2 == tail->netpt_y) {
			new = convert_netline_to_netpt(gn, obj, 1);
			tail->netpt_next = new;
			tail = new;
			success = 1;
			goto loop;
		}
	}
	return(success);
}

netconvert_append_decors(gnobj, nlobj)
	struct schemobj *gnobj, *nlobj;
{
	register struct decoration *decor;
	register struct decoration **np;

	for (np = &gnobj->obj_decorations; decor = *np; np = &decor->decor_next)
		;
	*np = nlobj->obj_decorations;
}