home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 644.IO.C < prev    next >
C/C++ Source or Header  |  1989-03-05  |  26KB  |  883 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.  
  8. /* board dimensions */
  9. extern int Nrows;
  10. extern int Ncols;
  11.  
  12. extern int InitBoardDone; /* sanity check */
  13.  
  14. /* memory usage */
  15. extern long Ltotal; /* for board */
  16. extern long Itotal; /* for dist */
  17. extern long Ctotal; /* for dir */
  18.  
  19. /*
  20. ** the following types of input lines are legal (spaces and tabs can separate
  21. ** tokens, and case is not significant):
  22. **
  23. **  1) a blank line (ignored)
  24. **  2) ';' followed by anything (ignored)
  25. **     use semicolon to insert comments.
  26. **  3) DIMENSION (row,column)
  27. **     this defines the number of rows and columns on the board, and must be
  28. **     given before any of the lines below. note that the user sees the board
  29. **     coordinate space as being 1-based, but internally it is 0-based.
  30. **  4) HOLE (row,column)
  31. **     this defines a hole location.
  32. **  5) CONNECT thing AND thing
  33. **     this declares that two holes are to be electrically connected. a thing
  34. **     can be (row,column), or name1.name2, where name1 is the name of a
  35. **     CHIPAT-defined chip, and name2 is the name of one of its pins, or a
  36. **     number, giving the pin number of the named chip. you can use '='
  37. **     instead of 'AND' if you want.
  38. **  6) PRIORITY CONNECT thing AND thing
  39. **     same as above, except the order of connections will be preserved. the
  40. **     autorouter is free to reorder the non-PRIORITY CONNECTs, and in fact
  41. **     reorders them shortest first. if there are PRIORITY CONNECTs, they will
  42. **     all be routed before non-PRIORITY CONNECTs.
  43. **  7) INCLUDE filename
  44. **     this causes the input to be temporarily taken from the given filename.
  45. **     when the given filename is completely processed (EOF encountered),
  46. **     control returns to the current file. INCLUDE statements may be nested
  47. **     (they may occur inside the given filename). complete and partial
  48. **     pathnames can be used (C:\TTL.INC, ..\TTL.INC, \TTL.INC, FOO\TTL.INC).
  49. **  8) CHIP TYPE=type PINS=number HORIZONTAL=number VERTICAL=number
  50. **     this declares a chip type, which can be used to place chips on the
  51. **     board (see CHIPAT, below), but does not itself place anything on the
  52. **     board. TYPE gives the name that will be used in later CHIPAT
  53. **     statements. PINS declares the number of pins. HORIZONTAL gives the
  54. **     number of 50-mil units separating adjacent pins (along the long side of
  55. **     the chip). and VERTICAL gives the number of 50-mil units separating
  56. **     pins across from each other (across the skinny width of the chip).
  57. **     standard values for HORIZONTAL and VERTICAL are 2 and 6, respectively.
  58. **     all CHIP type names must be unique.
  59. **  9) number=name
  60. **     this declares a pin name for the chip that is currently being defined.
  61. **     this statement must follow a CHIP statement. pins not defined will have
  62. **     no name, but you can still refer to them by number. each pin on a chip
  63. **     can be named at most once.
  64. ** 10) name=number
  65. **     same as above.
  66. ** 11) CHIPAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
  67. **     this defines an instance of a chip, and places the appropriate holes on
  68. **     the board. (row,column) is the location of pin 1. NAME defines the name
  69. **     to be used in following CONNECT statements. TYPE declares the
  70. **     CHIPAT-defined type of the chip. ORIENTATION can have the values
  71. **     NORMAL, UP, DOWN, and UPSIDEDOWN. all CHIPAT names must be unique.
  72. **
  73. **      NORMAL           UP           DOWN        UPSIDEDOWN
  74. **
  75. **       6 5 4          +---+         +---+          3 2 1
  76. **     +-*-*-*-+      4 *   * 3     1 * | * 6      +-*-*-*-+
  77. **     |  ->   |      5 * ^ * 2     2 * v * 5      |   <-  |
  78. **     +-*-*-*-+      6 * | * 1     3 *   * 4      +-*-*-*-+
  79. **       1 2 3          +---+         +---+          4 5 6
  80. **
  81. **     usually the highest-numbered pin (pin N) is Vcc (power) and the pin
  82. **     farthest from it (pin N/2) is GND (ground).
  83. */
  84.  
  85. /* chip orientations (rotations) */
  86. #define ORIENT_NORMAL        1
  87. #define ORIENT_UP        2
  88. #define ORIENT_DOWN        3
  89. #define ORIENT_UPSIDEDOWN    4
  90.  
  91. /* input token types */
  92. #define TOK_EOF        1    /* end of file, no more tokens        */
  93. #define TOK_NEWLINE    2    /* end of line                */
  94. #define TOK_NUMBER    3    /* number (digits)            */
  95. #define TOK_HOLE    4    /* "HOLE"                */
  96. #define TOK_ROWCOLUMN    5    /* "(row,column)"            */
  97. #define TOK_CONNECT    6    /* "CONNECT"                */
  98. #define TOK_EQUAL    7    /* "="                    */
  99. #define TOK_AND        8    /* "AND"                */
  100. #define TOK_ALPHANUM    9    /* name (letters, digits, ':','.','\')    */
  101. #define TOK_CHIP    10    /* "CHIP"                */
  102. #define TOK_NAME    11    /* "NAME"                */
  103. #define TOK_PINS    12    /* "PINS"                */
  104. #define TOK_HORIZONTAL    13    /* "HORIZONTAL"                */
  105. #define TOK_VERTICAL    14    /* "VERTICAL"                */
  106. #define TOK_INCLUDE    15    /* "INCLUDE"                */
  107. #define TOK_CHIPAT    16    /* "CHIPAT"                */
  108. #define TOK_TYPE    17    /* "TYPE"                */
  109. #define TOK_ORIENTATION    18    /* "ORIENTATION"            */
  110. #define TOK_NORMAL    19    /* "NORMAL"                */
  111. #define TOK_UP        20    /* "UP"                    */
  112. #define TOK_DOWN    21    /* "DOWN"                */
  113. #define TOK_UPSIDEDOWN    22    /* "UPSIDEDOWN"                */
  114. #define TOK_DIMENSION    23    /* "DIMENSION"                */
  115. #define TOK_PRIORITY    24    /* "PRIORITY"                */
  116.  
  117. struct reserved { /* reserved word input tokens */
  118.     char *tokenname;
  119.     int tokenvalue;
  120.     };
  121.  
  122. static struct reserved tokenmatch[] = { /* reserved word table */
  123.   { "HOLE",       TOK_HOLE       },  { "CONNECT",     TOK_CONNECT     },
  124.   { "AND",        TOK_AND        },  { "CHIP",        TOK_CHIP        },
  125.   { "NAME",       TOK_NAME       },  { "PINS",        TOK_PINS        },
  126.   { "HORIZONTAL", TOK_HORIZONTAL },  { "VERTICAL",    TOK_VERTICAL    },
  127.   { "INCLUDE",    TOK_INCLUDE    },  { "CHIPAT",      TOK_CHIPAT      },
  128.   { "TYPE",       TOK_TYPE       },  { "ORIENTATION", TOK_ORIENTATION },
  129.   { "NORMAL",     TOK_NORMAL     },  { "UP",          TOK_UP          },
  130.   { "DOWN",       TOK_DOWN       },  { "UPSIDEDOWN",  TOK_UPSIDEDOWN  },
  131.   { "DIMENSION",  TOK_DIMENSION  },  { "PRIORITY",    TOK_PRIORITY    }
  132.  };
  133.  
  134. #define MAXTOK    80    /* maximum token length (including null) */
  135.  
  136. static int numres = sizeof(tokenmatch) / sizeof(tokenmatch[0]);
  137. static char token[MAXTOK]; /* the current token is formed here */
  138.  
  139. struct pinassign { /* for assigning names to pins */
  140.     int            index;
  141.     char far        *name;
  142.     struct pinassign far    *next;
  143.     };
  144.  
  145. struct template { /* for "CHIP" declarations */
  146.     char far        *type;
  147.     int            pins;
  148.     int            horizontal;
  149.     int            vertical;
  150.     struct pinassign far    *pinlist;
  151.     struct template far    *next;
  152.     };
  153.  
  154. struct instance { /* for "CHIPAT" definitions */
  155.     int            row;
  156.     int            column;
  157.     char far        *name;
  158.     struct template far    *type;
  159.     int            orientation;
  160.     struct instance far    *next;
  161.     };
  162.  
  163. static struct template far *chip = NULL; /* list of CHIPs */
  164. static struct instance far *chipat = NULL; /* list of CHIPATs */
  165.  
  166. extern void InitBoard( void );
  167. extern long GetCell( int, int, int );
  168. extern void SetCell( int, int, int, long );
  169. extern void InitWork( void );
  170. extern void SetWork( int, int, char far *, int, int, char far *, int );
  171. extern void SortWork( void );
  172. extern void Nomem( void );
  173.  
  174. void Initialize( FILE * );
  175. static void initfile( FILE * );
  176. static void initchip( struct instance far * );
  177. static void locate( char *, int *, int * );
  178. static int gettoken( FILE * );
  179. static char far *fcopy( char * );
  180. static int same( char far *, char far * );
  181. void Report( FILE * );
  182.  
  183. void Initialize ( fin ) /* get hole coordinates and connections */
  184.     FILE *fin;
  185.     {
  186.     printf( "enter Initialize()\n" );
  187.     InitWork(); /* clear work list */
  188.     initfile( fin ); /* read input file(s) */
  189.     SortWork(); /* arrange to do shortest ones first */
  190.     printf( "  %ld bytes used for board\n", Ltotal );
  191.     printf( "  %ld bytes used for dist\n", Itotal );
  192.     printf( "  %ld bytes used for dir\n", Ctotal );
  193.     printf( "leave Initialize()\n" );
  194.     }
  195.  
  196. /* some useful macros (common code sequences) */
  197.  
  198. #define SkipRest    { while ((tok = gettoken( fin )) != TOK_EOF \
  199.                 && tok != TOK_NEWLINE) ; }
  200.  
  201. #define SkipTokRest    { while (tok != TOK_EOF && tok != TOK_NEWLINE) \
  202.                 tok = gettoken( fin ); } \
  203.             continue;
  204.  
  205. #define CheckInit    { if (!InitBoardDone) { \
  206.                 printf( "error: need dimensions first\n" ); \
  207.                 SkipRest; \
  208.                 continue; } }
  209.  
  210. static void initfile ( fin ) /* read and process input file(s) */
  211.     FILE *fin;
  212.     {
  213.     int tok, r1, c1, r2, c2, i;
  214.     char far *p;
  215.     char far *n1;
  216.     char far *n2;
  217.     long cell;
  218.     struct template far *p1;
  219.     struct pinassign far *p2;
  220.     struct pinassign far *p22;
  221.     struct instance far *p3;
  222.     FILE *fnew;
  223.  
  224.     while ((tok = gettoken( fin )) != TOK_EOF) {
  225.         if (tok == TOK_DIMENSION) {
  226.             if (InitBoardDone) { /* can only do it once */
  227.                 printf( "error: redundant dimensions\n" );
  228.                 SkipRest;
  229.                 continue;
  230.                 }
  231.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  232.                 printf( "expect (row,column)\n" );
  233.                 SkipTokRest;
  234.                 }
  235.             sscanf( token, "(%d,%d)", &Nrows, &Ncols );
  236.             if (Nrows <= 0 || Ncols <= 0)
  237.                 printf( "dimension error\n" );
  238.             else /* allocate memory for data structures */
  239.                 InitBoard();
  240.             }
  241.         else if (tok == TOK_HOLE) {
  242.             CheckInit; /* must get dimensions first */
  243.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  244.                 printf( "expect (row,column)\n" );
  245.                 SkipTokRest;
  246.                 }
  247.             sscanf( token, "(%d,%d)", &r1, &c1 );
  248.             if (r1 <= 0 || r1 > Nrows || c1 <= 0 || c1 > Ncols)
  249.                 printf( "out of range\n" );
  250.             else { /* position the hole on the board */
  251.                 /* should check for neighbor holes (error) */
  252.                 SetCell( r1-1, c1-1, TOP, HOLE );
  253.                 SetCell( r1-1, c1-1, BOTTOM, HOLE );
  254.                 }
  255.             }
  256.         else if (tok == TOK_CONNECT) {
  257.             CheckInit; /* must get dimensions first */
  258.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  259.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  260.             else if (tok == TOK_ALPHANUM)
  261.                 locate( token, &r1, &c1 );
  262.             else {
  263.                 printf( "expect (row,column) or name\n" );
  264.                 SkipTokRest;
  265.                 }
  266.             n1 = fcopy( token );
  267.             if ((tok = gettoken( fin )) != TOK_EQUAL
  268.                 && tok != TOK_AND) {
  269.                 printf( "expect = or AND\n" );
  270.                 SkipTokRest;
  271.                 }
  272.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  273.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  274.             else if (tok == TOK_ALPHANUM)
  275.                 locate( token, &r2, &c2 );
  276.             else {
  277.                 printf( "expect (row,column) or name\n" );
  278.                 SkipTokRest;
  279.                 }
  280.             n2 = fcopy( token );
  281.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  282.                 || c1 <= 0 || c1 > Ncols
  283.                 || c2 <= 0 || c2 > Ncols) {
  284.                 printf( "out of range\n" );
  285.                 _ffree( n1 );
  286.                 _ffree( n2 );
  287.                 }
  288.             else {
  289.                 cell = GetCell( r1-1, c1-1, TOP );
  290.                 if (!(cell & HOLE)) {
  291.                     printf( "error: no source hole\n" );
  292.                     _ffree( n1 );
  293.                     _ffree( n2 );
  294.                     SkipRest;
  295.                     continue;
  296.                     }
  297.                 cell = GetCell( r2-1, c2-1, TOP );
  298.                 if (!(cell & HOLE)) {
  299.                     printf( "error: no target hole\n" );
  300.                     _ffree( n1 );
  301.                     _ffree( n2 );
  302.                     SkipRest;
  303.                     continue;
  304.                     }
  305.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 0 );
  306.                 }
  307.             }
  308.         else if (tok == TOK_PRIORITY) {
  309.             CheckInit; /* must get dimensions first */
  310.             if ((tok = gettoken( fin )) != TOK_CONNECT) {
  311.                 printf( "expect CONNECT\n" );
  312.                 SkipTokRest;
  313.                 }
  314.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  315.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  316.             else if (tok == TOK_ALPHANUM)
  317.                 locate( token, &r1, &c1 );
  318.             else {
  319.                 printf( "expect (row,column) or name\n" );
  320.                 SkipTokRest;
  321.                 }
  322.             n1 = fcopy( token );
  323.             if ((tok = gettoken( fin )) != TOK_EQUAL
  324.                 && tok != TOK_AND) {
  325.                 printf( "expect = or AND\n" );
  326.                 SkipTokRest;
  327.                 }
  328.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  329.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  330.             else if (tok == TOK_ALPHANUM)
  331.                 locate( token, &r2, &c2 );
  332.             else {
  333.                 printf( "expect (row,column) or name\n" );
  334.                 SkipTokRest;
  335.                 }
  336.             n2 = fcopy( token );
  337.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  338.                 || c1 <= 0 || c1 > Ncols
  339.                 || c2 <= 0 || c2 > Ncols) {
  340.                 printf( "out of range\n" );
  341.                 _ffree( n1 );
  342.                 _ffree( n2 );
  343.                 }
  344.             else {
  345.                 cell = GetCell( r1-1, c1-1, TOP );
  346.                 if (!(cell & HOLE)) {
  347.                     printf( "error: no source hole\n" );
  348.                     _ffree( n1 );
  349.                     _ffree( n2 );
  350.                     SkipRest;
  351.                     continue;
  352.                     }
  353.                 cell = GetCell( r2-1, c2-1, TOP );
  354.                 if (!(cell & HOLE)) {
  355.                     printf( "error: no target hole\n" );
  356.                     _ffree( n1 );
  357.                     _ffree( n2 );
  358.                     SkipRest;
  359.                     continue;
  360.                     }
  361.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 1 );
  362.                 }
  363.             }
  364.         else if (tok == TOK_INCLUDE) {
  365.             CheckInit; /* must get dimensions first */
  366.             if ((tok = gettoken( fin )) != TOK_ALPHANUM) {
  367.                 printf( "expect name for INCLUDE\n" );
  368.                 SkipTokRest;
  369.                 }
  370.             if (!(fnew = fopen( token, "r" ))) {
  371.                 printf( "can't open INCLUDE file %s\n",
  372.                     token );
  373.                 SkipRest;
  374.                 continue;
  375.                 }
  376.             if ((tok = gettoken( fin )) != TOK_EOF
  377.                 && tok != TOK_NEWLINE) {
  378.                 printf( "extra chars on INCLUDE line\n" );
  379.                 SkipRest;
  380.                 }
  381.             initfile( fnew ); /* recurse */
  382.             if (fclose( fnew ))
  383.                 printf( "error closing INCLUDE file\n" );
  384.             continue; /* already ate the NEWLINE, if any */
  385.             }
  386.         else if (tok == TOK_CHIP) {
  387.             CheckInit; /* must get dimensions first */
  388.             if ((tok = gettoken( fin )) != TOK_TYPE
  389.                 || (tok = gettoken( fin )) != TOK_EQUAL
  390.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  391.                 printf( "expect TYPE=type\n" );
  392.                 SkipTokRest;
  393.                 }
  394.             if (!(p1 = (struct template far *)
  395.                 _fmalloc( sizeof(struct template) )))
  396.                 Nomem();
  397.             p1->type = fcopy( token );
  398.             if ((tok = gettoken( fin )) != TOK_PINS
  399.                 || (tok = gettoken( fin )) != TOK_EQUAL
  400.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  401.                 printf( "expect PINS=number\n" );
  402.                 _ffree( p1->type );
  403.                 _ffree( p1 );
  404.                 SkipTokRest;
  405.                 }
  406.             sscanf( token, "%d", &i );
  407.             p1->pins = i;
  408.             if ((p1->pins = i) < 0 || (i & 1))
  409.                 printf( "PINS negative or odd\n" );
  410.             if ((tok = gettoken( fin )) != TOK_HORIZONTAL
  411.                 || (tok = gettoken( fin )) != TOK_EQUAL
  412.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  413.                 printf( "expect HORIZONTAL=number\n" );
  414.                 _ffree( p1->type );
  415.                 _ffree( p1 );
  416.                 SkipTokRest;
  417.                 }
  418.             sscanf( token, "%d", &i );
  419.             if ((p1->horizontal = i) <= 0)
  420.                 printf( "HORIZONTAL nonpositive\n" );
  421.             if ((tok = gettoken( fin )) != TOK_VERTICAL
  422.                 || (tok = gettoken( fin )) != TOK_EQUAL
  423.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  424.                 printf( "expect VERTICAL=number\n" );
  425.                 _ffree( p1->type );
  426.                 _ffree( p1 );
  427.                 SkipTokRest;
  428.                 }
  429.             sscanf( token, "%d", &i );
  430.             if ((p1->vertical = i) < 0)
  431.                 printf( "VERTICAL nonpositive\n" );
  432.             p1->pinlist = NULL;
  433.             p1->next = chip;
  434.             chip = p1;
  435.             }
  436.         else if (tok == TOK_NUMBER) {
  437.             CheckInit; /* must get dimensions first */
  438.             if (!chip) {
  439.                 printf( "no template\n" );
  440.                 SkipRest;
  441.                 continue;
  442.                 }
  443.             sscanf( token, "%d", &i );
  444.             if ((tok = gettoken( fin )) != TOK_EQUAL
  445.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  446.                 printf( "expect number=name\n" );
  447.                 SkipTokRest;
  448.                 }
  449.             if (!(p2 = (struct pinassign far *)
  450.                 _fmalloc( sizeof(struct pinassign) )))
  451.                 Nomem();
  452.             p2->name = fcopy( token );
  453.             p2->index = i;
  454.             /* check uniqueness of name and index */
  455.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  456.                 if (p22->index == i
  457.                     || same( p22->name, p )) {
  458.                     printf( "warning: repeated pin\n" );
  459.                     break;
  460.                     }
  461.             p2->next = chip->pinlist;
  462.             chip->pinlist = p2;
  463.             }
  464.         else if (tok == TOK_ALPHANUM) {
  465.             CheckInit; /* must get dimensions first */
  466.             if (!chip) {
  467.                 printf( "no template\n" );
  468.                 SkipRest;
  469.                 continue;
  470.                 }
  471.             p = fcopy( token );
  472.             if ((tok = gettoken( fin )) != TOK_EQUAL
  473.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  474.                 printf( "expect name=number\n" );
  475.                 _ffree( p );
  476.                 SkipTokRest;
  477.                 }
  478.             sscanf( token, "%d", &i );
  479.             if (!(p2 = (struct pinassign far *)
  480.                 _fmalloc( sizeof(struct pinassign) )))
  481.                 Nomem();
  482.             p2->name = p;
  483.             p2->index = i;
  484.             /* check uniqueness of name and index */
  485.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  486.                 if (p22->index == i
  487.                     || same( p22->name, p )) {
  488.                     printf( "warning: repeated pin\n" );
  489.                     break;
  490.                     }
  491.             p2->next = chip->pinlist;
  492.             chip->pinlist = p2;
  493.             }
  494.         else if (tok == TOK_CHIPAT) {
  495.             CheckInit; /* must get dimensions first */
  496.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  497.                 printf( "expect (row,column)\n" );
  498.                 SkipTokRest;
  499.                 }
  500.             sscanf( token, "(%d,%d)", &r1, &c1 );
  501.             if ((tok = gettoken( fin )) != TOK_NAME
  502.                 || (tok = gettoken( fin )) != TOK_EQUAL
  503.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  504.                 printf( "expect NAME=name\n" );
  505.                 SkipTokRest;
  506.                 }
  507.             if (!(p3 = (struct instance far *)
  508.                 _fmalloc( sizeof(struct instance) )))
  509.                 Nomem();
  510.             p3->name = fcopy( token );
  511.             p3->row = r1;
  512.             p3->column = c1;
  513.             if ((tok = gettoken( fin )) != TOK_TYPE
  514.                 || (tok = gettoken( fin )) != TOK_EQUAL
  515.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  516.                 printf( "expect TYPE=type\n" );
  517.                 _ffree( p3->name );
  518.                 _ffree( p3 );
  519.                 SkipTokRest;
  520.                 }
  521.             for (p3->type = chip; p3->type;
  522.                 p3->type = p3->type->next)
  523.                 if (same( token, p3->type->type ))
  524.                     break;
  525.             if (!(p3->type)) {
  526.                 printf( "couldn't find chip type\n" );
  527.                 _ffree( p3->name );
  528.                 _ffree( p3 );
  529.                 SkipTokRest;
  530.                 }
  531.             if ((tok = gettoken( fin )) != TOK_ORIENTATION
  532.                 || (tok = gettoken( fin )) != TOK_EQUAL
  533.                 || ((tok = gettoken( fin )) != TOK_NORMAL
  534.                 && tok != TOK_UP && tok != TOK_DOWN
  535.                 && tok != TOK_UPSIDEDOWN)) {
  536.                 printf( "expect ORIENTATION=orientation\n" );
  537.                 _ffree( p3->name );
  538.                 _ffree( p3 );
  539.                 SkipTokRest;
  540.                 }
  541.             switch (tok) {
  542.             case TOK_NORMAL:
  543.                 p3->orientation = ORIENT_NORMAL;    break;
  544.             case TOK_UP:
  545.                 p3->orientation = ORIENT_UP;        break;
  546.             case TOK_DOWN:
  547.                 p3->orientation = ORIENT_DOWN;        break;
  548.             case TOK_UPSIDEDOWN:
  549.                 p3->orientation = ORIENT_UPSIDEDOWN;    break;
  550.             default:
  551.                 printf( "internal error\n" );
  552.                 exit( -1 );
  553.                 break;
  554.                 }
  555.             p3->next = chipat;
  556.             chipat = p3;
  557.             initchip( p3 );
  558.             }
  559.         else if (tok == TOK_NEWLINE)
  560.             continue;
  561.         else /* something unexpected */
  562.             printf( "syntax error: unexpected input\n" );
  563.         if ((tok = gettoken( fin )) != TOK_EOF && tok != TOK_NEWLINE) {
  564.             printf( "syntax error: expected end of line\n" );
  565.             SkipRest;
  566.             }
  567.         }
  568.     }
  569.  
  570. static void initchip ( p ) /* initialize a chip definition (create holes) */
  571.     struct instance far *p;
  572.     {
  573.     int r, c, pin;
  574.     struct template far *t;
  575.  
  576.     pin = 1;
  577.     r = p->row;
  578.     c = p->column;
  579.     t = p->type;
  580.     /* should check for neighboring holes (warning if so) */
  581.     switch (p->orientation) {
  582.     case ORIENT_NORMAL:
  583.         while (pin <= t->pins / 2) {
  584.             SetCell( r-1, c-1, TOP, HOLE );
  585.             SetCell( r-1, c-1, BOTTOM, HOLE );
  586.             pin++;
  587.             c += t->horizontal;
  588.             }
  589.         c -= t->horizontal;
  590.         r += t->vertical;
  591.         while (pin <= t->pins) {
  592.             SetCell( r-1, c-1, TOP, HOLE );
  593.             SetCell( r-1, c-1, BOTTOM, HOLE );
  594.             pin++;
  595.             c -= t->horizontal;
  596.             }
  597.         break;
  598.     case ORIENT_UP:
  599.         while (pin <= t->pins / 2) {
  600.             SetCell( r-1, c-1, TOP, HOLE );
  601.             SetCell( r-1, c-1, BOTTOM, HOLE );
  602.             pin++;
  603.             r += t->horizontal;
  604.             }
  605.         r -= t->horizontal;
  606.         c -= t->vertical;
  607.         while (pin <= t->pins) {
  608.             SetCell( r-1, c-1, TOP, HOLE );
  609.             SetCell( r-1, c-1, BOTTOM, HOLE );
  610.             pin++;
  611.             r -= t->horizontal;
  612.             }
  613.         break;
  614.     case ORIENT_DOWN:
  615.         while (pin <= t->pins / 2) {
  616.             SetCell( r-1, c-1, TOP, HOLE );
  617.             SetCell( r-1, c-1, BOTTOM, HOLE );
  618.             pin++;
  619.             r -= t->horizontal;
  620.             }
  621.         r += t->horizontal;
  622.         c += t->vertical;
  623.         while (pin <= t->pins) {
  624.             SetCell( r-1, c-1, TOP, HOLE );
  625.             SetCell( r-1, c-1, BOTTOM, HOLE );
  626.             pin++;
  627.             r += t->horizontal;
  628.             }
  629.         break;
  630.     case ORIENT_UPSIDEDOWN:
  631.         while (pin <= t->pins / 2) {
  632.             SetCell( r-1, c-1, TOP, HOLE );
  633.             SetCell( r-1, c-1, BOTTOM, HOLE );
  634.             pin++;
  635.             c -= t->horizontal;
  636.             }
  637.         c += t->horizontal;
  638.         r -= t->vertical;
  639.         while (pin <= t->pins) {
  640.             SetCell( r-1, c-1, TOP, HOLE );
  641.             SetCell( r-1, c-1, BOTTOM, HOLE );
  642.             pin++;
  643.             c += t->horizontal;
  644.             }
  645.         break;
  646.     default:
  647.         printf( "internal error: unexpected orientation\n" );
  648.         exit( -1 );
  649.         break;
  650.         }
  651.     }
  652.  
  653. static void locate ( p, r, c ) /* find location of name1.{name2,number} */
  654.     char *p;
  655.     int *r, *c;
  656.     {
  657.     char *q;
  658.     int i;
  659.     struct instance far *s;
  660.     struct pinassign far *t;
  661.  
  662.     if (!(q = strchr( p, '.' ))) {
  663.         printf( "expect name1.{name2,number}\n" );
  664.         return;
  665.         }
  666.     *q++ = 0; /* separate into two parts & point at second part */
  667.     for (s = chipat; s; s = s->next) /* find proper chip */
  668.         if (same( p, s->name ))
  669.             break;
  670.     if (!s || !(s->type)) {
  671.         printf( "can't find chip or chip type\n" );
  672.         return;
  673.         }
  674.     if (isdigit( *q )) { /* get pin number */
  675.         i = atoi( q );
  676.         if (i <= 0 || i > s->type->pins) {
  677.             printf( "pin out of range\n" );
  678.             return;
  679.             }
  680.         }
  681.     else { /* get index of named pin via the template */
  682.         for (t = s->type->pinlist; t; t = t->next)
  683.             if (same( q, t->name ))
  684.                 break;
  685.         if (!t) {
  686.             printf( "can't find pin\n" );
  687.             return;
  688.             }
  689.         i = t->index;
  690.         }
  691.     *r = s->row;
  692.     *c = s->column;
  693.     switch (s->orientation) {
  694.     case ORIENT_NORMAL:
  695.         if (i <= s->type->pins / 2)
  696.             *c += (i-1) * s->type->horizontal;
  697.         else {
  698.             *r += s->type->vertical;
  699.             *c += (s->type->pins - i) * s->type->horizontal;
  700.             }
  701.         break;
  702.     case ORIENT_UP:
  703.         if (i <= s->type->pins / 2)
  704.             *r += (i-1) * s->type->horizontal;
  705.         else {
  706.             *c -= s->type->vertical;
  707.             *r += (s->type->pins - i) * s->type->horizontal;
  708.             }
  709.         break;
  710.     case ORIENT_DOWN:
  711.         if (i <= s->type->pins / 2)
  712.             *r -= (i-1) * s->type->horizontal;
  713.         else {
  714.             *c += s->type->vertical;
  715.             *r -= (s->type->pins - i) * s->type->horizontal;
  716.             }
  717.         break;
  718.     case ORIENT_UPSIDEDOWN:
  719.         if (i <= s->type->pins / 2)
  720.             *c -= (i-1) * s->type->horizontal;
  721.         else {
  722.             *r -= s->type->vertical;
  723.             *c -= (s->type->pins - i) * s->type->horizontal;
  724.             }
  725.         break;
  726.     default:
  727.         printf( "internal error: unexpected orientation\n" );
  728.         exit( -1 );
  729.         break;
  730.         }
  731.     *--q = '.'; /* put back the separator */
  732.     }
  733.  
  734. static int gettoken ( fin ) /* get next token into token[], return value */
  735.     FILE *fin;
  736.     {
  737.     int ch, i;
  738.  
  739.     /* burn whitespace */
  740.     while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  741.     if (ch == EOF)
  742.         return( TOK_EOF );
  743.     else if (ch == '\n')
  744.         return( TOK_NEWLINE );
  745.     else if (ch == ';') { /* comment; burn to end of line */
  746.         while ((ch = getc( fin )) != EOF && ch != '\n') ;
  747.         return( (ch == '\n') ? TOK_NEWLINE : TOK_EOF );
  748.         }
  749.     else if (ch == '=')
  750.         return( TOK_EQUAL );
  751.     else if (isdigit( ch )) { /* a number; move it to the buffer */
  752.         i = 0;
  753.         do {
  754.             if (i < MAXTOK-1)
  755.                 token[i++] = (char)ch;
  756.             ch = getc( fin );
  757.             } while (isdigit( ch ));
  758.         token[i] = 0;
  759.         if (ch != EOF)
  760.             ungetc( ch, fin );
  761.         return( TOK_NUMBER );
  762.         }
  763.     else if (isalpha( ch ) || ch == '.' || ch == '\\') {
  764.         /* a name; move it to the buffer */
  765.         i = 0;
  766.         do {
  767.             if (i < MAXTOK-1)
  768.                 token[i++] = (char)ch;
  769.             ch = getc( fin );
  770.             } while (isalnum( ch ) || ch == ':' || ch == '.'
  771.                 || ch == '\\');
  772.         token[i] = 0;
  773.         if (ch != EOF)
  774.             ungetc( ch, fin );
  775.         /* try to identify it as a reserved word */
  776.         for (i = 0; i < numres; i++) /* search table */
  777.             if (!stricmp( tokenmatch[i].tokenname, token ))
  778.                 return( tokenmatch[i].tokenvalue );
  779.         /* it's not a reserved word; just return it */
  780.         strupr( token );
  781.         return( TOK_ALPHANUM );
  782.         }
  783.     else if (ch == '(') { /* "(row,column)", move it to the buffer */
  784.         token[0] = (char)ch;
  785.         i = 1;
  786.         while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  787.         if (!isdigit( ch )) {
  788.             printf( "syntax error: expected digit\n" );
  789.             exit( -1 );
  790.             }
  791.         do {
  792.             if (i < MAXTOK-1)
  793.                 token[i++] = (char)ch;
  794.             ch = getc( fin );
  795.             } while (isdigit( ch ));
  796.         while (ch == ' ' || ch == '\t')
  797.             ch = getc( fin );
  798.         if (ch != ',') {
  799.             printf( "syntax error: expected comma\n" );
  800.             exit( -1 );
  801.             }
  802.         if (i < MAXTOK-1)
  803.             token[i++] = (char)ch;
  804.         while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  805.         if (!isdigit( ch )) {
  806.             printf( "syntax error: expected digit\n" );
  807.             exit( -1 );
  808.             }
  809.         do {
  810.             if (i < MAXTOK-1)
  811.                 token[i++] = (char)ch;
  812.             ch = getc( fin );
  813.             } while (isdigit( ch ));
  814.         while (ch == ' ' || ch == '\t')
  815.             ch = getc( fin );
  816.         if (ch != ')') {
  817.             printf( "syntax error: expected right paren\n" );
  818.             exit( -1 );
  819.             }
  820.         if (i < MAXTOK-1)
  821.             token[i++] = (char)ch;
  822.         token[i] = 0;
  823.         return( TOK_ROWCOLUMN );
  824.         }
  825.     else {
  826.         printf( "syntax error: unrecognized token\n" );
  827.         exit( -1 );
  828.         }
  829.     }
  830.  
  831. static char far *fcopy ( p ) /* return ptr to far string copy */
  832.     char *p;
  833.     {
  834.     char far *q;
  835.     char far *r;
  836.  
  837.     if (!(q = r = _fmalloc( strlen( p ) + 1 )))
  838.         Nomem();
  839.     while (*r++ = *p++) ; /* copy string */
  840.     return( q );
  841.     }
  842.  
  843. static int same ( p, q ) /* return 1 if far strings are identical, else 0 */
  844.     char far *p;
  845.     char far *q;
  846.     {
  847.     while (*p && *p == *q) { /* compare bytes until mismatch or end */
  848.         p++;
  849.         q++;
  850.         }
  851.     return( (*p || *q) ? 0 : 1 );
  852.     }
  853.  
  854. void Report ( fout ) /* output routed board */
  855.     FILE *fout;
  856.     {
  857.     int r, c;
  858.     char b;
  859.     long x;
  860.  
  861.     printf( "enter Report()\n" );
  862.     /* output dimensions first */
  863.     b = (char)Nrows;    putc( b, fout );
  864.     b = (char)(Nrows>>8);    putc( b, fout );
  865.     b = (char)Ncols;    putc( b, fout );
  866.     b = (char)(Ncols>>8);    putc( b, fout );
  867.     /* now do rows and columns */
  868.     for (r = 0; r < Nrows; r++)
  869.         for (c = 0; c < Ncols; c++) {
  870.             x = GetCell( r, c, TOP ); /* first do frontside */
  871.             b = (char)x;        putc( b, fout );
  872.             b = (char)(x>>8);    putc( b, fout );
  873.             b = (char)(x>>16);    putc( b, fout );
  874.             b = (char)(x>>24);    putc( b, fout );
  875.             x = GetCell( r, c, BOTTOM ); /* then do backside */
  876.             b = (char)x;        putc( b, fout );
  877.             b = (char)(x>>8);    putc( b, fout );
  878.             b = (char)(x>>16);    putc( b, fout );
  879.             b = (char)(x>>24);    putc( b, fout );
  880.             }
  881.     printf( "leave Report()\n" );
  882.     }
  883.