1 /*************************************************
3 *************************************************/
5 /* This is a grep program that uses the PCRE regular expression library to do
6 its pattern matching. */
22 /*************************************************
24 *************************************************/
27 static pcre_extra *hints;
29 static BOOL count_only = FALSE;
30 static BOOL filenames_only = FALSE;
31 static BOOL invert = FALSE;
32 static BOOL number = FALSE;
33 static BOOL silent = FALSE;
34 static BOOL whole_lines = FALSE;
39 /*************************************************
40 * Provide strerror() for non-ANSI libraries *
41 *************************************************/
43 /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()
44 in their libraries, but can provide the same facility by this simple
45 alternative function. */
48 extern char *sys_errlist[];
53 if (n < 0 || n >= sys_nerr) return "unknown error number";
54 return sys_errlist[n];
56 #endif /* HAVE_STRERROR */
60 /*************************************************
61 * Grep an individual file *
62 *************************************************/
65 pcregrep(FILE *in, char *name)
73 while (fgets(buffer, sizeof(buffer), in) != NULL)
76 int length = (int)strlen(buffer);
77 if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0;
80 match = pcre_exec(pattern, hints, buffer, length, 0, 0, offsets, 99) >= 0;
81 if (match && whole_lines && offsets[1] != length) match = FALSE;
85 if (count_only) count++;
87 else if (filenames_only)
89 fprintf(stdout, "%s\n", (name == NULL)? "<stdin>" : name);
93 else if (silent) return 0;
97 if (name != NULL) fprintf(stdout, "%s:", name);
98 if (number) fprintf(stdout, "%d:", linenumber);
99 fprintf(stdout, "%s\n", buffer);
108 if (name != NULL) fprintf(stdout, "%s:", name);
109 fprintf(stdout, "%d\n", count);
118 /*************************************************
120 *************************************************/
125 fprintf(stderr, "Usage: pcregrep [-Vchilnsvx] pattern [file] ...\n");
132 /*************************************************
134 *************************************************/
137 main(int argc, char **argv)
144 BOOL filenames = TRUE;
146 /* Process the options */
148 for (i = 1; i < argc; i++)
151 if (argv[i][0] != '-') break;
157 case 'c': count_only = TRUE; break;
158 case 'h': filenames = FALSE; break;
159 case 'i': options |= PCRE_CASELESS; break;
160 case 'l': filenames_only = TRUE;
161 case 'n': number = TRUE; break;
162 case 's': silent = TRUE; break;
163 case 'v': invert = TRUE; break;
164 case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break;
167 fprintf(stderr, "PCRE version %s\n", pcre_version());
171 fprintf(stderr, "pcregrep: unknown option %c\n", s[-1]);
177 /* There must be at least a regexp argument */
179 if (i >= argc) return usage(0);
181 /* Compile the regular expression. */
183 pattern = pcre_compile(argv[i++], options, &error, &errptr, NULL);
186 fprintf(stderr, "pcregrep: error in regex at offset %d: %s\n", errptr, error);
190 /* Study the regular expression, as we will be running it may times */
192 hints = pcre_study(pattern, 0, &error);
195 fprintf(stderr, "pcregrep: error while studing regex: %s\n", error);
199 /* If there are no further arguments, do the business on stdin and exit */
201 if (i >= argc) return pcregrep(stdin, NULL);
203 /* Otherwise, work through the remaining arguments as files. If there is only
204 one, don't give its name on the output. */
206 if (i == argc - 1) filenames = FALSE;
207 if (filenames_only) filenames = TRUE;
209 for (; i < argc; i++)
211 FILE *in = fopen(argv[i], "r");
214 fprintf(stderr, "%s: failed to open: %s\n", argv[i], strerror(errno));
219 int frc = pcregrep(in, filenames? argv[i] : NULL);
220 if (frc == 0 && rc == 1) rc = 0;