+/*
+ * RCS keyword extraction
+ */
+#ifndef lint
+static char rcsid[]= "$Id: rcskeep.c,v 4.4 87/12/18 11:44:21 narten Exp $ Purdue CS";
+#endif
+/*****************************************************************************
+ * main routine: getoldkeys()
+ * Testprogram: define KEEPTEST
+ *****************************************************************************
+ *
+ * Copyright (C) 1982 by Walter F. Tichy
+ * Purdue University
+ * Computer Science Department
+ * West Lafayette, IN 47907
+ *
+ * All rights reserved. No part of this software may be sold or distributed
+ * in any form or by any means without the prior written permission of the
+ * author.
+ * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
+ */
+
+
+
+/* $Log: rcskeep.c,v $
+ * 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 1.1 84/01/23 14:50:30 kcs
+ * Initial revision
+ *
+ * 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"
+extern char * checkid();
+extern FILE * fopen();
+static int getval();
+extern enum markers trymatch();
+
+FILE * fp;
+#define IDLENGTH 30
+char prevauthor[IDLENGTH];
+char prevdate[datelength];
+char prevRCS[NCPFN];
+char prevrev[revlength];
+char prevsource[NCPPN];
+char prevstate [IDLENGTH];
+char prevlocker[IDLENGTH];
+char dummy[IDLENGTH];
+
+getoldkeys(fname)
+char * fname;
+/* Function: Tries to read keyword values for author, date,
+ * revision number, RCS file, (both with and without path),
+ * state, and workfilename out of the file fname.
+ * The results are placed into
+ * prevauthor, prevdate, prevRCS, prevrev, prevsource, 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+2];
+ register char * tp;
+ enum markers mresult;
+
+ /* initialize to empty */
+ prevauthor[0]=prevsource[0]=prevstate[0]=prevdate[0]=prevrev[0]= '\0';
+
+ if ( (fp = fopen(fname, "r") ) == NULL ) {
+ error("Can't open %s\n", fname);
+ return false;
+ }
+ while( (c=getc(fp)) != EOF) {
+ if ( c==KDELIM) {
+ /* try to get keyword */
+ tp = keyword;
+ while( (c=getc(fp))!=EOF && (tp< keyword+keylength) && (c!='\n')
+ && (c!=KDELIM) && (c!=VDELIM))
+ *tp++ = c;
+
+ if (c==KDELIM) {VOID ungetc(c,fp);continue;}
+ if (c!=VDELIM) continue;
+ *tp++ = c;
+ *tp='\0';
+ while ((c=getc(fp))==' '||c=='\t'); /* skip blanks */
+ VOID ungetc(c,fp); /* needed for getval */
+
+ switch (mresult=trymatch(keyword,true)) {
+ case Author:
+ if (getval(prevauthor,IDLENGTH,true))
+ if (!checkid(prevauthor, '\0')) goto errexit;
+ break;
+ case Date:
+ if (!getprevdate(true)) goto errexit;
+ break;
+ case Header:
+ case Id:
+ if (mresult==Header) {
+ if (!getval(prevsource,NCPPN,true)) break; /*unexpanded*/
+ } else {
+ if (!getval(prevRCS,NCPFN,true)) break; /*unexpanded*/
+ }
+ if (!getval(prevrev,revlength,false)) goto errexit;
+ if (!checknum(prevrev,-1)) {
+ error("Bad revision number");
+ goto errexit;
+ }
+ if (!getprevdate(false)) goto errexit;
+ if (!getval(prevauthor,IDLENGTH,false)) goto errexit;
+ if (!checkid(prevauthor, '\0')) goto errexit;
+ if (!getval(prevstate,IDLENGTH,false)) goto errexit;
+ if (!checkid(prevstate, '\0')) goto errexit;
+ VOID getval(dummy, IDLENGTH, true); /* optional locker*/
+ VOID getval(prevlocker,IDLENGTH,true); /* optional locker*/
+ break;
+ case Locker:
+ VOID getval(prevlocker,IDLENGTH,true);
+ if (!checkid(prevlocker, '\0')) goto errexit;
+ break;
+ case Log:
+ VOID getval(prevRCS,NCPPN,true);
+ break;
+ case RCSfile:
+ VOID getval(prevRCS,NCPFN,true);
+ break;
+ case Revision:
+ if (getval(prevrev,revlength,true))
+ if (!checknum(prevrev,-1)) {
+ error("Bad revision number");
+ goto errexit;
+ }
+ break;
+ case Source:
+ VOID getval(prevsource,NCPPN,true);
+ break;
+ case State:
+ if (getval(prevstate,IDLENGTH,true))
+ if (!checkid(prevstate, '\0')) goto errexit;
+ break;
+ default:
+ continue;
+ }
+ if (getc(fp)!=KDELIM)
+ warn("Closing %c missing on keyword",KDELIM);
+ if (prevauthor[0]!='\0'&&prevrev[0]!='\0'&&prevstate[0]!='\0'&&
+ prevdate[0]!='\0' &&
+ ((prevsource[0]!='\0')||(prevRCS[0]!='\0'))){
+ /* done; prevlocker is irrelevant */
+ break;
+ }
+ }
+ }
+ VOID fclose(fp);
+ return true;
+
+errexit:
+ prevauthor[0]=prevsource[0]=prevstate[0]=prevdate[0]=prevrev[0]= '\0';
+ VOID fclose(fp); return false;
+}
+
+
+static int getval(target,maxchars,optional)
+char * target; int maxchars, optional;
+/* Function: Places a keyword value into target, but not more
+ * than maxchars characters. Prints an error if optional==false
+ * and there is no keyword. Returns true if one is found, false otherwise.
+ */
+{ register char * tp;
+ register int c;
+
+ tp=target;
+ c=getc(fp);
+ if (c==KDELIM) {
+ if (!optional)
+ error("Missing keyword value");
+ VOID ungetc(c,fp);
+ return false;
+ } else {
+ while (!(c==' '||c=='\n'||c=='\t'||c==KDELIM||c==EOF)) {
+ if (tp-target>=maxchars-1) {
+ error("keyword value too long");
+ return false;
+ } else {
+ *tp++ =c;
+ c=getc(fp);
+ }
+ }
+ *tp= '\0';
+# ifdef KEEPTEST
+ VOID printf("getval: %s\n",target);
+# endif
+ while(c==' '||c=='\t') c=getc(fp); /* skip trailing blanks */
+ }
+ VOID ungetc(c,fp);
+ return true;
+}
+
+
+int getprevdate(optional)
+int optional;
+/* Function: reads a date prevdate; checks format
+ * If there is not date and optional==false, an error is printed.
+ * Returns false on error, true otherwise.
+ */
+{ char prevday[10];
+ char prevtime[10];
+
+ prevday[0]=prevtime[0]='\0';
+ if (!getval(prevday,9,optional)) return optional;
+ if (!getval(prevtime,9,false)) return false;
+ /*process date */
+ prevday[2]=prevday[5]=prevday[8]=prevtime[2]=prevtime[5]='.';
+ prevday[9]='\0';
+ VOID strcpy(prevdate,prevday);
+ VOID strcat(prevdate,prevtime);
+ if (!checknum(prevdate,5)) {
+ error("Bad date: %s",prevdate);
+ prevdate[0]='\0';
+ return false;
+ }
+ return true;
+}
+
+int checknum(sp,fields)
+register char * sp; int fields;
+{ register int dotcount;
+ if (sp==nil||*sp=='\0') return true;
+ dotcount=0;
+ while(*sp) {
+ if (*sp=='.') dotcount++;
+ elsif (ctab[*sp]!=DIGIT) return false;
+ sp++;
+ }
+ if (fields >= 0 && dotcount!=fields) return false;
+ return true;
+}
+
+
+
+#ifdef KEEPTEST
+char * RCSfilename, * workfilename;
+
+main(argc, argv)
+int argc; char *argv[];
+{
+ cmdid="keeptest";
+ while (*(++argv)) {
+ if (getoldkeys(*argv))
+ VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n",
+ *argv, prevrev, prevdate, prevauthor,prevstate);
+ VOID printf("Source: %s, RCSfile: %s\n",prevsource,prevRCS);
+ }
+ exit(0);
+}
+#endif