/[pcre]/code/trunk/pcregrep.c
ViewVC logotype

Diff of /code/trunk/pcregrep.c

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

revision 239 by ph10, Tue Sep 11 13:46:30 2007 UTC revision 283 by ph10, Fri Dec 7 19:59:19 2007 UTC
# Line 142  static int process_options = 0; Line 142  static int process_options = 0;
142    
143  static BOOL count_only = FALSE;  static BOOL count_only = FALSE;
144  static BOOL do_colour = FALSE;  static BOOL do_colour = FALSE;
145    static BOOL file_offsets = FALSE;
146  static BOOL hyphenpending = FALSE;  static BOOL hyphenpending = FALSE;
147  static BOOL invert = FALSE;  static BOOL invert = FALSE;
148    static BOOL line_offsets = FALSE;
149  static BOOL multiline = FALSE;  static BOOL multiline = FALSE;
150  static BOOL number = FALSE;  static BOOL number = FALSE;
151  static BOOL only_matching = FALSE;  static BOOL only_matching = FALSE;
# Line 174  used to identify them. */ Line 176  used to identify them. */
176  #define N_LABEL     (-5)  #define N_LABEL     (-5)
177  #define N_LOCALE    (-6)  #define N_LOCALE    (-6)
178  #define N_NULL      (-7)  #define N_NULL      (-7)
179    #define N_LOFFSETS  (-8)
180    #define N_FOFFSETS  (-9)
181    
182  static option_item optionlist[] = {  static option_item optionlist[] = {
183    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },    { OP_NODATA,    N_NULL,   NULL,              "",              "  terminate options" },
# Line 189  static option_item optionlist[] = { Line 193  static option_item optionlist[] = {
193    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },    { OP_PATLIST,   'e',      NULL,              "regex(p)",      "specify pattern (may be used more than once)" },
194    { OP_NODATA,    'F',      NULL,              "fixed_strings", "patterns are sets of newline-separated strings" },    { OP_NODATA,    'F',      NULL,              "fixed_strings", "patterns are sets of newline-separated strings" },
195    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },    { OP_STRING,    'f',      &pattern_filename, "file=path",     "read patterns from file" },
196      { OP_NODATA,    N_FOFFSETS, NULL,            "file-offsets",  "output file offsets, not text" },
197    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },    { OP_NODATA,    'H',      NULL,              "with-filename", "force the prefixing filename on output" },
198    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },    { OP_NODATA,    'h',      NULL,              "no-filename",   "suppress the prefixing filename on output" },
199    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },    { OP_NODATA,    'i',      NULL,              "ignore-case",   "ignore case distinctions" },
200    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },    { OP_NODATA,    'l',      NULL,              "files-with-matches", "print only FILE names containing matches" },
201    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },    { OP_NODATA,    'L',      NULL,              "files-without-match","print only FILE names not containing matches" },
202    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },    { OP_STRING,    N_LABEL,  &stdin_name,       "label=name",    "set name for standard input" },
203      { OP_NODATA,    N_LOFFSETS, NULL,            "line-offsets",  "output line numbers and offsets, not text" },
204    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },    { OP_STRING,    N_LOCALE, &locale,           "locale=locale", "use the named locale" },
205    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },    { OP_NODATA,    'M',      NULL,              "multiline",     "run in multiline mode" },
206    { OP_STRING,    'N',      &newline,          "newline=type",  "specify newline type (CR, LF, CRLF, ANYCRLF or ANY)" },    { OP_STRING,    'N',      &newline,          "newline=type",  "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" },
207    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },    { OP_NODATA,    'n',      NULL,              "line-number",   "print line number with output lines" },
208    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },    { OP_NODATA,    'o',      NULL,              "only-matching", "show only the part of the line that matched" },
209    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },    { OP_NODATA,    'q',      NULL,              "quiet",         "suppress output, just set return code" },
# Line 316  return isatty(fileno(stdout)); Line 322  return isatty(fileno(stdout));
322    
323  /* I (Philip Hazel) have no means of testing this code. It was contributed by  /* I (Philip Hazel) have no means of testing this code. It was contributed by
324  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES  Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES
325  when it did not exist. */  when it did not exist. David Byron added a patch that moved the #include of
326    <windows.h> to before the INVALID_FILE_ATTRIBUTES definition rather than after.
327    */
328    
329  #elif HAVE_WINDOWS_H  #elif HAVE_WINDOWS_H
330    
# Line 327  when it did not exist. */ Line 334  when it did not exist. */
334  #ifndef WIN32_LEAN_AND_MEAN  #ifndef WIN32_LEAN_AND_MEAN
335  # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
336  #endif  #endif
337    
338    #include <windows.h>
339    
340  #ifndef INVALID_FILE_ATTRIBUTES  #ifndef INVALID_FILE_ATTRIBUTES
341  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF  #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
342  #endif  #endif
343    
 #include <windows.h>  
   
