/src/postgres/src/backend/regex/regc_lex.c
Line | Count | Source |
1 | | /* |
2 | | * lexical analyzer |
3 | | * This file is #included by regcomp.c. |
4 | | * |
5 | | * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. |
6 | | * |
7 | | * Development of this software was funded, in part, by Cray Research Inc., |
8 | | * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics |
9 | | * Corporation, none of whom are responsible for the results. The author |
10 | | * thanks all of them. |
11 | | * |
12 | | * Redistribution and use in source and binary forms -- with or without |
13 | | * modification -- are permitted for any purpose, provided that |
14 | | * redistributions in source form retain this entire copyright notice and |
15 | | * indicate the origin and nature of any modifications. |
16 | | * |
17 | | * I'd appreciate being given credit for this package in the documentation |
18 | | * of software which uses it, but that is not a requirement. |
19 | | * |
20 | | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
21 | | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
22 | | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
23 | | * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
24 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
25 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
26 | | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
27 | | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
28 | | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
29 | | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | | * |
31 | | * src/backend/regex/regc_lex.c |
32 | | * |
33 | | */ |
34 | | |
35 | | /* scanning macros (know about v) */ |
36 | 0 | #define ATEOS() (v->now >= v->stop) |
37 | 0 | #define HAVE(n) (v->stop - v->now >= (n)) |
38 | 0 | #define NEXT1(c) (!ATEOS() && *v->now == CHR(c)) |
39 | 0 | #define NEXT2(a,b) (HAVE(2) && *v->now == CHR(a) && *(v->now+1) == CHR(b)) |
40 | 0 | #define NEXT3(a,b,c) (HAVE(3) && *v->now == CHR(a) && \ |
41 | 0 | *(v->now+1) == CHR(b) && \ |
42 | 0 | *(v->now+2) == CHR(c)) |
43 | 0 | #define SET(c) (v->nexttype = (c)) |
44 | 0 | #define SETV(c, n) (v->nexttype = (c), v->nextvalue = (n)) |
45 | 0 | #define RET(c) return (SET(c), 1) |
46 | 0 | #define RETV(c, n) return (SETV(c, n), 1) |
47 | 0 | #define FAILW(e) return (ERR(e), 0) /* ERR does SET(EOS) */ |
48 | 0 | #define LASTTYPE(t) (v->lasttype == (t)) |
49 | | |
50 | | /* lexical contexts */ |
51 | 0 | #define L_ERE 1 /* mainline ERE/ARE */ |
52 | 0 | #define L_BRE 2 /* mainline BRE */ |
53 | 0 | #define L_Q 3 /* REG_QUOTE */ |
54 | 0 | #define L_EBND 4 /* ERE/ARE bound */ |
55 | 0 | #define L_BBND 5 /* BRE bound */ |
56 | 0 | #define L_BRACK 6 /* brackets */ |
57 | 0 | #define L_CEL 7 /* collating element */ |
58 | 0 | #define L_ECL 8 /* equivalence class */ |
59 | 0 | #define L_CCL 9 /* character class */ |
60 | 0 | #define INTOCON(c) (v->lexcon = (c)) |
61 | 0 | #define INCON(con) (v->lexcon == (con)) |
62 | | |
63 | | /* construct pointer past end of chr array */ |
64 | | #define ENDOF(array) ((array) + sizeof(array)/sizeof(chr)) |
65 | | |
66 | | /* |
67 | | * lexstart - set up lexical stuff, scan leading options |
68 | | */ |
69 | | static void |
70 | | lexstart(struct vars *v) |
71 | 0 | { |
72 | 0 | prefixes(v); /* may turn on new type bits etc. */ |
73 | 0 | NOERR(); |
74 | |
|
75 | 0 | if (v->cflags & REG_QUOTE) |
76 | 0 | { |
77 | 0 | assert(!(v->cflags & (REG_ADVANCED | REG_EXPANDED | REG_NEWLINE))); |
78 | 0 | INTOCON(L_Q); |
79 | 0 | } |
80 | 0 | else if (v->cflags & REG_EXTENDED) |
81 | 0 | { |
82 | 0 | assert(!(v->cflags & REG_QUOTE)); |
83 | 0 | INTOCON(L_ERE); |
84 | 0 | } |
85 | 0 | else |
86 | 0 | { |
87 | 0 | assert(!(v->cflags & (REG_QUOTE | REG_ADVF))); |
88 | 0 | INTOCON(L_BRE); |
89 | 0 | } |
90 | |
|
91 | 0 | v->nexttype = EMPTY; /* remember we were at the start */ |
92 | 0 | next(v); /* set up the first token */ |
93 | 0 | } |
94 | | |
95 | | /* |
96 | | * prefixes - implement various special prefixes |
97 | | */ |
98 | | static void |
99 | | prefixes(struct vars *v) |
100 | 0 | { |
101 | | /* literal string doesn't get any of this stuff */ |
102 | 0 | if (v->cflags & REG_QUOTE) |
103 | 0 | return; |
104 | | |
105 | | /* initial "***" gets special things */ |
106 | 0 | if (HAVE(4) && NEXT3('*', '*', '*')) |
107 | 0 | switch (*(v->now + 3)) |
108 | 0 | { |
109 | 0 | case CHR('?'): /* "***?" error, msg shows version */ |
110 | 0 | ERR(REG_BADPAT); |
111 | 0 | return; /* proceed no further */ |
112 | 0 | break; |
113 | 0 | case CHR('='): /* "***=" shifts to literal string */ |
114 | 0 | NOTE(REG_UNONPOSIX); |
115 | 0 | v->cflags |= REG_QUOTE; |
116 | 0 | v->cflags &= ~(REG_ADVANCED | REG_EXPANDED | REG_NEWLINE); |
117 | 0 | v->now += 4; |
118 | 0 | return; /* and there can be no more prefixes */ |
119 | 0 | break; |
120 | 0 | case CHR(':'): /* "***:" shifts to AREs */ |
121 | 0 | NOTE(REG_UNONPOSIX); |
122 | 0 | v->cflags |= REG_ADVANCED; |
123 | 0 | v->now += 4; |
124 | 0 | break; |
125 | 0 | default: /* otherwise *** is just an error */ |
126 | 0 | ERR(REG_BADRPT); |
127 | 0 | return; |
128 | 0 | break; |
129 | 0 | } |
130 | | |
131 | | /* BREs and EREs don't get embedded options */ |
132 | 0 | if ((v->cflags & REG_ADVANCED) != REG_ADVANCED) |
133 | 0 | return; |
134 | | |
135 | | /* embedded options (AREs only) */ |
136 | 0 | if (HAVE(3) && NEXT2('(', '?') && iscalpha(*(v->now + 2))) |
137 | 0 | { |
138 | 0 | NOTE(REG_UNONPOSIX); |
139 | 0 | v->now += 2; |
140 | 0 | for (; !ATEOS() && iscalpha(*v->now); v->now++) |
141 | 0 | switch (*v->now) |
142 | 0 | { |
143 | 0 | case CHR('b'): /* BREs (but why???) */ |
144 | 0 | v->cflags &= ~(REG_ADVANCED | REG_QUOTE); |
145 | 0 | break; |
146 | 0 | case CHR('c'): /* case sensitive */ |
147 | 0 | v->cflags &= ~REG_ICASE; |
148 | 0 | break; |
149 | 0 | case CHR('e'): /* plain EREs */ |
150 | 0 | v->cflags |= REG_EXTENDED; |
151 | 0 | v->cflags &= ~(REG_ADVF | REG_QUOTE); |
152 | 0 | break; |
153 | 0 | case CHR('i'): /* case insensitive */ |
154 | 0 | v->cflags |= REG_ICASE; |
155 | 0 | break; |
156 | 0 | case CHR('m'): /* Perloid synonym for n */ |
157 | 0 | case CHR('n'): /* \n affects ^ $ . [^ */ |
158 | 0 | v->cflags |= REG_NEWLINE; |
159 | 0 | break; |
160 | 0 | case CHR('p'): /* ~Perl, \n affects . [^ */ |
161 | 0 | v->cflags |= REG_NLSTOP; |
162 | 0 | v->cflags &= ~REG_NLANCH; |
163 | 0 | break; |
164 | 0 | case CHR('q'): /* literal string */ |
165 | 0 | v->cflags |= REG_QUOTE; |
166 | 0 | v->cflags &= ~REG_ADVANCED; |
167 | 0 | break; |
168 | 0 | case CHR('s'): /* single line, \n ordinary */ |
169 | 0 | v->cflags &= ~REG_NEWLINE; |
170 | 0 | break; |
171 | 0 | case CHR('t'): /* tight syntax */ |
172 | 0 | v->cflags &= ~REG_EXPANDED; |
173 | 0 | break; |
174 | 0 | case CHR('w'): /* weird, \n affects ^ $ only */ |
175 | 0 | v->cflags &= ~REG_NLSTOP; |
176 | 0 | v->cflags |= REG_NLANCH; |
177 | 0 | break; |
178 | 0 | case CHR('x'): /* expanded syntax */ |
179 | 0 | v->cflags |= REG_EXPANDED; |
180 | 0 | break; |
181 | 0 | default: |
182 | 0 | ERR(REG_BADOPT); |
183 | 0 | return; |
184 | 0 | } |
185 | 0 | if (!NEXT1(')')) |
186 | 0 | { |
187 | 0 | ERR(REG_BADOPT); |
188 | 0 | return; |
189 | 0 | } |
190 | 0 | v->now++; |
191 | 0 | if (v->cflags & REG_QUOTE) |
192 | 0 | v->cflags &= ~(REG_EXPANDED | REG_NEWLINE); |
193 | 0 | } |
194 | 0 | } |
195 | | |
196 | | /* |
197 | | * next - get next token |
198 | | */ |
199 | | static int /* 1 normal, 0 failure */ |
200 | | next(struct vars *v) |
201 | 0 | { |
202 | 0 | chr c; |
203 | |
|
204 | 0 | next_restart: /* loop here after eating a comment */ |
205 | | |
206 | | /* errors yield an infinite sequence of failures */ |
207 | 0 | if (ISERR()) |
208 | 0 | return 0; /* the error has set nexttype to EOS */ |
209 | | |
210 | | /* remember flavor of last token */ |
211 | 0 | v->lasttype = v->nexttype; |
212 | | |
213 | | /* REG_BOSONLY */ |
214 | 0 | if (v->nexttype == EMPTY && (v->cflags & REG_BOSONLY)) |
215 | 0 | { |
216 | | /* at start of a REG_BOSONLY RE */ |
217 | 0 | RETV(SBEGIN, 0); /* same as \A */ |
218 | 0 | } |
219 | | |
220 | | /* skip white space etc. if appropriate (not in literal or []) */ |
221 | 0 | if (v->cflags & REG_EXPANDED) |
222 | 0 | switch (v->lexcon) |
223 | 0 | { |
224 | 0 | case L_ERE: |
225 | 0 | case L_BRE: |
226 | 0 | case L_EBND: |
227 | 0 | case L_BBND: |
228 | 0 | skip(v); |
229 | 0 | break; |
230 | 0 | } |
231 | | |
232 | | /* handle EOS, depending on context */ |
233 | 0 | if (ATEOS()) |
234 | 0 | { |
235 | 0 | switch (v->lexcon) |
236 | 0 | { |
237 | 0 | case L_ERE: |
238 | 0 | case L_BRE: |
239 | 0 | case L_Q: |
240 | 0 | RET(EOS); |
241 | 0 | break; |
242 | 0 | case L_EBND: |
243 | 0 | case L_BBND: |
244 | 0 | FAILW(REG_EBRACE); |
245 | 0 | break; |
246 | 0 | case L_BRACK: |
247 | 0 | case L_CEL: |
248 | 0 | case L_ECL: |
249 | 0 | case L_CCL: |
250 | 0 | FAILW(REG_EBRACK); |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | assert(NOTREACHED); |
254 | 0 | } |
255 | | |
256 | | /* okay, time to actually get a character */ |
257 | 0 | c = *v->now++; |
258 | | |
259 | | /* deal with the easy contexts, punt EREs to code below */ |
260 | 0 | switch (v->lexcon) |
261 | 0 | { |
262 | 0 | case L_BRE: /* punt BREs to separate function */ |
263 | 0 | return brenext(v, c); |
264 | 0 | break; |
265 | 0 | case L_ERE: /* see below */ |
266 | 0 | break; |
267 | 0 | case L_Q: /* literal strings are easy */ |
268 | 0 | RETV(PLAIN, c); |
269 | 0 | break; |
270 | 0 | case L_BBND: /* bounds are fairly simple */ |
271 | 0 | case L_EBND: |
272 | 0 | switch (c) |
273 | 0 | { |
274 | 0 | case CHR('0'): |
275 | 0 | case CHR('1'): |
276 | 0 | case CHR('2'): |
277 | 0 | case CHR('3'): |
278 | 0 | case CHR('4'): |
279 | 0 | case CHR('5'): |
280 | 0 | case CHR('6'): |
281 | 0 | case CHR('7'): |
282 | 0 | case CHR('8'): |
283 | 0 | case CHR('9'): |
284 | 0 | RETV(DIGIT, (chr) DIGITVAL(c)); |
285 | 0 | break; |
286 | 0 | case CHR(','): |
287 | 0 | RET(','); |
288 | 0 | break; |
289 | 0 | case CHR('}'): /* ERE bound ends with } */ |
290 | 0 | if (INCON(L_EBND)) |
291 | 0 | { |
292 | 0 | INTOCON(L_ERE); |
293 | 0 | if ((v->cflags & REG_ADVF) && NEXT1('?')) |
294 | 0 | { |
295 | 0 | v->now++; |
296 | 0 | NOTE(REG_UNONPOSIX); |
297 | 0 | RETV('}', 0); |
298 | 0 | } |
299 | 0 | RETV('}', 1); |
300 | 0 | } |
301 | 0 | else |
302 | 0 | FAILW(REG_BADBR); |
303 | 0 | break; |
304 | 0 | case CHR('\\'): /* BRE bound ends with \} */ |
305 | 0 | if (INCON(L_BBND) && NEXT1('}')) |
306 | 0 | { |
307 | 0 | v->now++; |
308 | 0 | INTOCON(L_BRE); |
309 | 0 | RETV('}', 1); |
310 | 0 | } |
311 | 0 | else |
312 | 0 | FAILW(REG_BADBR); |
313 | 0 | break; |
314 | 0 | default: |
315 | 0 | FAILW(REG_BADBR); |
316 | 0 | break; |
317 | 0 | } |
318 | 0 | assert(NOTREACHED); |
319 | 0 | break; |
320 | 0 | case L_BRACK: /* brackets are not too hard */ |
321 | 0 | switch (c) |
322 | 0 | { |
323 | 0 | case CHR(']'): |
324 | 0 | if (LASTTYPE('[')) |
325 | 0 | RETV(PLAIN, c); |
326 | 0 | else |
327 | 0 | { |
328 | 0 | INTOCON((v->cflags & REG_EXTENDED) ? |
329 | 0 | L_ERE : L_BRE); |
330 | 0 | RET(']'); |
331 | 0 | } |
332 | 0 | break; |
333 | 0 | case CHR('\\'): |
334 | 0 | NOTE(REG_UBBS); |
335 | 0 | if (!(v->cflags & REG_ADVF)) |
336 | 0 | RETV(PLAIN, c); |
337 | 0 | NOTE(REG_UNONPOSIX); |
338 | 0 | if (ATEOS()) |
339 | 0 | FAILW(REG_EESCAPE); |
340 | 0 | if (!lexescape(v)) |
341 | 0 | return 0; |
342 | 0 | switch (v->nexttype) |
343 | 0 | { /* not all escapes okay here */ |
344 | 0 | case PLAIN: |
345 | 0 | case CCLASSS: |
346 | 0 | case CCLASSC: |
347 | 0 | return 1; |
348 | 0 | break; |
349 | 0 | } |
350 | | /* not one of the acceptable escapes */ |
351 | 0 | FAILW(REG_EESCAPE); |
352 | 0 | break; |
353 | 0 | case CHR('-'): |
354 | 0 | if (LASTTYPE('[') || NEXT1(']')) |
355 | 0 | RETV(PLAIN, c); |
356 | 0 | else |
357 | 0 | RETV(RANGE, c); |
358 | 0 | break; |
359 | 0 | case CHR('['): |
360 | 0 | if (ATEOS()) |
361 | 0 | FAILW(REG_EBRACK); |
362 | 0 | switch (*v->now++) |
363 | 0 | { |
364 | 0 | case CHR('.'): |
365 | 0 | INTOCON(L_CEL); |
366 | | /* might or might not be locale-specific */ |
367 | 0 | RET(COLLEL); |
368 | 0 | break; |
369 | 0 | case CHR('='): |
370 | 0 | INTOCON(L_ECL); |
371 | 0 | NOTE(REG_ULOCALE); |
372 | 0 | RET(ECLASS); |
373 | 0 | break; |
374 | 0 | case CHR(':'): |
375 | 0 | INTOCON(L_CCL); |
376 | 0 | NOTE(REG_ULOCALE); |
377 | 0 | RET(CCLASS); |
378 | 0 | break; |
379 | 0 | default: /* oops */ |
380 | 0 | v->now--; |
381 | 0 | RETV(PLAIN, c); |
382 | 0 | break; |
383 | 0 | } |
384 | 0 | assert(NOTREACHED); |
385 | 0 | break; |
386 | 0 | default: |
387 | 0 | RETV(PLAIN, c); |
388 | 0 | break; |
389 | 0 | } |
390 | 0 | assert(NOTREACHED); |
391 | 0 | break; |
392 | 0 | case L_CEL: /* collating elements are easy */ |
393 | 0 | if (c == CHR('.') && NEXT1(']')) |
394 | 0 | { |
395 | 0 | v->now++; |
396 | 0 | INTOCON(L_BRACK); |
397 | 0 | RETV(END, '.'); |
398 | 0 | } |
399 | 0 | else |
400 | 0 | RETV(PLAIN, c); |
401 | 0 | break; |
402 | 0 | case L_ECL: /* ditto equivalence classes */ |
403 | 0 | if (c == CHR('=') && NEXT1(']')) |
404 | 0 | { |
405 | 0 | v->now++; |
406 | 0 | INTOCON(L_BRACK); |
407 | 0 | RETV(END, '='); |
408 | 0 | } |
409 | 0 | else |
410 | 0 | RETV(PLAIN, c); |
411 | 0 | break; |
412 | 0 | case L_CCL: /* ditto character classes */ |
413 | 0 | if (c == CHR(':') && NEXT1(']')) |
414 | 0 | { |
415 | 0 | v->now++; |
416 | 0 | INTOCON(L_BRACK); |
417 | 0 | RETV(END, ':'); |
418 | 0 | } |
419 | 0 | else |
420 | 0 | RETV(PLAIN, c); |
421 | 0 | break; |
422 | 0 | default: |
423 | 0 | assert(NOTREACHED); |
424 | 0 | break; |
425 | 0 | } |
426 | | |
427 | | /* that got rid of everything except EREs and AREs */ |
428 | 0 | assert(INCON(L_ERE)); |
429 | | |
430 | | /* deal with EREs and AREs, except for backslashes */ |
431 | 0 | switch (c) |
432 | 0 | { |
433 | 0 | case CHR('|'): |
434 | 0 | RET('|'); |
435 | 0 | break; |
436 | 0 | case CHR('*'): |
437 | 0 | if ((v->cflags & REG_ADVF) && NEXT1('?')) |
438 | 0 | { |
439 | 0 | v->now++; |
440 | 0 | NOTE(REG_UNONPOSIX); |
441 | 0 | RETV('*', 0); |
442 | 0 | } |
443 | 0 | RETV('*', 1); |
444 | 0 | break; |
445 | 0 | case CHR('+'): |
446 | 0 | if ((v->cflags & REG_ADVF) && NEXT1('?')) |
447 | 0 | { |
448 | 0 | v->now++; |
449 | 0 | NOTE(REG_UNONPOSIX); |
450 | 0 | RETV('+', 0); |
451 | 0 | } |
452 | 0 | RETV('+', 1); |
453 | 0 | break; |
454 | 0 | case CHR('?'): |
455 | 0 | if ((v->cflags & REG_ADVF) && NEXT1('?')) |
456 | 0 | { |
457 | 0 | v->now++; |
458 | 0 | NOTE(REG_UNONPOSIX); |
459 | 0 | RETV('?', 0); |
460 | 0 | } |
461 | 0 | RETV('?', 1); |
462 | 0 | break; |
463 | 0 | case CHR('{'): /* bounds start or plain character */ |
464 | 0 | if (v->cflags & REG_EXPANDED) |
465 | 0 | skip(v); |
466 | 0 | if (ATEOS() || !iscdigit(*v->now)) |
467 | 0 | { |
468 | 0 | NOTE(REG_UBRACES); |
469 | 0 | NOTE(REG_UUNSPEC); |
470 | 0 | RETV(PLAIN, c); |
471 | 0 | } |
472 | 0 | else |
473 | 0 | { |
474 | 0 | NOTE(REG_UBOUNDS); |
475 | 0 | INTOCON(L_EBND); |
476 | 0 | RET('{'); |
477 | 0 | } |
478 | 0 | assert(NOTREACHED); |
479 | 0 | break; |
480 | 0 | case CHR('('): /* parenthesis, or advanced extension */ |
481 | 0 | if ((v->cflags & REG_ADVF) && NEXT1('?')) |
482 | 0 | { |
483 | 0 | NOTE(REG_UNONPOSIX); |
484 | 0 | v->now++; |
485 | 0 | if (ATEOS()) |
486 | 0 | FAILW(REG_BADRPT); |
487 | 0 | switch (*v->now++) |
488 | 0 | { |
489 | 0 | case CHR(':'): /* non-capturing paren */ |
490 | 0 | RETV('(', 0); |
491 | 0 | break; |
492 | 0 | case CHR('#'): /* comment */ |
493 | 0 | while (!ATEOS() && *v->now != CHR(')')) |
494 | 0 | v->now++; |
495 | 0 | if (!ATEOS()) |
496 | 0 | v->now++; |
497 | 0 | assert(v->nexttype == v->lasttype); |
498 | 0 | goto next_restart; |
499 | 0 | case CHR('='): /* positive lookahead */ |
500 | 0 | NOTE(REG_ULOOKAROUND); |
501 | 0 | RETV(LACON, LATYPE_AHEAD_POS); |
502 | 0 | break; |
503 | 0 | case CHR('!'): /* negative lookahead */ |
504 | 0 | NOTE(REG_ULOOKAROUND); |
505 | 0 | RETV(LACON, LATYPE_AHEAD_NEG); |
506 | 0 | break; |
507 | 0 | case CHR('<'): |
508 | 0 | if (ATEOS()) |
509 | 0 | FAILW(REG_BADRPT); |
510 | 0 | switch (*v->now++) |
511 | 0 | { |
512 | 0 | case CHR('='): /* positive lookbehind */ |
513 | 0 | NOTE(REG_ULOOKAROUND); |
514 | 0 | RETV(LACON, LATYPE_BEHIND_POS); |
515 | 0 | break; |
516 | 0 | case CHR('!'): /* negative lookbehind */ |
517 | 0 | NOTE(REG_ULOOKAROUND); |
518 | 0 | RETV(LACON, LATYPE_BEHIND_NEG); |
519 | 0 | break; |
520 | 0 | default: |
521 | 0 | FAILW(REG_BADRPT); |
522 | 0 | break; |
523 | 0 | } |
524 | 0 | assert(NOTREACHED); |
525 | 0 | break; |
526 | 0 | default: |
527 | 0 | FAILW(REG_BADRPT); |
528 | 0 | break; |
529 | 0 | } |
530 | 0 | assert(NOTREACHED); |
531 | 0 | } |
532 | 0 | RETV('(', 1); |
533 | 0 | break; |
534 | 0 | case CHR(')'): |
535 | 0 | if (LASTTYPE('(')) |
536 | 0 | NOTE(REG_UUNSPEC); |
537 | 0 | RETV(')', c); |
538 | 0 | break; |
539 | 0 | case CHR('['): /* easy except for [[:<:]] and [[:>:]] */ |
540 | 0 | if (HAVE(6) && *(v->now + 0) == CHR('[') && |
541 | 0 | *(v->now + 1) == CHR(':') && |
542 | 0 | (*(v->now + 2) == CHR('<') || |
543 | 0 | *(v->now + 2) == CHR('>')) && |
544 | 0 | *(v->now + 3) == CHR(':') && |
545 | 0 | *(v->now + 4) == CHR(']') && |
546 | 0 | *(v->now + 5) == CHR(']')) |
547 | 0 | { |
548 | 0 | c = *(v->now + 2); |
549 | 0 | v->now += 6; |
550 | 0 | NOTE(REG_UNONPOSIX); |
551 | 0 | RET((c == CHR('<')) ? '<' : '>'); |
552 | 0 | } |
553 | 0 | INTOCON(L_BRACK); |
554 | 0 | if (NEXT1('^')) |
555 | 0 | { |
556 | 0 | v->now++; |
557 | 0 | RETV('[', 0); |
558 | 0 | } |
559 | 0 | RETV('[', 1); |
560 | 0 | break; |
561 | 0 | case CHR('.'): |
562 | 0 | RET('.'); |
563 | 0 | break; |
564 | 0 | case CHR('^'): |
565 | 0 | RET('^'); |
566 | 0 | break; |
567 | 0 | case CHR('$'): |
568 | 0 | RET('$'); |
569 | 0 | break; |
570 | 0 | case CHR('\\'): /* mostly punt backslashes to code below */ |
571 | 0 | if (ATEOS()) |
572 | 0 | FAILW(REG_EESCAPE); |
573 | 0 | break; |
574 | 0 | default: /* ordinary character */ |
575 | 0 | RETV(PLAIN, c); |
576 | 0 | break; |
577 | 0 | } |
578 | | |
579 | | /* ERE/ARE backslash handling; backslash already eaten */ |
580 | 0 | assert(!ATEOS()); |
581 | 0 | if (!(v->cflags & REG_ADVF)) |
582 | 0 | { /* only AREs have non-trivial escapes */ |
583 | 0 | if (iscalnum(*v->now)) |
584 | 0 | { |
585 | 0 | NOTE(REG_UBSALNUM); |
586 | 0 | NOTE(REG_UUNSPEC); |
587 | 0 | } |
588 | 0 | RETV(PLAIN, *v->now++); |
589 | 0 | } |
590 | 0 | return lexescape(v); |
591 | 0 | } |
592 | | |
593 | | /* |
594 | | * lexescape - parse an ARE backslash escape (backslash already eaten) |
595 | | * |
596 | | * This is used for ARE backslashes both normally and inside bracket |
597 | | * expressions. In the latter case, not all escape types are allowed, |
598 | | * but the caller must reject unwanted ones after we return. |
599 | | */ |
600 | | static int |
601 | | lexescape(struct vars *v) |
602 | 0 | { |
603 | 0 | chr c; |
604 | 0 | static const chr alert[] = { |
605 | 0 | CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t') |
606 | 0 | }; |
607 | 0 | static const chr esc[] = { |
608 | 0 | CHR('E'), CHR('S'), CHR('C') |
609 | 0 | }; |
610 | 0 | const chr *save; |
611 | |
|
612 | 0 | assert(v->cflags & REG_ADVF); |
613 | |
|
614 | 0 | assert(!ATEOS()); |
615 | 0 | c = *v->now++; |
616 | | |
617 | | /* if it's not alphanumeric ASCII, treat it as a plain character */ |
618 | 0 | if (!('a' <= c && c <= 'z') && |
619 | 0 | !('A' <= c && c <= 'Z') && |
620 | 0 | !('0' <= c && c <= '9')) |
621 | 0 | RETV(PLAIN, c); |
622 | | |
623 | 0 | NOTE(REG_UNONPOSIX); |
624 | 0 | switch (c) |
625 | 0 | { |
626 | 0 | case CHR('a'): |
627 | 0 | RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007'))); |
628 | 0 | break; |
629 | 0 | case CHR('A'): |
630 | 0 | RETV(SBEGIN, 0); |
631 | 0 | break; |
632 | 0 | case CHR('b'): |
633 | 0 | RETV(PLAIN, CHR('\b')); |
634 | 0 | break; |
635 | 0 | case CHR('B'): |
636 | 0 | RETV(PLAIN, CHR('\\')); |
637 | 0 | break; |
638 | 0 | case CHR('c'): |
639 | 0 | NOTE(REG_UUNPORT); |
640 | 0 | if (ATEOS()) |
641 | 0 | FAILW(REG_EESCAPE); |
642 | 0 | RETV(PLAIN, (chr) (*v->now++ & 037)); |
643 | 0 | break; |
644 | 0 | case CHR('d'): |
645 | 0 | NOTE(REG_ULOCALE); |
646 | 0 | RETV(CCLASSS, CC_DIGIT); |
647 | 0 | break; |
648 | 0 | case CHR('D'): |
649 | 0 | NOTE(REG_ULOCALE); |
650 | 0 | RETV(CCLASSC, CC_DIGIT); |
651 | 0 | break; |
652 | 0 | case CHR('e'): |
653 | 0 | NOTE(REG_UUNPORT); |
654 | 0 | RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033'))); |
655 | 0 | break; |
656 | 0 | case CHR('f'): |
657 | 0 | RETV(PLAIN, CHR('\f')); |
658 | 0 | break; |
659 | 0 | case CHR('m'): |
660 | 0 | RET('<'); |
661 | 0 | break; |
662 | 0 | case CHR('M'): |
663 | 0 | RET('>'); |
664 | 0 | break; |
665 | 0 | case CHR('n'): |
666 | 0 | RETV(PLAIN, CHR('\n')); |
667 | 0 | break; |
668 | 0 | case CHR('r'): |
669 | 0 | RETV(PLAIN, CHR('\r')); |
670 | 0 | break; |
671 | 0 | case CHR('s'): |
672 | 0 | NOTE(REG_ULOCALE); |
673 | 0 | RETV(CCLASSS, CC_SPACE); |
674 | 0 | break; |
675 | 0 | case CHR('S'): |
676 | 0 | NOTE(REG_ULOCALE); |
677 | 0 | RETV(CCLASSC, CC_SPACE); |
678 | 0 | break; |
679 | 0 | case CHR('t'): |
680 | 0 | RETV(PLAIN, CHR('\t')); |
681 | 0 | break; |
682 | 0 | case CHR('u'): |
683 | 0 | c = lexdigits(v, 16, 4, 4); |
684 | 0 | if (ISERR() || !CHR_IS_IN_RANGE(c)) |
685 | 0 | FAILW(REG_EESCAPE); |
686 | 0 | RETV(PLAIN, c); |
687 | 0 | break; |
688 | 0 | case CHR('U'): |
689 | 0 | c = lexdigits(v, 16, 8, 8); |
690 | 0 | if (ISERR() || !CHR_IS_IN_RANGE(c)) |
691 | 0 | FAILW(REG_EESCAPE); |
692 | 0 | RETV(PLAIN, c); |
693 | 0 | break; |
694 | 0 | case CHR('v'): |
695 | 0 | RETV(PLAIN, CHR('\v')); |
696 | 0 | break; |
697 | 0 | case CHR('w'): |
698 | 0 | NOTE(REG_ULOCALE); |
699 | 0 | RETV(CCLASSS, CC_WORD); |
700 | 0 | break; |
701 | 0 | case CHR('W'): |
702 | 0 | NOTE(REG_ULOCALE); |
703 | 0 | RETV(CCLASSC, CC_WORD); |
704 | 0 | break; |
705 | 0 | case CHR('x'): |
706 | 0 | NOTE(REG_UUNPORT); |
707 | 0 | c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */ |
708 | 0 | if (ISERR() || !CHR_IS_IN_RANGE(c)) |
709 | 0 | FAILW(REG_EESCAPE); |
710 | 0 | RETV(PLAIN, c); |
711 | 0 | break; |
712 | 0 | case CHR('y'): |
713 | 0 | NOTE(REG_ULOCALE); |
714 | 0 | RETV(WBDRY, 0); |
715 | 0 | break; |
716 | 0 | case CHR('Y'): |
717 | 0 | NOTE(REG_ULOCALE); |
718 | 0 | RETV(NWBDRY, 0); |
719 | 0 | break; |
720 | 0 | case CHR('Z'): |
721 | 0 | RETV(SEND, 0); |
722 | 0 | break; |
723 | 0 | case CHR('1'): |
724 | 0 | case CHR('2'): |
725 | 0 | case CHR('3'): |
726 | 0 | case CHR('4'): |
727 | 0 | case CHR('5'): |
728 | 0 | case CHR('6'): |
729 | 0 | case CHR('7'): |
730 | 0 | case CHR('8'): |
731 | 0 | case CHR('9'): |
732 | 0 | save = v->now; |
733 | 0 | v->now--; /* put first digit back */ |
734 | 0 | c = lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */ |
735 | 0 | if (ISERR()) |
736 | 0 | FAILW(REG_EESCAPE); |
737 | | /* ugly heuristic (first test is "exactly 1 digit?") */ |
738 | 0 | if (v->now == save || ((int) c > 0 && (int) c <= v->nsubexp)) |
739 | 0 | { |
740 | 0 | NOTE(REG_UBACKREF); |
741 | 0 | RETV(BACKREF, c); |
742 | 0 | } |
743 | | /* oops, doesn't look like it's a backref after all... */ |
744 | 0 | v->now = save; |
745 | | /* and fall through into octal number */ |
746 | 0 | pg_fallthrough; |
747 | 0 | case CHR('0'): |
748 | 0 | NOTE(REG_UUNPORT); |
749 | 0 | v->now--; /* put first digit back */ |
750 | 0 | c = lexdigits(v, 8, 1, 3); |
751 | 0 | if (ISERR()) |
752 | 0 | FAILW(REG_EESCAPE); |
753 | 0 | if (c > 0xff) |
754 | 0 | { |
755 | | /* out of range, so we handled one digit too much */ |
756 | 0 | v->now--; |
757 | 0 | c >>= 3; |
758 | 0 | } |
759 | 0 | RETV(PLAIN, c); |
760 | 0 | break; |
761 | 0 | default: |
762 | | |
763 | | /* |
764 | | * Throw an error for unrecognized ASCII alpha escape sequences, |
765 | | * which reserves them for future use if needed. |
766 | | */ |
767 | 0 | FAILW(REG_EESCAPE); |
768 | 0 | break; |
769 | 0 | } |
770 | 0 | assert(NOTREACHED); |
771 | 0 | } |
772 | | |
773 | | /* |
774 | | * lexdigits - slurp up digits and return chr value |
775 | | * |
776 | | * This does not account for overflow; callers should range-check the result |
777 | | * if maxlen is large enough to make that possible. |
778 | | */ |
779 | | static chr /* chr value; errors signalled via ERR */ |
780 | | lexdigits(struct vars *v, |
781 | | int base, |
782 | | int minlen, |
783 | | int maxlen) |
784 | 0 | { |
785 | 0 | uchr n; /* unsigned to avoid overflow misbehavior */ |
786 | 0 | int len; |
787 | 0 | chr c; |
788 | 0 | int d; |
789 | 0 | const uchr ub = (uchr) base; |
790 | |
|
791 | 0 | n = 0; |
792 | 0 | for (len = 0; len < maxlen && !ATEOS(); len++) |
793 | 0 | { |
794 | 0 | c = *v->now++; |
795 | 0 | switch (c) |
796 | 0 | { |
797 | 0 | case CHR('0'): |
798 | 0 | case CHR('1'): |
799 | 0 | case CHR('2'): |
800 | 0 | case CHR('3'): |
801 | 0 | case CHR('4'): |
802 | 0 | case CHR('5'): |
803 | 0 | case CHR('6'): |
804 | 0 | case CHR('7'): |
805 | 0 | case CHR('8'): |
806 | 0 | case CHR('9'): |
807 | 0 | d = DIGITVAL(c); |
808 | 0 | break; |
809 | 0 | case CHR('a'): |
810 | 0 | case CHR('A'): |
811 | 0 | d = 10; |
812 | 0 | break; |
813 | 0 | case CHR('b'): |
814 | 0 | case CHR('B'): |
815 | 0 | d = 11; |
816 | 0 | break; |
817 | 0 | case CHR('c'): |
818 | 0 | case CHR('C'): |
819 | 0 | d = 12; |
820 | 0 | break; |
821 | 0 | case CHR('d'): |
822 | 0 | case CHR('D'): |
823 | 0 | d = 13; |
824 | 0 | break; |
825 | 0 | case CHR('e'): |
826 | 0 | case CHR('E'): |
827 | 0 | d = 14; |
828 | 0 | break; |
829 | 0 | case CHR('f'): |
830 | 0 | case CHR('F'): |
831 | 0 | d = 15; |
832 | 0 | break; |
833 | 0 | default: |
834 | 0 | v->now--; /* oops, not a digit at all */ |
835 | 0 | d = -1; |
836 | 0 | break; |
837 | 0 | } |
838 | | |
839 | 0 | if (d >= base) |
840 | 0 | { /* not a plausible digit */ |
841 | 0 | v->now--; |
842 | 0 | d = -1; |
843 | 0 | } |
844 | 0 | if (d < 0) |
845 | 0 | break; /* NOTE BREAK OUT */ |
846 | 0 | n = n * ub + (uchr) d; |
847 | 0 | } |
848 | 0 | if (len < minlen) |
849 | 0 | ERR(REG_EESCAPE); |
850 | |
|
851 | 0 | return (chr) n; |
852 | 0 | } |
853 | | |
854 | | /* |
855 | | * brenext - get next BRE token |
856 | | * |
857 | | * This is much like EREs except for all the stupid backslashes and the |
858 | | * context-dependency of some things. |
859 | | */ |
860 | | static int /* 1 normal, 0 failure */ |
861 | | brenext(struct vars *v, |
862 | | chr c) |
863 | 0 | { |
864 | 0 | switch (c) |
865 | 0 | { |
866 | 0 | case CHR('*'): |
867 | 0 | if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) |
868 | 0 | RETV(PLAIN, c); |
869 | 0 | RETV('*', 1); |
870 | 0 | break; |
871 | 0 | case CHR('['): |
872 | 0 | if (HAVE(6) && *(v->now + 0) == CHR('[') && |
873 | 0 | *(v->now + 1) == CHR(':') && |
874 | 0 | (*(v->now + 2) == CHR('<') || |
875 | 0 | *(v->now + 2) == CHR('>')) && |
876 | 0 | *(v->now + 3) == CHR(':') && |
877 | 0 | *(v->now + 4) == CHR(']') && |
878 | 0 | *(v->now + 5) == CHR(']')) |
879 | 0 | { |
880 | 0 | c = *(v->now + 2); |
881 | 0 | v->now += 6; |
882 | 0 | NOTE(REG_UNONPOSIX); |
883 | 0 | RET((c == CHR('<')) ? '<' : '>'); |
884 | 0 | } |
885 | 0 | INTOCON(L_BRACK); |
886 | 0 | if (NEXT1('^')) |
887 | 0 | { |
888 | 0 | v->now++; |
889 | 0 | RETV('[', 0); |
890 | 0 | } |
891 | 0 | RETV('[', 1); |
892 | 0 | break; |
893 | 0 | case CHR('.'): |
894 | 0 | RET('.'); |
895 | 0 | break; |
896 | 0 | case CHR('^'): |
897 | 0 | if (LASTTYPE(EMPTY)) |
898 | 0 | RET('^'); |
899 | 0 | if (LASTTYPE('(')) |
900 | 0 | { |
901 | 0 | NOTE(REG_UUNSPEC); |
902 | 0 | RET('^'); |
903 | 0 | } |
904 | 0 | RETV(PLAIN, c); |
905 | 0 | break; |
906 | 0 | case CHR('$'): |
907 | 0 | if (v->cflags & REG_EXPANDED) |
908 | 0 | skip(v); |
909 | 0 | if (ATEOS()) |
910 | 0 | RET('$'); |
911 | 0 | if (NEXT2('\\', ')')) |
912 | 0 | { |
913 | 0 | NOTE(REG_UUNSPEC); |
914 | 0 | RET('$'); |
915 | 0 | } |
916 | 0 | RETV(PLAIN, c); |
917 | 0 | break; |
918 | 0 | case CHR('\\'): |
919 | 0 | break; /* see below */ |
920 | 0 | default: |
921 | 0 | RETV(PLAIN, c); |
922 | 0 | break; |
923 | 0 | } |
924 | | |
925 | 0 | assert(c == CHR('\\')); |
926 | |
|
927 | 0 | if (ATEOS()) |
928 | 0 | FAILW(REG_EESCAPE); |
929 | | |
930 | 0 | c = *v->now++; |
931 | 0 | switch (c) |
932 | 0 | { |
933 | 0 | case CHR('{'): |
934 | 0 | INTOCON(L_BBND); |
935 | 0 | NOTE(REG_UBOUNDS); |
936 | 0 | RET('{'); |
937 | 0 | break; |
938 | 0 | case CHR('('): |
939 | 0 | RETV('(', 1); |
940 | 0 | break; |
941 | 0 | case CHR(')'): |
942 | 0 | RETV(')', c); |
943 | 0 | break; |
944 | 0 | case CHR('<'): |
945 | 0 | NOTE(REG_UNONPOSIX); |
946 | 0 | RET('<'); |
947 | 0 | break; |
948 | 0 | case CHR('>'): |
949 | 0 | NOTE(REG_UNONPOSIX); |
950 | 0 | RET('>'); |
951 | 0 | break; |
952 | 0 | case CHR('1'): |
953 | 0 | case CHR('2'): |
954 | 0 | case CHR('3'): |
955 | 0 | case CHR('4'): |
956 | 0 | case CHR('5'): |
957 | 0 | case CHR('6'): |
958 | 0 | case CHR('7'): |
959 | 0 | case CHR('8'): |
960 | 0 | case CHR('9'): |
961 | 0 | NOTE(REG_UBACKREF); |
962 | 0 | RETV(BACKREF, (chr) DIGITVAL(c)); |
963 | 0 | break; |
964 | 0 | default: |
965 | 0 | if (iscalnum(c)) |
966 | 0 | { |
967 | 0 | NOTE(REG_UBSALNUM); |
968 | 0 | NOTE(REG_UUNSPEC); |
969 | 0 | } |
970 | 0 | RETV(PLAIN, c); |
971 | 0 | break; |
972 | 0 | } |
973 | | |
974 | 0 | assert(NOTREACHED); |
975 | 0 | return 0; |
976 | 0 | } |
977 | | |
978 | | /* |
979 | | * skip - skip white space and comments in expanded form |
980 | | */ |
981 | | static void |
982 | | skip(struct vars *v) |
983 | 0 | { |
984 | 0 | const chr *start = v->now; |
985 | |
|
986 | 0 | assert(v->cflags & REG_EXPANDED); |
987 | |
|
988 | 0 | for (;;) |
989 | 0 | { |
990 | 0 | while (!ATEOS() && iscspace(*v->now)) |
991 | 0 | v->now++; |
992 | 0 | if (ATEOS() || *v->now != CHR('#')) |
993 | 0 | break; /* NOTE BREAK OUT */ |
994 | 0 | assert(NEXT1('#')); |
995 | 0 | while (!ATEOS() && *v->now != CHR('\n')) |
996 | 0 | v->now++; |
997 | | /* leave the newline to be picked up by the iscspace loop */ |
998 | 0 | } |
999 | |
|
1000 | 0 | if (v->now != start) |
1001 | 0 | NOTE(REG_UNONPOSIX); |
1002 | 0 | } |
1003 | | |
1004 | | /* |
1005 | | * newline - return the chr for a newline |
1006 | | * |
1007 | | * This helps confine use of CHR to this source file. |
1008 | | */ |
1009 | | static chr |
1010 | | newline(void) |
1011 | 0 | { |
1012 | 0 | return CHR('\n'); |
1013 | 0 | } |
1014 | | |
1015 | | /* |
1016 | | * chrnamed - return the chr known by a given (chr string) name |
1017 | | * |
1018 | | * The code is a bit clumsy, but this routine gets only such specialized |
1019 | | * use that it hardly matters. |
1020 | | */ |
1021 | | static chr |
1022 | | chrnamed(struct vars *v, |
1023 | | const chr *startp, /* start of name */ |
1024 | | const chr *endp, /* just past end of name */ |
1025 | | chr lastresort) /* what to return if name lookup fails */ |
1026 | 0 | { |
1027 | 0 | chr c; |
1028 | 0 | int errsave; |
1029 | 0 | int e; |
1030 | 0 | struct cvec *cv; |
1031 | |
|
1032 | 0 | errsave = v->err; |
1033 | 0 | v->err = 0; |
1034 | 0 | c = element(v, startp, endp); |
1035 | 0 | e = v->err; |
1036 | 0 | v->err = errsave; |
1037 | |
|
1038 | 0 | if (e != 0) |
1039 | 0 | return lastresort; |
1040 | | |
1041 | 0 | cv = range(v, c, c, 0); |
1042 | 0 | if (cv->nchrs == 0) |
1043 | 0 | return lastresort; |
1044 | 0 | return cv->chrs[0]; |
1045 | 0 | } |