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