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