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