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