📄 lex.c
字号:
/* Token has not started yet. */ source->ignored = isc_buffer_consumedlength(source->pushback); c = isc_buffer_getuint8(source->pushback); } else { c = EOF; } if (c == '\n') source->line++; if (lex->comment_ok && !no_comments) { if (!escaped && c == ';' && ((lex->comments & ISC_LEXCOMMENT_DNSMASTERFILE) != 0)) { saved_state = state; state = lexstate_eatline; no_comments = ISC_TRUE; continue; } else if (c == '/' && (lex->comments & (ISC_LEXCOMMENT_C| ISC_LEXCOMMENT_CPLUSPLUS)) != 0) { saved_state = state; state = lexstate_maybecomment; no_comments = ISC_TRUE; continue; } else if (c == '#' && ((lex->comments & ISC_LEXCOMMENT_SHELL) != 0)) { saved_state = state; state = lexstate_eatline; no_comments = ISC_TRUE; continue; } } no_read: /* INSIST(c == EOF || (c >= 0 && c <= 255)); */ switch (state) { case lexstate_start: if (c == EOF) { lex->last_was_eol = ISC_FALSE; if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && lex->paren_count != 0) { lex->paren_count = 0; result = ISC_R_UNBALANCED; goto done; } if ((options & ISC_LEXOPT_EOF) == 0) { result = ISC_R_EOF; goto done; } tokenp->type = isc_tokentype_eof; done = ISC_TRUE; } else if (c == ' ' || c == '\t') { if (lex->last_was_eol && (options & ISC_LEXOPT_INITIALWS) != 0) { lex->last_was_eol = ISC_FALSE; tokenp->type = isc_tokentype_initialws; tokenp->value.as_char = c; done = ISC_TRUE; } } else if (c == '\n') { if ((options & ISC_LEXOPT_EOL) != 0) { tokenp->type = isc_tokentype_eol; done = ISC_TRUE; } lex->last_was_eol = ISC_TRUE; } else if (c == '\r') { if ((options & ISC_LEXOPT_EOL) != 0) state = lexstate_crlf; } else if (c == '"' && (options & ISC_LEXOPT_QSTRING) != 0) { lex->last_was_eol = ISC_FALSE; no_comments = ISC_TRUE; state = lexstate_qstring; } else if (lex->specials[c]) { lex->last_was_eol = ISC_FALSE; if ((c == '(' || c == ')') && (options & ISC_LEXOPT_DNSMULTILINE) != 0) { if (c == '(') { if (lex->paren_count == 0) options &= ~IWSEOL; lex->paren_count++; } else { if (lex->paren_count == 0) { result = ISC_R_UNBALANCED; goto done; } lex->paren_count--; if (lex->paren_count == 0) options = saved_options; } continue; } tokenp->type = isc_tokentype_special; tokenp->value.as_char = c; done = ISC_TRUE; } else if (isdigit((unsigned char)c) && (options & ISC_LEXOPT_NUMBER) != 0) { lex->last_was_eol = ISC_FALSE; state = lexstate_number; goto no_read; } else { lex->last_was_eol = ISC_FALSE; state = lexstate_string; goto no_read; } break; case lexstate_crlf: if (c != '\n') pushback(source, c); tokenp->type = isc_tokentype_eol; done = ISC_TRUE; lex->last_was_eol = ISC_TRUE; break; case lexstate_number: if (c == EOF || !isdigit((unsigned char)c)) { if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == EOF || lex->specials[c]) { int base; if ((options & ISC_LEXOPT_CNUMBER) != 0) base = 0; else base = 10; pushback(source, c); result = isc_parse_uint32(&as_ulong, lex->data, base); if (result == ISC_R_SUCCESS) { tokenp->type = isc_tokentype_number; tokenp->value.as_ulong = as_ulong; } else if (result == ISC_R_BADNUMBER) { isc_tokenvalue_t *v; tokenp->type = isc_tokentype_string; v = &(tokenp->value); v->as_textregion.base = lex->data; v->as_textregion.length = lex->max_token - remaining; } else goto done; done = ISC_TRUE; continue; } else if (!(options & ISC_LEXOPT_CNUMBER) || ((c != 'x' && c != 'X') || (curr != &lex->data[1]) || (lex->data[0] != '0'))) { /* Above test supports hex numbers */ state = lexstate_string; } } if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } INSIST(remaining > 0U); *curr++ = c; *curr = '\0'; remaining--; break; case lexstate_string: if ((!escaped && (c == ' ' || c == '\t' || lex->specials[c])) || c == '\r' || c == '\n' || c == EOF) { pushback(source, c); if (source->result != ISC_R_SUCCESS) { result = source->result; goto done; } tokenp->type = isc_tokentype_string; tokenp->value.as_textregion.base = lex->data; tokenp->value.as_textregion.length = lex->max_token - remaining; done = ISC_TRUE; continue; } if ((options & ISC_LEXOPT_ESCAPE) != 0) escaped = (!escaped && c == '\\') ? ISC_TRUE : ISC_FALSE; if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } INSIST(remaining > 0U); *curr++ = c; *curr = '\0'; remaining--; break; case lexstate_maybecomment: if (c == '*' && (lex->comments & ISC_LEXCOMMENT_C) != 0) { state = lexstate_ccomment; continue; } else if (c == '/' && (lex->comments & ISC_LEXCOMMENT_CPLUSPLUS) != 0) { state = lexstate_eatline; continue; } pushback(source, c); c = '/'; no_comments = ISC_FALSE; state = saved_state; goto no_read; case lexstate_ccomment: if (c == EOF) { result = ISC_R_UNEXPECTEDEND; goto done; } if (c == '*') state = lexstate_ccommentend; break; case lexstate_ccommentend: if (c == EOF) { result = ISC_R_UNEXPECTEDEND; goto done; } if (c == '/') { /* * C-style comments become a single space. * We do this to ensure that a comment will * act as a delimiter for strings and * numbers. */ c = ' '; no_comments = ISC_FALSE; state = saved_state; goto no_read; } else if (c != '*') state = lexstate_ccomment; break; case lexstate_eatline: if (c == EOF) { result = ISC_R_UNEXPECTEDEND; goto done; } if (c == '\n') { no_comments = ISC_FALSE; state = saved_state; goto no_read; } break; case lexstate_qstring: if (c == EOF) { result = ISC_R_UNEXPECTEDEND; goto done; } if (c == '"') { if (escaped) { escaped = ISC_FALSE; /* * Overwrite the preceding backslash. */ INSIST(prev != NULL); *prev = '"'; } else { tokenp->type = isc_tokentype_qstring; tokenp->value.as_textregion.base = lex->data; tokenp->value.as_textregion.length = lex->max_token - remaining; no_comments = ISC_FALSE; done = ISC_TRUE; } } else { if (c == '\n' && !escaped && (options & ISC_LEXOPT_QSTRINGMULTILINE) == 0) { pushback(source, c); result = ISC_R_UNBALANCEDQUOTES; goto done; } if (c == '\\' && !escaped) escaped = ISC_TRUE; else escaped = ISC_FALSE; if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } INSIST(remaining > 0U); prev = curr; *curr++ = c; *curr = '\0'; remaining--; } break; default: FATAL_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX, ISC_MSG_UNEXPECTEDSTATE, "Unexpected state %d"), state); /* Does not return. */ } } while (!done); result = ISC_R_SUCCESS; done:#ifdef HAVE_FLOCKFILE if (source->is_file) funlockfile(source->input);#endif return (result);}isc_result_tisc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token, isc_tokentype_t expect, isc_boolean_t eol){ unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; isc_result_t result; if (expect == isc_tokentype_qstring) options |= ISC_LEXOPT_QSTRING; else if (expect == isc_tokentype_number) options |= ISC_LEXOPT_NUMBER; result = isc_lex_gettoken(lex, options, token); if (result == ISC_R_RANGE) isc_lex_ungettoken(lex, token); if (result != ISC_R_SUCCESS) return (result); if (eol && ((token->type == isc_tokentype_eol) || (token->type == isc_tokentype_eof))) return (ISC_R_SUCCESS); if (token->type == isc_tokentype_string && expect == isc_tokentype_qstring) return (ISC_R_SUCCESS); if (token->type != expect) { isc_lex_ungettoken(lex, token); if (token->type == isc_tokentype_eol || token->type == isc_tokentype_eof) return (ISC_R_UNEXPECTEDEND); if (expect == isc_tokentype_number) return (ISC_R_BADNUMBER); return (ISC_R_UNEXPECTEDTOKEN); } return (ISC_R_SUCCESS);}voidisc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) { inputsource *source; /* * Unget the current token. */ REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); REQUIRE(source != NULL); REQUIRE(tokenp != NULL); REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 || tokenp->type == isc_tokentype_eof); UNUSED(tokenp); isc_buffer_first(source->pushback); lex->paren_count = lex->saved_paren_count; source->line = source->saved_line; source->at_eof = ISC_FALSE;}voidisc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r){ inputsource *source; REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); REQUIRE(source != NULL); REQUIRE(tokenp != NULL); REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 || tokenp->type == isc_tokentype_eof); UNUSED(tokenp); INSIST(source->ignored <= isc_buffer_consumedlength(source->pushback)); r->base = (unsigned char *)isc_buffer_base(source->pushback) + source->ignored; r->length = isc_buffer_consumedlength(source->pushback) - source->ignored;}char *isc_lex_getsourcename(isc_lex_t *lex) { inputsource *source; REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); if (source == NULL) return (NULL); return (source->name);}unsigned longisc_lex_getsourceline(isc_lex_t *lex) { inputsource *source; REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); if (source == NULL) return (0); return (source->line);}isc_result_tisc_lex_setsourcename(isc_lex_t *lex, const char *name) { inputsource *source; char *newname; REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); if (source == NULL) return(ISC_R_NOTFOUND); newname = isc_mem_strdup(lex->mctx, name); if (newname == NULL) return (ISC_R_NOMEMORY); isc_mem_free(lex->mctx, source->name); source->name = newname; return (ISC_R_SUCCESS);}isc_boolean_tisc_lex_isfile(isc_lex_t *lex) { inputsource *source; REQUIRE(VALID_LEX(lex)); source = HEAD(lex->sources); if (source == NULL) return (ISC_FALSE); return (source->is_file);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -