parser.c revision ad1317338af79edad878c9c3e4361798503310ba
e1836d1fe413cc14430ce89508e79c4c01df830bTinderbox User * Copyright (C) 2000-2017 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉/* Shorthand */
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉#define MAP_SYM 1 /* Unique type for isc_symtab */
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉/* Check a return value. */
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 if (result != ISC_R_SUCCESS) goto cleanup; \
7f1785d0ded8897082abacec5219b27feac755afFrancis Dupont/* Clean up a configuration object if non-NULL. */
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 * Forward declarations of static functions.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntparse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntprint_list(cfg_printer_t *pctx, const cfg_obj_t *obj);
a0f91e910bd9af006a65e555ec4082864ca1eb8dMark Andrewscreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
a0f91e910bd9af006a65e555ec4082864ca1eb8dMark Andrewscreate_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
a70fc47e9dc165175e77f091076559748858a488Mark Andrewsfree_string(cfg_parser_t *pctx, cfg_obj_t *obj);
a70fc47e9dc165175e77f091076559748858a488Mark Andrewscreate_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
a70fc47e9dc165175e77f091076559748858a488Mark Andrewsparse_symtab_elt(cfg_parser_t *pctx, const char *name,
a70fc47e9dc165175e77f091076559748858a488Mark Andrewsparser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
a70fc47e9dc165175e77f091076559748858a488Mark Andrews unsigned int flags, const char *format, va_list args);
a70fc47e9dc165175e77f091076559748858a488Mark Andrews * Data representations. These correspond to members of the
a70fc47e9dc165175e77f091076559748858a488Mark Andrews * "value" union in struct cfg_obj (except "void", which does
a70fc47e9dc165175e77f091076559748858a488Mark Andrews * not need a union member).
a70fc47e9dc165175e77f091076559748858a488Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_uint32 = { "uint32", free_noop };
a70fc47e9dc165175e77f091076559748858a488Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_uint64 = { "uint64", free_noop };
a70fc47e9dc165175e77f091076559748858a488Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_string = { "string", free_string };
a70fc47e9dc165175e77f091076559748858a488Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_boolean = { "boolean", free_noop };
a70fc47e9dc165175e77f091076559748858a488Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_map = { "map", free_map };
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_list = { "list", free_list };
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_netprefix =
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_void = { "void", free_noop };
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_fixedpoint =
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉LIBISCCFG_EXTERNAL_DATA cfg_rep_t cfg_rep_percentage =
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Configuration type definitions.
a0f91e910bd9af006a65e555ec4082864ca1eb8dMark Andrews * An implicit list. These are formed by clauses that occur multiple times.
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉static cfg_type_t cfg_type_implicitlist = {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt "implicitlist", NULL, print_list, NULL, &cfg_rep_list, NULL };
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉/* Functions. */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_obj(cfg_printer_t *pctx, const cfg_obj_t *obj) {
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉cfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 if ((pctx->flags & CFG_PRINTER_ONELINE) != 0)
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt while (indent > 0) {
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 if ((pctx->flags & CFG_PRINTER_ONELINE) == 0) {
a0f91e910bd9af006a65e555ec4082864ca1eb8dMark Andrewscfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
859cfb24bfd7bd7754bb1d9ca68bce861a4b0a40Mark Andrews void (*f)(void *closure, const char *text, int textlen),
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_printx(const cfg_obj_t *obj, unsigned int flags,
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 void (*f)(void *closure, const char *text, int textlen),
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 const cfg_tuplefielddef_t *fields = type->of;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 unsigned int nfields = 0;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 obj->value.tuple = isc_mem_get(pctx->mctx,
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 for (f = fields, i = 0; f->name != NULL; f++, i++)
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj, sizeof(*obj));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntcfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
94315060c2b0d9deafabe72d6a0482405fd9d377Evan Hunt unsigned int i;
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews for (f = fields, i = 0; f->name != NULL; f++, i++)
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrews CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[i]));
8e50c697839c12d55bca0202ce09bd81f069f909Tinderbox Usercfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
8e50c697839c12d55bca0202ce09bd81f069f909Tinderbox User unsigned int i;
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 for (f = fields, i = 0; f->name != NULL; f++, i++) {
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 const cfg_obj_t *fieldobj = obj->value.tuple[i];
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 if (need_space && fieldobj->type->rep != &cfg_rep_void)
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 need_space = ISC_TF(f->type->print != cfg_print_void);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 unsigned int i;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 const cfg_tuplefielddef_t *fields = obj->type->of;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 unsigned int nfields = 0;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 for (f = fields, i = 0; f->name != NULL; f++, i++) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj->value.tuple,
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 return (ISC_TF(obj->type->rep == &cfg_rep_tuple));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_tuple_get(const cfg_obj_t *tupleobj, const char* name) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 unsigned int i;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 REQUIRE(tupleobj != NULL && tupleobj->type->rep == &cfg_rep_tuple);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 for (f = fields, i = 0; f->name != NULL; f++, i++) {
ce67023ae3ad39a77da5361d0187ab6f3f0219cbMark Andrewscfg_parse_special(cfg_parser_t *pctx, int special) {
35c014cb1d151983c455ad1ac99093591cbda97aMark Andrews if (pctx->token.type == isc_tokentype_special &&
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt cfg_parser_error(pctx, CFG_LOG_NEAR, "'%c' expected", special);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * Parse a required semicolon. If it is not there, log
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * an error and increment the error count but continue
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * parsing. Since the next token is pushed back,
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * care must be taken to make sure it is eventually
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * consumed or an infinite loop may result.
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 cfg_parser_error(pctx, CFG_LOG_BEFORE, "missing ';'");
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 * Parse EOF, logging and returning an error if not there.
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 if (pctx->token.type == isc_tokentype_eof)
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 cfg_parser_error(pctx, CFG_LOG_NEAR, "syntax error");
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉/* A list of files, used internally for pctx->files. */
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 "filelist", NULL, print_list, NULL, &cfg_rep_list,
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 result = isc_refcount_init(&pctx->references, 1);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_mem_putanddetach(&pctx->mctx, pctx, sizeof(*pctx));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 pctx->token.type = isc_tokentype_unknown;
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 CHECK(isc_lex_create(pctx->mctx, 1024, &pctx->lexer));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_lex_setspecials(pctx->lexer, specials);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_lex_setcomments(pctx->lexer, (ISC_LEXCOMMENT_C |
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 isc_mem_putanddetach(&pctx->mctx, pctx, sizeof(*pctx));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉parser_openfile(cfg_parser_t *pctx, const char *filename) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 result = isc_lex_openfile(pctx->lexer, filename);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 cfg_parser_error(pctx, 0, "open: %s: %s",
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 CHECK(create_string(pctx, filename, &cfg_type_qstring, &stringobj));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_parser_setcallback(cfg_parser_t *pctx,
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * Parse a configuration using a pctx where a lexer has already
62ec9fd1681ffae7d6b0d54618599ecf650e3100Mark Andrews * been set up with a source.
26833735d3d95e731a1cfb2a9b12c9bc10ba208aEvan Huntparse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
26833735d3d95e731a1cfb2a9b12c9bc10ba208aEvan Hunt /* Errors have been logged. */
26833735d3d95e731a1cfb2a9b12c9bc10ba208aEvan Hunt /* Parsing failed but no errors have been logged. */
7204d08a319cf590ae4280b8cc20999320398574Mark Andrewscfg_parse_file(cfg_parser_t *pctx, const char *filename,
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews /* Clean up the opened file */
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews elt = ISC_LIST_TAIL(pctx->open_files->value.list);
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 ISC_LIST_UNLINK(pctx->open_files->value.list, elt, link);
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 ISC_LIST_APPEND(pctx->closed_files->value.list, elt, link);
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
26833735d3d95e731a1cfb2a9b12c9bc10ba208aEvan Hunt return (cfg_parse_buffer3(pctx, buffer, NULL, 0, type, ret));
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉cfg_parse_buffer2(cfg_parser_t *pctx, isc_buffer_t *buffer,
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 const char *file, const cfg_type_t *type,
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt return (cfg_parse_buffer3(pctx, buffer, file, 0, type, ret));
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_parse_buffer3(cfg_parser_t *pctx, isc_buffer_t *buffer,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt unsigned int refs;
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Cleaning up open_files does not
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * close the files; that was already done
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * by closing the lexer.
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt isc_mem_putanddetach(&pctx->mctx, pctx, sizeof(*pctx));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt return (cfg_create_obj(pctx, &cfg_type_void, ret));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_void = {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * percentage
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_parse_percentage(cfg_parser_t *pctx, const cfg_type_t *type,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "expected percentage");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt percent = isc_string_touint64(TOKEN_STRING(pctx), &endp, 10);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "expected percentage");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_percentage(cfg_printer_t *pctx, const cfg_obj_t *obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt n = snprintf(buf, sizeof(buf), "%u%%", obj->value.uint32);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_percentage);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_percentage = {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "percentage", cfg_parse_percentage, cfg_print_percentage,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt return (ISC_TF(obj->type->rep == &cfg_rep_percentage));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Fixed point
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt const char *p;
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "expected fixed point number");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "expected fixed point number");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_fixedpoint, &obj));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10) * 10;
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_fixedpoint);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_fixedpoint = {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "fixedpoint", cfg_parse_fixedpoint, cfg_print_fixedpoint,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt return (ISC_TF(obj->type->rep == &cfg_rep_fixedpoint));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt cfg_parser_error(pctx, CFG_LOG_NEAR, "expected number");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_cstr(cfg_printer_t *pctx, const char *s) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_rawuint(cfg_printer_t *pctx, unsigned int u) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_uint32(cfg_printer_t *pctx, const cfg_obj_t *obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt return (ISC_TF(obj->type->rep == &cfg_rep_uint32));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint32);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_uint32 = {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "integer", cfg_parse_uint32, cfg_print_uint32, cfg_doc_terminal,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt return (ISC_TF(obj->type->rep == &cfg_rep_uint64));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint64);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_print_uint64(cfg_printer_t *pctx, const cfg_obj_t *obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt snprintf(buf, sizeof(buf), "%" ISC_PRINT_QUADFORMAT "u",
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_uint64 = {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "64_bit_integer", NULL, cfg_print_uint64, cfg_doc_terminal,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * qstring (quoted string), ustring (unquoted string), astring
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * (any string)
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt/* Create a string object from a null-terminated C string. */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcreate_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt obj->value.string.base = isc_mem_get(pctx->mctx, len + 1);
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj, sizeof(*obj));
7c60401dbd4dce617dffc685c269fca224c589adTatuya JINMEI 神明達哉 memmove(obj->value.string.base, contents, len);
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrewscfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews if (pctx->token.type != isc_tokentype_qstring) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews cfg_parser_error(pctx, CFG_LOG_NEAR, "expected quoted string");
e5d447be8c18eca7b858665323b07907019c0b96Mark Andrewsparse_ustring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 if (pctx->token.type != isc_tokentype_string) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 cfg_parser_error(pctx, CFG_LOG_NEAR, "expected unquoted string");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type,
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackbcfg_parse_sstring(cfg_parser_t *pctx, const cfg_type_t *type,
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 CHECK(cfg_gettoken(pctx, ISC_LEXOPT_BTEXT));
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackb "expected bracketed text");
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackbstatic void
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewsprint_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * We need to print "{" instead of running print_open()
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * in order to preserve the exact original formatting
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * of the bracketed text. But we increment the indent value
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * so that print_close() will leave us back in our original
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉 cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews cfg_print_cstr(pctx, "{ <unspecified-text> }");
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewscfg_is_enum(const char *s, const char *const *enums) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews const char * const *p;
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews if (strcasecmp(*p, s) == 0)
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewscheck_enum(cfg_parser_t *pctx, cfg_obj_t *obj, const char *const *enums) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews cfg_parser_error(pctx, 0, "'%s' unexpected", s);
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewscfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt const char * const *p;
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrewscfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewsprint_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntprint_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews while (len-- > 0)
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewsfree_string(cfg_parser_t *pctx, cfg_obj_t *obj) {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews isc_mem_put(pctx->mctx, obj->value.string.base,
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews return (ISC_TF(obj->type->rep == &cfg_rep_string));
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_string);
80fa3ef8517ff046a72c4cb1e785f30c9ef9ee75Mark Andrews/* Quoted string only */
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_qstring = {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt "quoted_string", cfg_parse_qstring, print_qstring, cfg_doc_terminal,
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews/* Unquoted string only */
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_ustring = {
80fa3ef8517ff046a72c4cb1e785f30c9ef9ee75Mark Andrews "string", parse_ustring, cfg_print_ustring, cfg_doc_terminal,
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews/* Any string (quoted or unquoted); printed with quotes */
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_astring = {
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews "string", cfg_parse_astring, print_qstring, cfg_doc_terminal,
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews * Any string (quoted or unquoted); printed with quotes.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * If CFG_PRINTER_XKEY is set when printing the string will be '?' out.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sstring = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "string", cfg_parse_sstring, print_sstring, cfg_doc_terminal,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * Text enclosed in brackets. Used to pass a block of configuration
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * text to dynamic library or external application. Checked for
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * bracket balance, but not otherwise parsed.
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bracketed_text = {
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews "bracketed_text", parse_btext, print_btext, doc_btext,
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackb * Booleans
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews return (ISC_TF(obj->type->rep == &cfg_rep_boolean));
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrews REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_boolean);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews (strcasecmp(TOKEN_STRING(pctx), "yes") == 0) ||
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews } else if ((strcasecmp(TOKEN_STRING(pctx), "false") == 0) ||
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_boolean, &obj));
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews cfg_parser_error(pctx, CFG_LOG_NEAR, "boolean expected");
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewscfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_boolean = {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews "boolean", cfg_parse_boolean, cfg_print_boolean, cfg_doc_terminal,
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewscfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewscreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewsfree_listelt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
40a7e85f3ee3bd66a8f87bf8af674e1e48b05396Evan Hunt * Parse a homogeneous list whose elements are of type 'elttype'
08f01297320b7ad55d0abff0aca9a577196079e2Mukund Sivaraman * and where each element is terminated by a semicolon.
08f01297320b7ad55d0abff0aca9a577196079e2Mukund Sivaramanparse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
a70fc47e9dc165175e77f091076559748858a488Mark Andrews CHECK(cfg_create_list(pctx, listtype, &listobj));
a70fc47e9dc165175e77f091076559748858a488Mark Andrews if (pctx->token.type == isc_tokentype_special &&
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews ISC_LIST_APPEND(listobj->value.list, elt, link);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntprint_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackbcfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type,
bb5d14d7243d71e03d262ff175b355b52873e195Evan Huntcfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
d9059b0c38bd630c367d81424d72b1308cd74b04Tatuya JINMEI 神明達哉cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews * Parse a homogeneous list whose elements are of type 'elttype'
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews * and where elements are separated by space. The list ends
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 * before the first semicolon.
bb5d14d7243d71e03d262ff175b355b52873e195Evan Huntcfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype,
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews return (ISC_TF(obj->type->rep == &cfg_rep_list));
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews REQUIRE(obj == NULL || obj->type->rep == &cfg_rep_list);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * Return the length of a list object. If obj is NULL or is not
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * a list, return 0.
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt unsigned int count = 0;
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt return (0U);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * Parse a map body. That's something like
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * "foo 1; bar { glub; }; zap true; zap false;"
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * i.e., a sequence of option names followed by values and
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * terminated by semicolons. Used for the top level of
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * the named.conf syntax, as well as for the body of the
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * options, view, zone, and other statements.
7204d08a319cf590ae4280b8cc20999320398574Mark Andrewscfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews const cfg_clausedef_t * const *clausesets = type->of;
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * Parse the option name and see if it is known.
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * We accept "include" statements wherever a map body
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt * clause can occur.
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt if (strcasecmp(TOKEN_STRING(pctx), "include") == 0) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Turn the file name into a temporary configuration
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews * object just so that it is not overwritten by the
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * semicolon token.
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_parse_obj(pctx, &cfg_type_qstring, &includename));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt for (clauseset = clausesets; *clauseset != NULL; clauseset++) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt cfg_parser_error(pctx, CFG_LOG_NOPREP, "unknown option");
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Try to recover by parsing this option as an unknown
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * option and discarding it.
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt CHECK(cfg_parse_obj(pctx, &cfg_type_unsupported, &eltobj));
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt /* Clause is known. */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt /* Issue warnings if appropriate */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews cfg_parser_warning(pctx, 0, "option '%s' is obsolete",
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt cfg_parser_warning(pctx, 0, "option '%s' was not "
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "enabled at compile time "
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews if ((clause->flags & CFG_CLAUSEFLAG_NOTCONFIGURED) != 0) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt cfg_parser_warning(pctx, 0, "option '%s' was not "
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt "enabled at compile time",
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * set here - we need to log the *lack* of such an option,
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews * not its presence.
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews /* See if the clause already has a value; if not create one. */
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews result = isc_symtab_lookup(obj->value.map.symtab,
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews /* Multivalued clause */
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews "isc_symtab_define(%s) "
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews CHECK(cfg_parse_listelt(pctx, clause->type, &elt));
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews ISC_LIST_APPEND(listobj->value.list, elt, link);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews /* Single-valued clause */
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews cfg_parser_error(pctx, CFG_LOG_NEAR, "'%s' redefined",
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews "isc_symtab_define() failed");
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉parse_symtab_elt(cfg_parser_t *pctx, const char *name,
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt CHECK(pctx->callback(name, obj, pctx->callbackarg));
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackb * Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }"
8907d8fa04fdaa65baf0bc6b01230b2ebde93106Mark Andrewscfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * Subroutine for cfg_parse_named_map() and cfg_parse_addressed_map().
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrewsparse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype,
7781f25078c491a9650dec555bdc86cb0ed49861Tatuya JINMEI 神明達哉 CHECK(cfg_parse_obj(pctx, nametype, &idobj));
7781f25078c491a9650dec555bdc86cb0ed49861Tatuya JINMEI 神明達哉 CHECK(cfg_parse_map(pctx, type, &mapobj));
b748b5e2c2fa40f758e3b35ad4f1fde99ab5e11fEvan Hunt * Parse a map identified by a string name. E.g., "name { foo 1; }".
b748b5e2c2fa40f758e3b35ad4f1fde99ab5e11fEvan Hunt * Used for the "key" and "channel" statements.
1d3c89483c781f0c3f8db77d3a00f9a64cdd335dMark Andrewscfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt return (parse_any_named_map(pctx, &cfg_type_astring, type, ret));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * Parse a map identified by a network address.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt * Used to be used for the "server" statement.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntcfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
b748b5e2c2fa40f758e3b35ad4f1fde99ab5e11fEvan Hunt return (parse_any_named_map(pctx, &cfg_type_netaddr, type, ret));
b748b5e2c2fa40f758e3b35ad4f1fde99ab5e11fEvan Hunt * Parse a map identified by a network prefix.
b748b5e2c2fa40f758e3b35ad4f1fde99ab5e11fEvan Hunt * Used for the "server" statement.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntcfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews return (parse_any_named_map(pctx, &cfg_type_netprefix, type, ret));
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntprint_symval(cfg_printer_t *pctx, const char *name, cfg_obj_t *obj) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 if ((pctx->flags & CFG_PRINTER_ONELINE) == 0)
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews result = isc_symtab_lookup(obj->value.map.symtab,
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews /* Multivalued. */
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 /* Single-valued. */
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt ; /* do nothing */
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt const char *text;
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 { CFG_CLAUSEFLAG_NOTIMP, "not implemented" },
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 { CFG_CLAUSEFLAG_NYI, "not yet implemented" },
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 { CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" },
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews { CFG_CLAUSEFLAG_NOTCONFIGURED, "not configured" },
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews { CFG_CLAUSEFLAG_MULTI, "may occur multiple times" },
8ac908b38a2fd9b780ae3a27ff26932a17823ae0Mark Andrews { CFG_CLAUSEFLAG_EXPERIMENTAL, "experimental" },
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackbstatic void
aecadaf3b1bbbe0bd58f703989baf38eedd0ffcackbprint_clause_flags(cfg_printer_t *pctx, unsigned int flags) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt for (clauseset = type->of; *clauseset != NULL; clauseset++) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt } else if (type->parse == cfg_parse_addressed_map) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt } else if (type->parse == cfg_parse_netprefix_map) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt for (clauseset = type->of; *clauseset != NULL; clauseset++) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt result = isc_symtab_lookup(map->symtab, name, MAP_SYM, &val);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews/* Parse an arbitrary token, storing its raw text representation. */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntparse_token(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_token, &obj));
bf216589c1a81e4431653a145b252b6ce367d7cdMark Andrews isc_lex_getlasttokentext(pctx->lexer, &pctx->token, &r);
aeff3f0541beed6c7e384737bc83b46ea5e66a84Evan Hunt obj->value.string.base = isc_mem_get(pctx->mctx, r.length + 1);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt memmove(obj->value.string.base, r.base, r.length);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_token = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "token", parse_token, cfg_print_ustring, cfg_doc_terminal,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * An unsupported option. This is just a list of tokens with balanced braces
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * ending in a semicolon.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntparse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
08f01297320b7ad55d0abff0aca9a577196079e2Mukund Sivaraman if (pctx->token.type == isc_tokentype_special) {
aeff3f0541beed6c7e384737bc83b46ea5e66a84Evan Hunt if (pctx->token.type == isc_tokentype_eof || braces < 0) {
a70fc47e9dc165175e77f091076559748858a488Mark Andrews cfg_parser_error(pctx, CFG_LOG_NEAR, "unexpected token");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_parse_listelt(pctx, &cfg_type_token, &elt));
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_unsupported = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "unsupported", parse_unsupported, cfg_print_spacelist, cfg_doc_terminal,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * Try interpreting the current token as a network address.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * If CFG_ADDR_WILDOK is set in flags, "*" can be used as a wildcard
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * and at least one of CFG_ADDR_V4OK and CFG_ADDR_V6OK must also be set. The
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * "*" is interpreted as the IPv4 wildcard address if CFG_ADDR_V4OK is
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * set (including the case where CFG_ADDR_V4OK and CFG_ADDR_V6OK are both set),
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt * and the IPv6 wildcard address otherwise.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunttoken_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt if ((flags & CFG_ADDR_WILDOK) != 0 && strcmp(s, "*") == 0) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt if ((flags & (CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK)) != 0) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt if ((flags & CFG_ADDR_V4PREFIXOK) != 0 && strlen(s) <= 15U) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt for (i = 0; i < 3; i++) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews if ((flags & CFG_ADDR_V6OK) != 0 && strlen(s) <= 127U) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews char buf[128]; /* see lib/bind9/getaddresses.c */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt char *d; /* zone delimiter */
bb5d14d7243d71e03d262ff175b355b52873e195Evan Huntcfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
a70fc47e9dc165175e77f091076559748858a488Mark Andrews "expected IPv4 address%s%s",
a70fc47e9dc165175e77f091076559748858a488Mark Andrews else if ((flags & CFG_ADDR_MASK) == CFG_ADDR_V6OK)
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "expected IPv6 address%s%s",
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "expected IP address%s%s",
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewscfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews if (pctx->token.type != isc_tokentype_number) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "expected port number or '*'");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "port number out of range");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parse_dscp(cfg_parser_t *pctx, isc_dscp_t *dscp) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "expected number");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "dscp out of range");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt/* netaddr */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int netaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int netaddr4_flags = CFG_ADDR_V4OK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int netaddr4wild_flags = CFG_ADDR_V4OK | CFG_ADDR_WILDOK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int netaddr6_flags = CFG_ADDR_V6OK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int netaddr6wild_flags = CFG_ADDR_V6OK | CFG_ADDR_WILDOK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntparse_netaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt unsigned int flags = *(const unsigned int *)type->of;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, 0);
7204d08a319cf590ae4280b8cc20999320398574Mark Andrewscfg_doc_netaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
7204d08a319cf590ae4280b8cc20999320398574Mark Andrews if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
7204d08a319cf590ae4280b8cc20999320398574Mark AndrewsLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netaddr = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netaddr", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netaddr4 = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netaddr4", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netaddr4wild = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netaddr4wild", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netaddr6 = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netaddr6", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netaddr6wild = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netaddr6wild", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt/* netprefix */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "expected prefix length");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "invalid prefix length");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt cfg_parser_error(pctx, CFG_LOG_NEAR, "expected network prefix");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntprint_netprefix(cfg_printer_t *pctx, const cfg_obj_t *obj) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt return (ISC_TF(obj->type->rep == &cfg_rep_netprefix));
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_obj_asnetprefix(const cfg_obj_t *obj, isc_netaddr_t *netaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt unsigned int *prefixlen)
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_netprefix);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_netprefix = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "netprefix", cfg_parse_netprefix, print_netprefix, cfg_doc_terminal,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntparse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt if (strcasecmp(TOKEN_STRING(pctx), "port") == 0) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt cfg_parser_error(pctx, 0, "expected at most one port");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt cfg_parser_error(pctx, 0, "expected at most one dscp");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int sockaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sockaddr = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntstatic unsigned int sockaddrdscp_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK |
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan HuntLIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sockaddrdscp = {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt "sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr,
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt const unsigned int *flagp;
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt return (parse_sockaddrsub(pctx, &cfg_type_sockaddr, *flagp, ret));
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt isc_netaddr_fromsockaddr(&netaddr, &obj->value.sockaddr);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt port = isc_sockaddr_getport(&obj->value.sockaddr);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewscfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]");
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews return (ISC_TF(obj->type->rep == &cfg_rep_sockaddr));
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews options |= (ISC_LEXOPT_EOF | ISC_LEXOPT_NOMORE);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews result = isc_lex_gettoken(pctx->lexer, options, &pctx->token);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews pctx->line = isc_lex_getsourceline(pctx->lexer);
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews if (isc_lex_getsourcename(pctx->lexer) != NULL) {
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt * Closed an included file, not the main file.
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews /* More understandable than "ran out of space". */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt cfg_parser_error(pctx, CFG_LOG_NEAR, "token too big");
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrewscfg_peektoken(cfg_parser_t *pctx, int options) {
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews * Get a string token, accepting both the quoted and the unquoted form.
10966da999f8f7f364418aa446d8ead9c8a761cfMark Andrews * Log an error if the next token is not a string.
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt cfg_parser_error(pctx, CFG_LOG_NEAR, "expected string");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt parser_complain(pctx, ISC_FALSE, flags, fmt, args);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntcfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt parser_complain(pctx, ISC_TRUE, flags, fmt, args);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt#define MAX_LOG_TOKEN 30 /* How much of a token to quote in log messages. */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt elt = ISC_LIST_TAIL(pctx->open_files->value.list);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntstatic char *
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt elt = ISC_LIST_TAIL(pctx->open_files->value.list);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt if (elt == NULL) /* shouldn't be possible, but... */
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Huntparser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt snprintf(where, sizeof(where), "%s: ", pctx->buf_name);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt len = vsnprintf(message, sizeof(message), format, args);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt if ((flags & (CFG_LOG_NEAR|CFG_LOG_BEFORE|CFG_LOG_NOPREP)) != 0) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt snprintf(tokenbuf, sizeof(tokenbuf), "end of file");
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt } else if (pctx->token.type == isc_tokentype_unknown) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt /* Choose a preposition. */
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Huntcfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level,
70d987def5a58ebeb8243017c0ec2e9b2c326cf4Evan Hunt const char *fmt, ...) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_log_write(lctx, CAT, MOD, level, "%s", msgbuf);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉map_symtabitem_destroy(char *key, unsigned int type,
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 cfg_parser_t *pctx = (cfg_parser_t *)userarg;
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 CHECK(isc_symtab_create(pctx->mctx, 5, /* XXX */
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj, sizeof(*obj));
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉free_map(cfg_parser_t *pctx, cfg_obj_t *obj) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_symtab_destroy(&obj->value.map.symtab);
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 * Destroy 'obj', a configuration object created in 'pctx'.
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_refcount_decrement(&obj->references, &refs);
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updatercfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 isc_refcount_increment(&src->references, NULL);
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type) {
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 void (*f)(void *closure, const char *text, int textlen),
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Huntcfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj,
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt for (clauseset = map->clausesets; *clauseset != NULL; clauseset++) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt for (clause = *clauseset; clause->name != NULL; clause++) {
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt result = isc_symtab_lookup(map->symtab, clausename, 0, &symval);
789252d55f025db52ee02aa933c9f09a4aadfa97Evan Hunt if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
feb067b25a8e33db62e2a7bf2e83bbb7f6eee845Evan Hunt CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 CHECK(isc_symtab_define(map->symtab, clausename, 1, symval,
bfcc5ae79a46c5c55e6cf1a9fe4d70a957712d2bTatuya JINMEI 神明達哉 if (destobj2->type == &cfg_type_implicitlist) {