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

Defined functions

cleanup defined in line 510; never used
getadmin defined in line 115; used 4 times
getdelta defined in line 225; used 1 times
getkeyval defined in line 313; used 6 times
main defined in line 482; never used
putadmin defined in line 343; used 4 times
putdelta defined in line 390; used 1 times
putdtext defined in line 444; used 6 times
puttree defined in line 421; used 6 times

Defined variables

Commleader defined in line 101; used 2 times
Kaccess defined in line 84; used 3 times
Kauthor defined in line 85; used 2 times
Kbranches defined in line 86; used 1 times
Kcomment defined in line 87; used 3 times
Kdate defined in line 88; used 2 times
Kdesc defined in line 89; used 4 times
Khead defined in line 90; used 3 times
Klocks defined in line 91; used 2 times
Klog defined in line 92; used 5 times
Knext defined in line 93; used 2 times
Kstate defined in line 94; used 2 times
Kstrict defined in line 95; used 3 times
Ksuffix defined in line 96; used 3 times
Ksymbols defined in line 97; used 2 times
Ktext defined in line 98; used 4 times
LastAccess defined in line 104; used 4 times
LastLock defined in line 108; used 4 times
LastSymbol defined in line 106; used 4 times
Locks defined in line 107; used 23 times
rcsid defined in line 5; never used

Defined macros

COMMLENGTH defined in line 100; used 2 times
Last modified: 1983-05-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2359
Valid CSS Valid XHTML 1.0 Strict