view ueda/libunet/unetrd.c @ 28:33e4c4cdf493

libunet: reading of ATTR lines implemented
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sat, 08 Aug 2015 21:17:57 +0000
parents dda8e455c863
children
line wrap: on
line source

/*
 * This module provides library functions for reading and parsing
 * netlist files in our unet format.
 */

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

open_unet_input_file(filename, state)
	char *filename;
	struct unetrd_state *state;
{
	state->filename = filename;
	state->stream = fopen(filename, "r");
	if (!state->stream) {
		perror(filename);
		exit(1);
	}
	state->lineno = 0;
}

static void
handle_name_only(state, out, rest)
	struct unetrd_state *state;
	struct unetrd_out *out;
	char *rest;
{
	char *cp;

	for (cp = rest; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#') {
		fprintf(stderr, "%s line %d: a name is expected after %s\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
	out->objname = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp && *cp != '#') {
		fprintf(stderr,
			"%s line %d: unexpected extra fields on %s line\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
}

static void
handle_component_opening(state, out, rest)
	struct unetrd_state *state;
	struct unetrd_out *out;
	char *rest;
{
	char *cp;

	for (cp = rest; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#') {
		fprintf(stderr, "%s line %d: a name is expected after %s\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
	out->objname = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '{') {
		fprintf(stderr,
			"%s line %d: expected '{' at the end of %s line\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
}

static void
handle_pin_line(state, out, rest)
	struct unetrd_state *state;
	struct unetrd_out *out;
	char *rest;
{
	char *cp = rest, *fields[3];
	int i;

	for (i = 0; i < 3; i++) {
		while (isspace(*cp))
			cp++;
		if (*cp == '\0' || *cp == '#') {
error:			fprintf(stderr,
				"%s line %d: invalid syntax on %s line\n",
				state->filename, state->lineno, out->keyword);
			exit(1);
		}
		fields[i] = cp;
		while (*cp && !isspace(*cp))
			cp++;
		if (*cp)
			*cp++ = '\0';
	}
	out->objname = fields[0];
	if (strcmp(fields[1], "="))
		goto error;
	if (!strcmp(fields[2], "NET")) {
		while (isspace(*cp))
			cp++;
		if (*cp == '\0' || *cp == '#')
			goto error;
		out->connect_to_net = cp;
		while (*cp && !isspace(*cp))
			cp++;
		if (*cp)
			*cp++ = '\0';
	} else if (!strcmp(fields[2], "NC")) {
		out->connect_to_net = 0;
		while (isspace(*cp))
			cp++;
		if (*cp++ != '(')
			goto error;
		out->nc_comment = cp;
		while (*cp && *cp != ')')
			cp++;
		if (*cp != ')')
			goto error;
		*cp++ = '\0';
	} else
		goto error;
	while (isspace(*cp))
		cp++;
	if (*cp && *cp != '#') {
		fprintf(stderr,
			"%s line %d: unexpected extra fields on %s line\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
}

static void
handle_attr(state, out, rest)
	struct unetrd_state *state;
	struct unetrd_out *out;
	char *rest;
{
	char *cp;

	for (cp = rest; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#') {
error:		fprintf(stderr, "%s line %d: invalid syntax on ATTR line\n",
			state->filename, state->lineno);
		exit(1);
	}
	out->objname = cp;
	cp = index(cp, '=');
	if (!cp)
		goto error;
	*cp++ = '\0';
	out->attr_value = cp;
}

static struct objmap {
	char	*keyword;
	int	typecode;
	void	(*handler)();
} objmap[] = {
	{"}",		UNETOBJ_CLOSINGBRACE,	0},
	{"NET",		UNETOBJ_NET,		handle_name_only},
	{"COMPONENT",	UNETOBJ_COMPONENT,	handle_component_opening},
	{"STARPOINT",	UNETOBJ_STARPOINT,	handle_component_opening},
	{"PRIMITIVE",	UNETOBJ_PRIMITIVE,	handle_name_only},
	{"ALTNAME",	UNETOBJ_ALTNAME,	handle_name_only},
	{"PIN",		UNETOBJ_PIN,		handle_pin_line},
	{"PINMAP",	UNETOBJ_PINMAP,		handle_pin_line},
	{"ATTR",	UNETOBJ_ATTR,		handle_attr},
	{0, 0, 0}
};

read_unet_line(state, out)
	struct unetrd_state *state;
	struct unetrd_out *out;
{
	static char linebuf[256];
	char *cp;
	struct objmap *tp;

	/* read lines until we get a non-empty, non-comment line or EOF */
	for (;;) {
		if (!fgets(linebuf, sizeof linebuf, state->stream)) {
			fclose(state->stream);
			return(0);
		}
		state->lineno++;
		cp = index(linebuf, '\n');
		if (!cp) {
			fprintf(stderr,
			"error: %s line %d is too long or unterminated\n",
				state->filename, state->lineno);
			exit(1);
		}
		*cp = '\0';
		for (cp = linebuf; isspace(*cp); cp++)
			;
		if (*cp && *cp != '#')
			break;
	}
	out->keyword = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (*cp)
		*cp++ = '\0';
	for (tp = objmap; tp->keyword; tp++)
		if (!strcmp(tp->keyword, out->keyword))
			break;
	if (!tp->keyword) {
		fprintf(stderr, "%s line %d: object type \"%s\" unknown\n",
			state->filename, state->lineno, out->keyword);
		exit(1);
	}
	out->typecode = tp->typecode;
	if (tp->handler)
		tp->handler(state, out, cp);
	return(1);
}