1 /* $NetBSD: grammar.h,v 1.1 2024/02/18 20:57:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef ISCCFG_GRAMMAR_H 17 #define ISCCFG_GRAMMAR_H 1 18 19 /*! \file isccfg/grammar.h */ 20 21 #include <inttypes.h> 22 #include <stdbool.h> 23 24 #include <isc/lex.h> 25 #include <isc/netaddr.h> 26 #include <isc/region.h> 27 #include <isc/sockaddr.h> 28 #include <isc/types.h> 29 30 #include <isccfg/cfg.h> 31 32 /* 33 * Definitions shared between the configuration parser 34 * and the grammars; not visible to users of the parser. 35 */ 36 37 /*% Clause may occur multiple times (e.g., "zone") */ 38 #define CFG_CLAUSEFLAG_MULTI 0x00000001 39 /*% Clause is obsolete (logs a warning, but is not a fatal error) */ 40 #define CFG_CLAUSEFLAG_OBSOLETE 0x00000002 41 /*% Clause is not implemented, and may never be */ 42 #define CFG_CLAUSEFLAG_NOTIMP 0x00000004 43 /*% Clause is not implemented yet */ 44 #define CFG_CLAUSEFLAG_NYI 0x00000008 45 /*% Default value has changed since earlier release */ 46 #define CFG_CLAUSEFLAG_NEWDEFAULT 0x00000010 47 /*% 48 * Clause needs to be interpreted during parsing 49 * by calling a callback function, like the 50 * "directory" option. 51 */ 52 #define CFG_CLAUSEFLAG_CALLBACK 0x00000020 53 /*% A option that is only used in testing. */ 54 #define CFG_CLAUSEFLAG_TESTONLY 0x00000040 55 /*% A configuration option that was not configured at compile time. */ 56 #define CFG_CLAUSEFLAG_NOTCONFIGURED 0x00000080 57 /*% A option for a experimental feature. */ 58 #define CFG_CLAUSEFLAG_EXPERIMENTAL 0x00000100 59 /*% A configuration option that is ineffective due to 60 * compile time options, but is harmless. */ 61 #define CFG_CLAUSEFLAG_NOOP 0x00000200 62 /*% Clause will be obsolete in a future release (logs a warning) */ 63 #define CFG_CLAUSEFLAG_DEPRECATED 0x00000400 64 /*% Clause has been obsolete so long that it's now a fatal error */ 65 #define CFG_CLAUSEFLAG_ANCIENT 0x00000800 66 67 /*% 68 * Zone types for which a clause is valid: 69 * These share space with CFG_CLAUSEFLAG values, but count 70 * down from the top. 71 */ 72 #define CFG_ZONE_PRIMARY 0x80000000 73 #define CFG_ZONE_SECONDARY 0x40000000 74 #define CFG_ZONE_STUB 0x20000000 75 #define CFG_ZONE_HINT 0x10000000 76 #define CFG_ZONE_FORWARD 0x08000000 77 #define CFG_ZONE_STATICSTUB 0x04000000 78 #define CFG_ZONE_REDIRECT 0x02000000 79 #define CFG_ZONE_DELEGATION 0x01000000 80 #define CFG_ZONE_INVIEW 0x00800000 81 #define CFG_ZONE_MIRROR 0x00400000 82 83 typedef struct cfg_clausedef cfg_clausedef_t; 84 typedef struct cfg_tuplefielddef cfg_tuplefielddef_t; 85 typedef struct cfg_printer cfg_printer_t; 86 typedef ISC_LIST(cfg_listelt_t) cfg_list_t; 87 typedef struct cfg_map cfg_map_t; 88 typedef struct cfg_rep cfg_rep_t; 89 typedef struct cfg_duration cfg_duration_t; 90 91 #define CFG_DURATION_MAXLEN 80 92 93 /* 94 * Function types for configuration object methods 95 */ 96 97 typedef isc_result_t (*cfg_parsefunc_t)(cfg_parser_t *, const cfg_type_t *type, 98 cfg_obj_t **); 99 typedef void (*cfg_printfunc_t)(cfg_printer_t *, const cfg_obj_t *); 100 typedef void (*cfg_docfunc_t)(cfg_printer_t *, const cfg_type_t *); 101 typedef void (*cfg_freefunc_t)(cfg_parser_t *, cfg_obj_t *); 102 103 /* 104 * Structure definitions 105 */ 106 107 /*% 108 * A configuration printer object. This is an abstract 109 * interface to a destination to which text can be printed 110 * by calling the function 'f'. 111 */ 112 struct cfg_printer { 113 void (*f)(void *closure, const char *text, int textlen); 114 void *closure; 115 int indent; 116 int flags; 117 }; 118 119 /*% A clause definition. */ 120 struct cfg_clausedef { 121 const char *name; 122 cfg_type_t *type; 123 unsigned int flags; 124 }; 125 126 /*% A tuple field definition. */ 127 struct cfg_tuplefielddef { 128 const char *name; 129 cfg_type_t *type; 130 unsigned int flags; 131 }; 132 133 /*% A configuration object type definition. */ 134 struct cfg_type { 135 const char *name; /*%< For debugging purposes only */ 136 cfg_parsefunc_t parse; 137 cfg_printfunc_t print; 138 cfg_docfunc_t doc; /*%< Print grammar description */ 139 cfg_rep_t *rep; /*%< Data representation */ 140 const void *of; /*%< Additional data for meta-types */ 141 }; 142 143 /*% A keyword-type definition, for things like "port <integer>". */ 144 typedef struct { 145 const char *name; 146 const cfg_type_t *type; 147 } keyword_type_t; 148 149 struct cfg_map { 150 cfg_obj_t *id; /*%< Used for 'named maps' like 151 * keys, zones, &c */ 152 const cfg_clausedef_t *const *clausesets; /*%< The clauses that 153 * can occur in this map; 154 * used for printing */ 155 isc_symtab_t *symtab; 156 }; 157 158 typedef struct cfg_netprefix cfg_netprefix_t; 159 160 struct cfg_netprefix { 161 isc_netaddr_t address; /* IP4/IP6 */ 162 unsigned int prefixlen; 163 }; 164 165 /*% 166 * A configuration object to store ISO 8601 durations. 167 */ 168 struct cfg_duration { 169 /* 170 * The duration is stored in multiple parts: 171 * [0] Years 172 * [1] Months 173 * [2] Weeks 174 * [3] Days 175 * [4] Hours 176 * [5] Minutes 177 * [6] Seconds 178 */ 179 uint32_t parts[7]; 180 bool iso8601; 181 bool unlimited; 182 }; 183 184 /*% 185 * A configuration data representation. 186 */ 187 struct cfg_rep { 188 const char *name; /*%< For debugging only */ 189 cfg_freefunc_t free; /*%< How to free this kind of data. */ 190 }; 191 192 /*% 193 * A configuration object. This is the main building block 194 * of the configuration parse tree. 195 */ 196 197 struct cfg_obj { 198 const cfg_type_t *type; 199 union { 200 uint32_t uint32; 201 uint64_t uint64; 202 isc_textregion_t string; /*%< null terminated, too */ 203 bool boolean; 204 cfg_map_t map; 205 cfg_list_t list; 206 cfg_obj_t **tuple; 207 isc_sockaddr_t sockaddr; 208 struct { 209 isc_sockaddr_t sockaddr; 210 isc_dscp_t dscp; 211 } sockaddrdscp; 212 cfg_netprefix_t netprefix; 213 cfg_duration_t duration; 214 } value; 215 isc_refcount_t references; /*%< reference counter */ 216 const char *file; 217 unsigned int line; 218 cfg_parser_t *pctx; 219 }; 220 221 /*% A list element. */ 222 struct cfg_listelt { 223 cfg_obj_t *obj; 224 ISC_LINK(cfg_listelt_t) link; 225 }; 226 227 /*% The parser object. */ 228 struct cfg_parser { 229 isc_mem_t *mctx; 230 isc_log_t *lctx; 231 isc_lex_t *lexer; 232 unsigned int errors; 233 unsigned int warnings; 234 isc_token_t token; 235 236 /*% We are at the end of all input. */ 237 bool seen_eof; 238 239 /*% The current token has been pushed back. */ 240 bool ungotten; 241 242 /*% 243 * The stack of currently active files, represented 244 * as a configuration list of configuration strings. 245 * The head is the top-level file, subsequent elements 246 * (if any) are the nested include files, and the 247 * last element is the file currently being parsed. 248 */ 249 cfg_obj_t *open_files; 250 251 /*% 252 * Names of files that we have parsed and closed 253 * and were previously on the open_file list. 254 * We keep these objects around after closing 255 * the files because the file names may still be 256 * referenced from other configuration objects 257 * for use in reporting semantic errors after 258 * parsing is complete. 259 */ 260 cfg_obj_t *closed_files; 261 262 /*% 263 * Name of a buffer being parsed; used only for 264 * logging. 265 */ 266 char const *buf_name; 267 268 /*% 269 * Current line number. We maintain our own 270 * copy of this so that it is available even 271 * when a file has just been closed. 272 */ 273 unsigned int line; 274 275 /*% 276 * Parser context flags, used for maintaining state 277 * from one token to the next. 278 */ 279 unsigned int flags; 280 281 /*%< Reference counter */ 282 isc_refcount_t references; 283 284 cfg_parsecallback_t callback; 285 void *callbackarg; 286 }; 287 288 /* Parser context flags */ 289 #define CFG_PCTX_SKIP 0x1 290 #define CFG_PCTX_NODEPRECATED 0x2 291 292 /*@{*/ 293 /*% 294 * Flags defining whether to accept certain types of network addresses. 295 */ 296 #define CFG_ADDR_V4OK 0x00000001 297 #define CFG_ADDR_V4PREFIXOK 0x00000002 298 #define CFG_ADDR_V6OK 0x00000004 299 #define CFG_ADDR_WILDOK 0x00000008 300 #define CFG_ADDR_DSCPOK 0x00000010 301 #define CFG_ADDR_MASK (CFG_ADDR_V6OK | CFG_ADDR_V4OK) 302 /*@}*/ 303 304 /*@{*/ 305 /*% 306 * Predefined data representation types. 307 */ 308 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_uint32; 309 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_uint64; 310 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_string; 311 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_boolean; 312 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_map; 313 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_list; 314 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_tuple; 315 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_sockaddr; 316 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_netprefix; 317 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_void; 318 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_fixedpoint; 319 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_percentage; 320 LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_duration; 321 /*@}*/ 322 323 /*@{*/ 324 /*% 325 * Predefined configuration object types. 326 */ 327 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_boolean; 328 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint32; 329 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint64; 330 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_qstring; 331 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring; 332 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring; 333 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sstring; 334 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_aml; 335 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_text; 336 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_optional_bracketed_text; 337 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_keyref; 338 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr; 339 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddrdscp; 340 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr; 341 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4; 342 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4wild; 343 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr6; 344 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr6wild; 345 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netprefix; 346 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_void; 347 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_token; 348 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported; 349 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint; 350 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage; 351 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_duration; 352 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_duration_or_unlimited; 353 /*@}*/ 354 355 isc_result_t 356 cfg_gettoken(cfg_parser_t *pctx, int options); 357 358 isc_result_t 359 cfg_peektoken(cfg_parser_t *pctx, int options); 360 361 void 362 cfg_ungettoken(cfg_parser_t *pctx); 363 364 #define CFG_LEXOPT_QSTRING (ISC_LEXOPT_QSTRING | ISC_LEXOPT_QSTRINGMULTILINE) 365 366 isc_result_t 367 cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 368 369 void 370 cfg_print_rawuint(cfg_printer_t *pctx, unsigned int u); 371 372 isc_result_t 373 cfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 374 375 void 376 cfg_print_uint32(cfg_printer_t *pctx, const cfg_obj_t *obj); 377 378 void 379 cfg_print_uint64(cfg_printer_t *pctx, const cfg_obj_t *obj); 380 381 isc_result_t 382 cfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 383 384 void 385 cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj); 386 387 isc_result_t 388 cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 389 390 isc_result_t 391 cfg_parse_sstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 392 393 isc_result_t 394 cfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na); 395 396 void 397 cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na); 398 399 bool 400 cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags); 401 402 isc_result_t 403 cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port); 404 405 isc_result_t 406 cfg_parse_dscp(cfg_parser_t *pctx, isc_dscp_t *dscp); 407 408 isc_result_t 409 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 410 411 isc_result_t 412 cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 413 414 void 415 cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj); 416 417 void 418 cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj); 419 420 void 421 cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type); 422 423 isc_result_t 424 cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type, 425 cfg_obj_t **ret); 426 427 isc_result_t 428 cfg_parse_special(cfg_parser_t *pctx, int special); 429 /*%< Parse a required special character 'special'. */ 430 431 isc_result_t 432 cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 433 434 isc_result_t 435 cfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 436 437 void 438 cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj); 439 440 void 441 cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type); 442 443 isc_result_t 444 cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 445 446 isc_result_t 447 cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype, 448 cfg_listelt_t **ret); 449 450 isc_result_t 451 cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, 452 cfg_obj_t **ret); 453 454 void 455 cfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj); 456 457 void 458 cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type); 459 460 isc_result_t 461 cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *type, 462 cfg_obj_t **ret); 463 464 void 465 cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj); 466 467 isc_result_t 468 cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 469 470 void 471 cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type); 472 473 isc_result_t 474 cfg_parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype, 475 const cfg_type_t *othertype, cfg_obj_t **ret); 476 477 void 478 cfg_doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype, 479 const cfg_type_t *othertype); 480 481 void 482 cfg_print_chars(cfg_printer_t *pctx, const char *text, int len); 483 /*%< Print 'len' characters at 'text' */ 484 485 void 486 cfg_print_cstr(cfg_printer_t *pctx, const char *s); 487 /*%< Print the null-terminated string 's' */ 488 489 isc_result_t 490 cfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 491 492 isc_result_t 493 cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, 494 cfg_obj_t **ret); 495 496 isc_result_t 497 cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, 498 cfg_obj_t **ret); 499 500 isc_result_t 501 cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, 502 cfg_obj_t **ret); 503 504 void 505 cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj); 506 507 void 508 cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type); 509 510 isc_result_t 511 cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 512 513 void 514 cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj); 515 516 void 517 cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type); 518 519 isc_result_t 520 cfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 521 522 void 523 cfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj); 524 525 void 526 cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type); 527 528 isc_result_t 529 cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type, 530 cfg_obj_t **ret); 531 532 void 533 cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj); 534 535 isc_result_t 536 cfg_parse_percentage(cfg_parser_t *pctx, const cfg_type_t *type, 537 cfg_obj_t **ret); 538 539 void 540 cfg_print_percentage(cfg_printer_t *pctx, const cfg_obj_t *obj); 541 542 isc_result_t 543 cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 544 545 void 546 cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj); 547 548 isc_result_t 549 cfg_parse_duration_or_unlimited(cfg_parser_t *pctx, const cfg_type_t *type, 550 cfg_obj_t **ret); 551 552 void 553 cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj); 554 555 isc_result_t 556 cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 557 558 void 559 cfg_print_obj(cfg_printer_t *pctx, const cfg_obj_t *obj); 560 561 void 562 cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type); 563 /*%< 564 * Print a description of the grammar of an arbitrary configuration 565 * type 'type' 566 */ 567 568 void 569 cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type); 570 /*%< 571 * Document the type 'type' as a terminal by printing its 572 * name in angle brackets, e.g., <uint32>. 573 */ 574 575 void 576 cfg_parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) 577 ISC_FORMAT_PRINTF(3, 4); 578 /*! 579 * Pass one of these flags to cfg_parser_error() to include the 580 * token text in log message. 581 */ 582 #define CFG_LOG_NEAR 0x00000001 /*%< Say "near <token>" */ 583 #define CFG_LOG_BEFORE 0x00000002 /*%< Say "before <token>" */ 584 #define CFG_LOG_NOPREP 0x00000004 /*%< Say just "<token>" */ 585 586 void 587 cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) 588 ISC_FORMAT_PRINTF(3, 4); 589 590 bool 591 cfg_is_enum(const char *s, const char *const *enums); 592 /*%< Return true iff the string 's' is one of the strings in 'enums' */ 593 594 bool 595 cfg_clause_validforzone(const char *name, unsigned int ztype); 596 /*%< 597 * Check whether an option is legal for the specified zone type. 598 */ 599 600 void 601 cfg_print_zonegrammar(const unsigned int zonetype, unsigned int flags, 602 void (*f)(void *closure, const char *text, int textlen), 603 void *closure); 604 /*%< 605 * Print a summary of the grammar of the zone type represented by 606 * 'zonetype'. 607 */ 608 609 void 610 cfg_print_clauseflags(cfg_printer_t *pctx, unsigned int flags); 611 /*%< 612 * Print clause flags (e.g. "obsolete", "not implemented", etc) in 613 * human readable form 614 */ 615 616 void 617 cfg_print_indent(cfg_printer_t *pctx); 618 /*%< 619 * Print the necessary indent required by the current settings of 'pctx'. 620 */ 621 622 #endif /* ISCCFG_GRAMMAR_H */ 623