⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: parser.c,v 1.70.2.20.2.18 2004/05/15 03:46:13 jinmei Exp $ */#include <config.h>#include <isc/buffer.h>#include <isc/dir.h>#include <isc/formatcheck.h>#include <isc/lex.h>#include <isc/log.h>#include <isc/mem.h>#include <isc/net.h>#include <isc/netaddr.h>#include <isc/print.h>#include <isc/string.h>#include <isc/sockaddr.h>#include <isc/netscope.h>#include <isc/util.h>#include <isc/symtab.h>#include <isccfg/cfg.h>#include <isccfg/grammar.h>#include <isccfg/log.h>/* Shorthand */#define CAT CFG_LOGCATEGORY_CONFIG#define MOD CFG_LOGMODULE_PARSER#define MAP_SYM 1 	/* Unique type for isc_symtab */#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)/* Check a return value. */#define CHECK(op) 						\     	do { result = (op); 					\		if (result != ISC_R_SUCCESS) goto cleanup; 	\	} while (0)/* Clean up a configuration object if non-NULL. */#define CLEANUP_OBJ(obj) \	do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)/* * Forward declarations of static functions. */static voidfree_tuple(cfg_parser_t *pctx, cfg_obj_t *obj);static isc_result_tparse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);static voidprint_list(cfg_printer_t *pctx, cfg_obj_t *obj);static voidfree_list(cfg_parser_t *pctx, cfg_obj_t *obj);static isc_result_tcreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);static isc_result_tcreate_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,	      cfg_obj_t **ret);static voidfree_string(cfg_parser_t *pctx, cfg_obj_t *obj);static isc_result_tcreate_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);static voidfree_map(cfg_parser_t *pctx, cfg_obj_t *obj);static isc_result_tparse_symtab_elt(cfg_parser_t *pctx, const char *name,		 cfg_type_t *elttype, isc_symtab_t *symtab,		 isc_boolean_t callback);static voidfree_noop(cfg_parser_t *pctx, cfg_obj_t *obj);static isc_result_tcfg_getstringtoken(cfg_parser_t *pctx);static voidparser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,		unsigned int flags, const char *format, va_list args);/* * Data representations.  These correspond to members of the * "value" union in struct cfg_obj (except "void", which does * not need a union member). */cfg_rep_t cfg_rep_uint32 = { "uint32", free_noop };cfg_rep_t cfg_rep_uint64 = { "uint64", free_noop };cfg_rep_t cfg_rep_string = { "string", free_string };cfg_rep_t cfg_rep_boolean = { "boolean", free_noop };cfg_rep_t cfg_rep_map = { "map", free_map };cfg_rep_t cfg_rep_list = { "list", free_list };cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };cfg_rep_t cfg_rep_void = { "void", free_noop };/* * Configuration type definitions. *//* * An implicit list.  These are formed by clauses that occur multiple times. */static cfg_type_t cfg_type_implicitlist = {	"implicitlist", NULL, print_list, NULL, &cfg_rep_list, NULL };/* Functions. */voidcfg_print_obj(cfg_printer_t *pctx, cfg_obj_t *obj) {	obj->type->print(pctx, obj);}voidcfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {	pctx->f(pctx->closure, text, len);}static voidprint_open(cfg_printer_t *pctx) {	cfg_print_chars(pctx, "{\n", 2);	pctx->indent++;}static voidprint_indent(cfg_printer_t *pctx) {	int indent = pctx->indent;	while (indent > 0) {		cfg_print_chars(pctx, "\t", 1);		indent--;	}}static voidprint_close(cfg_printer_t *pctx) {	pctx->indent--;	print_indent(pctx);	cfg_print_chars(pctx, "}", 1);}isc_result_tcfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	isc_result_t result;	INSIST(ret != NULL && *ret == NULL);	result = type->parse(pctx, type, ret);	if (result != ISC_R_SUCCESS)		return (result);	INSIST(*ret != NULL);	return (ISC_R_SUCCESS);}voidcfg_print(cfg_obj_t *obj,	  void (*f)(void *closure, const char *text, int textlen),	  void *closure){	cfg_printer_t pctx;	pctx.f = f;	pctx.closure = closure;	pctx.indent = 0;	obj->type->print(&pctx, obj);}/* Tuples. */  isc_result_tcfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	isc_result_t result;	const cfg_tuplefielddef_t *fields = type->of;	const cfg_tuplefielddef_t *f;	cfg_obj_t *obj = NULL;	unsigned int nfields = 0;	int i;	for (f = fields; f->name != NULL; f++)		nfields++;	CHECK(cfg_create_obj(pctx, type, &obj));	obj->value.tuple = isc_mem_get(pctx->mctx,				       nfields * sizeof(cfg_obj_t *));	if (obj->value.tuple == NULL) {		result = ISC_R_NOMEMORY;		goto cleanup;	}	for (f = fields, i = 0; f->name != NULL; f++, i++)		obj->value.tuple[i] = NULL;	*ret = obj;	return (ISC_R_SUCCESS); cleanup:	if (obj != NULL)		isc_mem_put(pctx->mctx, obj, sizeof(*obj));	return (result);}isc_result_tcfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){	isc_result_t result;	const cfg_tuplefielddef_t *fields = type->of;	const cfg_tuplefielddef_t *f;	cfg_obj_t *obj = NULL;	unsigned int i;	CHECK(cfg_create_tuple(pctx, type, &obj));	for (f = fields, i = 0; f->name != NULL; f++, i++)		CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[i]));	*ret = obj;	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(obj);	return (result);}voidcfg_print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj) {	unsigned int i;	const cfg_tuplefielddef_t *fields = obj->type->of;	const cfg_tuplefielddef_t *f;	isc_boolean_t need_space = ISC_FALSE;	for (f = fields, i = 0; f->name != NULL; f++, i++) {		cfg_obj_t *fieldobj = obj->value.tuple[i];		if (need_space)			cfg_print_chars(pctx, " ", 1);		cfg_print_obj(pctx, fieldobj);		need_space = ISC_TF(fieldobj->type->print != cfg_print_void);	}}voidcfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {	const cfg_tuplefielddef_t *fields = type->of;	const cfg_tuplefielddef_t *f;	isc_boolean_t need_space = ISC_FALSE;	for (f = fields; f->name != NULL; f++) {		if (need_space)			cfg_print_chars(pctx, " ", 1);		cfg_doc_obj(pctx, f->type);		need_space = ISC_TF(f->type->print != cfg_print_void);	}}static voidfree_tuple(cfg_parser_t *pctx, cfg_obj_t *obj) {	unsigned int i;	const cfg_tuplefielddef_t *fields = obj->type->of;	const cfg_tuplefielddef_t *f;	unsigned int nfields = 0;	if (obj->value.tuple == NULL)		return;	for (f = fields, i = 0; f->name != NULL; f++, i++) {		CLEANUP_OBJ(obj->value.tuple[i]);		nfields++;	}	isc_mem_put(pctx->mctx, obj->value.tuple,		    nfields * sizeof(cfg_obj_t *));}isc_boolean_tcfg_obj_istuple(cfg_obj_t *obj) {	REQUIRE(obj != NULL);	return (ISC_TF(obj->type->rep == &cfg_rep_tuple));}cfg_obj_t *cfg_tuple_get(cfg_obj_t *tupleobj, const char* name) {	unsigned int i;	const cfg_tuplefielddef_t *fields;	const cfg_tuplefielddef_t *f;		REQUIRE(tupleobj != NULL && tupleobj->type->rep == &cfg_rep_tuple);	fields = tupleobj->type->of;	for (f = fields, i = 0; f->name != NULL; f++, i++) {		if (strcmp(f->name, name) == 0)			return (tupleobj->value.tuple[i]);	}	INSIST(0);	return (NULL);}isc_result_tcfg_parse_special(cfg_parser_t *pctx, int special) {        isc_result_t result;	CHECK(cfg_gettoken(pctx, 0));	if (pctx->token.type == isc_tokentype_special &&	    pctx->token.value.as_char == special)		return (ISC_R_SUCCESS);	cfg_parser_error(pctx, CFG_LOG_NEAR, "'%c' expected", special);	return (ISC_R_UNEXPECTEDTOKEN); cleanup:	return (result);}/* * Parse a required semicolon.  If it is not there, log * an error and increment the error count but continue * parsing.  Since the next token is pushed back, * care must be taken to make sure it is eventually * consumed or an infinite loop may result. */static isc_result_tparse_semicolon(cfg_parser_t *pctx) {        isc_result_t result;	CHECK(cfg_gettoken(pctx, 0));	if (pctx->token.type == isc_tokentype_special &&	    pctx->token.value.as_char == ';')		return (ISC_R_SUCCESS);	cfg_parser_error(pctx, CFG_LOG_BEFORE, "missing ';'");	cfg_ungettoken(pctx); cleanup:	return (result);}/* * Parse EOF, logging and returning an error if not there. */static isc_result_tparse_eof(cfg_parser_t *pctx) {        isc_result_t result;	CHECK(cfg_gettoken(pctx, 0));	if (pctx->token.type == isc_tokentype_eof)		return (ISC_R_SUCCESS);	cfg_parser_error(pctx, CFG_LOG_NEAR, "syntax error");	return (ISC_R_UNEXPECTEDTOKEN); cleanup:	return (result);}/* A list of files, used internally for pctx->files. */static cfg_type_t cfg_type_filelist = {	"filelist", NULL, print_list, NULL, &cfg_rep_list,	&cfg_type_qstring};isc_result_tcfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {	isc_result_t result;	cfg_parser_t *pctx;	isc_lexspecials_t specials;	REQUIRE(mctx != NULL);	REQUIRE(ret != NULL && *ret == NULL);	pctx = isc_mem_get(mctx, sizeof(*pctx));	if (pctx == NULL)		return (ISC_R_NOMEMORY);	pctx->mctx = mctx;	pctx->lctx = lctx;	pctx->lexer = NULL;	pctx->seen_eof = ISC_FALSE;	pctx->ungotten = ISC_FALSE;	pctx->errors = 0;	pctx->warnings = 0;	pctx->open_files = NULL;	pctx->closed_files = NULL;	pctx->line = 0;	pctx->callback = NULL;	pctx->callbackarg = NULL;	pctx->token.type = isc_tokentype_unknown;	memset(specials, 0, sizeof(specials));	specials['{'] = 1;	specials['}'] = 1;	specials[';'] = 1;	specials['/'] = 1;	specials['"'] = 1;	specials['!'] = 1;	CHECK(isc_lex_create(pctx->mctx, 1024, &pctx->lexer));	isc_lex_setspecials(pctx->lexer, specials);	isc_lex_setcomments(pctx->lexer, (ISC_LEXCOMMENT_C |					 ISC_LEXCOMMENT_CPLUSPLUS |					 ISC_LEXCOMMENT_SHELL));	CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files));	CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files));	*ret = pctx;	return (ISC_R_SUCCESS); cleanup:	if (pctx->lexer != NULL)		isc_lex_destroy(&pctx->lexer);	CLEANUP_OBJ(pctx->open_files);	CLEANUP_OBJ(pctx->closed_files);	isc_mem_put(mctx, pctx, sizeof(*pctx));	return (result);}static isc_result_tparser_openfile(cfg_parser_t *pctx, const char *filename) {	isc_result_t result;	cfg_listelt_t *elt = NULL;	cfg_obj_t *stringobj = NULL;	result = isc_lex_openfile(pctx->lexer, filename);	if (result != ISC_R_SUCCESS) {		cfg_parser_error(pctx, 0, "open: %s: %s",			     filename, isc_result_totext(result));		goto cleanup;	}	CHECK(create_string(pctx, filename, &cfg_type_qstring, &stringobj));	CHECK(create_listelt(pctx, &elt));	elt->obj = stringobj;	ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(stringobj);	return (result);}voidcfg_parser_setcallback(cfg_parser_t *pctx,		       cfg_parsecallback_t callback,		       void *arg){	pctx->callback = callback;	pctx->callbackarg = arg;}/* * Parse a configuration using a pctx where a lexer has already * been set up with a source. */static isc_result_tparse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	isc_result_t result;	cfg_obj_t *obj = NULL;	result = cfg_parse_obj(pctx, type, &obj);	if (pctx->errors != 0) {		/* Errors have been logged. */		if (result == ISC_R_SUCCESS)			result = ISC_R_FAILURE;		goto cleanup;	}	if (result != ISC_R_SUCCESS) {		/* Parsing failed but no errors have been logged. */		cfg_parser_error(pctx, 0, "parsing failed");		goto cleanup;	}	CHECK(parse_eof(pctx));	*ret = obj;	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(obj);	return (result);}isc_result_tcfg_parse_file(cfg_parser_t *pctx, const char *filename,	       const cfg_type_t *type, cfg_obj_t **ret){	isc_result_t result;	REQUIRE(filename != NULL);	CHECK(parser_openfile(pctx, filename));	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 */isc_result_tcfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	UNUSED(type);	return (cfg_create_obj(pctx, &cfg_type_void, ret));}voidcfg_print_void(cfg_printer_t *pctx, cfg_obj_t *obj) {	UNUSED(pctx);	UNUSED(obj);}voidcfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type) {	UNUSED(pctx);	UNUSED(type);}isc_boolean_tcfg_obj_isvoid(cfg_obj_t *obj) {	REQUIRE(obj != NULL);	return (ISC_TF(obj->type->rep == &cfg_rep_void));}cfg_type_t cfg_type_void = {	"void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,	NULL };/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -