view ueda/libueda/pinouts.c @ 83:88cdef7e6b1b

BOM tallying code factored out of ueda-mkbom
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 23 Feb 2017 19:27:14 +0000
parents c91e7a30fab3
children
line wrap: on
line source

/*
 * Pinout handling functions
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "mcl.h"
#include "pinouts.h"

extern char *copystr();

extern struct component components[];
extern int ncomponents;

extern char *get_comp_attr();
extern FILE *find_symlib_file();
extern char sought_libfile_fullpath[];

struct pinout_def *
read_pinout_file(filename)
	char *filename;
{
	FILE *f;
	char line[1024];
	int lineno;
	struct pinout_def *head, **tailp;
	register struct pinout_def *pin;
	register char *cp;
	char *pinname, *pinnumber;

	f = find_symlib_file(filename, NULL);
	if (!f) {
		fprintf(stderr, "Cannot find pinout file %s\n", filename);
		exit(1);
	}

	head = NULL;
	tailp = &head;
	for (lineno = 1; fgets(line, sizeof line, f); lineno++) {
		for (cp = line; isspace(*cp); cp++)
			;
		if (*cp == '\0' || *cp == '#')
			continue;
		if (!isgraph(*cp)) {
syntaxerr:		fprintf(stderr, "%s: line %d: syntax error\n",
				sought_libfile_fullpath, lineno);
			exit(1);
		}
		for (pinname = cp; isgraph(*cp); cp++)
			;
		if (!isspace(*cp))
			goto syntaxerr;
		*cp++ = '\0';
		while (isspace(*cp))
			cp++;
		if (!isgraph(*cp) || *cp == '#')
			goto syntaxerr;
		for (pinnumber = cp; isgraph(*cp); cp++)
			;
		if (isspace(*cp))
			*cp++ = '\0';
		else if (*cp)
			goto syntaxerr;
		pin = (struct pinout_def *) malloc(sizeof(struct pinout_def));
		if (!pin) {
			perror("malloc");
			exit(1);
		}
		pin->pinname = copystr(pinname);
		pin->pinnumber = copystr(pinnumber);
		pin->next = NULL;
		*tailp = pin;
		tailp = &pin->next;
	}
	fclose(f);

	if (!head) {
		fprintf(stderr, "%s: empty pinout file\n",
			sought_libfile_fullpath);
		exit(1);
	}
	return(head);
}

/*
 * We implement an optimisation: when we read all pinouts into core in
 * read_pinouts(), we cache them by name so that we don't have to re-read
 * and re-parse the same pinout files multiple times for multiple components.
 * The caching array is local to read_pinouts() and limited by MAX_PINOUTS.
 * If that limit is exceeded, caching will stop but we'll continue reading
 * pinouts, i.e., only the optimisation will be lost.
 */

#define	MAX_PINOUTS	128

read_pinouts()
{
	char *pinout_file_names[MAX_PINOUTS];
	struct pinout_def *parsed_pinouts[MAX_PINOUTS];
	int cached_pinouts, i;
	register struct component *comp;
	register char *pinout_file;
	register struct pinout_def *parsed_pinout;
	register int j;

	for (cached_pinouts = i = 0, comp = components; i < ncomponents;
	     comp++, i++) {
		pinout_file = get_comp_attr(comp, "pinout");
		if (!pinout_file)
			continue;
		for (j = 0; j < cached_pinouts; j++)
			if (!strcmp(pinout_file_names[j], pinout_file)) {
				comp->pinout = parsed_pinouts[j];
				continue;
			}
		parsed_pinout = read_pinout_file(pinout_file);
		comp->pinout = parsed_pinout;
		if (cached_pinouts < MAX_PINOUTS) {
			pinout_file_names[cached_pinouts] = pinout_file;
			parsed_pinouts[cached_pinouts] = parsed_pinout;
			cached_pinouts++;
		}
	}
	return(0);
}

char *
pinname_to_pinnumber(comp, pinname, slot)
	struct component *comp;
	char *pinname, *slot;
{
	char strbuf[512];
	register char *searchkey;
	register struct pinout_def *pin;

	pin = comp->pinout;
	if (!pin) {
		fprintf(stderr, "%s has no pinout\n", comp->name);
		return(NULL);
	}
	if (slot) {
		sprintf(strbuf, "%s:%s", pinname, slot);
		searchkey = strbuf;
	} else
		searchkey = pinname;
	for (; pin; pin = pin->next)
		if (!strcmp(pin->pinname, searchkey))
			return(pin->pinnumber);
	fprintf(stderr, "%s: no pin named %s\n", comp->name, searchkey);
	return(NULL);
}