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

📄 parser.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	CHECK(create_cfgobj(pctx, &cfg_type_boolean, &obj));	obj->value.boolean = value;	*ret = obj;	return (result); bad_boolean:	parser_error(pctx, LOG_NEAR, "boolean expected");	return (ISC_R_UNEXPECTEDTOKEN); cleanup:	return (result);}static voidprint_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) {	if (obj->value.boolean)		print(pctx, "yes", 3);	else		print(pctx, "no", 2);}static cfg_type_t cfg_type_boolean = {	"boolean", parse_boolean, print_boolean, &cfg_rep_boolean, NULL };static const char *dialup_enums[] = {	"notify", "notify-passive", "refresh", "passive", NULL };static isc_result_tparse_dialup_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));}static cfg_type_t cfg_type_dialuptype = {	"dialuptype", parse_dialup_type, print_ustring, 	&cfg_rep_string, dialup_enums};static const char *notify_enums[] = { "explicit", NULL };static isc_result_tparse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {	return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));}static cfg_type_t cfg_type_notifytype = {	"notifytype", parse_notify_type, print_ustring, 	&cfg_rep_string, notify_enums,};static keyword_type_t key_kw = { "key", &cfg_type_astring };LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {	"keyref", parse_keyvalue, print_keyvalue,	&cfg_rep_string, &key_kw};static cfg_type_t cfg_type_optional_keyref = {	"optional_keyref", parse_optional_keyvalue, print_keyvalue,	&cfg_rep_string, &key_kw};/* * Lists. */static isc_result_tcreate_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {	isc_result_t result;	CHECK(create_cfgobj(pctx, type, obj));	ISC_LIST_INIT((*obj)->value.list); cleanup:	return (result);}static isc_result_tcreate_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {	cfg_listelt_t *elt;	elt = isc_mem_get(pctx->mctx, sizeof(*elt));	if (elt == NULL)		return (ISC_R_NOMEMORY);	elt->obj = NULL;	ISC_LINK_INIT(elt, link);	*eltp = elt;	return (ISC_R_SUCCESS);}static voidfree_list_elt(cfg_parser_t *pctx, cfg_listelt_t *elt) {	cfg_obj_destroy(pctx, &elt->obj);	isc_mem_put(pctx->mctx, elt, sizeof(*elt));}static voidfree_list(cfg_parser_t *pctx, cfg_obj_t *obj) {	cfg_listelt_t *elt, *next;	for (elt = ISC_LIST_HEAD(obj->value.list);	     elt != NULL;	     elt = next)	{		next = ISC_LIST_NEXT(elt, link);		free_list_elt(pctx, elt);	}}static isc_result_tparse_list_elt(cfg_parser_t *pctx, const cfg_type_t *elttype,	       cfg_listelt_t **ret){	isc_result_t result;	cfg_listelt_t *elt = NULL;	cfg_obj_t *value = NULL;	CHECK(create_listelt(pctx, &elt));	result = parse(pctx, elttype, &value);	if (result != ISC_R_SUCCESS)		goto cleanup;	elt->obj = value;	*ret = elt;	return (ISC_R_SUCCESS); cleanup:	isc_mem_put(pctx->mctx, elt, sizeof(*elt));	return (result);}/* * Parse a homogeneous list whose elements are of type 'elttype' * and where each element is terminated by a semicolon. */static isc_result_tparse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret){	cfg_obj_t *listobj = NULL;	const cfg_type_t *listof = listtype->of;	isc_result_t result;	cfg_listelt_t *elt = NULL;	CHECK(create_list(pctx, listtype, &listobj));	for (;;) {		CHECK(cfg_peektoken(pctx, 0));		if (pctx->token.type == isc_tokentype_special &&		    pctx->token.value.as_char == /*{*/ '}')			break;		CHECK(parse_list_elt(pctx, listof, &elt));		CHECK(parse_semicolon(pctx));		ISC_LIST_APPEND(listobj->value.list, elt, link);		elt = NULL;	}	*ret = listobj;	return (ISC_R_SUCCESS); cleanup:	if (elt != NULL)		free_list_elt(pctx, elt);	CLEANUP_OBJ(listobj);	return (result);}static voidprint_list(cfg_printer_t *pctx, cfg_obj_t *obj) {	cfg_list_t *list = &obj->value.list;	cfg_listelt_t *elt;	for (elt = ISC_LIST_HEAD(*list);	     elt != NULL;	     elt = ISC_LIST_NEXT(elt, link)) {		print_indent(pctx);		print_obj(pctx, elt->obj);		print(pctx, ";\n", 2);	}}static isc_result_tparse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){	isc_result_t result;	CHECK(parse_special(pctx, '{'));	CHECK(parse_list(pctx, type, ret));	CHECK(parse_special(pctx, '}')); cleanup:	return (result);}static voidprint_bracketed_list(cfg_printer_t *pctx, cfg_obj_t *obj) {	print_open(pctx);	print_list(pctx, obj);	print_close(pctx);}/* * Parse a homogeneous list whose elements are of type 'elttype' * and where elements are separated by space.  The list ends * before the first semicolon. */static isc_result_tparse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret){	cfg_obj_t *listobj = NULL;	const cfg_type_t *listof = listtype->of;	isc_result_t result;	CHECK(create_list(pctx, listtype, &listobj));	for (;;) {		cfg_listelt_t *elt = NULL;		CHECK(cfg_peektoken(pctx, 0));		if (pctx->token.type == isc_tokentype_special &&		    pctx->token.value.as_char == ';')			break;		CHECK(parse_list_elt(pctx, listof, &elt));		ISC_LIST_APPEND(listobj->value.list, elt, link);	}	*ret = listobj;	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(listobj);	return (result);}static voidprint_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj) {	cfg_list_t *list = &obj->value.list;	cfg_listelt_t *elt;	for (elt = ISC_LIST_HEAD(*list);	     elt != NULL;	     elt = ISC_LIST_NEXT(elt, link)) {		print_obj(pctx, elt->obj);		if (ISC_LIST_NEXT(elt, link) != NULL)			print(pctx, " ", 1);	}}isc_boolean_tcfg_obj_islist(cfg_obj_t *obj) {	REQUIRE(obj != NULL);	return (ISC_TF(obj->type->rep == &cfg_rep_list));}cfg_listelt_t *cfg_list_first(cfg_obj_t *obj) {	REQUIRE(obj == NULL || obj->type->rep == &cfg_rep_list);	if (obj == NULL)		return (NULL);	return (ISC_LIST_HEAD(obj->value.list));}cfg_listelt_t *cfg_list_next(cfg_listelt_t *elt) {	REQUIRE(elt != NULL);	return (ISC_LIST_NEXT(elt, link));}cfg_obj_t *cfg_listelt_value(cfg_listelt_t *elt) {	REQUIRE(elt != NULL);	return (elt->obj);}/* * Maps. *//* * Parse a map body.  That's something like * *   "foo 1; bar { glub; }; zap true; zap false;" * * i.e., a sequence of option names followed by values and * terminated by semicolons.  Used for the top level of * the named.conf syntax, as well as for the body of the * options, view, zone, and other statements. */static isc_result_tparse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){	const cfg_clausedef_t * const *clausesets = type->of;	isc_result_t result;	const cfg_clausedef_t * const *clauseset;	const cfg_clausedef_t *clause;	cfg_obj_t *value = NULL;	cfg_obj_t *obj = NULL;	cfg_obj_t *eltobj = NULL;	cfg_obj_t *includename = NULL;	isc_symvalue_t symval;	cfg_list_t *list = NULL;	CHECK(create_map(pctx, type, &obj));	obj->value.map.clausesets = clausesets;	for (;;) {		cfg_listelt_t *elt;	redo:		/*		 * Parse the option name and see if it is known.		 */		CHECK(cfg_gettoken(pctx, 0));		if (pctx->token.type != isc_tokentype_string) {			cfg_ungettoken(pctx);			break;		}		/*		 * We accept "include" statements wherever a map body		 * clause can occur.		 */		if (strcasecmp(pctx->token.value.as_pointer, "include") == 0) {			/*			 * Turn the file name into a temporary configuration			 * object just so that it is not overwritten by the			 * semicolon token.			 */			CHECK(parse(pctx, &cfg_type_qstring, &includename));			CHECK(parse_semicolon(pctx));			CHECK(parser_openfile(pctx, includename->					      value.string.base));			 cfg_obj_destroy(pctx, &includename);			 goto redo;		}		clause = NULL;		for (clauseset = clausesets; *clauseset != NULL; clauseset++) {			for (clause = *clauseset;			     clause->name != NULL;			     clause++) {				if (strcasecmp(pctx->token.value.as_pointer,					   clause->name) == 0)					goto done;			}		}	done:		if (clause == NULL || clause->name == NULL) {			parser_error(pctx, LOG_NOPREP, "unknown option");			/*			 * Try to recover by parsing this option as an unknown			 * option and discarding it.			 */			 CHECK(parse(pctx, &cfg_type_unsupported, &eltobj));			 cfg_obj_destroy(pctx, &eltobj);			 CHECK(parse_semicolon(pctx));			 continue;		}		/* Clause is known. */		/* Issue warnings if appropriate */		if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)			parser_warning(pctx, 0, "option '%s' is obsolete",				       clause->name);		if ((clause->flags & CFG_CLAUSEFLAG_NOTIMP) != 0)			parser_warning(pctx, 0, "option '%s' is "				       "not implemented", clause->name);		if ((clause->flags & CFG_CLAUSEFLAG_NYI) != 0)			parser_warning(pctx, 0, "option '%s' is "				       "not implemented", clause->name);		/*		 * Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT		 * set here - we need to log the *lack* of such an option,		 * not its presence.		 */		/* See if the clause already has a value; if not create one. */		result = isc_symtab_lookup(obj->value.map.symtab,					   clause->name, 0, &symval);		if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {			/* Multivalued clause */			cfg_obj_t *listobj = NULL;			if (result == ISC_R_NOTFOUND) {				CHECK(create_list(pctx,						  &cfg_type_implicitlist,						  &listobj));				symval.as_pointer = listobj;				result = isc_symtab_define(obj->value.						   map.symtab,						   clause->name,						   1, symval,						   isc_symexists_reject);				if (result != ISC_R_SUCCESS) {					parser_error(pctx, LOG_NEAR,						     "isc_symtab_define(%s) "						     "failed", clause->name);					isc_mem_put(pctx->mctx, list,						    sizeof(cfg_list_t));					goto cleanup;				}			} else {				INSIST(result == ISC_R_SUCCESS);				listobj = symval.as_pointer;			}			elt = NULL;			CHECK(parse_list_elt(pctx, clause->type, &elt));			CHECK(parse_semicolon(pctx));			ISC_LIST_APPEND(listobj->value.list, elt, link);		} else {			/* Single-valued clause */			if (result == ISC_R_NOTFOUND) {				isc_boolean_t callback =					ISC_TF((clause->flags &						CFG_CLAUSEFLAG_CALLBACK) != 0);				CHECK(parse_symtab_elt(pctx, clause->name,						       clause->type,						       obj->value.map.symtab,						       callback));				CHECK(parse_semicolon(pctx));			} else if (result == ISC_R_SUCCESS) {				parser_error(pctx, LOG_NEAR, "'%s' redefined",					     clause->name);				result = ISC_R_EXISTS;				goto cleanup;			} else {				parser_error(pctx, LOG_NEAR,					     "isc_symtab_define() failed");				goto cleanup;			}		}	}	*ret = obj;	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(value);	CLEANUP_OBJ(obj);	CLEANUP_OBJ(eltobj);	CLEANUP_OBJ(includename);	return (result);}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){	isc_result_t result;	cfg_obj_t *obj = NULL;	isc_symvalue_t symval;	CHECK(parse(pctx, elttype, &obj));	if (callback && pctx->callback != NULL)		CHECK(pctx->callback(name, obj, pctx->callbackarg));		symval.as_pointer = obj;	CHECK(isc_symtab_define(symtab, name,				1, symval,				isc_symexists_reject));	return (ISC_R_SUCCESS); cleanup:	CLEANUP_OBJ(obj);	return (result);}/* * Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }" */static isc_result_tparse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret){	isc_result_t result;	CHECK(parse_special(pctx, '{'));	CHECK(parse_mapbody(pctx, type, ret));	CHECK(parse_special(pctx, '}')); cleanup:	return (result);}/* * Subroutine for parse_named_map() and parse_addressed_map(). */static isc_result_tparse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *type,		    cfg_obj_t **ret){	isc_result_t result;	cfg_obj_t *idobj = NULL;	cfg_obj_t *mapobj = NULL;	CHECK(parse(pctx, nametype, &idobj));	CHECK(parse_map(pctx, type, &mapobj));	mapobj->value.map.id = idobj;	idobj = NULL;	*ret = mapobj; cleanup:	CLEANUP_OBJ(idobj);	return (re

⌨️ 快捷键说明

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