~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/pcre/pcregrep.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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. On a Unix or Win32 system it can recurse into
 
7
directories.
 
8
 
 
9
           Copyright (c) 1997-2004 University of Cambridge
 
10
 
 
11
-----------------------------------------------------------------------------
 
12
Redistribution and use in source and binary forms, with or without
 
13
modification, are permitted provided that the following conditions are met:
 
14
 
 
15
    * Redistributions of source code must retain the above copyright notice,
 
16
      this list of conditions and the following disclaimer.
 
17
 
 
18
    * Redistributions in binary form must reproduce the above copyright
 
19
      notice, this list of conditions and the following disclaimer in the
 
20
      documentation and/or other materials provided with the distribution.
 
21
 
 
22
    * Neither the name of the University of Cambridge nor the names of its
 
23
      contributors may be used to endorse or promote products derived from
 
24
      this software without specific prior written permission.
 
25
 
 
26
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
27
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
28
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
29
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
30
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
31
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
32
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
33
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
34
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
35
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
36
POSSIBILITY OF SUCH DAMAGE.
 
37
-----------------------------------------------------------------------------
 
38
*/
 
39
 
 
40
#include <ctype.h>
 
41
#include <stdio.h>
 
42
#include <string.h>
 
43
#include <stdlib.h>
 
44
#include <errno.h>
 
45
#include "config.h"
 
46
#include "pcre.h"
 
47
 
 
48
#define FALSE 0
 
49
#define TRUE 1
 
50
 
 
51
typedef int BOOL;
 
52
 
 
53
#define VERSION "3.0 14-Jan-2003"
 
54
#define MAX_PATTERN_COUNT 100
 
55
 
 
56
 
 
57
/*************************************************
 
58
*               Global variables                 *
 
59
*************************************************/
 
60
 
 
61
static char *pattern_filename = NULL;
 
62
static int  pattern_count = 0;
 
63
static pcre **pattern_list;
 
64
static pcre_extra **hints_list;
 
65
 
 
66
static BOOL count_only = FALSE;
 
67
static BOOL filenames = TRUE;
 
68
static BOOL filenames_only = FALSE;
 
69
static BOOL invert = FALSE;
 
70
static BOOL number = FALSE;
 
71
static BOOL recurse = FALSE;
 
72
static BOOL silent = FALSE;
 
73
static BOOL whole_lines = FALSE;
 
74
 
 
75
/* Structure for options and list of them */
 
76
 
 
77
typedef struct option_item {
 
78
  int one_char;
 
79
  const char *long_name;
 
80
  const char *help_text;
 
81
} option_item;
 
82
 
 
83
static option_item optionlist[] = {
 
84
  { -1,  "help",         "display this help and exit" },
 
85
  { 'c', "count",        "print only a count of matching lines per FILE" },
 
86
  { 'h', "no-filename",  "suppress the prefixing filename on output" },
 
87
  { 'i', "ignore-case",  "ignore case distinctions" },
 
88
  { 'l', "files-with-matches", "print only FILE names containing matches" },
 
89
  { 'n', "line-number",  "print line number with output lines" },
 
90
  { 'r', "recursive",    "recursively scan sub-directories" },
 
91
  { 's', "no-messages",  "suppress error messages" },
 
92
  { 'u', "utf-8",        "use UTF-8 mode" },
 
93
  { 'V', "version",      "print version information and exit" },
 
94
  { 'v', "invert-match", "select non-matching lines" },
 
95
  { 'x', "line-regex",   "force PATTERN to match only whole lines" },
 
96
  { 'x', "line-regexp",  "force PATTERN to match only whole lines" },
 
97
  { 0,    NULL,           NULL }
 
98
};
 
99
 
 
100
 
 
101
/*************************************************
 
102
*       Functions for directory scanning         *
 
103
*************************************************/
 
104
 
 
105
/* These functions are defined so that they can be made system specific,
 
106
although at present the only ones are for Unix, Win32, and for "no directory
 
107
recursion support". */
 
108
 
 
109
 
 
110
/************* Directory scanning in Unix ***********/
 
111
 
 
112
#if IS_UNIX
 
113
#include <sys/types.h>
 
114
#include <sys/stat.h>
 
115
#include <dirent.h>
 
116
 
 
117
typedef DIR directory_type;
 
118
 
 
119
static int
 
120
isdirectory(char *filename)
 
121
{
 
122
struct stat statbuf;
 
123
if (stat(filename, &statbuf) < 0)
 
124
  return 0;        /* In the expectation that opening as a file will fail */
 
125
return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;
 
126
}
 
