4 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: lex.c,v 1.86 2007/09/17 09:56:29 shane Exp */
30 #include <isc/buffer.h>
35 #include <isc/parseint.h>
36 #include <isc/print.h>
37 #include <isc/stdio.h>
38 #include <isc/string.h>
41 typedef struct inputsource
{
43 isc_boolean_t is_file
;
44 isc_boolean_t need_close
;
46 isc_buffer_t
* pushback
;
51 unsigned long saved_line
;
52 ISC_LINK(struct inputsource
) link
;
55 #define LEX_MAGIC ISC_MAGIC('L', 'e', 'x', '!')
56 #define VALID_LEX(l) ISC_MAGIC_VALID(l, LEX_MAGIC)
64 unsigned int comments
;
65 isc_boolean_t comment_ok
;
66 isc_boolean_t last_was_eol
;
67 unsigned int paren_count
;
68 unsigned int saved_paren_count
;
69 isc_lexspecials_t specials
;
70 LIST(struct inputsource
) sources
;
73 static inline isc_result_t
74 grow_data(isc_lex_t
*lex
, size_t *remainingp
, char **currp
, char **prevp
) {
77 new = isc_mem_get(lex
->mctx
, lex
->max_token
* 2 + 1);
79 return (ISC_R_NOMEMORY
);
80 memcpy(new, lex
->data
, lex
->max_token
+ 1);
81 *currp
= new + (*currp
- lex
->data
);
83 *prevp
= new + (*prevp
- lex
->data
);
84 isc_mem_put(lex
->mctx
, lex
->data
, lex
->max_token
+ 1);
86 *remainingp
+= lex
->max_token
;
88 return (ISC_R_SUCCESS
);
92 isc_lex_create(isc_mem_t
*mctx
, size_t max_token
, isc_lex_t
**lexp
) {
99 REQUIRE(lexp
!= NULL
&& *lexp
== NULL
);
100 REQUIRE(max_token
> 0U);
102 lex
= isc_mem_get(mctx
, sizeof(*lex
));
104 return (ISC_R_NOMEMORY
);
105 lex
->data
= isc_mem_get(mctx
, max_token
+ 1);
106 if (lex
->data
== NULL
) {
107 isc_mem_put(mctx
, lex
, sizeof(*lex
));
108 return (ISC_R_NOMEMORY
);
111 lex
->max_token
= max_token
;
113 lex
->comment_ok
= ISC_TRUE
;
114 lex
->last_was_eol
= ISC_TRUE
;
115 lex
->paren_count
= 0;
116 lex
->saved_paren_count
= 0;
117 memset(lex
->specials
, 0, 256);
118 INIT_LIST(lex
->sources
);
119 lex
->magic
= LEX_MAGIC
;
123 return (ISC_R_SUCCESS
);
127 isc_lex_destroy(isc_lex_t
**lexp
) {
134 REQUIRE(lexp
!= NULL
);
136 REQUIRE(VALID_LEX(lex
));
138 while (!EMPTY(lex
->sources
))
139 RUNTIME_CHECK(isc_lex_close(lex
) == ISC_R_SUCCESS
);
140 if (lex
->data
!= NULL
)
141 isc_mem_put(lex
->mctx
, lex
->data
, lex
->max_token
+ 1);
143 isc_mem_put(lex
->mctx
, lex
, sizeof(*lex
));
149 isc_lex_getcomments(isc_lex_t
*lex
) {
151 * Return the current lexer commenting styles.
154 REQUIRE(VALID_LEX(lex
));
156 return (lex
->comments
);
160 isc_lex_setcomments(isc_lex_t
*lex
, unsigned int comments
) {
162 * Set allowed lexer commenting styles.
165 REQUIRE(VALID_LEX(lex
));
167 lex
->comments
= comments
;
171 isc_lex_getspecials(isc_lex_t
*lex
, isc_lexspecials_t specials
) {
173 * Put the current list of specials into 'specials'.
176 REQUIRE(VALID_LEX(lex
));
178 memcpy(specials
, lex
->specials
, 256);
182 isc_lex_setspecials(isc_lex_t
*lex
, isc_lexspecials_t specials
) {
184 * The characters in 'specials' are returned as tokens. Along with
185 * whitespace, they delimit strings and numbers.
188 REQUIRE(VALID_LEX(lex
));
190 memcpy(lex
->specials
, specials
, 256);
193 static inline isc_result_t
194 new_source(isc_lex_t
*lex
, isc_boolean_t is_file
, isc_boolean_t need_close
,
195 void *input
, const char *name
)
200 source
= isc_mem_get(lex
->mctx
, sizeof(*source
));
202 return (ISC_R_NOMEMORY
);
203 source
->result
= ISC_R_SUCCESS
;
204 source
->is_file
= is_file
;
205 source
->need_close
= need_close
;
206 source
->at_eof
= ISC_FALSE
;
207 source
->input
= input
;
208 source
->name
= isc_mem_strdup(lex
->mctx
, name
);
209 if (source
->name
== NULL
) {
210 isc_mem_put(lex
->mctx
, source
, sizeof(*source
));
211 return (ISC_R_NOMEMORY
);
213 source
->pushback
= NULL
;
214 result
= isc_buffer_allocate(lex
->mctx
, &source
->pushback
,
216 if (result
!= ISC_R_SUCCESS
) {
217 isc_mem_free(lex
->mctx
, source
->name
);
218 isc_mem_put(lex
->mctx
, source
, sizeof(*source
));
223 ISC_LIST_INITANDPREPEND(lex
->sources
, source
, link
);
225 return (ISC_R_SUCCESS
);
229 isc_lex_openfile(isc_lex_t
*lex
, const char *filename
) {
234 * Open 'filename' and make it the current input source for 'lex'.
237 REQUIRE(VALID_LEX(lex
));
239 result
= isc_stdio_open(filename
, "r", &stream
);
240 if (result
!= ISC_R_SUCCESS
)
243 result
= new_source(lex
, ISC_TRUE
, ISC_TRUE
, stream
, filename
);
244 if (result
!= ISC_R_SUCCESS
)
245 (void)fclose(stream
);
250 isc_lex_openstream(isc_lex_t
*lex
, FILE *stream
) {
254 * Make 'stream' the current input source for 'lex'.
257 REQUIRE(VALID_LEX(lex
));
259 snprintf(name
, sizeof(name
), "stream-%p", stream
);
261 return (new_source(lex
, ISC_TRUE
, ISC_FALSE
, stream
, name
));
265 isc_lex_openbuffer(isc_lex_t
*lex
, isc_buffer_t
*buffer
) {
269 * Make 'buffer' the current input source for 'lex'.
272 REQUIRE(VALID_LEX(lex
));
274 snprintf(name
, sizeof(name
), "buffer-%p", buffer
);
276 return (new_source(lex
, ISC_FALSE
, ISC_FALSE
, buffer
, name
));
280 isc_lex_close(isc_lex_t
*lex
) {
284 * Close the most recently opened object (i.e. file or buffer).
287 REQUIRE(VALID_LEX(lex
));
289 source
= HEAD(lex
->sources
);
291 return (ISC_R_NOMORE
);
293 ISC_LIST_UNLINK(lex
->sources
, source
, link
);
294 if (source
->is_file
) {
295 if (source
->need_close
)
296 (void)fclose((FILE *)(source
->input
));
298 isc_mem_free(lex
->mctx
, source
->name
);
299 isc_buffer_free(&source
->pushback
);
300 isc_mem_put(lex
->mctx
, source
, sizeof(*source
));
302 return (ISC_R_SUCCESS
);
310 lexstate_maybecomment
,
312 lexstate_ccommentend
,
317 #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL)
320 pushback(inputsource
*source
, int c
) {
321 REQUIRE(source
->pushback
->current
> 0);
323 source
->at_eof
= ISC_FALSE
;
326 source
->pushback
->current
--;
332 pushandgrow(isc_lex_t
*lex
, inputsource
*source
, int c
) {
333 if (isc_buffer_availablelength(source
->pushback
) == 0) {
334 isc_buffer_t
*tbuf
= NULL
;
339 oldlen
= isc_buffer_length(source
->pushback
);
340 result
= isc_buffer_allocate(lex
->mctx
, &tbuf
, oldlen
* 2);
341 if (result
!= ISC_R_SUCCESS
)
343 isc_buffer_usedregion(source
->pushback
, &used
);
344 result
= isc_buffer_copyregion(tbuf
, &used
);
345 INSIST(result
== ISC_R_SUCCESS
);
346 tbuf
->current
= source
->pushback
->current
;
347 isc_buffer_free(&source
->pushback
);
348 source
->pushback
= tbuf
;
350 isc_buffer_putuint8(source
->pushback
, (isc_uint8_t
)c
);
351 return (ISC_R_SUCCESS
);
355 isc_lex_gettoken(isc_lex_t
*lex
, unsigned int options
, isc_token_t
*tokenp
) {
358 isc_boolean_t done
= ISC_FALSE
;
359 isc_boolean_t no_comments
= ISC_FALSE
;
360 isc_boolean_t escaped
= ISC_FALSE
;
361 lexstate state
= lexstate_start
;
362 lexstate saved_state
= lexstate_start
;
363 isc_buffer_t
*buffer
;
367 isc_uint32_t as_ulong
;
368 unsigned int saved_options
;
372 * Get the next token.
375 REQUIRE(VALID_LEX(lex
));
376 source
= HEAD(lex
->sources
);
377 REQUIRE(tokenp
!= NULL
);
379 if (source
== NULL
) {
380 if ((options
& ISC_LEXOPT_NOMORE
) != 0) {
381 tokenp
->type
= isc_tokentype_nomore
;
382 return (ISC_R_SUCCESS
);
384 return (ISC_R_NOMORE
);
387 if (source
->result
!= ISC_R_SUCCESS
)
388 return (source
->result
);
390 lex
->saved_paren_count
= lex
->paren_count
;
391 source
->saved_line
= source
->line
;
393 if (isc_buffer_remaininglength(source
->pushback
) == 0 &&
396 if ((options
& ISC_LEXOPT_DNSMULTILINE
) != 0 &&
397 lex
->paren_count
!= 0) {
398 lex
->paren_count
= 0;
399 return (ISC_R_UNBALANCED
);
401 if ((options
& ISC_LEXOPT_EOF
) != 0) {
402 tokenp
->type
= isc_tokentype_eof
;
403 return (ISC_R_SUCCESS
);
408 isc_buffer_compact(source
->pushback
);
410 saved_options
= options
;
411 if ((options
& ISC_LEXOPT_DNSMULTILINE
) != 0 && lex
->paren_count
> 0)
418 remaining
= lex
->max_token
;
420 #ifdef HAVE_FLOCKFILE
422 flockfile(source
->input
);
426 if (isc_buffer_remaininglength(source
->pushback
) == 0) {
427 if (source
->is_file
) {
428 stream
= source
->input
;
430 #if defined(HAVE_FLOCKFILE) && defined(HAVE_GETCUNLOCKED)
431 c
= getc_unlocked(stream
);
436 if (ferror(stream
)) {
437 source
->result
= ISC_R_IOERROR
;
438 result
= source
->result
;
441 source
->at_eof
= ISC_TRUE
;
444 buffer
= source
->input
;
446 if (buffer
->current
== buffer
->used
) {
448 source
->at_eof
= ISC_TRUE
;
450 c
= *((char *)buffer
->base
+
456 source
->result
= pushandgrow(lex
, source
, c
);
457 if (source
->result
!= ISC_R_SUCCESS
) {
458 result
= source
->result
;
464 if (!source
->at_eof
) {
465 if (state
== lexstate_start
)
466 /* Token has not started yet. */
468 isc_buffer_consumedlength(source
->pushback
);
469 c
= isc_buffer_getuint8(source
->pushback
);
477 if (lex
->comment_ok
&& !no_comments
) {
478 if (!escaped
&& c
== ';' &&
479 ((lex
->comments
& ISC_LEXCOMMENT_DNSMASTERFILE
)
482 state
= lexstate_eatline
;
483 no_comments
= ISC_TRUE
;
485 } else if (c
== '/' &&
488 ISC_LEXCOMMENT_CPLUSPLUS
)) != 0) {
490 state
= lexstate_maybecomment
;
491 no_comments
= ISC_TRUE
;
493 } else if (c
== '#' &&
494 ((lex
->comments
& ISC_LEXCOMMENT_SHELL
)
497 state
= lexstate_eatline
;
498 no_comments
= ISC_TRUE
;
504 /* INSIST(c == EOF || (c >= 0 && c <= 255)); */
508 lex
->last_was_eol
= ISC_FALSE
;
509 if ((options
& ISC_LEXOPT_DNSMULTILINE
) != 0 &&
510 lex
->paren_count
!= 0) {
511 lex
->paren_count
= 0;
512 result
= ISC_R_UNBALANCED
;
515 if ((options
& ISC_LEXOPT_EOF
) == 0) {
519 tokenp
->type
= isc_tokentype_eof
;
521 } else if (c
== ' ' || c
== '\t') {
522 if (lex
->last_was_eol
&&
523 (options
& ISC_LEXOPT_INITIALWS
)
525 lex
->last_was_eol
= ISC_FALSE
;
526 tokenp
->type
= isc_tokentype_initialws
;
527 tokenp
->value
.as_char
= c
;
530 } else if (c
== '\n') {
531 if ((options
& ISC_LEXOPT_EOL
) != 0) {
532 tokenp
->type
= isc_tokentype_eol
;
535 lex
->last_was_eol
= ISC_TRUE
;
536 } else if (c
== '\r') {
537 if ((options
& ISC_LEXOPT_EOL
) != 0)
538 state
= lexstate_crlf
;
539 } else if (c
== '"' &&
540 (options
& ISC_LEXOPT_QSTRING
) != 0) {
541 lex
->last_was_eol
= ISC_FALSE
;
542 no_comments
= ISC_TRUE
;
543 state
= lexstate_qstring
;
544 } else if (lex
->specials
[c
]) {
545 lex
->last_was_eol
= ISC_FALSE
;
546 if ((c
== '(' || c
== ')') &&
547 (options
& ISC_LEXOPT_DNSMULTILINE
) != 0) {
549 if (lex
->paren_count
== 0)
553 if (lex
->paren_count
== 0) {
554 result
= ISC_R_UNBALANCED
;
558 if (lex
->paren_count
== 0)
564 tokenp
->type
= isc_tokentype_special
;
565 tokenp
->value
.as_char
= c
;
567 } else if (isdigit((unsigned char)c
) &&
568 (options
& ISC_LEXOPT_NUMBER
) != 0) {
569 lex
->last_was_eol
= ISC_FALSE
;
570 if ((options
& ISC_LEXOPT_OCTAL
) != 0 &&
571 (c
== '8' || c
== '9'))
572 state
= lexstate_string
;
574 state
= lexstate_number
;
577 lex
->last_was_eol
= ISC_FALSE
;
578 state
= lexstate_string
;
585 tokenp
->type
= isc_tokentype_eol
;
587 lex
->last_was_eol
= ISC_TRUE
;
589 case lexstate_number
:
590 if (c
== EOF
|| !isdigit((unsigned char)c
)) {
591 if (c
== ' ' || c
== '\t' || c
== '\r' ||
592 c
== '\n' || c
== EOF
||
595 if ((options
& ISC_LEXOPT_OCTAL
) != 0)
597 else if ((options
& ISC_LEXOPT_CNUMBER
) != 0)
603 result
= isc_parse_uint32(&as_ulong
,
606 if (result
== ISC_R_SUCCESS
) {
608 isc_tokentype_number
;
609 tokenp
->value
.as_ulong
=
611 } else if (result
== ISC_R_BADNUMBER
) {
615 isc_tokentype_string
;
616 v
= &(tokenp
->value
);
617 v
->as_textregion
.base
=
619 v
->as_textregion
.length
=
626 } else if (!(options
& ISC_LEXOPT_CNUMBER
) ||
627 ((c
!= 'x' && c
!= 'X') ||
628 (curr
!= &lex
->data
[1]) ||
629 (lex
->data
[0] != '0'))) {
630 /* Above test supports hex numbers */
631 state
= lexstate_string
;
633 } else if ((options
& ISC_LEXOPT_OCTAL
) != 0 &&
634 (c
== '8' || c
== '9')) {
635 state
= lexstate_string
;
637 if (remaining
== 0U) {
638 result
= grow_data(lex
, &remaining
,
640 if (result
!= ISC_R_SUCCESS
)
643 INSIST(remaining
> 0U);
648 case lexstate_string
:
650 * EOF needs to be checked before lex->specials[c]
651 * as lex->specials[EOF] is not a good idea.
653 if (c
== '\r' || c
== '\n' || c
== EOF
||
655 (c
== ' ' || c
== '\t' || lex
->specials
[c
]))) {
657 if (source
->result
!= ISC_R_SUCCESS
) {
658 result
= source
->result
;
661 tokenp
->type
= isc_tokentype_string
;
662 tokenp
->value
.as_textregion
.base
= lex
->data
;
663 tokenp
->value
.as_textregion
.length
=
664 lex
->max_token
- remaining
;
668 if ((options
& ISC_LEXOPT_ESCAPE
) != 0)
669 escaped
= (!escaped
&& c
== '\\') ?
670 ISC_TRUE
: ISC_FALSE
;
671 if (remaining
== 0U) {
672 result
= grow_data(lex
, &remaining
,
674 if (result
!= ISC_R_SUCCESS
)
677 INSIST(remaining
> 0U);
682 case lexstate_maybecomment
:
684 (lex
->comments
& ISC_LEXCOMMENT_C
) != 0) {
685 state
= lexstate_ccomment
;
687 } else if (c
== '/' &&
688 (lex
->comments
& ISC_LEXCOMMENT_CPLUSPLUS
) != 0) {
689 state
= lexstate_eatline
;
694 no_comments
= ISC_FALSE
;
697 case lexstate_ccomment
:
699 result
= ISC_R_UNEXPECTEDEND
;
703 state
= lexstate_ccommentend
;
705 case lexstate_ccommentend
:
707 result
= ISC_R_UNEXPECTEDEND
;
712 * C-style comments become a single space.
713 * We do this to ensure that a comment will
714 * act as a delimiter for strings and
718 no_comments
= ISC_FALSE
;
722 state
= lexstate_ccomment
;
724 case lexstate_eatline
:
725 if ((c
== '\n') || (c
== EOF
)) {
726 no_comments
= ISC_FALSE
;
731 case lexstate_qstring
:
733 result
= ISC_R_UNEXPECTEDEND
;
740 * Overwrite the preceding backslash.
742 INSIST(prev
!= NULL
);
745 tokenp
->type
= isc_tokentype_qstring
;
746 tokenp
->value
.as_textregion
.base
=
748 tokenp
->value
.as_textregion
.length
=
749 lex
->max_token
- remaining
;
750 no_comments
= ISC_FALSE
;
754 if (c
== '\n' && !escaped
&&
755 (options
& ISC_LEXOPT_QSTRINGMULTILINE
) == 0) {
757 result
= ISC_R_UNBALANCEDQUOTES
;
760 if (c
== '\\' && !escaped
)
764 if (remaining
== 0U) {
765 result
= grow_data(lex
, &remaining
,
767 if (result
!= ISC_R_SUCCESS
)
770 INSIST(remaining
> 0U);
778 FATAL_ERROR(__FILE__
, __LINE__
,
779 isc_msgcat_get(isc_msgcat
, ISC_MSGSET_LEX
,
780 ISC_MSG_UNEXPECTEDSTATE
,
781 "Unexpected state %d"),
783 /* Does not return. */
788 result
= ISC_R_SUCCESS
;
790 #ifdef HAVE_FLOCKFILE
792 funlockfile(source
->input
);
798 isc_lex_getmastertoken(isc_lex_t
*lex
, isc_token_t
*token
,
799 isc_tokentype_t expect
, isc_boolean_t eol
)
801 unsigned int options
= ISC_LEXOPT_EOL
| ISC_LEXOPT_EOF
|
802 ISC_LEXOPT_DNSMULTILINE
| ISC_LEXOPT_ESCAPE
;
805 if (expect
== isc_tokentype_qstring
)
806 options
|= ISC_LEXOPT_QSTRING
;
807 else if (expect
== isc_tokentype_number
)
808 options
|= ISC_LEXOPT_NUMBER
;
809 result
= isc_lex_gettoken(lex
, options
, token
);
810 if (result
== ISC_R_RANGE
)
811 isc_lex_ungettoken(lex
, token
);
812 if (result
!= ISC_R_SUCCESS
)
815 if (eol
&& ((token
->type
== isc_tokentype_eol
) ||
816 (token
->type
== isc_tokentype_eof
)))
817 return (ISC_R_SUCCESS
);
818 if (token
->type
== isc_tokentype_string
&&
819 expect
== isc_tokentype_qstring
)
820 return (ISC_R_SUCCESS
);
821 if (token
->type
!= expect
) {
822 isc_lex_ungettoken(lex
, token
);
823 if (token
->type
== isc_tokentype_eol
||
824 token
->type
== isc_tokentype_eof
)
825 return (ISC_R_UNEXPECTEDEND
);
826 if (expect
== isc_tokentype_number
)
827 return (ISC_R_BADNUMBER
);
828 return (ISC_R_UNEXPECTEDTOKEN
);
830 return (ISC_R_SUCCESS
);
834 isc_lex_getoctaltoken(isc_lex_t
*lex
, isc_token_t
*token
, isc_boolean_t eol
)
836 unsigned int options
= ISC_LEXOPT_EOL
| ISC_LEXOPT_EOF
|
837 ISC_LEXOPT_DNSMULTILINE
| ISC_LEXOPT_ESCAPE
|
838 ISC_LEXOPT_NUMBER
| ISC_LEXOPT_OCTAL
;
841 result
= isc_lex_gettoken(lex
, options
, token
);
842 if (result
== ISC_R_RANGE
)
843 isc_lex_ungettoken(lex
, token
);
844 if (result
!= ISC_R_SUCCESS
)
847 if (eol
&& ((token
->type
== isc_tokentype_eol
) ||
848 (token
->type
== isc_tokentype_eof
)))
849 return (ISC_R_SUCCESS
);
850 if (token
->type
!= isc_tokentype_number
) {
851 isc_lex_ungettoken(lex
, token
);
852 if (token
->type
== isc_tokentype_eol
||
853 token
->type
== isc_tokentype_eof
)
854 return (ISC_R_UNEXPECTEDEND
);
855 return (ISC_R_BADNUMBER
);
857 return (ISC_R_SUCCESS
);
861 isc_lex_ungettoken(isc_lex_t
*lex
, isc_token_t
*tokenp
) {
864 * Unget the current token.
867 REQUIRE(VALID_LEX(lex
));
868 source
= HEAD(lex
->sources
);
869 REQUIRE(source
!= NULL
);
870 REQUIRE(tokenp
!= NULL
);
871 REQUIRE(isc_buffer_consumedlength(source
->pushback
) != 0 ||
872 tokenp
->type
== isc_tokentype_eof
);
876 isc_buffer_first(source
->pushback
);
877 lex
->paren_count
= lex
->saved_paren_count
;
878 source
->line
= source
->saved_line
;
879 source
->at_eof
= ISC_FALSE
;
883 isc_lex_getlasttokentext(isc_lex_t
*lex
, isc_token_t
*tokenp
, isc_region_t
*r
)
887 REQUIRE(VALID_LEX(lex
));
888 source
= HEAD(lex
->sources
);
889 REQUIRE(source
!= NULL
);
890 REQUIRE(tokenp
!= NULL
);
891 REQUIRE(isc_buffer_consumedlength(source
->pushback
) != 0 ||
892 tokenp
->type
== isc_tokentype_eof
);
896 INSIST(source
->ignored
<= isc_buffer_consumedlength(source
->pushback
));
897 r
->base
= (unsigned char *)isc_buffer_base(source
->pushback
) +
899 r
->length
= isc_buffer_consumedlength(source
->pushback
) -
905 isc_lex_getsourcename(isc_lex_t
*lex
) {
908 REQUIRE(VALID_LEX(lex
));
909 source
= HEAD(lex
->sources
);
914 return (source
->name
);
918 isc_lex_getsourceline(isc_lex_t
*lex
) {
921 REQUIRE(VALID_LEX(lex
));
922 source
= HEAD(lex
->sources
);
927 return (source
->line
);
932 isc_lex_setsourcename(isc_lex_t
*lex
, const char *name
) {
936 REQUIRE(VALID_LEX(lex
));
937 source
= HEAD(lex
->sources
);
940 return(ISC_R_NOTFOUND
);
941 newname
= isc_mem_strdup(lex
->mctx
, name
);
943 return (ISC_R_NOMEMORY
);
944 isc_mem_free(lex
->mctx
, source
->name
);
945 source
->name
= newname
;
946 return (ISC_R_SUCCESS
);
950 isc_lex_isfile(isc_lex_t
*lex
) {
953 REQUIRE(VALID_LEX(lex
));
955 source
= HEAD(lex
->sources
);
960 return (source
->is_file
);