📄 rcskeep.c
字号:
/* * RCS keyword extraction *//***************************************************************************** * main routine: getoldkeys() * Testprogram: define KEEPTEST ***************************************************************************** *//* 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: rcskeep.c,v $ * Revision 5.4 1991/08/19 03:13:55 eggert * Tune. * * Revision 5.3 1991/04/21 11:58:25 eggert * Shorten names to keep them distinct on shortname hosts. * * Revision 5.2 1990/10/04 06:30:20 eggert * Parse time zone offsets; future RCS versions may output them. * * Revision 5.1 1990/09/20 02:38:56 eggert * ci -k now checks dates more thoroughly. * * Revision 5.0 1990/08/22 08:12:53 eggert * Retrieve old log message if there is one. * Don't require final newline. * Remove compile-time limits; use malloc instead. Tune. * Permit dates past 1999/12/31. Ansify and Posixate. * * Revision 4.6 89/05/01 15:12:56 narten * changed copyright header to reflect current distribution rules * * Revision 4.5 88/08/09 19:13:03 eggert * Remove lint and speed up by making FILE *fp local, not global. * * Revision 4.4 87/12/18 11:44:21 narten * more lint cleanups (Guy Harris) * * Revision 4.3 87/10/18 10:35:50 narten * Updating version numbers. Changes relative to 1.1 actually relative * to 4.1 * * Revision 1.3 87/09/24 14:00:00 narten * Sources now pass through lint (if you ignore printf/sprintf/fprintf * warnings) * * Revision 1.2 87/03/27 14:22:29 jenkins * Port to suns * * Revision 4.1 83/05/10 16:26:44 wft * Added new markers Id and RCSfile; extraction added. * Marker matching with trymatch(). * * Revision 3.2 82/12/24 12:08:26 wft * added missing #endif. * * Revision 3.1 82/12/04 13:22:41 wft * Initial revision. * *//*#define KEEPTEST*//* Testprogram; prints out the keyword values found. */#include "rcsbase.h"libId(keepId, "$Id: rcskeep.c,v 5.4 1991/08/19 03:13:55 eggert Exp $")static int checknum P((char const*,int));static int getval P((RILE*,struct buf*,int));static int get0val P((int,RILE*,struct buf*,int));static int keepdate P((RILE*));static int keepid P((int,RILE*,struct buf*));static int keeprev P((RILE*));int prevkeys;struct buf prevauthor, prevdate, prevrev, prevstate; intgetoldkeys(fp) register RILE *fp;/* Function: Tries to read keyword values for author, date, * revision number, and state out of the file fp. * If FNAME is nonnull, it is opened and closed instead of using FP. * The results are placed into * prevauthor, prevdate, prevrev, prevstate. * Aborts immediately if it finds an error and returns false. * If it returns true, it doesn't mean that any of the * values were found; instead, check to see whether the corresponding arrays * contain the empty string. */{ register int c; char keyword[keylength+1]; register char * tp; int needs_closing; if (prevkeys) return true; needs_closing = false; if (!fp) { if (!(fp = Iopen(workfilename, FOPEN_R_WORK, (struct stat*)0))) { eerror(workfilename); return false; } needs_closing = true; } /* initialize to empty */ bufscpy(&prevauthor, ""); bufscpy(&prevdate, ""); bufscpy(&prevrev, ""); bufscpy(&prevstate, ""); c = '\0'; /* anything but KDELIM */ for (;;) { if ( c==KDELIM) { do { /* try to get keyword */ tp = keyword; for (;;) { Igeteof(fp, c, goto ok;); switch (c) { default: if (keyword+keylength <= tp) break; *tp++ = c; continue; case '\n': case KDELIM: case VDELIM: break; } break; } } while (c==KDELIM); if (c!=VDELIM) continue; *tp = c; Igeteof(fp, c, break;); switch (c) { case ' ': case '\t': break; default: continue; } switch (trymatch(keyword)) { case Author: if (!keepid(0, fp, &prevauthor)) return false; c = 0; break; case Date: if (!(c = keepdate(fp))) return false; break; case Header: case Id: if (!( getval(fp, (struct buf*)nil, false) && keeprev(fp) && (c = keepdate(fp)) && keepid(c, fp, &prevauthor) && keepid(0, fp, &prevstate) )) return false; /* Skip either ``who'' (new form) or ``Locker: who'' (old). */ if (getval(fp, (struct buf*)nil, true) && getval(fp, (struct buf*)nil, true)) c = 0; else if (nerror) return false; else c = KDELIM; break; case Locker: case Log: case RCSfile: case Source: if (!getval(fp, (struct buf*)nil, false)) return false; c = 0; break; case Revision: if (!keeprev(fp)) return false; c = 0; break; case State: if (!keepid(0, fp, &prevstate)) return false; c = 0; break; default: continue; } if (!c) Igeteof(fp, c, c=0;); if (c != KDELIM) { error("closing %c missing on keyword", KDELIM); return false; } if (*prevauthor.string && *prevdate.string && *prevrev.string && *prevstate.string) { break; } } Igeteof(fp, c, break;); } ok: if (needs_closing) Ifclose(fp); else Irewind(fp); prevkeys = true; return true;} static intbadly_terminated(){ error("badly terminated keyword value"); return false;} static intgetval(fp, target, optional) register RILE *fp; struct buf *target; int optional;/* Reads a keyword value from FP into TARGET. * Returns true if one is found, false otherwise. * Does not modify target if it is nil. * Do not report an error if OPTIONAL is set and KDELIM is found instead. */{ int c; Igeteof(fp, c, return badly_terminated();); return get0val(c, fp, target, optional);} static intget0val(c, fp, target, optional) register int c; register RILE *fp; struct buf *target; int optional;/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly. * Same as getval, except C is the lookahead character. */{ register char * tp; char const *tlim; register int got1; if (target) { bufalloc(target, 1); tp = target->string; tlim = tp + target->size; } else tlim = tp = 0; got1 = false; for (;;) { switch (c) { default: got1 = true; if (tp) { *tp++ = c; if (tlim <= tp) tp = bufenlarge(target, &tlim); } break; case ' ': case '\t': if (tp) { *tp = 0;# ifdef KEEPTEST VOID printf("getval: %s\n", target);# endif } if (!got1) error("too much white space in keyword value"); return got1; case KDELIM: if (!got1 && optional) return false; /* fall into */ case '\n': case 0: return badly_terminated(); } Igeteof(fp, c, return badly_terminated();); }} static intkeepdate(fp) RILE *fp;/* Function: reads a date prevdate; checks format * Return 0 on error, lookahead character otherwise. */{ struct buf prevday, prevtime, prevzone; register char const *p; register int c; c = 0; bufautobegin(&prevday); if (getval(fp,&prevday,false)) { bufautobegin(&prevtime); if (getval(fp,&prevtime,false)) { bufautobegin(&prevzone); bufscpy(&prevzone, ""); Igeteof(fp, c, c=0;); if (c=='-' || c=='+') if (!get0val(c,fp,&prevzone,false)) c = 0; else Igeteof(fp, c, c=0;); if (c) { p = prevday.string; bufalloc(&prevdate, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5); VOID sprintf(prevdate.string, "%s%s %s %s", /* Parse dates put out by old versions of RCS. */ isdigit(p[0]) && isdigit(p[1]) && p[2]=='/' ? "19" : "", p, prevtime.string, prevzone.string ); } bufautoend(&prevzone); } bufautoend(&prevtime); } bufautoend(&prevday); return c;} static intkeepid(c, fp, b) int c; RILE *fp; struct buf *b;/* Get previous identifier from C+FP into B. */{ if (!c) Igeteof(fp, c, return false;); if (!get0val(c, fp, b, false)) return false; checksid(b->string); return true;} static intkeeprev(fp) RILE *fp;/* Get previous revision from FP into prevrev. */{ return getval(fp,&prevrev,false) && checknum(prevrev.string,-1);} static intchecknum(sp,fields) register char const *sp; int fields;{ register int dotcount; dotcount=0; while(*sp) { if (*sp=='.') dotcount++; else if (!isdigit(*sp)) return false; sp++; } return fields<0 ? dotcount&1 : dotcount==fields;}#ifdef KEEPTESTchar const cmdid[] ="keeptest"; intmain(argc, argv)int argc; char *argv[];{ while (*(++argv)) { workfilename = *argv; getoldkeys((RILE*)0); VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n", *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string); } exitmain(EXIT_SUCCESS);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -