ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rexpr.c
Revision: 2.8
Committed: Mon Jun 30 14:59:11 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.7: +1 -4 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 2.8 static const char RCSid[] = "$Id: rexpr.c,v 2.7 2003/06/07 12:50:20 schorsch Exp $";
3 greg 1.1 #endif
4 greg 2.4 /*
5     * Regular expression parsing routines.
6     *
7     * External symbols declared in standard.h
8     */
9    
10 greg 2.5 #include "copyright.h"
11 greg 1.1
12     #include <stdio.h>
13 greg 2.4 #include <stdlib.h>
14 greg 1.1 #include <ctype.h>
15 schorsch 2.7 #include <string.h>
16    
17 greg 1.1 /*
18     * rexpr.c - regular expression parser (ala grep)
19     */
20    
21     #define CCHR 2
22     #define CDOT 4
23     #define CCL 6
24     #define NCCL 8
25     #define CDOL 10
26     #define CEOF 11
27     #define CBRC 14
28     #define CLET 15
29     #define STAR 01
30    
31     #define ESIZE 255
32    
33     #define same(a,b) (a==b || (iflag && (a^b)==' ' && isalpha(a)))
34    
35 greg 1.2
36 greg 1.4 static int advance(), cclass();
37    
38 greg 1.1 static char expbuf[ESIZE];
39     static int iflag;
40     static int circf;
41    
42     int explen; /* length of the last expression found */
43    
44     int
45     ecompile(sp, iflg, wflag) /* compile the expression */
46     register char *sp;
47     int iflg, wflag;
48     {
49     register c;
50     register char *ep;
51     char *lastep;
52     int cclcnt;
53    
54     iflag = iflg;
55     ep = expbuf;
56     explen = 0;
57     if (*sp == '^') {
58     circf = 1;
59     sp++;
60     } else
61     circf = 0;
62     if (wflag)
63     *ep++ = CBRC;
64     for (;;) {
65     if (ep >= &expbuf[ESIZE])
66     return(-1);
67     if ((c = *sp++) != '*')
68     lastep = ep;
69     switch (c) {
70    
71     case '\0':
72     if (wflag)
73     *ep++ = CLET;
74     *ep++ = CEOF;
75     explen = ep - expbuf;
76     return(0);
77    
78     case '.':
79     *ep++ = CDOT;
80     continue;
81    
82     case '*':
83     if (lastep==0)
84     goto defchar;
85     *lastep |= STAR;
86     continue;
87    
88     case '$':
89     if (*sp != '\0')
90     goto defchar;
91     *ep++ = CDOL;
92     continue;
93    
94     case '[':
95     *ep++ = CCL;
96     *ep++ = 0;
97     cclcnt = 1;
98     if ((c = *sp++) == '^') {
99     c = *sp++;
100     ep[-2] = NCCL;
101     }
102     do {
103     *ep++ = c;
104     cclcnt++;
105     if (c=='\0' || ep >= &expbuf[ESIZE])
106     return(-1);
107     } while ((c = *sp++) != ']');
108     lastep[1] = cclcnt;
109     continue;
110    
111     case '\\':
112     if ((c = *sp++) == '\0')
113     return(-1);
114     if (c == '<') {
115 greg 2.2 if (ep == expbuf || ep[-1] != CBRC)
116     *ep++ = CBRC;
117 greg 1.1 continue;
118     }
119     if (c == '>') {
120     *ep++ = CLET;
121     continue;
122     }
123     defchar:
124     default:
125     *ep++ = CCHR;
126     *ep++ = c;
127     }
128     }
129     }
130    
131     char *
132     expsave() /* save compiled string */
133     {
134     register char *ep;
135    
136     if (explen == 0)
137     return(NULL);
138 greg 2.4 if ((ep = (char *)malloc(explen+3)) == NULL)
139 greg 1.1 return(NULL);
140     ep[0] = iflag;
141     ep[1] = circf;
142     ep[2] = explen;
143     (void)memcpy(ep+3, expbuf, explen);
144     return(ep);
145     }
146    
147 greg 2.4 void
148 greg 1.1 expset(ep) /* install saved string */
149     register char *ep;
150     {
151     iflag = ep[0];
152     circf = ep[1];
153     (void)memcpy(expbuf, ep+3, ep[2]&0xff);
154     }
155    
156     char *
157 greg 2.2 eindex(sp) /* find the expression in string sp */
158 greg 1.1 register char *sp;
159     {
160 greg 2.2 /* check for match at beginning of line, watch CBRC */
161     if (advance(sp, expbuf[0]==CBRC ? expbuf+1 : expbuf))
162     return(sp);
163     if (circf)
164 greg 1.1 return(NULL);
165     /* fast check for first character */
166     if (expbuf[0]==CCHR) {
167     register c = expbuf[1];
168 greg 2.2 while (*++sp)
169 greg 1.1 if (same(*sp, c) && advance(sp, expbuf))
170     return(sp);
171     return(NULL);
172     }
173     /* regular algorithm */
174 greg 2.2 while (*++sp)
175 greg 1.1 if (advance(sp, expbuf))
176     return(sp);
177     return(NULL);
178     }
179    
180     static int
181     advance(alp, ep)
182     char *alp;
183     register char *ep;
184     {
185     register char *lp;
186     char *curlp;
187    
188     lp = alp;
189     for (;;) switch (*ep++) {
190    
191     case CCHR:
192     if (!same(*ep, *lp))
193     return (0);
194     ep++, lp++;
195     continue;
196    
197     case CDOT:
198     if (*lp++)
199     continue;
200     return(0);
201    
202     case CDOL:
203     if (*lp==0)
204     continue;
205     return(0);
206    
207     case CEOF:
208     explen = lp - alp;
209     return(1);
210    
211     case CCL:
212     if (cclass(ep, *lp++, 1)) {
213     ep += *ep;
214     continue;
215     }
216     return(0);
217    
218     case NCCL:
219     if (cclass(ep, *lp++, 0)) {
220     ep += *ep;
221     continue;
222     }
223     return(0);
224    
225     case CDOT|STAR:
226     curlp = lp;
227     while (*lp++);
228     goto star;
229    
230     case CCHR|STAR:
231     curlp = lp;
232     while (same(*lp, *ep))
233     lp++;
234     lp++;
235     ep++;
236     goto star;
237    
238     case CCL|STAR:
239     case NCCL|STAR:
240     curlp = lp;
241     while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
242     ep += *ep;
243     star:
244     do {
245     lp--;
246     if (advance(lp, ep)) {
247     explen += lp - alp;
248     return(1);
249     }
250     } while (lp > curlp);
251     return(0);
252    
253     case CBRC:
254     if ((isalnum(*lp) || *lp == '_') && !(isalnum(lp[-1]) || lp[-1] == '_'))
255     continue;
256     return (0);
257    
258     case CLET:
259     if (!isalnum(*lp) && *lp != '_')
260     continue;
261     return (0);
262    
263     default:
264     fprintf(stderr, "RE botch\n");
265     }
266     }
267    
268     static int
269     cclass(set, c, af)
270     register char *set;
271     register c;
272 greg 2.3 int af;
273 greg 1.1 {
274     register n;
275    
276     if (c == 0)
277     return(0);
278     n = *set++;
279     while (--n)
280     if (n > 2 && set[1] == '-') {
281     if (c >= set[0] && c <= set[2])
282     return (af);
283     set += 3;
284     n -= 2;
285     } else
286     if (*set++ == c)
287     return(af);
288     return(!af);
289     }