127
 
 
128
static directory_type *
 
129
opendirectory(char *filename)
 
130
{
 
131
return opendir(filename);
 
132
}
 
133
 
 
134
static char *
 
135
readdirectory(directory_type *dir)
 
136
{
 
137
for (;;)
 
138
  {
 
139
  struct dirent *dent = readdir(dir);
 
140
  if (dent == NULL) return NULL;
 
141
  if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0)
 
142
    return dent->d_name;
 
143
  }
 
144
return NULL;   /* Keep compiler happy; never executed */
 
145
}
 
146
 
 
147
static void
 
148
closedirectory(directory_type *dir)
 
149
{
 
150
closedir(dir);
 
151
}
 
152
 
 
153
 
 
154
/************* Directory scanning in Win32 ***********/
 
155
 
 
156
/* I (Philip Hazel) have no means of testing this code. It was contributed by
 
157
Lionel Fourquaux. */
 
158
 
 
159
 
 
160
#elif HAVE_WIN32API
 
161
 
 
162
#ifndef STRICT
 
163
# define STRICT
 
164
#endif
 
165
#ifndef WIN32_LEAN_AND_MEAN
 
166
# define WIN32_LEAN_AND_MEAN
 
167
#endif
 
168
#include <windows.h>
 
169
 
 
170
typedef struct directory_type
 
171
{
 
172
HANDLE handle;
 
173
BOOL first;
 
174
WIN32_FIND_DATA data;
 
175
} directory_type;
 
176
 
 
177
int
 
178
isdirectory(char *filename)
 
179
{
 
180
DWORD attr = GetFileAttributes(filename);
 
181
if (attr == INVALID_FILE_ATTRIBUTES)
 
182
  return 0;
 
183
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) ? '/' : 0;
 
184
}
 
185
 
 
186
directory_type *
 
187
opendirectory(char *filename)
 
188
{
 
189
size_t len;
 
190
char *pattern;
 
191
directory_type *dir;
 
192
DWORD err;
 
193
len = strlen(filename);
 
194
pattern = (char *) malloc(len + 3);
 
195
dir = (directory_type *) malloc(sizeof(*dir));
 
196
if ((pattern == NULL) || (dir == NULL))
 
197
  {
 
198
  fprintf(stderr, "pcregrep: malloc failed\n");
 
199
  exit(2);
 
200
  }
 
201
memcpy(pattern, filename, len);
 
202
memcpy(&(pattern[len]), "\\*", 3);
 
203
dir->handle = FindFirstFile(pattern, &(dir->data));
 
204
if (dir->handle != INVALID_HANDLE_VALUE)
 
205
  {
 
206
  free(pattern);
 
207
  dir->first = TRUE;
 
208
  return dir;
 
209
  }
 
210
err = GetLastError();
 
211
free(pattern);
 
212
free(dir);
 
213
errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT;
 
214
return NULL;
 
215
}
 
216
 
 
217
char *
 
218
readdirectory(directory_type *dir)
 
219
{
 
220
for (;;)
 
221
  {
 
222
  if (!dir->first)
 
223
    {
 
224
    if (!FindNextFile(dir->handle, &(dir->data)))
 
225
      return NULL;
 
226
    }
 
227
  else
 
228
    {
 
229
    dir->first = FALSE;
 
230
    }
 
231
  if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0)
 
232
    return dir->data.cFileName;
 
233
  }
 
234
#ifndef _MSC_VER
 
235
return NULL;   /* Keep compiler happy; never executed */
 
236
#endif
 
237
}
 
238
 
 
239
void
 
240
closedirectory(directory_type *dir)
 
241
{
 
242
FindClose(dir->handle);
 
243
free(dir);
 
244
}
 
245
 
 
246
 
 
247
/************* Directory scanning when we can't do it ***********/
 
248
 
 
249
/* The type is void, and apart from isdirectory(), the functions do nothing. */
 
250
 
 
251
#else
 
252
 
 
253
typedef void directory_type;
 
254
 
 
255
int isdirectory(char *filename) { return FALSE; }
 
256
directory_type * opendirectory(char *filename) {}
 
257
char *readdirectory(directory_type *dir) {}
 
258
void closedirectory(directory_type *dir) {}
 
259
 
 
260
#endif
 
261
 
 
262
 
 
263
 
 
264
#if ! HAVE_STRERROR
 
265
/*************************************************
 
266
*     Provide strerror() for non-ANSI libraries  *
 
267
*************************************************/
 
