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 5081 : lexstart(struct vars *v)
71 : {
72 5081 : prefixes(v); /* may turn on new type bits etc. */
73 5081 : NOERR();
74 :
75 5078 : if (v->cflags & REG_QUOTE)
76 : {
77 : assert(!(v->cflags & (REG_ADVANCED | REG_EXPANDED | REG_NEWLINE)));
78 61 : INTOCON(L_Q);
79 : }
80 5017 : else if (v->cflags & REG_EXTENDED)
81 : {
82 : assert(!(v->cflags & REG_QUOTE));
83 4889 : INTOCON(L_ERE);
84 : }
85 : else
86 : {
87 : assert(!(v->cflags & (REG_QUOTE | REG_ADVF)));
88 128 : INTOCON(L_BRE);
89 : }
90 :
91 5078 : v->nexttype = EMPTY; /* remember we were at the start */
92 5078 : next(v); /* set up the first token */
93 : }
94 :
95 : /*
96 : * prefixes - implement various special prefixes
97 : */
98 : static void
99 5081 : prefixes(struct vars *v)
100 : {
101 : /* literal string doesn't get any of this stuff */
102 5081 : if (v->cflags & REG_QUOTE)
103 54 : return;
104 :
105 : /* initial "***" gets special things */
106 5027 : 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 5023 : if ((v->cflags & REG_ADVANCED) != REG_ADVANCED)
133 133 : return;
134 :
135 : /* embedded options (AREs only) */
136 4890 : 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 94902 : next(struct vars *v)
201 : {
202 : chr c;
203 :
204 94903 : next_restart: /* loop here after eating a comment */
205 :
206 : /* errors yield an infinite sequence of failures */
207 94903 : if (ISERR())
208 71 : return 0; /* the error has set nexttype to EOS */
209 :
210 : /* remember flavor of last token */
211 94832 : v->lasttype = v->nexttype;
212 :
213 : /* REG_BOSONLY */
214 94832 : 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 94830 : if (v->cflags & REG_EXPANDED)
222 1237 : switch (v->lexcon)
223 : {
224 817 : case L_ERE:
225 : case L_BRE:
226 : case L_EBND:
227 : case L_BBND:
228 817 : skip(v);
229 817 : break;
230 : }
231 :
232 : /* handle EOS, depending on context */
233 94830 : if (ATEOS())
234 : {
235 4982 : switch (v->lexcon)
236 : {
237 4966 : case L_ERE:
238 : case L_BRE:
239 : case L_Q:
240 4966 : 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 89848 : c = *v->now++;
258 :
259 : /* deal with the easy contexts, punt EREs to code below */
260 89848 : switch (v->lexcon)
261 : {
262 322 : case L_BRE: /* punt BREs to separate function */
263 322 : return brenext(v, c);
264 : break;
265 84539 : case L_ERE: /* see below */
266 84539 : break;
267 318 : case L_Q: /* literal strings are easy */
268 318 : RETV(PLAIN, c);
269 : break;
270 948 : case L_BBND: /* bounds are fairly simple */
271 : case L_EBND:
272 948 : switch (c)
273 : {
274 493 : 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 493 : RETV(DIGIT, (chr) DIGITVAL(c));
285 : break;
286 148 : case CHR(','):
287 148 : RET(',');
288 : break;
289 303 : case CHR('}'): /* ERE bound ends with } */
290 303 : if (INCON(L_EBND))
291 : {
292 303 : INTOCON(L_ERE);
293 303 : if ((v->cflags & REG_ADVF) && NEXT1('?'))
294 : {
295 59 : v->now++;
296 59 : NOTE(REG_UNONPOSIX);
297 59 : RETV('}', 0);
298 : }
299 244 : 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 2630 : case L_BRACK: /* brackets are not too hard */
321 2630 : switch (c)
322 : {
323 752 : case CHR(']'):
324 752 : if (LASTTYPE('['))
325 10 : RETV(PLAIN, c);
326 : else
327 : {
328 742 : INTOCON((v->cflags & REG_EXTENDED) ?
329 : L_ERE : L_BRE);
330 742 : RET(']');
331 : }
332 : break;
333 80 : case CHR('\\'):
334 80 : NOTE(REG_UBBS);
335 80 : if (!(v->cflags & REG_ADVF))
336 7 : RETV(PLAIN, c);
337 73 : NOTE(REG_UNONPOSIX);
338 73 : if (ATEOS())
339 0 : FAILW(REG_EESCAPE);
340 73 : if (!lexescape(v))
341 0 : return 0;
342 73 : switch (v->nexttype)
343 : { /* not all escapes okay here */
344 72 : case PLAIN:
345 : case CCLASSS:
346 : case CCLASSC:
347 72 : return 1;
348 : break;
349 : }
350 : /* not one of the acceptable escapes */
351 1 : FAILW(REG_EESCAPE);
352 : break;
353 350 : case CHR('-'):
354 350 : if (LASTTYPE('[') || NEXT1(']'))
355 8 : RETV(PLAIN, c);
356 : else
357 342 : RETV(RANGE, c);
358 : break;
359 220 : case CHR('['):
360 220 : if (ATEOS())
361 0 : FAILW(REG_EBRACK);
362 220 : 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 178 : case CHR(':'):
375 178 : INTOCON(L_CCL);
376 178 : NOTE(REG_ULOCALE);
377 178 : RET(CCLASS);
378 : break;
379 14 : default: /* oops */
380 14 : v->now--;
381 14 : RETV(PLAIN, c);
382 : break;
383 : }
384 : assert(NOTREACHED);
385 : break;
386 1228 : default:
387 1228 : 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 1035 : case L_CCL: /* ditto character classes */
413 1035 : if (c == CHR(':') && NEXT1(']'))
414 : {
415 173 : v->now++;
416 173 : INTOCON(L_BRACK);
417 173 : RETV(END, ':');
418 : }
419 : else
420 862 : 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 84539 : switch (c)
432 : {
433 367 : case CHR('|'):
434 367 : RET('|');
435 : break;
436 13860 : case CHR('*'):
437 13860 : if ((v->cflags & REG_ADVF) && NEXT1('?'))
438 : {
439 33 : v->now++;
440 33 : NOTE(REG_UNONPOSIX);
441 33 : RETV('*', 0);
442 : }
443 13827 : RETV('*', 1);
444 : break;
445 572 : case CHR('+'):
446 572 : if ((v->cflags & REG_ADVF) && NEXT1('?'))
447 : {
448 25 : v->now++;
449 25 : NOTE(REG_UNONPOSIX);
450 25 : RETV('+', 0);
451 : }
452 547 : RETV('+', 1);
453 : break;
454 79 : case CHR('?'):
455 79 : if ((v->cflags & REG_ADVF) && NEXT1('?'))
456 : {
457 2 : v->now++;
458 2 : NOTE(REG_UNONPOSIX);
459 2 : RETV('?', 0);
460 : }
461 77 : RETV('?', 1);
462 : break;
463 311 : case CHR('{'): /* bounds start or plain character */
464 311 : if (v->cflags & REG_EXPANDED)
465 16 : skip(v);
466 311 : 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 307 : NOTE(REG_UBOUNDS);
475 307 : INTOCON(L_EBND);
476 307 : RET('{');
477 : }
478 : assert(NOTREACHED);
479 : break;
480 3574 : case CHR('('): /* parenthesis, or advanced extension */
481 3574 : if ((v->cflags & REG_ADVF) && NEXT1('?'))
482 : {
483 351 : NOTE(REG_UNONPOSIX);
484 351 : v->now++;
485 351 : if (ATEOS())
486 0 : FAILW(REG_BADRPT);
487 351 : switch (*v->now++)
488 : {
489 188 : case CHR(':'): /* non-capturing paren */
490 188 : 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 50 : case CHR('='): /* positive lookahead */
500 50 : NOTE(REG_ULOOKAROUND);
501 50 : RETV(LACON, LATYPE_AHEAD_POS);
502 : break;
503 45 : case CHR('!'): /* negative lookahead */
504 45 : NOTE(REG_ULOOKAROUND);
505 45 : RETV(LACON, LATYPE_AHEAD_NEG);
506 : break;
507 66 : case CHR('<'):
508 66 : if (ATEOS())
509 0 : FAILW(REG_BADRPT);
510 66 : switch (*v->now++)
511 : {
512 48 : case CHR('='): /* positive lookbehind */
513 48 : NOTE(REG_ULOOKAROUND);
514 48 : RETV(LACON, LATYPE_BEHIND_POS);
515 : break;
516 18 : case CHR('!'): /* negative lookbehind */
517 18 : NOTE(REG_ULOOKAROUND);
518 18 : 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 3223 : RETV('(', 1);
533 : break;
534 3536 : case CHR(')'):
535 3536 : if (LASTTYPE('('))
536 37 : NOTE(REG_UUNSPEC);
537 3536 : RETV(')', c);
538 : break;
539 711 : case CHR('['): /* easy except for [[:<:]] and [[:>:]] */
540 711 : if (HAVE(6) && *(v->now + 0) == CHR('[') &&
541 173 : *(v->now + 1) == CHR(':') &&
542 155 : (*(v->now + 2) == CHR('<') ||
543 150 : *(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 701 : INTOCON(L_BRACK);
554 701 : if (NEXT1('^'))
555 : {
556 151 : v->now++;
557 151 : RETV('[', 0);
558 : }
559 550 : RETV('[', 1);
560 : break;
561 2055 : case CHR('.'):
562 2055 : RET('.');
563 : break;
564 3447 : case CHR('^'):
565 3447 : RET('^');
566 : break;
567 2913 : case CHR('$'):
568 2913 : RET('$');
569 : break;
570 1450 : case CHR('\\'): /* mostly punt backslashes to code below */
571 1450 : if (ATEOS())
572 1 : FAILW(REG_EESCAPE);
573 1449 : break;
574 51664 : default: /* ordinary character */
575 51664 : RETV(PLAIN, c);
576 : break;
577 : }
578 :
579 : /* ERE/ARE backslash handling; backslash already eaten */
580 : assert(!ATEOS());
581 1449 : 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 1445 : 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 1518 : 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 1518 : c = *v->now++;
616 :
617 : /* if it's not alphanumeric ASCII, treat it as a plain character */
618 1518 : if (!('a' <= c && c <= 'z') &&
619 1137 : !('A' <= c && c <= 'Z') &&
620 415 : !('0' <= c && c <= '9'))
621 882 : RETV(PLAIN, c);
622 :
623 636 : NOTE(REG_UNONPOSIX);
624 636 : switch (c)
625 : {
626 5 : case CHR('a'):
627 5 : RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
628 : break;
629 11 : case CHR('A'):
630 11 : RETV(SBEGIN, 0);
631 : break;
632 17 : case CHR('b'):
633 17 : 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 185 : case CHR('d'):
645 185 : NOTE(REG_ULOCALE);
646 185 : 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 23 : case CHR('m'):
660 23 : RET('<');
661 : break;
662 19 : case CHR('M'):
663 19 : 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 31 : case CHR('s'):
672 31 : NOTE(REG_ULOCALE);
673 31 : RETV(CCLASSS, CC_SPACE);
674 : break;
675 20 : case CHR('S'):
676 20 : NOTE(REG_ULOCALE);
677 20 : 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 57 : case CHR('w'):
698 57 : NOTE(REG_ULOCALE);
699 57 : 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 7 : case CHR('x'):
706 7 : NOTE(REG_UUNPORT);
707 7 : c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */
708 7 : if (ISERR() || !CHR_IS_IN_RANGE(c))
709 5 : 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 21 : case CHR('Y'):
717 21 : NOTE(REG_ULOCALE);
718 21 : RETV(NWBDRY, 0);
719 : break;
720 6 : case CHR('Z'):
721 6 : RETV(SEND, 0);
722 : break;
723 136 : 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 136 : save = v->now;
733 136 : v->now--; /* put first digit back */
734 136 : c = lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */
735 136 : if (ISERR())
736 0 : FAILW(REG_EESCAPE);
737 : /* ugly heuristic (first test is "exactly 1 digit?") */
738 136 : if (v->now == save || ((int) c > 0 && (int) c <= v->nsubexp))
739 : {
740 131 : NOTE(REG_UBACKREF);
741 131 : 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 191 : 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 191 : const uchr ub = (uchr) base;
790 :
791 191 : n = 0;
792 592 : for (len = 0; len < maxlen && !ATEOS(); len++)
793 : {
794 500 : c = *v->now++;
795 500 : switch (c)
796 : {
797 364 : 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 364 : d = DIGITVAL(c);
808 364 : 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 36 : case CHR('f'):
830 : case CHR('F'):
831 36 : d = 15;
832 36 : break;
833 88 : default:
834 88 : v->now--; /* oops, not a digit at all */
835 88 : d = -1;
836 88 : break;
837 : }
838 :
839 500 : if (d >= base)
840 : { /* not a plausible digit */
841 11 : v->now--;
842 11 : d = -1;
843 : }
844 500 : if (d < 0)
845 99 : break; /* NOTE BREAK OUT */
846 401 : n = n * ub + (uchr) d;
847 : }
848 191 : if (len < minlen)
849 7 : ERR(REG_EESCAPE);
850 :
851 191 : 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 833 : skip(struct vars *v)
983 : {
984 833 : const chr *start = v->now;
985 :
986 : assert(v->cflags & REG_EXPANDED);
987 :
988 : for (;;)
989 : {
990 1350 : while (!ATEOS() && iscspace(*v->now))
991 447 : v->now++;
992 903 : 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 833 : if (v->now != start)
1001 107 : NOTE(REG_UNONPOSIX);
1002 833 : }
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 359 : newline(void)
1011 : {
1012 359 : 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 6 : 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 6 : errsave = v->err;
1033 6 : v->err = 0;
1034 6 : c = element(v, startp, endp);
1035 6 : e = v->err;
1036 6 : v->err = errsave;
1037 :
1038 6 : if (e != 0)
1039 0 : return lastresort;
1040 :
1041 6 : cv = range(v, c, c, 0);
1042 6 : if (cv->nchrs == 0)
1043 6 : return lastresort;
1044 0 : return cv->chrs[0];
1045 : }
|