More little stuff.
[oweals/busybox.git] / regexp.c
1 /* vi: set sw=4 ts=4: */
2 /* regexp.c */
3
4 #include "internal.h"
5 #include "regexp.h"
6 #include <setjmp.h>
7 #include <stdio.h>
8 #include <ctype.h>
9
10
11 #if ( defined BB_GREP || defined BB_SED)
12
13 /* This also tries to find a needle in a haystack, but uses
14  * real regular expressions....  The fake regular expression
15  * version of find_match lives in utility.c.  Using this version
16  * will add 3.9k to busybox...
17  *  -Erik Andersen
18  */
19 extern int find_match(char *haystack, char *needle, int ignoreCase)
20 {
21         int status;
22         struct regexp *re;
23
24         re = regcomp(needle);
25         status = regexec(re, haystack, FALSE, ignoreCase);
26         free(re);
27         return (status);
28 }
29
30 #if defined BB_SED
31 /* This performs substitutions after a regexp match has been found.  
32  * The new string is returned.  It is malloc'ed, and do must be freed. */
33 extern int replace_match(char *haystack, char *needle, char *newNeedle,
34                                                  int ignoreCase)
35 {
36         int status;
37         struct regexp *re;
38         char *s, buf[BUF_SIZE], *d = buf;
39
40         re = regcomp(needle);
41         status = regexec(re, haystack, FALSE, ignoreCase);
42         if (status == TRUE) {
43                 s = haystack;
44
45                 do {
46                         /* copy stuff from before the match */
47                         while (s < re->startp[0])
48                                 *d++ = *s++;
49                         /* substitute for the matched part */
50                         regsub(re, newNeedle, d);
51                         s = re->endp[0];
52                         d += strlen(d);
53                 } while (regexec(re, s, FALSE, ignoreCase) == TRUE);
54                 /* copy stuff from after the match */
55                 while ((*d++ = *s++)) {
56                 }
57                 d[0] = '\0';
58                 strcpy(haystack, buf);
59         }
60         free(re);
61         return (status);
62 }
63 #endif
64
65
66 /* code swiped from elvis-tiny 1.4 (a clone of vi) and adjusted to 
67  * suit the needs of busybox by Erik Andersen.
68  *
69  * From the README:
70  * "Elvis is freely redistributable, in either source form or executable form.
71  * There are no restrictions on how you may use it".
72  * Elvis was written by Steve Kirkendall <kirkenda@cs.pdx.edu>
73  *
74  *
75  * This file contains the code that compiles regular expressions and executes
76  * them.  It supports the same syntax and features as vi's regular expression
77  * code.  Specifically, the meta characters are:
78  *      ^       matches the beginning of a line
79  *      $       matches the end of a line
80  *      \<      matches the beginning of a word
81  *      \>      matches the end of a word
82  *      .       matches any single character
83  *      []      matches any character in a character class
84  *      \(      delimits the start of a subexpression
85  *      \)      delimits the end of a subexpression
86  *      *       repeats the preceding 0 or more times
87  * NOTE: You cannot follow a \) with a *.
88  *
89  * The physical structure of a compiled RE is as follows:
90  *      - First, there is a one-byte value that says how many character classes
91  *        are used in this regular expression
92  *      - Next, each character class is stored as a bitmap that is 256 bits
93  *        (32 bytes) long.
94  *      - A mixture of literal characters and compiled meta characters follows.
95  *        This begins with M_BEGIN(0) and ends with M_END(0).  All meta chars
96  *        are stored as a \n followed by a one-byte code, so they take up two
97  *        bytes apiece.  Literal characters take up one byte apiece.  \n can't
98  *        be used as a literal character.
99  *
100  */
101
102
103
104 static char *previous;                  /* the previous regexp, used when null regexp is given */
105
106 #if defined BB_SED
107 static char *previous1;                 /* a copy of the text from the previous substitution for regsub() */
108 #endif
109
110
111 /* These are used to classify or recognize meta-characters */
112 #define META            '\0'
113 #define BASE_META(m)    ((m) - 256)
114 #define INT_META(c)     ((c) + 256)
115 #define IS_META(m)      ((m) >= 256)
116 #define IS_CLASS(m)     ((m) >= M_CLASS(0) && (m) <= M_CLASS(9))
117 #define IS_START(m)     ((m) >= M_START(0) && (m) <= M_START(9))
118 #define IS_END(m)       ((m) >= M_END(0) && (m) <= M_END(9))
119 #define IS_CLOSURE(m)   ((m) >= M_SPLAT && (m) <= M_QMARK)
120 #define ADD_META(s,m)   (*(s)++ = META, *(s)++ = BASE_META(m))
121 #define GET_META(s)     (*(s) == META ? INT_META(*++(s)) : *s)
122
123 /* These are the internal codes used for each type of meta-character */
124 #define M_BEGLINE       256                     /* internal code for ^ */
125 #define M_ENDLINE       257                     /* internal code for $ */
126 #define M_BEGWORD       258                     /* internal code for \< */
127 #define M_ENDWORD       259                     /* internal code for \> */
128 #define M_ANY           260                     /* internal code for . */
129 #define M_SPLAT         261                     /* internal code for * */
130 #define M_PLUS          262                     /* internal code for \+ */
131 #define M_QMARK         263                     /* internal code for \? */
132 #define M_CLASS(n)      (264+(n))       /* internal code for [] */
133 #define M_START(n)      (274+(n))       /* internal code for \( */
134 #define M_END(n)        (284+(n))       /* internal code for \) */
135
136 /* These are used during compilation */
137 static int class_cnt;                   /* used to assign class IDs */
138 static int start_cnt;                   /* used to assign start IDs */
139 static int end_stk[NSUBEXP];    /* used to assign end IDs */
140 static int end_sp;
141 static char *retext;                    /* points to the text being compiled */
142
143 /* error-handling stuff */
144 jmp_buf errorhandler;
145
146 #define FAIL(why)  do {fprintf(stderr, why); longjmp(errorhandler, 1);} while (0)
147
148
149
150
151 /* This function builds a bitmap for a particular class */
152 /* text -- start of the class */
153 /* bmap -- the bitmap */
154 static char *makeclass(char *text, char *bmap)
155 {
156         int i;
157         int complement = 0;
158
159
160         /* zero the bitmap */
161         for (i = 0; bmap && i < 32; i++) {
162                 bmap[i] = 0;
163         }
164
165         /* see if we're going to complement this class */
166         if (*text == '^') {
167                 text++;
168                 complement = 1;
169         }
170
171         /* add in the characters */
172         while (*text && *text != ']') {
173                 /* is this a span of characters? */
174                 if (text[1] == '-' && text[2]) {
175                         /* spans can't be backwards */
176                         if (text[0] > text[2]) {
177                                 FAIL("Backwards span in []");
178                         }
179
180                         /* add each character in the span to the bitmap */
181                         for (i = text[0]; bmap && i <= text[2]; i++) {
182                                 bmap[i >> 3] |= (1 << (i & 7));
183                         }
184
185                         /* move past this span */
186                         text += 3;
187                 } else {
188                         /* add this single character to the span */
189                         i = *text++;
190                         if (bmap) {
191                                 bmap[i >> 3] |= (1 << (i & 7));
192                         }
193                 }
194         }
195
196         /* make sure the closing ] is missing */
197         if (*text++ != ']') {
198                 FAIL("] missing");
199         }
200
201         /* if we're supposed to complement this class, then do so */
202         if (complement && bmap) {
203                 for (i = 0; i < 32; i++) {
204                         bmap[i] = ~bmap[i];
205                 }
206         }
207
208         return text;
209 }
210
211
212
213
214 /* This function gets the next character or meta character from a string.
215  * The pointer is incremented by 1, or by 2 for \-quoted characters.  For [],
216  * a bitmap is generated via makeclass() (if re is given), and the
217  * character-class text is skipped.
218  */
219 static int gettoken(sptr, re)
220 char **sptr;
221 regexp *re;
222 {
223         int c;
224
225         c = **sptr;
226         ++*sptr;
227         if (c == '\\') {
228                 c = **sptr;
229                 ++*sptr;
230                 switch (c) {
231                 case '<':
232                         return M_BEGWORD;
233
234                 case '>':
235                         return M_ENDWORD;
236
237                 case '(':
238                         if (start_cnt >= NSUBEXP) {
239                                 FAIL("Too many \\(s");
240                         }
241                         end_stk[end_sp++] = start_cnt;
242                         return M_START(start_cnt++);
243
244                 case ')':
245                         if (end_sp <= 0) {
246                                 FAIL("Mismatched \\)");
247                         }
248                         return M_END(end_stk[--end_sp]);
249
250                 case '*':
251                         return M_SPLAT;
252
253                 case '.':
254                         return M_ANY;
255
256                 case '+':
257                         return M_PLUS;
258
259                 case '?':
260                         return M_QMARK;
261
262                 default:
263                         return c;
264                 }
265         } else {
266                 switch (c) {
267                 case '^':
268                         if (*sptr == retext + 1) {
269                                 return M_BEGLINE;
270                         }
271                         return c;
272
273                 case '$':
274                         if (!**sptr) {
275                                 return M_ENDLINE;
276                         }
277                         return c;
278
279                 case '.':
280                         return M_ANY;
281
282                 case '*':
283                         return M_SPLAT;
284
285                 case '[':
286                         /* make sure we don't have too many classes */
287                         if (class_cnt >= 10) {
288                                 FAIL("Too many []s");
289                         }
290
291                         /* process the character list for this class */
292                         if (re) {
293                                 /* generate the bitmap for this class */
294                                 *sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt);
295                         } else {
296                                 /* skip to end of the class */
297                                 *sptr = makeclass(*sptr, (char *) 0);
298                         }
299                         return M_CLASS(class_cnt++);
300
301                 default:
302                         return c;
303                 }
304         }
305  /*NOTREACHED*/}
306
307
308
309
310 /* This function calculates the number of bytes that will be needed for a
311  * compiled RE.  Its argument is the uncompiled version.  It is not clever
312  * about catching syntax errors; that is done in a later pass.
313  */
314 static unsigned calcsize(text)
315 char *text;
316 {
317         unsigned size;
318         int token;
319
320         retext = text;
321         class_cnt = 0;
322         start_cnt = 1;
323         end_sp = 0;
324         size = 5;
325         while ((token = gettoken(&text, (regexp *) 0)) != 0) {
326                 if (IS_CLASS(token)) {
327                         size += 34;
328                 } else if (IS_META(token)) {
329                         size += 2;
330                 } else {
331                         size++;
332                 }
333         }
334
335         return size;
336 }
337
338
339
340 /*---------------------------------------------------------------------------*/
341
342
343 /* This function checks for a match between a character and a token which is
344  * known to represent a single character.  It returns 0 if they match, or
345  * 1 if they don't.
346  */
347 static int match1(regexp * re, char ch, int token, int ignoreCase)
348 {
349         if (!ch) {
350                 /* the end of a line can't match any RE of width 1 */
351                 return 1;
352         }
353         if (token == M_ANY) {
354                 return 0;
355         } else if (IS_CLASS(token)) {
356                 if (re->
357                         program[1 + 32 * (token - M_CLASS(0)) +
358                                         (ch >> 3)] & (1 << (ch & 7)))
359                         return 0;
360         }
361 //fprintf(stderr, "match1: ch='%c' token='%c': ", ch, token);
362         if (ch == token
363                 || (ignoreCase == TRUE && tolower(ch) == tolower(token))) {
364 //fprintf(stderr, "match\n");
365                 return 0;
366         }
367 //fprintf(stderr, "no match\n");
368         return 1;
369 }
370
371
372
373 /* This function checks characters up to and including the next closure, at
374  * which point it does a recursive call to check the rest of it.  This function
375  * returns 0 if everything matches, or 1 if something doesn't match.
376  */
377 /* re   -- the regular expression */
378 /* str  -- the string */
379 /* prog -- a portion of re->program, an compiled RE */
380 /* here -- a portion of str, the string to compare it to */
381 static int match(regexp * re, char *str, char *prog, char *here,
382                                  int ignoreCase)
383 {
384         int token;
385         int nmatched;
386         int closure;
387
388         for (token = GET_META(prog); !IS_CLOSURE(token);
389                  prog++, token = GET_META(prog)) {
390                 switch (token) {
391                         /*case M_BEGLINE: can't happen; re->bol is used instead */
392                 case M_ENDLINE:
393                         if (*here)
394                                 return 1;
395                         break;
396
397                 case M_BEGWORD:
398                         if (here != str &&
399                                 (here[-1] == '_' ||
400                                  (isascii(here[-1]) && isalnum(here[-1])))) return 1;
401                         break;
402
403                 case M_ENDWORD:
404                         if ((here[0] == '_' || isascii(here[0])) && isalnum(here[0]))
405                                 return 1;
406                         break;
407
408                 case M_START(0):
409                 case M_START(1):
410                 case M_START(2):
411                 case M_START(3):
412                 case M_START(4):
413                 case M_START(5):
414                 case M_START(6):
415                 case M_START(7):
416                 case M_START(8):
417                 case M_START(9):
418                         re->startp[token - M_START(0)] = (char *) here;
419                         break;
420
421                 case M_END(0):
422                 case M_END(1):
423                 case M_END(2):
424                 case M_END(3):
425                 case M_END(4):
426                 case M_END(5):
427                 case M_END(6):
428                 case M_END(7):
429                 case M_END(8):
430                 case M_END(9):
431                         re->endp[token - M_END(0)] = (char *) here;
432                         if (token == M_END(0)) {
433                                 return 0;
434                         }
435                         break;
436
437                 default:                                /* literal, M_CLASS(n), or M_ANY */
438                         if (match1(re, *here, token, ignoreCase) != 0)
439                                 return 1;
440                         here++;
441                 }
442         }
443
444         /* C L O S U R E */
445
446         /* step 1: see what we have to match against, and move "prog" to point
447          * the the remainder of the compiled RE.
448          */
449         closure = token;
450         prog++, token = GET_META(prog);
451         prog++;
452
453         /* step 2: see how many times we can match that token against the string */
454         for (nmatched = 0;
455                  (closure != M_QMARK || nmatched < 1) && *here
456                  && match1(re, *here, token, ignoreCase) == 0; nmatched++, here++) {
457         }
458
459         /* step 3: try to match the remainder, and back off if it doesn't */
460         while (nmatched >= 0 && match(re, str, prog, here, ignoreCase) != 0) {
461                 nmatched--;
462                 here--;
463         }
464
465         /* so how did it work out? */
466         if (nmatched >= ((closure == M_PLUS) ? 1 : 0))
467                 return 0;
468         return 1;
469 }
470
471
472 /* This function compiles a regexp. */
473 extern regexp *regcomp(char *text)
474 {
475         int needfirst;
476         unsigned size;
477         int token;
478         int peek;
479         char *build;
480         regexp *re;                                     // Ignore compiler whining.  If we longjmp, we don't use re anymore.
481
482
483         /* prepare for error handling */
484         re = (regexp *) 0;
485         if (setjmp(errorhandler)) {
486                 if (re) {
487                         free(re);
488                 }
489                 return (regexp *) 0;
490         }
491
492         /* if an empty regexp string was given, use the previous one */
493         if (*text == 0) {
494                 if (!previous) {
495                         FAIL("No previous RE");
496                 }
497                 text = previous;
498         } else {                                        /* non-empty regexp given, so remember it */
499
500                 if (previous)
501                         free(previous);
502                 previous = (char *) malloc((unsigned) (strlen(text) + 1));
503                 if (previous)
504                         strcpy(previous, text);
505         }
506
507         /* allocate memory */
508         class_cnt = 0;
509         start_cnt = 1;
510         end_sp = 0;
511         retext = text;
512         size = calcsize(text) + sizeof(regexp);
513         re = (regexp *) malloc((unsigned) size);
514
515         if (!re) {
516                 FAIL("Not enough memory for this RE");
517         }
518
519         /* compile it */
520         build = &re->program[1 + 32 * class_cnt];
521         re->program[0] = class_cnt;
522         for (token = 0; token < NSUBEXP; token++) {
523                 re->startp[token] = re->endp[token] = (char *) 0;
524         }
525         re->first = 0;
526         re->bol = 0;
527         re->minlen = 0;
528         needfirst = 1;
529         class_cnt = 0;
530         start_cnt = 1;
531         end_sp = 0;
532         retext = text;
533         for (token = M_START(0), peek = gettoken(&text, re);
534                  token; token = peek, peek = gettoken(&text, re)) {
535                 /* special processing for the closure operator */
536                 if (IS_CLOSURE(peek)) {
537                         /* detect misuse of closure operator */
538                         if (IS_START(token)) {
539                                 FAIL("* or \\+ or \\? follows nothing");
540                         }
541                                 else if (IS_META(token) && token != M_ANY
542                                                  && !IS_CLASS(token)) {
543                                 FAIL
544                                         ("* or \\+ or \\? can only follow a normal character or . or []");
545                         }
546
547                         /* it is okay -- make it prefix instead of postfix */
548                         ADD_META(build, peek);
549
550                         /* take care of "needfirst" - is this the first char? */
551                         if (needfirst && peek == M_PLUS && !IS_META(token)) {
552                                 re->first = token;
553                         }
554                         needfirst = 0;
555
556                         /* we used "peek" -- need to refill it */
557                         peek = gettoken(&text, re);
558                         if (IS_CLOSURE(peek)) {
559                                 FAIL("* or \\+ or \\? doubled up");
560                         }
561                 } else if (!IS_META(token)) {
562                         /* normal char is NOT argument of closure */
563                         if (needfirst) {
564                                 re->first = token;
565                                 needfirst = 0;
566                         }
567                         re->minlen++;
568                 } else if (token == M_ANY || IS_CLASS(token)) {
569                         /* . or [] is NOT argument of closure */
570                         needfirst = 0;
571                         re->minlen++;
572                 }
573
574                 /* the "token" character is not closure -- process it normally */
575                 if (token == M_BEGLINE) {
576                         /* set the BOL flag instead of storing M_BEGLINE */
577                         re->bol = 1;
578                 } else if (IS_META(token)) {
579                         ADD_META(build, token);
580                 } else {
581                         *build++ = token;
582                 }
583         }
584
585         /* end it with a \) which MUST MATCH the opening \( */
586         ADD_META(build, M_END(0));
587         if (end_sp > 0) {
588                 FAIL("Not enough \\)s");
589         }
590
591         return re;
592 }
593
594
595
596
597 /* This function searches through a string for text that matches an RE. */
598 /* re  -- the compiled regexp to search for */
599 /* str -- the string to search through */
600 /* bol -- does str start at the beginning of a line? (boolean) */
601 /* ignoreCase -- ignoreCase or not */
602 extern int regexec(struct regexp *re, char *str, int bol, int ignoreCase)
603 {
604         char *prog;                                     /* the entry point of re->program */
605         int len;                                        /* length of the string */
606         char *here;
607
608         /* if must start at the beginning of a line, and this isn't, then fail */
609         if (re->bol && bol == TRUE) {
610                 return FALSE;
611         }
612
613         len = strlen(str);
614         prog = re->program + 1 + 32 * re->program[0];
615
616         /* search for the RE in the string */
617         if (re->bol) {
618                 /* must occur at BOL */
619                 if ((re->first && match1(re, *(char *) str, re->first, ignoreCase))     /* wrong first letter? */
620                         ||len < re->minlen      /* not long enough? */
621                         || match(re, (char *) str, prog, str, ignoreCase))      /* doesn't match? */
622                         return FALSE;           /* THEN FAIL! */
623         } else if (ignoreCase == FALSE) {
624                 /* can occur anywhere in the line, noignorecase */
625                 for (here = (char *) str; (re->first && re->first != *here)
626                          || match(re, (char *) str, prog, here, ignoreCase);
627                          here++, len--) {
628                         if (len < re->minlen)
629                                 return FALSE;
630                 }
631         } else {
632                 /* can occur anywhere in the line, ignorecase */
633                 for (here = (char *) str;
634                          (re->first && match1(re, *here, (int) re->first, ignoreCase))
635                          || match(re, (char *) str, prog, here, ignoreCase);
636                          here++, len--) {
637                         if (len < re->minlen)
638                                 return FALSE;
639                 }
640         }
641
642         /* if we didn't fail, then we must have succeeded */
643         return TRUE;
644 }
645
646
647
648
649 #if defined BB_SED
650 /* This performs substitutions after a regexp match has been found.  */
651 extern void regsub(regexp * re, char *src, char *dst)
652 {
653         char *cpy;
654         char *end;
655         char c;
656         char *start;
657         int mod;
658
659         mod = 0;
660
661         start = src;
662         while ((c = *src++) != '\0') {
663                 /* recognize any meta characters */
664                 if (c == '&') {
665                         cpy = re->startp[0];
666                         end = re->endp[0];
667                 } else if (c == '~') {
668                         cpy = previous1;
669                         if (cpy)
670                                 end = cpy + strlen(cpy);
671                 } else if (c == '\\') {
672                         c = *src++;
673                         switch (c) {
674                         case '0':
675                         case '1':
676                         case '2':
677                         case '3':
678                         case '4':
679                         case '5':
680                         case '6':
681                         case '7':
682                         case '8':
683                         case '9':
684                                 /* \0 thru \9 mean "copy subexpression" */
685                                 c -= '0';
686                                 cpy = re->startp[(int) c];
687                                 end = re->endp[(int) c];
688                                 break;
689                         case 'U':
690                         case 'u':
691                         case 'L':
692                         case 'l':
693                                 /* \U and \L mean "convert to upper/lowercase" */
694                                 mod = c;
695                                 continue;
696
697                         case 'E':
698                         case 'e':
699                                 /* \E ends the \U or \L */
700                                 mod = 0;
701                                 continue;
702                         case '&':
703                                 /* "\&" means "original text" */
704                                 *dst++ = c;
705                                 continue;
706
707                         case '~':
708                                 /* "\~" means "previous text, if any" */
709                                 *dst++ = c;
710                                 continue;
711                         default:
712                                 /* ordinary char preceded by backslash */
713                                 *dst++ = c;
714                                 continue;
715                         }
716                 } else {
717                         /* ordinary character, so just copy it */
718                         *dst++ = c;
719                         continue;
720                 }
721
722                 /* Note: to reach this point in the code, we must have evaded
723                  * all "continue" statements.  To do that, we must have hit
724                  * a metacharacter that involves copying.
725                  */
726
727                 /* if there is nothing to copy, loop */
728                 if (!cpy)
729                         continue;
730
731                 /* copy over a portion of the original */
732                 while (cpy < end) {
733                         switch (mod) {
734                         case 'U':
735                         case 'u':
736                                 /* convert to uppercase */
737                                 if (isascii(*cpy) && islower(*cpy)) {
738                                         *dst++ = toupper(*cpy);
739                                         cpy++;
740                                 } else {
741                                         *dst++ = *cpy++;
742                                 }
743                                 break;
744
745                         case 'L':
746                         case 'l':
747                                 /* convert to lowercase */
748                                 if (isascii(*cpy) && isupper(*cpy)) {
749                                         *dst++ = tolower(*cpy);
750                                         cpy++;
751                                 } else {
752                                         *dst++ = *cpy++;
753                                 }
754                                 break;
755
756                         default:
757                                 /* copy without any conversion */
758                                 *dst++ = *cpy++;
759                         }
760
761                         /* \u and \l end automatically after the first char */
762                         if (mod && (mod == 'u' || mod == 'l')) {
763                                 mod = 0;
764                         }
765                 }
766         }
767         *dst = '\0';
768
769         /* remember what text we inserted this time */
770         if (previous1)
771                 free(previous1);
772         previous1 = (char *) malloc((unsigned) (strlen(start) + 1));
773         if (previous1)
774                 strcpy(previous1, start);
775 }
776 #endif
777
778 #endif                                                  /* BB_REGEXP */