1238106Sdes%{ 2238106Sdes/* 3238106Sdes * configlexer.lex - lexical analyzer for unbound config file 4238106Sdes * 5238106Sdes * Copyright (c) 2001-2006, NLnet Labs. All rights reserved 6238106Sdes * 7238106Sdes * See LICENSE for the license. 8238106Sdes * 9238106Sdes */ 10238106Sdes 11269257Sdes#include "config.h" 12269257Sdes 13238106Sdes#include <ctype.h> 14238106Sdes#include <string.h> 15238106Sdes#include <strings.h> 16249141Sdes#ifdef HAVE_GLOB_H 17249141Sdes# include <glob.h> 18249141Sdes#endif 19238106Sdes 20238106Sdes#include "util/config_file.h" 21269257Sdes#include "configparser.h" 22238106Sdesvoid ub_c_error(const char *message); 23238106Sdes 24238106Sdes#if 0 25238106Sdes#define LEXOUT(s) printf s /* used ONLY when debugging */ 26238106Sdes#else 27238106Sdes#define LEXOUT(s) 28238106Sdes#endif 29238106Sdes 30238106Sdes/** avoid warning in about fwrite return value */ 31269257Sdes#define ECHO ub_c_error_msg("syntax error at text: %s", ub_c_text) 32238106Sdes 33238106Sdes/** A parser variable, this is a statement in the config file which is 34238106Sdes * of the form variable: value1 value2 ... nargs is the number of values. */ 35238106Sdes#define YDVAR(nargs, var) \ 36238106Sdes num_args=(nargs); \ 37269257Sdes LEXOUT(("v(%s%d) ", ub_c_text, num_args)); \ 38238106Sdes if(num_args > 0) { BEGIN(val); } \ 39238106Sdes return (var); 40238106Sdes 41238106Sdesstruct inc_state { 42238106Sdes char* filename; 43238106Sdes int line; 44269257Sdes YY_BUFFER_STATE buffer; 45269257Sdes struct inc_state* next; 46238106Sdes}; 47269257Sdesstatic struct inc_state* config_include_stack = NULL; 48269257Sdesstatic int inc_depth = 0; 49238106Sdesstatic int inc_prev = 0; 50238106Sdesstatic int num_args = 0; 51238106Sdes 52269257Sdesvoid init_cfg_parse(void) 53269257Sdes{ 54269257Sdes config_include_stack = NULL; 55269257Sdes inc_depth = 0; 56269257Sdes inc_prev = 0; 57269257Sdes num_args = 0; 58269257Sdes} 59249141Sdes 60238106Sdesstatic void config_start_include(const char* filename) 61238106Sdes{ 62238106Sdes FILE *input; 63269257Sdes struct inc_state* s; 64269257Sdes char* nm; 65269257Sdes if(inc_depth++ > 100000) { 66269257Sdes ub_c_error_msg("too many include files"); 67269257Sdes return; 68269257Sdes } 69238106Sdes if(strlen(filename) == 0) { 70238106Sdes ub_c_error_msg("empty include file name"); 71238106Sdes return; 72238106Sdes } 73269257Sdes s = (struct inc_state*)malloc(sizeof(*s)); 74269257Sdes if(!s) { 75269257Sdes ub_c_error_msg("include %s: malloc failure", filename); 76238106Sdes return; 77238106Sdes } 78238106Sdes if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, 79238106Sdes strlen(cfg_parser->chroot)) == 0) { 80238106Sdes filename += strlen(cfg_parser->chroot); 81238106Sdes } 82269257Sdes nm = strdup(filename); 83269257Sdes if(!nm) { 84269257Sdes ub_c_error_msg("include %s: strdup failure", filename); 85269257Sdes free(s); 86269257Sdes return; 87269257Sdes } 88238106Sdes input = fopen(filename, "r"); 89238106Sdes if(!input) { 90238106Sdes ub_c_error_msg("cannot open include file '%s': %s", 91238106Sdes filename, strerror(errno)); 92269257Sdes free(s); 93269257Sdes free(nm); 94238106Sdes return; 95238106Sdes } 96269257Sdes LEXOUT(("switch_to_include_file(%s)\n", filename)); 97269257Sdes s->filename = cfg_parser->filename; 98269257Sdes s->line = cfg_parser->line; 99269257Sdes s->buffer = YY_CURRENT_BUFFER; 100269257Sdes s->next = config_include_stack; 101269257Sdes config_include_stack = s; 102269257Sdes cfg_parser->filename = nm; 103238106Sdes cfg_parser->line = 1; 104238106Sdes yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE)); 105238106Sdes} 106238106Sdes 107249141Sdesstatic void config_start_include_glob(const char* filename) 108249141Sdes{ 109249141Sdes 110249141Sdes /* check for wildcards */ 111249141Sdes#ifdef HAVE_GLOB 112249141Sdes glob_t g; 113249141Sdes size_t i; 114249141Sdes int r, flags; 115249141Sdes if(!(!strchr(filename, '*') && !strchr(filename, '?') && !strchr(filename, '[') && 116249141Sdes !strchr(filename, '{') && !strchr(filename, '~'))) { 117249141Sdes flags = 0 118249141Sdes#ifdef GLOB_ERR 119249141Sdes | GLOB_ERR 120249141Sdes#endif 121249141Sdes#ifdef GLOB_NOSORT 122249141Sdes | GLOB_NOSORT 123249141Sdes#endif 124249141Sdes#ifdef GLOB_BRACE 125249141Sdes | GLOB_BRACE 126249141Sdes#endif 127249141Sdes#ifdef GLOB_TILDE 128249141Sdes | GLOB_TILDE 129249141Sdes#endif 130249141Sdes ; 131249141Sdes memset(&g, 0, sizeof(g)); 132249141Sdes r = glob(filename, flags, NULL, &g); 133249141Sdes if(r) { 134249141Sdes /* some error */ 135249141Sdes globfree(&g); 136269257Sdes if(r == GLOB_NOMATCH) 137269257Sdes return; /* no matches for pattern */ 138249141Sdes config_start_include(filename); /* let original deal with it */ 139249141Sdes return; 140249141Sdes } 141249141Sdes /* process files found, if any */ 142249141Sdes for(i=0; i<(size_t)g.gl_pathc; i++) { 143249141Sdes config_start_include(g.gl_pathv[i]); 144249141Sdes } 145249141Sdes globfree(&g); 146249141Sdes return; 147249141Sdes } 148249141Sdes#endif /* HAVE_GLOB */ 149249141Sdes 150249141Sdes config_start_include(filename); 151249141Sdes} 152249141Sdes 153238106Sdesstatic void config_end_include(void) 154238106Sdes{ 155269257Sdes struct inc_state* s = config_include_stack; 156269257Sdes --inc_depth; 157269257Sdes if(!s) return; 158238106Sdes free(cfg_parser->filename); 159269257Sdes cfg_parser->filename = s->filename; 160269257Sdes cfg_parser->line = s->line; 161238106Sdes yy_delete_buffer(YY_CURRENT_BUFFER); 162269257Sdes yy_switch_to_buffer(s->buffer); 163269257Sdes config_include_stack = s->next; 164269257Sdes free(s); 165238106Sdes} 166238106Sdes 167238106Sdes#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ 168238106Sdes#define yy_set_bol(at_bol) \ 169238106Sdes { \ 170238106Sdes if ( ! yy_current_buffer ) \ 171269257Sdes yy_current_buffer = yy_create_buffer( ub_c_in, YY_BUF_SIZE ); \ 172238106Sdes yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ 173238106Sdes } 174238106Sdes#endif 175238106Sdes 176238106Sdes%} 177238106Sdes%option noinput 178238106Sdes%option nounput 179238106Sdes%{ 180238106Sdes#ifndef YY_NO_UNPUT 181238106Sdes#define YY_NO_UNPUT 1 182238106Sdes#endif 183238106Sdes#ifndef YY_NO_INPUT 184238106Sdes#define YY_NO_INPUT 1 185238106Sdes#endif 186238106Sdes%} 187238106Sdes 188238106SdesSPACE [ \t] 189238106SdesLETTER [a-zA-Z] 190238106SdesUNQUOTEDLETTER [^\'\"\n\r \t\\]|\\. 191238106SdesUNQUOTEDLETTER_NOCOLON [^\:\'\"\n\r \t\\]|\\. 192238106SdesNEWLINE [\r\n] 193238106SdesCOMMENT \# 194238106SdesCOLON \: 195238106SdesDQANY [^\"\n\r\\]|\\. 196238106SdesSQANY [^\'\n\r\\]|\\. 197238106Sdes 198238106Sdes%x quotedstring singlequotedstr include include_quoted val 199238106Sdes 200238106Sdes%% 201238106Sdes<INITIAL,val>{SPACE}* { 202238106Sdes LEXOUT(("SP ")); /* ignore */ } 203238106Sdes<INITIAL,val>{SPACE}*{COMMENT}.* { 204238106Sdes /* note that flex makes the longest match and '.' is any but not nl */ 205269257Sdes LEXOUT(("comment(%s) ", ub_c_text)); /* ignore */ } 206238106Sdesserver{COLON} { YDVAR(0, VAR_SERVER) } 207238106Sdesnum-threads{COLON} { YDVAR(1, VAR_NUM_THREADS) } 208238106Sdesverbosity{COLON} { YDVAR(1, VAR_VERBOSITY) } 209238106Sdesport{COLON} { YDVAR(1, VAR_PORT) } 210238106Sdesoutgoing-range{COLON} { YDVAR(1, VAR_OUTGOING_RANGE) } 211238106Sdesoutgoing-port-permit{COLON} { YDVAR(1, VAR_OUTGOING_PORT_PERMIT) } 212238106Sdesoutgoing-port-avoid{COLON} { YDVAR(1, VAR_OUTGOING_PORT_AVOID) } 213238106Sdesoutgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) } 214238106Sdesincoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) } 215238106Sdesdo-ip4{COLON} { YDVAR(1, VAR_DO_IP4) } 216238106Sdesdo-ip6{COLON} { YDVAR(1, VAR_DO_IP6) } 217238106Sdesdo-udp{COLON} { YDVAR(1, VAR_DO_UDP) } 218238106Sdesdo-tcp{COLON} { YDVAR(1, VAR_DO_TCP) } 219238106Sdestcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) } 220238106Sdesssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } 221238106Sdesssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) } 222238106Sdesssl-service-pem{COLON} { YDVAR(1, VAR_SSL_SERVICE_PEM) } 223238106Sdesssl-port{COLON} { YDVAR(1, VAR_SSL_PORT) } 224238106Sdesdo-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) } 225238106Sdesinterface{COLON} { YDVAR(1, VAR_INTERFACE) } 226269257Sdesip-address{COLON} { YDVAR(1, VAR_INTERFACE) } 227238106Sdesoutgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) } 228238106Sdesinterface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) } 229238106Sdesso-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) } 230238106Sdesso-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) } 231269257Sdesso-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) } 232238106Sdeschroot{COLON} { YDVAR(1, VAR_CHROOT) } 233238106Sdesusername{COLON} { YDVAR(1, VAR_USERNAME) } 234238106Sdesdirectory{COLON} { YDVAR(1, VAR_DIRECTORY) } 235238106Sdeslogfile{COLON} { YDVAR(1, VAR_LOGFILE) } 236238106Sdespidfile{COLON} { YDVAR(1, VAR_PIDFILE) } 237238106Sdesroot-hints{COLON} { YDVAR(1, VAR_ROOT_HINTS) } 238238106Sdesedns-buffer-size{COLON} { YDVAR(1, VAR_EDNS_BUFFER_SIZE) } 239238106Sdesmsg-buffer-size{COLON} { YDVAR(1, VAR_MSG_BUFFER_SIZE) } 240238106Sdesmsg-cache-size{COLON} { YDVAR(1, VAR_MSG_CACHE_SIZE) } 241238106Sdesmsg-cache-slabs{COLON} { YDVAR(1, VAR_MSG_CACHE_SLABS) } 242238106Sdesrrset-cache-size{COLON} { YDVAR(1, VAR_RRSET_CACHE_SIZE) } 243238106Sdesrrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) } 244238106Sdescache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) } 245238106Sdescache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) } 246238106Sdesinfra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) } 247238106Sdesinfra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_TTL) } 248238106Sdesinfra-cache-slabs{COLON} { YDVAR(1, VAR_INFRA_CACHE_SLABS) } 249238106Sdesinfra-cache-numhosts{COLON} { YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) } 250238106Sdesinfra-cache-lame-size{COLON} { YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) } 251238106Sdesnum-queries-per-thread{COLON} { YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) } 252238106Sdesjostle-timeout{COLON} { YDVAR(1, VAR_JOSTLE_TIMEOUT) } 253269257Sdesdelay-close{COLON} { YDVAR(1, VAR_DELAY_CLOSE) } 254238106Sdestarget-fetch-policy{COLON} { YDVAR(1, VAR_TARGET_FETCH_POLICY) } 255238106Sdesharden-short-bufsize{COLON} { YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) } 256238106Sdesharden-large-queries{COLON} { YDVAR(1, VAR_HARDEN_LARGE_QUERIES) } 257238106Sdesharden-glue{COLON} { YDVAR(1, VAR_HARDEN_GLUE) } 258238106Sdesharden-dnssec-stripped{COLON} { YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) } 259238106Sdesharden-below-nxdomain{COLON} { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) } 260238106Sdesharden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) } 261238106Sdesuse-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) } 262238106Sdesunwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) } 263238106Sdesprivate-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) } 264238106Sdesprivate-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) } 265238106Sdesprefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) } 266238106Sdesprefetch{COLON} { YDVAR(1, VAR_PREFETCH) } 267238106Sdesstub-zone{COLON} { YDVAR(0, VAR_STUB_ZONE) } 268238106Sdesname{COLON} { YDVAR(1, VAR_NAME) } 269238106Sdesstub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) } 270238106Sdesstub-host{COLON} { YDVAR(1, VAR_STUB_HOST) } 271238106Sdesstub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) } 272238106Sdesstub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) } 273238106Sdesforward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) } 274238106Sdesforward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) } 275238106Sdesforward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) } 276238106Sdesforward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) } 277238106Sdesdo-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) } 278238106Sdesdo-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) } 279238106Sdesaccess-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) } 280238106Sdeshide-identity{COLON} { YDVAR(1, VAR_HIDE_IDENTITY) } 281238106Sdeshide-version{COLON} { YDVAR(1, VAR_HIDE_VERSION) } 282238106Sdesidentity{COLON} { YDVAR(1, VAR_IDENTITY) } 283238106Sdesversion{COLON} { YDVAR(1, VAR_VERSION) } 284238106Sdesmodule-config{COLON} { YDVAR(1, VAR_MODULE_CONF) } 285238106Sdesdlv-anchor{COLON} { YDVAR(1, VAR_DLV_ANCHOR) } 286238106Sdesdlv-anchor-file{COLON} { YDVAR(1, VAR_DLV_ANCHOR_FILE) } 287238106Sdestrust-anchor-file{COLON} { YDVAR(1, VAR_TRUST_ANCHOR_FILE) } 288238106Sdesauto-trust-anchor-file{COLON} { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) } 289238106Sdestrusted-keys-file{COLON} { YDVAR(1, VAR_TRUSTED_KEYS_FILE) } 290238106Sdestrust-anchor{COLON} { YDVAR(1, VAR_TRUST_ANCHOR) } 291238106Sdesval-override-date{COLON} { YDVAR(1, VAR_VAL_OVERRIDE_DATE) } 292238106Sdesval-sig-skew-min{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } 293238106Sdesval-sig-skew-max{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } 294238106Sdesval-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) } 295238106Sdesval-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } 296238106Sdesval-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } 297238106Sdesignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) } 298238106Sdesval-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) } 299238106Sdeskey-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) } 300238106Sdeskey-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) } 301238106Sdesneg-cache-size{COLON} { YDVAR(1, VAR_NEG_CACHE_SIZE) } 302238106Sdesval-nsec3-keysize-iterations{COLON} { 303238106Sdes YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) } 304238106Sdesadd-holddown{COLON} { YDVAR(1, VAR_ADD_HOLDDOWN) } 305238106Sdesdel-holddown{COLON} { YDVAR(1, VAR_DEL_HOLDDOWN) } 306238106Sdeskeep-missing{COLON} { YDVAR(1, VAR_KEEP_MISSING) } 307238106Sdesuse-syslog{COLON} { YDVAR(1, VAR_USE_SYSLOG) } 308238106Sdeslog-time-ascii{COLON} { YDVAR(1, VAR_LOG_TIME_ASCII) } 309238106Sdeslog-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) } 310238106Sdeslocal-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) } 311238106Sdeslocal-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) } 312238106Sdeslocal-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) } 313269257Sdesunblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) } 314238106Sdesstatistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) } 315238106Sdesstatistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) } 316238106Sdesextended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) } 317238106Sdesremote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) } 318238106Sdescontrol-enable{COLON} { YDVAR(1, VAR_CONTROL_ENABLE) } 319238106Sdescontrol-interface{COLON} { YDVAR(1, VAR_CONTROL_INTERFACE) } 320238106Sdescontrol-port{COLON} { YDVAR(1, VAR_CONTROL_PORT) } 321238106Sdesserver-key-file{COLON} { YDVAR(1, VAR_SERVER_KEY_FILE) } 322238106Sdesserver-cert-file{COLON} { YDVAR(1, VAR_SERVER_CERT_FILE) } 323238106Sdescontrol-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) } 324238106Sdescontrol-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) } 325238106Sdespython-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) } 326238106Sdespython{COLON} { YDVAR(0, VAR_PYTHON) } 327238106Sdesdomain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) } 328238106Sdesminimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) } 329238106Sdesrrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) } 330269257Sdesmax-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) } 331238106Sdes<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } 332238106Sdes 333238106Sdes /* Quoted strings. Strip leading and ending quotes */ 334238106Sdes<val>\" { BEGIN(quotedstring); LEXOUT(("QS ")); } 335238106Sdes<quotedstring><<EOF>> { 336269257Sdes ub_c_error("EOF inside quoted string"); 337238106Sdes if(--num_args == 0) { BEGIN(INITIAL); } 338238106Sdes else { BEGIN(val); } 339238106Sdes} 340269257Sdes<quotedstring>{DQANY}* { LEXOUT(("STR(%s) ", ub_c_text)); yymore(); } 341269257Sdes<quotedstring>{NEWLINE} { ub_c_error("newline inside quoted string, no end \""); 342238106Sdes cfg_parser->line++; BEGIN(INITIAL); } 343238106Sdes<quotedstring>\" { 344238106Sdes LEXOUT(("QE ")); 345238106Sdes if(--num_args == 0) { BEGIN(INITIAL); } 346238106Sdes else { BEGIN(val); } 347269257Sdes ub_c_text[ub_c_leng - 1] = '\0'; 348269257Sdes ub_c_lval.str = strdup(ub_c_text); 349269257Sdes if(!ub_c_lval.str) 350269257Sdes ub_c_error("out of memory"); 351238106Sdes return STRING_ARG; 352238106Sdes} 353238106Sdes 354238106Sdes /* Single Quoted strings. Strip leading and ending quotes */ 355238106Sdes<val>\' { BEGIN(singlequotedstr); LEXOUT(("SQS ")); } 356238106Sdes<singlequotedstr><<EOF>> { 357269257Sdes ub_c_error("EOF inside quoted string"); 358238106Sdes if(--num_args == 0) { BEGIN(INITIAL); } 359238106Sdes else { BEGIN(val); } 360238106Sdes} 361269257Sdes<singlequotedstr>{SQANY}* { LEXOUT(("STR(%s) ", ub_c_text)); yymore(); } 362269257Sdes<singlequotedstr>{NEWLINE} { ub_c_error("newline inside quoted string, no end '"); 363238106Sdes cfg_parser->line++; BEGIN(INITIAL); } 364238106Sdes<singlequotedstr>\' { 365238106Sdes LEXOUT(("SQE ")); 366238106Sdes if(--num_args == 0) { BEGIN(INITIAL); } 367238106Sdes else { BEGIN(val); } 368269257Sdes ub_c_text[ub_c_leng - 1] = '\0'; 369269257Sdes ub_c_lval.str = strdup(ub_c_text); 370269257Sdes if(!ub_c_lval.str) 371269257Sdes ub_c_error("out of memory"); 372238106Sdes return STRING_ARG; 373238106Sdes} 374238106Sdes 375238106Sdes /* include: directive */ 376238106Sdes<INITIAL,val>include{COLON} { 377269257Sdes LEXOUT(("v(%s) ", ub_c_text)); inc_prev = YYSTATE; BEGIN(include); } 378238106Sdes<include><<EOF>> { 379269257Sdes ub_c_error("EOF inside include directive"); 380238106Sdes BEGIN(inc_prev); 381238106Sdes} 382238106Sdes<include>{SPACE}* { LEXOUT(("ISP ")); /* ignore */ } 383238106Sdes<include>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} 384238106Sdes<include>\" { LEXOUT(("IQS ")); BEGIN(include_quoted); } 385238106Sdes<include>{UNQUOTEDLETTER}* { 386269257Sdes LEXOUT(("Iunquotedstr(%s) ", ub_c_text)); 387269257Sdes config_start_include_glob(ub_c_text); 388238106Sdes BEGIN(inc_prev); 389238106Sdes} 390238106Sdes<include_quoted><<EOF>> { 391269257Sdes ub_c_error("EOF inside quoted string"); 392238106Sdes BEGIN(inc_prev); 393238106Sdes} 394269257Sdes<include_quoted>{DQANY}* { LEXOUT(("ISTR(%s) ", ub_c_text)); yymore(); } 395269257Sdes<include_quoted>{NEWLINE} { ub_c_error("newline before \" in include name"); 396238106Sdes cfg_parser->line++; BEGIN(inc_prev); } 397238106Sdes<include_quoted>\" { 398238106Sdes LEXOUT(("IQE ")); 399269257Sdes ub_c_text[ub_c_leng - 1] = '\0'; 400269257Sdes config_start_include_glob(ub_c_text); 401238106Sdes BEGIN(inc_prev); 402238106Sdes} 403238106Sdes<INITIAL,val><<EOF>> { 404269257Sdes LEXOUT(("LEXEOF ")); 405238106Sdes yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ 406269257Sdes if (!config_include_stack) { 407238106Sdes yyterminate(); 408238106Sdes } else { 409269257Sdes fclose(ub_c_in); 410238106Sdes config_end_include(); 411238106Sdes } 412238106Sdes} 413238106Sdes 414269257Sdes<val>{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", ub_c_text)); 415238106Sdes if(--num_args == 0) { BEGIN(INITIAL); } 416269257Sdes ub_c_lval.str = strdup(ub_c_text); return STRING_ARG; } 417238106Sdes 418238106Sdes{UNQUOTEDLETTER_NOCOLON}* { 419269257Sdes ub_c_error_msg("unknown keyword '%s'", ub_c_text); 420238106Sdes } 421238106Sdes 422238106Sdes<*>. { 423269257Sdes ub_c_error_msg("stray '%s'", ub_c_text); 424238106Sdes } 425238106Sdes 426238106Sdes%% 427