268
 
 
269
/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()
 
270
in their libraries, but can provide the same facility by this simple
 
271
alternative function. */
 
272
 
 
273
extern int   sys_nerr;
 
274
extern char *sys_errlist[];
 
275
 
 
276
char *
 
277
strerror(int n)
 
278
{
 
279
if (n < 0 || n >= sys_nerr) return "unknown error number";
 
280
return sys_errlist[n];
 
281
}
 
282
#endif /* HAVE_STRERROR */
 
283
 
 
284
 
 
285
 
 
286
/*************************************************
 
287
*              Grep an individual file           *
 
288
*************************************************/
 
289
 
 
290
static int
 
291
pcregrep(FILE *in, char *name)
 
292
{
 
293
int rc = 1;
 
294
int linenumber = 0;
 
295
int count = 0;
 
296
int offsets[99];
 
297
char buffer[BUFSIZ];
 
298
 
 
299
while (fgets(buffer, sizeof(buffer), in) != NULL)
 
300
  {
 
301
  BOOL match = FALSE;
 
302
  int i;
 
303
  int length = (int)strlen(buffer);
 
304
  if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0;
 
305
  linenumber++;
 
306
 
 
307
  for (i = 0; !match && i < pattern_count; i++)
 
308
    {
 
309
    match = pcre_exec(pattern_list[i], hints_list[i], buffer, length, 0, 0,
 
310
      offsets, 99) >= 0;
 
311
    if (match && whole_lines && offsets[1] != length) match = FALSE;
 
312
    }
 
313
 
 
314
  if (match != invert)
 
315
    {
 
316
    if (count_only) count++;
 
317
 
 
318
    else if (filenames_only)
 
319
      {
 
320
      fprintf(stdout, "%s\n", (name == NULL)? "<stdin>" : name);
 
321
      return 0;
 
322
      }
 
323
 
 
324
    else if (silent) return 0;
 
325
 
 
326
    else
 
327
      {
 
328
      if (name != NULL) fprintf(stdout, "%s:", name);
 
329
      if (number) fprintf(stdout, "%d:", linenumber);
 
330
      fprintf(stdout, "%s\n", buffer);
 
331
      }
 
332
 
 
333
    rc = 0;
 
334
    }
 
335
  }
 
336
 
 
337
if (count_only)
 
338
  {
 
339
  if (name != NULL) fprintf(stdout, "%s:", name);
 
340
  fprintf(stdout, "%d\n", count);
 
341
  }
 
342
 
 
343
return rc;
 
344
}
 
345
 
 
346
 
 
347
 
 
348
 
 
349
/*************************************************
 
350
*     Grep a file or recurse into a directory    *
 
351
*************************************************/
 
352
 
 
353
static int
 
354
grep_or_recurse(char *filename, BOOL dir_recurse, BOOL show_filenames,
 
355
  BOOL only_one_at_top)
 
356
{
 
357
int rc = 1;
 
358
int sep;
 
359
FILE *in;
 
360
 
 
361
/* If the file is a directory and we are recursing, scan each file within it.
 
362
The scanning code is localized so it can be made system-specific. */
 
363
 
 
364
if ((sep = isdirectory(filename)) != 0 && dir_recurse)
 
365
  {
 
366
  char buffer[1024];
 
367
  char *nextfile;
 
368
  directory_type *dir = opendirectory(filename);
 
369
 
 
370
  if (dir == NULL)
 
371
    {
 
372
    fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", filename,
 
373
      strerror(errno));
 
374
    return 2;
 
375
    }
 
376
 
 
377
  while ((nextfile = readdirectory(dir)) != NULL)
 
378
    {
 
379
    int frc;
 
380
    sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile);
 
381
    frc = grep_or_recurse(buffer, dir_recurse, TRUE, FALSE);
 
382
    if (frc == 0 && rc == 1) rc = 0;
 
383
    }
 
384
 
 
385
  closedirectory(dir);
 
386
  return rc;
 
387
  }
 
388
 
 
389
/* If the file is not a directory, or we are not recursing, scan it. If this is
 
390
the first and only argument at top level, we don't show the file name (unless
 
391
we are only showing the file name). Otherwise, control is via the
 
392
show_filenames variable. */
 
393
 
 
394
in = fopen(filename, "r");
 
395
if (in == NULL)
 
396
  {
 
397
  fprintf(stderr, "pcregrep: Failed to open %s: %s\n", filename, strerror(errno));
 
398
  return 2;
 
399
  }
 
