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