From: CSRG Date: Tue, 15 Aug 1989 14:40:34 +0000 (-0800) Subject: BSD 4_3_Net_2 development X-Git-Tag: BSD-4_3_Net_2~988 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/1605b46f6154fe349d49340c6c7affa33183fbf9 BSD 4_3_Net_2 development Work on file usr/src/contrib/rcs/src/rcssyn.c Synthesized-from: CSRG/cd2/net.2 --- diff --git a/usr/src/contrib/rcs/src/rcssyn.c b/usr/src/contrib/rcs/src/rcssyn.c new file mode 100644 index 0000000000..c317a60ca8 --- /dev/null +++ b/usr/src/contrib/rcs/src/rcssyn.c @@ -0,0 +1,569 @@ +/* + * RCS file input + */ +#ifndef lint +static char rcsid[]= "$Id: rcssyn.c,v 4.6 89/05/01 15:13:32 narten Exp $ Purdue CS"; +#endif +/********************************************************************************* + * Syntax Analysis. + * Keyword table + * Testprogram: define SYNDB + * Compatibility with Release 2: define COMPAT2 + ********************************************************************************* + */ + +/* Copyright (C) 1982, 1988, 1989 Walter Tichy + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Walter Tichy. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Report all problems and direct all questions to: + * rcs-bugs@cs.purdue.edu + * + + + + + + + +*/ + + +/* $Log: rcssyn.c,v $ + * Revision 4.6 89/05/01 15:13:32 narten + * changed copyright header to reflect current distribution rules + * + * Revision 4.5 88/11/08 12:00:37 narten + * changes from eggert@sm.unisys.com (Paul Eggert) + * + * Revision 4.5 88/08/09 19:13:21 eggert + * Allow cc -R; remove lint. + * + * Revision 4.4 87/12/18 11:46:16 narten + * more lint cleanups (Guy Harris) + * + * Revision 4.3 87/10/18 10:39:36 narten + * Updating version numbers. Changes relative to 1.1 actually relative to + * 4.1 + * + * Revision 1.3 87/09/24 14:00:49 narten + * Sources now pass through lint (if you ignore printf/sprintf/fprintf + * warnings) + * + * Revision 1.2 87/03/27 14:22:40 jenkins + * Port to suns + * + * Revision 1.1 84/01/23 14:50:40 kcs + * Initial revision + * + * Revision 4.1 83/03/28 11:38:49 wft + * Added parsing and printing of default branch. + * + * Revision 3.6 83/01/15 17:46:50 wft + * Changed readdelta() to initialize selector and log-pointer. + * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM. + * + * Revision 3.5 82/12/08 21:58:58 wft + * renamed Commentleader to Commleader. + * + * Revision 3.4 82/12/04 13:24:40 wft + * Added routine gettree(), which updates keeplock after reading the + * delta tree. + * + * Revision 3.3 82/11/28 21:30:11 wft + * Reading and printing of Suffix removed; version COMPAT2 skips the + * Suffix for files of release 2 format. Fixed problems with printing nil. + * + * Revision 3.2 82/10/18 21:18:25 wft + * renamed putdeltatext to putdtext. + * + * Revision 3.1 82/10/11 19:45:11 wft + * made sure getc() returns into an integer. + */ + + + +/* +#define COMPAT2 +/* version COMPAT2 reads files of the format of release 2 and 3, but + * generates files of release 3 format. Need not be defined if no + * old RCS files generated with release 2 exist. + */ +/* +#define SYNDB +/* version SYNDB is for debugging the syntax analysis for RCS files. + * SYNDB performs additional error checks. + */ +/* +#define SYNTEST +/* version SYNTEST inputs a RCS file and then prints out its internal + * data structures. +*/ + +#include "rcsbase.h" +extern FILE * finptr; /*RCS input file*/ +extern char * getid(); +extern struct hshentry * getnum(); +extern int getkey(); +extern int getlex(); +extern readstring(); +extern savestring(); + +/* forward */ +char * getkeyval(); + +/* keyword table */ + +char Kaccess[] = "access"; +char Kauthor[] = "author"; +char Kbranch[] = "branch"; +char Kbranches[] = "branches"; +char Kcomment[] = "comment"; +char Kdate[] = "date"; +char Kdesc[] = "desc"; +char Khead[] = "head"; +char Klocks[] = "locks"; +char Klog[] = "log"; +char Knext[] = "next"; +char Kstate[] = "state"; +char Kstrict[] = "strict"; +#ifdef COMPAT2 +char Ksuffix[] = "suffix"; +#endif +char Ksymbols[] = "symbols"; +char Ktext[] = "text"; + +#define COMMLENGTH 20 +char Commleader[COMMLENGTH]; +char * Comment; +struct access * AccessList; +struct access * LastAccess; +struct assoc * Symbols; +struct assoc * LastSymbol; +struct lock * Locks; +struct lock * LastLock; +int StrictLocks; +struct hshentry * Head; +struct hshentry * Dbranch; +int TotalDeltas; + + + +getadmin() +/* Function: Reads an and initializes the globals + * AccessList, LastAccess, Symbols, LastSymbol, + * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas; + */ +{ + register char * id; + struct access * newaccess; + struct assoc * newassoc; + struct lock * newlock; + struct hshentry * delta; + + Comment=""; + AccessList=LastAccess=nil; + Symbols=LastSymbol=nil; + Locks=LastLock=nil; + Dbranch = Head = nil; + TotalDeltas=0; + + if (!getkey(Khead)) fatserror("Missing head"); + Head=getnum(); +# ifdef SYNDB + if (Head&&((countnumflds(Head->num)%2)!=0)) + serror("Delta number required for head"); +# endif + if (!getlex(SEMI)) serror("Missing ';' after head"); + + if (getkey(Kbranch)) { /* optional */ + Dbranch=getnum(); + if (!getlex(SEMI)) serror("Missing ';' after branch list"); + } + + +#ifdef COMPAT2 + /* read suffix. Only in release 2 format */ + if (getkey(Ksuffix)) { + if (nexttok==STRING) { + readstring(); nextlex(); /*through away the suffix*/ + } elsif(nexttok==ID) { + nextlex(); + } + if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix); + } +#endif + + if (!getkey(Kaccess)) fatserror("Missing access list"); + while (id=getid()) { + newaccess = (struct access *)talloc(sizeof(struct access)); + newaccess->login = id; + newaccess->nextaccess = nil; + if (AccessList == nil) { + AccessList=LastAccess=newaccess; + } else { + LastAccess=LastAccess->nextaccess=newaccess; + } + } + if (!getlex(SEMI)) serror("Missing ';' after access list"); + + if (!getkey(Ksymbols)) fatserror("Missing symbols"); + while (id = getid()) { + if (!getlex(COLON)) + serror("Missing ':' in symbolic name definition"); + if (!(delta=getnum())) { + serror("Missing number in symbolic name definition"); + } else { /*add new pair to association list*/ + newassoc=(struct assoc *)talloc(sizeof(struct assoc)); + newassoc->symbol=id; + newassoc->delta=delta; + newassoc->nextassoc=nil; + if (Symbols == nil) { + Symbols=LastSymbol=newassoc; + } else { + LastSymbol=LastSymbol->nextassoc=newassoc; + } + } + } + if (!getlex(SEMI)) serror("Missing ';' after symbolic names"); + + if (!getkey(Klocks)) serror("Missing locks"); + while (id = getid()) { + if (!getlex(COLON)) + serror("Missing ':' in lock"); + if (!(delta=getnum())) { + serror("Missing number in lock"); + } else { /*add new pair to lock list*/ +# ifdef SYNDB + if ((countnumflds(delta->num)%2)!=0) + serror("Delta number required for lock"); +# endif + newlock=(struct lock *)talloc(sizeof(struct lock)); + newlock->login=id; + newlock->delta=delta; + newlock->nextlock=nil; + if (Locks == nil) { + Locks=LastLock=newlock; + } else { + LastLock=LastLock->nextlock=newlock; + } + } + } + if (!getlex(SEMI)) serror("Missing ';' after locks"); + if (!getkey(Kstrict)) { + StrictLocks = false; + } else { + StrictLocks = true; + if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict); + } + if (getkey(Kcomment) && (nexttok==STRING)) { + VOID savestring(Commleader,COMMLENGTH);nextlex(); + Comment=Commleader; + if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment); + } +} + + + +getdelta() +/* Function: reads a delta block. + * returns false if the current block does not start with a number. + */ +{ + register struct hshentry * Delta, * num; + struct branchhead * LastBranch, * NewBranch; + + if (!(Delta=getnum())) return false; +# ifdef SYNDB + if ((countnumflds(Delta->num)%2)!=0) + serror("Delta number required"); +# endif + + hshenter = false; /*Don't enter dates into hashtable*/ + Delta->date = getkeyval(Kdate, NUM, false); + hshenter=true; /*reset hshenter for revision numbers.*/ + + Delta->author = getkeyval(Kauthor, ID, false); + + Delta->state = getkeyval(Kstate, ID, true); + + if (!getkey(Kbranches)) fatserror("Missing branches"); + Delta->branches = LastBranch=nil; + while (num=getnum()) { +# ifdef SYNDB + if ((countnumflds(num->num)%2)!=0) + serror("Delta number required"); +# endif + NewBranch = (struct branchhead *)talloc(sizeof(struct branchhead)); + NewBranch->hsh = num; + NewBranch->nextbranch = nil; + if (LastBranch == nil) { + Delta->branches=LastBranch=NewBranch; + } else { + LastBranch=LastBranch->nextbranch=NewBranch; + } + } + if (!getlex(SEMI)) serror("Missing ';' after branches"); + + if (!getkey(Knext)) fatserror("Missing next"); + Delta->next=num=getnum(); +# ifdef SYNDB + if (num&&((countnumflds(num->num)%2)!=0)) + serror("Delta number required"); +# endif + if (!getlex(SEMI)) serror("Missing ';' after next"); + Delta->log=Delta->lockedby = nil; + Delta->selector = '\0'; + TotalDeltas++; + return (true); +} + + +gettree() +/* Function: Reads in the delta tree with getdelta(), then + * updates the lockedby fields. + */ +{ struct lock * currlock; + while (getdelta()); + currlock=Locks; + while (currlock) { + currlock->delta->lockedby = currlock->login; + currlock = currlock->nextlock; + } +} + + +getdesc(prdesc) +int prdesc; +/* Function: read in descriptive text + * nexttok is not advanced afterwards. + * if prdesc==true, the text is printed to stdout. + */ +{ + + if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text"); + if (prdesc) + printstring(); /*echo string*/ + else readstring(); /*skip string*/ +} + + + + + + +char * getkeyval(keyword, token, optional) +enum tokens token; char * keyword; int optional; +/* reads a pair of the form + * ; + * where token is one of or . optional indicates whether + * is optional. A pointer to + * the acutal character string of or node read with getadmin() to file fout. + * Assumption: Variables AccessList, Symbols, Locks, StrictLocks, + * and Head have been set. + */ +{ struct assoc * curassoc; + struct lock * curlock; + struct access * curaccess; + register char * sp; + + VOID fputs(Khead,fout); VOID fputs(" ",fout); + if (Head) VOID fputs(Head->num,fout); + + VOID fprintf(fout,";\n%s ",Kbranch); + if (Dbranch) VOID fputs(Dbranch->num,fout); + + VOID fprintf(fout,";\n%s ",Kaccess); + curaccess = AccessList; + if (curaccess==nil) VOID putc(' ',fout); + while (curaccess) { + VOID putc(' ',fout); + VOID fputs(curaccess->login,fout); + curaccess = curaccess->nextaccess; + } + VOID fprintf(fout,";\n%s ",Ksymbols); + curassoc = Symbols; + if (curassoc==nil) VOID putc(' ',fout); + while (curassoc) { + VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num); + curassoc = curassoc->nextassoc; + } + VOID fprintf(fout,";\n%s ",Klocks); + curlock = Locks; + if (curlock==nil) VOID putc(' ',fout); + while (curlock) { + VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num); + curlock = curlock->nextlock; + } + if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict); + VOID fprintf(fout,";\n%s %c",Kcomment,SDELIM); + if((sp=Comment)!=nil) { + while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout); + } + VOID fprintf(fout,"%c;\n\n",SDELIM); +} + + + + +putdelta(node,fout) +register struct hshentry * node; +register FILE * fout; +/* Function: prints a node to fout; + */ +{ struct branchhead * nextbranch; + + if (node == nil) return; + + VOID fprintf(fout,"\n%s\n",node->num); + VOID fprintf(fout,"%s %s; %s %s; %s ", + Kdate,node->date,Kauthor,node->author,Kstate); + if (node->state!=nil) VOID fputs(node->state,fout); + VOID fputs(";\nbranches",fout); + nextbranch = node->branches; + if (nextbranch==nil) VOID putc(' ',fout); + while (nextbranch) { + VOID putc(' ',fout); + VOID fputs(nextbranch->hsh->num,fout); + nextbranch = nextbranch->nextbranch; + } + + VOID fprintf(fout,";\n%s ",Knext); + if (node->next!=nil) VOID fputs(node->next->num,fout); + VOID fputs(";\n",fout); + +} + + + + +puttree(root,fout) +struct hshentry * root; +register FILE * fout; +/* Function: prints the delta tree in preorder to fout, starting with root. + */ +{ struct branchhead * nextbranch; + + if (root==nil) return; + + if (root->selector !=DELETE)putdelta(root,fout); + /* selector DELETE means deleted; set by rcs -o */ + + puttree(root->next,fout); + + nextbranch = root->branches; + while (nextbranch) { + puttree(nextbranch->hsh,fout); + nextbranch = nextbranch->nextbranch; + } +} + + + +int putdtext(num,log,srcfilename,fout) +char * num, * log, * srcfilename; FILE * fout; +/* Function: write a deltatext-node to fout. + * num points to the deltanumber, log to the logmessage, and + * sourcefile contains the text. Doubles up all SDELIMs in both the + * log and the text; Makes sure the log message ends in \n. + * returns false on error. + */ +{ + register char * sp; + register int c; + register FILE * fin; + + VOID fprintf(fout,DELNUMFORM,num,Klog); + /* put log */ + VOID putc(SDELIM,fout); + sp=log; + while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout); + if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/ + /* put text */ + VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM); + if ((fin=fopen(srcfilename,"r"))==NULL) { + error("Can't open source file %s",srcfilename); + return false; + } + while ((c=fgetc(fin))!=EOF) { + if (c==SDELIM) VOID putc(SDELIM,fout); /*double up SDELIM*/ + VOID putc(c,fout); + } + VOID putc(SDELIM,fout); VOID putc('\n',fout); + VOID fclose(fin); + return true; +} + + + +#ifdef SYNTEST + +main(argc,argv) +int argc; char * argv[]; +{ + + cmdid = "syntest"; + if (argc<2) { + VOID fputs("No input file\n",stderr); + exit(-1); + } + if ((finptr=fopen(argv[1], "r")) == NULL) { + faterror("Can't open input file %s\n",argv[1]); + } + Lexinit(); + getadmin(); + putadmin(stdout); + + gettree(); + puttree(Head,stdout); + + getdesc(true); + + if (nextlex(),nexttok!=EOFILE) { + fatserror("Syntax error"); + } + exit(0); +} + + +cleanup(){} +/*dummy*/ + + +#endif +