📄 rcssyn.c
字号:
/* * RCS file input *//********************************************************************************* * Syntax Analysis. * Keyword table * Testprogram: define SYNTEST * Compatibility with Release 2: define COMPAT2=1 ********************************************************************************* *//* Copyright (C) 1982, 1988, 1989 Walter Tichy Copyright 1990, 1991 by Paul Eggert 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 modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with RCS; see the file COPYING. If not, write tothe 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.8 1991/08/19 03:13:55 eggert * Tune. * * Revision 5.7 1991/04/21 11:58:29 eggert * Disambiguate names on shortname hosts. * Fix errno bug. Add MS-DOS support. * * Revision 5.6 1991/02/28 19:18:51 eggert * Fix null termination bug in reporting keyword expansion. * * Revision 5.5 1991/02/25 07:12:44 eggert * Check diff output more carefully; avoid overflow. * * Revision 5.4 1990/11/01 05:28:48 eggert * When ignoring unknown phrases, copy them to the output RCS file. * Permit arbitrary data in logs and comment leaders. * Don't check for nontext on initial checkin. * * Revision 5.3 1990/09/20 07:58:32 eggert * Remove the test for non-text bytes; it caused more pain than it cured. * * Revision 5.2 1990/09/04 08:02:30 eggert * Parse RCS files with no revisions. * Don't strip leading white space from diff commands. Count RCS lines better. * * Revision 5.1 1990/08/29 07:14:06 eggert * Add -kkvl. Clean old log messages too. * * Revision 5.0 1990/08/22 08:13:44 eggert * Try to parse future RCS formats without barfing. * Add -k. Don't require final newline. * Remove compile-time limits; use malloc instead. * Don't output branch keyword if there's no default branch, * because RCS version 3 doesn't understand it. * Tune. Remove lint. * Add support for ISO 8859. Ansify and Posixate. * Check that a newly checked-in file is acceptable as input to 'diff'. * Check diff's output. * * Revision 4.6 89/05/01 15:13:32 narten * changed copyright header to reflect current distribution rules * * 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 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. *//* 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. *//* version SYNTEST inputs a RCS file and then prints out its internal * data structures.*/#include "rcsbase.h"libId(synId, "$Id: rcssyn.c,v 5.8 1991/08/19 03:13:55 eggert Exp $")/* forward */static char const *getkeyval P((char const*,enum tokens,int));static int strn2expmode P((char const*,size_t));/* keyword table */char const Kdesc[] = "desc", Klog[] = "log", Ktext[] = "text";static char const Kaccess[] = "access", Kauthor[] = "author", Kbranch[] = "branch", K_branches[]= "branches", Kcomment[] = "comment", Kdate[] = "date", Kexpand[] = "expand", Khead[] = "head", Klocks[] = "locks", Knext[] = "next", Kstate[] = "state", Kstrict[] = "strict",#if COMPAT2 Ksuffix[] = "suffix",#endif Ksymbols[] = "symbols";static struct buf Commleader;static struct cbuf Ignored;struct cbuf Comment;struct access * AccessList;struct assoc * Symbols;struct lock * Locks;int Expand;int StrictLocks;struct hshentry * Head;char const * Dbranch;unsigned TotalDeltas; static voidgetsemi(key) char const *key;/* Get a semicolon to finish off a phrase started by KEY. */{ if (!getlex(SEMI)) fatserror("missing ';' after '%s'", key);} static struct hshentry *getdnum()/* Get a delta number. */{ register struct hshentry *delta = getnum(); if (delta && countnumflds(delta->num)&1) fatserror("%s isn't a delta number", delta->num); return delta;} voidgetadmin()/* Read an <admin> and initialize the appropriate global variables. */{ register char const *id; struct access * newaccess; struct assoc * newassoc; struct lock * newlock; struct hshentry * delta; struct access **LastAccess; struct assoc **LastSymbol; struct lock **LastLock; struct buf b; struct cbuf cb; TotalDeltas=0; getkey(Khead); Head = getdnum(); getsemi(Khead); Dbranch = nil; if (getkeyopt(Kbranch)) { if ((delta = getnum())) Dbranch = delta->num; getsemi(Kbranch); }#if COMPAT2 /* read suffix. Only in release 2 format */ if (getkeyopt(Ksuffix)) { if (nexttok==STRING) { readstring(); nextlex(); /* Throw away the suffix. */ } else if (nexttok==ID) { nextlex(); } getsemi(Ksuffix); }#endif getkey(Kaccess); LastAccess = &AccessList; while (id=getid()) { newaccess = ftalloc(struct access); newaccess->login = id; *LastAccess = newaccess; LastAccess = &newaccess->nextaccess; } *LastAccess = nil; getsemi(Kaccess); getkey(Ksymbols); LastSymbol = &Symbols; while (id = getid()) { if (!getlex(COLON)) fatserror("missing ':' in symbolic name definition"); if (!(delta=getnum())) { fatserror("missing number in symbolic name definition"); } else { /*add new pair to association list*/ newassoc = ftalloc(struct assoc); newassoc->symbol=id; newassoc->num = delta->num; *LastSymbol = newassoc; LastSymbol = &newassoc->nextassoc; } } *LastSymbol = nil; getsemi(Ksymbols); getkey(Klocks); LastLock = &Locks; while (id = getid()) { if (!getlex(COLON)) fatserror("missing ':' in lock"); if (!(delta=getdnum())) { fatserror("missing number in lock"); } else { /*add new pair to lock list*/ newlock = ftalloc(struct lock); newlock->login=id; newlock->delta=delta; *LastLock = newlock; LastLock = &newlock->nextlock; } } *LastLock = nil; getsemi(Klocks); if ((StrictLocks = getkeyopt(Kstrict))) getsemi(Kstrict); Comment.size = 0; if (getkeyopt(Kcomment)) { if (nexttok==STRING) { Comment = savestring(&Commleader); nextlex(); } getsemi(Kcomment); } Expand = KEYVAL_EXPAND; if (getkeyopt(Kexpand)) { if (nexttok==STRING) { bufautobegin(&b); cb = savestring(&b); if ((Expand = strn2expmode(cb.string,cb.size)) < 0) fatserror("unknown expand mode %.*s", (int)cb.size, cb.string ); bufautoend(&b); nextlex(); } getsemi(Kexpand); } Ignored = getphrases(Kdesc);}char const *const expand_names[] = { /* These must agree with *_EXPAND in rcsbase.h. */ "kv","kvl","k","v","o", 0}; intstr2expmode(s) char const *s;/* Yield expand mode corresponding to S, or -1 if bad. */{ return strn2expmode(s, strlen(s));} static intstrn2expmode(s, n) char const *s; size_t n;{ char const *const *p; for (p = expand_names; *p; ++p) if (memcmp(*p,s,n) == 0 && !(*p)[n]) return p - expand_names; return -1;} voidignorephrase()/* Ignore a phrase introduced by a later version of RCS. */{ warnignore(); hshenter=false; for (;;) { switch (nexttok) { case SEMI: hshenter=true; nextlex(); return; case ID: case NUM: ffree1(NextString); break; case STRING: readstring(); break; default: break; } nextlex(); }} static intgetdelta()/* 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 = getdnum())) return false; 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); getkey(K_branches); LastBranch = &Delta->branches; while ((num = getdnum())) { NewBranch = ftalloc(struct branchhead); NewBranch->hsh = num; *LastBranch = NewBranch; LastBranch = &NewBranch->nextbranch; } *LastBranch = nil; getsemi(K_branches); getkey(Knext); Delta->next = num = getdnum(); getsemi(Knext); Delta->lockedby = nil; Delta->log.string = 0; Delta->selector = true; Delta->ig = getphrases(Kdesc); TotalDeltas++; return (true);} voidgettree()/* Function: Reads in the delta tree with getdelta(), then * updates the lockedby fields. */{ struct lock const *currlock; while (getdelta()); currlock=Locks; while (currlock) { currlock->delta->lockedby = currlock->login; currlock = currlock->nextlock; }} voidgetdesc(prdesc)int prdesc;/* Function: read in descriptive text * nexttok is not advanced afterwards. * If prdesc is set, the text is printed to stdout.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -