1: /*
   2:  *                     RCS file input
   3:  */
   4: #ifndef lint
   5: static char rcsid[]= "$Id: rcssyn.c,v 4.4.1 94/1/1 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

Defined functions

cleanup defined in line 541; never used
getadmin defined in line 138; used 3 times
getdelta defined in line 254; used 1 times
getkeyval defined in line 341; used 6 times
main defined in line 513; never used
putadmin defined in line 371; used 4 times
putdelta defined in line 421; used 1 times
putdtext defined in line 475; used 6 times
puttree defined in line 452; used 6 times

Defined variables

Commleader defined in line 123; used 2 times
Kaccess defined in line 103; used 3 times
Kauthor defined in line 104; used 2 times
Kbranch defined in line 105; used 2 times
Kbranches defined in line 106; used 1 times
Kcomment defined in line 107; used 3 times
Kdate defined in line 108; used 2 times
Kdesc defined in line 109; used 4 times
Khead defined in line 110; used 3 times
Klocks defined in line 111; used 2 times
Klog defined in line 112; used 5 times
Knext defined in line 113; used 2 times
Kstate defined in line 114; used 2 times
Kstrict defined in line 115; used 3 times
Ksuffix defined in line 117; used 3 times
Ksymbols defined in line 119; used 2 times
Ktext defined in line 120; used 4 times
LastAccess defined in line 126; used 4 times
LastLock defined in line 130; used 4 times
LastSymbol defined in line 128; used 4 times
rcsid defined in line 5; never used

Defined macros

COMMLENGTH defined in line 122; used 2 times
Last modified: 1994-01-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3738
Valid CSS Valid XHTML 1.0 Strict