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