FOSSology  4.7.1
Open Source License Compliance by Open Source Software
nomos_regex.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2006-2011 Hewlett-Packard Development Company, L.P.
3  SPDX-FileCopyrightText: © 2014 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 //#define DEBUG_TNG
8 #ifndef DEBUG_TNG
9 #define CALL_IF_DEBUG_MODE(x)
10 #else
11 #define CALL_IF_DEBUG_MODE(x) x
12 #endif
13 
14 #include "nomos_regex.h"
15 #include "nomos_gap.h"
16 #include "nomos_utils.h"
25 static char regexErrbuf[myBUFSIZ];
26 
27 regex_t idx_regc[NFOOTPRINTS];
28 regex_t regc[NFOOTPRINTS];
29 
38 void regexError(int ret, regex_t *regc, char *regex)
39 {
40 #ifdef PROC_TRACE
41  traceFunc("== regexError(%d, %p, %s)\n", ret, regc, regex);
42 #endif /* PROC_TRACE */
43 
44  (void) regerror(ret, regc, regexErrbuf, sizeof(regexErrbuf));
45  Msg("regex = \"%s\"\n", regex);
46  LOG_FATAL("regcomp failure: %s", regexErrbuf)
47  Bail(-__LINE__);
48 }
49 
56 int endsIn(char *s, char *suffix)
57 {
58  int slen = (int) strlen(s);
59  int sufflen = (int) strlen(suffix);
60  /*
61  * compare trailing chars in a string with a constant (should be faster
62  * than calling regcomp() and regexec()!)
63  */
64 #ifdef PROC_TRACE
65  traceFunc("== endsIn(%s, %s)\n", s, suffix);
66 #endif /* PROC_TRACE */
67 
68  if (strncasecmp(s + slen - sufflen, suffix, (size_t) sufflen) == 0)
69  {
70  return (1);
71  }
72  return (0);
73 }
74 
81 int lineInFile(char *pathname, char *regex)
82 {
83  char buf[myBUFSIZ];
84 
85 #ifdef PROC_TRACE
86  traceFunc("== lineInFile(%s, \"%s\")\n", pathname, regex);
87 #endif /* PROC_TRACE */
88 
89  (void) sprintf(buf, "^%s$", regex);
90  return (textInFile(pathname, buf, REG_NEWLINE));
91 }
92 
100 int textInFile(char *pathname, char *regex, int flags)
101 {
102  char *textp;
103  int ret;
104 
105 #ifdef PROC_TRACE
106  traceFunc("== textInFile(%s, \"%s\", 0x%x)\n", pathname, regex, flags);
107 #endif /* PROC_TRACE */
108 
109  if ((pathname == NULL_STR ) || (regex == NULL_STR ))
110  {
111 #ifdef QA_CHECKS
112  if (pathname == NULL_STR)
113  {
114  Assert(NO, "textInFile: NULL pathname");
115  }
116  if (regex == NULL_STR)
117  {
118  Assert(NO, "textInFile: NULL regex");
119  }
120 #endif /* QA_CHECKS */
121  return (0);
122  }
123  if ((textp = mmapFile(pathname)) == NULL_STR)
124  {
125  return (0);
126  }
127  ret = strGrep(regex, textp, flags);
128  munmapFile(textp);
129  return (ret);
130 }
131 
139 int strGrep(char *regex, char *data, int flags)
140 {
141  regex_t regc;
142  int ret;
143 
144 #ifdef PHRASE_DEBUG
145  int i;
146 #endif /* PHRASE_DEBUG */
147 
148 #if defined(PROC_TRACE) || defined(PHRASE_DEBUG)
149  traceFunc("== strGrep(\"%s\", %p, 0x%x)\n", regex, data, flags);
150 #endif /* PROC_TRACE || PHRASE_DEBUG */
151 
152  if (data == NULL_STR || regex == NULL_STR)
153  {
154  return (0);
155  }
156  /* DO NOT, repeat DO NOT add REG_EXTENDED as a default flag! */
157  if ((ret = regcomp(&regc, regex, flags)) != 0)
158  {
159  regexError(ret, &regc, regex);
160  regfree(&regc);
161  return (-1); /* <0 indicates compile failure */
162  }
163  /*
164  * regexec() returns 1 on failure and 0 on success - make sure we call
165  * regfree after the regexec call, else after a million or so regex
166  * searches we'll have lost a LOT of memory. :)
167  */
168  ret = regexec(&regc, data, 1, &cur.regm, 0);
169  regfree(&regc);
170  if (ret)
171  {
172  return (0); /* >0 indicates search failure */
173  }
174 #ifdef QA_CHECKS
175  if (cur.regm.rm_so == cur.regm.rm_eo)
176  {
177  Assert(NO, "start/end offsets are identical in strGrep()");
178  }
179 #endif /* QA_CHECKS */
180 #ifdef PHRASE_DEBUG
181  printf("strGrep MATCH(%s) @ %d! = {", regex, cur.regm.rm_so);
182  for (i = cur.regm.rm_so; i < cur.regm.rm_eo; i++)
183  {
184  printf("%c", data[i]);
185  }
186  printf("}\n");
187 #endif /* PHRASE_DEBUG */
188  if (gl.flags & FL_SAVEBASE)
189  {
190  cur.matchBase = data;
191  }
192  return (1);
193 }
194 
205 int idxGrep(int index, char *data, int flags)
206 {
207  return idxGrep_base(index, data, flags, 0);
208 }
209 
220 int idxGrep_recordPosition(int index, char *data, int flags)
221 {
222  if( optionIsSet(OPTS_NO_HIGHLIGHTINFO) ) {
223  return idxGrep_base(index, data, flags, 0);
224  }
225  else {
226  return idxGrep_base(index, data, flags, 1);
227  }
228 }
229 
241 int idxGrep_recordPositionDoctored(int index, char *data, int flags)
242 {
243 
244  if( optionIsSet(OPTS_NO_HIGHLIGHTINFO) ) {
245  return idxGrep_base(index, data, flags, 0);
246  }
247  else {
248  return idxGrep_base(index, data, flags, 2);
249  }
250 }
251 
263 int idxGrep_recordIndex(int index, char *data, int flags)
264 {
265  if( optionIsSet(OPTS_NO_HIGHLIGHTINFO) ) {
266  return idxGrep_base(index, data, flags, 0);
267  }
268  else {
269  return idxGrep_base(index, data, flags, 3);
270  }
271 }
272 
282 int matchOnce(int isPlain, char *data, char* regex, regex_t *rp,
283  regmatch_t* regmatch)
284 {
285  if(isPlain) {
286  return !strNbuf_noGlobals(data, regex, regmatch , 0 , cur.matchBase );
287  }
288 
289  return regexec(rp, data, 1, regmatch, 0);
290 }
291 
301 int storeOneMatch(regmatch_t currentRegMatch, int lastmatch, GArray* allmatches,
302  char** tmpData, char* data)
303 {
304  regmatch_t storeRegMatch;
305  storeRegMatch.rm_so = currentRegMatch.rm_so + lastmatch;
306  storeRegMatch.rm_eo = currentRegMatch.rm_eo + lastmatch;
307  g_array_append_val(allmatches, storeRegMatch);
308  lastmatch += currentRegMatch.rm_eo;
309  *tmpData = data + lastmatch;
310  return lastmatch;
311 }
312 
324 int idxGrep_base(int index, char *data, int flags, int mode)
325 {
326  int i;
327  int ret;
328 
329  int show = flags & FL_SHOWMATCH;
330  licText_t *ltp;
331  regex_t localRegc;
332  regex_t *rp;
333  int use_precompiled;
334 
335  /* licText[] and idx_regc[] hold NFOOTPRINTS entries; check before dereferencing */
336  if (index >= NFOOTPRINTS)
337  {
338  LOG_FATAL("idxGrep: index %d out of range", index)
339  Bail(-__LINE__);
340  }
341  ltp = licText + index;
342 
343  /* skip regcomp/regfree for pre-compiled patterns; REG_NEWLINE changes ^/$ semantics so always recompile those */
344  use_precompiled = ltp->compiled && !(flags & REG_NEWLINE);
345 
346  /* transient compiles use local storage; freeing idx_regc[index] would dangle it */
347  rp = use_precompiled ? idx_regc + index : &localRegc;
348 
349  CALL_IF_DEBUG_MODE(printf(" %i %i \"", index, ltp->plain);)
350 
351 #if defined(PROC_TRACE) || defined(PHRASE_DEBUG)
352  traceFunc("== idxGrep(%d, %p, 0x%x)\n... regex \"%s\"\n", index, data,
353  flags, _REGEX(index));
354 #endif /* PROC_TRACE || PHRASE_DEBUG */
355 
356  if (data == NULL_STR)
357  {
358 #ifdef PHRASE_DEBUG
359  printf("idxGrep: NULL pointer to file data!\n");
360 #endif /* PHRASE_DEBUG */
361  return (0);
362  }
363 
364  if (ltp->plain)
365  {
366  ret = strNbuf(data, ltp->regex);
367  if (ret == 0) return (ret);
368  }
369  else {
370  if (!use_precompiled)
371  {
372  if ((ret = regcomp(rp, ltp->regex, flags)))
373  {
374  fprintf(stderr, "Compile failed, regex #%d\n", index);
375  regexError(ret, rp, ltp->regex);
376  regfree(rp);
377  printf("Compile error \n");
378  return (-1); /* <0 indicates compile failure */
379  }
380  }
381 
382  if (regexec(rp, data, 1, &cur.regm, 0))
383  {
384  if (!use_precompiled) regfree(rp);
385  return (0);
386  }
387  else ret = 1;
388 
389  #ifdef QA_CHECKS
390  if (cur.regm.rm_so == cur.regm.rm_eo)
391  {
392  if (!use_precompiled) regfree(rp);
393  Assert(NO, "start/end offsets are identical in idxGrep(%d)",
394  index);
395  }
396  #endif /* QA_CHECKS */
397  /* Set up a global match-length variable? */
398  if (show)
399  {
400  #ifdef DEBUG
401  printf("REGEX(%d) \"%s\"\n", index, ltp->regex);
402  #endif /* DEBUG */
403  printf("MATCH @ %d! = {", cur.regm.rm_so);
404  for (i = cur.regm.rm_so; i < cur.regm.rm_eo; i++)
405  {
406  printf("%c", data[i]);
407  }
408  printf("}\n");
409  }
410  if (gl.flags & FL_SAVEBASE)
411  {
412  cur.matchBase = data;
413  }
414  }
415 
417 
418  if (mode == 3) {
419  recordIndex(cur.indexList, index);
420  }
421  else if (mode == 1 || mode == 2)
422  {
423  CALL_IF_DEBUG_MODE(printf("MATCH!\n");)
425 
426  CALL_IF_DEBUG_MODE(printf("%s", data);)
427 
428  GArray* allmatches = g_array_new(FALSE, FALSE, sizeof(regmatch_t));
429  regmatch_t currentRegMatch;
430  int lastmatch = 0;
431 
432  char* tmpData = data;
433 
434  lastmatch = storeOneMatch(cur.regm, lastmatch, allmatches, &tmpData, data);
435 
436  while (!matchOnce(ltp->plain, tmpData, ltp->regex, rp, &currentRegMatch))
437  {
438  lastmatch = storeOneMatch(currentRegMatch, lastmatch, allmatches, &tmpData, data);
439  }
440 
441  if (index >= _KW_first && index <= _KW_last) {
442  rememberWhatWeFound(cur.keywordPositions, allmatches, index, mode);
443  }
444  else if (cur.currentLicenceIndex > -1) {
445  rememberWhatWeFound(getLicenceAndMatchPositions(cur.theMatches, cur.currentLicenceIndex)->matchPositions, allmatches, index, mode);
446  }
447  g_array_free(allmatches, 1);
448  CALL_IF_DEBUG_MODE(printf("Bye!\n");)
449  }
450 
451  if (!ltp->plain && !use_precompiled) regfree(rp);
452  return (1);
453 }
454 
460 void recordIndex(GArray* indexList, int index){
461  g_array_append_val(indexList, index);
462 }
463 
470 static int getOffset(int posInDoctoredBuffer)
471 {
472  return uncollapsePosition(posInDoctoredBuffer, cur.docBufferPositionsAndOffsets);
473 }
474 
481 regmatch_t* getRegmatch_t(GArray* in, int index)
482 {
483  return & g_array_index(in, regmatch_t, index);
484 }
485 
493 void rememberWhatWeFound(GArray* highlight, GArray* regmatch_tArray, int index,
494  int mode)
495 {
496 
497  if (mode != 1 && mode != 2)
498  {
499  FOSSY_EXIT("This mode is not supported\n", 8);
500  return;
501  }
502 
503  int i = 0;
504  int nmatches = regmatch_tArray->len;
505  int alreadyFound = highlight->len;
506  g_array_set_size(highlight, alreadyFound + nmatches);
507 
508  for (i = 0; i < nmatches; ++i)
509  {
510  regmatch_t* theRegmatch = getRegmatch_t(regmatch_tArray, i);
511  if (theRegmatch->rm_eo == -1 || theRegmatch->rm_so == -1)
512  {
513  FOSSY_EXIT("Found match at negative position... this should not happen\n", 9);
514  return;
515  }
516 
517  MatchPositionAndType* ourMatchv = getMatchfromHighlightInfo(highlight, i + alreadyFound);
518  ourMatchv->start = (mode == 1) ? theRegmatch->rm_so : getOffset(theRegmatch->rm_so);
519  ourMatchv->end = (mode == 1) ? theRegmatch->rm_eo : getOffset(theRegmatch->rm_eo);
520  ourMatchv->index = index;
521 
522  CALL_IF_DEBUG_MODE(printf("here: %i - %i \n", ourMatchv->start, ourMatchv->end);)
523  }
524  CALL_IF_DEBUG_MODE(printf(" We go and now we know %d ", highlight->len);)
525 }
526 
527 #define _XC(q) ((char) xascii[q])
528 
536 int strNbuf(char *data, char *str){
537 
538  return strNbuf_noGlobals(data, str, &(cur.regm), gl.flags & FL_SAVEBASE , cur.matchBase );
539 }
540 
546 int strNbuf_noGlobals(char *data, char *str, regmatch_t* matchPos, int doSave,
547 char* saveData)
548 {
549  static int firstFlag = 1;
550  static char xascii[128];
551  int i;
552  int alph = 0;
553  int save = 0;
554  char *bufp;
555  char *pattp;
556  char *mark;
557  char x;
558  char firstx = 0;
559 
560 #if defined(PROC_TRACE) || defined(PHRASE_DEBUG)
561  traceFunc("== strNbuf(%p, %p)\n", data, str);
562 #endif /* PROC_TRACE || PHRASE_DEBUG */
563 
564  if (firstFlag)
565  {
566  firstFlag = 0;
567  /*
568  * 32 characters separate 'A' (65) and 'a' (97), contiguous up to 'Z'.
569  * Therefore, 'Z' == 90, 'a' == 97, and 'z' == 122
570  */
571  for (i = 0; i < sizeof(xascii); i++)
572  {
573  if ((i >= 65) && (i <= 90))
574  { /* isupper */
575  xascii[i] = i + 32; /* -> tolower */
576  }
577  else if ((i >= 97) && (i <= 122))
578  { /* islower */
579  xascii[i] = i - 32; /* -> toupper */
580  }
581  else
582  {
583  /* *foo = tolower((char)i); */
584  xascii[i] = (char) /*i*/0;
585  }
586  }
587 #ifdef STRSTR_DEBUG
588  /*
589  * Dump the table (debugging purposes only)
590  */
591  for (i = 0; i < sizeof (xascii); i++)
592  {
593  if (xascii[i])
594  {
595  printf(" %c%c ", (unsigned) i, xascii[i]);
596  }
597  else
598  {
599  printf("\\%03d ", (int) xascii[i]);
600  }
601  if (i & 16 == 15)
602  {
603  printf("\n");
604  }
605  }
606 #endif /* STRSTR_DEBUG */
607  }
608 #ifdef STRSTR_DEBUG
609  printf("DATA \"%s\"\nPATT \"%s\"\n", data, str);
610 #endif /* STRSTR_DEBUG */
611  if (data == NULL_STR || str == NULL_STR)
612  {
613  return (0);
614  }
615  alph = isalpha(*str);
616  if (alph)
617  {
618  firstx = xascii[(int) *str];
619 #ifdef STRSTR_DEBUG
620  printf("NOTE: first char (%c) is Alphabetic - alternate is (%c)\n",
621  *str, firstx);
622 #endif /* STRSTR_DEBUG */
623 #ifdef QA_CHECKS
624  if (firstx == NULL_CHAR)
625  {
626  LOG_FATAL("Unexpected initialization")
627  Bail(-__LINE__);
628  }
629 #endif /* QA_CHECKS */
630  }
631  for (bufp = data; /* *pattp && */*bufp; bufp = mark)
632  {
633 #ifdef STRSTR_DEBUG
634  printf("\nDEBUG: start, buffer = \"%s\"\n", bufp);
635 #endif /* STRSTR_DEBUG */
636  pattp = str;
637  /*
638  * Locate the first character of our target-pattern in the buffer...
639  */
640  while (*bufp)
641  {
642 #ifdef STRSTR_DEBUG
643  printf("... findfirst, *bufp is '%c' == [%c%c]?\n",
644  *bufp, *str, alph ? firstx : *str);
645 #endif /* STRSTR_DEBUG */
646  if (*bufp == *pattp)
647  {
648  break;
649  }
650  if (alph && (*bufp == firstx))
651  {
652  break;
653  }
654  bufp++;
655  }
656  if (*bufp == NULL_CHAR)
657  {
658  return (0);
659  }
660  save = bufp - data;
661  mark = ++bufp; /* could optimize this in loop below */
662 #ifdef STRSTR_DEBUG
663  printf("GOT IT, at offset %d (*mark now is '%c')\n",
664  bufp - data - 1, *mark);
665 #endif /* STRSTR_DEBUG */
666  /* optimizeMark = 1; */
667  for (++pattp; *bufp && *pattp; bufp++, pattp++)
668  {
669 #ifdef STRSTR_DEBUG
670  printf("STRING-COMPARE: %c == %c ??\n", *bufp, *pattp);
671 #endif /* STRSTR_DEBUG */
672  if (*bufp == *pattp)
673  {
674  continue;
675  }
676 #ifdef STRSTR_DEBUG
677  printf("... or perhaps: %c == %c ??\n", *bufp,
678  xascii[*pattp]);
679 #endif /* STRSTR_DEBUG */
680  if (((x = xascii[(int) *pattp])) && (*bufp == x))
681  {
682  continue;
683  }
684  break;
685  }
686  if (*pattp == NULL_CHAR)
687  {
688  matchPos->rm_so = save;
689  matchPos->rm_eo = save + strlen(str);
690  if (doSave)
691  {
692  saveData = data;
693  }
694  return (1); /* end of pattern == success */
695  }
696  if (*bufp == NULL_CHAR)
697  {
698  return (0); /* end of buffer == success */
699  }
700  }
701  return (0);
702 }
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
void munmapFile(void *ptr)
Definition: util.c:1204
void Assert(int fatalFlag, const char *fmt,...)
Raise an assert.
Definition: util.c:1408
void Msg(const char *fmt,...)
DO NOT automatically add to a string passed to Msg(); in parseDistro, we sometimes want to dump a p...
Definition: util.c:1395
char * mmapFile(char *pathname)
Blarg. Files that are EXACTLY a multiple of the system pagesize do not get a NULL on the end of the b...
Definition: util.c:1088
licText_t licText[]
#define NULL_STR
NULL string.
Definition: nomos.h:235
#define _REGEX(x)
Definition: nomos.h:447
#define NO
Definition: nomos.h:171
void Bail(int exitval)
Close connections and exit.
Definition: nomos_utils.c:538
#define FL_SAVEBASE
Definition: nomos.h:155
#define NULL_CHAR
NULL character.
Definition: nomos.h:234
int optionIsSet(int val)
Check if an CLI option is set.
Definition: nomos_utils.c:567
int storeOneMatch(regmatch_t currentRegMatch, int lastmatch, GArray *allmatches, char **tmpData, char *data)
Store a single regex match to array.
Definition: nomos_regex.c:301
int idxGrep_base(int index, char *data, int flags, int mode)
compile a regex, and perform the search (on data?)
Definition: nomos_regex.c:324
regmatch_t * getRegmatch_t(GArray *in, int index)
From a given array, get regex match from a given index.
Definition: nomos_regex.c:481
int idxGrep_recordPosition(int index, char *data, int flags)
compile a regex, perform the search and record findings
Definition: nomos_regex.c:220
int idxGrep(int index, char *data, int flags)
compile a regex, and perform the search (on data?)
Definition: nomos_regex.c:205
int lineInFile(char *pathname, char *regex)
Check if a line exists in a file.
Definition: nomos_regex.c:81
static char regexErrbuf[myBUFSIZ]
Definition: nomos_regex.c:25
void recordIndex(GArray *indexList, int index)
Add a given index to index list.
Definition: nomos_regex.c:460
int strGrep(char *regex, char *data, int flags)
General-purpose grep function, used for one-time-only searches.
Definition: nomos_regex.c:139
int idxGrep_recordPositionDoctored(int index, char *data, int flags)
compile a regex, perform the search and record findings
Definition: nomos_regex.c:241
int strNbuf(char *data, char *str)
Check if a string exists in buffer (case insensitive)
Definition: nomos_regex.c:536
int strNbuf_noGlobals(char *data, char *str, regmatch_t *matchPos, int doSave, char *saveData)
This is our own internal, case-insensitive version of strstr().
Definition: nomos_regex.c:546
int matchOnce(int isPlain, char *data, char *regex, regex_t *rp, regmatch_t *regmatch)
Perform a regex match on a given data and return only first match.
Definition: nomos_regex.c:282
int endsIn(char *s, char *suffix)
Check if a string ends with given suffix.
Definition: nomos_regex.c:56
void regexError(int ret, regex_t *regc, char *regex)
Log an error caused by regex.
Definition: nomos_regex.c:38
int idxGrep_recordIndex(int index, char *data, int flags)
compile a regex, perform the search and record index
Definition: nomos_regex.c:263
int textInFile(char *pathname, char *regex, int flags)
Check if a regex passes in a file.
Definition: nomos_regex.c:100
void rememberWhatWeFound(GArray *highlight, GArray *regmatch_tArray, int index, int mode)
Store regex matches in highlight array.
Definition: nomos_regex.c:493
static int getOffset(int posInDoctoredBuffer)
Get offset from doctored buffer.
Definition: nomos_regex.c:470
FUNCTION MatchPositionAndType * getMatchfromHighlightInfo(GArray *in, int index)
Get the MatchPositionAndType for a given index in highlight array.
Definition: nomos_utils.c:913
FUNCTION LicenceAndMatchPositions * getLicenceAndMatchPositions(GArray *in, int index)
Get the LicenceAndMatchPositions for a given index in match array.
Definition: nomos_utils.c:925
GArray * matchPositions
Match positions.
Definition: nomos.h:379
int start
Start position of match.
Definition: nomos.h:370
int index
Enums from index (Entrynumber) in STRINGS.in.
Definition: nomos.h:372
int end
End position of match.
Definition: nomos.h:371
GArray * indexList
Definition: nomos.h:416
GArray * theMatches
Definition: nomos.h:417
GArray * keywordPositions
Definition: nomos.h:418
int flags
Flags.
Definition: nomos.h:348
char * regex
License regex.
Definition: nomos.h:435