344  typedef struct directory_type  typedef struct directory_type
345  {  {
346  HANDLE handle;  HANDLE handle;
# Line 417  regular if they are not directories. */ Line 425  regular if they are not directories. */
425    
426  int isregfile(char *filename)  int isregfile(char *filename)
427  {  {
428  return !isdirectory(filename)  return !isdirectory(filename);
429  }  }
430    
431    
# Line 428  return !isdirectory(filename) Line 436  return !isdirectory(filename)
436  static BOOL  static BOOL
437  is_stdout_tty(void)  is_stdout_tty(void)
438  {  {
439  FALSE;  return FALSE;
440  }  }
441    
442    
# Line 820  int rc = 1; Line 828  int rc = 1;
828  int linenumber = 1;  int linenumber = 1;
829  int lastmatchnumber = 0;  int lastmatchnumber = 0;
830  int count = 0;  int count = 0;
831    int filepos = 0;
832  int offsets[99];  int offsets[99];
833  char *lastmatchrestart = NULL;  char *lastmatchrestart = NULL;
834  char buffer[3*MBUFTHIRD];  char buffer[3*MBUFTHIRD];
# Line 844  while (ptr < endptr) Line 853  while (ptr < endptr)
853    int i, endlinelength;    int i, endlinelength;
854    int mrc = 0;    int mrc = 0;
855    BOOL match = FALSE;    BOOL match = FALSE;
856      char *matchptr = ptr;
857    char *t = ptr;    char *t = ptr;
858    size_t length, linelength;    size_t length, linelength;
859    
# Line 906  while (ptr < endptr) Line 916  while (ptr < endptr)
916    }    }
917  #endif  #endif
918    
919      /* We come back here after a match when the -o option (only_matching) is set,
920      in order to find any further matches in the same line. */
921    
922      ONLY_MATCHING_RESTART:
923    
924    /* Run through all the patterns until one matches. Note that we don't include    /* Run through all the patterns until one matches. Note that we don't include
925    the final newline in the subject string. */    the final newline in the subject string. */
926    
927    for (i = 0; i < pattern_count; i++)    for (i = 0; i < pattern_count; i++)
928      {      {
929      mrc = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0,      mrc = pcre_exec(pattern_list[i], hints_list[i], matchptr, length, 0, 0,
930        offsets, 99);        offsets, 99);
931      if (mrc >= 0) { match = TRUE; break; }      if (mrc >= 0) { match = TRUE; break; }
932      if (mrc != PCRE_ERROR_NOMATCH)      if (mrc != PCRE_ERROR_NOMATCH)
# Line 920  while (ptr < endptr) Line 934  while (ptr < endptr)
934        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);        fprintf(stderr, "pcregrep: pcre_exec() error %d while matching ", mrc);
935        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);        if (pattern_count > 1) fprintf(stderr, "pattern number %d to ", i+1);
936        fprintf(stderr, "this line:\n");        fprintf(stderr, "this line:\n");
937        fwrite(ptr, 1, linelength, stderr);   /* In case binary zero included */        fwrite(matchptr, 1, linelength, stderr);  /* In case binary zero included */
938        fprintf(stderr, "\n");        fprintf(stderr, "\n");
939        if (error_count == 0 &&        if (error_count == 0 &&
940            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))            (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))
# Line 967  while (ptr < endptr) Line 981  while (ptr < endptr)
981      else if (quiet) return 0;      else if (quiet) return 0;
982    
983      /* The --only-matching option prints just the substring that matched, and      /* The --only-matching option prints just the substring that matched, and
984      does not pring any context. */      the --file-offsets and --line-offsets options output offsets for the
985        matching substring (they both force --only-matching). None of these options
986        prints any context. Afterwards, adjust the start and length, and then jump
987        back to look for further matches in the same line. If we are in invert
988        mode, however, nothing is printed - this could be still useful because the
989        return code is set. */
990    
991      else if (only_matching)      else if (only_matching)
992        {        {
993        if (printname != NULL) fprintf(stdout, "%s:", printname);        if (!invert)
994        if (number) fprintf(stdout, "%d:", linenumber);          {
995        fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          if (printname != NULL) fprintf(stdout, "%s:", printname);
996        fprintf(stdout, "\n");          if (number) fprintf(stdout, "%d:", linenumber);
997            if (line_offsets)
998              fprintf(stdout, "%d,%d", matchptr + offsets[0] - ptr,
999                offsets[1] - offsets[0]);
1000            else if (file_offsets)
1001              fprintf(stdout, "%d,%d", filepos + matchptr + offsets[0] - ptr,
1002                offsets[1] - offsets[0]);
1003            else
1004              fwrite(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1005            fprintf(stdout, "\n");
1006            matchptr += offsets[1];
1007            length -= offsets[1];
1008            match = FALSE;
1009            goto ONLY_MATCHING_RESTART;
1010            }
1011        }        }
1012    
1013      /* This is the default case when none of the above options is set. We print      /* This is the default case when none of the above options is set. We print
# Line 1113  while (ptr < endptr) Line 1146  while (ptr < endptr)
1146          fprintf(stdout, "%c[%sm", 0x1b, colour_string);          fprintf(stdout, "%c[%sm", 0x1b, colour_string);
1147          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);          fwrite(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
1148          fprintf(stdout, "%c[00m", 0x1b);          fprintf(stdout, "%c[00m", 0x1b);
1149          fwrite(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],          fwrite(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],
1150            stdout);            stdout);
1151          }          }
1152        else fwrite(ptr, 1, linelength + endlinelength, stdout);        else fwrite(ptr, 1, linelength + endlinelength, stdout);
# Line 1148  while (ptr < endptr) Line 1181  while (ptr < endptr)
1181      linelength = endmatch - ptr - ellength;      linelength = endmatch - ptr - ellength;
1182      }      }
1183    
1184    /* Advance to after the newline and increment the line number. */    /* Advance to after the newline and increment the line number. The file
1185      offset to the current line is maintained in filepos. */
1186    
1187    ptr += linelength + endlinelength;    ptr += linelength + endlinelength;
1188      filepos += linelength + endlinelength;
1189    linenumber++;    linenumber++;
1190    
1191    /* If we haven't yet reached the end of the file (the buffer is full), and    /* If we haven't yet reached the end of the file (the buffer is full), and
# Line 1337  for (op = optionlist; op->one_char != 0; Line 1372  for (op = optionlist; op->one_char != 0;
1372    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);    if (op->one_char > 0) fprintf(stderr, "%c", op->one_char);
1373    }    }
1374  fprintf(stderr, "] [long options] [pattern] [files]\n");  fprintf(stderr, "] [long options] [pattern] [files]\n");
1375  fprintf(stderr, "Type `pcregrep --help' for more information.\n");  fprintf(stderr, "Type `pcregrep --help' for more information and the long "
1376      "options.\n");
1377  return rc;  return rc;
1378  }  }
1379    
# Line 1392  handle_option(int letter, int options) Line 1428  handle_option(int letter, int options)
1428  {  {
1429  switch(letter)  switch(letter)
1430    {    {
1431      case N_FOFFSETS: file_offsets = TRUE; break;
1432    case N_HELP: help(); exit(0);    case N_HELP: help(); exit(0);
1433      case N_LOFFSETS: line_offsets = number = TRUE; break;
1434    case 'c': count_only = TRUE; break;    case 'c': count_only = TRUE; break;
1435    case 'F': process_options |= PO_FIXED_STRINGS; break;    case 'F': process_options |= PO_FIXED_STRINGS; break;
1436    case 'H': filenames = FN_FORCE; break;    case 'H': filenames = FN_FORCE; break;
# Line 1828  if (both_context > 0) Line 1866  if (both_context > 0)
1866    if (after_context == 0) after_context = both_context;    if (after_context == 0) after_context = both_context;
1867    if (before_context == 0) before_context = both_context;    if (before_context == 0) before_context = both_context;
1868    }    }
1869    
1870    /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted.
1871    However, the latter two set the only_matching flag. */
1872    
1873    if ((only_matching && (file_offsets || line_offsets)) ||
1874        (file_offsets && line_offsets))
1875      {
1876      fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets "
1877        "and/or --line-offsets\n");
1878      exit(usage(2));
1879      }
1880    
1881    if (file_offsets || line_offsets) only_matching = TRUE;
1882    
1883  /* If a locale has not been provided as an option, see if the LC_CTYPE or  /* If a locale has not been provided as an option, see if the LC_CTYPE or
1884  LC_ALL environment variable is set, and if so, use it. */  LC_ALL environment variable is set, and if so, use it. */

Legend:
Removed from v.239  
changed lines
  Added in v.283

  ViewVC Help
Powered by ViewVC 1.1.5