]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libcompat/regexp/regexp.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libcompat / regexp / regexp.c
1 /*
2  * regcomp and regexec -- regsub and regerror are elsewhere
3  *
4  *      Copyright (c) 1986 by University of Toronto.
5  *      Written by Henry Spencer.  Not derived from licensed software.
6  *
7  *      Permission is granted to anyone to use this software for any
8  *      purpose on any computer system, and to redistribute it freely,
9  *      subject to the following restrictions:
10  *
11  *      1. The author is not responsible for the consequences of use of
12  *              this software, no matter how awful, even if they arise
13  *              from defects in it.
14  *
15  *      2. The origin of this software must not be misrepresented, either
16  *              by explicit claim or by omission.
17  *
18  *      3. Altered versions must be plainly marked as such, and must not
19  *              be misrepresented as being the original software.
20  *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
21  *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to |
22  *** to assist in implementing egrep.
23  *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
24  *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
25  *** as in BSD grep and ex.
26  *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
27  *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
28  *** THIS IS AN ALTERED VERSION.  It was altered by James A. Woods,
29  *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
30  *
31  * Beware that some of this code is subtly aware of the way operator
32  * precedence is structured in regular expressions.  Serious changes in
33  * regular-expression syntax might require a total rethink.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <limits.h>
40 #include <regexp.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include "collate.h"
46 #include "regmagic.h"
47
48 /*
49  * The "internal use only" fields in regexp.h are present to pass info from
50  * compile to execute that permits the execute phase to run lots faster on
51  * simple cases.  They are:
52  *
53  * regstart     char that must begin a match; '\0' if none obvious
54  * reganch      is the match anchored (at beginning-of-line only)?
55  * regmust      string (pointer into program) that match must include, or NULL
56  * regmlen      length of regmust string
57  *
58  * Regstart and reganch permit very fast decisions on suitable starting points
59  * for a match, cutting down the work a lot.  Regmust permits fast rejection
60  * of lines that cannot possibly match.  The regmust tests are costly enough
61  * that regcomp() supplies a regmust only if the r.e. contains something
62  * potentially expensive (at present, the only such thing detected is * or +
63  * at the start of the r.e., which can involve a lot of backup).  Regmlen is
64  * supplied because the test in regexec() needs it and regcomp() is computing
65  * it anyway.
66  */
67
68 /*
69  * Structure for regexp "program".  This is essentially a linear encoding
70  * of a nondeterministic finite-state machine (aka syntax charts or
71  * "railroad normal form" in parsing technology).  Each node is an opcode
72  * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
73  * all nodes except BRANCH implement concatenation; a "next" pointer with
74  * a BRANCH on both ends of it is connecting two alternatives.  (Here we
75  * have one of the subtle syntax dependencies:  an individual BRANCH (as
76  * opposed to a collection of them) is never concatenated with anything
77  * because of operator precedence.)  The operand of some types of node is
78  * a literal string; for others, it is a node leading into a sub-FSM.  In
79  * particular, the operand of a BRANCH node is the first node of the branch.
80  * (NB this is *not* a tree structure:  the tail of the branch connects
81  * to the thing following the set of BRANCHes.)  The opcodes are:
82  */
83
84 /* definition   number  opnd?   meaning */
85 #define END     0       /* no   End of program. */
86 #define BOL     1       /* no   Match "" at beginning of line. */
87 #define EOL     2       /* no   Match "" at end of line. */
88 #define ANY     3       /* no   Match any one character. */
89 #define ANYOF   4       /* str  Match any character in this string. */
90 #define ANYBUT  5       /* str  Match any character not in this string. */
91 #define BRANCH  6       /* node Match this alternative, or the next... */
92 #define BACK    7       /* no   Match "", "next" ptr points backward. */
93 #define EXACTLY 8       /* str  Match this string. */
94 #define NOTHING 9       /* no   Match empty string. */
95 #define STAR    10      /* node Match this (simple) thing 0 or more times. */
96 #define PLUS    11      /* node Match this (simple) thing 1 or more times. */
97 #define WORDA   12      /* no   Match "" at wordchar, where prev is nonword */
98 #define WORDZ   13      /* no   Match "" at nonwordchar, where prev is word */
99 #define OPEN    20      /* no   Mark this point in input as start of #n. */
100                         /*      OPEN+1 is number 1, etc. */
101 #define CLOSE   30      /* no   Analogous to OPEN. */
102
103 /*
104  * Opcode notes:
105  *
106  * BRANCH       The set of branches constituting a single choice are hooked
107  *              together with their "next" pointers, since precedence prevents
108  *              anything being concatenated to any individual branch.  The
109  *              "next" pointer of the last BRANCH in a choice points to the
110  *              thing following the whole choice.  This is also where the
111  *              final "next" pointer of each individual branch points; each
112  *              branch starts with the operand node of a BRANCH node.
113  *
114  * BACK         Normal "next" pointers all implicitly point forward; BACK
115  *              exists to make loop structures possible.
116  *
117  * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
118  *              BRANCH structures using BACK.  Simple cases (one character
119  *              per match) are implemented with STAR and PLUS for speed
120  *              and to minimize recursive plunges.
121  *
122  * OPEN,CLOSE   ...are numbered at compile time.
123  */
124
125 /*
126  * A node is one char of opcode followed by two chars of "next" pointer.
127  * "Next" pointers are stored as two 8-bit pieces, high order first.  The
128  * value is a positive offset from the opcode of the node containing it.
129  * An operand, if any, simply follows the node.  (Note that much of the
130  * code generation knows about this implicit relationship.)
131  *
132  * Using two bytes for the "next" pointer is vast overkill for most things,
133  * but allows patterns to get big without disasters.
134  */
135 #define OP(p)   (*(p))
136 #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
137 #define OPERAND(p)      ((p) + 3)
138
139 /*
140  * See regmagic.h for one further detail of program structure.
141  */
142
143
144 /*
145  * Utility definitions.
146  */
147 #ifndef CHARBITS
148 #define UCHARAT(p)      ((int)*(unsigned char *)(p))
149 #else
150 #define UCHARAT(p)      ((int)*(p)&CHARBITS)
151 #endif
152
153 #define FAIL(m) { regerror(m); return(NULL); }
154 #define ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?')
155
156 /*
157  * Flags to be passed up and down.
158  */
159 #define HASWIDTH        01      /* Known never to match null string. */
160 #define SIMPLE          02      /* Simple enough to be STAR/PLUS operand. */
161 #define SPSTART         04      /* Starts with * or +. */
162 #define WORST           0       /* Worst case. */
163
164 /*
165  * Global work variables for regcomp().
166  */
167 static char *regparse;          /* Input-scan pointer. */
168 static int regnpar;             /* () count. */
169 static char regdummy;
170 static char *regcode;           /* Code-emit pointer; &regdummy = don't. */
171 static long regsize;            /* Code size. */
172
173 /*
174  * Forward declarations for regcomp()'s friends.
175  */
176 #ifndef STATIC
177 #define STATIC  static
178 #endif
179 STATIC char *reg();
180 STATIC char *regbranch();
181 STATIC char *regpiece();
182 STATIC char *regatom();
183 STATIC char *regnode();
184 STATIC char *regnext();
185 STATIC void regc();
186 STATIC void reginsert();
187 STATIC void regtail();
188 STATIC void regoptail();
189 #ifdef STRCSPN
190 STATIC int strcspn();
191 #endif
192
193 /*
194  - regcomp - compile a regular expression into internal code
195  *
196  * We can't allocate space until we know how big the compiled form will be,
197  * but we can't compile it (and thus know how big it is) until we've got a
198  * place to put the code.  So we cheat:  we compile it twice, once with code
199  * generation turned off and size counting turned on, and once "for real".
200  * This also means that we don't allocate space until we are sure that the
201  * thing really will compile successfully, and we never have to move the
202  * code and thus invalidate pointers into it.  (Note that it has to be in
203  * one piece because free() must be able to free it all.)
204  *
205  * Beware that the optimization-preparation code in here knows about some
206  * of the structure of the compiled regexp.
207  */
208 regexp *
209 regcomp(exp)
210 const char *exp;
211 {
212         regexp *r;
213         char *scan;
214         char *longest;
215         int len;
216         int flags;
217
218         if (exp == NULL)
219                 FAIL("NULL argument");
220
221         /* First pass: determine size, legality. */
222 #ifdef notdef
223         if (exp[0] == '.' && exp[1] == '*') exp += 2;  /* aid grep */
224 #endif
225         regparse = (char *)exp;
226         regnpar = 1;
227         regsize = 0L;
228         regcode = &regdummy;
229         regc(MAGIC);
230         if (reg(0, &flags) == NULL)
231                 return(NULL);
232
233         /* Small enough for pointer-storage convention? */
234         if (regsize >= 32767L)          /* Probably could be 65535L. */
235                 FAIL("regexp too big");
236
237         /* Allocate space. */
238         r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
239         if (r == NULL)
240                 FAIL("out of space");
241
242         /* Second pass: emit code. */
243         regparse = (char *)exp;
244         regnpar = 1;
245         regcode = r->program;
246         regc(MAGIC);
247         if (reg(0, &flags) == NULL)
248                 return(NULL);
249
250         /* Dig out information for optimizations. */
251         r->regstart = '\0';     /* Worst-case defaults. */
252         r->reganch = 0;
253         r->regmust = NULL;
254         r->regmlen = 0;
255         scan = r->program+1;                    /* First BRANCH. */
256         if (OP(regnext(scan)) == END) {         /* Only one top-level choice. */
257                 scan = OPERAND(scan);
258
259                 /* Starting-point info. */
260                 if (OP(scan) == EXACTLY)
261                         r->regstart = *OPERAND(scan);
262                 else if (OP(scan) == BOL)
263                         r->reganch++;
264
265                 /*
266                  * If there's something expensive in the r.e., find the
267                  * longest literal string that must appear and make it the
268                  * regmust.  Resolve ties in favor of later strings, since
269                  * the regstart check works with the beginning of the r.e.
270                  * and avoiding duplication strengthens checking.  Not a
271                  * strong reason, but sufficient in the absence of others.
272                  */
273                 if (flags&SPSTART) {
274                         longest = NULL;
275                         len = 0;
276                         for (; scan != NULL; scan = regnext(scan))
277                                 if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
278                                         longest = OPERAND(scan);
279                                         len = strlen(OPERAND(scan));
280                                 }
281                         r->regmust = longest;
282                         r->regmlen = len;
283                 }
284         }
285
286         return(r);
287 }
288
289 /*
290  - reg - regular expression, i.e. main body or parenthesized thing
291  *
292  * Caller must absorb opening parenthesis.
293  *
294  * Combining parenthesis handling with the base level of regular expression
295  * is a trifle forced, but the need to tie the tails of the branches to what
296  * follows makes it hard to avoid.
297  */
298 static char *
299 reg(paren, flagp)
300 int paren;                      /* Parenthesized? */
301 int *flagp;
302 {
303         char *ret;
304         char *br;
305         char *ender;
306         int parno;
307         int flags;
308
309         *flagp = HASWIDTH;      /* Tentatively. */
310
311         /* Make an OPEN node, if parenthesized. */
312         if (paren) {
313                 if (regnpar >= NSUBEXP)
314                         FAIL("too many ()");
315                 parno = regnpar;
316                 regnpar++;
317                 ret = regnode(OPEN+parno);
318         } else
319                 ret = NULL;
320
321         /* Pick up the branches, linking them together. */
322         br = regbranch(&flags);
323         if (br == NULL)
324                 return(NULL);
325         if (ret != NULL)
326                 regtail(ret, br);       /* OPEN -> first. */
327         else
328                 ret = br;
329         if (!(flags&HASWIDTH))
330                 *flagp &= ~HASWIDTH;
331         *flagp |= flags&SPSTART;
332         while (*regparse == '|' || *regparse == '\n') {
333                 regparse++;
334                 br = regbranch(&flags);
335                 if (br == NULL)
336                         return(NULL);
337                 regtail(ret, br);       /* BRANCH -> BRANCH. */
338                 if (!(flags&HASWIDTH))
339                         *flagp &= ~HASWIDTH;
340                 *flagp |= flags&SPSTART;
341         }
342
343         /* Make a closing node, and hook it on the end. */
344         ender = regnode((paren) ? CLOSE+parno : END);
345         regtail(ret, ender);
346
347         /* Hook the tails of the branches to the closing node. */
348         for (br = ret; br != NULL; br = regnext(br))
349                 regoptail(br, ender);
350
351         /* Check for proper termination. */
352         if (paren && *regparse++ != ')') {
353                 FAIL("unmatched ()");
354         } else if (!paren && *regparse != '\0') {
355                 if (*regparse == ')') {
356                         FAIL("unmatched ()");
357                 } else
358                         FAIL("junk on end");    /* "Can't happen". */
359                 /* NOTREACHED */
360         }
361
362         return(ret);
363 }
364
365 /*
366  - regbranch - one alternative of an | operator
367  *
368  * Implements the concatenation operator.
369  */
370 static char *
371 regbranch(flagp)
372 int *flagp;
373 {
374         char *ret;
375         char *chain;
376         char *latest;
377         int flags;
378
379         *flagp = WORST;         /* Tentatively. */
380
381         ret = regnode(BRANCH);
382         chain = NULL;
383         while (*regparse != '\0' && *regparse != ')' &&
384                *regparse != '\n' && *regparse != '|') {
385                 latest = regpiece(&flags);
386                 if (latest == NULL)
387                         return(NULL);
388                 *flagp |= flags&HASWIDTH;
389                 if (chain == NULL)      /* First piece. */
390                         *flagp |= flags&SPSTART;
391                 else
392                         regtail(chain, latest);
393                 chain = latest;
394         }
395         if (chain == NULL)      /* Loop ran zero times. */
396                 (void) regnode(NOTHING);
397
398         return(ret);
399 }
400
401 /*
402  - regpiece - something followed by possible [*+?]
403  *
404  * Note that the branching code sequences used for ? and the general cases
405  * of * and + are somewhat optimized:  they use the same NOTHING node as
406  * both the endmarker for their branch list and the body of the last branch.
407  * It might seem that this node could be dispensed with entirely, but the
408  * endmarker role is not redundant.
409  */
410 static char *
411 regpiece(flagp)
412 int *flagp;
413 {
414         char *ret;
415         char op;
416         char *next;
417         int flags;
418
419         ret = regatom(&flags);
420         if (ret == NULL)
421                 return(NULL);
422
423         op = *regparse;
424         if (!ISMULT(op)) {
425                 *flagp = flags;
426                 return(ret);
427         }
428
429         if (!(flags&HASWIDTH) && op != '?')
430                 FAIL("*+ operand could be empty");
431         *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
432
433         if (op == '*' && (flags&SIMPLE))
434                 reginsert(STAR, ret);
435         else if (op == '*') {
436                 /* Emit x* as (x&|), where & means "self". */
437                 reginsert(BRANCH, ret);                 /* Either x */
438                 regoptail(ret, regnode(BACK));          /* and loop */
439                 regoptail(ret, ret);                    /* back */
440                 regtail(ret, regnode(BRANCH));          /* or */
441                 regtail(ret, regnode(NOTHING));         /* null. */
442         } else if (op == '+' && (flags&SIMPLE))
443                 reginsert(PLUS, ret);
444         else if (op == '+') {
445                 /* Emit x+ as x(&|), where & means "self". */
446                 next = regnode(BRANCH);                 /* Either */
447                 regtail(ret, next);
448                 regtail(regnode(BACK), ret);            /* loop back */
449                 regtail(next, regnode(BRANCH));         /* or */
450                 regtail(ret, regnode(NOTHING));         /* null. */
451         } else if (op == '?') {
452                 /* Emit x? as (x|) */
453                 reginsert(BRANCH, ret);                 /* Either x */
454                 regtail(ret, regnode(BRANCH));          /* or */
455                 next = regnode(NOTHING);                /* null. */
456                 regtail(ret, next);
457                 regoptail(ret, next);
458         }
459         regparse++;
460         if (ISMULT(*regparse))
461                 FAIL("nested *?+");
462
463         return(ret);
464 }
465
466 /*
467  - regatom - the lowest level
468  *
469  * Optimization:  gobbles an entire sequence of ordinary characters so that
470  * it can turn them into a single node, which is smaller to store and
471  * faster to run.  Backslashed characters are exceptions, each becoming a
472  * separate node; the code is simpler that way and it's not worth fixing.
473  */
474 static char *
475 regatom(flagp)
476 int *flagp;
477 {
478         char *ret;
479         int flags;
480
481         *flagp = WORST;         /* Tentatively. */
482
483         switch (*regparse++) {
484         /* FIXME: these chars only have meaning at beg/end of pat? */
485         case '^':
486                 ret = regnode(BOL);
487                 break;
488         case '$':
489                 ret = regnode(EOL);
490                 break;
491         case '.':
492                 ret = regnode(ANY);
493                 *flagp |= HASWIDTH|SIMPLE;
494                 break;
495         case '[': {
496                         int class;
497                         int classend;
498                         int i;
499
500                         if (*regparse == '^') { /* Complement of range. */
501                                 ret = regnode(ANYBUT);
502                                 regparse++;
503                         } else
504                                 ret = regnode(ANYOF);
505                         if (*regparse == ']' || *regparse == '-')
506                                 regc(*regparse++);
507                         while (*regparse != '\0' && *regparse != ']') {
508                                 if (*regparse == '-') {
509                                         regparse++;
510                                         if (*regparse == ']' || *regparse == '\0')
511                                                 regc('-');
512                                         else {
513                                                 class = UCHARAT(regparse-2);
514                                                 classend = UCHARAT(regparse);
515                                                 if (__collate_load_error) {
516                                                         if (class > classend)
517                                                                 FAIL("invalid [] range");
518                                                         for (class++; class <= classend; class++)
519                                                                 regc(class);
520                                                 } else {
521                                                         if (__collate_range_cmp(class, classend) > 0)
522                                                                 FAIL("invalid [] range");
523                                                         for (i = 0; i <= UCHAR_MAX; i++)
524                                                                 if (   i != class
525                                                                     && __collate_range_cmp(class, i) <= 0
526                                                                     && __collate_range_cmp(i, classend) <= 0
527                                                                    )
528                                                                         regc(i);
529                                                 }
530                                                 regparse++;
531                                         }
532                                 } else
533                                         regc(*regparse++);
534                         }
535                         regc('\0');
536                         if (*regparse != ']')
537                                 FAIL("unmatched []");
538                         regparse++;
539                         *flagp |= HASWIDTH|SIMPLE;
540                 }
541                 break;
542         case '(':
543                 ret = reg(1, &flags);
544                 if (ret == NULL)
545                         return(NULL);
546                 *flagp |= flags&(HASWIDTH|SPSTART);
547                 break;
548         case '\0':
549         case '|':
550         case '\n':
551         case ')':
552                 FAIL("internal urp");   /* Supposed to be caught earlier. */
553                 break;
554         case '?':
555         case '+':
556         case '*':
557                 FAIL("?+* follows nothing");
558                 break;
559         case '\\':
560                 switch (*regparse++) {
561                 case '\0':
562                         FAIL("trailing \\");
563                         break;
564                 case '<':
565                         ret = regnode(WORDA);
566                         break;
567                 case '>':
568                         ret = regnode(WORDZ);
569                         break;
570                 /* FIXME: Someday handle \1, \2, ... */
571                 default:
572                         /* Handle general quoted chars in exact-match routine */
573                         goto de_fault;
574                 }
575                 break;
576         de_fault:
577         default:
578                 /*
579                  * Encode a string of characters to be matched exactly.
580                  *
581                  * This is a bit tricky due to quoted chars and due to
582                  * '*', '+', and '?' taking the SINGLE char previous
583                  * as their operand.
584                  *
585                  * On entry, the char at regparse[-1] is going to go
586                  * into the string, no matter what it is.  (It could be
587                  * following a \ if we are entered from the '\' case.)
588                  *
589                  * Basic idea is to pick up a good char in  ch  and
590                  * examine the next char.  If it's *+? then we twiddle.
591                  * If it's \ then we frozzle.  If it's other magic char
592                  * we push  ch  and terminate the string.  If none of the
593                  * above, we push  ch  on the string and go around again.
594                  *
595                  *  regprev  is used to remember where "the current char"
596                  * starts in the string, if due to a *+? we need to back
597                  * up and put the current char in a separate, 1-char, string.
598                  * When  regprev  is NULL,  ch  is the only char in the
599                  * string; this is used in *+? handling, and in setting
600                  * flags |= SIMPLE at the end.
601                  */
602                 {
603                         char *regprev;
604                         char ch;
605
606                         regparse--;                     /* Look at cur char */
607                         ret = regnode(EXACTLY);
608                         for ( regprev = 0 ; ; ) {
609                                 ch = *regparse++;       /* Get current char */
610                                 switch (*regparse) {    /* look at next one */
611
612                                 default:
613                                         regc(ch);       /* Add cur to string */
614                                         break;
615
616                                 case '.': case '[': case '(':
617                                 case ')': case '|': case '\n':
618                                 case '$': case '^':
619                                 case '\0':
620                                 /* FIXME, $ and ^ should not always be magic */
621                                 magic:
622                                         regc(ch);       /* dump cur char */
623                                         goto done;      /* and we are done */
624
625                                 case '?': case '+': case '*':
626                                         if (!regprev)   /* If just ch in str, */
627                                                 goto magic;     /* use it */
628                                         /* End mult-char string one early */
629                                         regparse = regprev; /* Back up parse */
630                                         goto done;
631
632                                 case '\\':
633                                         regc(ch);       /* Cur char OK */
634                                         switch (regparse[1]){ /* Look after \ */
635                                         case '\0':
636                                         case '<':
637                                         case '>':
638                                         /* FIXME: Someday handle \1, \2, ... */
639                                                 goto done; /* Not quoted */
640                                         default:
641                                                 /* Backup point is \, scan                                                       * point is after it. */
642                                                 regprev = regparse;
643                                                 regparse++;
644                                                 continue;       /* NOT break; */
645                                         }
646                                 }
647                                 regprev = regparse;     /* Set backup point */
648                         }
649                 done:
650                         regc('\0');
651                         *flagp |= HASWIDTH;
652                         if (!regprev)           /* One char? */
653                                 *flagp |= SIMPLE;
654                 }
655                 break;
656         }
657
658         return(ret);
659 }
660
661 /*
662  - regnode - emit a node
663  */
664 static char *                   /* Location. */
665 regnode(op)
666 char op;
667 {
668         char *ret;
669         char *ptr;
670
671         ret = regcode;
672         if (ret == &regdummy) {
673                 regsize += 3;
674                 return(ret);
675         }
676
677         ptr = ret;
678         *ptr++ = op;
679         *ptr++ = '\0';          /* Null "next" pointer. */
680         *ptr++ = '\0';
681         regcode = ptr;
682
683         return(ret);
684 }
685
686 /*
687  - regc - emit (if appropriate) a byte of code
688  */
689 static void
690 regc(b)
691 char b;
692 {
693         if (regcode != &regdummy)
694                 *regcode++ = b;
695         else
696                 regsize++;
697 }
698
699 /*
700  - reginsert - insert an operator in front of already-emitted operand
701  *
702  * Means relocating the operand.
703  */
704 static void
705 reginsert(op, opnd)
706 char op;
707 char *opnd;
708 {
709         char *src;
710         char *dst;
711         char *place;
712
713         if (regcode == &regdummy) {
714                 regsize += 3;
715                 return;
716         }
717
718         src = regcode;
719         regcode += 3;
720         dst = regcode;
721         while (src > opnd)
722                 *--dst = *--src;
723
724         place = opnd;           /* Op node, where operand used to be. */
725         *place++ = op;
726         *place++ = '\0';
727         *place++ = '\0';
728 }
729
730 /*
731  - regtail - set the next-pointer at the end of a node chain
732  */
733 static void
734 regtail(p, val)
735 char *p;
736 char *val;
737 {
738         char *scan;
739         char *temp;
740         int offset;
741
742         if (p == &regdummy)
743                 return;
744
745         /* Find last node. */
746         scan = p;
747         for (;;) {
748                 temp = regnext(scan);
749                 if (temp == NULL)
750                         break;
751                 scan = temp;
752         }
753
754         if (OP(scan) == BACK)
755                 offset = scan - val;
756         else
757                 offset = val - scan;
758         *(scan+1) = (offset>>8)&0377;
759         *(scan+2) = offset&0377;
760 }
761
762 /*
763  - regoptail - regtail on operand of first argument; nop if operandless
764  */
765 static void
766 regoptail(p, val)
767 char *p;
768 char *val;
769 {
770         /* "Operandless" and "op != BRANCH" are synonymous in practice. */
771         if (p == NULL || p == &regdummy || OP(p) != BRANCH)
772                 return;
773         regtail(OPERAND(p), val);
774 }
775
776 /*
777  * regexec and friends
778  */
779
780 /*
781  * Global work variables for regexec().
782  */
783 static char *reginput;          /* String-input pointer. */
784 static char *regbol;            /* Beginning of input, for ^ check. */
785 static char **regstartp;        /* Pointer to startp array. */
786 static char **regendp;          /* Ditto for endp. */
787
788 /*
789  * Forwards.
790  */
791 STATIC int regtry();
792 STATIC int regmatch();
793 STATIC int regrepeat();
794
795 #ifdef DEBUG
796 int regnarrate = 0;
797 void regdump();
798 STATIC char *regprop();
799 #endif
800
801 /*
802  - regexec - match a regexp against a string
803  */
804 int
805 regexec(prog, string)
806 const regexp *prog;
807 const char *string;
808 {
809         char *s;
810         extern char *strchr();
811
812         /* Be paranoid... */
813         if (prog == NULL || string == NULL) {
814                 regerror("NULL parameter");
815                 return(0);
816         }
817
818         /* Check validity of program. */
819         if (UCHARAT(prog->program) != MAGIC) {
820                 regerror("corrupted program");
821                 return(0);
822         }
823
824         /* If there is a "must appear" string, look for it. */
825         if (prog->regmust != NULL) {
826                 s = (char *)string;
827                 while ((s = strchr(s, prog->regmust[0])) != NULL) {
828                         if (strncmp(s, prog->regmust, prog->regmlen) == 0)
829                                 break;  /* Found it. */
830                         s++;
831                 }
832                 if (s == NULL)  /* Not present. */
833                         return(0);
834         }
835
836         /* Mark beginning of line for ^ . */
837         regbol = (char *)string;
838
839         /* Simplest case:  anchored match need be tried only once. */
840         if (prog->reganch)
841                 return(regtry(prog, string));
842
843         /* Messy cases:  unanchored match. */
844         s = (char *)string;
845         if (prog->regstart != '\0')
846                 /* We know what char it must start with. */
847                 while ((s = strchr(s, prog->regstart)) != NULL) {
848                         if (regtry(prog, s))
849                                 return(1);
850                         s++;
851                 }
852         else
853                 /* We don't -- general case. */
854                 do {
855                         if (regtry(prog, s))
856                                 return(1);
857                 } while (*s++ != '\0');
858
859         /* Failure. */
860         return(0);
861 }
862
863 /*
864  - regtry - try match at specific point
865  */
866 static int                      /* 0 failure, 1 success */
867 regtry(prog, string)
868 regexp *prog;
869 char *string;
870 {
871         int i;
872         char **sp;
873         char **ep;
874
875         reginput = string;
876         regstartp = prog->startp;
877         regendp = prog->endp;
878
879         sp = prog->startp;
880         ep = prog->endp;
881         for (i = NSUBEXP; i > 0; i--) {
882                 *sp++ = NULL;
883                 *ep++ = NULL;
884         }
885         if (regmatch(prog->program + 1)) {
886                 prog->startp[0] = string;
887                 prog->endp[0] = reginput;
888                 return(1);
889         } else
890                 return(0);
891 }
892
893 /*
894  - regmatch - main matching routine
895  *
896  * Conceptually the strategy is simple:  check to see whether the current
897  * node matches, call self recursively to see whether the rest matches,
898  * and then act accordingly.  In practice we make some effort to avoid
899  * recursion, in particular by going through "ordinary" nodes (that don't
900  * need to know whether the rest of the match failed) by a loop instead of
901  * by recursion.
902  */
903 static int                      /* 0 failure, 1 success */
904 regmatch(prog)
905 char *prog;
906 {
907         char *scan;     /* Current node. */
908         char *next;             /* Next node. */
909
910         scan = prog;
911 #ifdef DEBUG
912         if (scan != NULL && regnarrate)
913                 fprintf(stderr, "%s(\n", regprop(scan));
914 #endif
915         while (scan != NULL) {
916 #ifdef DEBUG
917                 if (regnarrate)
918                         fprintf(stderr, "%s...\n", regprop(scan));
919 #endif
920                 next = regnext(scan);
921
922                 switch (OP(scan)) {
923                 case BOL:
924                         if (reginput != regbol)
925                                 return(0);
926                         break;
927                 case EOL:
928                         if (*reginput != '\0')
929                                 return(0);
930                         break;
931                 case WORDA:
932                         /* Must be looking at a letter, digit, or _ */
933                         if ((!isalnum((unsigned char)*reginput)) && *reginput != '_')
934                                 return(0);
935                         /* Prev must be BOL or nonword */
936                         if (reginput > regbol &&
937                             (isalnum((unsigned char)reginput[-1]) || reginput[-1] == '_'))
938                                 return(0);
939                         break;
940                 case WORDZ:
941                         /* Must be looking at non letter, digit, or _ */
942                         if (isalnum((unsigned char)*reginput) || *reginput == '_')
943                                 return(0);
944                         /* We don't care what the previous char was */
945                         break;
946                 case ANY:
947                         if (*reginput == '\0')
948                                 return(0);
949                         reginput++;
950                         break;
951                 case EXACTLY: {
952                                 int len;
953                                 char *opnd;
954
955                                 opnd = OPERAND(scan);
956                                 /* Inline the first character, for speed. */
957                                 if (*opnd != *reginput)
958                                         return(0);
959                                 len = strlen(opnd);
960                                 if (len > 1 && strncmp(opnd, reginput, len) != 0)
961                                         return(0);
962                                 reginput += len;
963                         }
964                         break;
965                 case ANYOF:
966                         if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
967                                 return(0);
968                         reginput++;
969                         break;
970                 case ANYBUT:
971                         if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
972                                 return(0);
973                         reginput++;
974                         break;
975                 case NOTHING:
976                         break;
977                 case BACK:
978                         break;
979                 case OPEN+1:
980                 case OPEN+2:
981                 case OPEN+3:
982                 case OPEN+4:
983                 case OPEN+5:
984                 case OPEN+6:
985                 case OPEN+7:
986                 case OPEN+8:
987                 case OPEN+9: {
988                                 int no;
989                                 char *save;
990
991                                 no = OP(scan) - OPEN;
992                                 save = reginput;
993
994                                 if (regmatch(next)) {
995                                         /*
996                                          * Don't set startp if some later
997                                          * invocation of the same parentheses
998                                          * already has.
999                                          */
1000                                         if (regstartp[no] == NULL)
1001                                                 regstartp[no] = save;
1002                                         return(1);
1003                                 } else
1004                                         return(0);
1005                         }
1006                         break;
1007                 case CLOSE+1:
1008                 case CLOSE+2:
1009                 case CLOSE+3:
1010                 case CLOSE+4:
1011                 case CLOSE+5:
1012                 case CLOSE+6:
1013                 case CLOSE+7:
1014                 case CLOSE+8:
1015                 case CLOSE+9: {
1016                                 int no;
1017                                 char *save;
1018
1019                                 no = OP(scan) - CLOSE;
1020                                 save = reginput;
1021
1022                                 if (regmatch(next)) {
1023                                         /*
1024                                          * Don't set endp if some later
1025                                          * invocation of the same parentheses
1026                                          * already has.
1027                                          */
1028                                         if (regendp[no] == NULL)
1029                                                 regendp[no] = save;
1030                                         return(1);
1031                                 } else
1032                                         return(0);
1033                         }
1034                         break;
1035                 case BRANCH: {
1036                                 char *save;
1037
1038                                 if (OP(next) != BRANCH)         /* No choice. */
1039                                         next = OPERAND(scan);   /* Avoid recursion. */
1040                                 else {
1041                                         do {
1042                                                 save = reginput;
1043                                                 if (regmatch(OPERAND(scan)))
1044                                                         return(1);
1045                                                 reginput = save;
1046                                                 scan = regnext(scan);
1047                                         } while (scan != NULL && OP(scan) == BRANCH);
1048                                         return(0);
1049                                         /* NOTREACHED */
1050                                 }
1051                         }
1052                         break;
1053                 case STAR:
1054                 case PLUS: {
1055                                 char nextch;
1056                                 int no;
1057                                 char *save;
1058                                 int min;
1059
1060                                 /*
1061                                  * Lookahead to avoid useless match attempts
1062                                  * when we know what character comes next.
1063                                  */
1064                                 nextch = '\0';
1065                                 if (OP(next) == EXACTLY)
1066                                         nextch = *OPERAND(next);
1067                                 min = (OP(scan) == STAR) ? 0 : 1;
1068                                 save = reginput;
1069                                 no = regrepeat(OPERAND(scan));
1070                                 while (no >= min) {
1071                                         /* If it could work, try it. */
1072                                         if (nextch == '\0' || *reginput == nextch)
1073                                                 if (regmatch(next))
1074                                                         return(1);
1075                                         /* Couldn't or didn't -- back up. */
1076                                         no--;
1077                                         reginput = save + no;
1078                                 }
1079                                 return(0);
1080                         }
1081                         break;
1082                 case END:
1083                         return(1);      /* Success! */
1084                         break;
1085                 default:
1086                         regerror("memory corruption");
1087                         return(0);
1088                         break;
1089                 }
1090
1091                 scan = next;
1092         }
1093
1094         /*
1095          * We get here only if there's trouble -- normally "case END" is
1096          * the terminating point.
1097          */
1098         regerror("corrupted pointers");
1099         return(0);
1100 }
1101
1102 /*
1103  - regrepeat - repeatedly match something simple, report how many
1104  */
1105 static int
1106 regrepeat(p)
1107 char *p;
1108 {
1109         int count = 0;
1110         char *scan;
1111         char *opnd;
1112
1113         scan = reginput;
1114         opnd = OPERAND(p);
1115         switch (OP(p)) {
1116         case ANY:
1117                 count = strlen(scan);
1118                 scan += count;
1119                 break;
1120         case EXACTLY:
1121                 while (*opnd == *scan) {
1122                         count++;
1123                         scan++;
1124                 }
1125                 break;
1126         case ANYOF:
1127                 while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
1128                         count++;
1129                         scan++;
1130                 }
1131                 break;
1132         case ANYBUT:
1133                 while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
1134                         count++;
1135                         scan++;
1136                 }
1137                 break;
1138         default:                /* Oh dear.  Called inappropriately. */
1139                 regerror("internal foulup");
1140                 count = 0;      /* Best compromise. */
1141                 break;
1142         }
1143         reginput = scan;
1144
1145         return(count);
1146 }
1147
1148 /*
1149  - regnext - dig the "next" pointer out of a node
1150  */
1151 static char *
1152 regnext(p)
1153 char *p;
1154 {
1155         int offset;
1156
1157         if (p == &regdummy)
1158                 return(NULL);
1159
1160         offset = NEXT(p);
1161         if (offset == 0)
1162                 return(NULL);
1163
1164         if (OP(p) == BACK)
1165                 return(p-offset);
1166         else
1167                 return(p+offset);
1168 }
1169
1170 #ifdef DEBUG
1171
1172 STATIC char *regprop();
1173
1174 /*
1175  - regdump - dump a regexp onto stdout in vaguely comprehensible form
1176  */
1177 void
1178 regdump(r)
1179 regexp *r;
1180 {
1181         char *s;
1182         char op = EXACTLY;      /* Arbitrary non-END op. */
1183         char *next;
1184         extern char *strchr();
1185
1186
1187         s = r->program + 1;
1188         while (op != END) {     /* While that wasn't END last time... */
1189                 op = OP(s);
1190                 printf("%2d%s", s-r->program, regprop(s));      /* Where, what. */
1191                 next = regnext(s);
1192                 if (next == NULL)               /* Next ptr. */
1193                         printf("(0)");
1194                 else
1195                         printf("(%d)", (s-r->program)+(next-s));
1196                 s += 3;
1197                 if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
1198                         /* Literal string, where present. */
1199                         while (*s != '\0') {
1200                                 putchar(*s);
1201                                 s++;
1202                         }
1203                         s++;
1204                 }
1205                 putchar('\n');
1206         }
1207
1208         /* Header fields of interest. */
1209         if (r->regstart != '\0')
1210                 printf("start `%c' ", r->regstart);
1211         if (r->reganch)
1212                 printf("anchored ");
1213         if (r->regmust != NULL)
1214                 printf("must have \"%s\"", r->regmust);
1215         printf("\n");
1216 }
1217
1218 /*
1219  - regprop - printable representation of opcode
1220  */
1221 static char *
1222 regprop(op)
1223 char *op;
1224 {
1225         char *p;
1226         static char buf[50];
1227
1228         (void) strcpy(buf, ":");
1229
1230         switch (OP(op)) {
1231         case BOL:
1232                 p = "BOL";
1233                 break;
1234         case EOL:
1235                 p = "EOL";
1236                 break;
1237         case ANY:
1238                 p = "ANY";
1239                 break;
1240         case ANYOF:
1241                 p = "ANYOF";
1242                 break;
1243         case ANYBUT:
1244                 p = "ANYBUT";
1245                 break;
1246         case BRANCH:
1247                 p = "BRANCH";
1248                 break;
1249         case EXACTLY:
1250                 p = "EXACTLY";
1251                 break;
1252         case NOTHING:
1253                 p = "NOTHING";
1254                 break;
1255         case BACK:
1256                 p = "BACK";
1257                 break;
1258         case END:
1259                 p = "END";
1260                 break;
1261         case OPEN+1:
1262         case OPEN+2:
1263         case OPEN+3:
1264         case OPEN+4:
1265         case OPEN+5:
1266         case OPEN+6:
1267         case OPEN+7:
1268         case OPEN+8:
1269         case OPEN+9:
1270                 sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
1271                 p = NULL;
1272                 break;
1273         case CLOSE+1:
1274         case CLOSE+2:
1275         case CLOSE+3:
1276         case CLOSE+4:
1277         case CLOSE+5:
1278         case CLOSE+6:
1279         case CLOSE+7:
1280         case CLOSE+8:
1281         case CLOSE+9:
1282                 sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
1283                 p = NULL;
1284                 break;
1285         case STAR:
1286                 p = "STAR";
1287                 break;
1288         case PLUS:
1289                 p = "PLUS";
1290                 break;
1291         case WORDA:
1292                 p = "WORDA";
1293                 break;
1294         case WORDZ:
1295                 p = "WORDZ";
1296                 break;
1297         default:
1298                 regerror("corrupted opcode");
1299                 break;
1300         }
1301         if (p != NULL)
1302                 (void) strcat(buf, p);
1303         return(buf);
1304 }
1305 #endif
1306
1307 /*
1308  * The following is provided for those people who do not have strcspn() in
1309  * their C libraries.  They should get off their butts and do something
1310  * about it; at least one public-domain implementation of those (highly
1311  * useful) string routines has been published on Usenet.
1312  */
1313 #ifdef STRCSPN
1314 /*
1315  * strcspn - find length of initial segment of s1 consisting entirely
1316  * of characters not from s2
1317  */
1318
1319 static int
1320 strcspn(s1, s2)
1321 char *s1;
1322 char *s2;
1323 {
1324         char *scan1;
1325         char *scan2;
1326         int count;
1327
1328         count = 0;
1329         for (scan1 = s1; *scan1 != '\0'; scan1++) {
1330                 for (scan2 = s2; *scan2 != '\0';)       /* ++ moved down. */
1331                         if (*scan1 == *scan2++)
1332                                 return(count);
1333                 count++;
1334         }
1335         return(count);
1336 }
1337 #endif