ident.c revision 22996
1193323Sed/* Identify RCS keyword strings in files. */ 2224145Sdim 3193323Sed/* Copyright 1982, 1988, 1989 Walter Tichy 4193323Sed Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert 5193323Sed Distributed under license by the Free Software Foundation, Inc. 6193323Sed 7224145SdimThis file is part of RCS. 8193323Sed 9193323SedRCS is free software; you can redistribute it and/or modify 10193323Sedit under the terms of the GNU General Public License as published by 11193323Sedthe Free Software Foundation; either version 2, or (at your option) 12193323Sedany later version. 13193323Sed 14193323SedRCS is distributed in the hope that it will be useful, 15193323Sedbut WITHOUT ANY WARRANTY; without even the implied warranty of 16193323SedMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17193323SedGNU General Public License for more details. 18193323Sed 19193323SedYou should have received a copy of the GNU General Public License 20193323Sedalong with RCS; see the file COPYING. 21193323SedIf not, write to the Free Software Foundation, 22193323Sed59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23193323Sed 24193323SedReport problems and direct all questions to: 25193323Sed 26193323Sed rcs-bugs@cs.purdue.edu 27193323Sed 28193323Sed*/ 29263508Sdim 30234353Sdim/* 31234353Sdim * Revision 5.9 1995/06/16 06:19:24 eggert 32234353Sdim * Update FSF address. 33234353Sdim * 34234353Sdim * Revision 5.8 1995/06/01 16:23:43 eggert 35195340Sed * (exiterr, reportError): New functions, needed for DOS and OS/2 ports. 36243830Sdim * (scanfile): Use them. 37243830Sdim * 38243830Sdim * Revision 5.7 1994/03/20 04:52:58 eggert 39243830Sdim * Remove `exiting' from identExit. 40249423Sdim * 41249423Sdim * Revision 5.6 1993/11/09 17:40:15 eggert 42263508Sdim * Add -V. 43263508Sdim * 44263508Sdim * Revision 5.5 1993/11/03 17:42:27 eggert 45263508Sdim * Test for char == EOF, not char < 0. 46263508Sdim * 47263508Sdim * Revision 5.4 1992/01/24 18:44:19 eggert 48263508Sdim * lint -> RCS_lint 49263508Sdim * 50263508Sdim * Revision 5.3 1991/09/10 22:15:46 eggert 51263508Sdim * Open files with FOPEN_R, not FOPEN_R_WORK, 52263508Sdim * because they might be executables, not working files. 53263508Sdim * 54263508Sdim * Revision 5.2 1991/08/19 03:13:55 eggert 55263508Sdim * Report read errors immediately. 56263508Sdim * 57263508Sdim * Revision 5.1 1991/02/25 07:12:37 eggert 58263508Sdim * Don't report empty keywords. Check for I/O errors. 59263508Sdim * 60263508Sdim * Revision 5.0 1990/08/22 08:12:37 eggert 61263508Sdim * Don't limit output to known keywords. 62263508Sdim * Remove arbitrary limits and lint. Ansify and Posixate. 63263508Sdim * 64263508Sdim * Revision 4.5 89/05/01 15:11:54 narten 65193323Sed * changed copyright header to reflect current distribution rules 66263508Sdim * 67263508Sdim * Revision 4.4 87/10/23 17:09:57 narten 68263508Sdim * added exit(0) so exit return code would be non random 69263508Sdim * 70263508Sdim * Revision 4.3 87/10/18 10:23:55 narten 71263508Sdim * Updating version numbers. Changes relative to 1.1 are actually relative 72263508Sdim * to 4.1 73263508Sdim * 74263508Sdim * Revision 1.3 87/07/09 09:20:52 trinkle 75263508Sdim * Added check to make sure there is at least one arg before comparing argv[1] 76263508Sdim * with "-q". This necessary on machines that don't allow dereferncing null 77263508Sdim * pointers (i.e. Suns). 78198090Srdivacky * 79200581Srdivacky * Revision 1.2 87/03/27 14:21:47 jenkins 80263508Sdim * Port to suns 81263508Sdim * 82263508Sdim * Revision 4.1 83/05/10 16:31:02 wft 83263508Sdim * Added option -q and input from reading stdin. 84198090Srdivacky * Marker matching is now done with trymatch() (independent of keywords). 85198090Srdivacky * 86193323Sed * Revision 3.4 83/02/18 17:37:49 wft 87193323Sed * removed printing of new line after last file. 88198090Srdivacky * 89193323Sed * Revision 3.3 82/12/04 12:48:55 wft 90198090Srdivacky * Added LOCKER. 91198090Srdivacky * 92198090Srdivacky * Revision 3.2 82/11/28 18:24:17 wft 93193323Sed * removed Suffix; added ungetc to avoid skipping over trailing KDELIM. 94193323Sed * 95193323Sed * Revision 3.1 82/10/13 15:58:51 wft 96193323Sed * fixed type of variables receiving from getc() (char-->int). 97193323Sed*/ 98193323Sed 99193323Sed#include "rcsbase.h" 100193323Sed 101static int match P((FILE*)); 102static int scanfile P((FILE*,char const*,int)); 103static void reportError P((char const*)); 104 105mainProg(identId, "ident", "$Id$") 106/* Ident searches the named files for all occurrences 107 * of the pattern $@: text $ where @ is a keyword. 108 */ 109 110{ 111 FILE *fp; 112 int quiet = 0; 113 int status = EXIT_SUCCESS; 114 char const *a; 115 116 while ((a = *++argv) && *a=='-') 117 while (*++a) 118 switch (*a) { 119 case 'q': 120 quiet = 1; 121 break; 122 123 case 'V': 124 VOID printf("RCS version %s\n", RCS_version_string); 125 quiet = -1; 126 break; 127 128 default: 129 VOID fprintf(stderr, 130 "ident: usage: ident -{qV} [file...]\n" 131 ); 132 exitmain(EXIT_FAILURE); 133 break; 134 } 135 136 if (0 <= quiet) 137 if (!a) 138 VOID scanfile(stdin, (char*)0, quiet); 139 else 140 do { 141 if (!(fp = fopen(a, FOPEN_RB))) { 142 reportError(a); 143 status = EXIT_FAILURE; 144 } else if ( 145 scanfile(fp, a, quiet) != 0 146 || (argv[1] && putchar('\n') == EOF) 147 ) 148 break; 149 } while ((a = *++argv)); 150 151 if (ferror(stdout) || fclose(stdout)!=0) { 152 reportError("standard output"); 153 status = EXIT_FAILURE; 154 } 155 exitmain(status); 156} 157 158#if RCS_lint 159# define exiterr identExit 160#endif 161 void 162exiterr() 163{ 164 _exit(EXIT_FAILURE); 165} 166 167 static void 168reportError(s) 169 char const *s; 170{ 171 int e = errno; 172 VOID fprintf(stderr, "%s error: ", cmdid); 173 errno = e; 174 perror(s); 175} 176 177 178 static int 179scanfile(file, name, quiet) 180 register FILE *file; 181 char const *name; 182 int quiet; 183/* Function: scan an open file with descriptor file for keywords. 184 * Return -1 if there's a write error; exit immediately on a read error. 185 */ 186{ 187 register int c; 188 189 if (name) { 190 VOID printf("%s:\n", name); 191 if (ferror(stdout)) 192 return -1; 193 } else 194 name = "standard input"; 195 c = 0; 196 while (c != EOF || ! (feof(file)|ferror(file))) { 197 if (c == KDELIM) { 198 if ((c = match(file))) 199 continue; 200 if (ferror(stdout)) 201 return -1; 202 quiet = true; 203 } 204 c = getc(file); 205 } 206 if (ferror(file) || fclose(file) != 0) { 207 reportError(name); 208 /* 209 * The following is equivalent to exit(EXIT_FAILURE), but we invoke 210 * exiterr to keep lint happy. The DOS and OS/2 ports need exiterr. 211 */ 212 VOID fflush(stderr); 213 VOID fflush(stdout); 214 exiterr(); 215 } 216 if (!quiet) 217 VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name); 218 return 0; 219} 220 221 222 223 static int 224match(fp) /* group substring between two KDELIM's; then do pattern match */ 225 register FILE *fp; 226{ 227 char line[BUFSIZ]; 228 register int c; 229 register char * tp; 230 231 tp = line; 232 while ((c = getc(fp)) != VDELIM) { 233 if (c == EOF && feof(fp) | ferror(fp)) 234 return c; 235 switch (ctab[c]) { 236 case LETTER: case Letter: 237 *tp++ = c; 238 if (tp < line+sizeof(line)-4) 239 break; 240 /* fall into */ 241 default: 242 return c ? c : '\n'/* anything but 0 or KDELIM or EOF */; 243 } 244 } 245 if (tp == line) 246 return c; 247 *tp++ = c; 248 if ((c = getc(fp)) != ' ') 249 return c ? c : '\n'; 250 *tp++ = c; 251 while( (c = getc(fp)) != KDELIM ) { 252 if (c == EOF && feof(fp) | ferror(fp)) 253 return c; 254 switch (ctab[c]) { 255 default: 256 *tp++ = c; 257 if (tp < line+sizeof(line)-2) 258 break; 259 /* fall into */ 260 case NEWLN: case UNKN: 261 return c ? c : '\n'; 262 } 263 } 264 if (tp[-1] != ' ') 265 return c; 266 *tp++ = c; /*append trailing KDELIM*/ 267 *tp = '\0'; 268 VOID printf(" %c%s\n", KDELIM, line); 269 return 0; 270} 271