400
 
 
401
rc = pcregrep(in, (filenames_only || (show_filenames && !only_one_at_top))?
 
402
  filename : NULL);
 
403
fclose(in);
 
404
return rc;
 
405
}
 
406
 
 
407
 
 
408
 
 
409
 
 
410
/*************************************************
 
411
*                Usage function                  *
 
412
*************************************************/
 
413
 
 
414
static int
 
415
usage(int rc)
 
416
{
 
417
fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] [pattern] [file1 file2 ...]\n");
 
418
fprintf(stderr, "Type `pcregrep --help' for more information.\n");
 
419
return rc;
 
420
}
 
421
 
 
422
 
 
423
 
 
424
 
 
425
/*************************************************
 
426
*                Help function                   *
 
427
*************************************************/
 
428
 
 
429
static void
 
430
help(void)
 
431
{
 
432
option_item *op;
 
433
 
 
434
printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
 
435
printf("Search for PATTERN in each FILE or standard input.\n");
 
436
printf("PATTERN must be present if -f is not used.\n");
 
437
printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
 
438
 
 
439
printf("Options:\n");
 
440
 
 
441
for (op = optionlist; op->one_char != 0; op++)
 
442
  {
 
443
  int n;
 
444
  char s[4];
 
445
  if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, "   ");
 
446
  printf("  %s --%s%n", s, op->long_name, &n);
 
447
  n = 30 - n;
 
448
  if (n < 1) n = 1;
 
449
  printf("%.*s%s\n", n, "                    ", op->help_text);
 
450
  }
 
451
 
 
452
printf("\n  -f<filename>  or  --file=<filename>\n");
 
453
printf("    Read patterns from <filename> instead of using a command line option.\n");
 
454
printf("    Trailing white space is removed; blanks lines are ignored.\n");
 
455
printf("    There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);
 
456
 
 
457
printf("\nWith no FILE, read standard input. If fewer than two FILEs given, assume -h.\n");
 
458
printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
 
459
}
 
460
 
 
461
 
 
462
 
 
463
 
 
464
/*************************************************
 
465
*                Handle an option                *
 
466
*************************************************/
 
467
 
 
468
static int
 
469
handle_option(int letter, int options)
 
470
{
 
471
switch(letter)
 
472
  {
 
473
  case -1:  help(); exit(0);
 
474
  case 'c': count_only = TRUE; break;
 
475
  case 'h': filenames = FALSE; break;
 
476
  case 'i': options |= PCRE_CASELESS; break;
 
477
  case 'l': filenames_only = TRUE;
 
478
  case 'n': number = TRUE; break;
 
479
  case 'r': recurse = TRUE; break;
 
480
  case 's': silent = TRUE; break;
 
481
  case 'u': options |= PCRE_UTF8; break;
 
482
  case 'v': invert = TRUE; break;
 
483
  case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break;
 
484
 
 
485
  case 'V':
 
486
  fprintf(stderr, "pcregrep version %s using ", VERSION);
 
487
  fprintf(stderr, "PCRE version %s\n", pcre_version());
 
488
  exit(0);
 
489
  break;
 
490
 
 
491
  default:
 
492
  fprintf(stderr, "pcregrep: Unknown option -%c\n", letter);
 
493
  exit(usage(2));
 
494
  }
 
495
 
 
496
return options;
 
497
}
 
498
 
 
499
 
 
500
 
 
501
 
 
502
/*************************************************
 
503
*                Main program                    *
 
504
*************************************************/
 
505
 
 
506
int
 
507
main(int argc, char **argv)
 
508
{
 
509
int i, j;
 
510
int rc = 1;
 
511
int options = 0;
 
512
int errptr;
 
513
const char *error;
 
514
BOOL only_one_at_top;
 
515
 
 
516
/* Process the options */
 
517
 
 
518
for (i = 1; i < argc; i++)
 
519
  {
 
520
  if (argv[i][0] != '-') break;
 
521
 
 
522
  /* Missing options */
 
523
 
 
524
  if (argv[i][1] == 0) exit(usage(2));
 
525
 
 
526
  /* Long name options */
 
527
 
 
528
  if (argv[i][1] == '-')
 
529
    {
 
530
    option_item *op;
 
531
 
 
532
    if (strncmp(argv[i]+2, "file=", 5) == 0)
 
533
      {
 
534
      pattern_filename = argv[i] + 7;
 
535
      continue;
 
536
      }
 
537
 
 
538
    for (op = optionlist; op->one_char != 0; op++)
 
539
      {
 
540
      if (strcmp(argv[i]+2, op->long_name) == 0)
 
541
        {
 
542
        options = handle_option(op->one_char, options);
 
543
        break;
 
544
        }
 
545
      }
 
546
    if (op->one_char == 0)
 
547
      {
 
548
      fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]);
 
549
      exit(usage(2));
 
550
      }
 
551
    }
 
