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