xref: /freebsd/contrib/less/regexp.c (revision fa0dc4f0f96a1b77d4be7bcdbf965897cda14521)
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; &regdummy = 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 = &regdummy;
225 	regc(MAGIC);
226 	if (reg(0, &flags) == NULL)
227 		return(NULL);
228 
229 	/* Small enough for pointer-storage convention? */
230 	if (regsize >= 32767L)		/* Probably could be 65535L. */
231 		FAIL("regexp too big");
232 
233 	/* Allocate space. */
234 	r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
235 	if (r == NULL)
236 		FAIL("out of space");
237 
238 	/* Second pass: emit code. */
239 	regparse = 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 == &regdummy) {
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 != &regdummy)
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 == &regdummy) {
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 == &regdummy)
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 == &regdummy || 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 == &regdummy)
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