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

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25