Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /*! \file */ |
15 | | |
16 | | #include <ctype.h> |
17 | | #include <errno.h> |
18 | | #include <inttypes.h> |
19 | | #include <stdbool.h> |
20 | | #include <stdlib.h> |
21 | | |
22 | | #include <isc/buffer.h> |
23 | | #include <isc/file.h> |
24 | | #include <isc/lex.h> |
25 | | #include <isc/mem.h> |
26 | | #include <isc/parseint.h> |
27 | | #include <isc/print.h> |
28 | | #include <isc/stdio.h> |
29 | | #include <isc/string.h> |
30 | | #include <isc/util.h> |
31 | | |
32 | | #include "errno2result.h" |
33 | | |
34 | | typedef struct inputsource { |
35 | | isc_result_t result; |
36 | | bool is_file; |
37 | | bool need_close; |
38 | | bool at_eof; |
39 | | bool last_was_eol; |
40 | | isc_buffer_t *pushback; |
41 | | unsigned int ignored; |
42 | | void *input; |
43 | | char *name; |
44 | | unsigned long line; |
45 | | unsigned long saved_line; |
46 | | ISC_LINK(struct inputsource) link; |
47 | | } inputsource; |
48 | | |
49 | 24.9k | #define LEX_MAGIC ISC_MAGIC('L', 'e', 'x', '!') |
50 | | #define VALID_LEX(l) ISC_MAGIC_VALID(l, LEX_MAGIC) |
51 | | |
52 | | struct isc_lex { |
53 | | /* Unlocked. */ |
54 | | unsigned int magic; |
55 | | isc_mem_t *mctx; |
56 | | size_t max_token; |
57 | | char *data; |
58 | | unsigned int comments; |
59 | | bool comment_ok; |
60 | | bool last_was_eol; |
61 | | unsigned int brace_count; |
62 | | unsigned int paren_count; |
63 | | unsigned int saved_paren_count; |
64 | | isc_lexspecials_t specials; |
65 | | LIST(struct inputsource) sources; |
66 | | }; |
67 | | |
68 | | static inline isc_result_t |
69 | 6.74k | grow_data(isc_lex_t *lex, size_t *remainingp, char **currp, char **prevp) { |
70 | 6.74k | char *tmp; |
71 | | |
72 | 6.74k | tmp = isc_mem_get(lex->mctx, lex->max_token * 2 + 1); |
73 | 6.74k | memmove(tmp, lex->data, lex->max_token + 1); |
74 | 6.74k | *currp = tmp + (*currp - lex->data); |
75 | 6.74k | if (*prevp != NULL) { |
76 | 404 | *prevp = tmp + (*prevp - lex->data); |
77 | 404 | } |
78 | 6.74k | isc_mem_put(lex->mctx, lex->data, lex->max_token + 1); |
79 | 6.74k | lex->data = tmp; |
80 | 6.74k | *remainingp += lex->max_token; |
81 | 6.74k | lex->max_token *= 2; |
82 | 6.74k | return (ISC_R_SUCCESS); |
83 | 6.74k | } |
84 | | |
85 | | isc_result_t |
86 | 24.9k | isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) { |
87 | 24.9k | isc_lex_t *lex; |
88 | | |
89 | | /* |
90 | | * Create a lexer. |
91 | | */ |
92 | 24.9k | REQUIRE(lexp != NULL && *lexp == NULL); |
93 | | |
94 | 24.9k | if (max_token == 0U) { |
95 | 0 | max_token = 1; |
96 | 0 | } |
97 | | |
98 | 24.9k | lex = isc_mem_get(mctx, sizeof(*lex)); |
99 | 24.9k | lex->data = isc_mem_get(mctx, max_token + 1); |
100 | 24.9k | lex->mctx = mctx; |
101 | 24.9k | lex->max_token = max_token; |
102 | 24.9k | lex->comments = 0; |
103 | 24.9k | lex->comment_ok = true; |
104 | 24.9k | lex->last_was_eol = true; |
105 | 24.9k | lex->brace_count = 0; |
106 | 24.9k | lex->paren_count = 0; |
107 | 24.9k | lex->saved_paren_count = 0; |
108 | 24.9k | memset(lex->specials, 0, 256); |
109 | 24.9k | INIT_LIST(lex->sources); |
110 | 24.9k | lex->magic = LEX_MAGIC; |
111 | | |
112 | 24.9k | *lexp = lex; |
113 | | |
114 | 24.9k | return (ISC_R_SUCCESS); |
115 | 24.9k | } |
116 | | |
117 | | void |
118 | 24.9k | isc_lex_destroy(isc_lex_t **lexp) { |
119 | 24.9k | isc_lex_t *lex; |
120 | | |
121 | | /* |
122 | | * Destroy the lexer. |
123 | | */ |
124 | | |
125 | 24.9k | REQUIRE(lexp != NULL); |
126 | 0 | lex = *lexp; |
127 | 24.9k | *lexp = NULL; |
128 | 24.9k | REQUIRE(VALID_LEX(lex)); |
129 | | |
130 | 34.5k | while (!EMPTY(lex->sources)) { |
131 | 9.67k | RUNTIME_CHECK(isc_lex_close(lex) == ISC_R_SUCCESS); |
132 | 9.67k | } |
133 | 24.9k | if (lex->data != NULL) { |
134 | 24.9k | isc_mem_put(lex->mctx, lex->data, lex->max_token + 1); |
135 | 24.9k | } |
136 | 24.9k | lex->magic = 0; |
137 | 24.9k | isc_mem_put(lex->mctx, lex, sizeof(*lex)); |
138 | 24.9k | } |
139 | | |
140 | | unsigned int |
141 | 0 | isc_lex_getcomments(isc_lex_t *lex) { |
142 | | /* |
143 | | * Return the current lexer commenting styles. |
144 | | */ |
145 | |
|
146 | 0 | REQUIRE(VALID_LEX(lex)); |
147 | | |
148 | 0 | return (lex->comments); |
149 | 0 | } |
150 | | |
151 | | void |
152 | 24.9k | isc_lex_setcomments(isc_lex_t *lex, unsigned int comments) { |
153 | | /* |
154 | | * Set allowed lexer commenting styles. |
155 | | */ |
156 | | |
157 | 24.9k | REQUIRE(VALID_LEX(lex)); |
158 | | |
159 | 0 | lex->comments = comments; |
160 | 24.9k | } |
161 | | |
162 | | void |
163 | 0 | isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials) { |
164 | | /* |
165 | | * Put the current list of specials into 'specials'. |
166 | | */ |
167 | |
|
168 | 0 | REQUIRE(VALID_LEX(lex)); |
169 | | |
170 | 0 | memmove(specials, lex->specials, 256); |
171 | 0 | } |
172 | | |
173 | | void |
174 | 24.9k | isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials) { |
175 | | /* |
176 | | * The characters in 'specials' are returned as tokens. Along with |
177 | | * whitespace, they delimit strings and numbers. |
178 | | */ |
179 | | |
180 | 24.9k | REQUIRE(VALID_LEX(lex)); |
181 | | |
182 | 0 | memmove(lex->specials, specials, 256); |
183 | 24.9k | } |
184 | | |
185 | | static inline isc_result_t |
186 | | new_source(isc_lex_t *lex, bool is_file, bool need_close, void *input, |
187 | 2.70M | const char *name) { |
188 | 2.70M | inputsource *source; |
189 | | |
190 | 2.70M | source = isc_mem_get(lex->mctx, sizeof(*source)); |
191 | 2.70M | source->result = ISC_R_SUCCESS; |
192 | 2.70M | source->is_file = is_file; |
193 | 2.70M | source->need_close = need_close; |
194 | 2.70M | source->at_eof = false; |
195 | 2.70M | source->last_was_eol = lex->last_was_eol; |
196 | 2.70M | source->input = input; |
197 | 2.70M | source->name = isc_mem_strdup(lex->mctx, name); |
198 | 2.70M | source->pushback = NULL; |
199 | 2.70M | isc_buffer_allocate(lex->mctx, &source->pushback, |
200 | 2.70M | (unsigned int)lex->max_token); |
201 | 2.70M | source->ignored = 0; |
202 | 2.70M | source->line = 1; |
203 | 2.70M | ISC_LIST_INITANDPREPEND(lex->sources, source, link); |
204 | | |
205 | 2.70M | return (ISC_R_SUCCESS); |
206 | 2.70M | } |
207 | | |
208 | | isc_result_t |
209 | 11 | isc_lex_openfile(isc_lex_t *lex, const char *filename) { |
210 | 11 | isc_result_t result; |
211 | 11 | FILE *stream = NULL; |
212 | | |
213 | | /* |
214 | | * Open 'filename' and make it the current input source for 'lex'. |
215 | | */ |
216 | | |
217 | 11 | REQUIRE(VALID_LEX(lex)); |
218 | | |
219 | 0 | result = isc_stdio_open(filename, "r", &stream); |
220 | 11 | if (result != ISC_R_SUCCESS) { |
221 | 10 | return (result); |
222 | 10 | } |
223 | | |
224 | 1 | result = new_source(lex, true, true, stream, filename); |
225 | 1 | if (result != ISC_R_SUCCESS) { |
226 | 0 | (void)fclose(stream); |
227 | 0 | } |
228 | 1 | return (result); |
229 | 11 | } |
230 | | |
231 | | isc_result_t |
232 | 0 | isc_lex_openstream(isc_lex_t *lex, FILE *stream) { |
233 | 0 | char name[128]; |
234 | | |
235 | | /* |
236 | | * Make 'stream' the current input source for 'lex'. |
237 | | */ |
238 | |
|
239 | 0 | REQUIRE(VALID_LEX(lex)); |
240 | | |
241 | 0 | snprintf(name, sizeof(name), "stream-%p", stream); |
242 | |
|
243 | 0 | return (new_source(lex, true, false, stream, name)); |
244 | 0 | } |
245 | | |
246 | | isc_result_t |
247 | 2.70M | isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer) { |
248 | 2.70M | char name[128]; |
249 | | |
250 | | /* |
251 | | * Make 'buffer' the current input source for 'lex'. |
252 | | */ |
253 | | |
254 | 2.70M | REQUIRE(VALID_LEX(lex)); |
255 | | |
256 | 0 | snprintf(name, sizeof(name), "buffer-%p", buffer); |
257 | | |
258 | 2.70M | return (new_source(lex, false, false, buffer, name)); |
259 | 2.70M | } |
260 | | |
261 | | isc_result_t |
262 | 2.69M | isc_lex_close(isc_lex_t *lex) { |
263 | 2.69M | inputsource *source; |
264 | | |
265 | | /* |
266 | | * Close the most recently opened object (i.e. file or buffer). |
267 | | */ |
268 | | |
269 | 2.69M | REQUIRE(VALID_LEX(lex)); |
270 | | |
271 | 2.69M | source = HEAD(lex->sources); |
272 | 2.69M | if (source == NULL) { |
273 | 0 | return (ISC_R_NOMORE); |
274 | 0 | } |
275 | | |
276 | 2.69M | ISC_LIST_UNLINK(lex->sources, source, link); |
277 | 0 | lex->last_was_eol = source->last_was_eol; |
278 | 2.69M | if (source->is_file) { |
279 | 1 | if (source->need_close) { |
280 | 1 | (void)fclose((FILE *)(source->input)); |
281 | 1 | } |
282 | 1 | } |
283 | 2.69M | isc_mem_free(lex->mctx, source->name); |
284 | 2.69M | isc_buffer_free(&source->pushback); |
285 | 2.69M | isc_mem_put(lex->mctx, source, sizeof(*source)); |
286 | | |
287 | 2.69M | return (ISC_R_SUCCESS); |
288 | 2.69M | } |
289 | | |
290 | | typedef enum { |
291 | | lexstate_start, |
292 | | lexstate_crlf, |
293 | | lexstate_string, |
294 | | lexstate_number, |
295 | | lexstate_maybecomment, |
296 | | lexstate_ccomment, |
297 | | lexstate_ccommentend, |
298 | | lexstate_eatline, |
299 | | lexstate_qstring, |
300 | | lexstate_btext, |
301 | | lexstate_vpair, |
302 | | lexstate_vpairstart, |
303 | | lexstate_qvpair, |
304 | | } lexstate; |
305 | | |
306 | 1.87M | #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL) |
307 | | |
308 | | static void |
309 | 8.99M | pushback(inputsource *source, int c) { |
310 | 8.99M | REQUIRE(source->pushback->current > 0); |
311 | 8.99M | if (c == EOF) { |
312 | 5.31M | source->at_eof = false; |
313 | 5.31M | return; |
314 | 5.31M | } |
315 | 3.67M | source->pushback->current--; |
316 | 3.67M | if (c == '\n') { |
317 | 597k | source->line--; |
318 | 597k | } |
319 | 3.67M | } |
320 | | |
321 | | static isc_result_t |
322 | 189M | pushandgrow(isc_lex_t *lex, inputsource *source, int c) { |
323 | 189M | if (isc_buffer_availablelength(source->pushback) == 0) { |
324 | 6.88k | isc_buffer_t *tbuf = NULL; |
325 | 6.88k | unsigned int oldlen; |
326 | 6.88k | isc_region_t used; |
327 | 6.88k | isc_result_t result; |
328 | | |
329 | 6.88k | oldlen = isc_buffer_length(source->pushback); |
330 | 6.88k | isc_buffer_allocate(lex->mctx, &tbuf, oldlen * 2); |
331 | 6.88k | isc_buffer_usedregion(source->pushback, &used); |
332 | 6.88k | result = isc_buffer_copyregion(tbuf, &used); |
333 | 6.88k | INSIST(result == ISC_R_SUCCESS); |
334 | 0 | tbuf->current = source->pushback->current; |
335 | 6.88k | isc_buffer_free(&source->pushback); |
336 | 6.88k | source->pushback = tbuf; |
337 | 6.88k | } |
338 | 189M | isc_buffer_putuint8(source->pushback, (uint8_t)c); |
339 | 0 | return (ISC_R_SUCCESS); |
340 | 189M | } |
341 | | |
342 | | isc_result_t |
343 | 13.6M | isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { |
344 | 13.6M | inputsource *source; |
345 | 13.6M | int c; |
346 | 13.6M | bool done = false; |
347 | 13.6M | bool no_comments = false; |
348 | 13.6M | bool escaped = false; |
349 | 13.6M | lexstate state = lexstate_start; |
350 | 13.6M | lexstate saved_state = lexstate_start; |
351 | 13.6M | isc_buffer_t *buffer; |
352 | 13.6M | FILE *stream; |
353 | 13.6M | char *curr, *prev; |
354 | 13.6M | size_t remaining; |
355 | 13.6M | uint32_t as_ulong; |
356 | 13.6M | unsigned int saved_options; |
357 | 13.6M | isc_result_t result; |
358 | | |
359 | | /* |
360 | | * Get the next token. |
361 | | */ |
362 | | |
363 | 13.6M | REQUIRE(VALID_LEX(lex)); |
364 | 13.6M | source = HEAD(lex->sources); |
365 | 13.6M | REQUIRE(tokenp != NULL); |
366 | | |
367 | 13.6M | if (source == NULL) { |
368 | 0 | if ((options & ISC_LEXOPT_NOMORE) != 0) { |
369 | 0 | tokenp->type = isc_tokentype_nomore; |
370 | 0 | return (ISC_R_SUCCESS); |
371 | 0 | } |
372 | 0 | return (ISC_R_NOMORE); |
373 | 0 | } |
374 | | |
375 | 13.6M | if (source->result != ISC_R_SUCCESS) { |
376 | 0 | return (source->result); |
377 | 0 | } |
378 | | |
379 | 13.6M | lex->saved_paren_count = lex->paren_count; |
380 | 13.6M | source->saved_line = source->line; |
381 | | |
382 | 13.6M | if (isc_buffer_remaininglength(source->pushback) == 0 && source->at_eof) |
383 | 2.11k | { |
384 | 2.11k | if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && |
385 | 2.11k | lex->paren_count != 0) { |
386 | 14 | lex->paren_count = 0; |
387 | 14 | return (ISC_R_UNBALANCED); |
388 | 14 | } |
389 | 2.10k | if ((options & ISC_LEXOPT_BTEXT) != 0 && lex->brace_count != 0) |
390 | 0 | { |
391 | 0 | lex->brace_count = 0; |
392 | 0 | return (ISC_R_UNBALANCED); |
393 | 0 | } |
394 | 2.10k | if ((options & ISC_LEXOPT_EOF) != 0) { |
395 | 2.10k | tokenp->type = isc_tokentype_eof; |
396 | 2.10k | return (ISC_R_SUCCESS); |
397 | 2.10k | } |
398 | 0 | return (ISC_R_EOF); |
399 | 2.10k | } |
400 | | |
401 | 13.6M | isc_buffer_compact(source->pushback); |
402 | | |
403 | 13.6M | saved_options = options; |
404 | 13.6M | if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && lex->paren_count > 0) { |
405 | 1.76M | options &= ~IWSEOL; |
406 | 1.76M | } |
407 | | |
408 | 13.6M | curr = lex->data; |
409 | 13.6M | *curr = '\0'; |
410 | | |
411 | 13.6M | prev = NULL; |
412 | 13.6M | remaining = lex->max_token; |
413 | | |
414 | 13.6M | #ifdef HAVE_FLOCKFILE |
415 | 13.6M | if (source->is_file) { |
416 | 1 | flockfile(source->input); |
417 | 1 | } |
418 | 13.6M | #endif /* ifdef HAVE_FLOCKFILE */ |
419 | | |
420 | 267M | do { |
421 | 267M | if (isc_buffer_remaininglength(source->pushback) == 0) { |
422 | 199M | if (source->is_file) { |
423 | 1 | stream = source->input; |
424 | | |
425 | 1 | #if defined(HAVE_FLOCKFILE) && defined(HAVE_GETC_UNLOCKED) |
426 | 1 | c = getc_unlocked(stream); |
427 | | #else /* if defined(HAVE_FLOCKFILE) && defined(HAVE_GETC_UNLOCKED) */ |
428 | | c = getc(stream); |
429 | | #endif /* if defined(HAVE_FLOCKFILE) && defined(HAVE_GETC_UNLOCKED) */ |
430 | 1 | if (c == EOF) { |
431 | 1 | if (ferror(stream)) { |
432 | 1 | source->result = |
433 | 1 | isc__errno2result( |
434 | 1 | errno); |
435 | 1 | result = source->result; |
436 | 1 | goto done; |
437 | 1 | } |
438 | 0 | source->at_eof = true; |
439 | 0 | } |
440 | 199M | } else { |
441 | 199M | buffer = source->input; |
442 | | |
443 | 199M | if (buffer->current == buffer->used) { |
444 | 9.20M | c = EOF; |
445 | 9.20M | source->at_eof = true; |
446 | 189M | } else { |
447 | 189M | c = *((unsigned char *)buffer->base + |
448 | 189M | buffer->current); |
449 | 189M | buffer->current++; |
450 | 189M | } |
451 | 199M | } |
452 | 199M | if (c != EOF) { |
453 | 189M | source->result = pushandgrow(lex, source, c); |
454 | 189M | if (source->result != ISC_R_SUCCESS) { |
455 | 0 | result = source->result; |
456 | 0 | goto done; |
457 | 0 | } |
458 | 189M | } |
459 | 199M | } |
460 | | |
461 | 267M | if (!source->at_eof) { |
462 | 258M | if (state == lexstate_start) { |
463 | | /* Token has not started yet. */ |
464 | 16.0M | source->ignored = isc_buffer_consumedlength( |
465 | 16.0M | source->pushback); |
466 | 16.0M | } |
467 | 258M | c = isc_buffer_getuint8(source->pushback); |
468 | 258M | } else { |
469 | 9.20M | c = EOF; |
470 | 9.20M | } |
471 | | |
472 | 267M | if (c == '\n') { |
473 | 1.43M | source->line++; |
474 | 1.43M | } |
475 | | |
476 | 267M | if (lex->comment_ok && !no_comments) { |
477 | 244M | if (!escaped && c == ';' && |
478 | 244M | ((lex->comments & ISC_LEXCOMMENT_DNSMASTERFILE) != |
479 | 286k | 0)) |
480 | 184k | { |
481 | 184k | saved_state = state; |
482 | 184k | state = lexstate_eatline; |
483 | 184k | no_comments = true; |
484 | 184k | continue; |
485 | 243M | } else if (c == '/' && |
486 | 243M | (lex->comments & |
487 | 161k | (ISC_LEXCOMMENT_C | |
488 | 161k | ISC_LEXCOMMENT_CPLUSPLUS)) != 0) |
489 | 0 | { |
490 | 0 | saved_state = state; |
491 | 0 | state = lexstate_maybecomment; |
492 | 0 | no_comments = true; |
493 | 0 | continue; |
494 | 243M | } else if (c == '#' && ((lex->comments & |
495 | 129k | ISC_LEXCOMMENT_SHELL) != 0)) { |
496 | 0 | saved_state = state; |
497 | 0 | state = lexstate_eatline; |
498 | 0 | no_comments = true; |
499 | 0 | continue; |
500 | 0 | } |
501 | 244M | } |
502 | | |
503 | 276M | no_read: |
504 | | /* INSIST(c == EOF || (c >= 0 && c <= 255)); */ |
505 | 276M | switch (state) { |
506 | 19.9M | case lexstate_start: |
507 | 19.9M | if (c == EOF) { |
508 | 3.89M | lex->last_was_eol = false; |
509 | 3.89M | if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && |
510 | 3.89M | lex->paren_count != 0) { |
511 | 5.26k | lex->paren_count = 0; |
512 | 5.26k | result = ISC_R_UNBALANCED; |
513 | 5.26k | goto done; |
514 | 5.26k | } |
515 | 3.88M | if ((options & ISC_LEXOPT_BTEXT) != 0 && |
516 | 3.88M | lex->brace_count != 0) { |
517 | 0 | lex->brace_count = 0; |
518 | 0 | result = ISC_R_UNBALANCED; |
519 | 0 | goto done; |
520 | 0 | } |
521 | 3.88M | if ((options & ISC_LEXOPT_EOF) == 0) { |
522 | 383 | result = ISC_R_EOF; |
523 | 383 | goto done; |
524 | 383 | } |
525 | 3.88M | tokenp->type = isc_tokentype_eof; |
526 | 3.88M | done = true; |
527 | 16.0M | } else if (c == ' ' || c == '\t') { |
528 | 3.26M | if (lex->last_was_eol && |
529 | 3.26M | (options & ISC_LEXOPT_INITIALWS) != 0) { |
530 | 130k | lex->last_was_eol = false; |
531 | 130k | tokenp->type = isc_tokentype_initialws; |
532 | 130k | tokenp->value.as_char = c; |
533 | 130k | done = true; |
534 | 130k | } |
535 | 12.8M | } else if (c == '\n') { |
536 | 838k | if ((options & ISC_LEXOPT_EOL) != 0) { |
537 | 484k | tokenp->type = isc_tokentype_eol; |
538 | 484k | done = true; |
539 | 484k | } |
540 | 838k | lex->last_was_eol = true; |
541 | 11.9M | } else if (c == '\r') { |
542 | 284k | if ((options & ISC_LEXOPT_EOL) != 0) { |
543 | 161k | state = lexstate_crlf; |
544 | 161k | } |
545 | 11.7M | } else if (c == '"' && |
546 | 11.7M | (options & ISC_LEXOPT_QSTRING) != 0) { |
547 | 64.5k | lex->last_was_eol = false; |
548 | 64.5k | no_comments = true; |
549 | 64.5k | state = lexstate_qstring; |
550 | 11.6M | } else if (lex->specials[c]) { |
551 | 2.80M | lex->last_was_eol = false; |
552 | 2.80M | if ((c == '(' || c == ')') && |
553 | 2.80M | (options & ISC_LEXOPT_DNSMULTILINE) != 0) { |
554 | 2.71M | if (c == '(') { |
555 | 2.54M | if (lex->paren_count == 0) { |
556 | 112k | options &= ~IWSEOL; |
557 | 112k | } |
558 | 2.54M | lex->paren_count++; |
559 | 2.54M | } else { |
560 | 167k | if (lex->paren_count == 0) { |
561 | 273 | result = |
562 | 273 | ISC_R_UNBALANCED; |
563 | 273 | goto done; |
564 | 273 | } |
565 | 167k | lex->paren_count--; |
566 | 167k | if (lex->paren_count == 0) { |
567 | 118k | options = saved_options; |
568 | 118k | } |
569 | 167k | } |
570 | 2.71M | continue; |
571 | 2.71M | } else if (c == '{' && |
572 | 92.7k | (options & ISC_LEXOPT_BTEXT) != 0) { |
573 | 0 | if (lex->brace_count != 0) { |
574 | 0 | result = ISC_R_UNBALANCED; |
575 | 0 | goto done; |
576 | 0 | } |
577 | 0 | lex->brace_count++; |
578 | 0 | options &= ~IWSEOL; |
579 | 0 | state = lexstate_btext; |
580 | 0 | no_comments = true; |
581 | 0 | continue; |
582 | 0 | } |
583 | 92.7k | tokenp->type = isc_tokentype_special; |
584 | 92.7k | tokenp->value.as_char = c; |
585 | 92.7k | done = true; |
586 | 8.83M | } else if (isdigit((unsigned char)c) && |
587 | 8.83M | (options & ISC_LEXOPT_NUMBER) != 0) { |
588 | 198k | lex->last_was_eol = false; |
589 | 198k | if ((options & ISC_LEXOPT_OCTAL) != 0 && |
590 | 198k | (c == '8' || c == '9')) { |
591 | 2 | state = lexstate_string; |
592 | 198k | } else { |
593 | 198k | state = lexstate_number; |
594 | 198k | } |
595 | 198k | goto no_read; |
596 | 8.63M | } else { |
597 | 8.63M | lex->last_was_eol = false; |
598 | 8.63M | state = lexstate_string; |
599 | 8.63M | goto no_read; |
600 | 8.63M | } |
601 | 8.42M | break; |
602 | 8.42M | case lexstate_crlf: |
603 | 161k | if (c != '\n') { |
604 | 158k | pushback(source, c); |
605 | 158k | } |
606 | 161k | tokenp->type = isc_tokentype_eol; |
607 | 161k | done = true; |
608 | 161k | lex->last_was_eol = true; |
609 | 161k | break; |
610 | 3.89M | case lexstate_number: |
611 | 3.89M | if (c == EOF || !isdigit((unsigned char)c)) { |
612 | 198k | if (c == ' ' || c == '\t' || c == '\r' || |
613 | 198k | c == '\n' || c == EOF || lex->specials[c]) |
614 | 197k | { |
615 | 197k | int base; |
616 | 197k | if ((options & ISC_LEXOPT_OCTAL) != 0) { |
617 | 110 | base = 8; |
618 | 197k | } else if ((options & |
619 | 197k | ISC_LEXOPT_CNUMBER) != 0) { |
620 | 0 | base = 0; |
621 | 197k | } else { |
622 | 197k | base = 10; |
623 | 197k | } |
624 | 197k | pushback(source, c); |
625 | | |
626 | 197k | result = isc_parse_uint32( |
627 | 197k | &as_ulong, lex->data, base); |
628 | 197k | if (result == ISC_R_SUCCESS) { |
629 | 196k | tokenp->type = |
630 | 196k | isc_tokentype_number; |
631 | 196k | tokenp->value.as_ulong = |
632 | 196k | as_ulong; |
633 | 196k | } else if (result == ISC_R_BADNUMBER) { |
634 | 0 | isc_tokenvalue_t *v; |
635 | |
|
636 | 0 | tokenp->type = |
637 | 0 | isc_tokentype_string; |
638 | 0 | v = &(tokenp->value); |
639 | 0 | v->as_textregion.base = |
640 | 0 | lex->data; |
641 | 0 | v->as_textregion.length = |
642 | 0 | (unsigned int)(lex->max_token - |
643 | 0 | remaining); |
644 | 1.08k | } else { |
645 | 1.08k | goto done; |
646 | 1.08k | } |
647 | 196k | done = true; |
648 | 196k | continue; |
649 | 197k | } else if ((options & ISC_LEXOPT_CNUMBER) == |
650 | 975 | 0 || |
651 | 975 | ((c != 'x' && c != 'X') || |
652 | 0 | (curr != &lex->data[1]) || |
653 | 0 | (lex->data[0] != '0'))) |
654 | 975 | { |
655 | | /* Above test supports hex numbers */ |
656 | 975 | state = lexstate_string; |
657 | 975 | } |
658 | 3.70M | } else if ((options & ISC_LEXOPT_OCTAL) != 0 && |
659 | 3.70M | (c == '8' || c == '9')) { |
660 | 2 | state = lexstate_string; |
661 | 2 | } |
662 | 3.70M | if (remaining == 0U) { |
663 | 88 | result = grow_data(lex, &remaining, &curr, |
664 | 88 | &prev); |
665 | 88 | if (result != ISC_R_SUCCESS) { |
666 | 0 | goto done; |
667 | 0 | } |
668 | 88 | } |
669 | 3.70M | INSIST(remaining > 0U); |
670 | 0 | *curr++ = c; |
671 | 3.70M | *curr = '\0'; |
672 | 3.70M | remaining--; |
673 | 3.70M | break; |
674 | 211M | case lexstate_string: |
675 | 211M | if (!escaped && c == '=' && |
676 | 211M | (options & ISC_LEXOPT_VPAIR) != 0) { |
677 | 15.6k | if (remaining == 0U) { |
678 | 5 | result = grow_data(lex, &remaining, |
679 | 5 | &curr, &prev); |
680 | 5 | if (result != ISC_R_SUCCESS) { |
681 | 0 | goto done; |
682 | 0 | } |
683 | 5 | } |
684 | 15.6k | INSIST(remaining > 0U); |
685 | 0 | *curr++ = c; |
686 | 15.6k | *curr = '\0'; |
687 | 15.6k | remaining--; |
688 | 15.6k | state = lexstate_vpairstart; |
689 | 15.6k | break; |
690 | 15.6k | } |
691 | | /* FALLTHROUGH */ |
692 | 211M | case lexstate_vpairstart: |
693 | 211M | if (state == lexstate_vpairstart) { |
694 | 15.6k | if (c == '"' && |
695 | 15.6k | (options & ISC_LEXOPT_QVPAIR) != 0) { |
696 | 1.05k | no_comments = true; |
697 | 1.05k | state = lexstate_qvpair; |
698 | 1.05k | break; |
699 | 1.05k | } |
700 | 14.5k | state = lexstate_vpair; |
701 | 14.5k | } |
702 | | /* FALLTHROUGH */ |
703 | 228M | case lexstate_vpair: |
704 | | /* |
705 | | * EOF needs to be checked before lex->specials[c] |
706 | | * as lex->specials[EOF] is not a good idea. |
707 | | */ |
708 | 228M | if (c == '\r' || c == '\n' || c == EOF || |
709 | 228M | (!escaped && |
710 | 222M | (c == ' ' || c == '\t' || lex->specials[c]))) |
711 | 8.63M | { |
712 | 8.63M | pushback(source, c); |
713 | 8.63M | if (source->result != ISC_R_SUCCESS) { |
714 | 0 | result = source->result; |
715 | 0 | goto done; |
716 | 0 | } |
717 | 8.63M | if (escaped && c == EOF) { |
718 | 62 | result = ISC_R_UNEXPECTEDEND; |
719 | 62 | goto done; |
720 | 62 | } |
721 | 8.63M | tokenp->type = (state == lexstate_string) |
722 | 8.63M | ? isc_tokentype_string |
723 | 8.63M | : isc_tokentype_vpair; |
724 | 8.63M | tokenp->value.as_textregion.base = lex->data; |
725 | 8.63M | tokenp->value.as_textregion.length = |
726 | 8.63M | (unsigned int)(lex->max_token - |
727 | 8.63M | remaining); |
728 | 8.63M | done = true; |
729 | 8.63M | continue; |
730 | 8.63M | } |
731 | 220M | if ((options & ISC_LEXOPT_ESCAPE) != 0) { |
732 | 156M | escaped = (!escaped && c == '\\') ? true |
733 | 156M | : false; |
734 | 156M | } |
735 | 220M | if (remaining == 0U) { |
736 | 6.25k | result = grow_data(lex, &remaining, &curr, |
737 | 6.25k | &prev); |
738 | 6.25k | if (result != ISC_R_SUCCESS) { |
739 | 0 | goto done; |
740 | 0 | } |
741 | 6.25k | } |
742 | 220M | INSIST(remaining > 0U); |
743 | 0 | *curr++ = c; |
744 | 220M | *curr = '\0'; |
745 | 220M | remaining--; |
746 | 220M | break; |
747 | 0 | case lexstate_maybecomment: |
748 | 0 | if (c == '*' && (lex->comments & ISC_LEXCOMMENT_C) != 0) |
749 | 0 | { |
750 | 0 | state = lexstate_ccomment; |
751 | 0 | continue; |
752 | 0 | } else if (c == '/' && (lex->comments & |
753 | 0 | ISC_LEXCOMMENT_CPLUSPLUS) != 0) |
754 | 0 | { |
755 | 0 | state = lexstate_eatline; |
756 | 0 | continue; |
757 | 0 | } |
758 | 0 | pushback(source, c); |
759 | 0 | c = '/'; |
760 | 0 | no_comments = false; |
761 | 0 | state = saved_state; |
762 | 0 | goto no_read; |
763 | 0 | case lexstate_ccomment: |
764 | 0 | if (c == EOF) { |
765 | 0 | result = ISC_R_UNEXPECTEDEND; |
766 | 0 | goto done; |
767 | 0 | } |
768 | 0 | if (c == '*') { |
769 | 0 | state = lexstate_ccommentend; |
770 | 0 | } |
771 | 0 | break; |
772 | 0 | case lexstate_ccommentend: |
773 | 0 | if (c == EOF) { |
774 | 0 | result = ISC_R_UNEXPECTEDEND; |
775 | 0 | goto done; |
776 | 0 | } |
777 | 0 | if (c == '/') { |
778 | | /* |
779 | | * C-style comments become a single space. |
780 | | * We do this to ensure that a comment will |
781 | | * act as a delimiter for strings and |
782 | | * numbers. |
783 | | */ |
784 | 0 | c = ' '; |
785 | 0 | no_comments = false; |
786 | 0 | state = saved_state; |
787 | 0 | goto no_read; |
788 | 0 | } else if (c != '*') { |
789 | 0 | state = lexstate_ccomment; |
790 | 0 | } |
791 | 0 | break; |
792 | 8.61M | case lexstate_eatline: |
793 | 8.61M | if ((c == '\n') || (c == EOF)) { |
794 | 184k | no_comments = false; |
795 | 184k | state = saved_state; |
796 | 184k | goto no_read; |
797 | 184k | } |
798 | 8.43M | break; |
799 | 8.43M | case lexstate_qstring: |
800 | 14.9M | case lexstate_qvpair: |
801 | 14.9M | if (c == EOF) { |
802 | 215 | result = ISC_R_UNEXPECTEDEND; |
803 | 215 | goto done; |
804 | 215 | } |
805 | 14.9M | if (c == '"') { |
806 | 75.2k | if (escaped) { |
807 | 9.91k | escaped = false; |
808 | | /* |
809 | | * Overwrite the preceding backslash. |
810 | | */ |
811 | 9.91k | INSIST(prev != NULL); |
812 | 0 | *prev = '"'; |
813 | 65.3k | } else { |
814 | 65.3k | tokenp->type = |
815 | 65.3k | (state == lexstate_qstring) |
816 | 65.3k | ? isc_tokentype_qstring |
817 | 65.3k | : isc_tokentype_qvpair; |
818 | 65.3k | tokenp->value.as_textregion.base = |
819 | 65.3k | lex->data; |
820 | 65.3k | tokenp->value.as_textregion.length = |
821 | 65.3k | (unsigned int)(lex->max_token - |
822 | 65.3k | remaining); |
823 | 65.3k | no_comments = false; |
824 | 65.3k | done = true; |
825 | 65.3k | } |
826 | 14.8M | } else { |
827 | 14.8M | if (c == '\n' && !escaped && |
828 | 14.8M | (options & ISC_LEXOPT_QSTRINGMULTILINE) == |
829 | 46 | 0) { |
830 | 46 | pushback(source, c); |
831 | 46 | result = ISC_R_UNBALANCEDQUOTES; |
832 | 46 | goto done; |
833 | 46 | } |
834 | 14.8M | if (c == '\\' && !escaped) { |
835 | 535k | escaped = true; |
836 | 14.3M | } else { |
837 | 14.3M | escaped = false; |
838 | 14.3M | } |
839 | 14.8M | if (remaining == 0U) { |
840 | 405 | result = grow_data(lex, &remaining, |
841 | 405 | &curr, &prev); |
842 | 405 | if (result != ISC_R_SUCCESS) { |
843 | 0 | goto done; |
844 | 0 | } |
845 | 405 | } |
846 | 14.8M | INSIST(remaining > 0U); |
847 | 0 | prev = curr; |
848 | 14.8M | *curr++ = c; |
849 | 14.8M | *curr = '\0'; |
850 | 14.8M | remaining--; |
851 | 14.8M | } |
852 | 14.9M | break; |
853 | 14.9M | case lexstate_btext: |
854 | 0 | if (c == EOF) { |
855 | 0 | result = ISC_R_UNEXPECTEDEND; |
856 | 0 | goto done; |
857 | 0 | } |
858 | 0 | if (c == '{') { |
859 | 0 | if (escaped) { |
860 | 0 | escaped = false; |
861 | 0 | } else { |
862 | 0 | lex->brace_count++; |
863 | 0 | } |
864 | 0 | } else if (c == '}') { |
865 | 0 | if (escaped) { |
866 | 0 | escaped = false; |
867 | 0 | } else { |
868 | 0 | INSIST(lex->brace_count > 0); |
869 | 0 | lex->brace_count--; |
870 | 0 | } |
871 | | |
872 | 0 | if (lex->brace_count == 0) { |
873 | 0 | tokenp->type = isc_tokentype_btext; |
874 | 0 | tokenp->value.as_textregion.base = |
875 | 0 | lex->data; |
876 | 0 | tokenp->value.as_textregion.length = |
877 | 0 | (unsigned int)(lex->max_token - |
878 | 0 | remaining); |
879 | 0 | no_comments = false; |
880 | 0 | done = true; |
881 | 0 | break; |
882 | 0 | } |
883 | 0 | } |
884 | | |
885 | 0 | if (c == '\\' && !escaped) { |
886 | 0 | escaped = true; |
887 | 0 | } else { |
888 | 0 | escaped = false; |
889 | 0 | } |
890 | |
|
891 | 0 | if (remaining == 0U) { |
892 | 0 | result = grow_data(lex, &remaining, &curr, |
893 | 0 | &prev); |
894 | 0 | if (result != ISC_R_SUCCESS) { |
895 | 0 | goto done; |
896 | 0 | } |
897 | 0 | } |
898 | 0 | INSIST(remaining > 0U); |
899 | 0 | prev = curr; |
900 | 0 | *curr++ = c; |
901 | 0 | *curr = '\0'; |
902 | 0 | remaining--; |
903 | 0 | break; |
904 | 0 | default: |
905 | 0 | FATAL_ERROR(__FILE__, __LINE__, "Unexpected state %d", |
906 | 0 | state); |
907 | 276M | } |
908 | 276M | } while (!done); |
909 | | |
910 | 13.6M | result = ISC_R_SUCCESS; |
911 | 13.6M | done: |
912 | 13.6M | #ifdef HAVE_FLOCKFILE |
913 | 13.6M | if (source->is_file) { |
914 | 1 | funlockfile(source->input); |
915 | 1 | } |
916 | 13.6M | #endif /* ifdef HAVE_FLOCKFILE */ |
917 | 13.6M | return (result); |
918 | 13.6M | } |
919 | | |
920 | | isc_result_t |
921 | | isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token, |
922 | 9.23M | isc_tokentype_t expect, bool eol) { |
923 | 9.23M | unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | |
924 | 9.23M | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; |
925 | 9.23M | isc_result_t result; |
926 | | |
927 | 9.23M | if (expect == isc_tokentype_vpair) { |
928 | 1.17k | options |= ISC_LEXOPT_VPAIR; |
929 | 9.23M | } else if (expect == isc_tokentype_qvpair) { |
930 | 28.4k | options |= ISC_LEXOPT_VPAIR; |
931 | 28.4k | options |= ISC_LEXOPT_QVPAIR; |
932 | 9.20M | } else if (expect == isc_tokentype_qstring) { |
933 | 4.09M | options |= ISC_LEXOPT_QSTRING; |
934 | 5.11M | } else if (expect == isc_tokentype_number) { |
935 | 180k | options |= ISC_LEXOPT_NUMBER; |
936 | 180k | } |
937 | 9.23M | result = isc_lex_gettoken(lex, options, token); |
938 | 9.23M | if (result == ISC_R_RANGE) { |
939 | 991 | isc_lex_ungettoken(lex, token); |
940 | 991 | } |
941 | 9.23M | if (result != ISC_R_SUCCESS) { |
942 | 2.93k | return (result); |
943 | 2.93k | } |
944 | | |
945 | 9.23M | if (eol && ((token->type == isc_tokentype_eol) || |
946 | 6.05M | (token->type == isc_tokentype_eof))) |
947 | 1.36M | { |
948 | 1.36M | return (ISC_R_SUCCESS); |
949 | 1.36M | } |
950 | 7.87M | if (token->type == isc_tokentype_string && |
951 | 7.87M | (expect == isc_tokentype_qstring || expect == isc_tokentype_qvpair)) |
952 | 3.75M | { |
953 | 3.75M | return (ISC_R_SUCCESS); |
954 | 3.75M | } |
955 | 4.11M | if (token->type == isc_tokentype_vpair && |
956 | 4.11M | expect == isc_tokentype_qvpair) { |
957 | 14.0k | return (ISC_R_SUCCESS); |
958 | 14.0k | } |
959 | 4.10M | if (token->type != expect) { |
960 | 8.89k | isc_lex_ungettoken(lex, token); |
961 | 8.89k | if (token->type == isc_tokentype_eol || |
962 | 8.89k | token->type == isc_tokentype_eof) { |
963 | 7.63k | return (ISC_R_UNEXPECTEDEND); |
964 | 7.63k | } |
965 | 1.26k | if (expect == isc_tokentype_number) { |
966 | 885 | return (ISC_R_BADNUMBER); |
967 | 885 | } |
968 | 376 | return (ISC_R_UNEXPECTEDTOKEN); |
969 | 1.26k | } |
970 | 4.09M | return (ISC_R_SUCCESS); |
971 | 4.10M | } |
972 | | |
973 | | isc_result_t |
974 | 126 | isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, bool eol) { |
975 | 126 | unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | |
976 | 126 | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE | |
977 | 126 | ISC_LEXOPT_NUMBER | ISC_LEXOPT_OCTAL; |
978 | 126 | isc_result_t result; |
979 | | |
980 | 126 | result = isc_lex_gettoken(lex, options, token); |
981 | 126 | if (result == ISC_R_RANGE) { |
982 | 6 | isc_lex_ungettoken(lex, token); |
983 | 6 | } |
984 | 126 | if (result != ISC_R_SUCCESS) { |
985 | 8 | return (result); |
986 | 8 | } |
987 | | |
988 | 118 | if (eol && ((token->type == isc_tokentype_eol) || |
989 | 0 | (token->type == isc_tokentype_eof))) |
990 | 0 | { |
991 | 0 | return (ISC_R_SUCCESS); |
992 | 0 | } |
993 | 118 | if (token->type != isc_tokentype_number) { |
994 | 14 | isc_lex_ungettoken(lex, token); |
995 | 14 | if (token->type == isc_tokentype_eol || |
996 | 14 | token->type == isc_tokentype_eof) { |
997 | 9 | return (ISC_R_UNEXPECTEDEND); |
998 | 9 | } |
999 | 5 | return (ISC_R_BADNUMBER); |
1000 | 14 | } |
1001 | 104 | return (ISC_R_SUCCESS); |
1002 | 118 | } |
1003 | | |
1004 | | void |
1005 | 4.32M | isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) { |
1006 | 4.32M | inputsource *source; |
1007 | | /* |
1008 | | * Unget the current token. |
1009 | | */ |
1010 | | |
1011 | 4.32M | REQUIRE(VALID_LEX(lex)); |
1012 | 4.32M | source = HEAD(lex->sources); |
1013 | 4.32M | REQUIRE(source != NULL); |
1014 | 4.32M | REQUIRE(tokenp != NULL); |
1015 | 4.32M | REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 || |
1016 | 0 | tokenp->type == isc_tokentype_eof); |
1017 | | |
1018 | 4.32M | UNUSED(tokenp); |
1019 | | |
1020 | 4.32M | isc_buffer_first(source->pushback); |
1021 | 4.32M | lex->paren_count = lex->saved_paren_count; |
1022 | 4.32M | source->line = source->saved_line; |
1023 | 4.32M | source->at_eof = false; |
1024 | 4.32M | } |
1025 | | |
1026 | | void |
1027 | 0 | isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r) { |
1028 | 0 | inputsource *source; |
1029 | |
|
1030 | 0 | REQUIRE(VALID_LEX(lex)); |
1031 | 0 | source = HEAD(lex->sources); |
1032 | 0 | REQUIRE(source != NULL); |
1033 | 0 | REQUIRE(tokenp != NULL); |
1034 | 0 | REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 || |
1035 | 0 | tokenp->type == isc_tokentype_eof); |
1036 | | |
1037 | 0 | UNUSED(tokenp); |
1038 | |
|
1039 | 0 | INSIST(source->ignored <= isc_buffer_consumedlength(source->pushback)); |
1040 | 0 | r->base = (unsigned char *)isc_buffer_base(source->pushback) + |
1041 | 0 | source->ignored; |
1042 | 0 | r->length = isc_buffer_consumedlength(source->pushback) - |
1043 | 0 | source->ignored; |
1044 | 0 | } |
1045 | | |
1046 | | char * |
1047 | 3.54M | isc_lex_getsourcename(isc_lex_t *lex) { |
1048 | 3.54M | inputsource *source; |
1049 | | |
1050 | 3.54M | REQUIRE(VALID_LEX(lex)); |
1051 | 3.54M | source = HEAD(lex->sources); |
1052 | | |
1053 | 3.54M | if (source == NULL) { |
1054 | 0 | return (NULL); |
1055 | 0 | } |
1056 | | |
1057 | 3.54M | return (source->name); |
1058 | 3.54M | } |
1059 | | |
1060 | | unsigned long |
1061 | 4.50M | isc_lex_getsourceline(isc_lex_t *lex) { |
1062 | 4.50M | inputsource *source; |
1063 | | |
1064 | 4.50M | REQUIRE(VALID_LEX(lex)); |
1065 | 4.50M | source = HEAD(lex->sources); |
1066 | | |
1067 | 4.50M | if (source == NULL) { |
1068 | 0 | return (0); |
1069 | 0 | } |
1070 | | |
1071 | 4.50M | return (source->line); |
1072 | 4.50M | } |
1073 | | |
1074 | | isc_result_t |
1075 | 0 | isc_lex_setsourcename(isc_lex_t *lex, const char *name) { |
1076 | 0 | inputsource *source; |
1077 | 0 | char *newname; |
1078 | |
|
1079 | 0 | REQUIRE(VALID_LEX(lex)); |
1080 | 0 | source = HEAD(lex->sources); |
1081 | |
|
1082 | 0 | if (source == NULL) { |
1083 | 0 | return (ISC_R_NOTFOUND); |
1084 | 0 | } |
1085 | 0 | newname = isc_mem_strdup(lex->mctx, name); |
1086 | 0 | isc_mem_free(lex->mctx, source->name); |
1087 | 0 | source->name = newname; |
1088 | 0 | return (ISC_R_SUCCESS); |
1089 | 0 | } |
1090 | | |
1091 | | isc_result_t |
1092 | 0 | isc_lex_setsourceline(isc_lex_t *lex, unsigned long line) { |
1093 | 0 | inputsource *source; |
1094 | |
|
1095 | 0 | REQUIRE(VALID_LEX(lex)); |
1096 | 0 | source = HEAD(lex->sources); |
1097 | |
|
1098 | 0 | if (source == NULL) { |
1099 | 0 | return (ISC_R_NOTFOUND); |
1100 | 0 | } |
1101 | | |
1102 | 0 | source->line = line; |
1103 | 0 | return (ISC_R_SUCCESS); |
1104 | 0 | } |
1105 | | |
1106 | | bool |
1107 | 2.67M | isc_lex_isfile(isc_lex_t *lex) { |
1108 | 2.67M | inputsource *source; |
1109 | | |
1110 | 2.67M | REQUIRE(VALID_LEX(lex)); |
1111 | | |
1112 | 2.67M | source = HEAD(lex->sources); |
1113 | | |
1114 | 2.67M | if (source == NULL) { |
1115 | 0 | return (false); |
1116 | 0 | } |
1117 | | |
1118 | 2.67M | return (source->is_file); |
1119 | 2.67M | } |