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
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
222 end_of_line(
const char *
p,
const char *endptr,
size_t *lenptr)
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) {
372 previous_line(
const char *p,
const char *startptr)
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);
472 static void do_after_lines(
int lastmatchnumber,
const char *lastmatchrestart,
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);
483 pp = end_of_line(pp, endptr, &ellength);
484 fwrite_check(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
485 lastmatchrestart = pp;
509 pcregrep(
FD_t fd,
const char *printname)
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;
555 t = end_of_line(t, endptr, &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; }
583 if (pattern_count > 1)
fprintf(stderr,
_(
"pattern number %d to "), i+1);
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);
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);
663 matchptr += offsets[1];
664 length -= offsets[1];
666 goto ONLY_MATCHING_RESTART;
681 && lastmatchnumber > 0 && lastmatchrestart !=
NULL)
685 const char *p = lastmatchrestart;
688 p = end_of_line(p, ptr, &ellength);
698 while (lastmatchrestart < p) {
699 const char *pp = lastmatchrestart;
700 if (printname !=
NULL)
fprintf(stdout,
"%s-", printname);
702 pp = end_of_line(pp, endptr, &ellength);
703 fwrite_check(lastmatchrestart, 1, pp - lastmatchrestart, stdout);
704 lastmatchrestart = pp;
706 if (lastmatchrestart != ptr) hyphenpending =
TRUE;
712 hyphenpending =
FALSE;
713 hyphenprinted =
TRUE;
724 while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) &&
728 p = previous_line(p, buffer);
731 if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
737 if (printname !=
NULL)
fprintf(stdout,
"%s-", printname);
738 if (
GF_ISSET(LNUMBER))
fprintf(stdout,
"%d-", linenumber - linecount--);
739 pp = end_of_line(pp, endptr, &ellength);
750 endhyphenpending =
TRUE;
752 if (printname !=
NULL)
fprintf(stdout,
"%s:", printname);
765 const char *endmatch =
ptr;
767 endmatch += offsets[1];
769 while (t < endmatch) {
770 t = end_of_line(t, endptr, &ellength);
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) {
816 t = end_of_line(t, endptr, &ellength);
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)
845 do_after_lines(lastmatchnumber, lastmatchrestart,
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));
931 grep_or_recurse(
const char *pathname,
BOOL dir_recurse,
BOOL only_one_at_top)
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';
996 xx = grep_or_recurse(buffer, dir_recurse,
FALSE);
998 else if (xx == 0 && rc == 1) rc = 0;
1022 pathlen = strlen(pathname);
1037 fd =
Fopen(pathname, fmode);
1041 fprintf(stderr,
_(
"%s: Failed to open %s: %s\n"),
1072 compile_single_pattern(
const char *
pattern,
1073 const char *filename,
int count)
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);
1128 compile_pattern(
const char *pattern,
const char *filename,
int count)
1132 if (
GF_ISSET(FIXED_STRINGS) != 0) {
1133 const char *eop = pattern + strlen(pattern);
1137 const char *p = end_of_line(pattern, eop, &ellength);
1139 return compile_single_pattern(pattern, filename, count);
1140 sprintf(buffer,
"%.*s", (
int)(p - pattern - ellength), pattern);
1142 if (!compile_single_pattern(buffer, filename, count))
1146 else return compile_single_pattern(pattern, filename, count);
1154 static int mireLoadPatternFiles(
ARGV_t files)
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"),
1187 char *
se = buffer + (
int)strlen(buffer);
1188 while (se > buffer &&
xisspace((
int)se[-1]))
1193 if (buffer[0] ==
'\0')
continue;
1194 if (!compile_pattern(buffer, fn, linenumber))
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)
1283 poptPrintUsage(con, stderr, 0);
1295 {
NULL,
'\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
1296 grepArgCallback, 0,
NULL, NULL },
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]);
1519 if (!compile_pattern(
patterns[j], NULL,
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"),
1563 rc = grep_or_recurse(
"-", 0, 1);
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;
static const char * suffix[]
static const char * stdin_name
poptContext rpmioInit(int argc, char *const argv[], struct poptOption *optionsTable)
static int before_context
int mireSetEOptions(miRE mire, int *offsets, int noffsets)
Initialize pattern execute options (PCRE only).
int mireApply(miRE mire, int nmire, const char *s, size_t slen, int rc)
Apply array of patterns to a string.
static enum grepFlags_e grepFlags
int mireLoadPatterns(rpmMireMode mode, int tag, const char **patterns, const unsigned char *table, miRE *mirep, int *nmirep)
Load patterns from string array.
char * getenv(const char *name)
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
void * mireFreeAll(miRE mire, int nmire)
Destroy compiled patterns.
char * xstrdup(const char *str)
const unsigned char * _mirePCREtables
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
DEE_e
Actions for the -D option.
static struct poptOption optionsTable[]
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
int main(int argc, const char **argv, char **envp)
int mireSetCOptions(miRE mire, rpmMireMode mode, int tag, int options, const unsigned char *table)
Initialize pattern compile options.
int Stat(const char *path, struct stat *st)
stat(2) clone.
dee_e
Actions for the -d option.
static const unsigned utf8_table3[]
UTF-8 tables - used only when the newline setting is "any".
FN_e
Values for the "filenames" variable, which specifies options for file name output.
static enum DEE_e DEE_action
sprintf(t," (%u)",(unsigned) dig->nbytes)
const char * Fstrerror(FD_t fd)
strerror(3) clone.
void * xcalloc(size_t nmemb, size_t size)
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
static const char * locale
void rpmswPrint(const char *name, rpmop op, FILE *fp)
Print operation statistics.
int argvCount(const ARGV_t argv)
Return no.
static int xisspace(int c)
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
static const char utf8_table4[]
static enum FN_e filenames
static void fwrite_check(const void *ptr, size_t size, size_t nmemb, FILE *stream)
static ARGV_t exclude_patterns
The FD_t File Handle data structure.
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
enum rpmMireMode_e rpmMireMode
Tag value pattern match mode.
static rpmMireMode grepMode
static ARGV_t include_patterns
int Fclose(FD_t fd)
fclose(3) clone.
Cumulative statistics for an operation.
int mireStudy(miRE mire, int nmires)
Study PCRE patterns (if any).
static const char * color_string
static const char *char c
Return text between pl and matching pr characters.
int Ferror(FD_t fd)
ferror(3) clone.
return strcmp(ame->name, bme->name)
int mireSetLocale(miRE mire, const char *locale)
Compile locale-specific PCRE tables.
static struct rpmop_s grep_totalops
static int snprintf(char *buf, int nb, const char *fmt,...)
static const char * prefix[]
Tables for prefixing and suffixing patterns, according to the -w, -x, and -F options.
#define MAX_PATTERN_COUNT
static enum dee_e dee_action
static int chkSuffix(const char *fn, const char *suffix)
Check string for a suffix.
static ARGV_t pattern_filenames
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
int
Save source and expand field into target.
static rpmop fdstat_op(FD_t fd, fdOpX opx)
static struct rpmop_s grep_readops
int mireSetGOptions(const char *newline, int caseless, int multiline, int utf8)
Initialize pattern global options (PCRE only).
struct poptOption rpmioAllPoptTable[]
static const char * newline
poptContext rpmioFini(poptContext optCon)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.