parser.c revision 7d4a465de03b26bf9f5ef131d03253b8f6afc169
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
f0aad5341752aefe5059832f6cf3abc3283c6e16Tinderbox User * Copyright (C) 2000-2003 Internet Software Consortium.
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * Permission to use, copy, modify, and distribute this software for any
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * purpose with or without fee is hereby granted, provided that the above
5347c0fcb04eaea19d9f39795646239f487c6207Tinderbox User * copyright notice and this permission notice appear in all copies.
d6fa26d0adaec6c910115be34fe7a5a5f402c14fMark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * PERFORMANCE OF THIS SOFTWARE.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein/* $Id: parser.c,v 1.121 2006/02/17 00:24:21 marka Exp $ */
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User/* Shorthand */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#define MAP_SYM 1 /* Unique type for isc_symtab */
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein/* Check a return value. */
9c6a5d1f22f972232d7a9fd5c5fa64f10bacbdffAutomatic Updater if (result != ISC_R_SUCCESS) goto cleanup; \
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt/* Clean up a configuration object if non-NULL. */
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * Forward declarations of static functions.
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Userparse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Userprint_list(cfg_printer_t *pctx, cfg_obj_t *obj);
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Userfree_list(cfg_parser_t *pctx, cfg_obj_t *obj);
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeincreate_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsfree_string(cfg_parser_t *pctx, cfg_obj_t *obj);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewscreate_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
ac93437301f55ed69bf85883a497a75598c628f9Automatic Updaterfree_map(cfg_parser_t *pctx, cfg_obj_t *obj);
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luceparse_symtab_elt(cfg_parser_t *pctx, const char *name,
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luceparser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce unsigned int flags, const char *format, va_list args);
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User * Data representations. These correspond to members of the
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User * "value" union in struct cfg_obj (except "void", which does
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User * not need a union member).
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_uint32 = { "uint32", free_noop };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_uint64 = { "uint64", free_noop };
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox Usercfg_rep_t cfg_rep_string = { "string", free_string };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_boolean = { "boolean", free_noop };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_list = { "list", free_list };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_rep_t cfg_rep_void = { "void", free_noop };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User * Configuration type definitions.
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User * An implicit list. These are formed by clauses that occur multiple times.
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User "implicitlist", NULL, print_list, NULL, &cfg_rep_list, NULL };
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User/* Functions. */
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_print_obj(cfg_printer_t *pctx, cfg_obj_t *obj) {
ffe29868b4bbc64953fc5d0de51f988c20158967Tinderbox Usercfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt while (indent > 0) {
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User void (*f)(void *closure, const char *text, int textlen),
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox Usercfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User const cfg_tuplefielddef_t *fields = type->of;
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User unsigned int nfields = 0;
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User for (f = fields, i = 0; f->name != NULL; f++, i++)
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User const cfg_tuplefielddef_t *fields = type->of;
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User unsigned int i;
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User for (f = fields, i = 0; f->name != NULL; f++, i++)
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[i]));
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox Usercfg_print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj) {
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User unsigned int i;
aa1905addf2f33d90aa020080e4e77a8651e829aTinderbox User const cfg_tuplefielddef_t *fields = obj->type->of;
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User for (f = fields, i = 0; f->name != NULL; f++, i++) {
4abdfc917e6635a7c81d1f931a0c79227e72d025Mark Andrews need_space = ISC_TF(fieldobj->type->print != cfg_print_void);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntcfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt need_space = ISC_TF(f->type->print != cfg_print_void);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int i;
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User const cfg_tuplefielddef_t *fields = obj->type->of;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int nfields = 0;
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User for (f = fields, i = 0; f->name != NULL; f++, i++) {
56bd026e6c96482dccab83778bf8f9c92c36bf11Tinderbox User return (ISC_TF(obj->type->rep == &cfg_rep_tuple));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntcfg_tuple_get(cfg_obj_t *tupleobj, const char* name) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int i;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein REQUIRE(tupleobj != NULL && tupleobj->type->rep == &cfg_rep_tuple);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for (f = fields, i = 0; f->name != NULL; f++, i++) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeincfg_parse_special(cfg_parser_t *pctx, int special) {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cfg_parser_error(pctx, CFG_LOG_NEAR, "'%c' expected", special);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews * Parse a required semicolon. If it is not there, log
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User * an error and increment the error count but continue
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User * parsing. Since the next token is pushed back,
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User * care must be taken to make sure it is eventually
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User * consumed or an infinite loop may result.
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User if (pctx->token.type == isc_tokentype_special &&
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_parser_error(pctx, CFG_LOG_BEFORE, "missing ';'");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * Parse EOF, logging and returning an error if not there.
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User cfg_parser_error(pctx, CFG_LOG_NEAR, "syntax error");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt/* A list of files, used internally for pctx->files. */
7911e6f9de303bca5a3d8b34f4330c8f7cecffaeTinderbox User "filelist", NULL, print_list, NULL, &cfg_rep_list,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeincfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
void *arg)
static isc_result_t
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
return (result);
return (result);
NULL };
return (ISC_R_UNEXPECTEDTOKEN);
return (result);
static isc_result_t
int len;
return (ISC_R_NOMEMORY);
return (result);
return (ISC_R_UNEXPECTEDTOKEN);
ret));
return (result);
static isc_result_t
return (ISC_R_UNEXPECTEDTOKEN);
ret));
return (result);
ret));
return (result);
if (strcasecmp(*p, s) == 0)
return (ISC_TRUE);
return (ISC_FALSE);
static isc_result_t
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (result);
goto bad_boolean;
goto bad_boolean;
return (result);
return (ISC_R_UNEXPECTEDTOKEN);
return (result);
return (result);
static isc_result_t
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
return (result);
return (result);
return (ISC_R_SUCCESS);
return (result);
return (NULL);
* the named.conf syntax, as well as for the body of the
redo:
goto redo;
clause++) {
goto done;
done:
&listobj));
sizeof(cfg_list_t));
goto cleanup;
CFG_CLAUSEFLAG_CALLBACK) != 0);
callback));
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
return (result);
return (result);
static isc_result_t
return (result);
clauseset++)
clause++) {
INSIST(0);
clause++) {
static struct flagtext {
unsigned int flag;
const char *text;
} flagtexts[] = {
{ 0, NULL }
struct flagtext *p;
if (first)
clause++) {
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
isc_region_t r;
goto cleanup;
goto cleanup;
return (result);
return (result);
static isc_result_t
int braces = 0;
braces++;
braces--;
if (braces == 0)
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
INSIST(0);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
if (d != NULL)
if (d != NULL) {
#ifdef ISC_PLATFORM_HAVESCOPEID
&in6a,
&zone);
return (result);
return (ISC_R_BADADDRESSFORM);
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDTOKEN);
return (result);
*port = 0;
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
return (result);
case AF_INET:
case AF_INET6:
addrlen = 0;
INSIST(0);
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_RANGE);
return (ISC_R_SUCCESS);
return (result);
unsigned int *prefixlen) {
static isc_result_t
return (ISC_R_SUCCESS);
return (result);
if (port != 0) {
return (ISC_R_SUCCESS);
redo:
switch (result) {
case ISC_R_SUCCESS:
goto redo;
case ISC_R_NOSPACE:
case ISC_R_IOERROR:
return (result);
return (result);
static isc_result_t
return (result);
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_SUCCESS);
return (none);
return (none);
if (is_warning)
isc_region_t r;
flags = 0;
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_SUCCESS);
return (result);
void *closure)
pctx.f = f;