home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
644.IO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-05
|
26KB
|
883 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include "cell.h"
/* board dimensions */
extern int Nrows;
extern int Ncols;
extern int InitBoardDone; /* sanity check */
/* memory usage */
extern long Ltotal; /* for board */
extern long Itotal; /* for dist */
extern 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 '='
** 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
** 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.
** 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 CHIPAT 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).
*/
/* 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" */
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 }
};
#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;
};
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 );
void Initialize( FILE * );
static void initfile( FILE * );
static void initchip( struct instance far * );
static void locate( char *, int *, int * );
static int gettoken( FILE * );
static char far *fcopy( char * );
static int same( char far *, char far * );
void Report( FILE * );
void Initialize ( fin ) /* get hole coordinates and connections */
FILE *fin;
{
printf( "enter Initialize()\n" );
InitWork(); /* clear work list */
initfile( fin ); /* read input file(s) */
SortWork(); /* arrange to do shortest ones first */
printf( " %ld bytes used for board\n", Ltotal );
printf( " %ld bytes used for dist\n", Itotal );
printf( " %ld bytes used for dir\n", Ctotal );
printf( "leave Initialize()\n" );
}
/* some useful macros (common code sequences) */
#define SkipRest { while ((tok = gettoken( fin )) != TOK_EOF \
&& tok != TOK_NEWLINE) ; }
#define SkipTokRest { while (tok != TOK_EOF && tok != TOK_NEWLINE) \
tok = gettoken( fin ); } \
continue;
#define CheckInit { if (!InitBoardDone) { \
printf( "error: need dimensions first\n" ); \
SkipRest; \
continue; } }
static void initfile ( fin ) /* read and process input file(s) */
FILE *fin;
{
int tok, r1, c1, r2, c2, i;
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;
while ((tok = gettoken( fin )) != TOK_EOF) {
if (tok == TOK_DIMENSION) {
if (InitBoardDone) { /* can only do it once */
printf( "error: redundant dimensions\n" );
SkipRest;
continue;
}
if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
printf( "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &Nrows, &Ncols );
if (Nrows <= 0 || Ncols <= 0)
printf( "dimension error\n" );
else /* allocate memory for data structures */
InitBoard();
}
else if (tok == TOK_HOLE) {
CheckInit; /* must get dimensions first */
if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
printf( "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if (r1 <= 0 || r1 > Nrows || c1 <= 0 || c1 > Ncols)
printf( "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 ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r1, &c1 );
else if (tok == TOK_ALPHANUM)
locate( token, &r1, &c1 );
else {
printf( "expect (row,column) or name\n" );
SkipTokRest;
}
n1 = fcopy( token );
if ((tok = gettoken( fin )) != TOK_EQUAL
&& tok != TOK_AND) {
printf( "expect = or AND\n" );
SkipTokRest;
}
if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r2, &c2 );
else if (tok == TOK_ALPHANUM)
locate( token, &r2, &c2 );
else {
printf( "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) {
printf( "out of range\n" );
_ffree( n1 );
_ffree( n2 );
}
else {
cell = GetCell( r1-1, c1-1, TOP );
if (!(cell & HOLE)) {
printf( "error: no source hole\n" );
_ffree( n1 );
_ffree( n2 );
SkipRest;
continue;
}
cell = GetCell( r2-1, c2-1, TOP );
if (!(cell & HOLE)) {
printf( "error: no target hole\n" );
_ffree( n1 );
_ffree( n2 );
SkipRest;
continue;
}
SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 0 );
}
}
else if (tok == TOK_PRIORITY) {
CheckInit; /* must get dimensions first */
if ((tok = gettoken( fin )) != TOK_CONNECT) {
printf( "expect CONNECT\n" );
SkipTokRest;
}
if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r1, &c1 );
else if (tok == TOK_ALPHANUM)
locate( token, &r1, &c1 );
else {
printf( "expect (row,column) or name\n" );
SkipTokRest;
}
n1 = fcopy( token );
if ((tok = gettoken( fin )) != TOK_EQUAL
&& tok != TOK_AND) {
printf( "expect = or AND\n" );
SkipTokRest;
}
if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
sscanf( token, "(%d,%d)", &r2, &c2 );
else if (tok == TOK_ALPHANUM)
locate( token, &r2, &c2 );
else {
printf( "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) {
printf( "out of range\n" );
_ffree( n1 );
_ffree( n2 );
}
else {
cell = GetCell( r1-1, c1-1, TOP );
if (!(cell & HOLE)) {
printf( "error: no source hole\n" );
_ffree( n1 );
_ffree( n2 );
SkipRest;
continue;
}
cell = GetCell( r2-1, c2-1, TOP );
if (!(cell & HOLE)) {
printf( "error: no target hole\n" );
_ffree( n1 );
_ffree( n2 );
SkipRest;
continue;
}
SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 1 );
}
}
else if (tok == TOK_INCLUDE) {
CheckInit; /* must get dimensions first */
if ((tok = gettoken( fin )) != TOK_ALPHANUM) {
printf( "expect name for INCLUDE\n" );
SkipTokRest;
}
if (!(fnew = fopen( token, "r" ))) {
printf( "can't open INCLUDE file %s\n",
token );
SkipRest;
continue;
}
if ((tok = gettoken( fin )) != TOK_EOF
&& tok != TOK_NEWLINE) {
printf( "extra chars on INCLUDE line\n" );
SkipRest;
}
initfile( fnew ); /* recurse */
if (fclose( fnew ))
printf( "error closing INCLUDE file\n" );
continue; /* already ate the NEWLINE, if any */
}
else if (tok == TOK_CHIP) {
CheckInit; /* must get dimensions first */
if ((tok = gettoken( fin )) != TOK_TYPE
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_ALPHANUM) {
printf( "expect TYPE=type\n" );
SkipTokRest;
}
if (!(p1 = (struct template far *)
_fmalloc( sizeof(struct template) )))
Nomem();
p1->type = fcopy( token );
if ((tok = gettoken( fin )) != TOK_PINS
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_NUMBER) {
printf( "expect PINS=number\n" );
_ffree( p1->type );
_ffree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
p1->pins = i;
if ((p1->pins = i) < 0 || (i & 1))
printf( "PINS negative or odd\n" );
if ((tok = gettoken( fin )) != TOK_HORIZONTAL
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_NUMBER) {
printf( "expect HORIZONTAL=number\n" );
_ffree( p1->type );
_ffree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
if ((p1->horizontal = i) <= 0)
printf( "HORIZONTAL nonpositive\n" );
if ((tok = gettoken( fin )) != TOK_VERTICAL
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_NUMBER) {
printf( "expect VERTICAL=number\n" );
_ffree( p1->type );
_ffree( p1 );
SkipTokRest;
}
sscanf( token, "%d", &i );
if ((p1->vertical = i) < 0)
printf( "VERTICAL nonpositive\n" );
p1->pinlist = NULL;
p1->next = chip;
chip = p1;
}
else if (tok == TOK_NUMBER) {
CheckInit; /* must get dimensions first */
if (!chip) {
printf( "no template\n" );
SkipRest;
continue;
}
sscanf( token, "%d", &i );
if ((tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_ALPHANUM) {
printf( "expect number=name\n" );
SkipTokRest;
}
if (!(p2 = (struct pinassign far *)
_fmalloc( 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 )) {
printf( "warning: repeated pin\n" );
break;
}
p2->next = chip->pinlist;
chip->pinlist = p2;
}
else if (tok == TOK_ALPHANUM) {
CheckInit; /* must get dimensions first */
if (!chip) {
printf( "no template\n" );
SkipRest;
continue;
}
p = fcopy( token );
if ((tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_NUMBER) {
printf( "expect name=number\n" );
_ffree( p );
SkipTokRest;
}
sscanf( token, "%d", &i );
if (!(p2 = (struct pinassign far *)
_fmalloc( 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 )) {
printf( "warning: repeated pin\n" );
break;
}
p2->next = chip->pinlist;
chip->pinlist = p2;
}
else if (tok == TOK_CHIPAT) {
CheckInit; /* must get dimensions first */
if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
printf( "expect (row,column)\n" );
SkipTokRest;
}
sscanf( token, "(%d,%d)", &r1, &c1 );
if ((tok = gettoken( fin )) != TOK_NAME
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_ALPHANUM) {
printf( "expect NAME=name\n" );
SkipTokRest;
}
if (!(p3 = (struct instance far *)
_fmalloc( sizeof(struct instance) )))
Nomem();
p3->name = fcopy( token );
p3->row = r1;
p3->column = c1;
if ((tok = gettoken( fin )) != TOK_TYPE
|| (tok = gettoken( fin )) != TOK_EQUAL
|| (tok = gettoken( fin )) != TOK_ALPHANUM) {
printf( "expect TYPE=type\n" );
_ffree( p3->name );
_ffree( p3 );
SkipTokRest;
}
for (p3->type = chip; p3->type;
p3->type = p3->type->next)
if (same( token, p3->type->type ))
break;
if (!(p3->type)) {
printf( "couldn't find chip type\n" );
_ffree( p3->name );
_ffree( p3 );
SkipTokRest;
}
if ((tok = gettoken( fin )) != TOK_ORIENTATION
|| (tok = gettoken( fin )) != TOK_EQUAL
|| ((tok = gettoken( fin )) != TOK_NORMAL
&& tok != TOK_UP && tok != TOK_DOWN
&& tok != TOK_UPSIDEDOWN)) {
printf( "expect ORIENTATION=orientation\n" );
_ffree( p3->name );
_ffree( 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:
printf( "internal error\n" );
exit( -1 );
break;
}
p3->next = chipat;
chipat = p3;
initchip( p3 );
}
else if (tok == TOK_NEWLINE)
continue;
else /* something unexpected */
printf( "syntax error: unexpected input\n" );
if ((tok = gettoken( fin )) != TOK_EOF && tok != TOK_NEWLINE) {
printf( "syntax error: expected end of line\n" );
SkipRest;
}
}
}
static void initchip ( p ) /* initialize a chip definition (create holes) */
struct instance far *p;
{
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:
printf( "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
}
static void locate ( p, r, c ) /* find location of name1.{name2,number} */
char *p;
int *r, *c;
{
char *q;
int i;
struct instance far *s;
struct pinassign far *t;
if (!(q = strchr( p, '.' ))) {
printf( "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)) {
printf( "can't find chip or chip type\n" );
return;
}
if (isdigit( *q )) { /* get pin number */
i = atoi( q );
if (i <= 0 || i > s->type->pins) {
printf( "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) {
printf( "can't find pin\n" );
return;
}
i = t->index;
}
*r = s->row;
*c = s->column;
switch (s->orientation) {
case ORIENT_NORMAL:
if (i <= s->type->pins / 2)
*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)
*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)
*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)
*c -= (i-1) * s->type->horizontal;
else {
*r -= s->type->vertical;
*c -= (s->type->pins - i) * s->type->horizontal;
}
break;
default:
printf( "internal error: unexpected orientation\n" );
exit( -1 );
break;
}
*--q = '.'; /* put back the separator */
}
static int gettoken ( fin ) /* get next token into token[], return value */
FILE *fin;
{
int ch, i;
/* burn whitespace */
while ((ch = getc( fin )) == ' ' || 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( fin )) != 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( fin );
} while (isdigit( ch ));
token[i] = 0;
if (ch != EOF)
ungetc( ch, fin );
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( fin );
} while (isalnum( ch ) || ch == ':' || ch == '.'
|| ch == '\\');
token[i] = 0;
if (ch != EOF)
ungetc( ch, fin );
/* 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( fin )) == ' ' || ch == '\t') ;
if (!isdigit( ch )) {
printf( "syntax error: expected digit\n" );
exit( -1 );
}
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fin );
} while (isdigit( ch ));
while (ch == ' ' || ch == '\t')
ch = getc( fin );
if (ch != ',') {
printf( "syntax error: expected comma\n" );
exit( -1 );
}
if (i < MAXTOK-1)
token[i++] = (char)ch;
while ((ch = getc( fin )) == ' ' || ch == '\t') ;
if (!isdigit( ch )) {
printf( "syntax error: expected digit\n" );
exit( -1 );
}
do {
if (i < MAXTOK-1)
token[i++] = (char)ch;
ch = getc( fin );
} while (isdigit( ch ));
while (ch == ' ' || ch == '\t')
ch = getc( fin );
if (ch != ')') {
printf( "syntax error: expected right paren\n" );
exit( -1 );
}
if (i < MAXTOK-1)
token[i++] = (char)ch;
token[i] = 0;
return( TOK_ROWCOLUMN );
}
else {
printf( "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 = _fmalloc( 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 ( fout ) /* output routed board */
FILE *fout;
{
int r, c;
char b;
long x;
printf( "enter Report()\n" );
/* output dimensions first */
b = (char)Nrows; putc( b, fout );
b = (char)(Nrows>>8); putc( b, fout );
b = (char)Ncols; putc( b, fout );
b = (char)(Ncols>>8); putc( b, fout );
/* 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, fout );
b = (char)(x>>8); putc( b, fout );
b = (char)(x>>16); putc( b, fout );
b = (char)(x>>24); putc( b, fout );
x = GetCell( r, c, BOTTOM ); /* then do backside */
b = (char)x; putc( b, fout );
b = (char)(x>>8); putc( b, fout );
b = (char)(x>>16); putc( b, fout );
b = (char)(x>>24); putc( b, fout );
}
printf( "leave Report()\n" );
}