1*86d7f5d3SJohn Marino /* Extract RCS keyword string values from working files. */
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn Marino /* Copyright 1982, 1988, 1989 Walter Tichy
4*86d7f5d3SJohn Marino Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
5*86d7f5d3SJohn Marino Distributed under license by the Free Software Foundation, Inc.
6*86d7f5d3SJohn Marino
7*86d7f5d3SJohn Marino This file is part of RCS.
8*86d7f5d3SJohn Marino
9*86d7f5d3SJohn Marino RCS is free software; you can redistribute it and/or modify
10*86d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
11*86d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
12*86d7f5d3SJohn Marino any later version.
13*86d7f5d3SJohn Marino
14*86d7f5d3SJohn Marino RCS is distributed in the hope that it will be useful,
15*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
16*86d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*86d7f5d3SJohn Marino GNU General Public License for more details.
18*86d7f5d3SJohn Marino
19*86d7f5d3SJohn Marino You should have received a copy of the GNU General Public License
20*86d7f5d3SJohn Marino along with RCS; see the file COPYING.
21*86d7f5d3SJohn Marino If not, write to the Free Software Foundation,
22*86d7f5d3SJohn Marino 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino Report problems and direct all questions to:
25*86d7f5d3SJohn Marino
26*86d7f5d3SJohn Marino rcs-bugs@cs.purdue.edu
27*86d7f5d3SJohn Marino
28*86d7f5d3SJohn Marino */
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /*
31*86d7f5d3SJohn Marino * $FreeBSD: src/gnu/usr.bin/rcs/lib/rcskeep.c,v 1.8 1999/08/27 23:36:46 peter Exp $
32*86d7f5d3SJohn Marino * $DragonFly: src/gnu/usr.bin/rcs/lib/rcskeep.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
33*86d7f5d3SJohn Marino *
34*86d7f5d3SJohn Marino * Revision 5.10 1995/06/16 06:19:24 eggert
35*86d7f5d3SJohn Marino * Update FSF address.
36*86d7f5d3SJohn Marino *
37*86d7f5d3SJohn Marino * Revision 5.9 1995/06/01 16:23:43 eggert
38*86d7f5d3SJohn Marino * (getoldkeys): Don't panic if a Name: is empty.
39*86d7f5d3SJohn Marino *
40*86d7f5d3SJohn Marino * Revision 5.8 1994/03/17 14:05:48 eggert
41*86d7f5d3SJohn Marino * Remove lint.
42*86d7f5d3SJohn Marino *
43*86d7f5d3SJohn Marino * Revision 5.7 1993/11/09 17:40:15 eggert
44*86d7f5d3SJohn Marino * Use simpler timezone parsing strategy now that we're using ISO 8601 format.
45*86d7f5d3SJohn Marino *
46*86d7f5d3SJohn Marino * Revision 5.6 1993/11/03 17:42:27 eggert
47*86d7f5d3SJohn Marino * Scan for Name keyword. Improve quality of diagnostics.
48*86d7f5d3SJohn Marino *
49*86d7f5d3SJohn Marino * Revision 5.5 1992/07/28 16:12:44 eggert
50*86d7f5d3SJohn Marino * Statement macro names now end in _.
51*86d7f5d3SJohn Marino *
52*86d7f5d3SJohn Marino * Revision 5.4 1991/08/19 03:13:55 eggert
53*86d7f5d3SJohn Marino * Tune.
54*86d7f5d3SJohn Marino *
55*86d7f5d3SJohn Marino * Revision 5.3 1991/04/21 11:58:25 eggert
56*86d7f5d3SJohn Marino * Shorten names to keep them distinct on shortname hosts.
57*86d7f5d3SJohn Marino *
58*86d7f5d3SJohn Marino * Revision 5.2 1990/10/04 06:30:20 eggert
59*86d7f5d3SJohn Marino * Parse time zone offsets; future RCS versions may output them.
60*86d7f5d3SJohn Marino *
61*86d7f5d3SJohn Marino * Revision 5.1 1990/09/20 02:38:56 eggert
62*86d7f5d3SJohn Marino * ci -k now checks dates more thoroughly.
63*86d7f5d3SJohn Marino *
64*86d7f5d3SJohn Marino * Revision 5.0 1990/08/22 08:12:53 eggert
65*86d7f5d3SJohn Marino * Retrieve old log message if there is one.
66*86d7f5d3SJohn Marino * Don't require final newline.
67*86d7f5d3SJohn Marino * Remove compile-time limits; use malloc instead. Tune.
68*86d7f5d3SJohn Marino * Permit dates past 1999/12/31. Ansify and Posixate.
69*86d7f5d3SJohn Marino *
70*86d7f5d3SJohn Marino * Revision 4.6 89/05/01 15:12:56 narten
71*86d7f5d3SJohn Marino * changed copyright header to reflect current distribution rules
72*86d7f5d3SJohn Marino *
73*86d7f5d3SJohn Marino * Revision 4.5 88/08/09 19:13:03 eggert
74*86d7f5d3SJohn Marino * Remove lint and speed up by making FILE *fp local, not global.
75*86d7f5d3SJohn Marino *
76*86d7f5d3SJohn Marino * Revision 4.4 87/12/18 11:44:21 narten
77*86d7f5d3SJohn Marino * more lint cleanups (Guy Harris)
78*86d7f5d3SJohn Marino *
79*86d7f5d3SJohn Marino * Revision 4.3 87/10/18 10:35:50 narten
80*86d7f5d3SJohn Marino * Updating version numbers. Changes relative to 1.1 actually relative
81*86d7f5d3SJohn Marino * to 4.1
82*86d7f5d3SJohn Marino *
83*86d7f5d3SJohn Marino * Revision 1.3 87/09/24 14:00:00 narten
84*86d7f5d3SJohn Marino * Sources now pass through lint (if you ignore printf/sprintf/fprintf
85*86d7f5d3SJohn Marino * warnings)
86*86d7f5d3SJohn Marino *
87*86d7f5d3SJohn Marino * Revision 1.2 87/03/27 14:22:29 jenkins
88*86d7f5d3SJohn Marino * Port to suns
89*86d7f5d3SJohn Marino *
90*86d7f5d3SJohn Marino * Revision 4.1 83/05/10 16:26:44 wft
91*86d7f5d3SJohn Marino * Added new markers Id and RCSfile; extraction added.
92*86d7f5d3SJohn Marino * Marker matching with trymatch().
93*86d7f5d3SJohn Marino *
94*86d7f5d3SJohn Marino * Revision 3.2 82/12/24 12:08:26 wft
95*86d7f5d3SJohn Marino * added missing #endif.
96*86d7f5d3SJohn Marino *
97*86d7f5d3SJohn Marino * Revision 3.1 82/12/04 13:22:41 wft
98*86d7f5d3SJohn Marino * Initial revision.
99*86d7f5d3SJohn Marino *
100*86d7f5d3SJohn Marino */
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino #include "rcsbase.h"
103*86d7f5d3SJohn Marino
104*86d7f5d3SJohn Marino libId(keepId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcskeep.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
105*86d7f5d3SJohn Marino
106*86d7f5d3SJohn Marino static int badly_terminated P((void));
107*86d7f5d3SJohn Marino static int checknum P((char const*));
108*86d7f5d3SJohn Marino static int get0val P((int,RILE*,struct buf*,int));
109*86d7f5d3SJohn Marino static int getval P((RILE*,struct buf*,int));
110*86d7f5d3SJohn Marino static int keepdate P((RILE*));
111*86d7f5d3SJohn Marino static int keepid P((int,RILE*,struct buf*));
112*86d7f5d3SJohn Marino static int keeprev P((RILE*));
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marino int prevkeys;
115*86d7f5d3SJohn Marino struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
116*86d7f5d3SJohn Marino
117*86d7f5d3SJohn Marino int
getoldkeys(fp)118*86d7f5d3SJohn Marino getoldkeys(fp)
119*86d7f5d3SJohn Marino register RILE *fp;
120*86d7f5d3SJohn Marino /* Function: Tries to read keyword values for author, date,
121*86d7f5d3SJohn Marino * revision number, and state out of the file fp.
122*86d7f5d3SJohn Marino * If fp is null, workname is opened and closed instead of using fp.
123*86d7f5d3SJohn Marino * The results are placed into
124*86d7f5d3SJohn Marino * prevauthor, prevdate, prevname, prevrev, prevstate.
125*86d7f5d3SJohn Marino * Aborts immediately if it finds an error and returns false.
126*86d7f5d3SJohn Marino * If it returns true, it doesn't mean that any of the
127*86d7f5d3SJohn Marino * values were found; instead, check to see whether the corresponding arrays
128*86d7f5d3SJohn Marino * contain the empty string.
129*86d7f5d3SJohn Marino */
130*86d7f5d3SJohn Marino {
131*86d7f5d3SJohn Marino register int c;
132*86d7f5d3SJohn Marino char keyword[keylength+1];
133*86d7f5d3SJohn Marino register char * tp;
134*86d7f5d3SJohn Marino int needs_closing;
135*86d7f5d3SJohn Marino int prevname_found;
136*86d7f5d3SJohn Marino
137*86d7f5d3SJohn Marino if (prevkeys)
138*86d7f5d3SJohn Marino return true;
139*86d7f5d3SJohn Marino
140*86d7f5d3SJohn Marino needs_closing = false;
141*86d7f5d3SJohn Marino if (!fp) {
142*86d7f5d3SJohn Marino if (!(fp = Iopen(workname, FOPEN_R_WORK, (struct stat*)0))) {
143*86d7f5d3SJohn Marino eerror(workname);
144*86d7f5d3SJohn Marino return false;
145*86d7f5d3SJohn Marino }
146*86d7f5d3SJohn Marino needs_closing = true;
147*86d7f5d3SJohn Marino }
148*86d7f5d3SJohn Marino
149*86d7f5d3SJohn Marino /* initialize to empty */
150*86d7f5d3SJohn Marino bufscpy(&prevauthor, "");
151*86d7f5d3SJohn Marino bufscpy(&prevdate, "");
152*86d7f5d3SJohn Marino bufscpy(&prevname, ""); prevname_found = 0;
153*86d7f5d3SJohn Marino bufscpy(&prevrev, "");
154*86d7f5d3SJohn Marino bufscpy(&prevstate, "");
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino c = '\0'; /* anything but KDELIM */
157*86d7f5d3SJohn Marino for (;;) {
158*86d7f5d3SJohn Marino if ( c==KDELIM) {
159*86d7f5d3SJohn Marino do {
160*86d7f5d3SJohn Marino /* try to get keyword */
161*86d7f5d3SJohn Marino tp = keyword;
162*86d7f5d3SJohn Marino for (;;) {
163*86d7f5d3SJohn Marino Igeteof_(fp, c, goto ok;)
164*86d7f5d3SJohn Marino switch (c) {
165*86d7f5d3SJohn Marino default:
166*86d7f5d3SJohn Marino if (keyword+keylength <= tp)
167*86d7f5d3SJohn Marino break;
168*86d7f5d3SJohn Marino *tp++ = c;
169*86d7f5d3SJohn Marino continue;
170*86d7f5d3SJohn Marino
171*86d7f5d3SJohn Marino case '\n': case KDELIM: case VDELIM:
172*86d7f5d3SJohn Marino break;
173*86d7f5d3SJohn Marino }
174*86d7f5d3SJohn Marino break;
175*86d7f5d3SJohn Marino }
176*86d7f5d3SJohn Marino } while (c==KDELIM);
177*86d7f5d3SJohn Marino if (c!=VDELIM) continue;
178*86d7f5d3SJohn Marino *tp = c;
179*86d7f5d3SJohn Marino Igeteof_(fp, c, break;)
180*86d7f5d3SJohn Marino switch (c) {
181*86d7f5d3SJohn Marino case ' ': case '\t': break;
182*86d7f5d3SJohn Marino default: continue;
183*86d7f5d3SJohn Marino }
184*86d7f5d3SJohn Marino
185*86d7f5d3SJohn Marino switch (trymatch(keyword)) {
186*86d7f5d3SJohn Marino case Author:
187*86d7f5d3SJohn Marino if (!keepid(0, fp, &prevauthor))
188*86d7f5d3SJohn Marino return false;
189*86d7f5d3SJohn Marino c = 0;
190*86d7f5d3SJohn Marino break;
191*86d7f5d3SJohn Marino case Date:
192*86d7f5d3SJohn Marino if (!(c = keepdate(fp)))
193*86d7f5d3SJohn Marino return false;
194*86d7f5d3SJohn Marino break;
195*86d7f5d3SJohn Marino case Header:
196*86d7f5d3SJohn Marino case Id:
197*86d7f5d3SJohn Marino case LocalId:
198*86d7f5d3SJohn Marino if (!(
199*86d7f5d3SJohn Marino getval(fp, (struct buf*)0, false) &&
200*86d7f5d3SJohn Marino keeprev(fp) &&
201*86d7f5d3SJohn Marino (c = keepdate(fp)) &&
202*86d7f5d3SJohn Marino keepid(c, fp, &prevauthor) &&
203*86d7f5d3SJohn Marino keepid(0, fp, &prevstate)
204*86d7f5d3SJohn Marino ))
205*86d7f5d3SJohn Marino return false;
206*86d7f5d3SJohn Marino /* Skip either ``who'' (new form) or ``Locker: who'' (old). */
207*86d7f5d3SJohn Marino if (getval(fp, (struct buf*)0, true) &&
208*86d7f5d3SJohn Marino getval(fp, (struct buf*)0, true))
209*86d7f5d3SJohn Marino c = 0;
210*86d7f5d3SJohn Marino else if (nerror)
211*86d7f5d3SJohn Marino return false;
212*86d7f5d3SJohn Marino else
213*86d7f5d3SJohn Marino c = KDELIM;
214*86d7f5d3SJohn Marino break;
215*86d7f5d3SJohn Marino case Locker:
216*86d7f5d3SJohn Marino (void) getval(fp, (struct buf*)0, false);
217*86d7f5d3SJohn Marino c = 0;
218*86d7f5d3SJohn Marino break;
219*86d7f5d3SJohn Marino case Log:
220*86d7f5d3SJohn Marino case RCSfile:
221*86d7f5d3SJohn Marino case Source:
222*86d7f5d3SJohn Marino if (!getval(fp, (struct buf*)0, false))
223*86d7f5d3SJohn Marino return false;
224*86d7f5d3SJohn Marino c = 0;
225*86d7f5d3SJohn Marino break;
226*86d7f5d3SJohn Marino case Name:
227*86d7f5d3SJohn Marino if (getval(fp, &prevname, false)) {
228*86d7f5d3SJohn Marino if (*prevname.string)
229*86d7f5d3SJohn Marino checkssym(prevname.string);
230*86d7f5d3SJohn Marino prevname_found = 1;
231*86d7f5d3SJohn Marino }
232*86d7f5d3SJohn Marino c = 0;
233*86d7f5d3SJohn Marino break;
234*86d7f5d3SJohn Marino case Revision:
235*86d7f5d3SJohn Marino if (!keeprev(fp))
236*86d7f5d3SJohn Marino return false;
237*86d7f5d3SJohn Marino c = 0;
238*86d7f5d3SJohn Marino break;
239*86d7f5d3SJohn Marino case State:
240*86d7f5d3SJohn Marino if (!keepid(0, fp, &prevstate))
241*86d7f5d3SJohn Marino return false;
242*86d7f5d3SJohn Marino c = 0;
243*86d7f5d3SJohn Marino break;
244*86d7f5d3SJohn Marino default:
245*86d7f5d3SJohn Marino continue;
246*86d7f5d3SJohn Marino }
247*86d7f5d3SJohn Marino if (!c) {
248*86d7f5d3SJohn Marino Igeteof_(fp, c, c=0;)
249*86d7f5d3SJohn Marino }
250*86d7f5d3SJohn Marino if (c != KDELIM) {
251*86d7f5d3SJohn Marino workerror("closing %c missing on keyword", KDELIM);
252*86d7f5d3SJohn Marino return false;
253*86d7f5d3SJohn Marino }
254*86d7f5d3SJohn Marino if (prevname_found &&
255*86d7f5d3SJohn Marino *prevauthor.string && *prevdate.string &&
256*86d7f5d3SJohn Marino *prevrev.string && *prevstate.string
257*86d7f5d3SJohn Marino )
258*86d7f5d3SJohn Marino break;
259*86d7f5d3SJohn Marino }
260*86d7f5d3SJohn Marino Igeteof_(fp, c, break;)
261*86d7f5d3SJohn Marino }
262*86d7f5d3SJohn Marino
263*86d7f5d3SJohn Marino ok:
264*86d7f5d3SJohn Marino if (needs_closing)
265*86d7f5d3SJohn Marino Ifclose(fp);
266*86d7f5d3SJohn Marino else
267*86d7f5d3SJohn Marino Irewind(fp);
268*86d7f5d3SJohn Marino prevkeys = true;
269*86d7f5d3SJohn Marino return true;
270*86d7f5d3SJohn Marino }
271*86d7f5d3SJohn Marino
272*86d7f5d3SJohn Marino static int
badly_terminated()273*86d7f5d3SJohn Marino badly_terminated()
274*86d7f5d3SJohn Marino {
275*86d7f5d3SJohn Marino workerror("badly terminated keyword value");
276*86d7f5d3SJohn Marino return false;
277*86d7f5d3SJohn Marino }
278*86d7f5d3SJohn Marino
279*86d7f5d3SJohn Marino static int
getval(fp,target,optional)280*86d7f5d3SJohn Marino getval(fp, target, optional)
281*86d7f5d3SJohn Marino register RILE *fp;
282*86d7f5d3SJohn Marino struct buf *target;
283*86d7f5d3SJohn Marino int optional;
284*86d7f5d3SJohn Marino /* Reads a keyword value from FP into TARGET.
285*86d7f5d3SJohn Marino * Returns true if one is found, false otherwise.
286*86d7f5d3SJohn Marino * Does not modify target if it is 0.
287*86d7f5d3SJohn Marino * Do not report an error if OPTIONAL is set and KDELIM is found instead.
288*86d7f5d3SJohn Marino */
289*86d7f5d3SJohn Marino {
290*86d7f5d3SJohn Marino int c;
291*86d7f5d3SJohn Marino Igeteof_(fp, c, return badly_terminated();)
292*86d7f5d3SJohn Marino return get0val(c, fp, target, optional);
293*86d7f5d3SJohn Marino }
294*86d7f5d3SJohn Marino
295*86d7f5d3SJohn Marino static int
get0val(c,fp,target,optional)296*86d7f5d3SJohn Marino get0val(c, fp, target, optional)
297*86d7f5d3SJohn Marino register int c;
298*86d7f5d3SJohn Marino register RILE *fp;
299*86d7f5d3SJohn Marino struct buf *target;
300*86d7f5d3SJohn Marino int optional;
301*86d7f5d3SJohn Marino /* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
302*86d7f5d3SJohn Marino * Same as getval, except C is the lookahead character.
303*86d7f5d3SJohn Marino */
304*86d7f5d3SJohn Marino { register char * tp;
305*86d7f5d3SJohn Marino char const *tlim;
306*86d7f5d3SJohn Marino register int got1;
307*86d7f5d3SJohn Marino
308*86d7f5d3SJohn Marino if (target) {
309*86d7f5d3SJohn Marino bufalloc(target, 1);
310*86d7f5d3SJohn Marino tp = target->string;
311*86d7f5d3SJohn Marino tlim = tp + target->size;
312*86d7f5d3SJohn Marino } else
313*86d7f5d3SJohn Marino tlim = tp = 0;
314*86d7f5d3SJohn Marino got1 = false;
315*86d7f5d3SJohn Marino for (;;) {
316*86d7f5d3SJohn Marino switch (c) {
317*86d7f5d3SJohn Marino default:
318*86d7f5d3SJohn Marino got1 = true;
319*86d7f5d3SJohn Marino if (tp) {
320*86d7f5d3SJohn Marino *tp++ = c;
321*86d7f5d3SJohn Marino if (tlim <= tp)
322*86d7f5d3SJohn Marino tp = bufenlarge(target, &tlim);
323*86d7f5d3SJohn Marino }
324*86d7f5d3SJohn Marino break;
325*86d7f5d3SJohn Marino
326*86d7f5d3SJohn Marino case ' ':
327*86d7f5d3SJohn Marino case '\t':
328*86d7f5d3SJohn Marino if (tp) {
329*86d7f5d3SJohn Marino *tp = 0;
330*86d7f5d3SJohn Marino # ifdef KEEPTEST
331*86d7f5d3SJohn Marino VOID printf("getval: %s\n", target);
332*86d7f5d3SJohn Marino # endif
333*86d7f5d3SJohn Marino }
334*86d7f5d3SJohn Marino return got1;
335*86d7f5d3SJohn Marino
336*86d7f5d3SJohn Marino case KDELIM:
337*86d7f5d3SJohn Marino if (!got1 && optional)
338*86d7f5d3SJohn Marino return false;
339*86d7f5d3SJohn Marino /* fall into */
340*86d7f5d3SJohn Marino case '\n':
341*86d7f5d3SJohn Marino case 0:
342*86d7f5d3SJohn Marino return badly_terminated();
343*86d7f5d3SJohn Marino }
344*86d7f5d3SJohn Marino Igeteof_(fp, c, return badly_terminated();)
345*86d7f5d3SJohn Marino }
346*86d7f5d3SJohn Marino }
347*86d7f5d3SJohn Marino
348*86d7f5d3SJohn Marino
349*86d7f5d3SJohn Marino static int
keepdate(fp)350*86d7f5d3SJohn Marino keepdate(fp)
351*86d7f5d3SJohn Marino RILE *fp;
352*86d7f5d3SJohn Marino /* Function: reads a date prevdate; checks format
353*86d7f5d3SJohn Marino * Return 0 on error, lookahead character otherwise.
354*86d7f5d3SJohn Marino */
355*86d7f5d3SJohn Marino {
356*86d7f5d3SJohn Marino struct buf prevday, prevtime;
357*86d7f5d3SJohn Marino register int c;
358*86d7f5d3SJohn Marino
359*86d7f5d3SJohn Marino c = 0;
360*86d7f5d3SJohn Marino bufautobegin(&prevday);
361*86d7f5d3SJohn Marino if (getval(fp,&prevday,false)) {
362*86d7f5d3SJohn Marino bufautobegin(&prevtime);
363*86d7f5d3SJohn Marino if (getval(fp,&prevtime,false)) {
364*86d7f5d3SJohn Marino Igeteof_(fp, c, c=0;)
365*86d7f5d3SJohn Marino if (c) {
366*86d7f5d3SJohn Marino register char const *d = prevday.string, *t = prevtime.string;
367*86d7f5d3SJohn Marino bufalloc(&prevdate, strlen(d) + strlen(t) + 9);
368*86d7f5d3SJohn Marino VOID sprintf(prevdate.string, "%s%s %s%s",
369*86d7f5d3SJohn Marino /* Parse dates put out by old versions of RCS. */
370*86d7f5d3SJohn Marino isdigit(d[0]) && isdigit(d[1]) && !isdigit(d[2])
371*86d7f5d3SJohn Marino ? "19" : "",
372*86d7f5d3SJohn Marino d, t,
373*86d7f5d3SJohn Marino strchr(t,'-') || strchr(t,'+') ? "" : "+0000"
374*86d7f5d3SJohn Marino );
375*86d7f5d3SJohn Marino }
376*86d7f5d3SJohn Marino }
377*86d7f5d3SJohn Marino bufautoend(&prevtime);
378*86d7f5d3SJohn Marino }
379*86d7f5d3SJohn Marino bufautoend(&prevday);
380*86d7f5d3SJohn Marino return c;
381*86d7f5d3SJohn Marino }
382*86d7f5d3SJohn Marino
383*86d7f5d3SJohn Marino static int
keepid(c,fp,b)384*86d7f5d3SJohn Marino keepid(c, fp, b)
385*86d7f5d3SJohn Marino int c;
386*86d7f5d3SJohn Marino RILE *fp;
387*86d7f5d3SJohn Marino struct buf *b;
388*86d7f5d3SJohn Marino /* Get previous identifier from C+FP into B. */
389*86d7f5d3SJohn Marino {
390*86d7f5d3SJohn Marino if (!c) {
391*86d7f5d3SJohn Marino Igeteof_(fp, c, return false;)
392*86d7f5d3SJohn Marino }
393*86d7f5d3SJohn Marino if (!get0val(c, fp, b, false))
394*86d7f5d3SJohn Marino return false;
395*86d7f5d3SJohn Marino checksid(b->string);
396*86d7f5d3SJohn Marino return !nerror;
397*86d7f5d3SJohn Marino }
398*86d7f5d3SJohn Marino
399*86d7f5d3SJohn Marino static int
keeprev(fp)400*86d7f5d3SJohn Marino keeprev(fp)
401*86d7f5d3SJohn Marino RILE *fp;
402*86d7f5d3SJohn Marino /* Get previous revision from FP into prevrev. */
403*86d7f5d3SJohn Marino {
404*86d7f5d3SJohn Marino return getval(fp,&prevrev,false) && checknum(prevrev.string);
405*86d7f5d3SJohn Marino }
406*86d7f5d3SJohn Marino
407*86d7f5d3SJohn Marino
408*86d7f5d3SJohn Marino static int
checknum(s)409*86d7f5d3SJohn Marino checknum(s)
410*86d7f5d3SJohn Marino char const *s;
411*86d7f5d3SJohn Marino {
412*86d7f5d3SJohn Marino register char const *sp;
413*86d7f5d3SJohn Marino register int dotcount = 0;
414*86d7f5d3SJohn Marino for (sp=s; ; sp++) {
415*86d7f5d3SJohn Marino switch (*sp) {
416*86d7f5d3SJohn Marino case 0:
417*86d7f5d3SJohn Marino if (dotcount & 1)
418*86d7f5d3SJohn Marino return true;
419*86d7f5d3SJohn Marino else
420*86d7f5d3SJohn Marino break;
421*86d7f5d3SJohn Marino
422*86d7f5d3SJohn Marino case '.':
423*86d7f5d3SJohn Marino dotcount++;
424*86d7f5d3SJohn Marino continue;
425*86d7f5d3SJohn Marino
426*86d7f5d3SJohn Marino default:
427*86d7f5d3SJohn Marino if (isdigit(*sp))
428*86d7f5d3SJohn Marino continue;
429*86d7f5d3SJohn Marino break;
430*86d7f5d3SJohn Marino }
431*86d7f5d3SJohn Marino break;
432*86d7f5d3SJohn Marino }
433*86d7f5d3SJohn Marino workerror("%s is not a revision number", s);
434*86d7f5d3SJohn Marino return false;
435*86d7f5d3SJohn Marino }
436*86d7f5d3SJohn Marino
437*86d7f5d3SJohn Marino
438*86d7f5d3SJohn Marino
439*86d7f5d3SJohn Marino #ifdef KEEPTEST
440*86d7f5d3SJohn Marino
441*86d7f5d3SJohn Marino /* Print the keyword values found. */
442*86d7f5d3SJohn Marino
443*86d7f5d3SJohn Marino char const cmdid[] ="keeptest";
444*86d7f5d3SJohn Marino
445*86d7f5d3SJohn Marino int
main(argc,argv)446*86d7f5d3SJohn Marino main(argc, argv)
447*86d7f5d3SJohn Marino int argc; char *argv[];
448*86d7f5d3SJohn Marino {
449*86d7f5d3SJohn Marino while (*(++argv)) {
450*86d7f5d3SJohn Marino workname = *argv;
451*86d7f5d3SJohn Marino getoldkeys((RILE*)0);
452*86d7f5d3SJohn Marino VOID printf("%s: revision: %s, date: %s, author: %s, name: %s, state: %s\n",
453*86d7f5d3SJohn Marino *argv, prevrev.string, prevdate.string, prevauthor.string, prevname.string, prevstate.string);
454*86d7f5d3SJohn Marino }
455*86d7f5d3SJohn Marino exitmain(EXIT_SUCCESS);
456*86d7f5d3SJohn Marino }
457*86d7f5d3SJohn Marino #endif
458