xref: /386bsd/usr/src/usr.bin/rcs/src/rcskeep.c (revision a2142627)
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  *   rcs-bugs@cs.purdue.edu
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  eggert@sm.unisys.com (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 
getoldkeys(fname)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 
getval(fp,target,maxchars,optional)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 
getprevdate(fp,optional)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 
checknum(sp,fields)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 
main(argc,argv)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
310