chiark / gitweb /
Patch from Peter Benie.
[userv.git] / lexer.l.m4
index 0337686..7be0be0 100644 (file)
@@ -1,7 +1,7 @@
 dnl  userv - lexer.l.m4
 dnl  lexer, passed through m4 with defs from langauge.i4
 /*
- *   Copyright (C)1996-1997 Ian Jackson
+ *   Copyright (C)1996-1997,1999 Ian Jackson
  *  
  *   This is free software; you can redistribute it and/or modify it
  *   under the terms of the GNU General Public License as published by
@@ -33,22 +33,25 @@ 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"
 #include "daemon.h"
 #include "lib.h"
+#include "both.h"
 #include "tokens.h"
 
 #define HYPHEN '-'
 
 typedef int directive_fnt(int dtoken);
 static directive_fnt df_reject, df_execute, df_executefrompath;
-static directive_fnt df_executefromdirectory;
+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 dfg_fdwant, dfg_setflag, dfg_lookupquotemode;
 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;
@@ -57,14 +60,17 @@ 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 **parmvalues, int *rtrue);
+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.
+ *  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.
@@ -81,11 +87,23 @@ static parameter_fnt pf_callingusershell, pf_serviceusershell;
  * 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;
@@ -96,6 +114,7 @@ static int lr_fdwant_readwrite; /* -1=never, 0=opt, 1=always */
 struct parser_state {
   int lineno, reportlineno, notedreferer, isinternal;
   const char *filename;
+  struct stat filestab;
   YY_BUFFER_STATE ybuf;
   struct parser_state *upstate;
 };
@@ -104,7 +123,8 @@ static struct parser_state *cstate;
 
 struct error_handling {
   int handling; /* One of the error handling modes tokt_ehandlemode */
-  int logfacility, loglevel, filekeep;
+  int logfacility, loglevel;
+  int filekeep; /* File is in use by higher-level errors-push, leave it open */
   FILE *file;
   char *filename;
 };
@@ -112,9 +132,15 @@ struct error_handling {
 static struct error_handling eh = { tokv_word_errorstostderr, 0,0,0,0,0 };
 
 static int dequote(char *inplace);
+static void countnewlines(void);
+
+#define YY_NO_INPUT
 
 %}
+
 %option noyywrap
+%option nounput
+
 %%
 
 dnl simple words
@@ -129,47 +155,47 @@ changequote({*,*})
                        }
 [0-9]{1,8}-[0-9]{1,8}  {
                          char *ep;
-                         lr_min=(int)strtoul(yytext,&ep,10);
+                         lr_min= (int)strtoul(yytext,&ep,10);
                          assert(*ep == HYPHEN);
-                         assert(*++ep);
-                         lr_max=(int)strtoul(ep,&ep,10);
+                         ep++;  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;
-                         }
+                         if (lr_max < lr_min)
+                           return parseerrprint("fd range has min > max");
                          return tokv_fdrange;
                        }
 [0-9]{1,8}-            {
                          char *ep;
                          lr_min= (int)strtoul(yytext,&ep,10);
                          assert(*ep == HYPHEN);
-                         assert(!*++ep);
+                         ep++;  assert(!*ep);
                          lr_max=-1;
                          return tokv_fdstoend;
                        }
-[\ \t]+                        return tokv_lwsp;
+([\ \t]*\\[\ \t]*\n[\ \t]*)+   countnewlines(); return tokv_lwsp;
+[\ \t]+                                return tokv_lwsp;
 [\ \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)*\" {
+[\ \t]*\#[^\n]*                return parseerrprint("missing newline at eof after comment");
+\"([^\\\"\n]|\\[a-z]|\\[0-9]{3}|\\x[0-9A-Fa-f]{2}|\\[[:punct:]]|\\[ \t]*\n)*\" {
+                         countnewlines();
                          return dequote(yytext);
                        }
-\".*                   {
-                         parseerrprint("misquoted or unterminated string");
-                         return tokv_error;
-                       }
-<<EOF>>                        return tokv_eof;
+[^\ \t\n\\\"]+         return tokv_barestring;
+<<EOF>>                        return tokv_eof;
+\"                     return parseerrprint("misquoted or unterminated string");
+\\                     return parseerrprint("unexpected backslash");
+.                      abort(); /* expect lex warning "rule cannot be matched" */
 *}
 changequote(`,')
 %%
+
+const char *const builtinservicehelpstrings[]= {
+undivert(5)dnl
+   0
+};
 `
 #include "parser.c"
 '
 divert(-1)
 undivert
-