1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#if defined (_AIX) && !defined (REGEX_MALLOC)
24 #pragma alloca
25#endif
26
27#define _GNU_SOURCE
28
29
30#include <sys/types.h>
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36
37
38#ifdef emacs
39
40#include "lisp.h"
41#include "buffer.h"
42#include "syntax.h"
43
44
45#undef NULL
46
47#else
48
49
50
51#if HAVE_STRING_H || STDC_HEADERS
52#include <string.h>
53#ifndef bcmp
54#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
55#endif
56#ifndef bcopy
57#define bcopy(s, d, n) memcpy ((d), (s), (n))
58#endif
59#ifndef bzero
60#define bzero(s, n) memset ((s), 0, (n))
61#endif
62#else
63#include <strings.h>
64#endif
65
66#ifdef STDC_HEADERS
67#include <stdlib.h>
68#else
69char *malloc ();
70char *realloc ();
71#endif
72
73
74
75
76
77
78#ifndef Sword
79#define Sword 1
80#endif
81
82#ifdef SYNTAX_TABLE
83
84extern char *re_syntax_table;
85
86#else
87
88
89#define CHAR_SET_SIZE 256
90
91static char re_syntax_table[CHAR_SET_SIZE];
92
93static void
94init_syntax_once ()
95{
96 register int c;
97 static int done = 0;
98
99 if (done)
100 return;
101
102 bzero (re_syntax_table, sizeof re_syntax_table);
103
104 for (c = 'a'; c <= 'z'; c++)
105 re_syntax_table[c] = Sword;
106
107 for (c = 'A'; c <= 'Z'; c++)
108 re_syntax_table[c] = Sword;
109
110 for (c = '0'; c <= '9'; c++)
111 re_syntax_table[c] = Sword;
112
113 re_syntax_table['_'] = Sword;
114
115 done = 1;
116}
117
118#endif
119
120#define SYNTAX(c) re_syntax_table[c]
121
122#endif
123
124
125#include "regex.h"
126
127
128#include <ctype.h>
129
130#ifndef isascii
131#define isascii(c) 1
132#endif
133
134#ifdef isblank
135#define ISBLANK(c) (isascii (c) && isblank (c))
136#else
137#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
138#endif
139#ifdef isgraph
140#define ISGRAPH(c) (isascii (c) && isgraph (c))
141#else
142#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
143#endif
144
145#define ISPRINT(c) (isascii (c) && isprint (c))
146#define ISDIGIT(c) (isascii (c) && isdigit (c))
147#define ISALNUM(c) (isascii (c) && isalnum (c))
148#define ISALPHA(c) (isascii (c) && isalpha (c))
149#define ISCNTRL(c) (isascii (c) && iscntrl (c))
150#define ISLOWER(c) (isascii (c) && islower (c))
151#define ISPUNCT(c) (isascii (c) && ispunct (c))
152#define ISSPACE(c) (isascii (c) && isspace (c))
153#define ISUPPER(c) (isascii (c) && isupper (c))
154#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
155
156#ifndef NULL
157#define NULL 0
158#endif
159
160
161
162
163
164#undef SIGN_EXTEND_CHAR
165#if __STDC__
166#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
167#else
168
169#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
170#endif
171
172
173
174
175
176
177
178
179
180
181
182#ifdef REGEX_MALLOC
183
184#define REGEX_ALLOCATE malloc
185#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
186
187#else
188
189
190#ifndef alloca
191
192
193#ifdef __GNUC__
194#define alloca __builtin_alloca
195#else
196#if HAVE_ALLOCA_H
197#include <alloca.h>
198#else
199#ifndef _AIX
200char *alloca ();
201#endif
202#endif
203#endif
204
205#endif
206
207#define REGEX_ALLOCATE alloca
208
209
210#define REGEX_REALLOCATE(source, osize, nsize) \
211 (destination = (char *) alloca (nsize), \
212 bcopy (source, destination, osize), \
213 destination)
214
215#endif
216
217
218
219
220
221#define FIRST_STRING_P(ptr) \
222 (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
223
224
225#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
226#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
227#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
228
229#define BYTEWIDTH 8
230
231#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
232
233#define MAX(a, b) ((a) > (b) ? (a) : (b))
234#define MIN(a, b) ((a) < (b) ? (a) : (b))
235
236typedef char boolean;
237#define false 0
238#define true 1
239
240
241
242
243
244
245
246
247
248
249typedef enum
250{
251 no_op = 0,
252
253
254 exactn = 1,
255
256
257 anychar,
258
259
260
261
262
263
264
265 charset,
266
267
268
269 charset_not,
270
271
272
273
274
275
276
277
278 start_memory,
279
280
281
282
283
284
285
286
287 stop_memory,
288
289
290
291 duplicate,
292
293
294 begline,
295
296
297 endline,
298
299
300
301 begbuf,
302
303
304 endbuf,
305
306
307 jump,
308
309
310 jump_past_alt,
311
312
313
314 on_failure_jump,
315
316
317
318 on_failure_keep_string_jump,
319
320
321
322 pop_failure_jump,
323
324
325
326
327
328
329
330
331 maybe_pop_jump,
332
333
334
335
336
337
338 dummy_failure_jump,
339
340
341
342 push_dummy_failure,
343
344
345
346 succeed_n,
347
348
349
350 jump_n,
351
352
353
354
355 set_number_at,
356
357 wordchar,
358 notwordchar,
359
360 wordbeg,
361 wordend,
362
363 wordbound,
364 notwordbound
365
366#ifdef emacs
367 ,before_dot,
368 at_dot,
369 after_dot,
370
371
372
373 syntaxspec,
374
375
376 notsyntaxspec
377#endif
378} re_opcode_t;
379
380
381
382
383
384#define STORE_NUMBER(destination, number) \
385 do { \
386 (destination)[0] = (number) & 0377; \
387 (destination)[1] = (number) >> 8; \
388 } while (0)
389
390
391
392
393
394#define STORE_NUMBER_AND_INCR(destination, number) \
395 do { \
396 STORE_NUMBER (destination, number); \
397 (destination) += 2; \
398 } while (0)
399
400
401
402
403#define EXTRACT_NUMBER(destination, source) \
404 do { \
405 (destination) = *(source) & 0377; \
406 (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
407 } while (0)
408
409#ifdef DEBUG
410static void
411extract_number (dest, source)
412 int *dest;
413 unsigned char *source;
414{
415 int temp = SIGN_EXTEND_CHAR (*(source + 1));
416 *dest = *source & 0377;
417 *dest += temp << 8;
418}
419
420#ifndef EXTRACT_MACROS
421#undef EXTRACT_NUMBER
422#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
423#endif
424
425#endif
426
427
428
429
430#define EXTRACT_NUMBER_AND_INCR(destination, source) \
431 do { \
432 EXTRACT_NUMBER (destination, source); \
433 (source) += 2; \
434 } while (0)
435
436#ifdef DEBUG
437static void
438extract_number_and_incr (destination, source)
439 int *destination;
440 unsigned char **source;
441{
442 extract_number (destination, *source);
443 *source += 2;
444}
445
446#ifndef EXTRACT_MACROS
447#undef EXTRACT_NUMBER_AND_INCR
448#define EXTRACT_NUMBER_AND_INCR(dest, src) \
449 extract_number_and_incr (&dest, &src)
450#endif
451
452#endif
453
454
455
456
457
458
459
460#ifdef DEBUG
461
462
463#include <stdio.h>
464
465
466#include <assert.h>
467
468static int debug = 0;
469
470#define DEBUG_STATEMENT(e) e
471#define DEBUG_PRINT1(x) if (debug) printf (x)
472#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
473#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
474#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
475#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
476 if (debug) print_partial_compiled_pattern (s, e)
477#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
478 if (debug) print_double_string (w, s1, sz1, s2, sz2)
479
480
481extern void printchar ();
482
483
484
485void
486print_fastmap (fastmap)
487 char *fastmap;
488{
489 unsigned was_a_range = 0;
490 unsigned i = 0;
491
492 while (i < (1 << BYTEWIDTH))
493 {
494 if (fastmap[i++])
495 {
496 was_a_range = 0;
497 printchar (i - 1);
498 while (i < (1 << BYTEWIDTH) && fastmap[i])
499 {
500 was_a_range = 1;
501 i++;
502 }
503 if (was_a_range)
504 {
505 printf ("-");
506 printchar (i - 1);
507 }
508 }
509 }
510 putchar ('\n');
511}
512
513
514
515
516
517void
518print_partial_compiled_pattern (start, end)
519 unsigned char *start;
520 unsigned char *end;
521{
522 int mcnt, mcnt2;
523 unsigned char *p = start;
524 unsigned char *pend = end;
525
526 if (start == NULL)
527 {
528 printf ("(null)\n");
529 return;
530 }
531
532
533 while (p < pend)
534 {
535 switch ((re_opcode_t) *p++)
536 {
537 case no_op:
538 printf ("/no_op");
539 break;
540
541 case exactn:
542 mcnt = *p++;
543 printf ("/exactn/%d", mcnt);
544 do
545 {
546 putchar ('/');
547 printchar (*p++);
548 }
549 while (--mcnt);
550 break;
551
552 case start_memory:
553 mcnt = *p++;
554 printf ("/start_memory/%d/%d", mcnt, *p++);
555 break;
556
557 case stop_memory:
558 mcnt = *p++;
559 printf ("/stop_memory/%d/%d", mcnt, *p++);
560 break;
561
562 case duplicate:
563 printf ("/duplicate/%d", *p++);
564 break;
565
566 case anychar:
567 printf ("/anychar");
568 break;
569
570 case charset:
571 case charset_not:
572 {
573 register int c;
574
575 printf ("/charset%s",
576 (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
577
578 assert (p + *p < pend);
579
580 for (c = 0; c < *p; c++)
581 {
582 unsigned bit;
583 unsigned char map_byte = p[1 + c];
584
585 putchar ('/');
586
587 for (bit = 0; bit < BYTEWIDTH; bit++)
588 if (map_byte & (1 << bit))
589 printchar (c * BYTEWIDTH + bit);
590 }
591 p += 1 + *p;
592 break;
593 }
594
595 case begline:
596 printf ("/begline");
597 break;
598
599 case endline:
600 printf ("/endline");
601 break;
602
603 case on_failure_jump:
604 extract_number_and_incr (&mcnt, &p);
605 printf ("/on_failure_jump/0/%d", mcnt);
606 break;
607
608 case on_failure_keep_string_jump:
609 extract_number_and_incr (&mcnt, &p);
610 printf ("/on_failure_keep_string_jump/0/%d", mcnt);
611 break;
612
613 case dummy_failure_jump:
614 extract_number_and_incr (&mcnt, &p);
615 printf ("/dummy_failure_jump/0/%d", mcnt);
616 break;
617
618 case push_dummy_failure:
619 printf ("/push_dummy_failure");
620 break;
621
622 case maybe_pop_jump:
623 extract_number_and_incr (&mcnt, &p);
624 printf ("/maybe_pop_jump/0/%d", mcnt);
625 break;
626
627 case pop_failure_jump:
628 extract_number_and_incr (&mcnt, &p);
629 printf ("/pop_failure_jump/0/%d", mcnt);
630 break;
631
632 case jump_past_alt:
633 extract_number_and_incr (&mcnt, &p);
634 printf ("/jump_past_alt/0/%d", mcnt);
635 break;
636
637 case jump:
638 extract_number_and_incr (&mcnt, &p);
639 printf ("/jump/0/%d", mcnt);
640 break;
641
642 case succeed_n:
643 extract_number_and_incr (&mcnt, &p);
644 extract_number_and_incr (&mcnt2, &p);
645 printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
646 break;
647
648 case jump_n:
649 extract_number_and_incr (&mcnt, &p);
650 extract_number_and_incr (&mcnt2, &p);
651 printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
652 break;
653
654 case set_number_at:
655 extract_number_and_incr (&mcnt, &p);
656 extract_number_and_incr (&mcnt2, &p);
657 printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
658 break;
659
660 case wordbound:
661 printf ("/wordbound");
662 break;
663
664 case notwordbound:
665 printf ("/notwordbound");
666 break;
667
668 case wordbeg:
669 printf ("/wordbeg");
670 break;
671
672 case wordend:
673 printf ("/wordend");
674
675#ifdef emacs
676 case before_dot:
677 printf ("/before_dot");
678 break;
679
680 case at_dot:
681 printf ("/at_dot");
682 break;
683
684 case after_dot:
685 printf ("/after_dot");
686 break;
687
688 case syntaxspec:
689 printf ("/syntaxspec");
690 mcnt = *p++;
691 printf ("/%d", mcnt);
692 break;
693
694 case notsyntaxspec:
695 printf ("/notsyntaxspec");
696 mcnt = *p++;
697 printf ("/%d", mcnt);
698 break;
699#endif
700
701 case wordchar:
702 printf ("/wordchar");
703 break;
704
705 case notwordchar:
706 printf ("/notwordchar");
707 break;
708
709 case begbuf:
710 printf ("/begbuf");
711 break;
712
713 case endbuf:
714 printf ("/endbuf");
715 break;
716
717 default:
718 printf ("?%d", *(p-1));
719 }
720 }
721 printf ("/\n");
722}
723
724
725void
726print_compiled_pattern (bufp)
727 struct re_pattern_buffer *bufp;
728{
729 unsigned char *buffer = bufp->buffer;
730
731 print_partial_compiled_pattern (buffer, buffer + bufp->used);
732 printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
733
734 if (bufp->fastmap_accurate && bufp->fastmap)
735 {
736 printf ("fastmap: ");
737 print_fastmap (bufp->fastmap);
738 }
739
740 printf ("re_nsub: %d\t", bufp->re_nsub);
741 printf ("regs_alloc: %d\t", bufp->regs_allocated);
742 printf ("can_be_null: %d\t", bufp->can_be_null);
743 printf ("newline_anchor: %d\n", bufp->newline_anchor);
744 printf ("no_sub: %d\t", bufp->no_sub);
745 printf ("not_bol: %d\t", bufp->not_bol);
746 printf ("not_eol: %d\t", bufp->not_eol);
747 printf ("syntax: %d\n", bufp->syntax);
748
749}
750
751
752void
753print_double_string (where, string1, size1, string2, size2)
754 const char *where;
755 const char *string1;
756 const char *string2;
757 int size1;
758 int size2;
759{
760 unsigned this_char;
761
762 if (where == NULL)
763 printf ("(null)");
764 else
765 {
766 if (FIRST_STRING_P (where))
767 {
768 for (this_char = where - string1; this_char < size1; this_char++)
769 printchar (string1[this_char]);
770
771 where = string2;
772 }
773
774 for (this_char = where - string2; this_char < size2; this_char++)
775 printchar (string2[this_char]);
776 }
777}
778
779#else
780
781#undef assert
782#define assert(e)
783
784#define DEBUG_STATEMENT(e)
785#define DEBUG_PRINT1(x)
786#define DEBUG_PRINT2(x1, x2)
787#define DEBUG_PRINT3(x1, x2, x3)
788#define DEBUG_PRINT4(x1, x2, x3, x4)
789#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
790#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
791
792#endif
793
794
795
796
797reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
798
799
800
801
802
803
804
805
806
807reg_syntax_t
808re_set_syntax (syntax)
809 reg_syntax_t syntax;
810{
811 reg_syntax_t ret = re_syntax_options;
812
813 re_syntax_options = syntax;
814 return ret;
815}
816
817
818
819
820static const char *re_error_msg[] =
821 { NULL,
822 "No match",
823 "Invalid regular expression",
824 "Invalid collation character",
825 "Invalid character class name",
826 "Trailing backslash",
827 "Invalid back reference",
828 "Unmatched [ or [^",
829 "Unmatched ( or \\(",
830 "Unmatched \\{",
831 "Invalid content of \\{\\}",
832 "Invalid range end",
833 "Memory exhausted",
834 "Invalid preceding regular expression",
835 "Premature end of regular expression",
836 "Regular expression too big",
837 "Unmatched ) or \\)",
838 };
839
840
841
842static void store_op1 (), store_op2 ();
843static void insert_op1 (), insert_op2 ();
844static boolean at_begline_loc_p (), at_endline_loc_p ();
845static boolean group_in_compile_stack ();
846static reg_errcode_t compile_range ();
847
848
849
850
851
852#define PATFETCH(c) \
853 do {if (p == pend) return REG_EEND; \
854 c = (unsigned char) *p++; \
855 if (translate) c = translate[c]; \
856 } while (0)
857
858
859
860#define PATFETCH_RAW(c) \
861 do {if (p == pend) return REG_EEND; \
862 c = (unsigned char) *p++; \
863 } while (0)
864
865
866#define PATUNFETCH p--
867
868
869
870
871
872
873#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
874
875
876
877
878
879#define INIT_BUF_SIZE 32
880
881
882#define GET_BUFFER_SPACE(n) \
883 while (b - bufp->buffer + (n) > bufp->allocated) \
884 EXTEND_BUFFER ()
885
886
887#define BUF_PUSH(c) \
888 do { \
889 GET_BUFFER_SPACE (1); \
890 *b++ = (unsigned char) (c); \
891 } while (0)
892
893
894
895#define BUF_PUSH_2(c1, c2) \
896 do { \
897 GET_BUFFER_SPACE (2); \
898 *b++ = (unsigned char) (c1); \
899 *b++ = (unsigned char) (c2); \
900 } while (0)
901
902
903
904#define BUF_PUSH_3(c1, c2, c3) \
905 do { \
906 GET_BUFFER_SPACE (3); \
907 *b++ = (unsigned char) (c1); \
908 *b++ = (unsigned char) (c2); \
909 *b++ = (unsigned char) (c3); \
910 } while (0)
911
912
913
914
915#define STORE_JUMP(op, loc, to) \
916 store_op1 (op, loc, (to) - (loc) - 3)
917
918
919#define STORE_JUMP2(op, loc, to, arg) \
920 store_op2 (op, loc, (to) - (loc) - 3, arg)
921
922
923#define INSERT_JUMP(op, loc, to) \
924 insert_op1 (op, loc, (to) - (loc) - 3, b)
925
926
927#define INSERT_JUMP2(op, loc, to, arg) \
928 insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
929
930
931
932
933
934#define MAX_BUF_SIZE (1L << 16)
935
936
937
938
939
940
941#define EXTEND_BUFFER() \
942 do { \
943 unsigned char *old_buffer = bufp->buffer; \
944 if (bufp->allocated == MAX_BUF_SIZE) \
945 return REG_ESIZE; \
946 bufp->allocated <<= 1; \
947 if (bufp->allocated > MAX_BUF_SIZE) \
948 bufp->allocated = MAX_BUF_SIZE; \
949 bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
950 if (bufp->buffer == NULL) \
951 return REG_ESPACE; \
952 \
953 if (old_buffer != bufp->buffer) \
954 { \
955 b = (b - old_buffer) + bufp->buffer; \
956 begalt = (begalt - old_buffer) + bufp->buffer; \
957 if (fixup_alt_jump) \
958 fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
959 if (laststart) \
960 laststart = (laststart - old_buffer) + bufp->buffer; \
961 if (pending_exact) \
962 pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
963 } \
964 } while (0)
965
966
967
968
969
970#define MAX_REGNUM 255
971
972
973
974typedef unsigned regnum_t;
975
976
977
978
979
980
981typedef int pattern_offset_t;
982
983typedef struct
984{
985 pattern_offset_t begalt_offset;
986 pattern_offset_t fixup_alt_jump;
987 pattern_offset_t inner_group_offset;
988 pattern_offset_t laststart_offset;
989 regnum_t regnum;
990} compile_stack_elt_t;
991
992
993typedef struct
994{
995 compile_stack_elt_t *stack;
996 unsigned size;
997 unsigned avail;
998} compile_stack_type;
999
1000
1001#define INIT_COMPILE_STACK_SIZE 32
1002
1003#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
1004#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
1005
1006
1007#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
1008
1009
1010
1011#define SET_LIST_BIT(c) \
1012 (b[((unsigned char) (c)) / BYTEWIDTH] \
1013 |= 1 << (((unsigned char) c) % BYTEWIDTH))
1014
1015
1016
1017#define GET_UNSIGNED_NUMBER(num) \
1018 { if (p != pend) \
1019 { \
1020 PATFETCH (c); \
1021 while (ISDIGIT (c)) \
1022 { \
1023 if (num < 0) \
1024 num = 0; \
1025 num = num * 10 + c - '0'; \
1026 if (p == pend) \
1027 break; \
1028 PATFETCH (c); \
1029 } \
1030 } \
1031 }
1032
1033#define CHAR_CLASS_MAX_LENGTH 6
1034
1035#define IS_CHAR_CLASS(string) \
1036 (STREQ (string, "alpha") || STREQ (string, "upper") \
1037 || STREQ (string, "lower") || STREQ (string, "digit") \
1038 || STREQ (string, "alnum") || STREQ (string, "xdigit") \
1039 || STREQ (string, "space") || STREQ (string, "print") \
1040 || STREQ (string, "punct") || STREQ (string, "graph") \
1041 || STREQ (string, "cntrl") || STREQ (string, "blank"))
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061static reg_errcode_t
1062regex_compile (pattern, size, syntax, bufp)
1063 const char *pattern;
1064 int size;
1065 reg_syntax_t syntax;
1066 struct re_pattern_buffer *bufp;
1067{
1068
1069
1070
1071 register unsigned char c, c1;
1072
1073
1074 const char *p1;
1075
1076
1077 register unsigned char *b;
1078
1079
1080 compile_stack_type compile_stack;
1081
1082
1083 const char *p = pattern;
1084 const char *pend = pattern + size;
1085
1086
1087 char *translate = bufp->translate;
1088
1089
1090
1091
1092
1093 unsigned char *pending_exact = 0;
1094
1095
1096
1097
1098 unsigned char *laststart = 0;
1099
1100
1101 unsigned char *begalt;
1102
1103
1104
1105 const char *beg_interval;
1106
1107
1108
1109
1110 unsigned char *fixup_alt_jump = 0;
1111
1112
1113
1114
1115 regnum_t regnum = 0;
1116
1117#ifdef DEBUG
1118 DEBUG_PRINT1 ("\nCompiling pattern: ");
1119 if (debug)
1120 {
1121 unsigned debug_count;
1122
1123 for (debug_count = 0; debug_count < size; debug_count++)
1124 printchar (pattern[debug_count]);
1125 putchar ('\n');
1126 }
1127#endif
1128
1129
1130 compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
1131 if (compile_stack.stack == NULL)
1132 return REG_ESPACE;
1133
1134 compile_stack.size = INIT_COMPILE_STACK_SIZE;
1135 compile_stack.avail = 0;
1136
1137
1138 bufp->syntax = syntax;
1139 bufp->fastmap_accurate = 0;
1140 bufp->not_bol = bufp->not_eol = 0;
1141
1142
1143
1144
1145 bufp->used = 0;
1146
1147
1148 bufp->re_nsub = 0;
1149
1150#if !defined (emacs) && !defined (SYNTAX_TABLE)
1151
1152 init_syntax_once ();
1153#endif
1154
1155 if (bufp->allocated == 0)
1156 {
1157 if (bufp->buffer)
1158 {
1159
1160
1161 RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
1162 }
1163 else
1164 {
1165 bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
1166 }
1167 if (!bufp->buffer) return REG_ESPACE;
1168
1169 bufp->allocated = INIT_BUF_SIZE;
1170 }
1171
1172 begalt = b = bufp->buffer;
1173
1174
1175 while (p != pend)
1176 {
1177 PATFETCH (c);
1178
1179 switch (c)
1180 {
1181 case '^':
1182 {
1183 if (
1184 p == pattern + 1
1185
1186 || syntax & RE_CONTEXT_INDEP_ANCHORS
1187
1188 || at_begline_loc_p (pattern, p, syntax))
1189 BUF_PUSH (begline);
1190 else
1191 goto normal_char;
1192 }
1193 break;
1194
1195
1196 case '$':
1197 {
1198 if (
1199 p == pend
1200
1201 || syntax & RE_CONTEXT_INDEP_ANCHORS
1202
1203 || at_endline_loc_p (p, pend, syntax))
1204 BUF_PUSH (endline);
1205 else
1206 goto normal_char;
1207 }
1208 break;
1209
1210
1211 case '+':
1212 case '?':
1213 if ((syntax & RE_BK_PLUS_QM)
1214 || (syntax & RE_LIMITED_OPS))
1215 goto normal_char;
1216 handle_plus:
1217 case '*':
1218
1219 if (!laststart)
1220 {
1221 if (syntax & RE_CONTEXT_INVALID_OPS)
1222 return REG_BADRPT;
1223 else if (!(syntax & RE_CONTEXT_INDEP_OPS))
1224 goto normal_char;
1225 }
1226
1227 {
1228
1229 boolean keep_string_p = false;
1230
1231
1232 char zero_times_ok = 0, many_times_ok = 0;
1233
1234
1235
1236
1237
1238
1239 for (;;)
1240 {
1241 zero_times_ok |= c != '+';
1242 many_times_ok |= c != '?';
1243
1244 if (p == pend)
1245 break;
1246
1247 PATFETCH (c);
1248
1249 if (c == '*'
1250 || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
1251 ;
1252
1253 else if (syntax & RE_BK_PLUS_QM && c == '\\')
1254 {
1255 if (p == pend) return REG_EESCAPE;
1256
1257 PATFETCH (c1);
1258 if (!(c1 == '+' || c1 == '?'))
1259 {
1260 PATUNFETCH;
1261 PATUNFETCH;
1262 break;
1263 }
1264
1265 c = c1;
1266 }
1267 else
1268 {
1269 PATUNFETCH;
1270 break;
1271 }
1272
1273
1274 }
1275
1276
1277
1278 if (!laststart)
1279 break;
1280
1281
1282
1283 if (many_times_ok)
1284 {
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294 assert (p - 1 > pattern);
1295
1296
1297 GET_BUFFER_SPACE (3);
1298
1299
1300
1301
1302
1303
1304 if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
1305 && zero_times_ok
1306 && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
1307 && !(syntax & RE_DOT_NEWLINE))
1308 {
1309 STORE_JUMP (jump, b, laststart);
1310 keep_string_p = true;
1311 }
1312 else
1313
1314 STORE_JUMP (maybe_pop_jump, b, laststart - 3);
1315
1316
1317 b += 3;
1318 }
1319
1320
1321
1322 GET_BUFFER_SPACE (3);
1323 INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
1324 : on_failure_jump,
1325 laststart, b + 3);
1326 pending_exact = 0;
1327 b += 3;
1328
1329 if (!zero_times_ok)
1330 {
1331
1332
1333
1334
1335
1336 GET_BUFFER_SPACE (3);
1337 INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
1338 b += 3;
1339 }
1340 }
1341 break;
1342
1343
1344 case '.':
1345 laststart = b;
1346 BUF_PUSH (anychar);
1347 break;
1348
1349
1350 case '[':
1351 {
1352 boolean had_char_class = false;
1353
1354 if (p == pend) return REG_EBRACK;
1355
1356
1357
1358 GET_BUFFER_SPACE (34);
1359
1360 laststart = b;
1361
1362
1363
1364 BUF_PUSH (*p == '^' ? charset_not : charset);
1365 if (*p == '^')
1366 p++;
1367
1368
1369 p1 = p;
1370
1371
1372 BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
1373
1374
1375 bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
1376
1377
1378 if ((re_opcode_t) b[-2] == charset_not
1379 && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
1380 SET_LIST_BIT ('\n');
1381
1382
1383 for (;;)
1384 {
1385 if (p == pend) return REG_EBRACK;
1386
1387 PATFETCH (c);
1388
1389
1390 if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
1391 {
1392 if (p == pend) return REG_EESCAPE;
1393
1394 PATFETCH (c1);
1395 SET_LIST_BIT (c1);
1396 continue;
1397 }
1398
1399
1400
1401
1402 if (c == ']' && p != p1 + 1)
1403 break;
1404
1405
1406
1407 if (had_char_class && c == '-' && *p != ']')
1408 return REG_ERANGE;
1409
1410
1411
1412
1413
1414 if (c == '-'
1415 && !(p - 2 >= pattern && p[-2] == '[')
1416 && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
1417 && *p != ']')
1418 {
1419 reg_errcode_t ret
1420 = compile_range (&p, pend, translate, syntax, b);
1421 if (ret != REG_NOERROR) return ret;
1422 }
1423
1424 else if (p[0] == '-' && p[1] != ']')
1425 {
1426 reg_errcode_t ret;
1427
1428
1429 PATFETCH (c1);
1430
1431 ret = compile_range (&p, pend, translate, syntax, b);
1432 if (ret != REG_NOERROR) return ret;
1433 }
1434
1435
1436
1437
1438 else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
1439 {
1440 char str[CHAR_CLASS_MAX_LENGTH + 1];
1441
1442 PATFETCH (c);
1443 c1 = 0;
1444
1445
1446 if (p == pend) return REG_EBRACK;
1447
1448 for (;;)
1449 {
1450 PATFETCH (c);
1451 if (c == ':' || c == ']' || p == pend
1452 || c1 == CHAR_CLASS_MAX_LENGTH)
1453 break;
1454 str[c1++] = c;
1455 }
1456 str[c1] = '\0';
1457
1458
1459
1460
1461 if (c == ':' && *p == ']')
1462 {
1463 int ch;
1464 boolean is_alnum = STREQ (str, "alnum");
1465 boolean is_alpha = STREQ (str, "alpha");
1466 boolean is_blank = STREQ (str, "blank");
1467 boolean is_cntrl = STREQ (str, "cntrl");
1468 boolean is_digit = STREQ (str, "digit");
1469 boolean is_graph = STREQ (str, "graph");
1470 boolean is_lower = STREQ (str, "lower");
1471 boolean is_print = STREQ (str, "print");
1472 boolean is_punct = STREQ (str, "punct");
1473 boolean is_space = STREQ (str, "space");
1474 boolean is_upper = STREQ (str, "upper");
1475 boolean is_xdigit = STREQ (str, "xdigit");
1476
1477 if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
1478
1479
1480
1481 PATFETCH (c);
1482
1483 if (p == pend) return REG_EBRACK;
1484
1485 for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
1486 {
1487 if ( (is_alnum && ISALNUM (ch))
1488 || (is_alpha && ISALPHA (ch))
1489 || (is_blank && ISBLANK (ch))
1490 || (is_cntrl && ISCNTRL (ch))
1491 || (is_digit && ISDIGIT (ch))
1492 || (is_graph && ISGRAPH (ch))
1493 || (is_lower && ISLOWER (ch))
1494 || (is_print && ISPRINT (ch))
1495 || (is_punct && ISPUNCT (ch))
1496 || (is_space && ISSPACE (ch))
1497 || (is_upper && ISUPPER (ch))
1498 || (is_xdigit && ISXDIGIT (ch)))
1499 SET_LIST_BIT (ch);
1500 }
1501 had_char_class = true;
1502 }
1503 else
1504 {
1505 c1++;
1506 while (c1--)
1507 PATUNFETCH;
1508 SET_LIST_BIT ('[');
1509 SET_LIST_BIT (':');
1510 had_char_class = false;
1511 }
1512 }
1513 else
1514 {
1515 had_char_class = false;
1516 SET_LIST_BIT (c);
1517 }
1518 }
1519
1520
1521
1522 while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
1523 b[-1]--;
1524 b += b[-1];
1525 }
1526 break;
1527
1528
1529 case '(':
1530 if (syntax & RE_NO_BK_PARENS)
1531 goto handle_open;
1532 else
1533 goto normal_char;
1534
1535
1536 case ')':
1537 if (syntax & RE_NO_BK_PARENS)
1538 goto handle_close;
1539 else
1540 goto normal_char;
1541
1542
1543 case '\n':
1544 if (syntax & RE_NEWLINE_ALT)
1545 goto handle_alt;
1546 else
1547 goto normal_char;
1548
1549
1550 case '|':
1551 if (syntax & RE_NO_BK_VBAR)
1552 goto handle_alt;
1553 else
1554 goto normal_char;
1555
1556
1557 case '{':
1558 if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
1559 goto handle_interval;
1560 else
1561 goto normal_char;
1562
1563
1564 case '\\':
1565 if (p == pend) return REG_EESCAPE;
1566
1567
1568
1569
1570 PATFETCH_RAW (c);
1571
1572 switch (c)
1573 {
1574 case '(':
1575 if (syntax & RE_NO_BK_PARENS)
1576 goto normal_backslash;
1577
1578 handle_open:
1579 bufp->re_nsub++;
1580 regnum++;
1581
1582 if (COMPILE_STACK_FULL)
1583 {
1584 RETALLOC (compile_stack.stack, compile_stack.size << 1,
1585 compile_stack_elt_t);
1586 if (compile_stack.stack == NULL) return REG_ESPACE;
1587
1588 compile_stack.size <<= 1;
1589 }
1590
1591
1592
1593
1594
1595 COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
1596 COMPILE_STACK_TOP.fixup_alt_jump
1597 = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
1598 COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
1599 COMPILE_STACK_TOP.regnum = regnum;
1600
1601
1602
1603
1604
1605 if (regnum <= MAX_REGNUM)
1606 {
1607 COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
1608 BUF_PUSH_3 (start_memory, regnum, 0);
1609 }
1610
1611 compile_stack.avail++;
1612
1613 fixup_alt_jump = 0;
1614 laststart = 0;
1615 begalt = b;
1616
1617
1618
1619 pending_exact = 0;
1620 break;
1621
1622
1623 case ')':
1624 if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
1625
1626 if (COMPILE_STACK_EMPTY)
1627 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
1628 goto normal_backslash;
1629 else
1630 return REG_ERPAREN;
1631
1632 handle_close:
1633 if (fixup_alt_jump)
1634 {
1635
1636
1637
1638 BUF_PUSH (push_dummy_failure);
1639
1640
1641
1642 STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
1643 }
1644
1645
1646 if (COMPILE_STACK_EMPTY)
1647 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
1648 goto normal_char;
1649 else
1650 return REG_ERPAREN;
1651
1652
1653
1654 assert (compile_stack.avail != 0);
1655 {
1656
1657
1658
1659 regnum_t this_group_regnum;
1660
1661 compile_stack.avail--;
1662 begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
1663 fixup_alt_jump
1664 = COMPILE_STACK_TOP.fixup_alt_jump
1665 ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
1666 : 0;
1667 laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
1668 this_group_regnum = COMPILE_STACK_TOP.regnum;
1669
1670
1671
1672 pending_exact = 0;
1673
1674
1675
1676 if (this_group_regnum <= MAX_REGNUM)
1677 {
1678 unsigned char *inner_group_loc
1679 = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
1680
1681 *inner_group_loc = regnum - this_group_regnum;
1682 BUF_PUSH_3 (stop_memory, this_group_regnum,
1683 regnum - this_group_regnum);
1684 }
1685 }
1686 break;
1687
1688
1689 case '|':
1690 if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
1691 goto normal_backslash;
1692 handle_alt:
1693 if (syntax & RE_LIMITED_OPS)
1694 goto normal_char;
1695
1696
1697
1698 GET_BUFFER_SPACE (3);
1699 INSERT_JUMP (on_failure_jump, begalt, b + 6);
1700 pending_exact = 0;
1701 b += 3;
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719 if (fixup_alt_jump)
1720 STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
1721
1722
1723
1724
1725 fixup_alt_jump = b;
1726 GET_BUFFER_SPACE (3);
1727 b += 3;
1728
1729 laststart = 0;
1730 begalt = b;
1731 break;
1732
1733
1734 case '{':
1735
1736 if (!(syntax & RE_INTERVALS)
1737
1738
1739 || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1740 || (p - 2 == pattern && p == pend))
1741 goto normal_backslash;
1742
1743 handle_interval:
1744 {
1745
1746
1747
1748 int lower_bound = -1, upper_bound = -1;
1749
1750 beg_interval = p - 1;
1751
1752 if (p == pend)
1753 {
1754 if (syntax & RE_NO_BK_BRACES)
1755 goto unfetch_interval;
1756 else
1757 return REG_EBRACE;
1758 }
1759
1760 GET_UNSIGNED_NUMBER (lower_bound);
1761
1762 if (c == ',')
1763 {
1764 GET_UNSIGNED_NUMBER (upper_bound);
1765 if (upper_bound < 0) upper_bound = RE_DUP_MAX;
1766 }
1767 else
1768
1769 upper_bound = lower_bound;
1770
1771 if (lower_bound < 0 || upper_bound > RE_DUP_MAX
1772 || lower_bound > upper_bound)
1773 {
1774 if (syntax & RE_NO_BK_BRACES)
1775 goto unfetch_interval;
1776 else
1777 return REG_BADBR;
1778 }
1779
1780 if (!(syntax & RE_NO_BK_BRACES))
1781 {
1782 if (c != '\\') return REG_EBRACE;
1783
1784 PATFETCH (c);
1785 }
1786
1787 if (c != '}')
1788 {
1789 if (syntax & RE_NO_BK_BRACES)
1790 goto unfetch_interval;
1791 else
1792 return REG_BADBR;
1793 }
1794
1795
1796
1797
1798 if (!laststart)
1799 {
1800 if (syntax & RE_CONTEXT_INVALID_OPS)
1801 return REG_BADRPT;
1802 else if (syntax & RE_CONTEXT_INDEP_OPS)
1803 laststart = b;
1804 else
1805 goto unfetch_interval;
1806 }
1807
1808
1809
1810
1811 if (upper_bound == 0)
1812 {
1813 GET_BUFFER_SPACE (3);
1814 INSERT_JUMP (jump, laststart, b + 3);
1815 b += 3;
1816 }
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827 else
1828 {
1829
1830 unsigned nbytes = 10 + (upper_bound > 1) * 10;
1831
1832 GET_BUFFER_SPACE (nbytes);
1833
1834
1835
1836
1837
1838
1839 INSERT_JUMP2 (succeed_n, laststart,
1840 b + 5 + (upper_bound > 1) * 5,
1841 lower_bound);
1842 b += 5;
1843
1844
1845
1846
1847
1848 insert_op2 (set_number_at, laststart, 5, lower_bound, b);
1849 b += 5;
1850
1851 if (upper_bound > 1)
1852 {
1853
1854
1855
1856
1857
1858
1859 STORE_JUMP2 (jump_n, b, laststart + 5,
1860 upper_bound - 1);
1861 b += 5;
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 insert_op2 (set_number_at, laststart, b - laststart,
1878 upper_bound - 1, b);
1879 b += 5;
1880 }
1881 }
1882 pending_exact = 0;
1883 beg_interval = NULL;
1884 }
1885 break;
1886
1887 unfetch_interval:
1888
1889 assert (beg_interval);
1890 p = beg_interval;
1891 beg_interval = NULL;
1892
1893
1894 PATFETCH (c);
1895
1896 if (!(syntax & RE_NO_BK_BRACES))
1897 {
1898 if (p > pattern && p[-1] == '\\')
1899 goto normal_backslash;
1900 }
1901 goto normal_char;
1902
1903#ifdef emacs
1904
1905
1906 case '=':
1907 BUF_PUSH (at_dot);
1908 break;
1909
1910 case 's':
1911 laststart = b;
1912 PATFETCH (c);
1913 BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
1914 break;
1915
1916 case 'S':
1917 laststart = b;
1918 PATFETCH (c);
1919 BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
1920 break;
1921#endif
1922
1923
1924 case 'w':
1925 laststart = b;
1926 BUF_PUSH (wordchar);
1927 break;
1928
1929
1930 case 'W':
1931 laststart = b;
1932 BUF_PUSH (notwordchar);
1933 break;
1934
1935
1936 case '<':
1937 BUF_PUSH (wordbeg);
1938 break;
1939
1940 case '>':
1941 BUF_PUSH (wordend);
1942 break;
1943
1944 case 'b':
1945 BUF_PUSH (wordbound);
1946 break;
1947
1948 case 'B':
1949 BUF_PUSH (notwordbound);
1950 break;
1951
1952 case '`':
1953 BUF_PUSH (begbuf);
1954 break;
1955
1956 case '\'':
1957 BUF_PUSH (endbuf);
1958 break;
1959
1960 case '1': case '2': case '3': case '4': case '5':
1961 case '6': case '7': case '8': case '9':
1962 if (syntax & RE_NO_BK_REFS)
1963 goto normal_char;
1964
1965 c1 = c - '0';
1966
1967 if (c1 > regnum)
1968 return REG_ESUBREG;
1969
1970
1971 if (group_in_compile_stack (compile_stack, c1))
1972 goto normal_char;
1973
1974 laststart = b;
1975 BUF_PUSH_2 (duplicate, c1);
1976 break;
1977
1978
1979 case '+':
1980 case '?':
1981 if (syntax & RE_BK_PLUS_QM)
1982 goto handle_plus;
1983 else
1984 goto normal_backslash;
1985
1986 default:
1987 normal_backslash:
1988
1989
1990
1991 c = TRANSLATE (c);
1992 goto normal_char;
1993 }
1994 break;
1995
1996
1997 default:
1998
1999 normal_char:
2000
2001 if (!pending_exact
2002
2003
2004 || pending_exact + *pending_exact + 1 != b
2005
2006
2007 || *pending_exact == (1 << BYTEWIDTH) - 1
2008
2009
2010 || *p == '*' || *p == '^'
2011 || ((syntax & RE_BK_PLUS_QM)
2012 ? *p == '\\' && (p[1] == '+' || p[1] == '?')
2013 : (*p == '+' || *p == '?'))
2014 || ((syntax & RE_INTERVALS)
2015 && ((syntax & RE_NO_BK_BRACES)
2016 ? *p == '{'
2017 : (p[0] == '\\' && p[1] == '{'))))
2018 {
2019
2020
2021 laststart = b;
2022
2023 BUF_PUSH_2 (exactn, 0);
2024 pending_exact = b - 1;
2025 }
2026
2027 BUF_PUSH (c);
2028 (*pending_exact)++;
2029 break;
2030 }
2031 }
2032
2033
2034
2035
2036 if (fixup_alt_jump)
2037 STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
2038
2039 if (!COMPILE_STACK_EMPTY)
2040 return REG_EPAREN;
2041
2042 free (compile_stack.stack);
2043
2044
2045 bufp->used = b - bufp->buffer;
2046
2047#ifdef DEBUG
2048 if (debug)
2049 {
2050 DEBUG_PRINT1 ("\nCompiled pattern: ");
2051 print_compiled_pattern (bufp);
2052 }
2053#endif
2054
2055 return REG_NOERROR;
2056}
2057
2058
2059
2060
2061
2062static void
2063store_op1 (op, loc, arg)
2064 re_opcode_t op;
2065 unsigned char *loc;
2066 int arg;
2067{
2068 *loc = (unsigned char) op;
2069 STORE_NUMBER (loc + 1, arg);
2070}
2071
2072
2073
2074
2075static void
2076store_op2 (op, loc, arg1, arg2)
2077 re_opcode_t op;
2078 unsigned char *loc;
2079 int arg1, arg2;
2080{
2081 *loc = (unsigned char) op;
2082 STORE_NUMBER (loc + 1, arg1);
2083 STORE_NUMBER (loc + 3, arg2);
2084}
2085
2086
2087
2088
2089
2090static void
2091insert_op1 (op, loc, arg, end)
2092 re_opcode_t op;
2093 unsigned char *loc;
2094 int arg;
2095 unsigned char *end;
2096{
2097 register unsigned char *pfrom = end;
2098 register unsigned char *pto = end + 3;
2099
2100 while (pfrom != loc)
2101 *--pto = *--pfrom;
2102
2103 store_op1 (op, loc, arg);
2104}
2105
2106
2107
2108
2109static void
2110insert_op2 (op, loc, arg1, arg2, end)
2111 re_opcode_t op;
2112 unsigned char *loc;
2113 int arg1, arg2;
2114 unsigned char *end;
2115{
2116 register unsigned char *pfrom = end;
2117 register unsigned char *pto = end + 5;
2118
2119 while (pfrom != loc)
2120 *--pto = *--pfrom;
2121
2122 store_op2 (op, loc, arg1, arg2);
2123}
2124
2125
2126
2127
2128
2129
2130static boolean
2131at_begline_loc_p (pattern, p, syntax)
2132 const char *pattern, *p;
2133 reg_syntax_t syntax;
2134{
2135 const char *prev = p - 2;
2136 boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
2137
2138 return
2139
2140 (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
2141
2142 || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
2143}
2144
2145
2146
2147
2148