FreeCalypso > hg > ueda-linux
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); +}