📄 parser.c
字号:
CHECK(parse2(pctx, type, ret)); cleanup: return (result);}isc_result_tcfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const cfg_type_t *type, cfg_obj_t **ret){ isc_result_t result; REQUIRE(buffer != NULL); CHECK(isc_lex_openbuffer(pctx->lexer, buffer)); CHECK(parse2(pctx, type, ret)); cleanup: return (result);}voidcfg_parser_destroy(cfg_parser_t **pctxp) { cfg_parser_t *pctx = *pctxp; isc_lex_destroy(&pctx->lexer); /* * Cleaning up open_files does not * close the files; that was already done * by closing the lexer. */ CLEANUP_OBJ(pctx->open_files); CLEANUP_OBJ(pctx->closed_files); isc_mem_put(pctx->mctx, pctx, sizeof(*pctx)); *pctxp = NULL;}/* * void */static isc_result_tparse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { UNUSED(type); return (create_cfgobj(pctx, &cfg_type_void, ret));}static voidprint_void(cfg_printer_t *pctx, cfg_obj_t *obj) { UNUSED(pctx); UNUSED(obj);}isc_boolean_tcfg_obj_isvoid(cfg_obj_t *obj) { REQUIRE(obj != NULL); return (ISC_TF(obj->type->rep == &cfg_rep_void));}static cfg_type_t cfg_type_void = { "void", parse_void, print_void, &cfg_rep_void, NULL };/* * uint32 */static isc_result_tparse_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) { parser_error(pctx, LOG_NEAR, "expected number"); return (ISC_R_UNEXPECTEDTOKEN); } CHECK(create_cfgobj(pctx, &cfg_type_uint32, &obj)); obj->value.uint32 = pctx->token.value.as_ulong; *ret = obj; cleanup: return (result);}static voidprint_cstr(cfg_printer_t *pctx, const char *s) { print(pctx, s, strlen(s));}static voidprint_uint(cfg_printer_t *pctx, unsigned int u) { char buf[32]; snprintf(buf, sizeof(buf), "%u", u); print_cstr(pctx, buf);}static voidprint_uint32(cfg_printer_t *pctx, cfg_obj_t *obj) { print_uint(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);}static cfg_type_t cfg_type_uint32 = { "integer", parse_uint32, print_uint32, &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);}static isc_result_tparse_unitstring(char *str, isc_resourcevalue_t *valuep) { char *endp; unsigned int len; isc_uint64_t value; isc_uint64_t unit; value = isc_string_touint64(str, &endp, 10); if (*endp == 0) { *valuep = value; return (ISC_R_SUCCESS); } len = strlen(str); if (len < 2 || endp[1] != '\0') return (ISC_R_FAILURE); switch (str[len - 1]) { case 'k': case 'K': unit = 1024; break; case 'm': case 'M': unit = 1024 * 1024; break; case 'g': case 'G': unit = 1024 * 1024 * 1024; break; default: return (ISC_R_FAILURE); } if (value > ISC_UINT64_MAX / unit) return (ISC_R_FAILURE); *valuep = value * unit; return (ISC_R_SUCCESS);}static voidprint_uint64(cfg_printer_t *pctx, cfg_obj_t *obj) { char buf[32]; sprintf(buf, "%" ISC_PRINT_QUADFORMAT "u", obj->value.uint64); print_cstr(pctx, buf);}static cfg_type_t cfg_type_uint64 = { "64_bit_integer", NULL, print_uint64, &cfg_rep_uint64, NULL };static isc_result_tparse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; cfg_obj_t *obj = NULL; isc_uint64_t val; UNUSED(type); CHECK(cfg_gettoken(pctx, 0)); if (pctx->token.type != isc_tokentype_string) { result = ISC_R_UNEXPECTEDTOKEN; goto cleanup; } CHECK(parse_unitstring(pctx->token.value.as_pointer, &val)); CHECK(create_cfgobj(pctx, &cfg_type_uint64, &obj)); obj->value.uint64 = val; *ret = obj; return (ISC_R_SUCCESS); cleanup: parser_error(pctx, LOG_NEAR, "expected integer and optional unit"); return (result);}/* * A size value (number + optional unit). */static cfg_type_t cfg_type_sizeval = { "sizeval", parse_sizeval, print_uint64, &cfg_rep_uint64, NULL };/* * A size, "unlimited", or "default". */static isc_result_tparse_size(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { return (parse_enum_or_other(pctx, type, &cfg_type_sizeval, ret));}static const char *size_enums[] = { "unlimited", "default", NULL };static cfg_type_t cfg_type_size = { "size", parse_size, print_ustring, &cfg_rep_string, size_enums};/* * A size or "unlimited", but not "default". */static const char *sizenodefault_enums[] = { "unlimited", NULL };static cfg_type_t cfg_type_sizenodefault = { "size_no_default", parse_size, print_ustring, &cfg_rep_string, sizenodefault_enums};/* * optional_keyvalue */static isc_result_tparse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, isc_boolean_t optional, cfg_obj_t **ret){ isc_result_t result; cfg_obj_t *obj = NULL; const keyword_type_t *kw = type->of; CHECK(cfg_peektoken(pctx, 0)); if (pctx->token.type == isc_tokentype_string && strcasecmp(pctx->token.value.as_pointer, kw->name) == 0) { CHECK(cfg_gettoken(pctx, 0)); CHECK(kw->type->parse(pctx, kw->type, &obj)); obj->type = type; /* XXX kludge */ } else { if (optional) { CHECK(parse_void(pctx, NULL, &obj)); } else { parser_error(pctx, LOG_NEAR, "expected '%s'", kw->name); result = ISC_R_UNEXPECTEDTOKEN; goto cleanup; } } *ret = obj; cleanup: return (result);}static isc_result_tparse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { return (parse_maybe_optional_keyvalue(pctx, type, ISC_FALSE, ret));}static isc_result_tparse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { return (parse_maybe_optional_keyvalue(pctx, type, ISC_TRUE, ret));}static voidprint_keyvalue(cfg_printer_t *pctx, cfg_obj_t *obj) { const keyword_type_t *kw = obj->type->of; print_cstr(pctx, kw->name); print(pctx, " ", 1); kw->type->print(pctx, obj);}/* * qstring, ustring, astring *//* 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(create_cfgobj(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);}static isc_result_tparse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; UNUSED(type); CHECK(cfg_gettoken(pctx, QSTRING)); if (pctx->token.type != isc_tokentype_qstring) { parser_error(pctx, LOG_NEAR, "expected quoted string"); return (ISC_R_UNEXPECTEDTOKEN); } return (create_string(pctx, pctx->token.value.as_pointer, &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) { parser_error(pctx, LOG_NEAR, "expected unquoted string"); return (ISC_R_UNEXPECTEDTOKEN); } return (create_string(pctx, pctx->token.value.as_pointer, &cfg_type_ustring, ret)); cleanup: return (result);}static isc_result_tparse_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, pctx->token.value.as_pointer, &cfg_type_qstring, ret)); cleanup: return (result);}static isc_boolean_tis_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 (is_enum(s, enums)) return (ISC_R_SUCCESS); parser_error(pctx, 0, "'%s' unexpected", s); return (ISC_R_UNEXPECTEDTOKEN);}static isc_result_tparse_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);}static isc_result_tparse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype, const cfg_type_t *othertype, cfg_obj_t **ret){ isc_result_t result; CHECK(cfg_peektoken(pctx, 0)); if (pctx->token.type == isc_tokentype_string && is_enum(pctx->token.value.as_pointer, enumtype->of)) { CHECK(parse_enum(pctx, enumtype, ret)); } else { CHECK(parse(pctx, othertype, ret)); } cleanup: return (result);}/* * Print a string object. */static voidprint_ustring(cfg_printer_t *pctx, cfg_obj_t *obj) { print(pctx, obj->value.string.base, obj->value.string.length);}static voidprint_qstring(cfg_printer_t *pctx, cfg_obj_t *obj) { print(pctx, "\"", 1); print_ustring(pctx, obj); print(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);}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);}/* Quoted string only */static cfg_type_t cfg_type_qstring = { "quoted_string", parse_qstring, print_qstring, &cfg_rep_string, NULL };/* Unquoted string only */static cfg_type_t cfg_type_ustring = { "string", parse_ustring, print_ustring, &cfg_rep_string, NULL };/* Any string (quoted or unquoted); printed with quotes */static cfg_type_t cfg_type_astring = { "string", parse_astring, print_qstring, &cfg_rep_string, NULL };/* * 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(pctx->token.value.as_pointer, "true") == 0) || (strcasecmp(pctx->token.value.as_pointer, "yes") == 0) || (strcmp(pctx->token.value.as_pointer, "1") == 0)) { value = ISC_TRUE; } else if ((strcasecmp(pctx->token.value.as_pointer, "false") == 0) || (strcasecmp(pctx->token.value.as_pointer, "no") == 0) || (strcmp(pctx->token.value.as_pointer, "0") == 0)) { value = ISC_FALSE; } else { goto bad_boolean; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -