home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / tech / pcbsrcs2 / io4.c < prev    next >
C/C++ Source or Header  |  1991-02-10  |  56KB  |  1,528 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <malloc.h>
  5. #include <ctype.h>
  6. #include "cell.h"
  7. #include "custom.h"
  8.  
  9. extern int Nrows, Ncols; /* board dimensions */
  10.  
  11. extern int InitBoardDone; /* sanity check */
  12. extern int SortConnects; /* 0 = don't sort, 1 = sort */
  13. extern int PartsList;    /* 0 = no listing, 1 = a listing */
  14. extern FILE *partsfile;  /* file pointer for the above switch */
  15.  
  16. /* memory usage */
  17. extern unsigned long Ltotal; /* for board */
  18. extern unsigned long Itotal; /* for dist */
  19. extern unsigned long Ctotal; /* for dir */
  20.  
  21. /*
  22. ** the following types of input lines are legal (spaces and tabs can separate
  23. ** tokens, and case is not significant):
  24. **
  25. **  1) a blank line (ignored)
  26. **  2) ';' followed by anything (ignored)
  27. **     use semicolon to insert comments.
  28. **  3) DIMENSION (row,column)
  29. **     this defines the number of rows and columns on the board, and must be
  30. **     given before any of the lines below. note that the user sees the board
  31. **     coordinate space as being 1-based, but internally it is 0-based.
  32. **  4) HOLE (row,column)
  33. **     this defines a hole location.
  34. **  5) CONNECT thing AND thing
  35. **     this declares that two holes are to be electrically connected. a thing
  36. **     can be (row,column), or name1.name2, where name1 is the name of a
  37. **     CHIPAT-defined chip, and name2 is the name of one of its pins, or a
  38. **     number, giving the pin number of the named chip. you can use "TO" or
  39. **     "=" instead of "AND" if you want.
  40. **  6) PRIORITY CONNECT thing AND thing
  41. **     same as above, except the order of connections will be preserved. the
  42. **     autorouter is free to reorder the non-PRIORITY CONNECTs, and in fact
  43. **     reorders them shortest first. if there are PRIORITY CONNECTs, they will
  44. **     all be routed before non-PRIORITY CONNECTs.
  45. **  7) INCLUDE filename
  46. **     this causes the input to be temporarily taken from the given filename.
  47. **     when the given filename is completely processed (EOF encountered),
  48. **     control returns to the current file. INCLUDE statements may be nested
  49. **     (they may occur inside the given filename). complete and partial
  50. **     pathnames can be used (C:\TTL.INC, ..\TTL.INC, \TTL.INC, FOO\TTL.INC).
  51. **  8) CHIP TYPE=type PINS=number HORIZONTAL=number VERTICAL=number
  52. **       [PACKAGE=package]
  53. **     this declares a chip type, which can be used to place chips on the
  54. **     board (see CHIPAT, below), but does not itself place anything on the
  55. **     board. TYPE gives the name that will be used in later CHIPAT
  56. **     statements. PINS declares the number of pins. HORIZONTAL gives the
  57. **     number of 50-mil units separating adjacent pins (along the long side of
  58. **     the chip). and VERTICAL gives the number of 50-mil units separating
  59. **     pins across from each other (across the skinny width of the chip).
  60. **     standard values for HORIZONTAL and VERTICAL are 2 and 6, respectively.
  61. **     all CHIP type names must be unique.  The package string must be
  62. **     included if the parts listing switch is used.
  63. **  9) number=name
  64. **     this declares a pin name for the chip that is currently being defined.
  65. **     this statement must follow a CHIP statement. pins not defined will have
  66. **     no name, but you can still refer to them by number. each pin on a chip
  67. **     can be named at most once.
  68. ** 10) name=number
  69. **     same as above.
  70. ** 11) CHIPAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
  71. **     this defines an instance of a chip, and places the appropriate holes on
  72. **     the board. (row,column) is the location of pin 1. NAME defines the name
  73. **     to be used in following CONNECT statements. TYPE declares the
  74. **     CHIPAT-defined type of the chip. ORIENTATION can have the values
  75. **     NORMAL, UP, DOWN, and UPSIDEDOWN.All CUSTOM, INLINE and CHIP names
  76. **     must be unique.
  77. **      NORMAL           UP           DOWN        UPSIDEDOWN
  78. **
  79. **       6 5 4          +---+         +---+          3 2 1
  80. **     +-*-*-*-+      4 *   * 3     1 * | * 6      +-*-*-*-+
  81. **     |  ->   |      5 * ^ * 2     2 * v * 5      |   <-  |
  82. **     +-*-*-*-+      6 * | * 1     3 *   * 4      +-*-*-*-+
  83. **       1 2 3          +---+         +---+          4 5 6
  84. **
  85. **     usually the highest-numbered pin (pin N) is Vcc (power) and the pin
  86. **     farthest from it (pin N/2) is GND (ground).
  87. **
  88. ** The following statements were added by Stephen Smith.
  89. **
  90. ** 12) INLINE TYPE=type PINS=number HORIZONTAL=number [PACKAGE=package]
  91. **     this declares an inline type, which can be used to place chips on the
  92. **     board (see CHIPAT, above), but does not itself place anything on the
  93. **     board. TYPE gives the name that will be used in later INLINAT
  94. **     statements. PINS declares the number of pins. HORIZONTAL gives the
  95. **     number of 50-mil units separating adjacent pins.  Standard value
  96. **     for HORIZONTAL is 2.  All INLINE type names must be unique.
  97. **     The package string must be included if the parts listing switch is
  98. **     used.
  99. ** 13) INLINEAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
  100. **     this defines an instance of an inline, and places the appropriate
  101. **     holes on the board. (row,column) is the location of pin 1. NAME defines
  102. **     the name to be used in following CONNECT statements. TYPE declares the
  103. **     INLINEAT-defined type of the chip. ORIENTATION can have the values
  104. **     NORMAL, UP, DOWN, and UPSIDEDOWN.  All CUSTOM, INLINE and CHIP
  105. **     names must be unique.
  106. **
  107. **      NORMAL           UP           DOWN        UPSIDEDOWN
  108. **
  109. **      1 2 3            +              +          3 2 1
  110. **    +-*-*-*-+          * 3          1 *        +-*-*-*-+
  111. **                       * 2          2 *
  112. **                       * 1          3 *
  113. **                       +              +
  114. **
  115. ** 14) CUSTOM TYPE=type PACKAGE=package
  116. **     In this case package is predefined in the EXE file and can be
  117. **     one of the following strings:
  118. **         PLCC20, PLCC28, PLCC32, PLCC44, PLCC52, PLCC68, PLCC84,
  119. **         TO5, TO18, TRIMMERW, TRIMMERP, and TRIMMERY.
  120. **     These strings and the associated arrays that go with them are defined
  121. **     in the file plcc.c.  The numbers in the arrays are offsets from pin
  122. **     number 1 on a fifty mil grid.
  123. **
  124. ** 15) CUSTOMAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
  125. **     this defines an instance of an inline, and places the appropriate
  126. **     holes on the board. (row,column) is the location of pin 1. NAME defines
  127. **     the name to be used in following CONNECT statements. TYPE declares the
  128. **     CUSTOMAT-defined type of the chip. ORIENTATION can have the values
  129. **     NORMAL, UP, DOWN, and UPSIDEDOWN.  All CUSTOM, INLINE and CHIP
  130. **     names must be unique.  The directions shown below are for the
  131. **     PLCC chip carriers.
  132. **
  133. **      NORMAL           UP           DOWN        UPSIDEDOWN
  134. **
  135. **       *****          *****         **1**          *****
  136. **      *******        *******       *******        *******
  137. **      **   **        **   **       **   **        **   **
  138. **      1*   **        **   **       **   **        **   *1
  139. **      **   **        **   **       **   **        **   **
  140. **      *******        *******       *******        *******
  141. **       *****          **1**         *****          *****
  142. **
  143. **      TOxx packages:
  144. **
  145. **                       E              C
  146. **        B            B                  B          E   C
  147. **      C   E            C              E              B
  148. **
  149. **
  150. **      TRIMMERx packages:
  151. **
  152. **                       3              1
  153. **                        2                           2
  154. **      1    3                         2             3    1
  155. **          2            1              3
  156. **
  157. **     Note:  The coordinate system is left handed.  ( Positive X values
  158. **     are vertical and positive Y values are to the right.  Cell (1,1)
  159. **     denotes the lower left hand corner of the board. )
  160. **
  161. **
  162. **     X
  163. **     ^
  164. **     |
  165. **     |
  166. **     +----> Y
  167. **/
  168.  
  169. /* chip orientations (rotations) */
  170. #define ORIENT_NORMAL       1
  171. #define ORIENT_UP           2
  172. #define ORIENT_DOWN         3
  173. #define ORIENT_UPSIDEDOWN   4
  174.  
  175. /* input token types */
  176. #define TOK_EOF             1   /* end of file, no more tokens          */
  177. #define TOK_NEWLINE         2   /* end of line                          */
  178. #define TOK_NUMBER          3   /* number (digits)                      */
  179. #define TOK_HOLE            4   /* "HOLE"                               */
  180. #define TOK_ROWCOLUMN       5   /* "(row,column)"                       */
  181. #define TOK_CONNECT         6   /* "CONNECT"                            */
  182. #define TOK_EQUAL           7   /* "="                                  */
  183. #define TOK_AND             8   /* "AND"                                */
  184. #define TOK_ALPHANUM        9   /* name (letters, digits, ':','.','\')  */
  185. #define TOK_CHIP           10  /* "CHIP"                                */
  186. #define TOK_NAME           11  /* "NAME"                                */
  187. #define TOK_PINS           12  /* "PINS"                                */
  188. #define TOK_HORIZONTAL     13  /* "HORIZONTAL"                          */
  189. #define TOK_VERTICAL       14  /* "VERTICAL"                            */
  190. #define TOK_INCLUDE        15  /* "INCLUDE"                             */
  191. #define TOK_CHIPAT         16  /* "CHIPAT"                              */
  192. #define TOK_TYPE           17  /* "TYPE"                                */
  193. #define TOK_ORIENTATION    18  /* "ORIENTATION"                         */
  194. #define TOK_NORMAL         19  /* "NORMAL"                              */
  195. #define TOK_UP             20  /* "UP"                                  */
  196. #define TOK_DOWN           21  /* "DOWN"                                */
  197. #define TOK_UPSIDEDOWN     22  /* "UPSIDEDOWN"                          */
  198. #define TOK_DIMENSION      23  /* "DIMENSION"                           */
  199. #define TOK_PRIORITY       24  /* "PRIORITY"                            */
  200. #define TOK_TO             25  /* "TO"                                  */
  201. #define TOK_INLINE         26  /* "INLINE"                              */
  202. #define TOK_INLINEAT       27  /* "INLINEAT"                            */
  203. #define TOK_CUSTOM         28  /* "CUSTOM"                              */
  204. #define TOK_CUSTOMAT       29  /* "CUSTOMAT"                            */
  205. #define TOK_PACKAGE        29  /* "PACKAGE"                             */
  206.  
  207. struct reserved { /* reserved word input tokens */
  208.     char *tokenname;
  209.     int tokenvalue;
  210.     };
  211.  
  212. static struct reserved tokenmatch[] = { /* reserved word table */
  213.   { "HOLE",       TOK_HOLE       },  { "CONNECT",     TOK_CONNECT     },
  214.   { "AND",        TOK_AND        },  { "CHIP",        TOK_CHIP        },
  215.   { "NAME",       TOK_NAME       },  { "PINS",        TOK_PINS        },
  216.   { "HORIZONTAL", TOK_HORIZONTAL },  { "VERTICAL",    TOK_VERTICAL    },
  217.   { "INCLUDE",    TOK_INCLUDE    },  { "CHIPAT",      TOK_CHIPAT      },
  218.   { "TYPE",       TOK_TYPE       },  { "ORIENTATION", TOK_ORIENTATION },
  219.   { "NORMAL",     TOK_NORMAL     },  { "UP",          TOK_UP          },
  220.   { "DOWN",       TOK_DOWN       },  { "UPSIDEDOWN",  TOK_UPSIDEDOWN  },
  221.   { "DIMENSION",  TOK_DIMENSION  },  { "PRIORITY",    TOK_PRIORITY    },
  222.   { "TO",         TOK_TO         },  { "INLINE",      TOK_INLINE      },
  223.   { "INLINEAT",   TOK_INLINEAT   },  { "CUSTOM",      TOK_CUSTOM      },
  224.   { "CUSTOMAT",   TOK_CUSTOMAT   },  { "PACKAGE",     TOK_PACKAGE     }
  225.  };
  226.  
  227. #define MAXTOK  80  /* maximum token length (including null) */
  228.  
  229. static int numres = sizeof(tokenmatch) / sizeof(tokenmatch[0]);
  230. static char token[MAXTOK]; /* the current token is formed here */
  231.  
  232. struct pinassign { /* for assigning names to pins */
  233.     int         index;
  234.     char far        *name;
  235.     struct pinassign far    *next;
  236.     };
  237.  
  238. struct template { /* for "CHIP" declarations */
  239.     char far        *type;
  240.     int             pins;
  241.     int             horizontal;
  242.     int             vertical;
  243.     struct pinassign far *pinlist;
  244.     struct template far  *next;
  245.     pin            *array;
  246.     char far       *package;
  247.     };
  248.  
  249. struct instance { /* for "CHIPAT" definitions */
  250.     int         row;
  251.     int         column;
  252.     char far        *name;
  253.     struct template far *type;
  254.     int         orientation;
  255.     struct instance far *next;
  256.     };
  257.  
  258. static struct template far *chip = NULL; /* list of CHIPs */
  259. static struct instance far *chipat = NULL; /* list of CHIPATs */
  260.  
  261. extern void InitBoard( void );
  262. extern long GetCell( int, int, int );
  263. extern void SetCell( int, int, int, long );
  264. extern void InitWork( void );
  265. extern void SetWork( int, int, char far *, int, int, char far *, int );
  266. extern void SortWork( void );
  267. extern void Nomem( void );
  268.  
  269. int Initialize( char *, int );
  270. static int initfile( FILE *, char * );
  271. static void initchip( struct instance far *, char *, int );
  272. static void initinline( struct instance far *, char *, int );
  273. static void initcustom( struct instance far *, char *, int );
  274. static void locate( char *, int *, int *, char *, int );
  275. static int gettoken( FILE *, char *, int );
  276. static char far *fcopy( char * );
  277. static int same( char far *, char far * );
  278. void Report( FILE * );
  279. void partlist( struct instance far * );
  280.  
  281. int Initialize ( file, echo ) /* get hole coordinates and connections */
  282.     char *file;
  283.     int echo;
  284.     {
  285.     FILE *fp;
  286.     int tot;
  287.  
  288.     if (echo)
  289.         printf( "Enter Initialize()\n" );
  290.     if (!(fp = fopen( file, "r" ))) {
  291.         fprintf( stderr, "can't open %s\n", file );
  292.         exit( -1 );
  293.         }
  294.     InitWork(); /* clear work list */
  295.     tot = initfile( fp, file ); /* read input file(s) */
  296.     if (SortConnects)
  297.         SortWork(); /* arrange to do shortest ones first */
  298.     if (echo) {
  299.         printf( "  %lu bytes used for Board\n", Ltotal );
  300.         printf( "  %lu bytes used for Dist\n", Itotal );
  301.         printf( "  %lu bytes used for Dir\n", Ctotal );
  302.         printf( "Exit Initialize()\n" );
  303.         }
  304.     if (fclose( fp ))
  305.         fprintf( stderr, "error closing %s\n", file );
  306.     return( tot );
  307.     }
  308.  
  309. /* some useful macros (common code sequences) */
  310.  
  311. #define FileLine    { fprintf( stderr, "%s(%d): ", file, line ); }
  312.  
  313. #define GetTok(tok) ((tok) = gettoken( fp, file, line ))
  314.  
  315. #define SkipRest    { while (GetTok(tok) != TOK_EOF \
  316.                 && tok != TOK_NEWLINE) ; \
  317.             if (tok == TOK_NEWLINE) line++; }
  318.  
  319. #define SkipTokRest { while (tok != TOK_EOF && tok != TOK_NEWLINE) \
  320.                 GetTok(tok); } \
  321.             if (tok == TOK_NEWLINE) line++; \
  322.             continue;
  323.  
  324. #define CheckInit   { if (!InitBoardDone) { \
  325.                 FileLine; \
  326.                 fprintf( stderr, "need dimensions first\n" ); \
  327.                 SkipRest; \
  328.                 continue; } }
  329.  
  330. static int initfile ( fp, file ) /* read and process input file(s) */
  331.     FILE *fp;
  332.     char *file;
  333.     {
  334.     int tok, r1, c1, r2, c2, i, line;
  335.     char far *p;
  336.     char far *n1;
  337.     char far *n2;
  338.     long cell;
  339.     struct template far *p1;
  340.     struct pinassign far *p2;
  341.     struct pinassign far *p22;
  342.     struct instance far *p3;
  343.     FILE *fnew;
  344.     char *fname;
  345.     int tot = 0;
  346.     int index;  /* into custom[];  Added by Stephen Smith */
  347.  
  348.     line = 1;
  349.     while (GetTok(tok) != TOK_EOF) {
  350.         if (tok == TOK_DIMENSION) {
  351.             if (InitBoardDone) { /* can only do it once */
  352.                 FileLine;
  353.                 fprintf( stderr,
  354.                     "redundant dimensions\n" );
  355.                 SkipRest;
  356.                 continue;
  357.                 }
  358.             if (GetTok(tok) != TOK_ROWCOLUMN) {
  359.                 FileLine;
  360.                 fprintf( stderr, "expect (row,column)\n" );
  361.                 SkipTokRest;
  362.                 }
  363.             sscanf( token, "(%d,%d)", &Nrows, &Ncols );
  364.             if (Nrows <= 0 || Ncols <= 0) {
  365.                 FileLine;
  366.                 fprintf( stderr, "dimension error\n" );
  367.                 }
  368.             else /* allocate memory for data structures */
  369.                 InitBoard();
  370.             }
  371.         else if (tok == TOK_HOLE) {
  372.             CheckInit; /* must get dimensions first */
  373.             if (GetTok(tok) != TOK_ROWCOLUMN) {
  374.                 FileLine;
  375.                 fprintf( stderr, "expect (row,column)\n" );
  376.                 SkipTokRest;
  377.                 }
  378.             sscanf( token, "(%d,%d)", &r1, &c1 );
  379.             if (r1 <= 0 || r1 > Nrows || c1 <= 0 || c1 > Ncols) {
  380.                 FileLine;
  381.                 fprintf( stderr, "out of range\n" );
  382.                 }
  383.             else { /* position the hole on the board */
  384.                 /* should check for neighbor holes (error) */
  385.                 SetCell( r1-1, c1-1, TOP, HOLE );
  386.                 SetCell( r1-1, c1-1, BOTTOM, HOLE );
  387.                 }
  388.             }
  389.         else if (tok == TOK_CONNECT) {
  390.             CheckInit; /* must get dimensions first */
  391.             if (GetTok(tok) == TOK_ROWCOLUMN)
  392.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  393.             else if (tok == TOK_ALPHANUM)
  394.                 locate( token, &r1, &c1, file, line );
  395.             else {
  396.                 FileLine;
  397.                 fprintf( stderr,
  398.                     "expect (row,column) or name\n" );
  399.                 SkipTokRest;
  400.                 }
  401.             n1 = fcopy( token );
  402.             if (GetTok(tok) != TOK_EQUAL
  403.                 && tok != TOK_AND && tok != TOK_TO) {
  404.                 FileLine;
  405.                 fprintf( stderr, "expect = or AND or TO\n" );
  406.                 SkipTokRest;
  407.                 }
  408.             if (GetTok(tok) == TOK_ROWCOLUMN)
  409.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  410.             else if (tok == TOK_ALPHANUM)
  411.                 locate( token, &r2, &c2, file, line );
  412.             else {
  413.                 FileLine;
  414.                 fprintf( stderr,
  415.                     "expect (row,column) or name\n" );
  416.                 SkipTokRest;
  417.                 }
  418.             n2 = fcopy( token );
  419.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  420.                 || c1 <= 0 || c1 > Ncols
  421.                 || c2 <= 0 || c2 > Ncols) {
  422.                 FileLine;
  423.                 fprintf( stderr, "out of range\n" );
  424.                 farfree( n1 );
  425.                 farfree( n2 );
  426.                 }
  427.             else {
  428.                 cell = GetCell( r1-1, c1-1, TOP );
  429.                 if (!(cell & HOLE)) {
  430.                     FileLine;
  431.                     fprintf( stderr, "no source hole\n" );
  432.                     farfree( n1 );
  433.                     farfree( n2 );
  434.                     SkipRest;
  435.                     continue;
  436.                     }
  437.                 cell = GetCell( r2-1, c2-1, TOP );
  438.                 if (!(cell & HOLE)) {
  439.                     FileLine;
  440.                     fprintf( stderr, "no target hole\n" );
  441.                     farfree( n1 );
  442.                     farfree( n2 );
  443.                     SkipRest;
  444.                     continue;
  445.                     }
  446.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 0 );
  447.                 tot++;
  448.                 }
  449.             }
  450.         else if (tok == TOK_PRIORITY) {
  451.             CheckInit; /* must get dimensions first */
  452.             if (GetTok(tok) != TOK_CONNECT) {
  453.                 FileLine;
  454.                 fprintf( stderr, "expect CONNECT\n" );
  455.                 SkipTokRest;
  456.                 }
  457.             if (GetTok(tok) == TOK_ROWCOLUMN)
  458.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  459.             else if (tok == TOK_ALPHANUM)
  460.                 locate( token, &r1, &c1, file, line );
  461.             else {
  462.                 FileLine;
  463.                 fprintf( stderr,
  464.                     "expect (row,column) or name\n" );
  465.                 SkipTokRest;
  466.                 }
  467.             n1 = fcopy( token );
  468.             if (GetTok(tok) != TOK_EQUAL
  469.                 && tok != TOK_AND && tok != TOK_TO) {
  470.                 FileLine;
  471.                 fprintf( stderr, "expect = or AND or TO\n" );
  472.                 SkipTokRest;
  473.                 }
  474.             if (GetTok(tok) == TOK_ROWCOLUMN)
  475.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  476.             else if (tok == TOK_ALPHANUM)
  477.                 locate( token, &r2, &c2, file, line );
  478.             else {
  479.                 FileLine;
  480.                 fprintf( stderr,
  481.                     "expect (row,column) or name\n" );
  482.                 SkipTokRest;
  483.                 }
  484.             n2 = fcopy( token );
  485.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  486.                 || c1 <= 0 || c1 > Ncols
  487.                 || c2 <= 0 || c2 > Ncols) {
  488.                 FileLine;
  489.                 fprintf( stderr, "out of range\n" );
  490.                 farfree( n1 );
  491.                 farfree( n2 );
  492.                 }
  493.             else {
  494.                 cell = GetCell( r1-1, c1-1, TOP );
  495.                 if (!(cell & HOLE)) {
  496.                     FileLine;
  497.                     fprintf( stderr, "no source hole\n" );
  498.                     farfree( n1 );
  499.                     farfree( n2 );
  500.                     SkipRest;
  501.                     continue;
  502.                     }
  503.                 cell = GetCell( r2-1, c2-1, TOP );
  504.                 if (!(cell & HOLE)) {
  505.                     FileLine;
  506.                     fprintf( stderr, "no target hole\n" );
  507.                     farfree( n1 );
  508.                     farfree( n2 );
  509.                     SkipRest;
  510.                     continue;
  511.                     }
  512.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 1 );
  513.                 tot++;
  514.                 }
  515.             }
  516.         else if (tok == TOK_INCLUDE) {
  517.             CheckInit; /* must get dimensions first */
  518.             if (GetTok(tok) != TOK_ALPHANUM) {
  519.                 FileLine;
  520.                 fprintf( stderr,
  521.                     "expect file name for INCLUDE\n" );
  522.                 SkipTokRest;
  523.                 }
  524.             if (!(fnew = fopen( token, "r" ))) {
  525.                 FileLine;
  526.                 fprintf( stderr,
  527.                     "can't open INCLUDE file %s\n",
  528.                     token );
  529.                 SkipRest;
  530.                 continue;
  531.                 }
  532.             if (!(fname = strdup( token )))
  533.                 Nomem();
  534.             if (GetTok(tok) != TOK_EOF
  535.                 && tok != TOK_NEWLINE) {
  536.                 FileLine;
  537.                 fprintf( stderr,
  538.                     "extra chars on INCLUDE line\n" );
  539.                 SkipRest;
  540.                 }
  541.             if (tok == TOK_NEWLINE)
  542.                 line++;
  543.             tot += initfile( fnew, fname ); /* recurse */
  544.             if (fclose( fnew )) {
  545.                 FileLine;
  546.                 fprintf( stderr,
  547.                     "error closing INCLUDE file\n" );
  548.                 }
  549.             free( fname );
  550.             continue; /* already ate the NEWLINE, if any */
  551.             }
  552.         else if (tok == TOK_CHIP) {
  553.             CheckInit; /* must get dimensions first */
  554.             if (GetTok(tok) != TOK_TYPE
  555.                 || GetTok(tok) != TOK_EQUAL
  556.                 || GetTok(tok) != TOK_ALPHANUM) {
  557.                 FileLine;
  558.                 fprintf( stderr, "expect TYPE=type\n" );
  559.                 SkipTokRest;
  560.                 }
  561.             if (!(p1 = (struct template far *)
  562.                 farmalloc( sizeof(struct template) )))
  563.                 Nomem();
  564.             p1->type = fcopy( token );
  565.             if (GetTok(tok) != TOK_PINS
  566.                 || GetTok(tok) != TOK_EQUAL
  567.                 || GetTok(tok) != TOK_NUMBER) {
  568.                 FileLine;
  569.                 fprintf( stderr, "expect PINS=number\n" );
  570.                 farfree( p1->type );
  571.                 farfree( p1 );
  572.                 SkipTokRest;
  573.                 }
  574.             sscanf( token, "%d", &i );
  575.             p1->pins = i;
  576.             if ((p1->pins = i) < 0 || (i & 1)) {
  577.                 FileLine;
  578.                 fprintf( stderr, "PINS negative or odd\n" );
  579.                 }
  580.             if (GetTok(tok) != TOK_HORIZONTAL
  581.                 || GetTok(tok) != TOK_EQUAL
  582.                 || GetTok(tok) != TOK_NUMBER) {
  583.                 FileLine;
  584.                 fprintf( stderr,
  585.                     "expect HORIZONTAL=number\n" );
  586.                 farfree( p1->type );
  587.                 farfree( p1 );
  588.                 SkipTokRest;
  589.                 }
  590.             sscanf( token, "%d", &i );
  591.             if ((p1->horizontal = i) <= 0) {
  592.                 FileLine;
  593.                 fprintf( stderr, "HORIZONTAL nonpositive\n" );
  594.                 }
  595.             if (GetTok(tok) != TOK_VERTICAL
  596.                 || GetTok(tok) != TOK_EQUAL
  597.                 || GetTok(tok) != TOK_NUMBER) {
  598.                 FileLine;
  599.                 fprintf( stderr, "expect VERTICAL=number\n" );
  600.                 farfree( p1->type );
  601.                 farfree( p1 );
  602.                 SkipTokRest;
  603.                 }
  604.             sscanf( token, "%d", &i );
  605.             if ((p1->vertical = i) < 0) {
  606.                 FileLine;
  607.                 fprintf( stderr, "VERTICAL nonpositive\n" );
  608.                 }
  609.             if( PartsList )
  610.             {
  611.                 if (GetTok(tok) != TOK_PACKAGE
  612.                     || GetTok(tok) != TOK_EQUAL
  613.                     || GetTok(tok) != TOK_ALPHANUM) {
  614.                     FileLine;
  615.                     fprintf( stderr, "expect PACKAGE=type\n" );
  616.                     SkipTokRest;
  617.                     }
  618.                 p1->package = fcopy( token );
  619.             }
  620.             else
  621.                p1->package = fcopy("");
  622.             p1->pinlist = NULL;
  623.             p1->array = NULL;
  624.             p1->next = chip;
  625.             chip = p1;
  626.             }
  627.         else if (tok == TOK_INLINE) {
  628.             CheckInit; /* must get dimensions first */
  629.             if (GetTok(tok) != TOK_TYPE
  630.                 || GetTok(tok) != TOK_EQUAL
  631.                 || GetTok(tok) != TOK_ALPHANUM) {
  632.                 FileLine;
  633.                 fprintf( stderr, "expect TYPE=type\n" );
  634.                 SkipTokRest;
  635.                 }
  636.             if (!(p1 = (struct template far *)
  637.                 farmalloc( sizeof(struct template) )))
  638.                 Nomem();
  639.             p1->type = fcopy( token );
  640.             if (GetTok(tok) != TOK_PINS
  641.                 || GetTok(tok) != TOK_EQUAL
  642.                 || GetTok(tok) != TOK_NUMBER) {
  643.                 FileLine;
  644.                 fprintf( stderr, "expect PINS=number\n" );
  645.                 farfree( p1->type );
  646.                 farfree( p1 );
  647.                 SkipTokRest;
  648.                 }
  649.             sscanf( token, "%d", &i );
  650.             p1->pins = i;
  651.             if (GetTok(tok) != TOK_HORIZONTAL
  652.                 || GetTok(tok) != TOK_EQUAL
  653.                 || GetTok(tok) != TOK_NUMBER) {
  654.                 FileLine;
  655.                 fprintf( stderr,
  656.                     "expect HORIZONTAL=number\n" );
  657.                 farfree( p1->type );
  658.                 farfree( p1 );
  659.                 SkipTokRest;
  660.                 }
  661.             sscanf( token, "%d", &i );
  662.             if ((p1->horizontal = i) <= 0) {
  663.                 FileLine;
  664.                 fprintf( stderr, "HORIZONTAL nonpositive\n" );
  665.                 }
  666.             if( PartsList )
  667.             {
  668.                 if (GetTok(tok) != TOK_PACKAGE
  669.                     || GetTok(tok) != TOK_EQUAL
  670.                     || GetTok(tok) != TOK_ALPHANUM) {
  671.                     FileLine;
  672.                     fprintf( stderr, "expect PACKAGE=type\n" );
  673.                     SkipTokRest;
  674.                     }
  675.                 p1->package = fcopy( token );
  676.             }
  677.             else
  678.                p1->package = fcopy("");
  679.             p1->vertical = 0;
  680.             p1->pinlist = NULL;
  681.             p1->array = NULL;
  682.             p1->next = chip;
  683.             chip = p1;
  684.             }
  685.         else if (tok == TOK_CUSTOM) {
  686.             CheckInit; /* must get dimensions first */
  687.             if (GetTok(tok) != TOK_TYPE
  688.                 || GetTok(tok) != TOK_EQUAL
  689.                 || GetTok(tok) != TOK_ALPHANUM) {
  690.                 FileLine;
  691.                 fprintf( stderr, "expect TYPE=type\n" );
  692.                 SkipTokRest;
  693.                 }
  694.             if (!(p1 = (struct template far *)
  695.                 farmalloc( sizeof(struct template) )))
  696.                 Nomem();
  697.             p1->type = fcopy( token );
  698.             if (GetTok(tok) != TOK_PACKAGE
  699.                 || GetTok(tok) != TOK_EQUAL
  700.                 || GetTok(tok) != TOK_ALPHANUM) {
  701.                 FileLine;
  702.                 fprintf( stderr, "expect PACKAGE=type\n" );
  703.                 SkipTokRest;
  704.                 }
  705.             p1->package = fcopy( token );
  706.             i = 0;
  707.             index = 0;
  708.             while( i == 0 )
  709.                if ( strcmp( token, custom[index].string ) != 0 )
  710.                      index++;
  711.                else
  712.                   {
  713.                      i = custom[index].array_len;
  714.                      p1->array = custom[index].offset;
  715.                      p1->vertical = 0;
  716.                      p1->horizontal = 0;
  717.                   }
  718.             if ( index == custom_len )
  719.                {
  720.                   FileLine;
  721.                   fprintf( stderr, "custom part isn\'t part of"
  722.                            "this package\n" );
  723.                   SkipRest;
  724.                   continue;
  725.                }
  726.             p1->pins = i;
  727.             p1->pinlist = NULL;
  728.             p1->next = chip;
  729.             chip = p1;
  730.             }
  731.         else if (tok == TOK_NUMBER) {
  732.             CheckInit; /* must get dimensions first */
  733.             if (!chip) {
  734.                 FileLine;
  735.                 fprintf( stderr, "no template\n" );
  736.                 SkipRest;
  737.                 continue;
  738.                 }
  739.             sscanf( token, "%d", &i );
  740.             if (GetTok(tok) != TOK_EQUAL
  741.                 || GetTok(tok) != TOK_ALPHANUM) {
  742.                 FileLine;
  743.                 fprintf( stderr, "expect number=name\n" );
  744.                 SkipTokRest;
  745.                 }
  746.             if (!(p2 = (struct pinassign far *)
  747.                 farmalloc( sizeof(struct pinassign) )))
  748.                 Nomem();
  749.             p2->name = fcopy( token );
  750.             p2->index = i;
  751.             /* check uniqueness of name and index */
  752.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  753.                 if (p22->index == i
  754.                     || same( p22->name, p )) {
  755.                     FileLine;
  756.                     fprintf( stderr,
  757.                         "warning: repeated pin\n" );
  758.                     break;
  759.                     }
  760.             p2->next = chip->pinlist;
  761.             chip->pinlist = p2;
  762.             }
  763.         else if (tok == TOK_ALPHANUM) {
  764.             CheckInit; /* must get dimensions first */
  765.             if (!chip) {
  766.                 FileLine;
  767.                 fprintf( stderr, "no template\n" );
  768.                 SkipRest;
  769.                 continue;
  770.                 }
  771.             p = fcopy( token );
  772.             if (GetTok(tok) != TOK_EQUAL
  773.                 || GetTok(tok) != TOK_NUMBER) {
  774.                 FileLine;
  775.                 fprintf( stderr, "expect name=number\n" );
  776.                 farfree( p );
  777.                 SkipTokRest;
  778.                 }
  779.             sscanf( token, "%d", &i );
  780.             if (!(p2 = (struct pinassign far *)
  781.                 farmalloc( sizeof(struct pinassign) )))
  782.                 Nomem();
  783.             p2->name = p;
  784.             p2->index = i;
  785.             /* check uniqueness of name and index */
  786.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  787.                 if (p22->index == i
  788.                     || same( p22->name, p )) {
  789.                     FileLine;
  790.                     fprintf( stderr,
  791.                         "warning: repeated pin\n" );
  792.                     break;
  793.                     }
  794.             p2->next = chip->pinlist;
  795.             chip->pinlist = p2;
  796.             }
  797.         else if (tok == TOK_CHIPAT) {
  798.             CheckInit; /* must get dimensions first */
  799.             if (GetTok(tok) != TOK_ROWCOLUMN) {
  800.                 FileLine;
  801.                 fprintf( stderr, "expect (row,column)\n" );
  802.                 SkipTokRest;
  803.                 }
  804.             sscanf( token, "(%d,%d)", &r1, &c1 );
  805.             if (GetTok(tok) != TOK_NAME
  806.                 || GetTok(tok) != TOK_EQUAL
  807.                 || GetTok(tok) != TOK_ALPHANUM) {
  808.                 FileLine;
  809.                 fprintf( stderr, "expect NAME=name\n" );
  810.                 SkipTokRest;
  811.                 }
  812.             if (!(p3 = (struct instance far *)
  813.                 farmalloc( sizeof(struct instance) )))
  814.                 Nomem();
  815.             p3->name = fcopy( token );
  816.             p3->row = r1;
  817.             p3->column = c1;
  818.             if (GetTok(tok) != TOK_TYPE
  819.                 || GetTok(tok) != TOK_EQUAL
  820.                 || GetTok(tok) != TOK_ALPHANUM) {
  821.                 FileLine;
  822.                 fprintf( stderr, "expect TYPE=type\n" );
  823.                 farfree( p3->name );
  824.                 farfree( p3 );
  825.                 SkipTokRest;
  826.                 }
  827.             for (p3->type = chip; p3->type;
  828.                 p3->type = p3->type->next)
  829.                 if (same( token, p3->type->type ))
  830.                     break;
  831.             if (!(p3->type)) {
  832.                 FileLine;
  833.                 fprintf( stderr,
  834.                     "couldn't find chip type\n" );
  835.                 farfree( p3->name );
  836.                 farfree( p3 );
  837.                 SkipTokRest;
  838.                 }
  839.             if (GetTok(tok) != TOK_ORIENTATION
  840.                 || GetTok(tok) != TOK_EQUAL
  841.                 || (GetTok(tok) != TOK_NORMAL
  842.                 && tok != TOK_UP && tok != TOK_DOWN
  843.                 && tok != TOK_UPSIDEDOWN)) {
  844.                 FileLine;
  845.                 fprintf( stderr,
  846.                     "expect ORIENTATION=orientation\n" );
  847.                 farfree( p3->name );
  848.                 farfree( p3 );
  849.                 SkipTokRest;
  850.                 }
  851.             switch (tok) {
  852.             case TOK_NORMAL:
  853.                 p3->orientation = ORIENT_NORMAL;    break;
  854.             case TOK_UP:
  855.                 p3->orientation = ORIENT_UP;        break;
  856.             case TOK_DOWN:
  857.                 p3->orientation = ORIENT_DOWN;      break;
  858.             case TOK_UPSIDEDOWN:
  859.                 p3->orientation = ORIENT_UPSIDEDOWN;    break;
  860.             default:
  861.                 FileLine;
  862.                 fprintf( stderr, "internal error\n" );
  863.                 exit( -1 );
  864.                 break;
  865.                 }
  866.             p3->next = chipat;
  867.             chipat = p3;
  868.             initchip( p3, file, line );
  869.             }
  870.         else if (tok == TOK_INLINEAT) {
  871.             CheckInit; /* must get dimensions first */
  872.             if (GetTok(tok) != TOK_ROWCOLUMN) {
  873.                 FileLine;
  874.                 fprintf( stderr, "expect (row,column)\n" );
  875.                 SkipTokRest;
  876.                 }
  877.             sscanf( token, "(%d,%d)", &r1, &c1 );
  878.             if (GetTok(tok) != TOK_NAME
  879.                 || GetTok(tok) != TOK_EQUAL
  880.                 || GetTok(tok) != TOK_ALPHANUM) {
  881.                 FileLine;
  882.                 fprintf( stderr, "expect NAME=name\n" );
  883.                 SkipTokRest;
  884.                 }
  885.             if (!(p3 = (struct instance far *)
  886.                 farmalloc( sizeof(struct instance) )))
  887.                 Nomem();
  888.             p3->name = fcopy( token );
  889.             p3->row = r1;
  890.             p3->column = c1;
  891.             if (GetTok(tok) != TOK_TYPE
  892.                 || GetTok(tok) != TOK_EQUAL
  893.                 || GetTok(tok) != TOK_ALPHANUM) {
  894.                 FileLine;
  895.                 fprintf( stderr, "expect TYPE=type\n" );
  896.                 farfree( p3->name );
  897.                 farfree( p3 );
  898.                 SkipTokRest;
  899.                 }
  900.             for (p3->type = chip; p3->type;
  901.                 p3->type = p3->type->next)
  902.                 if (same( token, p3->type->type ))
  903.                     break;
  904.             if (!(p3->type)) {
  905.                 FileLine;
  906.                 fprintf( stderr,
  907.                     "couldn't find chip type\n" );
  908.                 farfree( p3->name );
  909.                 farfree( p3 );
  910.                 SkipTokRest;
  911.                 }
  912.             if (GetTok(tok) != TOK_ORIENTATION
  913.                 || GetTok(tok) != TOK_EQUAL
  914.                 || (GetTok(tok) != TOK_NORMAL
  915.                 && tok != TOK_UP && tok != TOK_DOWN
  916.                 && tok != TOK_UPSIDEDOWN)) {
  917.                 FileLine;
  918.                 fprintf( stderr,
  919.                     "expect ORIENTATION=orientation\n" );
  920.                 farfree( p3->name );
  921.                 farfree( p3 );
  922.                 SkipTokRest;
  923.                 }
  924.             switch (tok) {
  925.             case TOK_NORMAL:
  926.                 p3->orientation = ORIENT_NORMAL;    break;
  927.             case TOK_UP:
  928.                 p3->orientation = ORIENT_UP;        break;
  929.             case TOK_DOWN:
  930.                 p3->orientation = ORIENT_DOWN;      break;
  931.             case TOK_UPSIDEDOWN:
  932.                 p3->orientation = ORIENT_UPSIDEDOWN;    break;
  933.             default:
  934.                 FileLine;
  935.                 fprintf( stderr, "internal error\n" );
  936.                 exit( -1 );
  937.                 break;
  938.                 }
  939.             p3->next = chipat;
  940.             chipat = p3;
  941.             initinline( p3, file, line );
  942.             }
  943.         else if (tok == TOK_CUSTOMAT) {
  944.             CheckInit; /* must get dimensions first */
  945.             if (GetTok(tok) != TOK_ROWCOLUMN) {
  946.                 FileLine;
  947.                 fprintf( stderr, "expect (row,column)\n" );
  948.                 SkipTokRest;
  949.                 }
  950.             sscanf( token, "(%d,%d)", &r1, &c1 );
  951.             if (GetTok(tok) != TOK_NAME
  952.                 || GetTok(tok) != TOK_EQUAL
  953.                 || GetTok(tok) != TOK_ALPHANUM) {
  954.                 FileLine;
  955.                 fprintf( stderr, "expect NAME=name\n" );
  956.                 SkipTokRest;
  957.                 }
  958.             if (!(p3 = (struct instance far *)
  959.                 farmalloc( sizeof(struct instance) )))
  960.                 Nomem();
  961.             p3->name = fcopy( token );
  962.             p3->row = r1;
  963.             p3->column = c1;
  964.             if (GetTok(tok) != TOK_TYPE
  965.                 || GetTok(tok) != TOK_EQUAL
  966.                 || GetTok(tok) != TOK_ALPHANUM) {
  967.                 FileLine;
  968.                 fprintf( stderr, "expect TYPE=type\n" );
  969.                 farfree( p3->name );
  970.                 farfree( p3 );
  971.                 SkipTokRest;
  972.                 }
  973.             for (p3->type = chip; p3->type;
  974.                 p3->type = p3->type->next)
  975.                 if (same( token, p3->type->type ))
  976.                     break;
  977.             if (!(p3->type)) {
  978.                 FileLine;
  979.                 fprintf( stderr,
  980.                     "couldn't find chip type\n" );
  981.                 farfree( p3->name );
  982.                 farfree( p3 );
  983.                 SkipTokRest;
  984.                 }
  985.             if (GetTok(tok) != TOK_ORIENTATION
  986.                 || GetTok(tok) != TOK_EQUAL
  987.                 || (GetTok(tok) != TOK_NORMAL
  988.                 && tok != TOK_UP && tok != TOK_DOWN
  989.                 && tok != TOK_UPSIDEDOWN)) {
  990.                 FileLine;
  991.                 fprintf( stderr,
  992.                     "expect ORIENTATION=orientation\n" );
  993.                 farfree( p3->name );
  994.                 farfree( p3 );
  995.                 SkipTokRest;
  996.                 }
  997.             switch (tok) {
  998.             case TOK_NORMAL:
  999.                 p3->orientation = ORIENT_NORMAL;    break;
  1000.             case TOK_UP:
  1001.                 p3->orientation = ORIENT_UP;        break;
  1002.             case TOK_DOWN:
  1003.                 p3->orientation = ORIENT_DOWN;      break;
  1004.             case TOK_UPSIDEDOWN:
  1005.                 p3->orientation = ORIENT_UPSIDEDOWN;    break;
  1006.             default:
  1007.                 FileLine;
  1008.                 fprintf( stderr, "internal error\n" );
  1009.                 exit( -1 );
  1010.                 break;
  1011.                 }
  1012.             p3->next = chipat;
  1013.             chipat = p3;
  1014.             initcustom( p3, file, line );
  1015.             }
  1016.         else if (tok == TOK_NEWLINE) {
  1017.             line++;
  1018.             continue;
  1019.             }
  1020.         else { /* something unexpected */
  1021.             FileLine;
  1022.             fprintf( stderr, "syntax error: unexpected input\n" );
  1023.             }
  1024.         if (GetTok(tok) != TOK_EOF
  1025.             && tok != TOK_NEWLINE) {
  1026.             FileLine;
  1027.             fprintf( stderr,
  1028.                 "syntax error: expected end of line\n" );
  1029.             SkipRest;
  1030.             }
  1031.         else if (tok == TOK_NEWLINE)
  1032.             line++;
  1033.         }
  1034.     if ( PartsList) partlist(chipat);
  1035.     return( tot );
  1036.     }
  1037.  
  1038. static void initchip ( p, file, line ) /* init chip definition (make holes) */
  1039.     struct instance far *p;
  1040.     char *file;
  1041.     int line;
  1042.     {
  1043.     int r, c, pin;
  1044.     struct template far *t;
  1045.  
  1046.     pin = 1;
  1047.     r = p->row;
  1048.     c = p->column;
  1049.     t = p->type;
  1050.     /* should check for neighboring holes (warning if so) */
  1051.     switch (p->orientation) {
  1052.     case ORIENT_NORMAL:
  1053.         while (pin <= t->pins / 2) {
  1054.             SetCell( r-1, c-1, TOP, HOLE );
  1055.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1056.             pin++;
  1057.             c += t->horizontal;
  1058.             }
  1059.         c -= t->horizontal;
  1060.         r += t->vertical;
  1061.         while (pin <= t->pins) {
  1062.             SetCell( r-1, c-1, TOP, HOLE );
  1063.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1064.             pin++;
  1065.             c -= t->horizontal;
  1066.             }
  1067.         break;
  1068.     case ORIENT_UP:
  1069.         while (pin <= t->pins / 2) {
  1070.             SetCell( r-1, c-1, TOP, HOLE );
  1071.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1072.             pin++;
  1073.             r += t->horizontal;
  1074.             }
  1075.         r -= t->horizontal;
  1076.         c -= t->vertical;
  1077.         while (pin <= t->pins) {
  1078.             SetCell( r-1, c-1, TOP, HOLE );
  1079.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1080.             pin++;
  1081.             r -= t->horizontal;
  1082.             }
  1083.         break;
  1084.     case ORIENT_DOWN:
  1085.         while (pin <= t->pins / 2) {
  1086.             SetCell( r-1, c-1, TOP, HOLE );
  1087.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1088.             pin++;
  1089.             r -= t->horizontal;
  1090.             }
  1091.         r += t->horizontal;
  1092.         c += t->vertical;
  1093.         while (pin <= t->pins) {
  1094.             SetCell( r-1, c-1, TOP, HOLE );
  1095.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1096.             pin++;
  1097.             r += t->horizontal;
  1098.             }
  1099.         break;
  1100.     case ORIENT_UPSIDEDOWN:
  1101.         while (pin <= t->pins / 2) {
  1102.             SetCell( r-1, c-1, TOP, HOLE );
  1103.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1104.             pin++;
  1105.             c -= t->horizontal;
  1106.             }
  1107.         c += t->horizontal;
  1108.         r -= t->vertical;
  1109.         while (pin <= t->pins) {
  1110.             SetCell( r-1, c-1, TOP, HOLE );
  1111.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1112.             pin++;
  1113.             c += t->horizontal;
  1114.             }
  1115.         break;
  1116.     default:
  1117.         FileLine;
  1118.         fprintf( stderr, "internal error: unexpected orientation\n" );
  1119.         exit( -1 );
  1120.         break;
  1121.         }
  1122.     }
  1123.  
  1124. static void initinline( p, file, line ) /* init inline definition (make holes) */
  1125.     struct instance far *p;
  1126.     char *file;
  1127.     int line;
  1128.     {
  1129.     int r, c, pin;
  1130.     struct template far *t;
  1131.  
  1132.     pin = 1;
  1133.     r = p->row;
  1134.     c = p->column;
  1135.     t = p->type;
  1136.     /* should check for neighboring holes (warning if so) */
  1137.     switch (p->orientation) {
  1138.     case ORIENT_NORMAL:
  1139.         while (pin <= t->pins) {
  1140.             SetCell( r-1, c-1, TOP, HOLE );
  1141.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1142.             pin++;
  1143.             c += t->horizontal;
  1144.             }
  1145.         break;
  1146.     case ORIENT_UP:
  1147.         while (pin <= t->pins) {
  1148.             SetCell( r-1, c-1, TOP, HOLE );
  1149.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1150.             pin++;
  1151.             r += t->horizontal;
  1152.             }
  1153.         break;
  1154.     case ORIENT_DOWN:
  1155.         while (pin <= t->pins) {
  1156.             SetCell( r-1, c-1, TOP, HOLE );
  1157.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1158.             pin++;
  1159.             r -= t->horizontal;
  1160.             }
  1161.         break;
  1162.     case ORIENT_UPSIDEDOWN:
  1163.         while (pin <= t->pins) {
  1164.             SetCell( r-1, c-1, TOP, HOLE );
  1165.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1166.             pin++;
  1167.             c -= t->horizontal;
  1168.             }
  1169.         break;
  1170.     default:
  1171.         FileLine;
  1172.         fprintf( stderr, "internal error: unexpected orientation\n" );
  1173.         exit( -1 );
  1174.         break;
  1175.         }
  1176.     }
  1177.  
  1178. static void initcustom( p, file, line ) /* init custom definition (make holes) */
  1179.     struct instance far *p;
  1180.     char *file;
  1181.     int line;
  1182.     {
  1183.     int r, c, row, col, pin;
  1184.     struct template far *t;
  1185.  
  1186.     pin = 0;
  1187.     row = r = p->row;
  1188.     col = c = p->column;
  1189.     t = p->type;
  1190.     /* should check for neighboring holes (warning if so) */
  1191.     switch (p->orientation) {
  1192.     case ORIENT_NORMAL:
  1193.         while (pin < t->pins) {
  1194.             SetCell( r-1, c-1, TOP, HOLE );
  1195.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1196.             pin++;
  1197.             c = col + (t->array+pin)->c;
  1198.             r = row + (t->array+pin)->r;
  1199.             }
  1200.         break;
  1201.     case ORIENT_UP:
  1202.         while (pin < t->pins) {
  1203.             SetCell( r-1, c-1, TOP, HOLE );
  1204.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1205.             pin++;
  1206.             r = row + (t->array+pin)->c;
  1207.             c = col - (t->array+pin)->r;
  1208.             }
  1209.         break;
  1210.     case ORIENT_DOWN:
  1211.         while (pin < t->pins) {
  1212.             SetCell( r-1, c-1, TOP, HOLE );
  1213.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1214.             pin++;
  1215.             r = row - (t->array+pin)->c;
  1216.             c = col + (t->array+pin)->r;
  1217.             }
  1218.         break;
  1219.     case ORIENT_UPSIDEDOWN:
  1220.         while (pin < t->pins) {
  1221.             SetCell( r-1, c-1, TOP, HOLE );
  1222.             SetCell( r-1, c-1, BOTTOM, HOLE );
  1223.             pin++;
  1224.             r = row - (t->array+pin)->r;
  1225.             c = col - (t->array+pin)->c;
  1226.             }
  1227.         break;
  1228.     default:
  1229.         FileLine;
  1230.         fprintf( stderr, "internal error: unexpected orientation\n" );
  1231.         exit( -1 );
  1232.         break;
  1233.         }
  1234.     }
  1235.  
  1236.  
  1237. static void locate ( p, r, c, file, line )
  1238.     /* find location of name1.{name2,number} */
  1239.     char *p;
  1240.     int *r, *c;
  1241.     char *file;
  1242.     int line;
  1243.     {
  1244.     char *q;
  1245.     int i;
  1246.     struct instance far *s;
  1247.     struct pinassign far *t;
  1248.  
  1249.     if (!(q = strchr( p, '.' ))) {
  1250.         FileLine;
  1251.         fprintf( stderr, "expect name1.{name2,number}\n" );
  1252.         return;
  1253.         }
  1254.     *q++ = 0; /* separate into two parts & point at second part */
  1255.     for (s = chipat; s; s = s->next) /* find proper chip */
  1256.         if (same( p, s->name ))
  1257.             break;
  1258.     if (!s || !(s->type)) {
  1259.         FileLine;
  1260.         fprintf( stderr, "can't find chip or chip type: %s\n", p );
  1261.         fprintf( stdout, "\n" );
  1262.         return;
  1263.         }
  1264.     if (isdigit( *q )) { /* get pin number */
  1265.         i = atoi( q );
  1266.         if (i <= 0 || i > s->type->pins) {
  1267.             FileLine;
  1268.             fprintf( stderr, "pin out of range\n" );
  1269.             return;
  1270.             }
  1271.         }
  1272.     else { /* get index of named pin via the template */
  1273.         for (t = s->type->pinlist; t; t = t->next)
  1274.             if (same( q, t->name ))
  1275.                 break;
  1276.         if (!t) {
  1277.             FileLine;
  1278.             fprintf( stderr, "can't find pin\n" );
  1279.             return;
  1280.             }
  1281.         i = t->index;
  1282.         }
  1283.     *r = s->row;
  1284.     *c = s->column;
  1285.     if( s->type->array == NULL )
  1286.        {
  1287.        switch (s->orientation) {
  1288.        case ORIENT_NORMAL:
  1289.            if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
  1290.                *c += (i-1) * s->type->horizontal;
  1291.            else {
  1292.                *r += s->type->vertical;
  1293.                *c += (s->type->pins - i) * s->type->horizontal;
  1294.                }
  1295.            break;
  1296.        case ORIENT_UP:
  1297.            if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
  1298.                *r += (i-1) * s->type->horizontal;
  1299.            else {
  1300.                *c -= s->type->vertical;
  1301.                *r += (s->type->pins - i) * s->type->horizontal;
  1302.                }
  1303.            break;
  1304.        case ORIENT_DOWN:
  1305.            if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
  1306.                *r -= (i-1) * s->type->horizontal;
  1307.            else {
  1308.                *c += s->type->vertical;
  1309.                *r -= (s->type->pins - i) * s->type->horizontal;
  1310.                }
  1311.            break;
  1312.        case ORIENT_UPSIDEDOWN:
  1313.            if ((i <= s->type->pins / 2) || (s->type->vertical == 0))
  1314.                *c -= (i-1) * s->type->horizontal;
  1315.            else {
  1316.                *r -= s->type->vertical;
  1317.                *c -= (s->type->pins - i) * s->type->horizontal;
  1318.                }
  1319.            break;
  1320.        default:
  1321.            FileLine;
  1322.            fprintf( stderr, "internal error: unexpected orientation\n" );
  1323.            exit( -1 );
  1324.            break;
  1325.            }
  1326.        }
  1327.     else
  1328.        {
  1329.        switch (s->orientation) {
  1330.        case ORIENT_NORMAL:
  1331.                *r += (s->type->array+i-1)->r;
  1332.                *c += (s->type->array+i-1)->c;
  1333.            break;
  1334.        case ORIENT_UP:
  1335.                *c -= (s->type->array+i-1)->r;
  1336.                *r += (s->type->array+i-1)->c;
  1337.            break;
  1338.        case ORIENT_DOWN:
  1339.                *c += (s->type->array+i-1)->r;
  1340.                *r -= (s->type->array+i-1)->c;
  1341.            break;
  1342.        case ORIENT_UPSIDEDOWN:
  1343.                *r -= (s->type->array+i-1)->r;
  1344.                *c -= (s->type->array+i-1)->c;
  1345.            break;
  1346.        default:
  1347.            FileLine;
  1348.            fprintf( stderr, "internal error: unexpected orientation\n" );
  1349.            exit( -1 );
  1350.            break;
  1351.            }
  1352.        }
  1353.     *--q = '.'; /* put back the separator */
  1354.     }
  1355.  
  1356. static int gettoken ( fp, file, line )
  1357.     /* get next token into token[], return value */
  1358.     FILE *fp;
  1359.     char *file;
  1360.     int line;
  1361.     {
  1362.     int ch, i;
  1363.  
  1364.     /* burn whitespace */
  1365.     while ((ch = getc( fp )) == ' ' || ch == '\t')
  1366.         ;
  1367.     if (ch == EOF)
  1368.         return( TOK_EOF );
  1369.     else if (ch == '\n')
  1370.         return( TOK_NEWLINE );
  1371.     else if (ch == ';') { /* comment; burn to end of line */
  1372.         while ((ch = getc( fp )) != EOF && ch != '\n')
  1373.             ;
  1374.         return( (ch == '\n') ? TOK_NEWLINE : TOK_EOF );
  1375.         }
  1376.     else if (ch == '=')
  1377.         return( TOK_EQUAL );
  1378.     else if (isdigit( ch )) { /* a number; move it to the buffer */
  1379.         i = 0;
  1380.         do {
  1381.             if (i < MAXTOK-1)
  1382.                 token[i++] = (char)ch;
  1383.             ch = getc( fp );
  1384.             } while (isdigit( ch ));
  1385.         token[i] = 0;
  1386.         if (ch != EOF)
  1387.             ungetc( ch, fp );
  1388.         return( TOK_NUMBER );
  1389.         }
  1390.     else if (isalpha( ch ) || ch == '.' || ch == '\\') {
  1391.         /* a name; move it to the buffer */
  1392.         i = 0;
  1393.         do {
  1394.             if (i < MAXTOK-1)
  1395.                 token[i++] = (char)ch;
  1396.             ch = getc( fp );
  1397.             } while (isalnum( ch ) || ch == ':' || ch == '.'
  1398.                 || ch == '\\');
  1399.         token[i] = 0;
  1400.         if (ch != EOF)
  1401.             ungetc( ch, fp );
  1402.         /* try to identify it as a reserved word */
  1403.         for (i = 0; i < numres; i++) /* search table */
  1404.             if (!stricmp( tokenmatch[i].tokenname, token ))
  1405.                 return( tokenmatch[i].tokenvalue );
  1406.         /* it's not a reserved word; just return it */
  1407.         strupr( token );
  1408.         return( TOK_ALPHANUM );
  1409.         }
  1410.     else if (ch == '(') { /* "(row,column)", move it to the buffer */
  1411.         token[0] = (char)ch;
  1412.         i = 1;
  1413.         while ((ch = getc( fp )) == ' ' || ch == '\t')
  1414.             ;
  1415.         if (!isdigit( ch )) {
  1416.             FileLine;
  1417.             fprintf( stderr, "syntax error: expected digit\n" );
  1418.             exit( -1 );
  1419.             }
  1420.         do {
  1421.             if (i < MAXTOK-1)
  1422.                 token[i++] = (char)ch;
  1423.             ch = getc( fp );
  1424.             } while (isdigit( ch ));
  1425.         while (ch == ' ' || ch == '\t')
  1426.             ch = getc( fp );
  1427.         if (ch != ',') {
  1428.             FileLine;
  1429.             fprintf( stderr, "syntax error: expected comma\n" );
  1430.             exit( -1 );
  1431.             }
  1432.         if (i < MAXTOK-1)
  1433.             token[i++] = (char)ch;
  1434.         while ((ch = getc( fp )) == ' ' || ch == '\t')
  1435.             ;
  1436.         if (!isdigit( ch )) {
  1437.             FileLine;
  1438.             fprintf( stderr, "syntax error: expected digit\n" );
  1439.             exit( -1 );
  1440.             }
  1441.         do {
  1442.             if (i < MAXTOK-1)
  1443.                 token[i++] = (char)ch;
  1444.             ch = getc( fp );
  1445.             } while (isdigit( ch ));
  1446.         while (ch == ' ' || ch == '\t')
  1447.             ch = getc( fp );
  1448.         if (ch != ')') {
  1449.             FileLine;
  1450.             fprintf( stderr,
  1451.                 "syntax error: expected right paren\n" );
  1452.             exit( -1 );
  1453.             }
  1454.         if (i < MAXTOK-1)
  1455.             token[i++] = (char)ch;
  1456.         token[i] = 0;
  1457.         return( TOK_ROWCOLUMN );
  1458.         }
  1459.     else {
  1460.         FileLine;
  1461.         fprintf( stderr, "syntax error: unrecognized token\n" );
  1462.         exit( -1 );
  1463.         }
  1464.     }
  1465.  
  1466. static char far *fcopy ( p ) /* return ptr to far string copy */
  1467.     char *p;
  1468.     {
  1469.     char far *q;
  1470.     char far *r;
  1471.  
  1472.     if (!(q = r = farmalloc( strlen( p ) + 1 )))
  1473.         Nomem();
  1474.     while (*r++ = *p++) /* copy string */
  1475.         ;
  1476.     return( q );
  1477.     }
  1478.  
  1479. static int same ( p, q ) /* return 1 if far strings are identical, else 0 */
  1480.     char far *p;
  1481.     char far *q;
  1482.     {
  1483.     while (*p && *p == *q) { /* compare bytes until mismatch or end */
  1484.         p++;
  1485.         q++;
  1486.         }
  1487.     return( (*p || *q) ? 0 : 1 );
  1488.     }
  1489.  
  1490. void Report ( fp ) /* output routed board */
  1491.     FILE *fp;
  1492.     {
  1493.     int r, c;
  1494.     char b;
  1495.     long x;
  1496.  
  1497.     printf( "Enter Report()\n" );
  1498.     /* output dimensions first */
  1499.     b = (char)Nrows;    putc( b, fp );
  1500.     b = (char)(Nrows>>8);   putc( b, fp );
  1501.     b = (char)Ncols;    putc( b, fp );
  1502.     b = (char)(Ncols>>8);   putc( b, fp );
  1503.     /* now do rows and columns */
  1504.     for (r = 0; r < Nrows; r++)
  1505.         for (c = 0; c < Ncols; c++) {
  1506.             x = GetCell( r, c, TOP ); /* first do frontside */
  1507.             b = (char)x;        putc( b, fp );
  1508.             b = (char)(x>>8);   putc( b, fp );
  1509.             b = (char)(x>>16);  putc( b, fp );
  1510.             b = (char)(x>>24);  putc( b, fp );
  1511.             x = GetCell( r, c, BOTTOM ); /* then do backside */
  1512.             b = (char)x;        putc( b, fp );
  1513.             b = (char)(x>>8);   putc( b, fp );
  1514.             b = (char)(x>>16);  putc( b, fp );
  1515.             b = (char)(x>>24);  putc( b, fp );
  1516.             }
  1517.     if (ferror( fp ))
  1518.         fprintf( stderr, "output error; disk might be full\n" );
  1519.     printf( "Exit Report()\n" );
  1520.     }
  1521.  
  1522. void partlist( struct instance far * chip)
  1523. {
  1524.     if ( chip->next != NULL) partlist( chip->next );
  1525.     fprintf(partsfile, "%-8s%-12s%-4d%-8s\n",chip->name, chip->type->type,
  1526.             chip->type->pins, chip->type->package);
  1527. }
  1528.