Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/jam_src/regexp.c @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

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