dnl  userv - language.i4
dnl  definition of the configuration language, used for tokens.h and lexer.l
dnl
dnl  Copyright (C)1996-1997,1999 Ian Jackson
dnl
dnl  This is free software; you can redistribute it and/or modify it
dnl  under the terms of the GNU General Public License as published by
dnl  the Free Software Foundation; either version 2 of the License, or
dnl  (at your option) any later version.
dnl
dnl  This program is distributed in the hope that it will be useful, but
dnl  WITHOUT ANY WARRANTY; without even the implied warranty of
dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dnl  General Public License for more details.
dnl
dnl  You should have received a copy of the GNU General Public License
dnl  along with userv; if not, write to the Free Software
dnl  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

dnl  Diversions are
dnl   1,2,4: sections of token enum list
dnl   3:     flex rules

divert(-1)

define(`makename',`translit(``$1'',`-_')')

define(`hasvalistype',`pushdef(`odiv',divnum)dnl
divert(1)dnl
  format(``%-50s'',`toki_$1=')`$2',
divert(2)dnl
  format(``%-30s'',`tokv_$1=')`$3|toki_$1',
divert(odiv)popdef(`odiv')')

define(`cautotoki',eval(`0x1'))
define(`cautotokt',eval(`0x1000'))

define(`autovalistype',`hasvalistype(`$1',format(``0x%08x'',cautotoki),`$2')`'define(`cautotoki',incr(cautotoki))')

define(`autovaldeftype',`pushdef(`odiv',divnum)divert(4)dnl
  format(``%-25s'',`tokt_$1=')format(``0x%08x'',cautotokt),
divert(odiv)popdef(`odiv')define(`cautotokt',eval(cautotokt`*2'))')

define(`nametypelexpatexec',`
autovalistype(`$1',`$2')
pushdef(`odiv',divnum)divert(3)dnl
`$3 { $4'`return tokv_$1; }'
divert(odiv)popdef(`odiv')')

define(`wordtypelexexec',
`nametypelexpatexec(`word_'makename(`$1'),`$2|tokr_word',`$1',`$3')')

dnl types
autovaldeftype(`directive')
autovaldeftype(`controlstart')
autovaldeftype(`controlend')
autovaldeftype(`exception')
autovaldeftype(`parmcondition')
autovaldeftype(`condop')
autovaldeftype(`parameter')
autovaldeftype(`number')
autovaldeftype(`fdrange')
autovaldeftype(`logfacility')
autovaldeftype(`loglevel')
autovaldeftype(`readwrite')
autovaldeftype(`string')
autovaldeftype(`execmode')
autovaldeftype(`ehandlemode')
autovaldeftype(`builtinservice')
autovaldeftype(`misc')
autovaldeftype(`internal')

dnl simple isdirectives
define(`isdirectivefn',`dnl
wordtypelexexec(`$1',`tokt_directive$3',`lr_dir= $2; $4')dnl
pushdef(`odiv',divnum)
divert(odiv)popdef(`odiv')')
define(`isdirective',`isdirectivefn(`$1',`df_'makename(`$1'),`$2')')
define(`isdirectiveinternal',`isdirectivefn(`$1',`dfi_'makename(`$1'),
                                            `|tokt_internal$2')')
define(`isexecmode',`isdirective(`$1',`|tokt_execmode')')
define(`isehandlemode',`isdirective(`$1',`|tokt_ehandlemode')')
define(`isfdwant',`isdirectivefn(`$1',`dfg_fdwant',`',
                      `lr_fdwant_readwrite=$2; ')')
define(`isflagpair',`isdirectivefn(`$1',`dfg_setflag',`',
                      `lr_flag= &'makename(`$1')`; lr_flagval= 1; ')
                     isdirectivefn(`no-$1',`dfg_setflag',`',
                      `lr_flag= &'makename(`$1')`; lr_flagval= 0; ')')
dnl `reset' is also a builtin service
isexecmode(`reject')
dnl `execute' is also a builtin service
isexecmode(`execute-from-directory')
isexecmode(`execute-from-path')
isexecmode(`execute-builtin')
isehandlemode(`errors-to-stderr')
isehandlemode(`errors-to-syslog')
isehandlemode(`errors-to-file')
isfdwant(`require-fd',`1')
isfdwant(`allow-fd',`0')
isfdwant(`null-fd',`0')
isfdwant(`reject-fd',`-1')
isfdwant(`ignore-fd',`-1')
isflagpair(`set-environment')
isflagpair(`suppress-args')
isflagpair(`disconnect-hup')
isdirective(`cd')
isdirective(`user-rcfile')
isdirective(`include')
isdirectivefn(`include-ifexist',`df_include')
isdirective(`include-lookup')
isdirectivefn(`include-lookup-all',`df_includelookup')
isdirective(`include-directory')
isdirective(`message')
isdirectivefn(`_include-sysconfig',`df_include',`|tokt_internal')
isdirectiveinternal(`_include-user-rcfile')
isdirectiveinternal(`_include-client-config')

dnl quit and eof are each a directive _and_ an exception
dnl as separate tokens.  A true end of file is returned by yylex
dnl as the exception.  The directive (word) tokens are
dnl tokv_word_{eof,quit}; the exceptions are tokv_{eof,quit}.
isdirective(`quit')
isdirective(`eof')

dnl control construct starters
define(`iscontrolstart',
`isdirective(`$1',`|tokt_controlstart')')
iscontrolstart(`if')
iscontrolstart(`catch-quit')
iscontrolstart(`errors-push')

dnl control construct enders
define(`iscontrolend',
`wordtypelexexec(`$1',`tokt_controlend$3',
                 `lr_controlend= tokv_word_'makename(`$2')`; ')')
iscontrolend(`elif',   `if', `|tokt_controlstart')
iscontrolend(`else',   `if', `|tokt_controlstart')
iscontrolend(`fi',     `if')
iscontrolend(`hctac',  `catch-quit')
iscontrolend(`srorre', `errors-push')

dnl conditions
define(`isparmcondition',`wordtypelexexec(`$1',`tokt_parmcondition',
                           `lr_parmcond= pcf_'makename(`$1')`; ')')
isparmcondition(`glob')
isparmcondition(`range')
isparmcondition(`grep')


define(`builtininlist',`
pushdef(`odiv',divnum)divert(5)dnl
  `"$1$2"',
divert(odiv)popdef(`odiv')')

dnl builtin services
define(`isbuiltinservice',
 `wordtypelexexec(`$1',`tokt_builtinservice$3',
    `lr_bispa= bispa_'makename(`$2')`; lr_bisexec= bisexec_'makename(`$1')`; $5')
  builtininlist(`$1',`$4')')
isbuiltinservice(`environment',`none')
isbuiltinservice(`parameter',`parameter',`',` <parameter>')
isbuiltinservice(`version',`none')
isbuiltinservice(`toplevel',`none')
isbuiltinservice(`override',`none')
isbuiltinservice(`shutdown',`none')

dnl builtin services that are also directive names
define(`isdirectivebuiltinservice',
   `isbuiltinservice(`$1',`$2',`|tokt_directive$3',`$4',
                     `lr_dir= df_'makename(`$1')`; ')')
isdirectivebuiltinservice(`reset',`none')
isdirectivebuiltinservice(`execute',`none',`|tokt_execmode')

isbuiltinservice(`help',`none')

dnl parameters
define(`isparameter',`wordtypelexexec(`$1',`tokt_parameter',
                        `lr_parameter= pf_'makename(`$1')`; ')')
isparameter(`service')
isparameter(`calling-user')
isparameter(`calling-group')
isparameter(`calling-user-shell')
isparameter(`service-user')
isparameter(`service-group')
isparameter(`service-user-shell')

dnl syslog levels
define(`isloglevellexpat',
`nametypelexpatexec(`syslog_$1',`tokt_loglevel|tokr_word',`$2',
                    `lr_loglevel= LOG_'translit(``$1'',`a-z',`A-Z')`; ')')
define(`isloglevel',`isloglevellexpat(`$1',`$1')')
isloglevel(`debug')
isloglevel(`info')
isloglevel(`notice')
isloglevellexpat(`warning',`warn(ing)?')
isloglevel(`err')dnl also the word error, which has dual meaning (below)
isloglevel(`crit')
isloglevel(`alert')
isloglevellexpat(`emerg',`emerg|panic')

dnl syslog facilities
define(`islogfacilitylexpat',
`nametypelexpatexec(`syslog_$1',`tokt_logfacility|tokr_word',`$2',
                    `lr_logfacility= LOG_'translit(``$1'',`a-z',`A-Z')`; ')')
define(`islogfacility',`islogfacilitylexpat(`$1',`$1')')
islogfacilitylexpat(`authpriv',`auth(priv)?|security')
islogfacility(`cron')
islogfacility(`daemon')
islogfacilitylexpat(`kern',`kern(el)?')
islogfacility(`lpr')
islogfacility(`mail')
islogfacility(`news')
islogfacility(`syslog')
islogfacility(`user')
islogfacility(`uucp')
islogfacility(`local0')
islogfacility(`local1')
islogfacility(`local2')
islogfacility(`local3')
islogfacility(`local4')
islogfacility(`local5')
islogfacility(`local6')
islogfacility(`local7')

dnl misc. word-like things
wordtypelexexec(`read',`tokt_readwrite',`')
wordtypelexexec(`write',`tokt_readwrite',`')

dnl small nonnegative integers and fd ranges
dnl some of these have two tokt_ bits set, because they can be several things.
autovalistype(`ordinal',	`tokt_number|tokt_fdrange|tokr_word')
autovalistype(`fdrange',	`tokt_fdrange|tokr_punct')
autovalistype(`fdstoend',	`tokt_fdrange|tokr_punct')
nametypelexpatexec(`dollar',`tokt_misc|tokr_punct',`\$',`')

dnl non-word things
autovalistype(`lwsp',            `tokt_misc|tokr_nonstring')
autovalistype(`newline',         `tokt_misc|tokr_nonstring')
autovalistype(`barestring',      `tokt_string|tokr_string')
autovalistype(`quotedstring',    `tokt_string|tokr_string')

dnl exceptions - NB that there are also tokv_word_{eof,quit}
dnl - see above, near the directives.
autovalistype(`eof',             `tokt_exception|tokr_nonstring')
autovalistype(`quit',            `tokt_exception|tokr_nonstring')
autovalistype(`error',           `tokt_exception|tokr_nonstring')

define(`iscondop',`nametypelexpatexec(`$2',`tokt_condop|tokr_punct',`$1',`')')
iscondop(`\(',`openparen')
iscondop(`\)',`closeparen')
iscondop(`\!',`not')
iscondop(`\&',`and')
iscondop(`\|',`or')

dnl words that could be two things
wordtypelexexec(`error',`tokt_directive|tokt_loglevel',
               `lr_dir= df_error; lr_loglevel= LOG_ERR; ')

divert
