ident.c revision 10
1207753Smm/* Copyright (C) 1982, 1988, 1989 Walter Tichy
2207753Smm   Copyright 1990, 1991 by Paul Eggert
3207753Smm   Distributed under license by the Free Software Foundation, Inc.
4207753Smm
5207753SmmThis file is part of RCS.
6207753Smm
7207753SmmRCS is free software; you can redistribute it and/or modify
8207753Smmit under the terms of the GNU General Public License as published by
9207753Smmthe Free Software Foundation; either version 2, or (at your option)
10207753Smmany later version.
11207753Smm
12207753SmmRCS is distributed in the hope that it will be useful,
13207753Smmbut WITHOUT ANY WARRANTY; without even the implied warranty of
14207753SmmMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15207753SmmGNU General Public License for more details.
16207753Smm
17207753SmmYou should have received a copy of the GNU General Public License
18207753Smmalong with RCS; see the file COPYING.  If not, write to
19207753Smmthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20207753Smm
21207753SmmReport problems and direct all questions to:
22207753Smm
23207753Smm    rcs-bugs@cs.purdue.edu
24207753Smm
25*/
26
27/*
28 *                     RCS identification operation
29 */
30
31/* $Log: ident.c,v $
32 * Revision 5.3  1991/09/10  22:15:46  eggert
33 * Open files with FOPEN_R, not FOPEN_R_WORK,
34 * because they might be executables, not working files.
35 *
36 * Revision 5.2  1991/08/19  03:13:55  eggert
37 * Report read errors immediately.
38 *
39 * Revision 5.1  1991/02/25  07:12:37  eggert
40 * Don't report empty keywords.  Check for I/O errors.
41 *
42 * Revision 5.0  1990/08/22  08:12:37  eggert
43 * Don't limit output to known keywords.
44 * Remove arbitrary limits and lint.  Ansify and Posixate.
45 *
46 * Revision 4.5  89/05/01  15:11:54  narten
47 * changed copyright header to reflect current distribution rules
48 *
49 * Revision 4.4  87/10/23  17:09:57  narten
50 * added exit(0) so exit return code would be non random
51 *
52 * Revision 4.3  87/10/18  10:23:55  narten
53 * Updating version numbers. Changes relative to 1.1 are actually relative
54 * to 4.1
55 *
56 * Revision 1.3  87/07/09  09:20:52  trinkle
57 * Added check to make sure there is at least one arg before comparing argv[1]
58 * with "-q".  This necessary on machines that don't allow dereferncing null
59 * pointers (i.e. Suns).
60 *
61 * Revision 1.2  87/03/27  14:21:47  jenkins
62 * Port to suns
63 *
64 * Revision 4.1  83/05/10  16:31:02  wft
65 * Added option -q and input from reading stdin.
66 * Marker matching is now done with trymatch() (independent of keywords).
67 *
68 * Revision 3.4  83/02/18  17:37:49  wft
69 * removed printing of new line after last file.
70 *
71 * Revision 3.3  82/12/04  12:48:55  wft
72 * Added LOCKER.
73 *
74 * Revision 3.2  82/11/28  18:24:17  wft
75 * removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
76 *
77 * Revision 3.1  82/10/13  15:58:51  wft
78 * fixed type of variables receiving from getc() (char-->int).
79*/
80
81#include  "rcsbase.h"
82
83static int match P((FILE*));
84static void scanfile P((FILE*,char const*,int));
85
86mainProg(identId, "ident", "$Id: ident.c,v 5.3 1991/09/10 22:15:46 eggert Exp $")
87/*  Ident searches the named files for all occurrences
88 *  of the pattern $keyword:...$, where the keywords are
89 *  Author, Date, Header, Id, Log, RCSfile, Revision, Source, and State.
90 */
91
92{
93   FILE *fp;
94   int quiet;
95   int status = EXIT_SUCCESS;
96
97   if ((quiet  =  argc > 1 && strcmp("-q",argv[1])==0)) {
98        argc--; argv++;
99   }
100
101   if (argc<2)
102	scanfile(stdin, (char*)0, quiet);
103
104   while ( --argc > 0 ) {
105      if (!(fp = fopen(*++argv, FOPEN_R))) {
106	 VOID fprintf(stderr,  "%s error: can't open %s\n", cmdid, *argv);
107	 status = EXIT_FAILURE;
108      } else {
109	 scanfile(fp, *argv, quiet);
110	 if (argc>1) VOID putchar('\n');
111      }
112   }
113   if (ferror(stdout) || fclose(stdout)!=0) {
114      VOID fprintf(stderr,  "%s error: write error\n", cmdid);
115      status = EXIT_FAILURE;
116   }
117   exitmain(status);
118}
119
120#if lint
121	exiting void identExit() { _exit(EXIT_FAILURE); }
122#endif
123
124
125	static void
126scanfile(file, name, quiet)
127	register FILE *file;
128	char const *name;
129	int quiet;
130/* Function: scan an open file with descriptor file for keywords.
131 * Return false if there's a read error.
132 */
133{
134   register int c;
135
136   if (name)
137      VOID printf("%s:\n", name);
138   else
139      name = "input";
140   c = 0;
141   for (;;) {
142      if (c < 0) {
143	 if (feof(file))
144	    break;
145	 if (ferror(file))
146	    goto read_error;
147      }
148      if (c == KDELIM) {
149	 if ((c = match(file)))
150	    continue;
151	 quiet = true;
152      }
153      c = getc(file);
154   }
155   if (!quiet)
156      VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name);
157   if (fclose(file) == 0)
158      return;
159
160 read_error:
161   VOID fprintf(stderr, "%s error: %s: read error\n", cmdid, name);
162   exit(EXIT_FAILURE);
163}
164
165
166
167	static int
168match(fp)   /* group substring between two KDELIM's; then do pattern match */
169   register FILE *fp;
170{
171   char line[BUFSIZ];
172   register int c;
173   register char * tp;
174
175   tp = line;
176   while ((c = getc(fp)) != VDELIM) {
177      if (c < 0)
178	 return c;
179      switch (ctab[c]) {
180	 case LETTER: case Letter:
181	    *tp++ = c;
182	    if (tp < line+sizeof(line)-4)
183	       break;
184	    /* fall into */
185	 default:
186	    return c ? c : '\n'/* anything but 0 or KDELIM or EOF */;
187      }
188   }
189   if (tp == line)
190      return c;
191   *tp++ = c;
192   if ((c = getc(fp)) != ' ')
193      return c ? c : '\n';
194   *tp++ = c;
195   while( (c = getc(fp)) != KDELIM ) {
196      if (c < 0  &&  feof(fp) | ferror(fp))
197	    return c;
198      switch (ctab[c]) {
199	 default:
200	    *tp++ = c;
201	    if (tp < line+sizeof(line)-2)
202	       break;
203	    /* fall into */
204	 case NEWLN: case UNKN:
205	    return c ? c : '\n';
206      }
207   }
208   if (tp[-1] != ' ')
209      return c;
210   *tp++ = c;     /*append trailing KDELIM*/
211   *tp   = '\0';
212   VOID fprintf(stdout, "     %c%s\n", KDELIM, line);
213   return 0;
214}
215