📄 parser.c
字号:
* uint32 */isc_result_tcfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; cfg_obj_t *obj = NULL; UNUSED(type); CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER)); if (pctx->token.type != isc_tokentype_number) { cfg_parser_error(pctx, CFG_LOG_NEAR, "expected number"); return (ISC_R_UNEXPECTEDTOKEN); } CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj)); obj->value.uint32 = pctx->token.value.as_ulong; *ret = obj; cleanup: return (result);}voidcfg_print_cstr(cfg_printer_t *pctx, const char *s) { cfg_print_chars(pctx, s, strlen(s));}voidcfg_print_rawuint(cfg_printer_t *pctx, unsigned int u) { char buf[32]; snprintf(buf, sizeof(buf), "%u", u); cfg_print_cstr(pctx, buf);}voidcfg_print_uint32(cfg_printer_t *pctx, cfg_obj_t *obj) { cfg_print_rawuint(pctx, obj->value.uint32);}isc_boolean_tcfg_obj_isuint32(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_uint32));}isc_uint32_tcfg_obj_asuint32(cfg_obj_t *obj) { REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint32); return (obj->value.uint32);}cfg_type_t cfg_type_uint32 = { "integer", cfg_parse_uint32, cfg_print_uint32, cfg_doc_terminal, &cfg_rep_uint32, NULL};/* * uint64 */isc_boolean_tcfg_obj_isuint64(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_uint64));}isc_uint64_tcfg_obj_asuint64(cfg_obj_t *obj) { REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint64); return (obj->value.uint64);}voidcfg_print_uint64(cfg_printer_t *pctx, cfg_obj_t *obj) { char buf[32]; snprintf(buf, sizeof(buf), "%" ISC_PRINT_QUADFORMAT "u", obj->value.uint64); cfg_print_cstr(pctx, buf);}cfg_type_t cfg_type_uint64 = { "64_bit_integer", NULL, cfg_print_uint64, cfg_doc_terminal, &cfg_rep_uint64, NULL};/* * qstring (quoted string), ustring (unquoted string), astring * (any string) *//* Create a string object from a null-terminated C string. */static isc_result_tcreate_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type, cfg_obj_t **ret){ isc_result_t result; cfg_obj_t *obj = NULL; int len; CHECK(cfg_create_obj(pctx, type, &obj)); len = strlen(contents); obj->value.string.length = len; obj->value.string.base = isc_mem_get(pctx->mctx, len + 1); if (obj->value.string.base == 0) { isc_mem_put(pctx->mctx, obj, sizeof(*obj)); return (ISC_R_NOMEMORY); } memcpy(obj->value.string.base, contents, len); obj->value.string.base[len] = '\0'; *ret = obj; cleanup: return (result);}isc_result_tcfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; UNUSED(type); CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING)); if (pctx->token.type != isc_tokentype_qstring) { cfg_parser_error(pctx, CFG_LOG_NEAR, "expected quoted string"); return (ISC_R_UNEXPECTEDTOKEN); } return (create_string(pctx, TOKEN_STRING(pctx), &cfg_type_qstring, ret)); cleanup: return (result);}static isc_result_tparse_ustring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; UNUSED(type); CHECK(cfg_gettoken(pctx, 0)); if (pctx->token.type != isc_tokentype_string) { cfg_parser_error(pctx, CFG_LOG_NEAR, "expected unquoted string"); return (ISC_R_UNEXPECTEDTOKEN); } return (create_string(pctx, TOKEN_STRING(pctx), &cfg_type_ustring, ret)); cleanup: return (result);}isc_result_tcfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; UNUSED(type); CHECK(cfg_getstringtoken(pctx)); return (create_string(pctx, TOKEN_STRING(pctx), &cfg_type_qstring, ret)); cleanup: return (result);}isc_boolean_tcfg_is_enum(const char *s, const char *const *enums) { const char * const *p; for (p = enums; *p != NULL; p++) { if (strcasecmp(*p, s) == 0) return (ISC_TRUE); } return (ISC_FALSE);}static isc_result_tcheck_enum(cfg_parser_t *pctx, cfg_obj_t *obj, const char *const *enums) { const char *s = obj->value.string.base; if (cfg_is_enum(s, enums)) return (ISC_R_SUCCESS); cfg_parser_error(pctx, 0, "'%s' unexpected", s); return (ISC_R_UNEXPECTEDTOKEN);}isc_result_tcfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; cfg_obj_t *obj = NULL; CHECK(parse_ustring(pctx, NULL, &obj)); CHECK(check_enum(pctx, obj, type->of)); *ret = obj; return (ISC_R_SUCCESS); cleanup: CLEANUP_OBJ(obj); return (result);}voidcfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) { const char * const *p; cfg_print_chars(pctx, "( ", 2); for (p = type->of; *p != NULL; p++) { cfg_print_cstr(pctx, *p); if (p[1] != NULL) cfg_print_chars(pctx, " | ", 3); } cfg_print_chars(pctx, " )", 2);}voidcfg_print_ustring(cfg_printer_t *pctx, cfg_obj_t *obj) { cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);}static voidprint_qstring(cfg_printer_t *pctx, cfg_obj_t *obj) { cfg_print_chars(pctx, "\"", 1); cfg_print_ustring(pctx, obj); cfg_print_chars(pctx, "\"", 1);}static voidfree_string(cfg_parser_t *pctx, cfg_obj_t *obj) { isc_mem_put(pctx->mctx, obj->value.string.base, obj->value.string.length + 1);}isc_boolean_tcfg_obj_isstring(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_string));}char *cfg_obj_asstring(cfg_obj_t *obj) { REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_string); return (obj->value.string.base);}/* Quoted string only */cfg_type_t cfg_type_qstring = { "quoted_string", cfg_parse_qstring, print_qstring, cfg_doc_terminal, &cfg_rep_string, NULL};/* Unquoted string only */cfg_type_t cfg_type_ustring = { "string", parse_ustring, cfg_print_ustring, cfg_doc_terminal, &cfg_rep_string, NULL};/* Any string (quoted or unquoted); printed with quotes */cfg_type_t cfg_type_astring = { "string", cfg_parse_astring, print_qstring, cfg_doc_terminal, &cfg_rep_string, NULL};/* * Booleans */isc_boolean_tcfg_obj_isboolean(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_boolean));}isc_boolean_tcfg_obj_asboolean(cfg_obj_t *obj) { REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_boolean); return (obj->value.boolean);}static isc_result_tparse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){ isc_result_t result; isc_boolean_t value; cfg_obj_t *obj = NULL; UNUSED(type); result = cfg_gettoken(pctx, 0); if (result != ISC_R_SUCCESS) return (result); if (pctx->token.type != isc_tokentype_string) goto bad_boolean; if ((strcasecmp(TOKEN_STRING(pctx), "true") == 0) || (strcasecmp(TOKEN_STRING(pctx), "yes") == 0) || (strcmp(TOKEN_STRING(pctx), "1") == 0)) { value = ISC_TRUE; } else if ((strcasecmp(TOKEN_STRING(pctx), "false") == 0) || (strcasecmp(TOKEN_STRING(pctx), "no") == 0) || (strcmp(TOKEN_STRING(pctx), "0") == 0)) { value = ISC_FALSE; } else { goto bad_boolean; } CHECK(cfg_create_obj(pctx, &cfg_type_boolean, &obj)); obj->value.boolean = value; *ret = obj; return (result); bad_boolean: cfg_parser_error(pctx, CFG_LOG_NEAR, "boolean expected"); return (ISC_R_UNEXPECTEDTOKEN); cleanup: return (result);}static voidprint_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) { if (obj->value.boolean) cfg_print_chars(pctx, "yes", 3); else cfg_print_chars(pctx, "no", 2);}cfg_type_t cfg_type_boolean = { "boolean", parse_boolean, print_boolean, cfg_doc_terminal, &cfg_rep_boolean, NULL};/* * Lists. */isc_result_tcfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) { isc_result_t result; CHECK(cfg_create_obj(pctx, type, obj)); ISC_LIST_INIT((*obj)->value.list); cleanup: return (result);}static isc_result_tcreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) { cfg_listelt_t *elt; elt = isc_mem_get(pctx->mctx, sizeof(*elt)); if (elt == NULL) return (ISC_R_NOMEMORY); elt->obj = NULL; ISC_LINK_INIT(elt, link); *eltp = elt; return (ISC_R_SUCCESS);}static voidfree_list_elt(cfg_parser_t *pctx, cfg_listelt_t *elt) { cfg_obj_destroy(pctx, &elt->obj); isc_mem_put(pctx->mctx, elt, sizeof(*elt));}static voidfree_list(cfg_parser_t *pctx, cfg_obj_t *obj) { cfg_listelt_t *elt, *next; for (elt = ISC_LIST_HEAD(obj->value.list); elt != NULL; elt = next) { next = ISC_LIST_NEXT(elt, link); free_list_elt(pctx, elt); }}isc_result_tcfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype, cfg_listelt_t **ret){ isc_result_t result; cfg_listelt_t *elt = NULL; cfg_obj_t *value = NULL; CHECK(create_listelt(pctx, &elt)); result = cfg_parse_obj(pctx, elttype, &value); if (result != ISC_R_SUCCESS) goto cleanup; elt->obj = value; *ret = elt; return (ISC_R_SUCCESS); cleanup: isc_mem_put(pctx->mctx, elt, sizeof(*elt)); return (result);}/* * Parse a homogeneous list whose elements are of type 'elttype' * and where each element is terminated by a semicolon. */static isc_result_tparse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret){ cfg_obj_t *listobj = NULL; const cfg_type_t *listof = listtype->of; isc_result_t result; cfg_listelt_t *elt = NULL; CHECK(cfg_create_list(pctx, listtype, &listobj)); for (;;) { CHECK(cfg_peektoken(pctx, 0)); if (pctx->token.type == isc_tokentype_special && pctx->token.value.as_char == /*{*/ '}') break; CHECK(cfg_parse_listelt(pctx, listof, &elt)); CHECK(parse_semicolon(pctx)); ISC_LIST_APPEND(listobj->value.list, elt, link); elt = NULL; } *ret = listobj; return (ISC_R_SUCCESS); cleanup: if (elt != NULL) free_list_elt(pctx, elt); CLEANUP_OBJ(listobj); return (result);}static voidprint_list(cfg_printer_t *pctx, cfg_obj_t *obj) { cfg_list_t *list = &obj->value.list; cfg_listelt_t *elt; for (elt = ISC_LIST_HEAD(*list); elt != NULL; elt = ISC_LIST_NEXT(elt, link)) { print_indent(pctx); cfg_print_obj(pctx, elt->obj); cfg_print_chars(pctx, ";\n", 2); }}isc_result_tcfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){ isc_result_t result; CHECK(cfg_parse_special(pctx, '{')); CHECK(parse_list(pctx, type, ret)); CHECK(cfg_parse_special(pctx, '}')); cleanup: return (result);}voidcfg_print_bracketed_list(cfg_printer_t *pctx, cfg_obj_t *obj) { print_open(pctx); print_list(pctx, obj); print_close(pctx);}voidcfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_print_chars(pctx, "{ ", 2); cfg_doc_obj(pctx, type->of); cfg_print_chars(pctx, "; ... }", 7);}/* * Parse a homogeneous list whose elements are of type 'elttype' * and where elements are separated by space. The list ends * before the first semicolon. */isc_result_tcfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret){ cfg_obj_t *listobj = NULL; const cfg_type_t *listof = listtype->of; isc_result_t result; CHECK(cfg_create_list(pctx, listtype, &listobj)); for (;;) { cfg_listelt_t *elt = NULL; CHECK(cfg_peektoken(pctx, 0)); if (pctx->token.type == isc_tokentype_special && pctx->token.value.as_char == ';') break; CHECK(cfg_parse_listelt(pctx, listof, &elt)); ISC_LIST_APPEND(listobj->value.list, elt, link); } *ret = listobj; return (ISC_R_SUCCESS); cleanup: CLEANUP_OBJ(listobj); return (result);}voidcfg_print_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj) { cfg_list_t *list = &obj->value.list; cfg_listelt_t *elt; for (elt = ISC_LIST_HEAD(*list); elt != NULL; elt = ISC_LIST_NEXT(elt, link)) { cfg_print_obj(pctx, elt->obj); if (ISC_LIST_NEXT(elt, link) != NULL) cfg_print_chars(pctx, " ", 1); }}isc_boolean_tcfg_obj_islist(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_list));}cfg_listelt_t *cfg_list_first(cfg_obj_t *obj) { REQUIRE(obj == NULL || obj->type->rep == &cfg_rep_list); if (obj == NULL) return (NULL); return (ISC_LIST_HEAD(obj->value.list));}cfg_listelt_t *cfg_list_next(cfg_listelt_t *elt) { REQUIRE(elt != NULL); return (ISC_LIST_NEXT(elt, link));}cfg_obj_t *cfg_listelt_value(cfg_listelt_t *elt) { REQUIRE(elt != NULL); return (elt->obj);}/* * Maps. *//* * Parse a map body. That's something like * * "foo 1; bar { glub; }; zap true; zap false;" * * i.e., a sequence of option names followed by values and * terminated by semicolons. Used for the top level of * the named.conf syntax, as well as for the body of the * options, view, zone, and other statements. */isc_result_tcfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){ const cfg_clausedef_t * const *clausesets = type->of; isc_result_t result; const cfg_clausedef_t * const *clauseset; const cfg_clausedef_t *clause; cfg_obj_t *value = NULL; cfg_obj_t *obj = NULL; cfg_obj_t *eltobj = NULL; cfg_obj_t *includename = NULL; isc_symvalue_t symval; cfg_list_t *list = NULL; CHECK(create_map(pctx, type, &obj)); obj->value.map.clausesets = clausesets;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -