1: /*
2: * RCS keyword extraction
3: */
4: #ifndef lint
5: static char rcsid[]= "$Id: rcskeep.c,v 4.4 87/12/18 11:44:21 narten Exp $ Purdue CS";
6: #endif
7: /*****************************************************************************
8: * main routine: getoldkeys()
9: * Testprogram: define KEEPTEST
10: *****************************************************************************
11: *
12: * Copyright (C) 1982 by Walter F. Tichy
13: * Purdue University
14: * Computer Science Department
15: * West Lafayette, IN 47907
16: *
17: * All rights reserved. No part of this software may be sold or distributed
18: * in any form or by any means without the prior written permission of the
19: * author.
20: * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
21: */
22:
23:
24:
25: /* $Log: rcskeep.c,v $
26: * Revision 4.4 87/12/18 11:44:21 narten
27: * more lint cleanups (Guy Harris)
28: *
29: * Revision 4.3 87/10/18 10:35:50 narten
30: * Updating version numbers. Changes relative to 1.1 actually relative
31: * to 4.1
32: *
33: * Revision 1.3 87/09/24 14:00:00 narten
34: * Sources now pass through lint (if you ignore printf/sprintf/fprintf
35: * warnings)
36: *
37: * Revision 1.2 87/03/27 14:22:29 jenkins
38: * Port to suns
39: *
40: * Revision 1.1 84/01/23 14:50:30 kcs
41: * Initial revision
42: *
43: * Revision 4.1 83/05/10 16:26:44 wft
44: * Added new markers Id and RCSfile; extraction added.
45: * Marker matching with trymatch().
46: *
47: * Revision 3.2 82/12/24 12:08:26 wft
48: * added missing #endif.
49: *
50: * Revision 3.1 82/12/04 13:22:41 wft
51: * Initial revision.
52: *
53: */
54:
55: /*
56: #define KEEPTEST
57: /* Testprogram; prints out the keyword values found. */
58:
59: #include "rcsbase.h"
60: extern char * checkid();
61: extern FILE * fopen();
62: static int getval();
63: extern enum markers trymatch();
64:
65: FILE * fp;
66: #define IDLENGTH 30
67: char prevauthor[IDLENGTH];
68: char prevdate[datelength];
69: char prevRCS[NCPFN];
70: char prevrev[revlength];
71: char prevsource[NCPPN];
72: char prevstate [IDLENGTH];
73: char prevlocker[IDLENGTH];
74: char dummy[IDLENGTH];
75:
76: getoldkeys(fname)
77: char * fname;
78: /* Function: Tries to read keyword values for author, date,
79: * revision number, RCS file, (both with and without path),
80: * state, and workfilename out of the file fname.
81: * The results are placed into
82: * prevauthor, prevdate, prevRCS, prevrev, prevsource, prevstate.
83: * Aborts immediately if it finds an error and returns false.
84: * If it returns true, it doesn't mean that any of the
85: * values were found; instead, check to see whether the corresponding arrays
86: * contain the empty string.
87: */
88: {
89: register int c;
90: char keyword[keylength+2];
91: register char * tp;
92: enum markers mresult;
93:
94: /* initialize to empty */
95: prevauthor[0]=prevsource[0]=prevstate[0]=prevdate[0]=prevrev[0]= '\0';
96:
97: if ( (fp = fopen(fname, "r") ) == NULL ) {
98: error("Can't open %s\n", fname);
99: return false;
100: }
101: while( (c=getc(fp)) != EOF) {
102: if ( c==KDELIM) {
103: /* try to get keyword */
104: tp = keyword;
105: while( (c=getc(fp))!=EOF && (tp< keyword+keylength) && (c!='\n')
106: && (c!=KDELIM) && (c!=VDELIM))
107: *tp++ = c;
108:
109: if (c==KDELIM) {VOID ungetc(c,fp);continue;}
110: if (c!=VDELIM) continue;
111: *tp++ = c;
112: *tp='\0';
113: while ((c=getc(fp))==' '||c=='\t'); /* skip blanks */
114: VOID ungetc(c,fp); /* needed for getval */
115:
116: switch (mresult=trymatch(keyword,true)) {
117: case Author:
118: if (getval(prevauthor,IDLENGTH,true))
119: if (!checkid(prevauthor, '\0')) goto errexit;
120: break;
121: case Date:
122: if (!getprevdate(true)) goto errexit;
123: break;
124: case :
125: case Id:
126: if (mresult==Header) {
127: if (!getval(prevsource,NCPPN,true)) break; /*unexpanded*/
128: } else {
129: if (!getval(prevRCS,NCPFN,true)) break; /*unexpanded*/
130: }
131: if (!getval(prevrev,revlength,false)) goto errexit;
132: if (!checknum(prevrev,-1)) {
133: error("Bad revision number");
134: goto errexit;
135: }
136: if (!getprevdate(false)) goto errexit;
137: if (!getval(prevauthor,IDLENGTH,false)) goto errexit;
138: if (!checkid(prevauthor, '\0')) goto errexit;
139: if (!getval(prevstate,IDLENGTH,false)) goto errexit;
140: if (!checkid(prevstate, '\0')) goto errexit;
141: VOID getval(dummy, IDLENGTH, true); /* optional locker*/
142: VOID getval(prevlocker,IDLENGTH,true); /* optional locker*/
143: break;
144: case Locker:
145: VOID getval(prevlocker,IDLENGTH,true);
146: if (!checkid(prevlocker, '\0')) goto errexit;
147: break;
148: case Log:
149: VOID getval(prevRCS,NCPPN,true);
150: break;
151: case RCSfile:
152: VOID getval(prevRCS,NCPFN,true);
153: break;
154: case Revision:
155: if (getval(prevrev,revlength,true))
156: if (!checknum(prevrev,-1)) {
157: error("Bad revision number");
158: goto errexit;
159: }
160: break;
161: case Source:
162: VOID getval(prevsource,NCPPN,true);
163: break;
164: case State:
165: if (getval(prevstate,IDLENGTH,true))
166: if (!checkid(prevstate, '\0')) goto errexit;
167: break;
168: default:
169: continue;
170: }
171: if (getc(fp)!=KDELIM)
172: warn("Closing %c missing on keyword",KDELIM);
173: if (prevauthor[0]!='\0'&&prevrev[0]!='\0'&&prevstate[0]!='\0'&&
174: prevdate[0]!='\0' &&
175: ((prevsource[0]!='\0')||(prevRCS[0]!='\0'))){
176: /* done; prevlocker is irrelevant */
177: break;
178: }
179: }
180: }
181: VOID fclose(fp);
182: return true;
183:
184: errexit:
185: prevauthor[0]=prevsource[0]=prevstate[0]=prevdate[0]=prevrev[0]= '\0';
186: VOID fclose(fp); return false;
187: }
188:
189:
190: static int getval(target,maxchars,optional)
191: char * target; int maxchars, optional;
192: /* Function: Places a keyword value into target, but not more
193: * than maxchars characters. Prints an error if optional==false
194: * and there is no keyword. Returns true if one is found, false otherwise.
195: */
196: { register char * tp;
197: register int c;
198:
199: tp=target;
200: c=getc(fp);
201: if (c==KDELIM) {
202: if (!optional)
203: error("Missing keyword value");
204: VOID ungetc(c,fp);
205: return false;
206: } else {
207: while (!(c==' '||c=='\n'||c=='\t'||c==KDELIM||c==EOF)) {
208: if (tp-target>=maxchars-1) {
209: error("keyword value too long");
210: return false;
211: } else {
212: *tp++ =c;
213: c=getc(fp);
214: }
215: }
216: *tp= '\0';
217: # ifdef KEEPTEST
218: VOID printf("getval: %s\n",target);
219: # endif
220: while(c==' '||c=='\t') c=getc(fp); /* skip trailing blanks */
221: }
222: VOID ungetc(c,fp);
223: return true;
224: }
225:
226:
227: int getprevdate(optional)
228: int optional;
229: /* Function: reads a date prevdate; checks format
230: * If there is not date and optional==false, an error is printed.
231: * Returns false on error, true otherwise.
232: */
233: { char prevday[10];
234: char prevtime[10];
235:
236: prevday[0]=prevtime[0]='\0';
237: if (!getval(prevday,9,optional)) return optional;
238: if (!getval(prevtime,9,false)) return false;
239: /*process date */
240: prevday[2]=prevday[5]=prevday[8]=prevtime[2]=prevtime[5]='.';
241: prevday[9]='\0';
242: VOID strcpy(prevdate,prevday);
243: VOID strcat(prevdate,prevtime);
244: if (!checknum(prevdate,5)) {
245: error("Bad date: %s",prevdate);
246: prevdate[0]='\0';
247: return false;
248: }
249: return true;
250: }
251:
252: int checknum(sp,fields)
253: register char * sp; int fields;
254: { register int dotcount;
255: if (sp==nil||*sp=='\0') return true;
256: dotcount=0;
257: while(*sp) {
258: if (*sp=='.') dotcount++;
259: elsif (ctab[*sp]!=DIGIT) return false;
260: sp++;
261: }
262: if (fields >= 0 && dotcount!=fields) return false;
263: return true;
264: }
265:
266:
267:
268: #ifdef KEEPTEST
269: char * RCSfilename, * workfilename;
270:
271: main(argc, argv)
272: int argc; char *argv[];
273: {
274: cmdid="keeptest";
275: while (*(++argv)) {
276: if (getoldkeys(*argv))
277: VOID printf("%s: revision: %s, date: %s, author: %s, state: %s\n",
278: *argv, prevrev, prevdate, prevauthor,prevstate);
279: VOID printf("Source: %s, RCSfile: %s\n",prevsource,prevRCS);
280: }
281: exit(0);
282: }
283: #endif