|
|
1.1 ! root 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 ! 515:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.