Resurrecting these files which are required for the MS Visual C++
[privoxy.git] / pcre / pcregrep.c
1 /*************************************************
2 *               pcregrep program                 *
3 *************************************************/
4
5 /* This is a grep program that uses the PCRE regular expression library to do
6 its pattern matching. */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include "config.h"
13 #include "pcre.h"
14
15 #define FALSE 0
16 #define TRUE 1
17
18 typedef int BOOL;
19
20
21
22 /*************************************************
23 *               Global variables                 *
24 *************************************************/
25
26 static pcre *pattern;
27 static pcre_extra *hints;
28
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;
35
36
37
38 #if ! HAVE_STRERROR
39 /*************************************************
40 *     Provide strerror() for non-ANSI libraries  *
41 *************************************************/
42
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. */
46
47 extern int   sys_nerr;
48 extern char *sys_errlist[];
49
50 char *
51 strerror(int n)
52 {
53 if (n < 0 || n >= sys_nerr) return "unknown error number";
54 return sys_errlist[n];
55 }
56 #endif /* HAVE_STRERROR */
57
58
59
60 /*************************************************
61 *              Grep an individual file           *
62 *************************************************/
63
64 static int
65 pcregrep(FILE *in, char *name)
66 {
67 int rc = 1;
68 int linenumber = 0;
69 int count = 0;
70 int offsets[99];
71 char buffer[BUFSIZ];
72
73 while (fgets(buffer, sizeof(buffer), in) != NULL)
74   {
75   BOOL match;
76   int length = (int)strlen(buffer);
77   if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0;
78   linenumber++;
79
80   match = pcre_exec(pattern, hints, buffer, length, 0, 0, offsets, 99) >= 0;
81   if (match && whole_lines && offsets[1] != length) match = FALSE;
82
83   if (match != invert)
84     {
85     if (count_only) count++;
86
87     else if (filenames_only)
88       {
89       fprintf(stdout, "%s\n", (name == NULL)? "<stdin>" : name);
90       return 0;
91       }
92
93     else if (silent) return 0;
94
95     else
96       {
97       if (name != NULL) fprintf(stdout, "%s:", name);
98       if (number) fprintf(stdout, "%d:", linenumber);
99       fprintf(stdout, "%s\n", buffer);
100       }
101
102     rc = 0;
103     }
104   }
105
106 if (count_only)
107   {
108   if (name != NULL) fprintf(stdout, "%s:", name);
109   fprintf(stdout, "%d\n", count);
110   }
111
112 return rc;
113 }
114
115
116
117
118 /*************************************************
119 *                Usage function                  *
120 *************************************************/
121
122 static int
123 usage(int rc)
124 {
125 fprintf(stderr, "Usage: pcregrep [-Vchilnsvx] pattern [file] ...\n");
126 return rc;
127 }
128
129
130
131
132 /*************************************************
133 *                Main program                    *
134 *************************************************/
135
136 int
137 main(int argc, char **argv)
138 {
139 int i;
140 int rc = 1;
141 int options = 0;
142 int errptr;
143 const char *error;
144 BOOL filenames = TRUE;
145
146 /* Process the options */
147
148 for (i = 1; i < argc; i++)
149   {
150   char *s;
151   if (argv[i][0] != '-') break;
152   s = argv[i] + 1;
153   while (*s != 0)
154     {
155     switch (*s++)
156       {
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;
165
166       case 'V':
167       fprintf(stderr, "PCRE version %s\n", pcre_version());
168       break;
169
170       default:
171       fprintf(stderr, "pcregrep: unknown option %c\n", s[-1]);
172       return usage(2);
173       }
174     }
175   }
176
177 /* There must be at least a regexp argument */
178
179 if (i >= argc) return usage(0);
180
181 /* Compile the regular expression. */
182
183 pattern = pcre_compile(argv[i++], options, &error, &errptr, NULL);
184 if (pattern == NULL)
185   {
186   fprintf(stderr, "pcregrep: error in regex at offset %d: %s\n", errptr, error);
187   return 2;
188   }
189
190 /* Study the regular expression, as we will be running it may times */
191
192 hints = pcre_study(pattern, 0, &error);
193 if (error != NULL)
194   {
195   fprintf(stderr, "pcregrep: error while studing regex: %s\n", error);
196   return 2;
197   }
198
199 /* If there are no further arguments, do the business on stdin and exit */
200
201 if (i >= argc) return pcregrep(stdin, NULL);
202
203 /* Otherwise, work through the remaining arguments as files. If there is only
204 one, don't give its name on the output. */
205
206 if (i == argc - 1) filenames = FALSE;
207 if (filenames_only) filenames = TRUE;
208
209 for (; i < argc; i++)
210   {
211   FILE *in = fopen(argv[i], "r");
212   if (in == NULL)
213     {
214     fprintf(stderr, "%s: failed to open: %s\n", argv[i], strerror(errno));
215     rc = 2;
216     }
217   else
218     {
219     int frc = pcregrep(in, filenames? argv[i] : NULL);
220     if (frc == 0 && rc == 1) rc = 0;
221     fclose(in);
222     }
223   }
224
225 return rc;
226 }
227
228 /* End */