home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / rcs.t.Z / rcs.t / RCS / SRC / rcssyn.c < prev    next >
Text File  |  1988-08-24  |  17KB  |  547 lines

  1. /*
  2.  *                     RCS file input
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcssyn.c,v 4.4 87/12/18 11:46:16 narten Exp $ Purdue CS";
  6. #endif
  7. /*********************************************************************************
  8.  *                       Syntax Analysis.
  9.  *                       Keyword table
  10.  *                       Testprogram: define SYNDB
  11.  *                       Compatibility with Release 2: define COMPAT2
  12.  *********************************************************************************
  13.  *
  14.  * Copyright (C) 1982 by Walter F. Tichy
  15.  *                       Purdue University
  16.  *                       Computer Science Department
  17.  *                       West Lafayette, IN 47907
  18.  *
  19.  * All rights reserved. No part of this software may be sold or distributed
  20.  * in any form or by any means without the prior written permission of the
  21.  * author.
  22.  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
  23.  */
  24.  
  25.  
  26. /* $Log:    rcssyn.c,v $
  27.  * Revision 4.4  87/12/18  11:46:16  narten
  28.  * more lint cleanups (Guy Harris)
  29.  * 
  30.  * Revision 4.3  87/10/18  10:39:36  narten
  31.  * Updating version numbers. Changes relative to 1.1 actually relative to
  32.  * 4.1
  33.  * 
  34.  * Revision 1.3  87/09/24  14:00:49  narten
  35.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  36.  * warnings)
  37.  * 
  38.  * Revision 1.2  87/03/27  14:22:40  jenkins
  39.  * Port to suns
  40.  * 
  41.  * Revision 1.1  84/01/23  14:50:40  kcs
  42.  * Initial revision
  43.  * 
  44.  * Revision 4.1  83/03/28  11:38:49  wft
  45.  * Added parsing and printing of default branch.
  46.  * 
  47.  * Revision 3.6  83/01/15  17:46:50  wft
  48.  * Changed readdelta() to initialize selector and log-pointer.
  49.  * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
  50.  *
  51.  * Revision 3.5  82/12/08  21:58:58  wft
  52.  * renamed Commentleader to Commleader.
  53.  *
  54.  * Revision 3.4  82/12/04  13:24:40  wft
  55.  * Added routine gettree(), which updates keeplock after reading the
  56.  * delta tree.
  57.  *
  58.  * Revision 3.3  82/11/28  21:30:11  wft
  59.  * Reading and printing of Suffix removed; version COMPAT2 skips the
  60.  * Suffix for files of release 2 format. Fixed problems with printing nil.
  61.  *
  62.  * Revision 3.2  82/10/18  21:18:25  wft
  63.  * renamed putdeltatext to putdtext.
  64.  *
  65.  * Revision 3.1  82/10/11  19:45:11  wft
  66.  * made sure getc() returns into an integer.
  67.  */
  68.  
  69.  
  70.  
  71. /*
  72. #define COMPAT2
  73. /* version COMPAT2 reads files of the format of release 2 and 3, but
  74.  * generates files of release 3 format. Need not be defined if no
  75.  * old RCS files generated with release 2 exist.
  76.  */
  77. /*
  78. #define SYNDB
  79. /* version SYNDB is for debugging the syntax analysis for RCS files.
  80.  * SYNDB performs additional error checks.
  81.  */
  82. /*
  83. #define SYNTEST
  84. /* version SYNTEST inputs a RCS file and then prints out its internal
  85.  * data structures.
  86. */
  87.  
  88. #include "rcsbase.h"
  89. extern FILE * finptr;        /*RCS input file*/
  90. extern char * getid();
  91. extern struct hshentry * getnum();
  92. extern int    getkey();
  93. extern int    getlex();
  94. extern char * malloc();
  95. extern        readstring();
  96. extern int    savestring();
  97.  
  98. /* forward */
  99. char * getkeyval();
  100.  
  101. /* keyword table */
  102.  
  103. char * Kaccess     = "access";
  104. char * Kauthor     = "author";
  105. char * Kbranch     = "branch";
  106. char * Kbranches   = "branches";
  107. char * Kcomment    = "comment";
  108. char * Kdate       = "date";
  109. char * Kdesc       = "desc";
  110. char * Khead       = "head";
  111. char * Klocks      = "locks";
  112. char * Klog        = "log";
  113. char * Knext       = "next";
  114. char * Kstate      = "state";
  115. char * Kstrict     = "strict";
  116. #ifdef COMPAT2
  117. char * Ksuffix     = "suffix";
  118. #endif
  119. char * Ksymbols    = "symbols";
  120. char * Ktext       = "text";
  121.  
  122. #define COMMLENGTH 20
  123. char              Commleader[COMMLENGTH];
  124. char            * Comment    = "";
  125. struct access   * AccessList =nil;
  126. struct access   * LastAccess =nil;
  127. struct assoc    * Symbols    =nil;
  128. struct assoc    * LastSymbol =nil;
  129. struct lock     * Locks      =nil;
  130. struct lock     * LastLock   =nil;
  131. int               StrictLocks=false;
  132. struct hshentry * Head       =nil;
  133. struct hshentry * Dbranch    =nil;
  134. int               TotalDeltas=0;
  135.  
  136.  
  137.  
  138. getadmin()
  139. /* Function: Reads an <admin> and initializes the globals
  140.  * AccessList, LastAccess, Symbols, LastSymbol,
  141.  * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas;
  142.  */
  143. {
  144.         register char   * id;
  145.         struct access   * newaccess;
  146.         struct assoc    * newassoc;
  147.         struct lock     * newlock;
  148.         struct hshentry * delta;
  149.  
  150.         Comment="";
  151.         AccessList=LastAccess=nil;
  152.         Symbols=LastSymbol=nil;
  153.         Locks=LastLock=nil;
  154.         Dbranch = Head = nil;
  155.         TotalDeltas=0;
  156.  
  157.         if (!getkey(Khead)) fatserror("Missing head");
  158.         Head=getnum();
  159. #       ifdef SYNDB
  160.         if (Head&&((countnumflds(Head->num)%2)!=0))
  161.                 serror("Delta number required for head");
  162. #       endif
  163.         if (!getlex(SEMI)) serror("Missing ';' after head");
  164.  
  165.         if (getkey(Kbranch)) { /* optional */
  166.                 Dbranch=getnum();
  167.                 if (!getlex(SEMI)) serror("Missing ';' after branch list");
  168.         }
  169.  
  170.  
  171. #ifdef COMPAT2
  172.         /* read suffix. Only in release 2 format */
  173.         if (getkey(Ksuffix)) {
  174.                 if (nexttok==STRING) {
  175.                         readstring(); nextlex(); /*through away the suffix*/
  176.                 } elsif(nexttok==ID) {
  177.                         nextlex();
  178.                 }
  179.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix);
  180.         }
  181. #endif
  182.  
  183.         if (!getkey(Kaccess)) fatserror("Missing access list");
  184.         while (id=getid()) {
  185.                 newaccess = (struct access *)malloc(sizeof(struct access));
  186.                 newaccess->login = id;
  187.                 newaccess->nextaccess = nil;
  188.                 if (AccessList == nil) {
  189.                         AccessList=LastAccess=newaccess;
  190.                 } else {
  191.                         LastAccess=LastAccess->nextaccess=newaccess;
  192.                 }
  193.         }
  194.         if (!getlex(SEMI)) serror("Missing ';' after access list");
  195.  
  196.         if (!getkey(Ksymbols)) fatserror("Missing symbols");
  197.         while (id = getid()) {
  198.                 if (!getlex(COLON))
  199.                         serror("Missing ':' in symbolic name definition");
  200.                 if (!(delta=getnum())) {
  201.                         serror("Missing number in symbolic name definition");
  202.                 } else { /*add new pair to association list*/
  203.                         newassoc=(struct assoc *)malloc(sizeof(struct assoc));
  204.                         newassoc->symbol=id;
  205.                         newassoc->delta=delta;
  206.                         newassoc->nextassoc=nil;
  207.                         if (Symbols == nil) {
  208.                                 Symbols=LastSymbol=newassoc;
  209.                         } else {
  210.                                 LastSymbol=LastSymbol->nextassoc=newassoc;
  211.                         }
  212.                 }
  213.         }
  214.         if (!getlex(SEMI)) serror("Missing ';' after symbolic names");
  215.  
  216.         if (!getkey(Klocks)) serror("Missing locks");
  217.         while (id = getid()) {
  218.                 if (!getlex(COLON))
  219.                         serror("Missing ':' in lock");
  220.                 if (!(delta=getnum())) {
  221.                         serror("Missing number in lock");
  222.                 } else { /*add new pair to lock list*/
  223. #                       ifdef SYNDB
  224.                         if ((countnumflds(delta->num)%2)!=0)
  225.                                 serror("Delta number required for lock");
  226. #                       endif
  227.                         newlock=(struct lock *)malloc(sizeof(struct lock));
  228.                         newlock->login=id;
  229.                         newlock->delta=delta;
  230.                         newlock->nextlock=nil;
  231.                         if (Locks == nil) {
  232.                                 Locks=LastLock=newlock;
  233.                         } else {
  234.                                 LastLock=LastLock->nextlock=newlock;
  235.                         }
  236.                 }
  237.         }
  238.         if (!getlex(SEMI)) serror("Missing ';' after locks");
  239.         if (!getkey(Kstrict)) {
  240.                 StrictLocks = false;
  241.         } else {
  242.                 StrictLocks = true;
  243.                 if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict);
  244.         }
  245.         if (getkey(Kcomment) && (nexttok==STRING)) {
  246.                 VOID savestring(Commleader,COMMLENGTH);nextlex();
  247.                 Comment=Commleader;
  248.                 if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment);
  249.         }
  250. }
  251.  
  252.  
  253.  
  254. getdelta()
  255. /* Function: reads a delta block.
  256.  * returns false if the current block does not start with a number.
  257.  */
  258. {
  259.         register struct hshentry * Delta, * num;
  260.         struct branchhead * LastBranch, * NewBranch;
  261.  
  262.         if (!(Delta=getnum())) return false;
  263. #       ifdef SYNDB
  264.         if ((countnumflds(Delta->num)%2)!=0)
  265.                 serror("Delta number required");
  266. #       endif
  267.  
  268.         hshenter = false; /*Don't enter dates into hashtable*/
  269.         Delta->date = getkeyval(Kdate, NUM, false);
  270.         hshenter=true;    /*reset hshenter for revision numbers.*/
  271.  
  272.         Delta->author = getkeyval(Kauthor, ID, false);
  273.  
  274.         Delta->state = getkeyval(Kstate, ID, true);
  275.  
  276.         if (!getkey(Kbranches)) fatserror("Missing branches");
  277.         Delta->branches = LastBranch=nil;
  278.         while (num=getnum()) {
  279. #               ifdef SYNDB
  280.                 if ((countnumflds(num->num)%2)!=0)
  281.                         serror("Delta number required");
  282. #               endif
  283.                 NewBranch = (struct branchhead *)malloc(sizeof(struct branchhead));
  284.                 NewBranch->hsh = num;
  285.                 NewBranch->nextbranch = nil;
  286.                 if (LastBranch == nil) {
  287.                         Delta->branches=LastBranch=NewBranch;
  288.                 } else {
  289.                         LastBranch=LastBranch->nextbranch=NewBranch;
  290.                 }
  291.         }
  292.         if (!getlex(SEMI)) serror("Missing ';' after branches");
  293.  
  294.         if (!getkey(Knext)) fatserror("Missing next");
  295.         Delta->next=num=getnum();
  296. #       ifdef SYNDB
  297.         if (num&&((countnumflds(num->num)%2)!=0))
  298.                 serror("Delta number required");
  299. #       endif
  300.         if (!getlex(SEMI)) serror("Missing ';' after next");
  301.         Delta->log=Delta->lockedby = nil;
  302.         Delta->selector = '\0';
  303.         TotalDeltas++;
  304.         return (true);
  305. }
  306.  
  307.  
  308. gettree()
  309. /* Function: Reads in the delta tree with getdelta(), then
  310.  * updates the lockedby fields.
  311.  */
  312. {       struct lock * currlock;
  313.         while (getdelta());
  314.         currlock=Locks;
  315.         while (currlock) {
  316.                 currlock->delta->lockedby = currlock->login;
  317.                 currlock = currlock->nextlock;
  318.         }
  319. }
  320.  
  321.  
  322. getdesc(prdesc)
  323. int  prdesc;
  324. /* Function: read in descriptive text
  325.  * nexttok is not advanced afterwards.
  326.  * if prdesc==true, the text is printed to stdout.
  327.  */
  328. {
  329.  
  330.         if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text");
  331.         if (prdesc)
  332.                 printstring();  /*echo string*/
  333.         else    readstring();   /*skip string*/
  334. }
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341. char * getkeyval(keyword, token, optional)
  342. enum tokens token; char * keyword; int optional;
  343. /* reads a pair of the form
  344.  * <keyword> <token> ;
  345.  * where token is one of <id> or <num>. optional indicates whether
  346.  * <token> is optional. A pointer to
  347.  * the acutal character string of <id> or <num) is returned.
  348.  * Getkeyval terminates the program on missing keyword or token, continues
  349.  * on missing ;.
  350.  */
  351. {
  352.         register char * val;
  353.  
  354.         if (!getkey(keyword)) {
  355.                 fatserror("Missing %s", keyword);
  356.         }
  357.         if (nexttok==token) {
  358.                 val = NextString;
  359.                 nextlex();
  360.         } else {
  361.                 if (!optional) {fatserror("Missing %s", keyword); }
  362.                 else val = nil;
  363.         }
  364.         if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
  365.         return(val);
  366. }
  367.  
  368.  
  369.  
  370.  
  371. putadmin(fout)
  372. register FILE * fout;
  373. /* Function: Print the <admin> node read with getadmin() to file fout.
  374.  * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
  375.  * and Head have been set.
  376.  */
  377. {       struct assoc  * curassoc;
  378.         struct lock   * curlock;
  379.         struct access * curaccess;
  380.         register char * sp;
  381.  
  382.         VOID fputs(Khead,fout); VOID fputs("     ",fout);
  383.         if (Head) VOID fputs(Head->num,fout);
  384.  
  385.         VOID fprintf(fout,";\n%s   ",Kbranch);
  386.         if (Dbranch) VOID fputs(Dbranch->num,fout);
  387.  
  388.         VOID fprintf(fout,";\n%s  ",Kaccess);
  389.         curaccess = AccessList;
  390.         if (curaccess==nil) VOID putc(' ',fout);
  391.         while (curaccess) {
  392.                VOID putc(' ',fout);
  393.                VOID fputs(curaccess->login,fout);
  394.                curaccess = curaccess->nextaccess;
  395.         }
  396.         VOID fprintf(fout,";\n%s ",Ksymbols);
  397.         curassoc = Symbols;
  398.         if (curassoc==nil) VOID putc(' ',fout);
  399.         while (curassoc) {
  400.                VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num);
  401.                curassoc = curassoc->nextassoc;
  402.         }
  403.         VOID fprintf(fout,";\n%s   ",Klocks);
  404.         curlock = Locks;
  405.         if (curlock==nil) VOID putc(' ',fout);
  406.         while (curlock) {
  407.                VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num);
  408.                curlock = curlock->nextlock;
  409.         }
  410.         if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict);
  411.         VOID fprintf(fout,";\n%s  %c",Kcomment,SDELIM);
  412.         if((sp=Comment)!=nil) {
  413.                while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  414.         }
  415.         VOID fprintf(fout,"%c;\n\n",SDELIM);
  416. }
  417.  
  418.  
  419.  
  420.  
  421. putdelta(node,fout)
  422. register struct hshentry * node;
  423. register FILE * fout;
  424. /* Function: prints a <delta> node to fout;
  425.  */
  426. {      struct branchhead * nextbranch;
  427.  
  428.         if (node == nil) return;
  429.  
  430.         VOID fprintf(fout,"\n%s\n",node->num);
  431.         VOID fprintf(fout,"%s     %s;  %s %s;  %s ",
  432.                 Kdate,node->date,Kauthor,node->author,Kstate);
  433.         if (node->state!=nil) VOID fputs(node->state,fout);
  434.         VOID fputs(";\nbranches",fout);
  435.         nextbranch = node->branches;
  436.         if (nextbranch==nil) VOID putc(' ',fout);
  437.         while (nextbranch) {
  438.                VOID putc(' ',fout);
  439.                VOID fputs(nextbranch->hsh->num,fout);
  440.                nextbranch = nextbranch->nextbranch;
  441.         }
  442.  
  443.         VOID fprintf(fout,";\n%s     ",Knext);
  444.         if (node->next!=nil) VOID fputs(node->next->num,fout);
  445.         VOID fputs(";\n",fout);
  446.  
  447. }
  448.  
  449.  
  450.  
  451.  
  452. puttree(root,fout)
  453. struct hshentry * root;
  454. register FILE * fout;
  455. /* Function: prints the delta tree in preorder to fout, starting with root.
  456.  */
  457. {       struct branchhead * nextbranch;
  458.  
  459.         if (root==nil) return;
  460.  
  461.         if (root->selector !=DELETE)putdelta(root,fout);
  462.         /* selector DELETE means deleted; set by rcs -o */
  463.  
  464.         puttree(root->next,fout);
  465.  
  466.         nextbranch = root->branches;
  467.         while (nextbranch) {
  468.              puttree(nextbranch->hsh,fout);
  469.              nextbranch = nextbranch->nextbranch;
  470.         }
  471. }
  472.  
  473.  
  474.  
  475. int putdtext(num,log,srcfilename,fout)
  476. char * num, * log, * srcfilename; FILE * fout;
  477. /* Function: write a deltatext-node to fout.
  478.  * num points to the deltanumber, log to the logmessage, and
  479.  * sourcefile contains the text. Doubles up all SDELIMs in both the
  480.  * log and the text; Makes sure the log message ends in \n.
  481.  * returns false on error.
  482.  */
  483. {
  484.         register char * sp;
  485.     register int c;
  486.         register FILE * fin;
  487.  
  488.         VOID fprintf(fout,DELNUMFORM,num,Klog);
  489.         /* put log */
  490.         VOID putc(SDELIM,fout);
  491.         sp=log;
  492.         while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  493.         if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/
  494.         /* put text */
  495.         VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM);
  496.         if ((fin=fopen(srcfilename,"r"))==NULL) {
  497.                 error("Can't open source file %s",srcfilename);
  498.                 return false;
  499.         }
  500.         while ((c=fgetc(fin))!=EOF) {
  501.                 if (c==SDELIM) VOID putc(SDELIM,fout);   /*double up SDELIM*/
  502.                 VOID putc(c,fout);
  503.         }
  504.         VOID putc(SDELIM,fout); VOID putc('\n',fout);
  505.         VOID fclose(fin);
  506.         return true;
  507. }
  508.  
  509.  
  510.  
  511. #ifdef SYNTEST
  512.  
  513. main(argc,argv)
  514. int argc; char * argv[];
  515. {
  516.  
  517.         cmdid = "syntest";
  518.         if (argc<2) {
  519.                 VOID fputs("No input file\n",stderr);
  520.                 exit(-1);
  521.         }
  522.         if ((finptr=fopen(argv[1], "r")) == NULL) {
  523.                 faterror("Can't open input file %s\n",argv[1]);
  524.         }
  525.         Lexinit();
  526.         getadmin();
  527.         putadmin(stdout);
  528.  
  529.         gettree();
  530.         puttree(Head,stdout);
  531.  
  532.         getdesc(true);
  533.  
  534.         if (nextlex(),nexttok!=EOFILE) {
  535.                 fatserror("Syntax error");
  536.         }
  537.         exit(0);
  538. }
  539.  
  540.  
  541. cleanup(){}
  542. /*dummy*/
  543.  
  544.  
  545. #endif
  546.  
  547.