home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
tech
/
pcbsrcs2
/
io4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-10
|
56KB
|
1,528 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include "cell.h"
#include "custom.h"
extern int Nrows, Ncols; /* board dimensions */
extern int InitBoardDone; /* sanity check */
extern int SortConnects; /* 0 = don't sort, 1 = sort */
extern int PartsList; /* 0 = no listing, 1 = a listing */
extern FILE *partsfile; /* file pointer for the above switch */
/* memory usage */
extern unsigned long Ltotal; /* for board */
extern unsigned long Itotal; /* for dist */
extern unsigned long Ctotal; /* for dir */
/*
** the following types of input lines are legal (spaces and tabs can separate
** tokens, and case is not significant):
**
** 1) a blank line (ignored)
** 2) ';' followed by anything (ignored)
** use semicolon to insert comments.
** 3) DIMENSION (row,column)
** this defines the number of rows and columns on the board, and must be
** given before any of the lines below. note that the user sees the board
** coordinate space as being 1-based, but internally it is 0-based.
** 4) HOLE (row,column)
** this defines a hole location.
** 5) CONNECT thing AND thing
** this declares that two holes are to be electrically connected. a thing
** can be (row,column), or name1.name2, where name1 is the name of a
** CHIPAT-defined chip, and name2 is the name of one of its pins, or a
** number, giving the pin number of the named chip. you can use "TO" or
** "=" instead of "AND" if you want.
** 6) PRIORITY CONNECT thing AND thing
** same as above, except the order of connections will be preserved. the
** autorouter is free to reorder the non-PRIORITY CONNECTs, and in fact
** reorders them shortest first. if there are PRIORITY CONNECTs, they will
** all be routed before non-PRIORITY CONNECTs.
** 7) INCLUDE filename
** this causes the input to be temporarily taken from the given filename.
** when the given filename is completely processed (EOF encountered),
** control returns to the current file. INCLUDE statements may be nested
** (they may occur inside the given filename). complete and partial
** pathnames can be used (C:\TTL.INC, ..\TTL.INC, \TTL.INC, FOO\TTL.INC).
** 8) CHIP TYPE=type PINS=number HORIZONTAL=number VERTICAL=number
** [PACKAGE=package]
** this declares a chip type, which can be used to place chips on the
** board (see CHIPAT, below), but does not itself place anything on the
** board. TYPE gives the name that will be used in later CHIPAT
** statements. PINS declares the number of pins. HORIZONTAL gives the
** number of 50-mil units separating adjacent pins (along the long side of
** the chip). and VERTICAL gives the number of 50-mil units separating
** pins across from each other (across the skinny width of the chip).
** standard values for HORIZONTAL and VERTICAL are 2 and 6, respectively.
** all CHIP type names must be unique. The package string must be
** included if the parts listing switch is used.
** 9) number=name
** this declares a pin name for the chip that is currently being defined.
** this statement must follow a CHIP statement. pins not defined will have
** no name, but you can still refer to them by number. each pin on a chip
** can be named at most once.
** 10) name=number
** same as above.
** 11) CHIPAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
** this defines an instance of a chip, and places the appropriate holes on
** the board. (row,column) is the location of pin 1. NAME defines the name
** to be used in following CONNECT statements. TYPE declares the
** CHIPAT-defined type of the chip. ORIENTATION can have the values
** NORMAL, UP, DOWN, and UPSIDEDOWN.All CUSTOM, INLINE and CHIP names
** must be unique.
** NORMAL UP DOWN UPSIDEDOWN
**
** 6 5 4 +---+ +---+ 3 2 1
** +-*-*-*-+ 4 * * 3 1 * | * 6 +-*-*-*-+
** | -> | 5 * ^ * 2 2 * v * 5 | <- |
** +-*-*-*-+ 6 * | * 1 3 * * 4 +-*-*-*-+
** 1 2 3 +---+ +---+ 4 5 6
**
** usually the highest-numbered pin (pin N) is Vcc (power) and the pin
** farthest from it (pin N/2) is GND (ground).
**
** The following statements were added by Stephen Smith.
**
** 12) INLINE TYPE=type PINS=number HORIZONTAL=number [PACKAGE=package]
** this declares an inline type, which can be used to place chips on the
** board (see CHIPAT, above), but does not itself place anything on the
** board. TYPE gives the name that will be used in later INLINAT
** statements. PINS declares the number of pins. HORIZONTAL gives the
** number of 50-mil units separating adjacent pins. Standard value
** for HORIZONTAL is 2. All INLINE type names must be unique.
** The package string must be included if the parts listing switch is
** used.
** 13) INLINEAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
** this defines an instance of an inline, and places the appropriate
** holes on the board. (row,column) is the location of pin 1. NAME defines
** the name to be used in following CONNECT statements. TYPE declares the
** INLINEAT-defined type of the chip. ORIENTATION can have the values
** NORMAL, UP, DOWN, and UPSIDEDOWN. All CUSTOM, INLINE and CHIP
** names must be unique.
**
** NORMAL UP DOWN UPSIDEDOWN
**
** 1 2 3 + + 3 2 1
** +-*-*-*-+ * 3 1 * +-*-*-*-+
** * 2 2 *
** * 1 3 *
** + +
**
** 14) CUSTOM TYPE=type PACKAGE=package
** In this case package is predefined in the EXE file and can be
** one of the following strings:
** PLCC20, PLCC28, PLCC32, PLCC44, PLCC52, PLCC68, PLCC84,
** TO5, TO18, TRIMMERW, TRIMMERP, and TRIMMERY.
** These strings and the associated arrays that go with them are defined
** in the file plcc.c. The numbers in the arrays are offsets from pin
** number 1 on a fifty mil grid.
**
** 15) CUSTOMAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
** this defines an instance of an inline, and places the appropriate
** holes on the board. (row,column) is the location of pin 1. NAME defines
** the name to be used in following CONNECT statements. TYPE declares the
** CUSTOMAT-defined type of the chip. ORIENTATION can have the values
** NORMAL, UP, DOWN, and UPSIDEDOWN. All CUSTOM, INLINE and CHIP
** names must be unique. The directions shown below are for the
** PLCC chip carriers.
**
** NORMAL UP DOWN UPSIDEDOWN
**
** ***** ***** **1** *****
** ******* ******* ******* *******
** ** ** ** ** ** ** ** **
** 1* ** ** ** ** ** ** *1
** ** ** ** ** ** ** ** **
** ******* ******* ******* *******
** ***** **1** ***** *****
**
** TOxx packages:
**
** E C
** B B B E C
** C E C E B
**
**
** TRIMMERx packages:
**
** 3 1
** 2 2
** 1 3 2 3 1
** 2 1 3
**
** Note: The coordinate system is left handed. ( Positive X values
** are vertical and positive Y values are to the right. Cell (1,1)
** denotes the lower left hand corner of the board. )
**
**
** X
** ^
** |
** |
** +----> Y
**/
/* chip orientations (rotations) */
#define ORIENT_NORMAL 1
#define ORIENT_UP 2
#define ORIENT_DOWN 3
#define ORIENT_UPSIDEDOWN 4
/* input token types */
#define TOK_EOF 1 /* end of file, no more tokens */
#define TOK_NEWLINE 2 /* end of line */
#define TOK_NUMBER 3 /* number (digits) */
#define TOK_HOLE 4 /* "HOLE" */
#define TOK_ROWCOLUMN 5 /* "(row,column)" */
#define TOK_CONNECT 6 /* "CONNECT" */
#define TOK_EQUAL 7 /* "=" */
#define TOK_AND 8 /* "AND" */
#define TOK_ALPHANUM 9 /* name (letters, digits, ':','.','\') */
#define TOK_CHIP 10 /* "CHIP" */
#define TOK_NAME 11 /* "NAME" */
#define TOK_PINS 12 /* "PINS" */
#define TOK_HORIZONTAL 13 /* "HORIZONTAL" */
#define TOK_VERTICAL 14 /* "VERTICAL" */
#define TOK_INCLUDE 15 /* "INCLUDE" */
#define TOK_CHIPAT 16 /* "CHIPAT" */
#define TOK_TYPE 17 /* "TYPE" */
#define TOK_ORIENTATION 18 /* "ORIENTATION" */
#define TOK_NORMAL 19 /* "NORMAL" */
#define TOK_UP 20 /* "UP" */
#define TOK_DOWN 21 /* "DOWN" */
#define TOK_UPSIDEDOWN 22 /* "UPSIDEDOWN" */
#define TOK_DIMENSION 23 /* "DIMENSION" */
#define TOK_PRIORITY 24 /* "PRIORITY" */
#define TOK_TO 25 /* "TO" */
#define TOK_INLINE 26 /* "INLINE" */
#define TOK_INLINEAT 27 /* "INLINEAT" */
#define TOK_CUSTOM 28 /* "CUSTOM" */
#define TOK_CUSTOMAT 29 /* "CUSTOMAT" */
#define TOK_PACKAGE 29 /* "PACKAGE" */
struct reserved { /* reserved word input tokens */
char *tokenname;
int tokenvalue;
};
static struct reserved tokenmatch[] = { /* reserved word table */
{ "HOLE", TOK_HOLE }, { "CONNECT", TOK_CONNECT },
{ "AND", TOK_AND }, { "CHIP", TOK_CHIP },
{ "NAME", TOK_NAME }, { "PINS", TOK_PINS },
{ "HORIZONTAL", TOK_HORIZONTAL }, { "VERTICAL", TOK_VERTICAL },
{ "INCLUDE", TOK_INCLUDE }, { "CHIPAT", TOK_CHIPAT },
{ "TYPE", TOK_TYPE }, { "ORIENTATION", TOK_ORIENTATION },
{ "NORMAL", TOK_NORMAL }, { "UP", TOK_UP },
{ "DOWN", TOK_DOWN }, { "UPSIDEDOWN", TOK_UPSIDEDOWN },
{ "DIMENSION", TOK_DIMENSION }, { "PRIORITY", TOK_PRIORITY },
{ "TO", TOK_TO }, { "INLINE", TOK_INLINE },
{ "INLINEAT", TOK_INLINEAT }, { "CUSTOM", TOK_CUSTOM },
{ "CUSTOMAT", TOK_CUSTOMAT }, { "PACKAGE", TOK_PACKAGE }
};
#define MAXTOK 80 /* maximum token length (including null) */
static int numres = sizeof(tokenmatch) / sizeof(tokenmatch[0]);
static char token[MAXTOK]; /* the current token is formed here */
struct pinassign { /* for assigning names to pins */
int index;
char far *name;
struct pinassign far *next;
};
struct template { /* for "CHIP" declarations */
char far *type;
int pins;
int horizontal;
int vertical;
struct pinassign far *pinlist;
struct template far *next;
pin *array;
char far *package;
};
struct instance { /* for "CHIPAT" definitions */
int row;
int column;
char far *name;
struct template far *type;
int orientation;
struct instance far *next;
};
static struct template far *chip = NULL; /* list of CHIPs */
static struct instance far *chipat = NULL; /* list of CHIPATs */
extern void InitBoard( void );
extern long GetCell( int, int, int );
extern void SetCell( int, int, int, long );
extern void InitWork( void );
extern void SetWork( int, int, char far *, int, int, char far *, int );
extern void SortWork( void );
extern void Nomem( void );
int Initialize( char *, int );
static int initfile( FILE *, char * );
static void initchip( struct instance far *, char *, int );
static void initinline( struct instance far *, char *, int );
static void initcustom( struct instance far *, char *, int );
static void locate( char *, int *, int *, char *, int );
static int gettoken( FILE *, char *, int );
static char far *fcopy( char * );
static int same( char far *, char far * );
void Report( FILE * );
void partlist( struct instance far * );
int Initialize ( file, echo ) /* get hole coordinates and connections */
char *file;
int echo;
{
FILE *fp;
int tot;
if (echo)
printf( "Enter Initialize()\n" );
if (!(fp = fopen( file, "r" ))) {
fprintf( stderr, "can't open %s\n", file );
exit( -1 );
}
InitWork(); /* clear work list */
tot = initfile( fp, file ); /* read input file(s) */
if (SortConnects)
SortWork(); /* arrange to do shortest ones first */
if (echo) {
printf( " %lu bytes used for Board\n", Ltotal );
printf( " %lu bytes used for Dist\n", Itotal );
printf( " %lu bytes used for Dir\n", Ctotal );
printf( "Exit Initialize()\n" );
}
if (fclose( fp ))
fprintf( stderr, "error closing %s\n", file );
return( tot );
}
/* some useful macros (common code sequences) */
#define FileLine { fprintf( stderr, "%s(%d): ", file, line ); }
#define GetTok(tok) ((tok) = gettoken( fp, file, line ))
#define SkipRest { while (GetTok(tok) != TOK_EOF \
&& tok != TOK_NEWLINE) ; \
if (tok == TOK_NEWLINE) line++; }
#define SkipTokRest { while (tok != TOK_EOF && tok != TOK_NEWLINE) \
GetTok(tok); } \
if (tok == TOK_NEWLINE) line++; \
continue;
#define CheckInit { if (!InitBoardDone) { \
FileLine; \
fprintf( stderr, "need dimensions first\n" ); \
SkipRest; \
continue; } }
static int initfile ( fp, file ) /* read and process input file(s) */
FILE *fp;
char *file;
{
int tok, r1, c1, r2, c2, i, line;
char far *p;
char far *n1;
char far *n2;
long cell;
struct template far *p1;
struct pinassign far *p2;
struct pinassign far *p22;
struct instance far *p3;
FILE *fnew;
char *fname;
int tot = 0;
int index; /* into custom[]; Added by Stephen Smith */
line = 1;
while (GetTok(tok) != TOK_EOF) {
if (tok == TOK_DIMENSION) {
if (InitBoardDone) { /* can only do it once */
FileLine;
fprintf( stderr,
"redundant dimensions\n" );
SkipRest;
continue;
}
if (GetTok(tok) != TOK_ROWCOLUMN) {
FileLine;
fprintf( stderr, "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &Nrows, &Ncols );
if (Nrows <= 0 || Ncols <= 0) {
FileLine;
fprintf( stderr, "dimension error\n" );
}
else /* allocate memory for data structures */
InitBoard();
}
else if (tok == TOK_HOLE) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_ROWCOLUMN) {
FileLine;
fprintf( stderr, "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if (r1 <= 0 || r1 > Nrows || c1 <= 0 || c1 > Ncols) {
FileLine;
fprintf( stderr, "out of range\n" );
}
else { /* position the hole on the board */
/* should check for neighbor holes (error) */
SetCell( r1-1, c1-1, TOP, HOLE );
SetCell( r1-1, c1-1, BOTTOM, HOLE );
}
}
else if (tok == TOK_CONNECT) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r1, &c1 );
else if (tok == TOK_ALPHANUM)
locate( token, &r1, &c1, file, line );
else {
FileLine;
fprintf( stderr,
"expect (row,column) or name\n" );
SkipTokRest;
}
n1 = fcopy( token );
if (GetTok(tok) != TOK_EQUAL
&& tok != TOK_AND && tok != TOK_TO) {
FileLine;
fprintf( stderr, "expect = or AND or TO\n" );
SkipTokRest;
}
if (GetTok(tok) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r2, &c2 );
else if (tok == TOK_ALPHANUM)
locate( token, &r2, &c2, file, line );
else {
FileLine;
fprintf( stderr,
"expect (row,column) or name\n" );
SkipTokRest;
}
n2 = fcopy( token );
if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
|| c1 <= 0 || c1 > Ncols
|| c2 <= 0 || c2 > Ncols) {
FileLine;
fprintf( stderr, "out of range\n" );
farfree( n1 );
farfree( n2 );
}
else {
cell = GetCell( r1-1, c1-1, TOP );
if (!(cell & HOLE)) {
FileLine;
fprintf( stderr, "no source hole\n" );
farfree( n1 );
farfree( n2 );
SkipRest;
continue;
}
cell = GetCell( r2-1, c2-1, TOP );
if (!(cell & HOLE)) {
FileLine;
fprintf( stderr, "no target hole\n" );
farfree( n1 );
farfree( n2 );
SkipRest;
continue;
}
SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 0 );
tot++;
}
}
else if (tok == TOK_PRIORITY) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_CONNECT) {
FileLine;
fprintf( stderr, "expect CONNECT\n" );
SkipTokRest;
}
if (GetTok(tok) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r1, &c1 );
else if (tok == TOK_ALPHANUM)
locate( token, &r1, &c1, file, line );
else {
FileLine;
fprintf( stderr,
"expect (row,column) or name\n" );
SkipTokRest;
}
n1 = fcopy( token );
if (GetTok(tok) != TOK_EQUAL
&& tok != TOK_AND && tok != TOK_TO) {
FileLine;
fprintf( stderr, "expect = or AND or TO\n" );
SkipTokRest;
}
if (GetTok(tok) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r2, &c2 );
else if (tok == TOK_ALPHANUM)
locate( token, &r2, &c2, file, line );
else {
FileLine;
fprintf( stderr,
"expect (row,column) or name\n" );
SkipTokRest;
}
n2 = fcopy( token );
if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
|| c1 <= 0 || c1 > Ncols
|| c2 <= 0 || c2 > Ncols) {
FileLine;
fprintf( stderr, "out of range\n" );
farfree( n1 );
farfree( n2 );
}
else {
cell = GetCell( r1-1, c1-1, TOP );
if (!(cell & HOLE)) {
FileLine;
fprintf( stderr, "no source hole\n" );
farfree( n1 );
farfree( n2 );
SkipRest;
continue;
}
cell = GetCell( r2-1, c2-1, TOP );
if (!(cell & HOLE)) {
FileLine;
fprintf( stderr, "no target hole\n" );
farfree( n1 );
farfree( n2 );
SkipRest;
continue;
}
SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 1 );
tot++;
}
}
else if (tok == TOK_INCLUDE) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr,
"expect file name for INCLUDE\n" );
SkipTokRest;
}
if (!(fnew = fopen( token, "r" ))) {
FileLine;
fprintf( stderr,
"can't open INCLUDE file %s\n",
token );
SkipRest;
continue;
}
if (!(fname = strdup( token )))
Nomem();
if (GetTok(tok) != TOK_EOF
&& tok != TOK_NEWLINE) {
FileLine;
fprintf( stderr,
"extra chars on INCLUDE line\n" );
SkipRest;
}
if (tok == TOK_NEWLINE)
line++;
tot += initfile( fnew, fname ); /* recurse */
if (fclose( fnew )) {
FileLine;
fprintf( stderr,
"error closing INCLUDE file\n" );
}
free( fname );
continue; /* already ate the NEWLINE, if any */
}
else if (tok == TOK_CHIP) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
SkipTokRest;
}
if (!(p1 = (struct template far *)
farmalloc( sizeof(struct template) )))
Nomem();
p1->type = fcopy( token );
if (GetTok(tok) != TOK_PINS
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr, "expect PINS=number\n" );
farfree( p1->type );
farfree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
p1->pins = i;
if ((p1->pins = i) < 0 || (i & 1)) {
FileLine;
fprintf( stderr, "PINS negative or odd\n" );
}
if (GetTok(tok) != TOK_HORIZONTAL
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr,
"expect HORIZONTAL=number\n" );
farfree( p1->type );
farfree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
if ((p1->horizontal = i) <= 0) {
FileLine;
fprintf( stderr, "HORIZONTAL nonpositive\n" );
}
if (GetTok(tok) != TOK_VERTICAL
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr, "expect VERTICAL=number\n" );
farfree( p1->type );
farfree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
if ((p1->vertical = i) < 0) {
FileLine;
fprintf( stderr, "VERTICAL nonpositive\n" );
}
if( PartsList )
{
if (GetTok(tok) != TOK_PACKAGE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect PACKAGE=type\n" );
SkipTokRest;
}
p1->package = fcopy( token );
}
else
p1->package = fcopy("");
p1->pinlist = NULL;
p1->array = NULL;
p1->next = chip;
chip = p1;
}
else if (tok == TOK_INLINE) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
SkipTokRest;
}
if (!(p1 = (struct template far *)
farmalloc( sizeof(struct template) )))
Nomem();
p1->type = fcopy( token );
if (GetTok(tok) != TOK_PINS
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr, "expect PINS=number\n" );
farfree( p1->type );
farfree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
p1->pins = i;
if (GetTok(tok) != TOK_HORIZONTAL
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr,
"expect HORIZONTAL=number\n" );
farfree( p1->type );
farfree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
if ((p1->horizontal = i) <= 0) {
FileLine;
fprintf( stderr, "HORIZONTAL nonpositive\n" );
}
if( PartsList )
{
if (GetTok(tok) != TOK_PACKAGE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect PACKAGE=type\n" );
SkipTokRest;
}
p1->package = fcopy( token );
}
else
p1->package = fcopy("");
p1->vertical = 0;
p1->pinlist = NULL;
p1->array = NULL;
p1->next = chip;
chip = p1;
}
else if (tok == TOK_CUSTOM) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
SkipTokRest;
}
if (!(p1 = (struct template far *)
farmalloc( sizeof(struct template) )))
Nomem();
p1->type = fcopy( token );
if (GetTok(tok) != TOK_PACKAGE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect PACKAGE=type\n" );
SkipTokRest;
}
p1->package = fcopy( token );
i = 0;
index = 0;
while( i == 0 )
if ( strcmp( token, custom[index].string ) != 0 )
index++;
else
{
i = custom[index].array_len;
p1->array = custom[index].offset;
p1->vertical = 0;
p1->horizontal = 0;
}
if ( index == custom_len )
{
FileLine;
fprintf( stderr, "custom part isn\'t part of"
"this package\n" );
SkipRest;
continue;
}
p1->pins = i;
p1->pinlist = NULL;
p1->next = chip;
chip = p1;
}
else if (tok == TOK_NUMBER) {
CheckInit; /* must get dimensions first */
if (!chip) {
FileLine;
fprintf( stderr, "no template\n" );
SkipRest;
continue;
}
sscanf( token, "%d", &i );
if (GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect number=name\n" );
SkipTokRest;
}
if (!(p2 = (struct pinassign far *)
farmalloc( sizeof(struct pinassign) )))
Nomem();
p2->name = fcopy( token );
p2->index = i;
/* check uniqueness of name and index */
for (p22 = chip->pinlist; p22; p22 = p22->next)
if (p22->index == i
|| same( p22->name, p )) {
FileLine;
fprintf( stderr,
"warning: repeated pin\n" );
break;
}
p2->next = chip->pinlist;
chip->pinlist = p2;
}
else if (tok == TOK_ALPHANUM) {
CheckInit; /* must get dimensions first */
if (!chip) {
FileLine;
fprintf( stderr, "no template\n" );
SkipRest;
continue;
}
p = fcopy( token );
if (GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_NUMBER) {
FileLine;
fprintf( stderr, "expect name=number\n" );
farfree( p );
SkipTokRest;
}
sscanf( token, "%d", &i );
if (!(p2 = (struct pinassign far *)
farmalloc( sizeof(struct pinassign) )))
Nomem();
p2->name = p;
p2->index = i;
/* check uniqueness of name and index */
for (p22 = chip->pinlist; p22; p22 = p22->next)
if (p22->index == i
|| same( p22->name, p )) {
FileLine;
fprintf( stderr,
"warning: repeated pin\n" );
break;
}
p2->next = chip->pinlist;
chip->pinlist = p2;
}
else if (tok == TOK_CHIPAT) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_ROWCOLUMN) {
FileLine;
fprintf( stderr, "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if (GetTok(tok) != TOK_NAME
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect NAME=name\n" );
SkipTokRest;
}
if (!(p3 = (struct instance far *)
farmalloc( sizeof(struct instance) )))
Nomem();
p3->name = fcopy( token );
p3->row = r1;
p3->column = c1;
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
for (p3->type = chip; p3->type;
p3->type = p3->type->next)
if (same( token, p3->type->type ))
break;
if (!(p3->type)) {
FileLine;
fprintf( stderr,
"couldn't find chip type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
if (GetTok(tok) != TOK_ORIENTATION
|| GetTok(tok) != TOK_EQUAL
|| (GetTok(tok) != TOK_NORMAL
&& tok != TOK_UP && tok != TOK_DOWN
&& tok != TOK_UPSIDEDOWN)) {
FileLine;
fprintf( stderr,
"expect ORIENTATION=orientation\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
switch (tok) {
case TOK_NORMAL:
p3->orientation = ORIENT_NORMAL; break;
case TOK_UP:
p3->orientation = ORIENT_UP; break;
case TOK_DOWN:
p3->orientation = ORIENT_DOWN; break;
case TOK_UPSIDEDOWN:
p3->orientation = ORIENT_UPSIDEDOWN; break;
default:
FileLine;
fprintf( stderr, "internal error\n" );
exit( -1 );
break;
}
p3->next = chipat;
chipat = p3;
initchip( p3, file, line );
}
else if (tok == TOK_INLINEAT) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_ROWCOLUMN) {
FileLine;
fprintf( stderr, "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if (GetTok(tok) != TOK_NAME
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect NAME=name\n" );
SkipTokRest;
}
if (!(p3 = (struct instance far *)
farmalloc( sizeof(struct instance) )))
Nomem();
p3->name = fcopy( token );
p3->row = r1;
p3->column = c1;
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
for (p3->type = chip; p3->type;
p3->type = p3->type->next)
if (same( token, p3->type->type ))
break;
if (!(p3->type)) {
FileLine;
fprintf( stderr,
"couldn't find chip type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
if (GetTok(tok) != TOK_ORIENTATION
|| GetTok(tok) != TOK_EQUAL
|| (GetTok(tok) != TOK_NORMAL
&& tok != TOK_UP && tok != TOK_DOWN
&& tok != TOK_UPSIDEDOWN)) {
FileLine;
fprintf( stderr,
"expect ORIENTATION=orientation\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
switch (tok) {
case TOK_NORMAL:
p3->orientation = ORIENT_NORMAL; break;
case TOK_UP:
p3->orientation = ORIENT_UP; break;
case TOK_DOWN:
p3->orientation = ORIENT_DOWN; break;
case TOK_UPSIDEDOWN:
p3->orientation = ORIENT_UPSIDEDOWN; break;
default:
FileLine;
fprintf( stderr, "internal error\n" );
exit( -1 );
break;
}
p3->next = chipat;
chipat = p3;
initinline( p3, file, line );
}
else if (tok == TOK_CUSTOMAT) {
CheckInit; /* must get dimensions first */
if (GetTok(tok) != TOK_ROWCOLUMN) {
FileLine;
fprintf( stderr, "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if (GetTok(tok) != TOK_NAME
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect NAME=name\n" );
SkipTokRest;
}
if (!(p3 = (struct instance far *)
farmalloc( sizeof(struct instance) )))
Nomem();
p3->name = fcopy( token );
p3->row = r1;
p3->column = c1;
if (GetTok(tok) != TOK_TYPE
|| GetTok(tok) != TOK_EQUAL
|| GetTok(tok) != TOK_ALPHANUM) {
FileLine;
fprintf( stderr, "expect TYPE=type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
for (p3->type = chip; p3->type;
p3->type = p3->type->next)
if (same( token, p3->type->type ))
break;
if (!(p3->type)) {
FileLine;
fprintf( stderr,
"couldn't find chip type\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
if (GetTok(tok) != TOK_ORIENTATION
|| GetTok(tok) != TOK_EQUAL
|| (GetTok(tok) != TOK_NORMAL
&& tok != TOK_UP && tok != TOK_DOWN
&& tok != TOK_UPSIDEDOWN)) {
FileLine;
fprintf( stderr,
"expect ORIENTATION=orientation\n" );
farfree( p3->name );
farfree( p3 );
SkipTokRest;
}
switch (tok) {
case TOK_NORMAL:
p3->orientation = ORIENT_NORMAL; break;
case TOK_UP:
p3->orientation = ORIENT_UP; break;
case TOK_DOWN:
p3->orientation = ORIENT_DOWN; break;
case TOK_UPSIDEDOWN:
p3->orientation = ORIENT_UPSIDEDOWN; break;
default:
FileLine;
fprintf( stderr, "internal error\n" );
exit( -1 );
break;
}
p3->next = chipat;
chipat = p3;
initcustom( p3, file, line );
}
else if (tok == TOK_NEWLINE) {
line++;
continue;
}
else { /* something unexpected */
FileLine;
fprintf( stderr, "syntax error: unexpected input\n" );
}
if (GetTok(tok) != TOK_EOF
&& tok != TOK_NEWLINE) {
FileLine;
fprintf( stderr,
"syntax error: expected end of line\n" );
SkipRest;
}
else if (tok == TOK_NEWLINE)
line++;
}
if ( PartsList) partlist(chipat);
return( tot );
}
static void initchip ( p, file, line ) /* init chip definition (make holes) */
struct instance far *p;
char *file;
int line;
{
int r, c, pin;
struct template far *t;
pin = 1;
r = p->row;
c = p->column;
t = p->type;
/* should check for neighboring holes (warning if so) */
switch (p->orientation) {
case ORIENT_NORMAL:
while (pin <= t->pins / 2) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c += t->horizontal;
}
c -= t->horizontal;
r += t->vertical;
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c -= t->horizontal;
}
break;
case ORIENT_UP:
while (pin <= t->pins / 2) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r += t->horizontal;
}
r -= t->horizontal;
c -= t->vertical;
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r -= t->horizontal;
}
break;
case ORIENT_DOWN:
while (pin <= t->pins / 2) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r -= t->horizontal;
}
r += t->horizontal;
c += t->vertical;
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r += t->horizontal;
}
break;
case ORIENT_UPSIDEDOWN:
while (pin <= t->pins / 2) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c -= t->horizontal;
}
c += t->horizontal;
r -= t->vertical;
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c += t->horizontal;
}
break;
default:
FileLine;
fprintf( stderr, "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
static void initinline( p, file, line ) /* init inline definition (make holes) */
struct instance far *p;
char *file;
int line;
{
int r, c, pin;
struct template far *t;
pin = 1;
r = p->row;
c = p->column;
t = p->type;
/* should check for neighboring holes (warning if so) */
switch (p->orientation) {
case ORIENT_NORMAL:
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c += t->horizontal;
}
break;
case ORIENT_UP:
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r += t->horizontal;
}
break;
case ORIENT_DOWN:
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r -= t->horizontal;
}
break;
case ORIENT_UPSIDEDOWN:
while (pin <= t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c -= t->horizontal;
}
break;
default:
FileLine;
fprintf( stderr, "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
static void initcustom( p, file, line ) /* init custom definition (make holes) */
struct instance far *p;
char *file;
int line;
{
int r, c, row, col, pin;
struct template far *t;
pin = 0;
row = r = p->row;
col = c = p->column;
t = p->type;
/* should check for neighboring holes (warning if so) */
switch (p->orientation) {
case ORIENT_NORMAL:
while (pin < t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
c = col + (t->array+pin)->c;
r = row + (t->array+pin)->r;
}
break;
case ORIENT_UP:
while (pin < t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r = row + (t->array+pin)->c;
c = col - (t->array+pin)->r;
}
break;
case ORIENT_DOWN:
while (pin < t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r = row - (t->array+pin)->c;
c = col + (t->array+pin)->r;
}
break;
case ORIENT_UPSIDEDOWN:
while (pin < t->pins) {
SetCell( r-1, c-1, TOP, HOLE );
SetCell( r-1, c-1, BOTTOM, HOLE );
pin++;
r = row - (t->array+pin)->r;
c = col - (t->array+pin)->c;
}
break;
default:
FileLine;
fprintf( stderr, "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
static void locate ( p, r, c, file, line )
/* find location of name1.{name2,number} */
char *p;
int *r, *c;
char *file;
int line;
{
char *q;
int i;
struct instance far *s;
struct pinassign far *t;
if (!(q = strchr( p, '.' ))) {
FileLine;
fprintf( stderr, "expect name1.{name2,number}\n" );
return;
}
*q++ = 0; /* separate into two parts & point at second part */
for (s = chipat; s; s = s->next) /* find proper chip */
if (same( p, s->name ))
break;
if (!s || !(s->type)) {
FileLine;
fprintf( stderr, "can't find chip or chip type: %s\n", p );
fprintf( stdout, "\n" );
return;
}
if (isdigit( *q )) { /* get pin number */
i = atoi( q );
if (i <= 0 || i > s->type->pins) {
FileLine;
fprintf( stderr, "pin out of range\n" );
return;
}
}
else { /* get index of named pin via the template */
for (t = s->type->pinlist; t; t = t->next)
if (same( q, t->name ))
break;
if (!t) {
FileLine;
fprintf( stderr, "can't find pin\n" );
return;
}
i = t->index;
}
*r = s->row;
*c = s->column;
if( s->type->array == NULL )
{
switch (s->orientation) {
case ORIENT_NORMAL:
if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
*c += (i-1) * s->type->horizontal;
else {
*r += s->type->vertical;
*c += (s->type->pins - i) * s->type->horizontal;
}
break;
case ORIENT_UP:
if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
*r += (i-1) * s->type->horizontal;
else {
*c -= s->type->vertical;
*r += (s->type->pins - i) * s->type->horizontal;
}
break;
case ORIENT_DOWN:
if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
*r -= (i-1) * s->type->horizontal;
else {
*c += s->type->vertical;
*r -= (s->type->pins - i) * s->type->horizontal;
}
break;
case ORIENT_UPSIDEDOWN:
if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
*c -= (i-1) * s->type->horizontal;
else {
*r -= s->type->vertical;
*c -= (s->type->pins - i) * s->type->horizontal;
}
break;
default:
FileLine;
fprintf( stderr, "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
else
{
switch (s->orientation) {
case ORIENT_NORMAL:
*r += (s->type->array+i-1)->r;
*c += (s->type->array+i-1)->c;
break;
case ORIENT_UP:
*c -= (s->type->array+i-1)->r;
*r += (s->type->array+i-1)->c;
break;
case ORIENT_DOWN:
*c += (s->type->array+i-1)->r;
*r -= (s->type->array+i-1)->c;
break;
case ORIENT_UPSIDEDOWN:
*r -= (s->type->array+i-1)->r;
*c -= (s->type->array+i-1)->c;
break;
default:
FileLine;
fprintf( stderr, "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
*--q = '.'; /* put back the separator */
}
static int gettoken ( fp, file, line )
/* get next token into token[], return value */
FILE *fp;
char *file;
int line;
{
int ch, i;
/* burn whitespace */
while ((ch = getc( fp )) == ' ' || ch == '\t')
;
if (ch == EOF)
return( TOK_EOF );
else if (ch == '\n')
return( TOK_NEWLINE );
else if (ch == ';') { /* comment; burn to end of line */
while ((ch = getc( fp )) != EOF && ch != '\n')
;
return( (ch == '\n') ? TOK_NEWLINE : TOK_EOF );
}
else if (ch == '=')
return( TOK_EQUAL );
else if (isdigit( ch )) { /* a number; move it to the buffer */
i = 0;
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fp );
} while (isdigit( ch ));
token[i] = 0;
if (ch != EOF)
ungetc( ch, fp );
return( TOK_NUMBER );
}
else if (isalpha( ch ) || ch == '.' || ch == '\\') {
/* a name; move it to the buffer */
i = 0;
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fp );
} while (isalnum( ch ) || ch == ':' || ch == '.'
|| ch == '\\');
token[i] = 0;
if (ch != EOF)
ungetc( ch, fp );
/* try to identify it as a reserved word */
for (i = 0; i < numres; i++) /* search table */
if (!stricmp( tokenmatch[i].tokenname, token ))
return( tokenmatch[i].tokenvalue );
/* it's not a reserved word; just return it */
strupr( token );
return( TOK_ALPHANUM );
}
else if (ch == '(') { /* "(row,column)", move it to the buffer */
token[0] = (char)ch;
i = 1;
while ((ch = getc( fp )) == ' ' || ch == '\t')
;
if (!isdigit( ch )) {
FileLine;
fprintf( stderr, "syntax error: expected digit\n" );
exit( -1 );
}
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fp );
} while (isdigit( ch ));
while (ch == ' ' || ch == '\t')
ch = getc( fp );
if (ch != ',') {
FileLine;
fprintf( stderr, "syntax error: expected comma\n" );
exit( -1 );
}
if (i < MAXTOK-1)
token[i++] = (char)ch;
while ((ch = getc( fp )) == ' ' || ch == '\t')
;
if (!isdigit( ch )) {
FileLine;
fprintf( stderr, "syntax error: expected digit\n" );
exit( -1 );
}
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fp );
} while (isdigit( ch ));
while (ch == ' ' || ch == '\t')
ch = getc( fp );
if (ch != ')') {
FileLine;
fprintf( stderr,
"syntax error: expected right paren\n" );
exit( -1 );
}
if (i < MAXTOK-1)
token[i++] = (char)ch;
token[i] = 0;
return( TOK_ROWCOLUMN );
}
else {
FileLine;
fprintf( stderr, "syntax error: unrecognized token\n" );
exit( -1 );
}
}
static char far *fcopy ( p ) /* return ptr to far string copy */
char *p;
{
char far *q;
char far *r;
if (!(q = r = farmalloc( strlen( p ) + 1 )))
Nomem();
while (*r++ = *p++) /* copy string */
;
return( q );
}
static int same ( p, q ) /* return 1 if far strings are identical, else 0 */
char far *p;
char far *q;
{
while (*p && *p == *q) { /* compare bytes until mismatch or end */
p++;
q++;
}
return( (*p || *q) ? 0 : 1 );
}
void Report ( fp ) /* output routed board */
FILE *fp;
{
int r, c;
char b;
long x;
printf( "Enter Report()\n" );
/* output dimensions first */
b = (char)Nrows; putc( b, fp );
b = (char)(Nrows>>8); putc( b, fp );
b = (char)Ncols; putc( b, fp );
b = (char)(Ncols>>8); putc( b, fp );
/* now do rows and columns */
for (r = 0; r < Nrows; r++)
for (c = 0; c < Ncols; c++) {
x = GetCell( r, c, TOP ); /* first do frontside */
b = (char)x; putc( b, fp );
b = (char)(x>>8); putc( b, fp );
b = (char)(x>>16); putc( b, fp );
b = (char)(x>>24); putc( b, fp );
x = GetCell( r, c, BOTTOM ); /* then do backside */
b = (char)x; putc( b, fp );
b = (char)(x>>8); putc( b, fp );
b = (char)(x>>16); putc( b, fp );
b = (char)(x>>24); putc( b, fp );
}
if (ferror( fp ))
fprintf( stderr, "output error; disk might be full\n" );
printf( "Exit Report()\n" );
}
void partlist( struct instance far * chip)
{
if ( chip->next != NULL) partlist( chip->next );
fprintf(partsfile, "%-8s%-12s%-4d%-8s\n",chip->name, chip->type->type,
chip->type->pins, chip->type->package);
}