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