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