| 50 |
|
|
| 51 |
#include <sys/types.h> |
#include <sys/types.h> |
| 52 |
#include <sys/stat.h> |
#include <sys/stat.h> |
| 53 |
#include <unistd.h> |
#ifdef HAVE_UNISTD_H |
| 54 |
|
# include <unistd.h> |
| 55 |
|
#endif |
| 56 |
|
|
| 57 |
#include "pcre.h" |
#include <pcre.h> |
| 58 |
|
|
| 59 |
#define FALSE 0 |
#define FALSE 0 |
| 60 |
#define TRUE 1 |
#define TRUE 1 |
| 88 |
|
|
| 89 |
/* Line ending types */ |
/* Line ending types */ |
| 90 |
|
|
| 91 |
enum { EL_LF, EL_CR, EL_CRLF, EL_ANY }; |
enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF }; |
| 92 |
|
|
| 93 |
|
|
| 94 |
|
|
| 196 |
{ 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" }, |
| 197 |
{ OP_STRING, N_LOCALE, &locale, "locale=locale", "use the named locale" }, |
{ OP_STRING, N_LOCALE, &locale, "locale=locale", "use the named locale" }, |
| 198 |
{ OP_NODATA, 'M', NULL, "multiline", "run in multiline mode" }, |
{ OP_NODATA, 'M', NULL, "multiline", "run in multiline mode" }, |
| 199 |
{ OP_STRING, 'N', &newline, "newline=type", "specify newline type (CR, LR, CRLF)" }, |
{ OP_STRING, 'N', &newline, "newline=type", "specify newline type (CR, LF, CRLF, ANYCRLF or ANY)" }, |
| 200 |
{ OP_NODATA, 'n', NULL, "line-number", "print line number with output lines" }, |
{ OP_NODATA, 'n', NULL, "line-number", "print line number with output lines" }, |
| 201 |
{ 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" }, |
| 202 |
{ OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, |
{ OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, |
| 226 |
static const char *suffix[] = { |
static const char *suffix[] = { |
| 227 |
"", "\\b", ")$", ")$", "\\E", "\\E\\b", "\\E)$", "\\E)$" }; |
"", "\\b", ")$", ")$", "\\E", "\\E\\b", "\\E)$", "\\E)$" }; |
| 228 |
|
|
| 229 |
/* UTF-8 tables - used only when the newline setting is "all". */ |
/* UTF-8 tables - used only when the newline setting is "any". */ |
| 230 |
|
|
| 231 |
const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; |
const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; |
| 232 |
|
|
| 280 |
if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) |
if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) |
| 281 |
return dent->d_name; |
return dent->d_name; |
| 282 |
} |
} |
| 283 |
return NULL; /* Keep compiler happy; never executed */ |
/* Control never reaches here */ |
| 284 |
} |
} |
| 285 |
|
|
| 286 |
static void |
static void |
| 465 |
|
|
| 466 |
|
|
| 467 |
|
|
| 468 |
#if ! HAVE_STRERROR |
#ifndef HAVE_STRERROR |
| 469 |
/************************************************* |
/************************************************* |
| 470 |
* Provide strerror() for non-ANSI libraries * |
* Provide strerror() for non-ANSI libraries * |
| 471 |
*************************************************/ |
*************************************************/ |
| 545 |
} |
} |
| 546 |
break; |
break; |
| 547 |
|
|
| 548 |
|
case EL_ANYCRLF: |
| 549 |
|
while (p < endptr) |
| 550 |
|
{ |
| 551 |
|
int extra = 0; |
| 552 |
|
register int c = *((unsigned char *)p); |
| 553 |
|
|
| 554 |
|
if (utf8 && c >= 0xc0) |
| 555 |
|
{ |
| 556 |
|
int gcii, gcss; |
| 557 |
|
extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */ |
| 558 |
|
gcss = 6*extra; |
| 559 |
|
c = (c & utf8_table3[extra]) << gcss; |
| 560 |
|
for (gcii = 1; gcii <= extra; gcii++) |
| 561 |
|
{ |
| 562 |
|
gcss -= 6; |
| 563 |
|
c |= (p[gcii] & 0x3f) << gcss; |
| 564 |
|
} |
| 565 |
|
} |
| 566 |
|
|
| 567 |
|
p += 1 + extra; |
| 568 |
|
|
| 569 |
|
switch (c) |
| 570 |
|
{ |
| 571 |
|
case 0x0a: /* LF */ |
| 572 |
|
*lenptr = 1; |
| 573 |
|
return p; |
| 574 |
|
|
| 575 |
|
case 0x0d: /* CR */ |
| 576 |
|
if (p < endptr && *p == 0x0a) |
| 577 |
|
{ |
| 578 |
|
*lenptr = 2; |
| 579 |
|
p++; |
| 580 |
|
} |
| 581 |
|
else *lenptr = 1; |
| 582 |
|
return p; |
| 583 |
|
|
| 584 |
|
default: |
| 585 |
|
break; |
| 586 |
|
} |
| 587 |
|
} /* End of loop for ANYCRLF case */ |
| 588 |
|
|
| 589 |
|
*lenptr = 0; /* Must have hit the end */ |
| 590 |
|
return endptr; |
| 591 |
|
|
| 592 |
case EL_ANY: |
case EL_ANY: |
| 593 |
while (p < endptr) |
while (p < endptr) |
| 594 |
{ |
{ |
| 687 |
return p; /* But control should never get here */ |
return p; /* But control should never get here */ |
| 688 |
|
|
| 689 |
case EL_ANY: |
case EL_ANY: |
| 690 |
|
case EL_ANYCRLF: |
| 691 |
if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--; |
if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--; |
| 692 |
if (utf8) while ((*p & 0xc0) == 0x80) p--; |
if (utf8) while ((*p & 0xc0) == 0x80) p--; |
| 693 |
|
|
| 716 |
} |
} |
| 717 |
else c = *((unsigned char *)pp); |
else c = *((unsigned char *)pp); |
| 718 |
|
|
| 719 |
switch (c) |
if (endlinetype == EL_ANYCRLF) switch (c) |
| 720 |
|
{ |
| 721 |
|
case 0x0a: /* LF */ |
| 722 |
|
case 0x0d: /* CR */ |
| 723 |
|
return p; |
| 724 |
|
|
| 725 |
|
default: |
| 726 |
|
break; |
| 727 |
|
} |
| 728 |
|
|
| 729 |
|
else switch (c) |
| 730 |
{ |
{ |
| 731 |
case 0x0a: /* LF */ |
case 0x0a: /* LF */ |
| 732 |
case 0x0b: /* VT */ |
case 0x0b: /* VT */ |
| 1463 |
suffix[process_options]); |
suffix[process_options]); |
| 1464 |
pattern_list[pattern_count] = |
pattern_list[pattern_count] = |
| 1465 |
pcre_compile(buffer, options, &error, &errptr, pcretables); |
pcre_compile(buffer, options, &error, &errptr, pcretables); |
| 1466 |
if (pattern_list[pattern_count++] != NULL) return TRUE; |
if (pattern_list[pattern_count] != NULL) |
| 1467 |
|
{ |
| 1468 |
|
pattern_count++; |
| 1469 |
|
return TRUE; |
| 1470 |
|
} |
| 1471 |
|
|
| 1472 |
/* Handle compile errors */ |
/* Handle compile errors */ |
| 1473 |
|
|
| 1525 |
char *p = end_of_line(pattern, eop, &ellength); |
char *p = end_of_line(pattern, eop, &ellength); |
| 1526 |
if (ellength == 0) |
if (ellength == 0) |
| 1527 |
return compile_single_pattern(pattern, options, filename, count); |
return compile_single_pattern(pattern, options, filename, count); |
| 1528 |
sprintf(buffer, "%.*s", p - pattern - ellength, pattern); |
sprintf(buffer, "%.*s", (int)(p - pattern - ellength), pattern); |
| 1529 |
pattern = p; |
pattern = p; |
| 1530 |
if (!compile_single_pattern(buffer, options, filename, count)) |
if (!compile_single_pattern(buffer, options, filename, count)) |
| 1531 |
return FALSE; |
return FALSE; |
| 1549 |
int rc = 1; |
int rc = 1; |
| 1550 |
int pcre_options = 0; |
int pcre_options = 0; |
| 1551 |
int cmd_pattern_count = 0; |
int cmd_pattern_count = 0; |
| 1552 |
|
int hint_count = 0; |
| 1553 |
int errptr; |
int errptr; |
| 1554 |
BOOL only_one_at_top; |
BOOL only_one_at_top; |
| 1555 |
char *patterns[MAX_PATTERN_COUNT]; |
char *patterns[MAX_PATTERN_COUNT]; |
| 1567 |
case '\r': newline = (char *)"cr"; break; |
case '\r': newline = (char *)"cr"; break; |
| 1568 |
case ('\r' << 8) | '\n': newline = (char *)"crlf"; break; |
case ('\r' << 8) | '\n': newline = (char *)"crlf"; break; |
| 1569 |
case -1: newline = (char *)"any"; break; |
case -1: newline = (char *)"any"; break; |
| 1570 |
|
case -2: newline = (char *)"anycrlf"; break; |
| 1571 |
} |
} |
| 1572 |
|
|
| 1573 |
/* Process the options */ |
/* Process the options */ |
| 1644 |
char buff2[24]; |
char buff2[24]; |
| 1645 |
int baselen = opbra - op->long_name; |
int baselen = opbra - op->long_name; |
| 1646 |
sprintf(buff1, "%.*s", baselen, op->long_name); |
sprintf(buff1, "%.*s", baselen, op->long_name); |
| 1647 |
sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2, |
sprintf(buff2, "%s%.*s", buff1, |
| 1648 |
opbra + 1); |
(int)strlen(op->long_name) - baselen - 2, opbra + 1); |
| 1649 |
if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0) |
if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0) |
| 1650 |
break; |
break; |
| 1651 |
} |
} |
| 1875 |
pcre_options |= PCRE_NEWLINE_ANY; |
pcre_options |= PCRE_NEWLINE_ANY; |
| 1876 |
endlinetype = EL_ANY; |
endlinetype = EL_ANY; |
| 1877 |
} |
} |
| 1878 |
|
else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0) |
| 1879 |
|
{ |
| 1880 |
|
pcre_options |= PCRE_NEWLINE_ANYCRLF; |
| 1881 |
|
endlinetype = EL_ANYCRLF; |
| 1882 |
|
} |
| 1883 |
else |
else |
| 1884 |
{ |
{ |
| 1885 |
fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline); |
fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline); |
| 1934 |
if (pattern_list == NULL || hints_list == NULL) |
if (pattern_list == NULL || hints_list == NULL) |
| 1935 |
{ |
{ |
| 1936 |
fprintf(stderr, "pcregrep: malloc failed\n"); |
fprintf(stderr, "pcregrep: malloc failed\n"); |
| 1937 |
goto EXIT2; |
goto EXIT2; |
| 1938 |
} |
} |
| 1939 |
|
|
| 1940 |
/* If no patterns were provided by -e, and there is no file provided by -f, |
/* If no patterns were provided by -e, and there is no file provided by -f, |
| 1953 |
{ |
{ |
| 1954 |
if (!compile_pattern(patterns[j], pcre_options, NULL, |
if (!compile_pattern(patterns[j], pcre_options, NULL, |
| 1955 |
(j == 0 && cmd_pattern_count == 1)? 0 : j + 1)) |
(j == 0 && cmd_pattern_count == 1)? 0 : j + 1)) |
| 1956 |
goto EXIT2; |
goto EXIT2; |
| 1957 |
} |
} |
| 1958 |
|
|
| 1959 |
/* Compile the regular expressions that are provided in a file. */ |
/* Compile the regular expressions that are provided in a file. */ |
| 1977 |
{ |
{ |
| 1978 |
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, |
fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, |
| 1979 |
strerror(errno)); |
strerror(errno)); |
| 1980 |
goto EXIT2; |
goto EXIT2; |
| 1981 |
} |
} |
| 1982 |
filename = pattern_filename; |
filename = pattern_filename; |
| 1983 |
} |
} |
| 2008 |
fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); |
fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); |
| 2009 |
goto EXIT2; |
goto EXIT2; |
| 2010 |
} |
} |
| 2011 |
|
hint_count++; |
| 2012 |
} |
} |
| 2013 |
|
|
| 2014 |
/* If there are include or exclude patterns, compile them. */ |
/* If there are include or exclude patterns, compile them. */ |
| 2043 |
{ |
{ |
| 2044 |
rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL); |
rc = pcregrep(stdin, (filenames > FN_DEFAULT)? stdin_name : NULL); |
| 2045 |
goto EXIT; |
goto EXIT; |
| 2046 |
} |
} |
| 2047 |
|
|
| 2048 |
/* Otherwise, work through the remaining arguments as files or directories. |
/* Otherwise, work through the remaining arguments as files or directories. |
| 2049 |
Pass in the fact that there is only one argument at top level - this suppresses |
Pass in the fact that there is only one argument at top level - this suppresses |
| 2063 |
EXIT: |
EXIT: |
| 2064 |
if (pattern_list != NULL) |
if (pattern_list != NULL) |
| 2065 |
{ |
{ |
| 2066 |
for (i = 0; i < pattern_count; i++) free(pattern_list[i]); |
for (i = 0; i < pattern_count; i++) free(pattern_list[i]); |
| 2067 |
free(pattern_list); |
free(pattern_list); |
| 2068 |
} |
} |
| 2069 |
if (hints_list != NULL) |
if (hints_list != NULL) |
| 2070 |
{ |
{ |
| 2071 |
for (i = 0; i < pattern_count; i++) free(hints_list[i]); |
for (i = 0; i < hint_count; i++) free(hints_list[i]); |
| 2072 |
free(hints_list); |
free(hints_list); |
| 2073 |
} |
} |
| 2074 |
return rc; |
return rc; |
| 2075 |
|
|
| 2076 |
EXIT2: |
EXIT2: |