home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 373.lha / route_v1.0 / src / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-25  |  24.9 KB  |  931 lines

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