diff ueda/libueda/xga.c @ 0:cd92449fdb51

initial import of ueda and ifctf-part-lib from ifctfvax CVS
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 20 Jul 2015 00:24:37 +0000
parents
children c91e7a30fab3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ueda/libueda/xga.c	Mon Jul 20 00:24:37 2015 +0000
@@ -0,0 +1,302 @@
+/*
+ * This module contains the function that implements the reading of PGA/BGA
+ * package description files and some related functions.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <strings.h>
+#include "xga.h"
+
+extern char *malloc();
+extern char *copystr();
+
+extern FILE *find_symlib_file();
+extern char sought_libfile_fullpath[];
+
+parse_xga_pinnumber(desc, pinstr, parsed)
+	register struct grid_pkg_desc *desc;
+	register char *pinstr;
+	struct xga_parsed_pinnum *parsed;
+{
+	char *rowfind;
+	int col;
+
+	if (!isupper(pinstr[0]) || !isdigit(pinstr[1]))
+		return(-1);
+	rowfind = index(desc->row_letters, pinstr[0]);
+	if (!rowfind)
+		return(-1);
+	if (!string_is_valid_decnum(pinstr + 1))
+		return(-1);
+	col = atoi(pinstr + 1);
+	if (col < 1 || col > desc->ncolumns)
+		return(-1);
+	parsed->row_0based = rowfind - desc->row_letters;
+	parsed->col_0based = col - 1;
+	return(0);
+}
+
+static void
+check_complete(desc)
+	register struct grid_pkg_desc *desc;
+{
+	register char *array;
+
+	if (desc->holes_array)			/* already allocated */
+		return;
+	if (!desc->nrows || !desc->ncolumns)	/* not specified yet */
+		return;
+	/* allocate it! */
+	array = malloc(desc->nrows * desc->ncolumns);
+	if (!array) {
+		perror("malloc");
+		exit(1);
+	}
+	desc->holes_array = array;
+	bzero(array, desc->nrows * desc->ncolumns);
+}
+
+static void
+validate_rows_arg(arg, filename, lineno)
+	char *arg, *filename;
+	int lineno;
+{
+	register char *cp;
+	register int c, prev;
+
+	prev = 0;
+	for (cp = arg; c = *cp++; prev = c) {
+		if (c < 'A' || c > 'Z') {
+			fprintf(stderr,
+	"%s line %d: rows setting: only uppercase letters are allowed\n",
+				filename, lineno);
+			exit(1);
+		}
+		if (c <= prev) {
+			fprintf(stderr,
+		"%s line %d: rows setting: letters must be increasing\n",
+				filename, lineno);
+			exit(1);
+		}
+	}
+}
+
+static void
+handle_rows_line(desc, arg, filename, lineno)
+	struct grid_pkg_desc *desc;
+	char *arg, *filename;
+	int lineno;
+{
+	register char *cp, *np;
+
+	if (desc->row_letters) {
+		fprintf(stderr, "%s line %d: duplicate rows setting\n",
+			filename, lineno);
+		exit(1);
+	}
+	for (cp = arg; isspace(*cp); cp++)
+		;
+	if (*cp == '\0' || *cp == '#') {
+		fprintf(stderr, "%s line %d: rows setting has no argument\n",
+			filename, lineno);
+		exit(1);
+	}
+	for (np = cp; *cp && !isspace(*cp); cp++)
+		;
+	if (*cp)
+		*cp++ = '\0';
+	validate_rows_arg(np, filename, lineno);
+	desc->row_letters = copystr(np);
+	desc->nrows = strlen(np);
+	check_complete(desc);
+}
+
+static void
+handle_columns_line(desc, arg, filename, lineno)
+	struct grid_pkg_desc *desc;
+	char *arg, *filename;
+	int lineno;
+{
+	register char *cp, *np;
+
+	if (desc->ncolumns) {
+		fprintf(stderr, "%s line %d: duplicate columns setting\n",
+			filename, lineno);
+		exit(1);
+	}
+	for (cp = arg; isspace(*cp); cp++)
+		;
+	if (*cp == '\0' || *cp == '#') {
+		fprintf(stderr, "%s line %d: columns setting has no argument\n",
+			filename, lineno);
+		exit(1);
+	}
+	for (np = cp; *cp && !isspace(*cp); cp++)
+		;
+	if (*cp)
+		*cp++ = '\0';
+	if (!string_is_valid_decnum(np)) {
+		fprintf(stderr,
+			"%s line %d: columns setting must be a number\n",
+			filename, lineno);
+		exit(1);
+	}
+	desc->ncolumns = atoi(np);
+	if (desc->ncolumns < 1) {
+		fprintf(stderr, "%s line %d: columns number must be positive\n",
+			filename, lineno);
+		exit(1);
+	}
+	check_complete(desc);
+}
+
+static void
+handle_hole_spec(desc, arg, filename, lineno)
+	register struct grid_pkg_desc *desc;
+	char *arg, *filename;
+	int lineno;
+{
+	char *arg2;
+	struct xga_parsed_pinnum start_parsed, end_parsed;
+	register int r, c;
+
+	arg2 = index(arg, '-');
+	if (arg2)
+		*arg2++ = '\0';
+	else
+		arg2 = arg;
+	if (parse_xga_pinnumber(desc, arg, &start_parsed) < 0) {
+		fprintf(stderr,
+	"%s line %d: \"%s\" is not a valid pin position for this package\n",
+			filename, lineno, arg);
+		exit(1);
+	}
+	if (parse_xga_pinnumber(desc, arg2, &end_parsed) < 0) {
+		fprintf(stderr,
+	"%s line %d: \"%s\" is not a valid pin position for this package\n",
+			filename, lineno, arg2);
+		exit(1);
+	}
+	if (start_parsed.row_0based == end_parsed.row_0based) {
+		r = start_parsed.row_0based;
+		if (start_parsed.col_0based > end_parsed.col_0based) {
+error_reversed:		fprintf(stderr,
+			"%s line %d: hole ranges need to be increasing\n",
+				filename, lineno);
+			exit(1);
+		}
+		for (c = start_parsed.col_0based; c <= end_parsed.col_0based;
+		     c++)
+			desc->holes_array[r * desc->ncolumns + c] = 1;
+	} else if (start_parsed.col_0based == end_parsed.col_0based) {
+		c = start_parsed.col_0based;
+		if (start_parsed.row_0based > end_parsed.row_0based)
+			goto error_reversed;
+		for (r = start_parsed.row_0based; r <= end_parsed.row_0based;
+		     r++)
+			desc->holes_array[r * desc->ncolumns + c] = 1;
+	} else {
+		fprintf(stderr,
+		"%s line %d: hole ranges must be horizontal or vertical\n",
+			filename, lineno);
+		exit(1);
+	}
+}
+
+static void
+handle_hole_line(desc, arg, filename, lineno)
+	struct grid_pkg_desc *desc;
+	char *arg, *filename;
+	int lineno;
+{
+	register char *cp, *np;
+
+	if (!desc->holes_array) {
+		fprintf(stderr,
+		"%s line %d: rows and columns must be defined before holes\n",
+			filename, lineno);
+		exit(1);
+	}
+	for (cp = arg; ; ) {
+		while (isspace(*cp))
+			cp++;
+		if (*cp == '\0' || *cp == '#')
+			break;
+		for (np = cp; *cp && !isspace(*cp); cp++)
+			;
+		if (*cp)
+			*cp++ = '\0';
+		handle_hole_spec(desc, np, filename, lineno);
+	}
+}
+
+struct grid_pkg_desc *
+read_grid_pkg_file(filename)
+	char *filename;
+{
+	FILE *f;
+	char linebuf[1024];
+	int lineno;
+	register char *cp, *np;
+	struct grid_pkg_desc *desc;
+
+	f = find_symlib_file(filename, NULL);
+	if (!f) {
+		fprintf(stderr, "Cannot find xGA definition file %s\n",
+			filename);
+		exit(1);
+	}
+	desc = (struct grid_pkg_desc *) malloc(sizeof(struct grid_pkg_desc));
+	if (!desc) {
+		perror("malloc");
+		exit(1);
+	}
+	bzero(desc, sizeof(struct grid_pkg_desc));
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) {
+		for (cp = linebuf; isspace(*cp); cp++)
+			;
+		if (*cp == '\0' || *cp == '#')
+			continue;
+		for (np = cp; *cp && !isspace(*cp); cp++)
+			;
+		if (*cp)
+			*cp++ = '\0';
+		if (!strcmp(np, "rows"))
+			handle_rows_line(desc, cp, sought_libfile_fullpath,
+					 lineno);
+		else if (!strcmp(np, "columns"))
+			handle_columns_line(desc, cp, sought_libfile_fullpath,
+						lineno);
+		else if (!strcmp(np, "hole"))
+			handle_hole_line(desc, cp, sought_libfile_fullpath,
+					 lineno);
+		else {
+			fprintf(stderr,
+				"%s line %d: setting \"%s\" not understood\n",
+				sought_libfile_fullpath, lineno, np);
+			exit(1);
+		}
+	}
+	fclose(f);
+
+	if (!desc->nrows) {
+		fprintf(stderr, "error: %s contains no rows setting\n",
+			sought_libfile_fullpath);
+		exit(1);
+	}
+	if (!desc->ncolumns) {
+		fprintf(stderr, "error: %s contains no columns setting\n",
+			sought_libfile_fullpath);
+		exit(1);
+	}
+	return(desc);
+}
+
+free_grid_pkg_desc(desc)
+	struct grid_pkg_desc *desc;
+{
+	free(desc->row_letters);
+	free(desc->holes_array);
+	free(desc);
+}