chiark / gitweb /
Only retry connect on EINTR.
[userv.git] / lexer.l.m4
index 2f9dee60b895b0c22ffa28118a4bb9170e9b5a07..0b7e705f8f521ea57f2d3c84a7c65c27bcdbaad0 100644 (file)
@@ -33,8 +33,10 @@ include(language.i4)
 #include <fnmatch.h>
 #include <limits.h>
 #include <dirent.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <time.h>
+#include <errno.h>
 
 #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;
+                       }
 <<EOF>>                        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
-