552
 
 
553
  /* One-char options */
 
554
 
 
555
  else
 
556
    {
 
557
    char *s = argv[i] + 1;
 
558
    while (*s != 0)
 
559
      {
 
560
      if (*s == 'f')
 
561
        {
 
562
        pattern_filename = s + 1;
 
563
        if (pattern_filename[0] == 0)
 
564
          {
 
565
          if (i >= argc - 1)
 
566
            {
 
567
            fprintf(stderr, "pcregrep: File name missing after -f\n");
 
568
            exit(usage(2));
 
569
            }
 
570
          pattern_filename = argv[++i];
 
571
          }
 
572
        break;
 
573
        }
 
574
      else options = handle_option(*s++, options);
 
575
      }
 
576
    }
 
577
  }
 
578
 
 
579
pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
 
580
hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
 
581
 
 
582
if (pattern_list == NULL || hints_list == NULL)
 
583
  {
 
584
  fprintf(stderr, "pcregrep: malloc failed\n");
 
585
  return 2;
 
586
  }
 
587
 
 
588
/* Compile the regular expression(s). */
 
589
 
 
590
if (pattern_filename != NULL)
 
591
  {
 
592
  FILE *f = fopen(pattern_filename, "r");
 
593
  char buffer[BUFSIZ];
 
594
  if (f == NULL)
 
595
    {
 
596
    fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename,
 
597
      strerror(errno));
 
598
    return 2;
 
599
    }
 
600
  while (fgets(buffer, sizeof(buffer), f) != NULL)
 
601
    {
 
602
    char *s = buffer + (int)strlen(buffer);
 
603
    if (pattern_count >= MAX_PATTERN_COUNT)
 
604
      {
 
605
      fprintf(stderr, "pcregrep: Too many patterns in file (max %d)\n",
 
606
        MAX_PATTERN_COUNT);
 
607
      return 2;
 
608
      }
 
609
    while (s > buffer && isspace((unsigned char)(s[-1]))) s--;
 
610
    if (s == buffer) continue;
 
611
    *s = 0;
 
612
    pattern_list[pattern_count] = pcre_compile(buffer, options, &error,
 
613
      &errptr, NULL);
 
614
    if (pattern_list[pattern_count++] == NULL)
 
615
      {
 
616
      fprintf(stderr, "pcregrep: Error in regex number %d at offset %d: %s\n",
 
617
        pattern_count, errptr, error);
 
618
      return 2;
 
619
      }
 
620
    }
 
621
  fclose(f);
 
622
  }
 
623
 
 
624
/* If no file name, a single regex must be given inline */
 
625
 
 
626
else
 
627
  {
 
628
  if (i >= argc) return usage(2);
 
629
  pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL);
 
630
  if (pattern_list[0] == NULL)
 
631
    {
 
632
    fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", errptr,
 
633
      error);
 
634
    return 2;
 
635
    }
 
636
  pattern_count++;
 
637
  }
 
638
 
 
639
/* Study the regular expressions, as we will be running them may times */
 
640
 
 
641
for (j = 0; j < pattern_count; j++)
 
642
  {
 
643
  hints_list[j] = pcre_study(pattern_list[j], 0, &error);
 
644
  if (error != NULL)
 
645
    {
 
646
    char s[16];
 
647
    if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j);
 
648
    fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error);
 
649
    return 2;
 
650
    }
 
651
  }
 
652
 
 
653
/* If there are no further arguments, do the business on stdin and exit */
 
654
 
 
655
if (i >= argc) return pcregrep(stdin, NULL);
 
656
 
 
657
/* Otherwise, work through the remaining arguments as files or directories.
 
658
Pass in the fact that there is only one argument at top level - this suppresses
 
659
the file name if the argument is not a directory. */
 
660
 
 
661
only_one_at_top = (i == argc - 1);
 
662
if (filenames_only) filenames = TRUE;
 
663
 
 
664
for (; i < argc; i++)
 
665
  {
 
666
  int frc = grep_or_recurse(argv[i], recurse, filenames, only_one_at_top);
 
667
  if (frc == 0 && rc == 1) rc = 0;
 
668
  }
 
669
 
 
670
return rc;
 
671
}
 
672
 
 
673
/* End */