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