1 /*        $NetBSD: regex2.h,v 1.16 2025/01/01 18:19:50 christos Exp $ */
2 
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (c) 1992, 1993, 1994 Henry Spencer.
7  * Copyright (c) 1992, 1993, 1994
8  *        The Regents of the University of California.  All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Henry Spencer.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *        @(#)regex2.h        8.4 (Berkeley) 3/20/94
38  * $FreeBSD: head/lib/libc/regex/regex2.h 368359 2020-12-05 03:18:48Z kevans $
39  */
40 
41 /*
42  * First, the stuff that ends up in the outside-world include file
43  = typedef off_t regoff_t;
44  = typedef struct {
45  =        int re_magic;
46  =        size_t re_nsub;               // number of parenthesized subexpressions
47  =        const char *re_endp;          // end pointer for REG_PEND
48  =        struct re_guts *re_g;         // none of your business :-)
49  = } regex_t;
50  = typedef struct {
51  =        regoff_t rm_so;               // start of match
52  =        regoff_t rm_eo;               // end of match
53  = } regmatch_t;
54  */
55 /*
56  * internals of regex_t
57  */
58 #define   MAGIC1    ((('r'^0200)<<8) | 'e')
59 
60 /*
61  * The internal representation is a *strip*, a sequence of
62  * operators ending with an endmarker.  (Some terminology etc. is a
63  * historical relic of earlier versions which used multiple strips.)
64  * Certain oddities in the representation are there to permit running
65  * the machinery backwards; in particular, any deviation from sequential
66  * flow must be marked at both its source and its destination.  Some
67  * fine points:
68  *
69  * - OPLUS_ and O_PLUS are *inside* the loop they create.
70  * - OQUEST_ and O_QUEST are *outside* the bypass they create.
71  * - OCH_ and O_CH are *outside* the multi-way branch they create, while
72  *   OOR1 and OOR2 are respectively the end and the beginning of one of
73  *   the branches.  Note that there is an implicit OOR2 following OCH_
74  *   and an implicit OOR1 preceding O_CH.
75  *
76  * In state representations, an operator's bit is on to signify a state
77  * immediately *preceding* "execution" of that operator.
78  */
79 typedef uint32_t sop;         /* strip operator */
80 typedef uint32_t sopno;
81 #define   OPRMASK   0xf8000000U
82 #define   OPDMASK   0x07ffffffU
83 #define   OPSHIFT   (27U)
84 #define   OP(n)     ((n)&OPRMASK)
85 #define   OPND(n)   ((n)&OPDMASK)
86 #define   SOP(op, opnd)       ((op)|(opnd))
87 /* operators                               meaning          operand                       */
88 /*                                                          (back, fwd are offsets)       */
89 #define   OEND      (1U<<OPSHIFT)       /* endmarker        -                             */
90 #define   OCHAR     (2U<<OPSHIFT)       /* character        wide character                */
91 #define   OBOL      (3U<<OPSHIFT)       /* left anchor      -                             */
92 #define   OEOL      (4U<<OPSHIFT)       /* right anchor     -                             */
93 #define   OANY      (5U<<OPSHIFT)       /* .                -                             */
94 #define   OANYOF    (6U<<OPSHIFT)       /* [...]  set number                    */
95 #define   OBACK_    (7U<<OPSHIFT)       /* begin \d         paren number                  */
96 #define   O_BACK    (8U<<OPSHIFT)       /* end \d paren number                  */
97 #define   OPLUS_    (9U<<OPSHIFT)       /* + prefix         fwd to suffix                 */
98 #define   O_PLUS    (10U<<OPSHIFT)      /* + suffix         back to prefix                */
99 #define   OQUEST_   (11U<<OPSHIFT)      /* ? prefix         fwd to suffix                 */
100 #define   O_QUEST   (12U<<OPSHIFT)      /* ? suffix         back to prefix                */
101 #define   OLPAREN   (13U<<OPSHIFT)      /* (                fwd to )            */
102 #define   ORPAREN   (14U<<OPSHIFT)      /* )                back to (           */
103 #define   OCH_      (15U<<OPSHIFT)      /* begin choice     fwd to OOR2                   */
104 #define   OOR1      (16U<<OPSHIFT)      /* | pt. 1          back to OOR1 or OCH_          */
105 #define   OOR2      (17U<<OPSHIFT)      /* | pt. 2          fwd to OOR2 or O_CH */
106 #define   O_CH      (18U<<OPSHIFT)      /* end choice       back to OOR1                  */
107 #define   OBOW      (19U<<OPSHIFT)      /* begin word       -                             */
108 #define   OEOW      (20U<<OPSHIFT)      /* end word         -                             */
109 #define   OBOS      (21U<<OPSHIFT)      /* begin subj.  -                       */
110 #define   OEOS      (22U<<OPSHIFT)      /* end subj.        -                             */
111 #define   OWBND     (23U<<OPSHIFT)      /* word bound       -                             */
112 #define   ONWBND    (24U<<OPSHIFT)      /* not bound        -                             */
113 
114 /*
115  * Structures for [] character-set representation.
116  */
117 typedef struct {
118           wint_t              min;
119           wint_t              max;
120 } crange;
121 typedef struct {
122           unsigned char       bmp[NC_MAX / 8];
123           wctype_t  *types;
124           unsigned int        ntypes;
125           wint_t              *wides;
126           unsigned int        nwides;
127           crange              *ranges;
128           unsigned int        nranges;
129           int                 invert;
130           int                 icase;
131 } cset;
132 
133 static int
CHIN1(cset * cs,wint_t ch)134 CHIN1(cset *cs, wint_t ch)
135 {
136           unsigned int i;
137 
138           if ((unsigned)ch < NC)
139                     return (((cs->bmp[(unsigned)ch >> 3] & (1 << (ch & 7))) != 0) ^
140                         cs->invert);
141           for (i = 0; i < cs->nwides; i++) {
142                     if (cs->icase) {
143                               if (ch == towlower(cs->wides[i]) ||
144                                   ch == towupper(cs->wides[i]))
145                                         return (!cs->invert);
146                     } else if (ch == cs->wides[i])
147                               return (!cs->invert);
148           }
149           for (i = 0; i < cs->nranges; i++)
150                     if (cs->ranges[i].min <= ch && ch <= cs->ranges[i].max)
151                               return (!cs->invert);
152           for (i = 0; i < cs->ntypes; i++)
153                     if (iswctype(ch, cs->types[i]))
154                               return (!cs->invert);
155           return (cs->invert);
156 }
157 
158 static __inline int
CHIN(cset * cs,wint_t ch)159 CHIN(cset *cs, wint_t ch)
160 {
161 
162           if ((unsigned)ch < NC)
163                     return (((cs->bmp[(unsigned)ch >> 3] & (1 << (ch & 7))) != 0) ^
164                         cs->invert);
165           else if (cs->icase)
166                     return (CHIN1(cs, ch) || CHIN1(cs, towlower(ch)) ||
167                         CHIN1(cs, towupper(ch)));
168           else
169                     return (CHIN1(cs, ch));
170 }
171 
172 /*
173  * main compiled-expression structure
174  */
175 struct re_guts {
176           int magic;
177 #                   define    MAGIC2    ((('R'^0200)<<8)|'E')
178           sop *strip;                   /* malloced area for strip */
179           size_t ncsets;                /* number of csets in use */
180           cset *sets;                   /* -> cset [ncsets] */
181           int cflags;                   /* copy of regcomp() cflags argument */
182           sopno nstates;                /* = number of sops */
183           sopno firststate;   /* the initial OEND (normally 0) */
184           sopno laststate;    /* the final OEND */
185           int iflags;                   /* internal flags */
186 #                   define    USEBOL    01        /* used ^ */
187 #                   define    USEEOL    02        /* used $ */
188 #                   define    BAD       04        /* something wrong */
189           size_t nbol;                  /* number of ^ used */
190           size_t neol;                  /* number of $ used */
191           char *must;                   /* match must contain this string */
192           int moffset;                  /* latest point at which must may be located */
193           size_t *charjump;   /* Boyer-Moore char jump table */
194           size_t *matchjump;  /* Boyer-Moore match jump table */
195           size_t mlen;                  /* length of must */
196           size_t nsub;                  /* copy of re_nsub */
197           int backrefs;                 /* does it use back references? */
198           sopno nplus;                  /* how deep does it nest +s? */
199 };
200 
201 /* misc utilities */
202 #define   OUT       (CHAR_MIN - 1)      /* a non-character value */
203 #define   IGN       (CHAR_MIN - 2)
204 #define ISWORD(c)       (iswalnum((uch)(c)) || (c) == '_')
205