42 #define _MIRE_INTERNAL
52 #define FALSE ((BOOL)0)
53 #define TRUE ((BOOL)1)
55 #define MAX_PATTERN_COUNT 100
58 #define MBUFTHIRD BUFSIZ
60 #define MBUFTHIRD 8192
63 static inline void fwrite_check(
const void *ptr,
size_t size,
size_t nmemb, FILE *stream)
65 if(fwrite(ptr, size, nmemb, stream) != nmemb)
136 #define _GFB(n) ((1U << (n)) | 0x40000000)
137 #define GF_ISSET(_FLAG) ((grepFlags & ((GREP_FLAGS_##_FLAG) & ~0x40000000)) != GREP_FLAGS_NONE)
164 #if defined(WITH_PCRE)
184 "",
"\\b",
"^(?:",
"^(?:",
"\\Q",
"\\b\\Q",
"^(?:\\Q",
"^(?:\\Q"
189 "",
"\\b",
")$",
")$",
"\\E",
"\\E\\b",
"\\E)$",
"\\E)$"
195 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01
201 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
202 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
203 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
204 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
228 while (p < endptr && *p !=
'\n') p++;
238 while (p < endptr && *p !=
'\r') p++;
249 while (p < endptr && *p !=
'\r') p++;
264 unsigned int c = (unsigned)*((
unsigned char *)p);
271 for (gcii = 1; gcii <= extra; gcii++) {
273 c |= ((unsigned)p[gcii] & 0x3f) << gcss;
286 if (p < endptr && (
unsigned)*p == 0x0a) {
306 unsigned int c = (unsigned)*((
unsigned char *)p);
313 for (gcii = 1; gcii <= extra; gcii++) {
315 c |= ((unsigned)p[gcii] & 0x3f) << gcss;
330 if (p < endptr && (
unsigned)*p == 0x0a) {
379 while (p > startptr && p[-1] !=
'\n') p--;
385 while (p > startptr && p[-1] !=
'\n') p--;
392 while (p > startptr && p[-1] !=
'\n') p--;
393 if (p <= startptr + 1 || p[-2] ==
'\r')
return p;
400 if (*(--p) ==
'\n' && p > startptr && p[-1] ==
'\r') p--;
401 if (
GF_ISSET(UTF8))
while ((((
unsigned)*p) & 0xc0) == 0x80) p--;
403 while (p > startptr) {
404 const char *pp = p - 1;
409 while ((((
unsigned)*pp) & 0xc0) == 0x80) pp--;
410 c = (unsigned)*((
unsigned char *)pp);
416 for (gcii = 1; gcii <= extra; gcii++) {
418 c |= ((unsigned)pp[gcii] & 0x3f) << gcss;
422 c = (unsigned)*((
unsigned char *)pp);
473 const char *endptr,
const char *printname)
478 while (lastmatchrestart < endptr && count++ <
after_context) {
479 const char *pp = lastmatchrestart;
481 if (printname != NULL) fprintf(stdout,
"%s-", printname);
482 if (
GF_ISSET(LNUMBER)) fprintf(stdout,
"%d-", lastmatchnumber++);
484 fwrite_check(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
485 lastmatchrestart = pp;
515 int lastmatchnumber = 0;
519 const char *lastmatchrestart = NULL;
521 const char *ptr = buffer;
529 endptr = buffer + bufflength;
537 while (ptr < endptr) {
541 const char *matchptr = ptr;
543 size_t length, linelength;
544 size_t endlinelength;
556 linelength = t - ptr - endlinelength;
557 length =
GF_ISSET(MULTILINE) ? (size_t)(endptr - ptr) : linelength;
563 ONLY_MATCHING_RESTART:
578 mrc = (length > 0 ?
mireRegexec(mire, matchptr, length) : -1);
580 if (mrc >= 0) { match =
TRUE;
break; }
582 fprintf(stderr,
_(
"%s: pcre_exec() error %d while matching "),
__progname, mrc);
583 if (pattern_count > 1) fprintf(stderr,
_(
"pattern number %d to "), i+1);
584 fprintf(stderr,
_(
"this line:\n"));
586 fprintf(stderr,
"\n");
587 #if defined(PCRE_ERROR_MATCHLIMIT)
589 (mrc == PCRE_ERROR_MATCHLIMIT || mrc == PCRE_ERROR_RECURSIONLIMIT))
592 _(
"%s: error %d means that a resource limit was exceeded\n"),
595 _(
"%s: check your regex for nested unlimited loops\n"),
600 fprintf(stderr,
_(
"%s: too many errors - abandoned\n"),
612 if (match != invert) {
629 if (printname != NULL) fprintf(stdout,
"%s\n", printname);
652 if (printname != NULL) fprintf(stdout,
"%s:", printname);
653 if (
GF_ISSET(LNUMBER)) fprintf(stdout,
"%d:", linenumber);
655 fprintf(stdout,
"%d,%d", (
int)(matchptr + offsets[0] - ptr),
656 offsets[1] - offsets[0]);
658 fprintf(stdout,
"%d,%d", (
int)(filepos + matchptr + offsets[0] - ptr),
659 offsets[1] - offsets[0]);
661 fwrite_check(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
662 fprintf(stdout,
"\n");
663 matchptr += offsets[1];
664 length -= offsets[1];
666 goto ONLY_MATCHING_RESTART;
681 && lastmatchnumber > 0 && lastmatchrestart != NULL)
685 const char *p = lastmatchrestart;
698 while (lastmatchrestart < p) {
699 const char *pp = lastmatchrestart;
700 if (printname != NULL) fprintf(stdout,
"%s-", printname);
701 if (
GF_ISSET(LNUMBER)) fprintf(stdout,
"%d-", lastmatchnumber++);
703 fwrite_check(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
704 lastmatchrestart = pp;
706 if (lastmatchrestart != ptr) hyphenpending =
TRUE;
711 fprintf(stdout,
"--\n");
712 hyphenpending =
FALSE;
713 hyphenprinted =
TRUE;
724 while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
731 if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
732 fprintf(stdout,
"--\n");
737 if (printname != NULL) fprintf(stdout,
"%s-", printname);
738 if (
GF_ISSET(LNUMBER)) fprintf(stdout,
"%d-", linenumber - linecount--);
750 endhyphenpending =
TRUE;
752 if (printname != NULL) fprintf(stdout,
"%s:", printname);
753 if (
GF_ISSET(LNUMBER)) fprintf(stdout,
"%d:", linenumber);
765 const char *endmatch = ptr;
767 endmatch += offsets[1];
769 while (t < endmatch) {
771 if (t <= endmatch) linenumber++;
else break;
774 endmatch =
end_of_line(endmatch, endptr, &ellength);
775 linelength = endmatch - ptr - ellength;
786 fwrite_check(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
787 fprintf(stdout,
"%c[00m", 0x1b);
788 fwrite_check(ptr + offsets[1], 1, (linelength + endlinelength) - offsets[1],
791 else fwrite_check(ptr, 1, linelength + endlinelength, stdout);
802 lastmatchrestart = ptr + linelength + endlinelength;
803 lastmatchnumber = linenumber + 1;
813 const char *endmatch = ptr + offsets[1];
815 while (t < endmatch) {
817 if (t <= endmatch) linenumber++;
else break;
819 endmatch =
end_of_line(endmatch, endptr, &ellength);
820 linelength = endmatch - ptr - ellength;
827 ptr += linelength + endlinelength;
828 filepos += linelength + endlinelength;
837 if (bufflength >=
sizeof(buffer) && ptr > buffer + 2*
MBUFTHIRD) {
839 lastmatchnumber > 0 && lastmatchrestart != NULL &&
843 && lastmatchnumber > 0 && lastmatchrestart != NULL)
847 hyphenpending =
TRUE;
860 endptr = buffer + bufflength;
864 if (lastmatchnumber > 0 && lastmatchrestart != NULL)
875 && lastmatchnumber > 0 && lastmatchrestart != NULL)
877 do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname);
878 hyphenpending =
TRUE;
880 hyphenpending |= endhyphenpending;
888 if (printname != NULL) fprintf(stdout,
"%s\n", printname);
895 if (printname != NULL) fprintf(stdout,
"%s:", printname);
896 fprintf(stdout,
"%d\n", count);
912 size_t flen = strlen(fn);
913 size_t slen = strlen(suffix);
914 return (flen > slen && !strcmp(fn + flen - slen, suffix));
935 struct stat sb, *st = &sb;
939 const char * fmode =
"r.ufdio";
943 if (!strcmp(pathname,
"-")) {
944 fd =
fdDup(STDIN_FILENO);
948 if ((xx =
Stat(pathname, st)) != 0)
957 if (S_ISDIR(st->st_mode))
967 DIR *dir = Opendir(pathname);
972 fprintf(stderr,
_(
"%s: Failed to open directory %s: %s\n"),
978 while ((dp = Readdir(dir)) != NULL) {
981 if (!strcmp(dp->d_name,
".") || !strcmp(dp->d_name,
".."))
984 xx =
snprintf(buffer,
sizeof(buffer),
"%.512s%c%.128s",
985 pathname, sep, dp->d_name);
986 buffer[
sizeof(buffer)-1] =
'\0';
998 else if (xx == 0 && rc == 1) rc = 0;
1022 pathlen = strlen(pathname);
1037 fd =
Fopen(pathname, fmode);
1039 if (fd == NULL ||
Ferror(fd)) {
1041 fprintf(stderr,
_(
"%s: Failed to open %s: %s\n"),
1073 const char *filename,
int count)
1082 fprintf(stderr,
_(
"%s: Too many patterns (max %d)\n"),
__progname,
1102 if (mire->erroff < 0)
1104 if (mire->erroff > (
int)strlen(pattern))
1105 mire->erroff = (
int)strlen(pattern);
1108 if (filename == NULL)
1109 fprintf(stderr,
_(
" command-line %d"), count);
1111 fprintf(stderr,
_(
" file:line %s:%d"), filename, count);
1112 fprintf(stderr,
_(
" regex at offset %d: %s\n"), mire->erroff, mire->errmsg);
1132 if (
GF_ISSET(FIXED_STRINGS) != 0) {
1133 const char *eop = pattern + strlen(pattern);
1137 const char *p =
end_of_line(pattern, eop, &ellength);
1140 sprintf(buffer,
"%.*s", (
int)(p - pattern - ellength), pattern);
1162 while ((fn = *files++) != NULL) {
1168 if (strcmp(fn,
"-") == 0) {
1174 fd =
Fopen(fn,
"r.fpio");
1176 fprintf(stderr,
_(
"%s: Failed to open %s: %s\n"),
1178 if (fd != NULL) (void)
Fclose(fd);
1186 while (fgets(buffer,
MBUFTHIRD, fp) != NULL) {
1187 char *se = buffer + (int)strlen(buffer);
1188 while (se > buffer &&
xisspace((
int)se[-1]))
1193 if (buffer[0] ==
'\0')
continue;
1216 enum poptCallbackReason reason,
1217 const struct poptOption * opt,
const char * arg,
1223 if (opt->arg == NULL)
1231 fprintf(stderr,
_(
"%s: Invalid value \"%s\" for -d\n"),
1241 fprintf(stderr,
_(
"%s: Invalid value \"%s\" for -D\n"),
1248 if (!strcmp(arg,
"never"))
1250 else if (!strcmp(arg,
"always"))
1252 else if (!strcmp(arg,
"auto")) {
1253 if (isatty(fileno(stdout)))
1258 fprintf(stderr,
_(
"%s: Unknown color setting \"%s\"\n"),
1265 char *cs =
getenv(
"PCREGREP_COLOUR");
1266 if (cs == NULL) cs =
getenv(
"PCREGREP_COLOR");
1272 #if defined(WITH_PCRE)
1274 fprintf(stderr,
_(
"%s %s (PCRE version %s)\n"),
__progname,
VERSION, pcre_version());
1282 fprintf(stderr,
_(
"%s: Unknown option -%c\n"),
__progname, opt->val);
1283 poptPrintUsage(con, stderr, 0);
1295 { NULL,
'\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
1300 N_(
"set number of following context lines"),
N_(
"=number") },
1302 N_(
"set number of prior context lines"),
N_(
"=number") },
1304 N_(
"set number of context lines, before & after"),
N_(
"=number") },
1306 N_(
"print only a count of matching lines per FILE"), NULL },
1307 {
"color",
'\0', POPT_ARG_STRING, NULL, (int)
'C',
1308 N_(
"matched text color option (auto|always|never)"),
N_(
"=option") },
1309 {
"colour",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, NULL, (int)
'C',
1310 N_(
"matched text colour option (auto|always|never)"),
N_(
"=option") },
1312 {
"devices",
'D', POPT_ARG_STRING, NULL, (int)
'D',
1313 N_(
"device, FIFO, or socket action (read|skip)"),
N_(
"=action") },
1314 {
"directories",
'd', POPT_ARG_STRING, NULL, (int)
'd',
1315 N_(
"directory action (read|skip|recurse)"),
N_(
"=action") },
1316 {
"regex",
'e', POPT_ARG_ARGV, &
patterns, 0,
1317 N_(
"specify pattern (may be used more than once)"),
N_(
"(p)") },
1319 N_(
"patterns are sets of newline-separated strings"), NULL },
1321 N_(
"read patterns from file (may be used more than once)"),
1324 N_(
"output file offsets, not text"), NULL },
1326 N_(
"force the prefixing filename on output"), NULL },
1328 N_(
"suppress the prefixing filename on output"), NULL },
1330 N_(
"ignore case distinctions"), NULL },
1332 N_(
"print only FILE names containing matches"), NULL },
1334 N_(
"print only FILE names not containing matches"), NULL },
1335 {
"label",
'\0', POPT_ARG_STRING, &
stdin_name, 0,
1336 N_(
"set name for standard input"),
N_(
"=name") },
1338 N_(
"output line numbers and offsets, not text"), NULL },
1340 {
"locale",
'\0', POPT_ARG_STRING, &
locale, 0,
1341 N_(
"use the named locale"),
N_(
"=locale") },
1343 N_(
"run in multiline mode"), NULL },
1344 {
"newline",
'N', POPT_ARG_STRING, &
newline, 0,
1345 N_(
"set newline type (CR|LF|CRLF|ANYCRLF|ANY)"),
N_(
"=type") },
1347 N_(
"print line number with output lines"), NULL },
1349 N_(
"show only the part of the line that matched"), NULL },
1352 N_(
"suppress output, just set return code"), NULL },
1354 N_(
"recursively scan sub-directories"), NULL },
1356 N_(
"exclude matching files when recursing (may be used more than once)"),
1359 N_(
"include matching files when recursing (may be used more than once)"),
1362 N_(
"suppress error messages"), NULL },
1364 N_(
"suppress error messages"), NULL },
1366 N_(
"use UTF-8 mode"), NULL },
1368 {
"version",
'V', POPT_ARG_NONE, NULL, (int)
'V',
1369 N_(
"print version information and exit"), NULL },
1372 N_(
"select non-matching lines"), NULL },
1374 N_(
"force patterns to match only as words") ,
N_(
"(p)") },
1376 N_(
"force patterns to match only whole lines"),
N_(
"(p)") },
1381 N_(
"Common options for all rpmio executables:"),
1386 { NULL, (char)-1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
1388 Usage: rpmgrep [OPTION...] [PATTERN] [FILE1 FILE2 ...]\n\n\
1389 Search for PATTERN in each FILE or standard input.\n\
1390 PATTERN must be present if neither -e nor -f is used.\n\
1391 \"-\" can be used as a file name to mean STDIN.\n\
1392 All files are read as plain files, without any interpretation.\n\n\
1393 Example: rpmgrep -i 'hello.*world' menu.h main.c\
1396 { NULL, (char)-1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
1398 When reading patterns from a file instead of using a command line option,\n\
1399 trailing white space is removed and blank lines are ignored.\n\
1401 With no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n\
1447 av = poptGetArgs(optCon);
1464 _(
"%s: Cannot mix --only-matching, --file-offsets and/or --line-offsets\n"),
1466 poptPrintUsage(optCon, stderr, 0);
1484 fprintf(stderr,
_(
"%s: Invalid newline specifier \"%s\"\n"),
1504 if (av == NULL|| i >= ac) {
1505 poptPrintUsage(optCon, stderr, 0);
1508 xx = poptSaveString(&
patterns, POPT_ARG_ARGV, av[i]);
1518 for (j = 0; j < npatterns; j++) {
1520 (j == 0 && npatterns == 1)? 0 : j + 1))
1543 fprintf(stderr,
_(
"%s: Error in 'exclude' regex at offset %d: %s\n"),
1555 fprintf(stderr,
_(
"%s: Error in 'include' regex at offset %d: %s\n"),
1572 {
BOOL only_one_at_top = (i == ac -1);
1575 for (; i < ac; i++) {
1578 if (frc > 1) rc = frc;
1579 else if (frc == 0 && rc == 1) rc = 0;