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