00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <ctype.h>
00025 #include <errno.h>
00026 #include <stdlib.h>
00027
00028 #include <isc/buffer.h>
00029 #include <isc/file.h>
00030 #include <isc/lex.h>
00031 #include <isc/mem.h>
00032 #include <isc/msgs.h>
00033 #include <isc/parseint.h>
00034 #include <isc/print.h>
00035 #include <isc/stdio.h>
00036 #include <isc/string.h>
00037 #include <isc/util.h>
00038
00039 typedef struct inputsource {
00040 isc_result_t result;
00041 isc_boolean_t is_file;
00042 isc_boolean_t need_close;
00043 isc_boolean_t at_eof;
00044 isc_boolean_t last_was_eol;
00045 isc_buffer_t * pushback;
00046 unsigned int ignored;
00047 void * input;
00048 char * name;
00049 unsigned long line;
00050 unsigned long saved_line;
00051 ISC_LINK(struct inputsource) link;
00052 } inputsource;
00053
00054 #define LEX_MAGIC ISC_MAGIC('L', 'e', 'x', '!')
00055 #define VALID_LEX(l) ISC_MAGIC_VALID(l, LEX_MAGIC)
00056
00057 struct isc_lex {
00058
00059 unsigned int magic;
00060 isc_mem_t * mctx;
00061 size_t max_token;
00062 char * data;
00063 unsigned int comments;
00064 isc_boolean_t comment_ok;
00065 isc_boolean_t last_was_eol;
00066 unsigned int paren_count;
00067 unsigned int saved_paren_count;
00068 isc_lexspecials_t specials;
00069 LIST(struct inputsource) sources;
00070 };
00071
00072 static inline isc_result_t
00073 grow_data(isc_lex_t *lex, size_t *remainingp, char **currp, char **prevp) {
00074 char *new;
00075
00076 new = isc_mem_get(lex->mctx, lex->max_token * 2 + 1);
00077 if (new == NULL)
00078 return (ISC_R_NOMEMORY);
00079 memmove(new, lex->data, lex->max_token + 1);
00080 *currp = new + (*currp - lex->data);
00081 if (*prevp != NULL)
00082 *prevp = new + (*prevp - lex->data);
00083 isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
00084 lex->data = new;
00085 *remainingp += lex->max_token;
00086 lex->max_token *= 2;
00087 return (ISC_R_SUCCESS);
00088 }
00089
00090 isc_result_t
00091 isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) {
00092 isc_lex_t *lex;
00093
00094
00095
00096
00097
00098 REQUIRE(lexp != NULL && *lexp == NULL);
00099 REQUIRE(max_token > 0U);
00100
00101 lex = isc_mem_get(mctx, sizeof(*lex));
00102 if (lex == NULL)
00103 return (ISC_R_NOMEMORY);
00104 lex->data = isc_mem_get(mctx, max_token + 1);
00105 if (lex->data == NULL) {
00106 isc_mem_put(mctx, lex, sizeof(*lex));
00107 return (ISC_R_NOMEMORY);
00108 }
00109 lex->mctx = mctx;
00110 lex->max_token = max_token;
00111 lex->comments = 0;
00112 lex->comment_ok = ISC_TRUE;
00113 lex->last_was_eol = ISC_TRUE;
00114 lex->paren_count = 0;
00115 lex->saved_paren_count = 0;
00116 memset(lex->specials, 0, 256);
00117 INIT_LIST(lex->sources);
00118 lex->magic = LEX_MAGIC;
00119
00120 *lexp = lex;
00121
00122 return (ISC_R_SUCCESS);
00123 }
00124
00125 void
00126 isc_lex_destroy(isc_lex_t **lexp) {
00127 isc_lex_t *lex;
00128
00129
00130
00131
00132
00133 REQUIRE(lexp != NULL);
00134 lex = *lexp;
00135 REQUIRE(VALID_LEX(lex));
00136
00137 while (!EMPTY(lex->sources))
00138 RUNTIME_CHECK(isc_lex_close(lex) == ISC_R_SUCCESS);
00139 if (lex->data != NULL)
00140 isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
00141 lex->magic = 0;
00142 isc_mem_put(lex->mctx, lex, sizeof(*lex));
00143
00144 *lexp = NULL;
00145 }
00146
00147 unsigned int
00148 isc_lex_getcomments(isc_lex_t *lex) {
00149
00150
00151
00152
00153 REQUIRE(VALID_LEX(lex));
00154
00155 return (lex->comments);
00156 }
00157
00158 void
00159 isc_lex_setcomments(isc_lex_t *lex, unsigned int comments) {
00160
00161
00162
00163
00164 REQUIRE(VALID_LEX(lex));
00165
00166 lex->comments = comments;
00167 }
00168
00169 void
00170 isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
00171
00172
00173
00174
00175 REQUIRE(VALID_LEX(lex));
00176
00177 memmove(specials, lex->specials, 256);
00178 }
00179
00180 void
00181 isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
00182
00183
00184
00185
00186
00187 REQUIRE(VALID_LEX(lex));
00188
00189 memmove(lex->specials, specials, 256);
00190 }
00191
00192 static inline isc_result_t
00193 new_source(isc_lex_t *lex, isc_boolean_t is_file, isc_boolean_t need_close,
00194 void *input, const char *name)
00195 {
00196 inputsource *source;
00197 isc_result_t result;
00198
00199 source = isc_mem_get(lex->mctx, sizeof(*source));
00200 if (source == NULL)
00201 return (ISC_R_NOMEMORY);
00202 source->result = ISC_R_SUCCESS;
00203 source->is_file = is_file;
00204 source->need_close = need_close;
00205 source->at_eof = ISC_FALSE;
00206 source->last_was_eol = lex->last_was_eol;
00207 source->input = input;
00208 source->name = isc_mem_strdup(lex->mctx, name);
00209 if (source->name == NULL) {
00210 isc_mem_put(lex->mctx, source, sizeof(*source));
00211 return (ISC_R_NOMEMORY);
00212 }
00213 source->pushback = NULL;
00214 result = isc_buffer_allocate(lex->mctx, &source->pushback,
00215 (unsigned int)lex->max_token);
00216 if (result != ISC_R_SUCCESS) {
00217 isc_mem_free(lex->mctx, source->name);
00218 isc_mem_put(lex->mctx, source, sizeof(*source));
00219 return (result);
00220 }
00221 source->ignored = 0;
00222 source->line = 1;
00223 ISC_LIST_INITANDPREPEND(lex->sources, source, link);
00224
00225 return (ISC_R_SUCCESS);
00226 }
00227
00228 isc_result_t
00229 isc_lex_openfile(isc_lex_t *lex, const char *filename) {
00230 isc_result_t result;
00231 FILE *stream = NULL;
00232
00233
00234
00235
00236
00237 REQUIRE(VALID_LEX(lex));
00238
00239 result = isc_stdio_open(filename, "r", &stream);
00240 if (result != ISC_R_SUCCESS)
00241 return (result);
00242
00243 result = new_source(lex, ISC_TRUE, ISC_TRUE, stream, filename);
00244 if (result != ISC_R_SUCCESS)
00245 (void)fclose(stream);
00246 return (result);
00247 }
00248
00249 isc_result_t
00250 isc_lex_openstream(isc_lex_t *lex, FILE *stream) {
00251 char name[128];
00252
00253
00254
00255
00256
00257 REQUIRE(VALID_LEX(lex));
00258
00259 snprintf(name, sizeof(name), "stream-%p", stream);
00260
00261 return (new_source(lex, ISC_TRUE, ISC_FALSE, stream, name));
00262 }
00263
00264 isc_result_t
00265 isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer) {
00266 char name[128];
00267
00268
00269
00270
00271
00272 REQUIRE(VALID_LEX(lex));
00273
00274 snprintf(name, sizeof(name), "buffer-%p", buffer);
00275
00276 return (new_source(lex, ISC_FALSE, ISC_FALSE, buffer, name));
00277 }
00278
00279 isc_result_t
00280 isc_lex_close(isc_lex_t *lex) {
00281 inputsource *source;
00282
00283
00284
00285
00286
00287 REQUIRE(VALID_LEX(lex));
00288
00289 source = HEAD(lex->sources);
00290 if (source == NULL)
00291 return (ISC_R_NOMORE);
00292
00293 ISC_LIST_UNLINK(lex->sources, source, link);
00294 lex->last_was_eol = source->last_was_eol;
00295 if (source->is_file) {
00296 if (source->need_close)
00297 (void)fclose((FILE *)(source->input));
00298 }
00299 isc_mem_free(lex->mctx, source->name);
00300 isc_buffer_free(&source->pushback);
00301 isc_mem_put(lex->mctx, source, sizeof(*source));
00302
00303 return (ISC_R_SUCCESS);
00304 }
00305
00306 typedef enum {
00307 lexstate_start,
00308 lexstate_crlf,
00309 lexstate_string,
00310 lexstate_number,
00311 lexstate_maybecomment,
00312 lexstate_ccomment,
00313 lexstate_ccommentend,
00314 lexstate_eatline,
00315 lexstate_qstring
00316 } lexstate;
00317
00318 #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL)
00319
00320 static void
00321 pushback(inputsource *source, int c) {
00322 REQUIRE(source->pushback->current > 0);
00323 if (c == EOF) {
00324 source->at_eof = ISC_FALSE;
00325 return;
00326 }
00327 source->pushback->current--;
00328 if (c == '\n')
00329 source->line--;
00330 }
00331
00332 static isc_result_t
00333 pushandgrow(isc_lex_t *lex, inputsource *source, int c) {
00334 if (isc_buffer_availablelength(source->pushback) == 0) {
00335 isc_buffer_t *tbuf = NULL;
00336 unsigned int oldlen;
00337 isc_region_t used;
00338 isc_result_t result;
00339
00340 oldlen = isc_buffer_length(source->pushback);
00341 result = isc_buffer_allocate(lex->mctx, &tbuf, oldlen * 2);
00342 if (result != ISC_R_SUCCESS)
00343 return (result);
00344 isc_buffer_usedregion(source->pushback, &used);
00345 result = isc_buffer_copyregion(tbuf, &used);
00346 INSIST(result == ISC_R_SUCCESS);
00347 tbuf->current = source->pushback->current;
00348 isc_buffer_free(&source->pushback);
00349 source->pushback = tbuf;
00350 }
00351 isc_buffer_putuint8(source->pushback, (isc_uint8_t)c);
00352 return (ISC_R_SUCCESS);
00353 }
00354
00355 isc_result_t
00356 isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
00357 inputsource *source;
00358 int c;
00359 isc_boolean_t done = ISC_FALSE;
00360 isc_boolean_t no_comments = ISC_FALSE;
00361 isc_boolean_t escaped = ISC_FALSE;
00362 lexstate state = lexstate_start;
00363 lexstate saved_state = lexstate_start;
00364 isc_buffer_t *buffer;
00365 FILE *stream;
00366 char *curr, *prev;
00367 size_t remaining;
00368 isc_uint32_t as_ulong;
00369 unsigned int saved_options;
00370 isc_result_t result;
00371
00372
00373
00374
00375
00376 REQUIRE(VALID_LEX(lex));
00377 source = HEAD(lex->sources);
00378 REQUIRE(tokenp != NULL);
00379
00380 if (source == NULL) {
00381 if ((options & ISC_LEXOPT_NOMORE) != 0) {
00382 tokenp->type = isc_tokentype_nomore;
00383 return (ISC_R_SUCCESS);
00384 }
00385 return (ISC_R_NOMORE);
00386 }
00387
00388 if (source->result != ISC_R_SUCCESS)
00389 return (source->result);
00390
00391 lex->saved_paren_count = lex->paren_count;
00392 source->saved_line = source->line;
00393
00394 if (isc_buffer_remaininglength(source->pushback) == 0 &&
00395 source->at_eof)
00396 {
00397 if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
00398 lex->paren_count != 0) {
00399 lex->paren_count = 0;
00400 return (ISC_R_UNBALANCED);
00401 }
00402 if ((options & ISC_LEXOPT_EOF) != 0) {
00403 tokenp->type = isc_tokentype_eof;
00404 return (ISC_R_SUCCESS);
00405 }
00406 return (ISC_R_EOF);
00407 }
00408
00409 isc_buffer_compact(source->pushback);
00410
00411 saved_options = options;
00412 if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && lex->paren_count > 0)
00413 options &= ~IWSEOL;
00414
00415 curr = lex->data;
00416 *curr = '\0';
00417
00418 prev = NULL;
00419 remaining = lex->max_token;
00420
00421 #ifdef HAVE_FLOCKFILE
00422 if (source->is_file)
00423 flockfile(source->input);
00424 #endif
00425
00426 do {
00427 if (isc_buffer_remaininglength(source->pushback) == 0) {
00428 if (source->is_file) {
00429 stream = source->input;
00430
00431 #if defined(HAVE_FLOCKFILE) && defined(HAVE_GETCUNLOCKED)
00432 c = getc_unlocked(stream);
00433 #else
00434 c = getc(stream);
00435 #endif
00436 if (c == EOF) {
00437 if (ferror(stream)) {
00438 source->result = ISC_R_IOERROR;
00439 result = source->result;
00440 goto done;
00441 }
00442 source->at_eof = ISC_TRUE;
00443 }
00444 } else {
00445 buffer = source->input;
00446
00447 if (buffer->current == buffer->used) {
00448 c = EOF;
00449 source->at_eof = ISC_TRUE;
00450 } else {
00451 c = *((unsigned char *)buffer->base +
00452 buffer->current);
00453 buffer->current++;
00454 }
00455 }
00456 if (c != EOF) {
00457 source->result = pushandgrow(lex, source, c);
00458 if (source->result != ISC_R_SUCCESS) {
00459 result = source->result;
00460 goto done;
00461 }
00462 }
00463 }
00464
00465 if (!source->at_eof) {
00466 if (state == lexstate_start)
00467
00468 source->ignored =
00469 isc_buffer_consumedlength(source->pushback);
00470 c = isc_buffer_getuint8(source->pushback);
00471 } else {
00472 c = EOF;
00473 }
00474
00475 if (c == '\n')
00476 source->line++;
00477
00478 if (lex->comment_ok && !no_comments) {
00479 if (!escaped && c == ';' &&
00480 ((lex->comments & ISC_LEXCOMMENT_DNSMASTERFILE)
00481 != 0)) {
00482 saved_state = state;
00483 state = lexstate_eatline;
00484 no_comments = ISC_TRUE;
00485 continue;
00486 } else if (c == '/' &&
00487 (lex->comments &
00488 (ISC_LEXCOMMENT_C|
00489 ISC_LEXCOMMENT_CPLUSPLUS)) != 0) {
00490 saved_state = state;
00491 state = lexstate_maybecomment;
00492 no_comments = ISC_TRUE;
00493 continue;
00494 } else if (c == '#' &&
00495 ((lex->comments & ISC_LEXCOMMENT_SHELL)
00496 != 0)) {
00497 saved_state = state;
00498 state = lexstate_eatline;
00499 no_comments = ISC_TRUE;
00500 continue;
00501 }
00502 }
00503
00504 no_read:
00505
00506 switch (state) {
00507 case lexstate_start:
00508 if (c == EOF) {
00509 lex->last_was_eol = ISC_FALSE;
00510 if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
00511 lex->paren_count != 0) {
00512 lex->paren_count = 0;
00513 result = ISC_R_UNBALANCED;
00514 goto done;
00515 }
00516 if ((options & ISC_LEXOPT_EOF) == 0) {
00517 result = ISC_R_EOF;
00518 goto done;
00519 }
00520 tokenp->type = isc_tokentype_eof;
00521 done = ISC_TRUE;
00522 } else if (c == ' ' || c == '\t') {
00523 if (lex->last_was_eol &&
00524 (options & ISC_LEXOPT_INITIALWS)
00525 != 0) {
00526 lex->last_was_eol = ISC_FALSE;
00527 tokenp->type = isc_tokentype_initialws;
00528 tokenp->value.as_char = c;
00529 done = ISC_TRUE;
00530 }
00531 } else if (c == '\n') {
00532 if ((options & ISC_LEXOPT_EOL) != 0) {
00533 tokenp->type = isc_tokentype_eol;
00534 done = ISC_TRUE;
00535 }
00536 lex->last_was_eol = ISC_TRUE;
00537 } else if (c == '\r') {
00538 if ((options & ISC_LEXOPT_EOL) != 0)
00539 state = lexstate_crlf;
00540 } else if (c == '"' &&
00541 (options & ISC_LEXOPT_QSTRING) != 0) {
00542 lex->last_was_eol = ISC_FALSE;
00543 no_comments = ISC_TRUE;
00544 state = lexstate_qstring;
00545 } else if (lex->specials[c]) {
00546 lex->last_was_eol = ISC_FALSE;
00547 if ((c == '(' || c == ')') &&
00548 (options & ISC_LEXOPT_DNSMULTILINE) != 0) {
00549 if (c == '(') {
00550 if (lex->paren_count == 0)
00551 options &= ~IWSEOL;
00552 lex->paren_count++;
00553 } else {
00554 if (lex->paren_count == 0) {
00555 result = ISC_R_UNBALANCED;
00556 goto done;
00557 }
00558 lex->paren_count--;
00559 if (lex->paren_count == 0)
00560 options =
00561 saved_options;
00562 }
00563 continue;
00564 }
00565 tokenp->type = isc_tokentype_special;
00566 tokenp->value.as_char = c;
00567 done = ISC_TRUE;
00568 } else if (isdigit((unsigned char)c) &&
00569 (options & ISC_LEXOPT_NUMBER) != 0) {
00570 lex->last_was_eol = ISC_FALSE;
00571 if ((options & ISC_LEXOPT_OCTAL) != 0 &&
00572 (c == '8' || c == '9'))
00573 state = lexstate_string;
00574 else
00575 state = lexstate_number;
00576 goto no_read;
00577 } else {
00578 lex->last_was_eol = ISC_FALSE;
00579 state = lexstate_string;
00580 goto no_read;
00581 }
00582 break;
00583 case lexstate_crlf:
00584 if (c != '\n')
00585 pushback(source, c);
00586 tokenp->type = isc_tokentype_eol;
00587 done = ISC_TRUE;
00588 lex->last_was_eol = ISC_TRUE;
00589 break;
00590 case lexstate_number:
00591 if (c == EOF || !isdigit((unsigned char)c)) {
00592 if (c == ' ' || c == '\t' || c == '\r' ||
00593 c == '\n' || c == EOF ||
00594 lex->specials[c]) {
00595 int base;
00596 if ((options & ISC_LEXOPT_OCTAL) != 0)
00597 base = 8;
00598 else if ((options & ISC_LEXOPT_CNUMBER) != 0)
00599 base = 0;
00600 else
00601 base = 10;
00602 pushback(source, c);
00603
00604 result = isc_parse_uint32(&as_ulong,
00605 lex->data,
00606 base);
00607 if (result == ISC_R_SUCCESS) {
00608 tokenp->type =
00609 isc_tokentype_number;
00610 tokenp->value.as_ulong =
00611 as_ulong;
00612 } else if (result == ISC_R_BADNUMBER) {
00613 isc_tokenvalue_t *v;
00614
00615 tokenp->type =
00616 isc_tokentype_string;
00617 v = &(tokenp->value);
00618 v->as_textregion.base =
00619 lex->data;
00620 v->as_textregion.length =
00621 (unsigned int)
00622 (lex->max_token -
00623 remaining);
00624 } else
00625 goto done;
00626 done = ISC_TRUE;
00627 continue;
00628 } else if (!(options & ISC_LEXOPT_CNUMBER) ||
00629 ((c != 'x' && c != 'X') ||
00630 (curr != &lex->data[1]) ||
00631 (lex->data[0] != '0'))) {
00632
00633 state = lexstate_string;
00634 }
00635 } else if ((options & ISC_LEXOPT_OCTAL) != 0 &&
00636 (c == '8' || c == '9')) {
00637 state = lexstate_string;
00638 }
00639 if (remaining == 0U) {
00640 result = grow_data(lex, &remaining,
00641 &curr, &prev);
00642 if (result != ISC_R_SUCCESS)
00643 goto done;
00644 }
00645 INSIST(remaining > 0U);
00646 *curr++ = c;
00647 *curr = '\0';
00648 remaining--;
00649 break;
00650 case lexstate_string:
00651
00652
00653
00654
00655 if (c == '\r' || c == '\n' || c == EOF ||
00656 (!escaped &&
00657 (c == ' ' || c == '\t' || lex->specials[c]))) {
00658 pushback(source, c);
00659 if (source->result != ISC_R_SUCCESS) {
00660 result = source->result;
00661 goto done;
00662 }
00663 tokenp->type = isc_tokentype_string;
00664 tokenp->value.as_textregion.base = lex->data;
00665 tokenp->value.as_textregion.length =
00666 (unsigned int)
00667 (lex->max_token - remaining);
00668 done = ISC_TRUE;
00669 continue;
00670 }
00671 if ((options & ISC_LEXOPT_ESCAPE) != 0)
00672 escaped = (!escaped && c == '\\') ?
00673 ISC_TRUE : ISC_FALSE;
00674 if (remaining == 0U) {
00675 result = grow_data(lex, &remaining,
00676 &curr, &prev);
00677 if (result != ISC_R_SUCCESS)
00678 goto done;
00679 }
00680 INSIST(remaining > 0U);
00681 *curr++ = c;
00682 *curr = '\0';
00683 remaining--;
00684 break;
00685 case lexstate_maybecomment:
00686 if (c == '*' &&
00687 (lex->comments & ISC_LEXCOMMENT_C) != 0) {
00688 state = lexstate_ccomment;
00689 continue;
00690 } else if (c == '/' &&
00691 (lex->comments & ISC_LEXCOMMENT_CPLUSPLUS) != 0) {
00692 state = lexstate_eatline;
00693 continue;
00694 }
00695 pushback(source, c);
00696 c = '/';
00697 no_comments = ISC_FALSE;
00698 state = saved_state;
00699 goto no_read;
00700 case lexstate_ccomment:
00701 if (c == EOF) {
00702 result = ISC_R_UNEXPECTEDEND;
00703 goto done;
00704 }
00705 if (c == '*')
00706 state = lexstate_ccommentend;
00707 break;
00708 case lexstate_ccommentend:
00709 if (c == EOF) {
00710 result = ISC_R_UNEXPECTEDEND;
00711 goto done;
00712 }
00713 if (c == '/') {
00714
00715
00716
00717
00718
00719
00720 c = ' ';
00721 no_comments = ISC_FALSE;
00722 state = saved_state;
00723 goto no_read;
00724 } else if (c != '*')
00725 state = lexstate_ccomment;
00726 break;
00727 case lexstate_eatline:
00728 if ((c == '\n') || (c == EOF)) {
00729 no_comments = ISC_FALSE;
00730 state = saved_state;
00731 goto no_read;
00732 }
00733 break;
00734 case lexstate_qstring:
00735 if (c == EOF) {
00736 result = ISC_R_UNEXPECTEDEND;
00737 goto done;
00738 }
00739 if (c == '"') {
00740 if (escaped) {
00741 escaped = ISC_FALSE;
00742
00743
00744
00745 INSIST(prev != NULL);
00746 *prev = '"';
00747 } else {
00748 tokenp->type = isc_tokentype_qstring;
00749 tokenp->value.as_textregion.base =
00750 lex->data;
00751 tokenp->value.as_textregion.length =
00752 (unsigned int)
00753 (lex->max_token - remaining);
00754 no_comments = ISC_FALSE;
00755 done = ISC_TRUE;
00756 }
00757 } else {
00758 if (c == '\n' && !escaped &&
00759 (options & ISC_LEXOPT_QSTRINGMULTILINE) == 0) {
00760 pushback(source, c);
00761 result = ISC_R_UNBALANCEDQUOTES;
00762 goto done;
00763 }
00764 if (c == '\\' && !escaped)
00765 escaped = ISC_TRUE;
00766 else
00767 escaped = ISC_FALSE;
00768 if (remaining == 0U) {
00769 result = grow_data(lex, &remaining,
00770 &curr, &prev);
00771 if (result != ISC_R_SUCCESS)
00772 goto done;
00773 }
00774 INSIST(remaining > 0U);
00775 prev = curr;
00776 *curr++ = c;
00777 *curr = '\0';
00778 remaining--;
00779 }
00780 break;
00781 default:
00782 FATAL_ERROR(__FILE__, __LINE__,
00783 isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX,
00784 ISC_MSG_UNEXPECTEDSTATE,
00785 "Unexpected state %d"),
00786 state);
00787
00788 }
00789
00790 } while (!done);
00791
00792 result = ISC_R_SUCCESS;
00793 done:
00794 #ifdef HAVE_FLOCKFILE
00795 if (source->is_file)
00796 funlockfile(source->input);
00797 #endif
00798 return (result);
00799 }
00800
00801 isc_result_t
00802 isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
00803 isc_tokentype_t expect, isc_boolean_t eol)
00804 {
00805 unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
00806 ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
00807 isc_result_t result;
00808
00809 if (expect == isc_tokentype_qstring)
00810 options |= ISC_LEXOPT_QSTRING;
00811 else if (expect == isc_tokentype_number)
00812 options |= ISC_LEXOPT_NUMBER;
00813 result = isc_lex_gettoken(lex, options, token);
00814 if (result == ISC_R_RANGE)
00815 isc_lex_ungettoken(lex, token);
00816 if (result != ISC_R_SUCCESS)
00817 return (result);
00818
00819 if (eol && ((token->type == isc_tokentype_eol) ||
00820 (token->type == isc_tokentype_eof)))
00821 return (ISC_R_SUCCESS);
00822 if (token->type == isc_tokentype_string &&
00823 expect == isc_tokentype_qstring)
00824 return (ISC_R_SUCCESS);
00825 if (token->type != expect) {
00826 isc_lex_ungettoken(lex, token);
00827 if (token->type == isc_tokentype_eol ||
00828 token->type == isc_tokentype_eof)
00829 return (ISC_R_UNEXPECTEDEND);
00830 if (expect == isc_tokentype_number)
00831 return (ISC_R_BADNUMBER);
00832 return (ISC_R_UNEXPECTEDTOKEN);
00833 }
00834 return (ISC_R_SUCCESS);
00835 }
00836
00837 isc_result_t
00838 isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol)
00839 {
00840 unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
00841 ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE|
00842 ISC_LEXOPT_NUMBER | ISC_LEXOPT_OCTAL;
00843 isc_result_t result;
00844
00845 result = isc_lex_gettoken(lex, options, token);
00846 if (result == ISC_R_RANGE)
00847 isc_lex_ungettoken(lex, token);
00848 if (result != ISC_R_SUCCESS)
00849 return (result);
00850
00851 if (eol && ((token->type == isc_tokentype_eol) ||
00852 (token->type == isc_tokentype_eof)))
00853 return (ISC_R_SUCCESS);
00854 if (token->type != isc_tokentype_number) {
00855 isc_lex_ungettoken(lex, token);
00856 if (token->type == isc_tokentype_eol ||
00857 token->type == isc_tokentype_eof)
00858 return (ISC_R_UNEXPECTEDEND);
00859 return (ISC_R_BADNUMBER);
00860 }
00861 return (ISC_R_SUCCESS);
00862 }
00863
00864 void
00865 isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) {
00866 inputsource *source;
00867
00868
00869
00870
00871 REQUIRE(VALID_LEX(lex));
00872 source = HEAD(lex->sources);
00873 REQUIRE(source != NULL);
00874 REQUIRE(tokenp != NULL);
00875 REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
00876 tokenp->type == isc_tokentype_eof);
00877
00878 UNUSED(tokenp);
00879
00880 isc_buffer_first(source->pushback);
00881 lex->paren_count = lex->saved_paren_count;
00882 source->line = source->saved_line;
00883 source->at_eof = ISC_FALSE;
00884 }
00885
00886 void
00887 isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r)
00888 {
00889 inputsource *source;
00890
00891 REQUIRE(VALID_LEX(lex));
00892 source = HEAD(lex->sources);
00893 REQUIRE(source != NULL);
00894 REQUIRE(tokenp != NULL);
00895 REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
00896 tokenp->type == isc_tokentype_eof);
00897
00898 UNUSED(tokenp);
00899
00900 INSIST(source->ignored <= isc_buffer_consumedlength(source->pushback));
00901 r->base = (unsigned char *)isc_buffer_base(source->pushback) +
00902 source->ignored;
00903 r->length = isc_buffer_consumedlength(source->pushback) -
00904 source->ignored;
00905 }
00906
00907
00908 char *
00909 isc_lex_getsourcename(isc_lex_t *lex) {
00910 inputsource *source;
00911
00912 REQUIRE(VALID_LEX(lex));
00913 source = HEAD(lex->sources);
00914
00915 if (source == NULL)
00916 return (NULL);
00917
00918 return (source->name);
00919 }
00920
00921 unsigned long
00922 isc_lex_getsourceline(isc_lex_t *lex) {
00923 inputsource *source;
00924
00925 REQUIRE(VALID_LEX(lex));
00926 source = HEAD(lex->sources);
00927
00928 if (source == NULL)
00929 return (0);
00930
00931 return (source->line);
00932 }
00933
00934
00935 isc_result_t
00936 isc_lex_setsourcename(isc_lex_t *lex, const char *name) {
00937 inputsource *source;
00938 char *newname;
00939
00940 REQUIRE(VALID_LEX(lex));
00941 source = HEAD(lex->sources);
00942
00943 if (source == NULL)
00944 return(ISC_R_NOTFOUND);
00945 newname = isc_mem_strdup(lex->mctx, name);
00946 if (newname == NULL)
00947 return (ISC_R_NOMEMORY);
00948 isc_mem_free(lex->mctx, source->name);
00949 source->name = newname;
00950 return (ISC_R_SUCCESS);
00951 }
00952
00953 isc_boolean_t
00954 isc_lex_isfile(isc_lex_t *lex) {
00955 inputsource *source;
00956
00957 REQUIRE(VALID_LEX(lex));
00958
00959 source = HEAD(lex->sources);
00960
00961 if (source == NULL)
00962 return (ISC_FALSE);
00963
00964 return (source->is_file);
00965 }