view ueda/uschem-utils/checknets.c @ 6:048d55d50ff3

ueda/README: describes this Linux port of ueda
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 20 Jul 2015 01:02:49 +0000
parents cd92449fdb51
children
line wrap: on
line source

/*
 * Pseudo-netlist functionality for uschem-check
 */

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

extern char *malloc();

extern struct schem *schem;

struct netname {
	char	*name;
	int	refcnt;
	struct	netexcl *excl;
	struct	netname *next;
};

struct netexcl {
	char	*filename;
	int	lineno;
	struct	netexcl *next;
};

#define	HASH_SIZE	1103

static struct netname *hashtab[HASH_SIZE];

static int
hash_netname(str)
	char *str;
{
	register u_long accum = 0;
	register char *cp;
	register int c, i;

	for (cp = str, i = 1; c = *cp; cp++, i++)
		accum += c * i;
	return(accum % HASH_SIZE);
}

static struct netname *
get_netname_struct(name)
	register char *name;
{
	register struct netname *n, **np;

	for (np = hashtab + hash_netname(name); n = *np; np = &n->next)
		if (!strcmp(n->name, name))
			return(n);
	n = (struct netname *) malloc(sizeof(struct netname));
	if (!n) {
		perror("malloc");
		exit(1);
	}
	bzero(n, sizeof(struct netname));
	n->name = name;
	*np = n;
	return(n);
}

record_netname_reference(netname, excl, filename, lineno)
	char *netname, *filename;
{
	register struct netname *n;
	register struct netexcl *e;

	n = get_netname_struct(netname);
	n->refcnt++;
	if (!excl)
		return;
	e = (struct netexcl *) malloc(sizeof(struct netexcl));
	if (!e) {
		perror("malloc");
		exit(1);
	}
	e->filename = filename;
	e->lineno = lineno;
	e->next = n->excl;
	n->excl = e;
}

static
get_exclusive_attr(obj, flagp)
	struct schemobj *obj;
	int *flagp;
{
	register struct decoration *decor;
	register char *val;

	for (decor = obj->obj_decorations; decor; decor = decor->decor_next)
		if (decor->decor_type == DECOR_TYPE_ATTR &&
		    !strcmp(decor->decorattr_name, "exclusive"))
			break;
	if (!decor)
		return(0);
	val = decor->decorattr_value;
	if (!strcmp(val, "yes") || !strcmp(val, "true") || !strcmp(val, "1")) {
		*flagp = 1;
		return(1);
	}
	if (!strcmp(val, "no") || !strcmp(val, "false") || !strcmp(val, "0")) {
		*flagp = 0;
		return(1);
	}
	return(0);
}

static
visual_netname_cues(grouphead)
	struct schemobj *grouphead;
{
	register struct schemobj *obj;
	register struct decoration *decor;

	for (obj = grouphead; ; obj = obj->obj_next) {
		if (obj->obj_type != OBJTYPE_GRAPHNET)
			break;
		if (obj->netobj_grouphead != grouphead)
			break;
		if (obj->netobj_forcenets)
			return(1);
		for (decor = obj->obj_decorations; decor;
		     decor = decor->decor_next)
			if (decor->decor_type == DECOR_TYPE_DISPLAYNETNAME)
				return(1);
	}
	return(0);
}

check_exclusive_nets()
{
	register struct schemobj *obj;
	int isexcl;

	for (obj = schem->obj_next; obj != (struct schemobj *)schem;
	     obj = obj->obj_next) {
		switch (obj->obj_type) {
		case OBJTYPE_NET:
			if (!obj->netobj_netname)
				continue;
			if (!get_exclusive_attr(obj, &isexcl))
				isexcl = 0;
			record_netname_reference(obj->netobj_netname, isexcl,
						 schem->orig_filename,
						 obj->obj_lineno);
			continue;
		case OBJTYPE_GRAPHNET:
			if (obj->netobj_grouphead != obj)
				continue;
			if (!obj->netobj_netname)
				continue;
			if (!get_exclusive_attr(obj, &isexcl)) {
				if (visual_netname_cues(obj))
					isexcl = 0;
				else
					isexcl = 1;
			}
			record_netname_reference(obj->netobj_netname, isexcl,
						 schem->orig_filename,
						 obj->obj_lineno);
			continue;
		}
	}
}

static
check_netname_for_excl(n)
	struct netname *n;
{
	register struct netexcl *e;

	for (e = n->excl; e; e = e->next)
		fprintf(stderr,
		"Exclusive net %s at %s line %d has other connections\n",
			n->name, e->filename, e->lineno);
}

report_exclusive_net_violations()
{
	register struct netname *n, **hb;
	register int i;

	for (hb = hashtab, i = 0; i < HASH_SIZE; hb++, i++)
		for (n = *hb; n; n = n->next)
			if (n->refcnt > 1)
				check_netname_for_excl(n);
}