home *** CD-ROM | disk | FTP | other *** search
/ gdead.berkeley.edu / gdead.berkeley.edu.tar / gdead.berkeley.edu / pub / cad-tools / ciftomann.tar / CD / parser.c < prev    next >
C/C++ Source or Header  |  1988-01-28  |  13KB  |  596 lines

  1. /*
  2.  * parser.c
  3.  *
  4.  * Copyright -C- 1981 Giles C. Billingsley
  5.  * sccsid "%W%  %G%"
  6.  *
  7.  *     KIC is a graphics editor that was developed by the integrated
  8.  * circuits group of the Electronics Research Laboratory and the
  9.  * Department of Electrical Engineering and Computer Sciences at
  10.  * the University of California, Berkeley, California.  The program
  11.  * KIC is available free of charge to any interested party.
  12.  * The sale, resale, or use of this program for profit without the
  13.  * express written consent of the Department of Electrical Engineering
  14.  * and Computer Sciences, University of California, Berkeley, California,
  15.  * is forbidden.
  16.  */
  17.  
  18. /*
  19.  * Fast CIF file parser.
  20.  * 
  21.  * It is easy to use it to write programs that traverse a CIF file. 
  22.  *
  23.  * Examples follows.
  24.  * 1.    A program that translates CIF to STREAM.
  25.  * 2.    A pattern factoring program for PG tape generation.
  26.  *       See TI's PFP.
  27.  * 3.    A statistics generation program. 
  28.  * 4.    A program that extracts each symbol, generates a name for it, and
  29.  *       writes it to a file.  See the CD package.
  30.  * 5.    A program that builds a binary representation of the CIF file that can
  31.  *       then be edited via procedure calls and then written back to the CIF
  32.  *       file.  See the CD package.
  33.  * 
  34.  * Here's how you use it.
  35.  * 
  36.  * First, you include the files actions.c and parser.h.
  37.  * Then you invoke PCIF(CIFFileName,StatusString,StatusInt). 
  38.  * Each time the parser recognizes a CIF command, it invokes an action routine.
  39.  * You should fill in the action routines in the file Actions.c.
  40.  * Each action routine name is prefixed by A.
  41.  * 
  42.  * Each parser routine and global variable name is prefixed by P.
  43.  * StatusInt == PFAILED if the parse failed and an error message along with
  44.  * about where in the CIF file the error is in the StatusString.
  45.  * Else StatusInt == PSUCCEEDED and StatusString == "".
  46.  * 
  47.  */
  48.  
  49. #include "parser.h"
  50. #include "cd.h"
  51.  
  52. /* Library routines */
  53. #ifndef vms
  54. char *sprintf();
  55. #endif
  56.  
  57. PCIF(CIFFileName,StatusString,StatusInt)
  58.     char *CIFFileName,**StatusString;
  59.     int *StatusInt;
  60.     {
  61.     PStatus[0] = EOS;
  62.     *StatusString = PStatus;
  63.     if((PCIFFileDesc = POpen(CIFFileName,"r",(char *)NULL,(char **)NULL))
  64.     == NULL){
  65.     PChar = EOF;
  66.     PError("Can't open CIF file.");
  67.     *StatusInt = PFAILED;
  68.     return;
  69.     }
  70.     loop{
  71.     PCharacter(PReturned,PSTRIPWHITESPACE2,PDONTFAILONEOF);
  72.     if(PReturned == PFAILED){
  73.         fclose(PCIFFileDesc);
  74.         *StatusInt = PFAILED;
  75.         return;
  76.         }
  77.     elif(PChar == 'D'){
  78.         PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
  79.         if(PReturned == PFAILED){
  80.         fclose(PCIFFileDesc);
  81.         *StatusInt = PFAILED;
  82.         return;
  83.         }
  84.         elif(PChar == 'S'){
  85.         if(PSymbol() == PFAILED){
  86.             fclose(PCIFFileDesc);
  87.             *StatusInt = PFAILED;
  88.             return;
  89.             }
  90.         }
  91.         elif(PChar == 'D'){
  92.         if(PDeleteSymbol() == PFAILED){
  93.             fclose(PCIFFileDesc);
  94.             *StatusInt = PFAILED;
  95.             return;
  96.             }
  97.         }
  98.         }
  99.     elif(PChar == 'E'){
  100.         *StatusInt = PEnd();
  101.         return;
  102.         }
  103.     elif((PReturned = PPrimitiveCommand()) == PFAILED){
  104.         fclose(PCIFFileDesc);
  105.         *StatusInt = PFAILED;
  106.         return;
  107.         }
  108.     elif(PReturned == PNOTAPPLICABLE){
  109.         PError("Can't understand next command.");
  110.         fclose(PCIFFileDesc);
  111.         *StatusInt = PFAILED;
  112.         return;
  113.         }
  114.     }
  115.     }
  116.  
  117. PPrimitiveCommand(){
  118.     if(PChar == 'P')
  119.     return(PPolygon());        
  120.     elif(PChar == 'B')
  121.     return(PBox());
  122.     elif(PChar == 'W')
  123.     return(PWire());
  124.     elif(PChar == 'L')
  125.     return(PLayer());
  126.     elif(PChar == 'C')
  127.     return(PCall());
  128.     elif(PChar == 'R')
  129.     return(PRoundFlash());
  130.     elif('0' <= PChar And PChar <= '9')
  131.     return(PUserExtension());
  132.     elif(PChar == '(')
  133.     return(PComment());
  134.     elif(PChar == ';')
  135.     return(PSUCCEEDED);
  136.     else
  137.     return(PNOTAPPLICABLE);
  138.     }
  139.  
  140. PEnd(){
  141.     AEnd();
  142.     fclose(PCIFFileDesc);
  143.     return(PSUCCEEDED);
  144.     }
  145.  
  146. PSymbol(){
  147.     char For;
  148.     int SymbolNum,A,B;
  149.  
  150. #ifdef TRACT
  151. fprintf(stderr," ENTERING PSYMBOL\n");
  152. #endif
  153.     PInteger(PReturned,PFAILONEOF);
  154.     if(PReturned == PFAILED)
  155.     return(PFAILED);
  156.     SymbolNum = PInt;
  157.     A = B = 1;
  158.     /* look for scaling factor */
  159.     for(For = '0'; For <= '9'; ++For){
  160.         PLookAhead(PReturned,PSTRIPWHITESPACE3,For);
  161.         if(PReturned == PFAILED)
  162.         return(PFAILED);
  163.         if(PChar == For){
  164.         ungetc(For,PCIFFileDesc);
  165.         if(PPoint(&A,&B) == PFAILED)
  166.             return(PFAILED);
  167.         break;
  168.         }
  169.     }
  170.     PLookForSemi(PReturned);
  171.     if(PReturned == PFAILED)
  172.     return(PFAILED);
  173.     if(ABeginSymbol(SymbolNum,A,B) == PFAILED){
  174.     PErrorCD();
  175.     return(PFAILED);
  176.     }
  177.     if(PReturned == PFAILED)
  178.     return(PFAILED);
  179.     loop{
  180.     PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
  181.     if(PReturned == PFAILED)
  182.         return(PFAILED);
  183.     if((PReturned = PPrimitiveCommand()) == PFAILED){
  184.         return(PFAILED);
  185.         }
  186.     elif(PReturned == PNOTAPPLICABLE)
  187.         break;
  188.     }
  189.     if(PChar != 'D')
  190.     return(PFAILED);
  191.     PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
  192.     if(PReturned == PFAILED)
  193.     return(PFAILED);
  194.     if(PChar != 'F')
  195.     return(PFAILED);
  196.     PLookForSemi(PReturned);
  197.     if(PReturned == PFAILED)
  198.     return(PFAILED);
  199.     AEndSymbol();
  200.     return(PSUCCEEDED);
  201.     }
  202.  
  203. PDeleteSymbol(){
  204.     PInteger(PReturned,PFAILONEOF);
  205.     if(PReturned == PFAILED)
  206.     return(PFAILED);
  207.     else{
  208.     PLookForSemi(PReturned);
  209.     if(PReturned == PFAILED)
  210.         return(PFAILED);
  211.     ADeleteSymbol(PInt);
  212.     return(PSUCCEEDED);
  213.     }
  214.     }
  215.  
  216. PCall(){
  217.     int SymbolNum,X,Y;
  218.  
  219.     PInteger(PReturned,PFAILONEOF);
  220.     if(PReturned == PFAILED)
  221.     return(PFAILED);
  222.     SymbolNum = PInt;
  223.     if(ABeginCall(SymbolNum) == PFAILED){
  224.     PErrorCD();
  225.     return(PFAILED);
  226.     }
  227.     loop{
  228.     PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
  229.     if(PReturned == PFAILED)
  230.         return(PFAILED);
  231.     elif(PChar == 'T'){
  232.         if(PPoint(&X,&Y) == PFAILED){
  233.         PError("Can't parse translation transform.");
  234.         return(PFAILED);
  235.         }
  236.         elif(AT(CDTRANSLATE,X,Y) == PFAILED){
  237.         PErrorCD();
  238.         return(PFAILED);
  239.         }
  240.         }
  241.     elif(PChar == 'M'){
  242.         PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
  243.         if(PReturned == PFAILED){
  244.         PErrorEOF();
  245.         return(PFAILED);
  246.         }
  247.         elif(PChar == 'X'){
  248.         if(AT(CDMIRRORX,X,Y) == PFAILED){
  249.             PErrorCD();
  250.             return(PFAILED);
  251.             }
  252.         }
  253.         elif(PChar == 'Y'){
  254.         if(AT(CDMIRRORY,X,Y) == PFAILED){
  255.             PErrorCD();
  256.             return(PFAILED);
  257.             }
  258.         }
  259.         else{
  260.         PError("Can't parse mirror transform.");
  261.         return(PFAILED);
  262.         }
  263.         }
  264.     elif(PChar == 'R'){
  265.         if(PPoint(&X,&Y) == PFAILED){
  266.         PError("Can't parse rotation transform.");
  267.         return(PFAILED);
  268.         }
  269.         if(AT(CDROTATE,X,Y) == PFAILED){
  270.         PErrorCD();
  271.         return(PFAILED);
  272.         }
  273.         }
  274.     elif(PChar == ';')
  275.         break;
  276.     else{
  277.         PError("Can't parse transformation.");
  278.         return(PFAILED);
  279.         }
  280.     } 
  281.     if(AEndCall() == PFAILED){
  282.     PErrorCD();
  283.     return(PFAILED);
  284.     }
  285.     return(PSUCCEEDED);
  286.     }
  287.  
  288. PPolygon(){
  289.     struct p *Path;
  290.  
  291. #ifdef TRACE
  292. fprintf(stderr," ENTERING PPOLYGON\n");
  293. #endif
  294.     if(PPath(&Path) == PFAILED)
  295.     return(PFAILED);
  296. #ifdef TRACE
  297. fprintf(stderr," LEAVING PPATH\n");
  298. #endif
  299.     if(APolygon(Path) == PFAILED){
  300.     PErrorCD();
  301.     return(PFAILED);
  302.     }
  303. #ifdef TRACE
  304. fprintf(stderr," LEAVING PPOLYGON\n");
  305. #endif
  306.     return(PSUCCEEDED);
  307.     }
  308.  
  309. PBox(){
  310.     int Length,Width,X,Y,XDirection,YDirection;
  311.  
  312.     XDirection = 1;
  313.     YDirection = 0;
  314.     PInteger(PReturned,PFAILONEOF);
  315.     if(PReturned == PFAILED)
  316.     return(PFAILED);
  317.     Length = PInt;
  318.     PInteger(PReturned,PFAILONEOF);
  319.     if(PReturned == PFAILED)
  320.     return(PFAILED);
  321.     Width = PInt;
  322.     if(PPoint(&X,&Y) == PFAILED)
  323.     return(PFAILED);
  324.     PLookForSemi(PReturned);
  325.     if(PReturned == PFAILED)
  326.     return(PFAILED);
  327.     elif(PChar != ';'){
  328.     if(PPoint(&XDirection,&YDirection) == PFAILED)
  329.         return(PFAILED);
  330.     PLookForSemi(PReturned);
  331.     if(PReturned == PFAILED Or PChar != ';'){
  332.         PErrorNoSemicolon();
  333.         return(PFAILED);
  334.         }
  335.     }
  336.     if(ABox(Length,Width,X,Y,XDirection,YDirection) == PFAILED){
  337.     PErrorCD();
  338.     return(PFAILED);
  339.     }
  340.     return(PSUCCEEDED);
  341.     }
  342.  
  343. PRoundFlash(){
  344.     int Width,X,Y;
  345.  
  346.     PInteger(PReturned,PFAILONEOF);
  347.     if(PReturned == PFAILED)
  348.     return(PFAILED);
  349.     Width = PInt;
  350.     if(PPoint(&X,&Y) == PFAILED)
  351.     return(PFAILED);
  352.     PLookForSemi(PReturned);
  353.     if(PReturned == PFAILED)
  354.     return(PFAILED);
  355.     elif(PChar != ';'){
  356.     PErrorNoSemicolon();
  357.     return(PFAILED);
  358.     }
  359.     if(ARoundFlash(Width,X,Y) == PFAILED){
  360.     PErrorCD();
  361.     return(PFAILED);
  362.     }
  363.     return(PSUCCEEDED);
  364.     }
  365.  
  366. PWire(){
  367.     int Width;
  368.     struct p *Path;
  369.  
  370. #ifdef TRACE
  371. fprintf(stderr," ENTERING PWIRE\n");
  372. #endif
  373.     PInteger(PReturned,PFAILONEOF);
  374.     if(PReturned == PFAILED)
  375.     return(PFAILED);
  376.     Width = PInt;
  377. #ifdef TRACE
  378. fprintf(stderr," ENTERING PPATH\n");
  379. #endif
  380.     if(PPath(&Path) == PFAILED)
  381.     return(PFAILED);
  382.     if(AWire(Width,Path) == PFAILED){
  383.     PErrorCD();
  384.     return(PFAILED);
  385.     }
  386.     return(PSUCCEEDED);
  387.     }
  388.  
  389. PPath(Path)
  390.     struct p **Path;
  391.     {
  392.     int X,Y;
  393.     struct p *Pair;
  394.  
  395.     *Path = NULL;
  396.     loop{
  397.     PLookForSemi(PReturned);
  398. #ifdef TRACE
  399. if(PReturned == PFAILED)
  400.     fprintf(stderr," PPATH FAILED AFTER PLOOKAHEAD\n");
  401. #endif
  402.     if(PReturned == PFAILED)
  403.         return(PFAILED);
  404.     elif(PChar == ';')
  405.         break; 
  406.     else{
  407.         if(PPoint(&X,&Y) == PFAILED)
  408.         return(PFAILED);
  409. #ifdef TRACE
  410. fprintf(stderr," PPATH POINT %d, %d\n",X,Y);
  411. #endif
  412.         if((Pair = (struct p *)malloc(sizeof(struct p))) == NULL){
  413.         PError("Out of memory.");
  414.         return(PFAILED);
  415.         }
  416.         Pair->pSucc = *Path;
  417.         Pair->pX = X;
  418.         Pair->pY = Y;
  419.         *Path = Pair;
  420.         }
  421.     }
  422.     return(PSUCCEEDED);
  423.     }
  424.  
  425. PPoint(X,Y)
  426.     int *X,*Y;
  427.     {
  428.     /* it is assumed that a LookAhead is done prior to calling PPoint */
  429.     PInteger(PReturned,PFAILONEOF);
  430.     if(PReturned == PFAILED)
  431.     return(PFAILED);
  432.     *X = PInt;
  433.     PLookForSemi(PReturned);
  434.     if(PReturned == PFAILED)
  435.     return(PFAILED);
  436.     elif(PChar == ';'){
  437.     PError("Bad X,Y path element.");
  438.     return(PFAILED);
  439.     }
  440.     PInteger(PReturned,PFAILONEOF);
  441.     if(PReturned == PFAILED)
  442.     return(PFAILED);
  443.     *Y = PInt;
  444.     return(PSUCCEEDED);
  445.     }
  446.  
  447. PLayer(){
  448.     char Technology,Mask[4];
  449.     int i;
  450.  
  451.     Mask[0] = Mask[1] = Mask[2] = ' '; Mask[3] = NULL;
  452.     PCharacter(PReturned,PSTRIPWHITESPACE2,PFAILONEOF);
  453.     if(PReturned == PFAILED)
  454.     return(PFAILED);
  455.     if(PChar == ';'){
  456.     PError("At least one character expected after L in layer command.");
  457.     return(PFAILED);
  458.     }
  459.     Technology = PChar;
  460.     for(i=0; i<3; ++i){
  461.     if((PChar = getc(PCIFFileDesc)) == EOF){
  462.             PErrorEOF();
  463.         return(PFAILED);
  464.         }
  465.     elif(PChar == ';'){
  466.         if(ALayer(Technology,Mask) == PSUCCEEDED)
  467.         return(PSUCCEEDED);
  468.         else{
  469.         PErrorUndefinedLayer(Technology,Mask);
  470.         return(PFAILED);
  471.         }
  472.         }
  473.     Mask[i] = PChar;
  474.     /* check for valid CIF layer name character */
  475.     if(Not ((PChar >= '0' And PChar <= '9') Or
  476.         (PChar >= 'A' And PChar <= 'Z'))){
  477.         PErrorUndefinedLayer(Technology,Mask);
  478.         return(PFAILED);
  479.         }
  480.     }
  481.     /* clear the semicolon */
  482.     PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
  483.     if(PReturned == PFAILED){
  484.     return(PFAILED);
  485.     }
  486.     elif(PChar == ';'){
  487.     if(ALayer(Technology,Mask) == PSUCCEEDED)
  488.         return(PSUCCEEDED);
  489.     else{
  490.         PErrorUndefinedLayer(Technology,Mask);
  491.         return(PFAILED);
  492.         }
  493.     }
  494.     PError("Illegal CIF layer name with > 4 characters discovered.");
  495.     return(PFAILED);
  496.     }
  497.  
  498. PUserExtension(){
  499.     char Digit;
  500.     int Int1;
  501.  
  502.     Digit = PChar; 
  503.     Int1 = 0;
  504.     loop{
  505.     PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
  506.     if(PReturned == PFAILED)
  507.         return(PFAILED);
  508.     elif(PChar == ';'){
  509.         PString[Int1] = EOS;
  510.         if(AUserExtension(Digit,PString) == PFAILED){
  511.         PErrorCD();
  512.         return(PFAILED);
  513.         }
  514. #ifdef TRACE
  515. fprintf(stderr,"PString = %s\n",PString);
  516. #endif
  517.         return(PSUCCEEDED);
  518.         }
  519.     elif(Int1 == PSTRINGSIZE){
  520.         PError("User extension command longer than 1920 characters.");
  521.         return(PFAILED);
  522.         }
  523.     else PString[Int1++] = PChar;
  524.     }
  525.     }
  526.  
  527. PComment(){
  528.     int Int1;
  529.  
  530.     Int1 = 0;
  531.     loop{
  532.     PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
  533.     if(PReturned == PFAILED)
  534.         return(PFAILED); 
  535.     elif(PChar == ')'){
  536.         PCharacter(PReturned,PSTRIPWHITESPACE1,PFAILONEOF);
  537.         if(PReturned == PFAILED)
  538.         return(PFAILED); 
  539.         elif(PChar == ';'){
  540.         PString[Int1] = EOS;
  541.         AComment(PString);
  542.         return(PSUCCEEDED);
  543.         }
  544.         elif(Int1 == PSTRINGSIZE){
  545.         PError("Comment command longer than 1920 characters.");
  546.         return(PFAILED);
  547.         }
  548.         else{
  549.         PErrorNoSemicolon();
  550.         return(PFAILED);
  551.         }
  552.         }
  553.     else PString[Int1++] = PChar;
  554.     }
  555.     }
  556.  
  557. PError(PErrorMessage)
  558.     char *PErrorMessage;
  559.     {
  560.     int Int1;
  561.     
  562.     for(Int1 = 0;Int1 < 20;++Int1){
  563.     if(PChar == EOF)
  564.         break;
  565.     PCharacter(PReturned,PLEAVEWHITESPACE,PFAILONEOF);
  566.     if(PReturned == PFAILED) 
  567.         break;
  568.     PString[Int1] = PChar;
  569.     }
  570.     PString[Int1] = EOS;
  571.     sprintf(PStatus,"%s.  Failed at around %s.",PErrorMessage,PString);
  572. #ifdef TRACE
  573. fprintf(stderr,"%s\n",PErrorMessage);
  574. #endif
  575.     }
  576.  
  577. PErrorEOF(){
  578.     PError("Early EOF.");
  579.     }
  580.  
  581. PErrorNoSemicolon(){
  582.     PError("; expected and not found.");
  583.     }
  584.  
  585. PErrorUndefinedLayer(Tech,Mask)
  586.     char Tech,*Mask;
  587.     {
  588.     char buf[35];
  589.     sprintf(buf,"Undefined layer: %c%s. ",Tech,Mask);
  590.     PError(buf);
  591.     }
  592.  
  593. PErrorCD(){
  594.     PError(CDStatusString);
  595.     }
  596.