| @@ -1,623 +1,653 @@ | | | @@ -1,623 +1,653 @@ |
1 | %{ | | 1 | %{ |
2 | /* $NetBSD: scan.l,v 1.29 2020/03/08 00:04:11 christos Exp $ */ | | 2 | /* $NetBSD: scan.l,v 1.30 2020/03/08 17:38:37 christos Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 1992, 1993 | | 5 | * Copyright (c) 1992, 1993 |
6 | * The Regents of the University of California. All rights reserved. | | 6 | * The Regents of the University of California. All rights reserved. |
7 | * | | 7 | * |
8 | * This software was developed by the Computer Systems Engineering group | | 8 | * This software was developed by the Computer Systems Engineering group |
9 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | | 9 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and |
10 | * contributed to Berkeley. | | 10 | * contributed to Berkeley. |
11 | * | | 11 | * |
12 | * All advertising materials mentioning features or use of this software | | 12 | * All advertising materials mentioning features or use of this software |
13 | * must display the following acknowledgement: | | 13 | * must display the following acknowledgement: |
14 | * This product includes software developed by the University of | | 14 | * This product includes software developed by the University of |
15 | * California, Lawrence Berkeley Laboratories. | | 15 | * California, Lawrence Berkeley Laboratories. |
16 | * | | 16 | * |
17 | * Redistribution and use in source and binary forms, with or without | | 17 | * Redistribution and use in source and binary forms, with or without |
18 | * modification, are permitted provided that the following conditions | | 18 | * modification, are permitted provided that the following conditions |
19 | * are met: | | 19 | * are met: |
20 | * 1. Redistributions of source code must retain the above copyright | | 20 | * 1. Redistributions of source code must retain the above copyright |
21 | * notice, this list of conditions and the following disclaimer. | | 21 | * notice, this list of conditions and the following disclaimer. |
22 | * 2. Redistributions in binary form must reproduce the above copyright | | 22 | * 2. Redistributions in binary form must reproduce the above copyright |
23 | * notice, this list of conditions and the following disclaimer in the | | 23 | * notice, this list of conditions and the following disclaimer in the |
24 | * documentation and/or other materials provided with the distribution. | | 24 | * documentation and/or other materials provided with the distribution. |
25 | * 3. Neither the name of the University nor the names of its contributors | | 25 | * 3. Neither the name of the University nor the names of its contributors |
26 | * may be used to endorse or promote products derived from this software | | 26 | * may be used to endorse or promote products derived from this software |
27 | * without specific prior written permission. | | 27 | * without specific prior written permission. |
28 | * | | 28 | * |
29 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 29 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
39 | * SUCH DAMAGE. | | 39 | * SUCH DAMAGE. |
40 | * | | 40 | * |
41 | * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 | | 41 | * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
45 | __RCSID("$NetBSD: scan.l,v 1.29 2020/03/08 00:04:11 christos Exp $"); | | 45 | __RCSID("$NetBSD: scan.l,v 1.30 2020/03/08 17:38:37 christos Exp $"); |
46 | | | 46 | |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <errno.h> | | 48 | #include <errno.h> |
49 | #include <libgen.h> | | 49 | #include <libgen.h> |
50 | #include <stdio.h> | | 50 | #include <stdio.h> |
51 | #include <stdlib.h> | | 51 | #include <stdlib.h> |
52 | #include <string.h> | | 52 | #include <string.h> |
53 | #include <unistd.h> | | 53 | #include <unistd.h> |
54 | #include <stddef.h> | | 54 | #include <stddef.h> |
55 | #include <ctype.h> | | 55 | #include <ctype.h> |
56 | #include <util.h> | | 56 | #include <util.h> |
57 | #undef ECHO | | 57 | #undef ECHO |
58 | #include "defs.h" | | 58 | #include "defs.h" |
59 | #include "gram.h" | | 59 | #include "gram.h" |
60 | | | 60 | |
61 | int yyline; | | 61 | int yyline; |
62 | const char *yyfile; | | 62 | const char *yyfile; |
63 | const char *lastfile; | | 63 | const char *lastfile; |
64 | char curinclpath[PATH_MAX]; | | 64 | char curinclpath[PATH_MAX]; |
65 | uint64_t ifdefstate; | | 65 | uint64_t ifdefstate; |
66 | int ifdefshift = -1; | | 66 | int ifdefshift = -1; |
67 | | | 67 | |
68 | /* | | 68 | /* |
69 | * The state is represented by 3 bits. | | 69 | * The state is represented by 3 bits. |
70 | */ | | 70 | */ |
71 | #define IDS_MATCH 1ll | | 71 | #define IDS_MATCH 1ll |
72 | #define IDS_ELIF 2ll | | 72 | #define IDS_ELIF 2ll |
73 | #define IDS_ELSE 4ll | | 73 | #define IDS_ELSE 4ll |
74 | | | 74 | |
75 | #define IDS_BITS 7 | | 75 | #define IDS_BITS 7 |
76 | #define IDS_SHIFT 3 | | 76 | #define IDS_SHIFT 3 |
77 | | | 77 | |
78 | #define IDS_ISMATCH(st) (((st) & IDS_MATCH) != 0) | | 78 | #define IDS_ISMATCH(st) (((st) & IDS_MATCH) != 0) |
79 | #define IDS_PARENT_DISABLED \ | | 79 | #define IDS_PARENT_DISABLED \ |
80 | (ifdefshift > 0 && !IDS_ISMATCH(ifdefstate >> IDS_SHIFT)) | | 80 | (ifdefshift > 0 && !IDS_ISMATCH(ifdefstate >> IDS_SHIFT)) |
81 | #define IDS_MAX_DEPTH 21 /* 64 / 3 */ | | 81 | #define IDS_MAX_DEPTH 21 /* 64 / 3 */ |
82 | | | 82 | |
| | | 83 | #ifdef IDS_DEBUG |
| | | 84 | # define IDS_PRINT(s, st, x) \ |
| | | 85 | do { \ |
| | | 86 | for (int i = 0; i < ifdefshift + 1; i++) \ |
| | | 87 | fprintf(stderr, " "); \ |
| | | 88 | printf("%s%s [%d,%d,%d] %#" PRIx64 "\n", x, # s, \ |
| | | 89 | IDS_PARENT_DISABLED, IDS_ISMATCH(st), getcurifdef(), \ |
| | | 90 | ifdefstate); \ |
| | | 91 | } while (/*CONSTCOND*/0) |
| | | 92 | #else |
| | | 93 | # define IDS_PRINT(s, st, x) __nothing |
| | | 94 | #endif |
| | | 95 | |
| | | 96 | #define IDS_ENTER(s, st) \ |
| | | 97 | IDS_PRINT(s, st, ">") |
| | | 98 | #define IDS_EXIT(s, st) \ |
| | | 99 | IDS_PRINT(s, st, "<") |
| | | 100 | |
83 | /* | | 101 | /* |
84 | * Data for returning to previous files from include files. | | 102 | * Data for returning to previous files from include files. |
85 | */ | | 103 | */ |
86 | struct incl { | | 104 | struct incl { |
87 | struct incl *in_prev; /* previous includes in effect, if any */ | | 105 | struct incl *in_prev; /* previous includes in effect, if any */ |
88 | YY_BUFFER_STATE in_buf; /* previous lex state */ | | 106 | YY_BUFFER_STATE in_buf; /* previous lex state */ |
89 | struct where in_where; | | 107 | struct where in_where; |
90 | int in_ateof; /* token to insert at EOF */ | | 108 | int in_ateof; /* token to insert at EOF */ |
91 | int in_interesting; /* previous value for "interesting" */ | | 109 | int in_interesting; /* previous value for "interesting" */ |
92 | uint64_t in_ifdefstate; /* conditional level */ | | 110 | uint64_t in_ifdefstate; /* conditional level */ |
93 | int in_ifdefshift; /* conditional level */ | | 111 | int in_ifdefshift; /* conditional level */ |
94 | }; | | 112 | }; |
95 | static struct incl *incl; | | 113 | static struct incl *incl; |
96 | static int endinclude(void); | | 114 | static int endinclude(void); |
97 | static int getincludepath(void); | | 115 | static int getincludepath(void); |
98 | static int getcurifdef(void); | | 116 | static int getcurifdef(void); |
99 | | | 117 | |
100 | | | 118 | |
101 | %} | | 119 | %} |
102 | | | 120 | |
103 | %option noyywrap nounput noinput | | 121 | %option noyywrap nounput noinput |
104 | | | 122 | |
105 | PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]* | | 123 | PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]* |
106 | QCHARS \"(\\.|[^\\"])*\" | | 124 | QCHARS \"(\\.|[^\\"])*\" |
107 | WORD [A-Za-z_][-A-Za-z_0-9]* | | 125 | WORD [A-Za-z_][-A-Za-z_0-9]* |
108 | FILENAME ({PATH}|{QCHARS}) | | 126 | FILENAME ({PATH}|{QCHARS}) |
109 | RESTOFLINE [ \t]*(#[^\n]*)?\n | | 127 | RESTOFLINE [ \t]*(#[^\n]*)?\n |
110 | WS ^[ \t]* | | 128 | WS ^[ \t]* |
111 | | | 129 | |
112 | %x IGNORED | | 130 | %x IGNORED |
113 | | | 131 | |
114 | %% | | 132 | %% |
115 | /* Local variables for yylex() */ | | 133 | /* Local variables for yylex() */ |
116 | int tok; | | 134 | int tok; |
117 | | | 135 | |
118 | and return AND; | | 136 | and return AND; |
119 | at return AT; | | 137 | at return AT; |
120 | attach return ATTACH; | | 138 | attach return ATTACH; |
121 | block return BLOCK; | | 139 | block return BLOCK; |
122 | build return BUILD; | | 140 | build return BUILD; |
123 | char return CHAR; | | 141 | char return CHAR; |
124 | compile-with return COMPILE_WITH; | | 142 | compile-with return COMPILE_WITH; |
125 | config return CONFIG; | | 143 | config return CONFIG; |
126 | deffs return DEFFS; | | 144 | deffs return DEFFS; |
127 | define return DEFINE; | | 145 | define return DEFINE; |
128 | defflag return DEFFLAG; | | 146 | defflag return DEFFLAG; |
129 | defopt return DEFOPT; | | 147 | defopt return DEFOPT; |
130 | defparam return DEFPARAM; | | 148 | defparam return DEFPARAM; |
131 | defpseudo return DEFPSEUDO; | | 149 | defpseudo return DEFPSEUDO; |
132 | defpseudodev return DEFPSEUDODEV; | | 150 | defpseudodev return DEFPSEUDODEV; |
133 | devclass return DEVCLASS; | | 151 | devclass return DEVCLASS; |
134 | device return DEVICE; | | 152 | device return DEVICE; |
135 | device-major return DEVICE_MAJOR; | | 153 | device-major return DEVICE_MAJOR; |
136 | dumps return DUMPS; | | 154 | dumps return DUMPS; |
137 | file return XFILE; | | 155 | file return XFILE; |
138 | file-system return FILE_SYSTEM; | | 156 | file-system return FILE_SYSTEM; |
139 | flags return FLAGS; | | 157 | flags return FLAGS; |
140 | ident return IDENT; | | 158 | ident return IDENT; |
141 | ioconf return IOCONF; | | 159 | ioconf return IOCONF; |
142 | linkzero return LINKZERO; | | 160 | linkzero return LINKZERO; |
143 | machine return XMACHINE; | | 161 | machine return XMACHINE; |
144 | major return MAJOR; | | 162 | major return MAJOR; |
145 | makeoptions return MAKEOPTIONS; | | 163 | makeoptions return MAKEOPTIONS; |
146 | maxpartitions return MAXPARTITIONS; | | 164 | maxpartitions return MAXPARTITIONS; |
147 | maxusers return MAXUSERS; | | 165 | maxusers return MAXUSERS; |
148 | minor return MINOR; | | 166 | minor return MINOR; |
149 | needs-count return NEEDS_COUNT; | | 167 | needs-count return NEEDS_COUNT; |
150 | needs-flag return NEEDS_FLAG; | | 168 | needs-flag return NEEDS_FLAG; |
151 | no return NO; | | 169 | no return NO; |
152 | -no return CNO; | | 170 | -no return CNO; |
153 | object return XOBJECT; | | 171 | object return XOBJECT; |
154 | obsolete return OBSOLETE; | | 172 | obsolete return OBSOLETE; |
155 | on return ON; | | 173 | on return ON; |
156 | options return OPTIONS; | | 174 | options return OPTIONS; |
157 | prefix return PREFIX; | | 175 | prefix return PREFIX; |
158 | buildprefix return BUILDPREFIX; | | 176 | buildprefix return BUILDPREFIX; |
159 | pseudo-device return PSEUDO_DEVICE; | | 177 | pseudo-device return PSEUDO_DEVICE; |
160 | pseudo-root return PSEUDO_ROOT; | | 178 | pseudo-root return PSEUDO_ROOT; |
161 | root return ROOT; | | 179 | root return ROOT; |
162 | select return SELECT; | | 180 | select return SELECT; |
163 | single return SINGLE; | | 181 | single return SINGLE; |
164 | source return SOURCE; | | 182 | source return SOURCE; |
165 | type return TYPE; | | 183 | type return TYPE; |
166 | vector return VECTOR; | | 184 | vector return VECTOR; |
167 | version return VERSION; | | 185 | version return VERSION; |
168 | with return WITH; | | 186 | with return WITH; |
169 | | | 187 | |
170 | \+= return PLUSEQ; | | 188 | \+= return PLUSEQ; |
171 | := return COLONEQ; | | 189 | := return COLONEQ; |
172 | | | 190 | |
173 | <*>{WS}ifdef[ \t]+{WORD}{RESTOFLINE} { | | 191 | <*>{WS}ifdef[ \t]+{WORD}{RESTOFLINE} { |
174 | ifdefstate <<= IDS_SHIFT; | | 192 | ifdefstate <<= IDS_SHIFT; |
175 | if (++ifdefshift >= IDS_MAX_DEPTH) { | | 193 | if (++ifdefshift >= IDS_MAX_DEPTH) { |
176 | yyerror("too many levels of conditional"); | | 194 | yyerror("too many levels of conditional"); |
177 | } | | 195 | } |
| | | 196 | IDS_ENTER(ifdef, 0); |
178 | if (IDS_PARENT_DISABLED || !getcurifdef()) { | | 197 | if (IDS_PARENT_DISABLED || !getcurifdef()) { |
179 | BEGIN(IGNORED); | | 198 | BEGIN(IGNORED); |
180 | } else { | | 199 | } else { |
181 | ifdefstate |= IDS_MATCH; | | 200 | ifdefstate |= IDS_MATCH; |
182 | BEGIN(INITIAL); | | 201 | BEGIN(INITIAL); |
183 | } | | 202 | } |
| | | 203 | IDS_EXIT(ifdef, 0); |
184 | yyline++; | | 204 | yyline++; |
185 | } | | 205 | } |
186 | | | 206 | |
187 | <*>{WS}ifndef[ \t]+{WORD}{RESTOFLINE} { | | 207 | <*>{WS}ifndef[ \t]+{WORD}{RESTOFLINE} { |
188 | ifdefstate <<= IDS_SHIFT; | | 208 | ifdefstate <<= IDS_SHIFT; |
189 | if (++ifdefshift >= IDS_MAX_DEPTH) { | | 209 | if (++ifdefshift >= IDS_MAX_DEPTH) { |
190 | yyerror("too many levels of conditional"); | | 210 | yyerror("too many levels of conditional"); |
191 | } | | 211 | } |
| | | 212 | IDS_ENTER(ifndef, 0); |
192 | if (IDS_PARENT_DISABLED || getcurifdef()) { | | 213 | if (IDS_PARENT_DISABLED || getcurifdef()) { |
193 | BEGIN(IGNORED); | | 214 | BEGIN(IGNORED); |
194 | } else { | | 215 | } else { |
195 | ifdefstate |= IDS_MATCH; | | 216 | ifdefstate |= IDS_MATCH; |
196 | BEGIN(INITIAL); | | 217 | BEGIN(INITIAL); |
197 | } | | 218 | } |
| | | 219 | IDS_EXIT(ifndef, 0); |
198 | yyline++; | | 220 | yyline++; |
199 | } | | 221 | } |
200 | | | 222 | |
201 | | | 223 | |
202 | <*>{WS}elifdef[ \t]+{WORD}{RESTOFLINE} { | | 224 | <*>{WS}elifdef[ \t]+{WORD}{RESTOFLINE} { |
203 | int st = ifdefstate & IDS_BITS; | | 225 | int st = ifdefstate & IDS_BITS; |
| | | 226 | IDS_ENTER(elifdef, st); |
204 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { | | 227 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { |
205 | yyerror("mismatched elifdef"); | | 228 | yyerror("mismatched elifdef"); |
206 | } | | 229 | } |
207 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || !getcurifdef()) { | | 230 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || !getcurifdef()) { |
208 | BEGIN(IGNORED); | | 231 | BEGIN(IGNORED); |
209 | } else { | | 232 | } else { |
210 | ifdefstate |= IDS_MATCH; | | 233 | ifdefstate |= IDS_MATCH; |
211 | BEGIN(INITIAL); | | 234 | BEGIN(INITIAL); |
212 | } | | 235 | } |
213 | ifdefstate |= IDS_ELIF; | | 236 | ifdefstate |= IDS_ELIF; |
| | | 237 | IDS_EXIT(elifdef, st); |
214 | yyline++; | | 238 | yyline++; |
215 | } | | 239 | } |
216 | | | 240 | |
217 | <*>{WS}elifndef[ \t]+{WORD}{RESTOFLINE} { | | 241 | <*>{WS}elifndef[ \t]+{WORD}{RESTOFLINE} { |
218 | int st = ifdefstate & IDS_BITS; | | 242 | int st = ifdefstate & IDS_BITS; |
| | | 243 | IDS_ENTER(elifndef, st); |
219 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { | | 244 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { |
220 | yyerror("mismatched elifndef"); | | 245 | yyerror("mismatched elifndef"); |
221 | } | | 246 | } |
222 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || getcurifdef()) { | | 247 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || getcurifdef()) { |
223 | BEGIN(IGNORED); | | 248 | BEGIN(IGNORED); |
224 | } else { | | 249 | } else { |
225 | ifdefstate |= IDS_MATCH; | | 250 | ifdefstate |= IDS_MATCH; |
226 | BEGIN(INITIAL); | | 251 | BEGIN(INITIAL); |
227 | } | | 252 | } |
228 | ifdefstate |= IDS_ELIF; | | 253 | ifdefstate |= IDS_ELIF; |
| | | 254 | IDS_EXIT(elifndef, st); |
229 | yyline++; | | 255 | yyline++; |
230 | } | | 256 | } |
231 | | | 257 | |
232 | <*>{WS}else{RESTOFLINE} { | | 258 | <*>{WS}else{RESTOFLINE} { |
233 | int st = ifdefstate & IDS_BITS; | | 259 | int st = ifdefstate & IDS_BITS; |
| | | 260 | IDS_ENTER(else, st); |
234 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { | | 261 | if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { |
235 | yyerror("mismatched else"); | | 262 | yyerror("mismatched else"); |
236 | } | | 263 | } |
237 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st)) { | | 264 | if (IDS_PARENT_DISABLED || IDS_ISMATCH(st)) { |
238 | BEGIN(IGNORED); | | 265 | BEGIN(IGNORED); |
239 | } else { | | 266 | } else { |
240 | ifdefstate |= IDS_MATCH; | | 267 | ifdefstate |= IDS_MATCH; |
241 | BEGIN(INITIAL); | | 268 | BEGIN(INITIAL); |
242 | } | | 269 | } |
243 | ifdefstate |= IDS_ELSE; | | 270 | ifdefstate |= IDS_ELSE; |
| | | 271 | IDS_ENTER(else, st); |
244 | yyline++; | | 272 | yyline++; |
245 | } | | 273 | } |
246 | | | 274 | |
247 | <*>{WS}endif{RESTOFLINE} { | | 275 | <*>{WS}endif{RESTOFLINE} { |
| | | 276 | IDS_ENTER(endif, 0); |
248 | if (ifdefshift == -1) { | | 277 | if (ifdefshift == -1) { |
249 | yyerror("mismatched endif"); | | 278 | yyerror("mismatched endif"); |
250 | } | | 279 | } |
251 | if (!IDS_PARENT_DISABLED) { | | 280 | if (!IDS_PARENT_DISABLED) { |
252 | BEGIN(INITIAL); | | 281 | BEGIN(INITIAL); |
253 | } | | 282 | } |
| | | 283 | IDS_EXIT(endif, 0); |
254 | ifdefshift--; | | 284 | ifdefshift--; |
255 | ifdefstate >>= IDS_SHIFT; | | 285 | ifdefstate >>= IDS_SHIFT; |
256 | yyline++; | | 286 | yyline++; |
257 | } | | 287 | } |
258 | | | 288 | |
259 | <IGNORED>\n { | | 289 | <IGNORED>\n { |
260 | yyline++; | | 290 | yyline++; |
261 | } | | 291 | } |
262 | | | 292 | |
263 | <IGNORED>. /* ignore */ | | 293 | <IGNORED>. /* ignore */ |
264 | | | 294 | |
265 | include[ \t]+{FILENAME}{RESTOFLINE} { | | 295 | include[ \t]+{FILENAME}{RESTOFLINE} { |
266 | yyline++; | | 296 | yyline++; |
267 | if (getincludepath()) { | | 297 | if (getincludepath()) { |
268 | include(curinclpath, 0, 0, 1); | | 298 | include(curinclpath, 0, 0, 1); |
269 | } else { | | 299 | } else { |
270 | yyerror("bad include path-name"); | | 300 | yyerror("bad include path-name"); |
271 | } | | 301 | } |
272 | } | | 302 | } |
273 | | | 303 | |
274 | cinclude[ \t]+{FILENAME}{RESTOFLINE} { | | 304 | cinclude[ \t]+{FILENAME}{RESTOFLINE} { |
275 | yyline++; | | 305 | yyline++; |
276 | if (getincludepath()) { | | 306 | if (getincludepath()) { |
277 | include(curinclpath, 0, 1, 1); | | 307 | include(curinclpath, 0, 1, 1); |
278 | } else { | | 308 | } else { |
279 | yyerror("bad cinclude path-name"); | | 309 | yyerror("bad cinclude path-name"); |
280 | } | | 310 | } |
281 | } | | 311 | } |
282 | | | 312 | |
283 | package[ \t]+{FILENAME}{RESTOFLINE} { | | 313 | package[ \t]+{FILENAME}{RESTOFLINE} { |
284 | yyline++; | | 314 | yyline++; |
285 | if (!oktopackage) { | | 315 | if (!oktopackage) { |
286 | yyerror("package not allowed here"); | | 316 | yyerror("package not allowed here"); |
287 | } else if (getincludepath()) { | | 317 | } else if (getincludepath()) { |
288 | package(curinclpath); | | 318 | package(curinclpath); |
289 | } else { | | 319 | } else { |
290 | yyerror("bad package path-name"); | | 320 | yyerror("bad package path-name"); |
291 | } | | 321 | } |
292 | } | | 322 | } |
293 | | | 323 | |
294 | {PATH} { | | 324 | {PATH} { |
295 | yylval.str = intern(yytext); | | 325 | yylval.str = intern(yytext); |
296 | return PATHNAME; | | 326 | return PATHNAME; |
297 | } | | 327 | } |
298 | | | 328 | |
299 | {WORD} { | | 329 | {WORD} { |
300 | yylval.str = intern(yytext); | | 330 | yylval.str = intern(yytext); |
301 | return WORD; | | 331 | return WORD; |
302 | } | | 332 | } |
303 | | | 333 | |
304 | \"\" { | | 334 | \"\" { |
305 | yylval.str = intern(""); | | 335 | yylval.str = intern(""); |
306 | return EMPTYSTRING; | | 336 | return EMPTYSTRING; |
307 | } | | 337 | } |
308 | | | 338 | |
309 | {QCHARS} { | | 339 | {QCHARS} { |
310 | size_t l = strlen(yytext); | | 340 | size_t l = strlen(yytext); |
311 | if (l > 1 && yytext[l - 1] == '"') | | 341 | if (l > 1 && yytext[l - 1] == '"') |
312 | yytext[l - 1] = '\0'; | | 342 | yytext[l - 1] = '\0'; |
313 | | | 343 | |
314 | yylval.str = intern(yytext + 1); | | 344 | yylval.str = intern(yytext + 1); |
315 | return QSTRING; | | 345 | return QSTRING; |
316 | } | | 346 | } |
317 | 0[0-7]* { | | 347 | 0[0-7]* { |
318 | yylval.num.fmt = 8; | | 348 | yylval.num.fmt = 8; |
319 | yylval.num.val = strtoll(yytext, NULL, 8); | | 349 | yylval.num.val = strtoll(yytext, NULL, 8); |
320 | return NUMBER; | | 350 | return NUMBER; |
321 | } | | 351 | } |
322 | 0[xX][0-9a-fA-F]+ { | | 352 | 0[xX][0-9a-fA-F]+ { |
323 | yylval.num.fmt = 16; | | 353 | yylval.num.fmt = 16; |
324 | yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); | | 354 | yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); |
325 | return NUMBER; | | 355 | return NUMBER; |
326 | } | | 356 | } |
327 | [1-9][0-9]* { | | 357 | [1-9][0-9]* { |
328 | yylval.num.fmt = 10; | | 358 | yylval.num.fmt = 10; |
329 | yylval.num.val = strtoll(yytext, NULL, 10); | | 359 | yylval.num.val = strtoll(yytext, NULL, 10); |
330 | return NUMBER; | | 360 | return NUMBER; |
331 | } | | 361 | } |
332 | \n[ \t] { | | 362 | \n[ \t] { |
333 | /* | | 363 | /* |
334 | * Note: newline followed by whitespace is always a | | 364 | * Note: newline followed by whitespace is always a |
335 | * continuation of the previous line, so do NOT | | 365 | * continuation of the previous line, so do NOT |
336 | * return a token in this case. | | 366 | * return a token in this case. |
337 | */ | | 367 | */ |
338 | yyline++; | | 368 | yyline++; |
339 | } | | 369 | } |
340 | \n { | | 370 | \n { |
341 | yyline++; | | 371 | yyline++; |
342 | return '\n'; | | 372 | return '\n'; |
343 | } | | 373 | } |
344 | \00 { | | 374 | \00 { |
345 | /* Detect NUL characters in the config file and | | 375 | /* Detect NUL characters in the config file and |
346 | * error out. | | 376 | * error out. |
347 | */ | | 377 | */ |
348 | cfgerror("NUL character detected at line %i", yyline); | | 378 | cfgerror("NUL character detected at line %i", yyline); |
349 | } | | 379 | } |
350 | #.* { /* ignored (comment) */; } | | 380 | #.* { /* ignored (comment) */; } |
351 | [ \t]+ { /* ignored (white space) */; } | | 381 | [ \t]+ { /* ignored (white space) */; } |
352 | . { return yytext[0]; } | | 382 | . { return yytext[0]; } |
353 | <*><<EOF>> { | | 383 | <*><<EOF>> { |
354 | if (ifdefshift > (incl == NULL ? -1 : incl->in_ifdefshift)) { | | 384 | if (ifdefshift > (incl == NULL ? -1 : incl->in_ifdefshift)) { |
355 | yyerror("reached EOF while looking for endif"); | | 385 | yyerror("reached EOF while looking for endif"); |
356 | } | | 386 | } |
357 | if (incl == NULL) | | 387 | if (incl == NULL) |
358 | return YY_NULL; | | 388 | return YY_NULL; |
359 | tok = endinclude(); | | 389 | tok = endinclude(); |
360 | if (tok) | | 390 | if (tok) |
361 | return tok; | | 391 | return tok; |
362 | /* otherwise continue scanning */ | | 392 | /* otherwise continue scanning */ |
363 | } | | 393 | } |
364 | | | 394 | |
365 | %% | | 395 | %% |
366 | | | 396 | |
367 | int interesting = 1; | | 397 | int interesting = 1; |
368 | | | 398 | |
369 | static int | | 399 | static int |
370 | curdir_push(const char *fname) | | 400 | curdir_push(const char *fname) |
371 | { | | 401 | { |
372 | struct prefix *pf; | | 402 | struct prefix *pf; |
373 | char *p, *d, *f; | | 403 | char *p, *d, *f; |
374 | | | 404 | |
375 | /* Set up the initial "current directory" for include directives. */ | | 405 | /* Set up the initial "current directory" for include directives. */ |
376 | d = dirname(f = estrdup(fname)); | | 406 | d = dirname(f = estrdup(fname)); |
377 | if (*d == '/') | | 407 | if (*d == '/') |
378 | p = estrdup(d); | | 408 | p = estrdup(d); |
379 | else { | | 409 | else { |
380 | char *cwd, buf[PATH_MAX]; | | 410 | char *cwd, buf[PATH_MAX]; |
381 | | | 411 | |
382 | if ((cwd = getcwd(buf, sizeof(buf))) == NULL) { | | 412 | if ((cwd = getcwd(buf, sizeof(buf))) == NULL) { |
383 | free(f); | | 413 | free(f); |
384 | return (-1); | | 414 | return (-1); |
385 | } | | 415 | } |
386 | easprintf(&p, "%s/%s", cwd, d); | | 416 | easprintf(&p, "%s/%s", cwd, d); |
387 | } | | 417 | } |
388 | free(f); | | 418 | free(f); |
389 | pf = ecalloc(1, sizeof(*pf)); | | 419 | pf = ecalloc(1, sizeof(*pf)); |
390 | pf->pf_prefix = p; | | 420 | pf->pf_prefix = p; |
391 | SLIST_INSERT_HEAD(&curdirs, pf, pf_next); | | 421 | SLIST_INSERT_HEAD(&curdirs, pf, pf_next); |
392 | | | 422 | |
393 | return (0); | | 423 | return (0); |
394 | } | | 424 | } |
395 | | | 425 | |
396 | static void | | 426 | static void |
397 | curdir_pop(void) | | 427 | curdir_pop(void) |
398 | { | | 428 | { |
399 | struct prefix *pf; | | 429 | struct prefix *pf; |
400 | | | 430 | |
401 | pf = SLIST_FIRST(&curdirs); | | 431 | pf = SLIST_FIRST(&curdirs); |
402 | SLIST_REMOVE_HEAD(&curdirs, pf_next); | | 432 | SLIST_REMOVE_HEAD(&curdirs, pf_next); |
403 | if (SLIST_EMPTY(&curdirs)) | | 433 | if (SLIST_EMPTY(&curdirs)) |
404 | panic("curdirs is empty"); | | 434 | panic("curdirs is empty"); |
405 | /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */ | | 435 | /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */ |
406 | free((void *)__UNCONST(pf->pf_prefix)); | | 436 | free((void *)__UNCONST(pf->pf_prefix)); |
407 | free(pf); | | 437 | free(pf); |
408 | } | | 438 | } |
409 | | | 439 | |
410 | /* | | 440 | /* |
411 | * Open the "main" file (conffile). | | 441 | * Open the "main" file (conffile). |
412 | */ | | 442 | */ |
413 | int | | 443 | int |
414 | firstfile(const char *fname) | | 444 | firstfile(const char *fname) |
415 | { | | 445 | { |
416 | | | 446 | |
417 | #if defined(__NetBSD__) | | 447 | #if defined(__NetBSD__) |
418 | if ((yyin = fopen(fname, "rf")) == NULL) | | 448 | if ((yyin = fopen(fname, "rf")) == NULL) |
419 | #else | | 449 | #else |
420 | if ((yyin = fopen(fname, "r")) == NULL) | | 450 | if ((yyin = fopen(fname, "r")) == NULL) |
421 | #endif | | 451 | #endif |
422 | return (-1); | | 452 | return (-1); |
423 | | | 453 | |
424 | if (curdir_push(fname) == -1) | | 454 | if (curdir_push(fname) == -1) |
425 | return (-1); | | 455 | return (-1); |
426 | | | 456 | |
427 | yyfile = conffile = fname; | | 457 | yyfile = conffile = fname; |
428 | yyline = 1; | | 458 | yyline = 1; |
429 | return (0); | | 459 | return (0); |
430 | } | | 460 | } |
431 | | | 461 | |
432 | /* | | 462 | /* |
433 | * Add a "package" to the configuration. This is essentially | | 463 | * Add a "package" to the configuration. This is essentially |
434 | * syntactic sugar around the sequence: | | 464 | * syntactic sugar around the sequence: |
435 | * | | 465 | * |
436 | * prefix ../some/directory | | 466 | * prefix ../some/directory |
437 | * include "files.package" | | 467 | * include "files.package" |
438 | * prefix | | 468 | * prefix |
439 | */ | | 469 | */ |
440 | void | | 470 | void |
441 | package(const char *fname) | | 471 | package(const char *fname) |
442 | { | | 472 | { |
443 | char *fname1 = estrdup(fname); | | 473 | char *fname1 = estrdup(fname); |
444 | char *fname2 = estrdup(fname); | | 474 | char *fname2 = estrdup(fname); |
445 | char *dir = dirname(fname1); | | 475 | char *dir = dirname(fname1); |
446 | char *file = basename(fname2); | | 476 | char *file = basename(fname2); |
447 | | | 477 | |
448 | /* | | 478 | /* |
449 | * Push the prefix on to the prefix stack and process the include | | 479 | * Push the prefix on to the prefix stack and process the include |
450 | * file. When we reach the end of the include file, inserting | | 480 | * file. When we reach the end of the include file, inserting |
451 | * the PREFIX token into the input stream will pop the prefix off | | 481 | * the PREFIX token into the input stream will pop the prefix off |
452 | * of the prefix stack. | | 482 | * of the prefix stack. |
453 | */ | | 483 | */ |
454 | prefix_push(dir); | | 484 | prefix_push(dir); |
455 | (void) include(file, PREFIX, 0, 1); | | 485 | (void) include(file, PREFIX, 0, 1); |
456 | | | 486 | |
457 | free(fname1); | | 487 | free(fname1); |
458 | free(fname2); | | 488 | free(fname2); |
459 | } | | 489 | } |
460 | | | 490 | |
461 | int includedepth; | | 491 | int includedepth; |
462 | | | 492 | |
463 | /* | | 493 | /* |
464 | * Open the named file for inclusion at the current point. Returns 0 on | | 494 | * Open the named file for inclusion at the current point. Returns 0 on |
465 | * success (file opened and previous state pushed), nonzero on failure | | 495 | * success (file opened and previous state pushed), nonzero on failure |
466 | * (fopen failed, complaint made). The `ateof' parameter controls the | | 496 | * (fopen failed, complaint made). The `ateof' parameter controls the |
467 | * token to be inserted at the end of the include file (i.e. ENDFILE). | | 497 | * token to be inserted at the end of the include file (i.e. ENDFILE). |
468 | * If ateof == 0 then nothing is inserted. | | 498 | * If ateof == 0 then nothing is inserted. |
469 | */ | | 499 | */ |
470 | int | | 500 | int |
471 | include(const char *fname, int ateof, int conditional, int direct) | | 501 | include(const char *fname, int ateof, int conditional, int direct) |
472 | { | | 502 | { |
473 | FILE *fp; | | 503 | FILE *fp; |
474 | struct incl *in; | | 504 | struct incl *in; |
475 | char *s; | | 505 | char *s; |
476 | static int havedirs; | | 506 | static int havedirs; |
477 | extern int vflag; | | 507 | extern int vflag; |
478 | | | 508 | |
479 | if (havedirs == 0) { | | 509 | if (havedirs == 0) { |
480 | havedirs = 1; | | 510 | havedirs = 1; |
481 | setupdirs(); | | 511 | setupdirs(); |
482 | } | | 512 | } |
483 | | | 513 | |
484 | if (fname[0] == '/') | | 514 | if (fname[0] == '/') |
485 | s = estrdup(fname); | | 515 | s = estrdup(fname); |
486 | else if (fname[0] == '.' && fname[1] == '/') { | | 516 | else if (fname[0] == '.' && fname[1] == '/') { |
487 | struct prefix *pf = SLIST_FIRST(&curdirs); | | 517 | struct prefix *pf = SLIST_FIRST(&curdirs); |
488 | easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); | | 518 | easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); |
489 | } else | | 519 | } else |
490 | s = sourcepath(fname); | | 520 | s = sourcepath(fname); |
491 | if ((fp = fopen(s, "r")) == NULL) { | | 521 | if ((fp = fopen(s, "r")) == NULL) { |
492 | if (conditional == 0) | | 522 | if (conditional == 0) |
493 | cfgerror("cannot open %s for reading: %s", s, | | 523 | cfgerror("cannot open %s for reading: %s", s, |
494 | strerror(errno)); | | 524 | strerror(errno)); |
495 | else if (vflag) | | 525 | else if (vflag) |
496 | cfgwarn("cannot open conditional include file %s: %s", | | 526 | cfgwarn("cannot open conditional include file %s: %s", |
497 | s, strerror(errno)); | | 527 | s, strerror(errno)); |
498 | free(s); | | 528 | free(s); |
499 | return (-1); | | 529 | return (-1); |
500 | } | | 530 | } |
501 | if (curdir_push(s) == -1) { | | 531 | if (curdir_push(s) == -1) { |
502 | cfgerror("cannot record current working directory for %s", s); | | 532 | cfgerror("cannot record current working directory for %s", s); |
503 | fclose(fp); | | 533 | fclose(fp); |
504 | free(s); | | 534 | free(s); |
505 | return (-1); | | 535 | return (-1); |
506 | } | | 536 | } |
507 | in = ecalloc(1, sizeof *in); | | 537 | in = ecalloc(1, sizeof *in); |
508 | in->in_prev = incl; | | 538 | in->in_prev = incl; |
509 | in->in_buf = YY_CURRENT_BUFFER; | | 539 | in->in_buf = YY_CURRENT_BUFFER; |
510 | in->in_where.w_srcfile = yyfile; | | 540 | in->in_where.w_srcfile = yyfile; |
511 | in->in_where.w_srcline = (u_short)yyline; | | 541 | in->in_where.w_srcline = (u_short)yyline; |
512 | in->in_ateof = ateof; | | 542 | in->in_ateof = ateof; |
513 | in->in_interesting = interesting; | | 543 | in->in_interesting = interesting; |
514 | in->in_ifdefstate = ifdefstate; | | 544 | in->in_ifdefstate = ifdefstate; |
515 | in->in_ifdefshift = ifdefshift; | | 545 | in->in_ifdefshift = ifdefshift; |
516 | interesting = direct & interesting; | | 546 | interesting = direct & interesting; |
517 | if (interesting) | | 547 | if (interesting) |
518 | logconfig_include(fp, fname); | | 548 | logconfig_include(fp, fname); |
519 | incl = in; | | 549 | incl = in; |
520 | CFGDBG(1, "include `%s' from `%s' line %d", fname, yyfile, yyline); | | 550 | CFGDBG(1, "include `%s' from `%s' line %d", fname, yyfile, yyline); |
521 | yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); | | 551 | yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); |
522 | yyfile = intern(s); | | 552 | yyfile = intern(s); |
523 | yyline = 1; | | 553 | yyline = 1; |
524 | free(s); | | 554 | free(s); |
525 | includedepth++; | | 555 | includedepth++; |
526 | return (0); | | 556 | return (0); |
527 | } | | 557 | } |
528 | | | 558 | |
529 | /* | | 559 | /* |
530 | * Extract the pathname from a include/cinclude/package into curinclpath | | 560 | * Extract the pathname from a include/cinclude/package into curinclpath |
531 | */ | | 561 | */ |
532 | static int | | 562 | static int |
533 | getincludepath(void) | | 563 | getincludepath(void) |
534 | { | | 564 | { |
535 | const char *p = yytext; | | 565 | const char *p = yytext; |
536 | ptrdiff_t len; | | 566 | ptrdiff_t len; |
537 | const char *e; | | 567 | const char *e; |
538 | | | 568 | |
539 | while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) | | 569 | while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) |
540 | p++; | | 570 | p++; |
541 | while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) | | 571 | while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) |
542 | p++; | | 572 | p++; |
543 | if (!*p) | | 573 | if (!*p) |
544 | return 0; | | 574 | return 0; |
545 | if (*p == '"') { | | 575 | if (*p == '"') { |
546 | p++; | | 576 | p++; |
547 | e = strchr(p, '"'); | | 577 | e = strchr(p, '"'); |
548 | if (!e) return 0; | | 578 | if (!e) return 0; |
549 | } else { | | 579 | } else { |
550 | e = p; | | 580 | e = p; |
551 | while (*e && isascii((unsigned int)*e) | | 581 | while (*e && isascii((unsigned int)*e) |
552 | && !isspace((unsigned int)*e)) | | 582 | && !isspace((unsigned int)*e)) |
553 | e++; | | 583 | e++; |
554 | } | | 584 | } |
555 | | | 585 | |
556 | len = e-p; | | 586 | len = e-p; |
557 | if (len > (ptrdiff_t)sizeof(curinclpath)-1) | | 587 | if (len > (ptrdiff_t)sizeof(curinclpath)-1) |
558 | len = sizeof(curinclpath)-1; | | 588 | len = sizeof(curinclpath)-1; |
559 | strncpy(curinclpath, p, sizeof(curinclpath)); | | 589 | strncpy(curinclpath, p, sizeof(curinclpath)); |
560 | curinclpath[len] = '\0'; | | 590 | curinclpath[len] = '\0'; |
561 | | | 591 | |
562 | return 1; | | 592 | return 1; |
563 | } | | 593 | } |
564 | | | 594 | |
565 | /* | | 595 | /* |
566 | * Terminate the most recent inclusion. | | 596 | * Terminate the most recent inclusion. |
567 | */ | | 597 | */ |
568 | static int | | 598 | static int |
569 | endinclude(void) | | 599 | endinclude(void) |
570 | { | | 600 | { |
571 | struct incl *in; | | 601 | struct incl *in; |
572 | int ateof; | | 602 | int ateof; |
573 | | | 603 | |
574 | curdir_pop(); | | 604 | curdir_pop(); |
575 | if ((in = incl) == NULL) | | 605 | if ((in = incl) == NULL) |
576 | panic("endinclude"); | | 606 | panic("endinclude"); |
577 | incl = in->in_prev; | | 607 | incl = in->in_prev; |
578 | lastfile = yyfile; | | 608 | lastfile = yyfile; |
579 | yy_delete_buffer(YY_CURRENT_BUFFER); | | 609 | yy_delete_buffer(YY_CURRENT_BUFFER); |
580 | (void)fclose(yyin); | | 610 | (void)fclose(yyin); |
581 | yy_switch_to_buffer(in->in_buf); | | 611 | yy_switch_to_buffer(in->in_buf); |
582 | yyfile = in->in_where.w_srcfile; | | 612 | yyfile = in->in_where.w_srcfile; |
583 | yyline = in->in_where.w_srcline; | | 613 | yyline = in->in_where.w_srcline; |
584 | ateof = in->in_ateof; | | 614 | ateof = in->in_ateof; |
585 | interesting = in->in_interesting; | | 615 | interesting = in->in_interesting; |
586 | ifdefstate = in->in_ifdefstate; | | 616 | ifdefstate = in->in_ifdefstate; |
587 | ifdefshift = in->in_ifdefshift; | | 617 | ifdefshift = in->in_ifdefshift; |
588 | free(in); | | 618 | free(in); |
589 | | | 619 | |
590 | includedepth--; | | 620 | includedepth--; |
591 | | | 621 | |
592 | return (ateof); | | 622 | return (ateof); |
593 | } | | 623 | } |
594 | | | 624 | |
595 | /* | | 625 | /* |
596 | * Return the current line number. If yacc has looked ahead and caused | | 626 | * Return the current line number. If yacc has looked ahead and caused |
597 | * us to consume a newline, we have to subtract one. yychar is yacc's | | 627 | * us to consume a newline, we have to subtract one. yychar is yacc's |
598 | * token lookahead, so we can tell. | | 628 | * token lookahead, so we can tell. |
599 | */ | | 629 | */ |
600 | u_short | | 630 | u_short |
601 | currentline(void) | | 631 | currentline(void) |
602 | { | | 632 | { |
603 | extern int yychar; | | 633 | extern int yychar; |
604 | | | 634 | |
605 | return (u_short)(yyline - (yychar == '\n')); | | 635 | return (u_short)(yyline - (yychar == '\n')); |
606 | } | | 636 | } |
607 | | | 637 | |
608 | static int | | 638 | static int |
609 | getcurifdef(void) | | 639 | getcurifdef(void) |
610 | { | | 640 | { |
611 | char *p = yytext, *q; | | 641 | char *p = yytext, *q; |
612 | | | 642 | |
613 | while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) | | 643 | while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) |
614 | p++; | | 644 | p++; |
615 | while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) | | 645 | while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) |
616 | p++; | | 646 | p++; |
617 | q = p; | | 647 | q = p; |
618 | while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q)) | | 648 | while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q)) |
619 | q++; | | 649 | q++; |
620 | *q = '\0'; | | 650 | *q = '\0'; |
621 | | | 651 | |
622 | return ht_lookup(attrtab, intern(p)) != NULL; | | 652 | return ht_lookup(attrtab, intern(p)) != NULL; |
623 | } | | 653 | } |