/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/regc_lex.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/regc_lex.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.70  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25