home *** CD-ROM | disk | FTP | other *** search
- /*
- * RCS file input
- */
- #ifndef lint
- static char rcsid[]= "$Id: rcssyn.c,v 5.2 90/07/15 11:35:24 ROOT_DOS Release $ Purdue CS";
- #endif
- /*********************************************************************************
- * Syntax Analysis.
- * Keyword table
- * Testprogram: define SYNDB
- * Compatibility with Release 2: define COMPAT2
- *********************************************************************************
- */
-
- /* Copyright (C) 1982, 1988, 1989 Walter Tichy
- Distributed under license by the Free Software Foundation, Inc.
-
- This file is part of RCS.
-
- RCS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- RCS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with RCS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Report problems and direct all questions to:
-
- rcs-bugs@cs.purdue.edu
-
- */
-
-
- /* $Log: rcssyn.c,v $
- * Revision 5.2 90/07/15 11:35:24 ROOT_DOS
- * DOS version of RCS 4.0 checked in for MODS
- * by lfk@athena.mit.edu
- * Also update to MSC 6.0
- *
- * 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 <admin> 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
- * <keyword> <token> ;
- * where token is one of <id> or <num>. optional indicates whether
- * <token> is optional. A pointer to
- * the acutal character string of <id> or <num) is returned.
- * Getkeyval terminates the program on missing keyword or token, continues
- * on missing ;.
- */
- {
- register char * val;
-
- if (!getkey(keyword)) {
- fatserror("Missing %s", keyword);
- }
- if (nexttok==token) {
- val = NextString;
- nextlex();
- } else {
- if (!optional) {fatserror("Missing %s", keyword); }
- else val = nil;
- }
- if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
- return(val);
- }
-
-
-
-
- putadmin(fout)
- register FILE * fout;
- /* Function: Print the <admin> 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 <delta> 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
-
-