xref: /original-bsd/lib/libc/regex/regexec.c (revision a6d8c59f)
1 /*-
2  * Copyright (c) 1992 Henry Spencer.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Henry Spencer of the University of Toronto.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)regexec.c	5.3 (Berkeley) 09/30/92
12  */
13 
14 #if defined(LIBC_SCCS) && !defined(lint)
15 static char sccsid[] = "@(#)regexec.c	5.3 (Berkeley) 09/30/92";
16 #endif /* LIBC_SCCS and not lint */
17 
18 /*
19  * the outer shell of regexec()
20  *
21  * This file includes engine.c *twice*, after muchos fiddling with the
22  * macros that code uses.  This lets the same code operate on two different
23  * representations for state sets.
24  */
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <ctype.h>
31 #include <regex.h>
32 
33 #include "utils.h"
34 #include "regex2.h"
35 
36 /* macros for manipulating states, small version */
37 #define	states	long
38 #define	states1	states		/* for later use in regexec() decision */
39 #define	CLEAR(v)	((v) = 0)
40 #define	SET0(v, n)	((v) &= ~(1 << (n)))
41 #define	SET1(v, n)	((v) |= 1 << (n))
42 #define	ISSET(v, n)	((v) & (1 << (n)))
43 #define	ASSIGN(d, s)	((d) = (s))
44 #define	EQ(a, b)	((a) == (b))
45 #define	STATEVARS	int dummy	/* dummy version */
46 #define	STATESETUP(m, n)	/* nothing */
47 #define	STATETEARDOWN(m)	/* nothing */
48 #define	SETUP(v)	((v) = 0)
49 #define	onestate	int
50 #define	INIT(o, n)	((o) = 1 << (n))
51 #define	INC(o)	((o) <<= 1)
52 #define	ISSTATEIN(v, o)	((v) & (o))
53 /* some abbreviations; note that some of these know variable names! */
54 /* do "if I'm here, I can also be there" etc without branches */
55 #define	FWD(dst, src, n)	((dst) |= ((src)&(here)) << (n))
56 #define	BACK(dst, src, n)	((dst) |= ((src)&(here)) >> (n))
57 #define	ISSETBACK(v, n)	((v) & (here >> (n)))
58 /* function names */
59 #define SNAMES			/* engine.c looks after details */
60 
61 #include "engine.c"
62 
63 /* now undo things */
64 #undef	states
65 #undef	CLEAR
66 #undef	SET0
67 #undef	SET1
68 #undef	ISSET
69 #undef	ASSIGN
70 #undef	EQ
71 #undef	STATEVARS
72 #undef	STATESETUP
73 #undef	STATETEARDOWN
74 #undef	SETUP
75 #undef	onestate
76 #undef	INIT
77 #undef	INC
78 #undef	ISSTATEIN
79 #undef	FWD
80 #undef	BACK
81 #undef	ISSETBACK
82 #undef	SNAMES
83 
84 /* macros for manipulating states, large version */
85 #define	states	char *
86 #define	CLEAR(v)	memset(v, 0, m->g->nstates)
87 #define	SET0(v, n)	((v)[n] = 0)
88 #define	SET1(v, n)	((v)[n] = 1)
89 #define	ISSET(v, n)	((v)[n])
90 #define	ASSIGN(d, s)	memcpy(d, s, m->g->nstates)
91 #define	EQ(a, b)	(memcmp(a, b, m->g->nstates) == 0)
92 #define	STATEVARS	int vn; char *space
93 #define	STATESETUP(m, nv)	{ (m)->space = malloc((nv)*(m)->g->nstates); \
94 				if ((m)->space == NULL) return(REG_ESPACE); \
95 				(m)->vn = 0; }
96 #define	STATETEARDOWN(m)	{ free((m)->space); }
97 #define	SETUP(v)	((v) = &m->space[m->vn++ * m->g->nstates])
98 #define	onestate	int
99 #define	INIT(o, n)	((o) = (n))
100 #define	INC(o)	((o)++)
101 #define	ISSTATEIN(v, o)	((v)[o])
102 /* some abbreviations; note that some of these know variable names! */
103 /* do "if I'm here, I can also be there" etc without branches */
104 #define	FWD(dst, src, n)	((dst)[here+(n)] |= (src)[here])
105 #define	BACK(dst, src, n)	((dst)[here-(n)] |= (src)[here])
106 #define	ISSETBACK(v, n)	((v)[here - (n)])
107 /* function names */
108 #define	LNAMES			/* flag */
109 
110 #include "engine.c"
111 
112 /*
113  - regexec - interface for matching
114  *
115  * We put this here so we can exploit knowledge of the state representation
116  * when choosing which matcher to call.  Also, by this point the matchers
117  * have been prototyped.
118  */
119 int				/* 0 success, REG_NOMATCH failure */
120 regexec(preg, string, nmatch, pmatch, eflags)
121 const regex_t *preg;
122 const char *string;
123 size_t nmatch;
124 regmatch_t pmatch[];
125 int eflags;
126 {
127 	register struct re_guts *g = preg->re_g;
128 #ifdef REDEBUG
129 #	define	GOODFLAGS(f)	(f)
130 #else
131 #	define	GOODFLAGS(f)	((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
132 #endif
133 
134 	if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
135 		return(REG_BADPAT);
136 	assert(!(g->iflags&BAD));
137 	if (g->iflags&BAD)		/* backstop for no-debug case */
138 		return(REG_BADPAT);
139 	eflags = GOODFLAGS(eflags);	/* xxx should we complain? */
140 
141 	if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
142 		return(smatcher(g, (uchar *)string, nmatch, pmatch, eflags));
143 	else
144 		return(lmatcher(g, (uchar *)string, nmatch, pmatch, eflags));
145 }
146