X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=userv.git;a=blobdiff_plain;f=lexer.l.m4;h=0b7e705f8f521ea57f2d3c84a7c65c27bcdbaad0;hp=2f9dee60b895b0c22ffa28118a4bb9170e9b5a07;hb=a038503244f2a71833bd8a6c2d6bdd73d4aea416;hpb=703b99b834625829d6b285e5bca619475ef54511 diff --git a/lexer.l.m4 b/lexer.l.m4 index 2f9dee6..0b7e705 100644 --- a/lexer.l.m4 +++ b/lexer.l.m4 @@ -33,8 +33,10 @@ include(language.i4) #include #include #include +#include #include #include +#include #include "config.h" #include "common.h" @@ -44,24 +46,147 @@ include(language.i4) #define HYPHEN '-' -static int lineno, atnewline, notedreferer; +typedef int directive_fnt(int dtoken); +static directive_fnt df_reject, df_execute, df_executefrompath; +static directive_fnt df_executefromdirectory, df_executebuiltin; +static directive_fnt df_errorstostderr, df_errorstosyslog, df_errorstofile; +static directive_fnt dfg_fdwant, dfg_setflag; +static directive_fnt df_reset, df_cd, df_userrcfile, df_include; +static directive_fnt df_includelookup, df_includedirectory; +static directive_fnt df_message, df_error, df_quit, df_eof; +static directive_fnt df_if, df_catchquit, df_errorspush; +static directive_fnt dfi_includeuserrcfile, dfi_includeclientconfig; +/* directive functions return: + * 0 for success having scanned up to and including end of line but not beyond, + * or tokv_error or tokv_quit. + * They expect to parse the whitespace before their parameters (if any). + */ + +typedef int parmcondition_fnt(int ctoken, char *const *parmvalues, int *rtrue); +static parmcondition_fnt pcf_glob, pcf_range, pcf_grep; +/* all conditional functions return tokv_error for failure or 0 for success + * at parsing and testing, in which case *rtrue is set to 0 or 1. + * On success they have scanned up to and including the condition's + * terminating newline; the pcf_... functions expect to parse the whitespace + * between the parameter name and the condition's arguments. + * Otherwise they return tokv_error. + * The parameter-based conditionals take a list of parameter values + * as obtained from the parameter functions and pa_parameter, + * and do _not_ free it. + */ + +typedef int parameter_fnt(int ptoken, char ***rvalues); +static parameter_fnt pf_service; +static parameter_fnt pf_callinguser, pf_serviceuser; +static parameter_fnt pf_callinggroup, pf_servicegroup; +static parameter_fnt pf_callingusershell, pf_serviceusershell; +/* Parameter functions return tokv_error or 0 for success at parsing + * and determining the value, in which case *rvalues is made to be + * a mallocd null-terminated array of pointers to mallocd strings. + * freeparm can be used to free such an array. + */ + +typedef int builtinserviceparse_fnt(char ***rnewargs); +static builtinserviceparse_fnt bispa_none, bispa_parameter; +/* These parse the arguments to a builtin service, including the + * newline at the end of the line. *rnewargs will initially be + * null, indicating that no arguments are to be set; the function + * may store a mallocd array of mallocd strings in it, + * containing the arguments it wishes to have set (null-pointer + * terminated). + */ + +static int yylex(void); +/* Returns a token (which may be an eof or error exception) */ + +static directive_fnt *lr_dir; +static parmcondition_fnt *lr_parmcond; +static builtinserviceparse_fnt *lr_bispa; +static builtinserviceexec_fnt *lr_bisexec; +static parameter_fnt *lr_parameter; +static int lr_loglevel, lr_logfacility, lr_min, lr_max, *lr_flag; +static int lr_flagval, lr_controlend; +static int lr_fdwant_readwrite; /* -1=never, 0=opt, 1=always */ + +/* Forward declarations of things used in lexer and parser */ + +struct parser_state { + int lineno, reportlineno, notedreferer, isinternal; + const char *filename; + struct stat filestab; + YY_BUFFER_STATE ybuf; + struct parser_state *upstate; +}; + +static struct parser_state *cstate; + +struct error_handling { + int handling; /* One of the error handling modes tokt_ehandlemode */ + int logfacility, loglevel; + int filekeep; /* File is in use by higher-level errors-push, leave it open */ + FILE *file; + char *filename; +}; + +static struct error_handling eh = { tokv_word_errorstostderr, 0,0,0,0,0 }; + static int dequote(char *inplace); + +#define YY_NO_UNPUT + %} + %option noyywrap + %% dnl simple words undivert(3) changequote({*,*}) {* +[0-9]{1,8} { + char *ep; + lr_min=lr_max= (int)strtoul(yytext,&ep,10); + assert(!*ep); + return tokv_ordinal; + } +[0-9]{1,8}-[0-9]{1,8} { + char *ep; + lr_min= (int)strtoul(yytext,&ep,10); + assert(*ep == HYPHEN); + assert(*++ep); + lr_max= (int)strtoul(ep,&ep,10); + assert(!*ep); + if (lr_max < lr_min) { + parseerrprint("fd range has min > max"); + return tokv_error; + } + return tokv_fdrange; + } +[0-9]{1,8}- { + char *ep; + lr_min= (int)strtoul(yytext,&ep,10); + assert(*ep == HYPHEN); + assert(!*++ep); + lr_max=-1; + return tokv_fdstoend; + } [\ \t]+ return tokv_lwsp; -[\ \t]*\n atnewline= 1; lineno++; return tokv_newline; -[\ \t]*\#[^\n]*\n atnewline= 1; lineno++; return tokv_newline; -[\ \t]*\#[^\n]* atnewline= 0; parseerrprint("missing newline at eof after comment"); return tokv_error; -[^\ \t\n]+ atnewline= 0; return tokv_barestring; +[\ \t]*\n cstate->lineno++; return tokv_newline; +[\ \t]*\#[^\n]*\n cstate->lineno++; return tokv_newline; +[\ \t]*\#[^\n]* { + parseerrprint("missing newline at eof after comment"); + return tokv_error; + } +[^\ \t\n]+ return tokv_barestring; +\"([^\\\"\n]|\\[a-z]|\\[0-9]{3}|\\x[0-9A-Fa-f]{2}|\\[:punct:]|\\[ \t]*\n)*\" { + return dequote(yytext); + } +\".* { + parseerrprint("misquoted or unterminated string"); + return tokv_error; + } <> return tokv_eof; -\"([^\\\"\n]|\\[a-z]|\\[0-9]{3}|\\x[0-9a-f]{2}|\\[:punct:]|\\[ \t]*\n)*\" return dequote(yytext); -\".* atnewline= 0; parseerrprint("misquoted or unterminated string"); return tokv_error; *} changequote(`,') %% @@ -70,4 +195,3 @@ changequote(`,') ' divert(-1) undivert -