/[pcre]/code/tags/pcre-5.0/pcregrep.c
ViewVC logotype

Diff of /code/tags/pcre-5.0/pcregrep.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 53 by nigel, Sat Feb 24 21:39:42 2007 UTC revision 75 by nigel, Sat Feb 24 21:40:37 2007 UTC
# Line 3  Line 3 
3  *************************************************/  *************************************************/
4    
5  /* This is a grep program that uses the PCRE regular expression library to do  /* This is a grep program that uses the PCRE regular expression library to do
6  its pattern matching. On a Unix system it can recurse into directories. */  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>  #include <ctype.h>
41  #include <stdio.h>  #include <stdio.h>
# Line 18  its pattern matching. On a Unix system i Line 50  its pattern matching. On a Unix system i
50    
51  typedef int BOOL;  typedef int BOOL;
52    
53  #define VERSION "2.0 01-Aug-2001"  #define VERSION "3.0 14-Jan-2003"
54  #define MAX_PATTERN_COUNT 100  #define MAX_PATTERN_COUNT 100
55    
56    
# Line 44  static BOOL whole_lines = FALSE; Line 76  static BOOL whole_lines = FALSE;
76    
77  typedef struct option_item {  typedef struct option_item {
78    int one_char;    int one_char;
79    char *long_name;    const char *long_name;
80    char *help_text;    const char *help_text;
81  } option_item;  } option_item;
82    
83  static option_item optionlist[] = {  static option_item optionlist[] = {
# Line 57  static option_item optionlist[] = { Line 89  static option_item optionlist[] = {
89    { 'n', "line-number",  "print line number with output lines" },    { 'n', "line-number",  "print line number with output lines" },
90    { 'r', "recursive",    "recursively scan sub-directories" },    { 'r', "recursive",    "recursively scan sub-directories" },
91    { 's', "no-messages",  "suppress error messages" },    { 's', "no-messages",  "suppress error messages" },
92      { 'u', "utf-8",        "use UTF-8 mode" },
93    { 'V', "version",      "print version information and exit" },    { 'V', "version",      "print version information and exit" },
94    { 'v', "invert-match", "select non-matching lines" },    { 'v', "invert-match", "select non-matching lines" },
95    { 'x', "line-regex",   "force PATTERN to match only whole lines" },    { 'x', "line-regex",   "force PATTERN to match only whole lines" },
# Line 70  static option_item optionlist[] = { Line 103  static option_item optionlist[] = {
103  *************************************************/  *************************************************/
104    
105  /* These functions are defined so that they can be made system specific,  /* These functions are defined so that they can be made system specific,
106  although at present the only ones are for Unix, and for "no directory recursion  although at present the only ones are for Unix, Win32, and for "no directory
107  support". */  recursion support". */
108    
109    
110  /************* Directory scanning in Unix ***********/  /************* Directory scanning in Unix ***********/
# Line 83  support". */ Line 116  support". */
116    
117  typedef DIR directory_type;  typedef DIR directory_type;
118    
119  int  static int
120  isdirectory(char *filename)  isdirectory(char *filename)
121  {  {
122  struct stat statbuf;  struct stat statbuf;
# Line 92  if (stat(filename, &statbuf) < 0) Line 125  if (stat(filename, &statbuf) < 0)
125  return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;  return ((statbuf.st_mode & S_IFMT) == S_IFDIR)? '/' : 0;
126  }  }
127    
128  directory_type *  static directory_type *
129  opendirectory(char *filename)  opendirectory(char *filename)
130  {  {
131  return opendir(filename);  return opendir(filename);
132  }  }
133    
134  char *  static char *
135  readdirectory(directory_type *dir)  readdirectory(directory_type *dir)
136  {  {
137  for (;;)  for (;;)
# Line 111  for (;;) Line 144  for (;;)
144  return NULL;   /* Keep compiler happy; never executed */  return NULL;   /* Keep compiler happy; never executed */
145  }  }
146    
147  void  static void
148  closedirectory(directory_type *dir)  closedirectory(directory_type *dir)
149  {  {
150  closedir(dir);  closedir(dir);
151  }  }
152    
153    
154  #else  /************* 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 ***********/  /************* Directory scanning when we can't do it ***********/
248    
249  /* The type is void, and apart from isdirectory(), the functions do nothing. */  /* The type is void, and apart from isdirectory(), the functions do nothing. */
250    
251    #else
252    
253  typedef void directory_type;  typedef void directory_type;
254    
255  int isdirectory(char *filename) { return FALSE; }  int isdirectory(char *filename) { return FALSE; }
# Line 226  return rc; Line 351  return rc;
351  *************************************************/  *************************************************/
352    
353  static int  static int
354  grep_or_recurse(char *filename, BOOL recurse, BOOL show_filenames,  grep_or_recurse(char *filename, BOOL dir_recurse, BOOL show_filenames,
355    BOOL only_one_at_top)    BOOL only_one_at_top)
356  {  {
357  int rc = 1;  int rc = 1;
# Line 236  FILE *in; Line 361  FILE *in;
361  /* If the file is a directory and we are recursing, scan each file within it.  /* 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. */  The scanning code is localized so it can be made system-specific. */
363    
364  if ((sep = isdirectory(filename)) != 0 && recurse)  if ((sep = isdirectory(filename)) != 0 && dir_recurse)
365    {    {
366    char buffer[1024];    char buffer[1024];
367    char *nextfile;    char *nextfile;
# Line 253  if ((sep = isdirectory(filename)) != 0 & Line 378  if ((sep = isdirectory(filename)) != 0 &
378      {      {
379      int frc;      int frc;
380      sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile);      sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile);
381      frc = grep_or_recurse(buffer, recurse, TRUE, FALSE);      frc = grep_or_recurse(buffer, dir_recurse, TRUE, FALSE);
382      if (frc == 0 && rc == 1) rc = 0;      if (frc == 0 && rc == 1) rc = 0;
383      }      }
384    
# Line 262  if ((sep = isdirectory(filename)) != 0 & Line 387  if ((sep = isdirectory(filename)) != 0 &
387    }    }
388    
389  /* If the file is not a directory, or we are not recursing, scan it. If this is  /* 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.  the first and only argument at top level, we don't show the file name (unless
391  Otherwise, control is via the show_filenames variable. */  we are only showing the file name). Otherwise, control is via the
392    show_filenames variable. */
393    
394  in = fopen(filename, "r");  in = fopen(filename, "r");
395  if (in == NULL)  if (in == NULL)
# Line 272  if (in == NULL) Line 398  if (in == NULL)
398    return 2;    return 2;
399    }    }
400    
401  rc = pcregrep(in, (show_filenames && !only_one_at_top)? filename : NULL);  rc = pcregrep(in, (filenames_only || (show_filenames && !only_one_at_top))?
402      filename : NULL);
403  fclose(in);  fclose(in);
404  return rc;  return rc;
405  }  }
# Line 287  return rc; Line 414  return rc;
414  static int  static int
415  usage(int rc)  usage(int rc)
416  {  {
417  fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] pattern [file] ...\n");  fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] [pattern] [file1 file2 ...]\n");
418  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information.\n");
419  return rc;  return rc;
420  }  }
# Line 304  help(void) Line 431  help(void)
431  {  {
432  option_item *op;  option_item *op;
433    
434  printf("Usage: pcregrep [OPTION]... PATTERN [FILE] ...\n");  printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
435  printf("Search for PATTERN in each FILE or standard input.\n");  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");  printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");
438    
439  printf("Options:\n");  printf("Options:\n");
# Line 350  switch(letter) Line 478  switch(letter)
478    case 'n': number = TRUE; break;    case 'n': number = TRUE; break;
479    case 'r': recurse = TRUE; break;    case 'r': recurse = TRUE; break;
480    case 's': silent = TRUE; break;    case 's': silent = TRUE; break;
481      case 'u': options |= PCRE_UTF8; break;
482    case 'v': invert = TRUE; break;    case 'v': invert = TRUE; break;
483    case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break;    case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break;
484    
# Line 390  for (i = 1; i < argc; i++) Line 519  for (i = 1; i < argc; i++)
519    {    {
520    if (argv[i][0] != '-') break;    if (argv[i][0] != '-') break;
521    
522      /* Missing options */
523    
524      if (argv[i][1] == 0) exit(usage(2));
525    
526    /* Long name options */    /* Long name options */
527    
528    if (argv[i][1] == '-')    if (argv[i][1] == '-')
# Line 443  for (i = 1; i < argc; i++) Line 576  for (i = 1; i < argc; i++)
576      }      }
577    }    }
578    
579  pattern_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre *));  pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));
580  hints_list = malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));  hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));
581    
582  if (pattern_list == NULL || hints_list == NULL)  if (pattern_list == NULL || hints_list == NULL)
583    {    {
# Line 492  if (pattern_filename != NULL) Line 625  if (pattern_filename != NULL)
625    
626  else  else
627    {    {
628    if (i >= argc) return usage(0);    if (i >= argc) return usage(2);
629    pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL);    pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL);
630    if (pattern_list[0] == NULL)    if (pattern_list[0] == NULL)
631      {      {

Legend:
Removed from v.53  
changed lines
  Added in v.75

  ViewVC Help
Powered by ViewVC 1.1.5