Add quoted strings capability in list values, no special chars
authorlum <lum@openbsd.org>
Sun, 21 Mar 2021 12:56:16 +0000 (12:56 +0000)
committerlum <lum@openbsd.org>
Sun, 21 Mar 2021 12:56:16 +0000 (12:56 +0000)
detection in between them though.  Add limitation to characters
allowed in symbol names, equivalent to mg function names (A-Za-z-),
quite restrictive but can grow of course. If value is not quoted and
is not a variable, give an error.

usr.bin/mg/def.h
usr.bin/mg/extend.c
usr.bin/mg/interpreter.c

index 7b7d900..0c436ef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: def.h,v 1.169 2021/03/20 09:00:49 lum Exp $   */
+/*     $OpenBSD: def.h,v 1.170 2021/03/21 12:56:16 lum Exp $   */
 
 /* This file is in the public domain. */
 
@@ -721,7 +721,7 @@ void                 dobeep(void);
 
 /* interpreter.c */
 int             foundparen(char *);
-int             clearvars(void);
+void            cleanup(void);
 
 /*
  * Externals.
index 4cb08fe..31c7f37 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extend.c,v 1.72 2021/03/01 10:51:14 lum Exp $ */
+/*     $OpenBSD: extend.c,v 1.73 2021/03/21 12:56:16 lum Exp $ */
 /* This file is in the public domain. */
 
 /*
@@ -606,11 +606,11 @@ evalbuffer(int f, int n)
                /* make sure it's terminated */
                excbuf[llength(lp)] = '\0';
                if ((s = excline(excbuf)) != TRUE) {
-                       (void) clearvars();
+                       cleanup();
                        return (s);
                }
        }
-       (void) clearvars();
+       cleanup();
        return (TRUE);
 }
 
index 3fb6450..4a156e0 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: interpreter.c,v 1.10 2021/03/20 19:39:30 lum Exp $   */
+/*      $OpenBSD: interpreter.c,v 1.11 2021/03/21 12:56:16 lum Exp $   */
 /*
  * This file is in the public domain.
  *
  * like:
  * 
  * 1. Give multiple arguments to a function that usually would accept only one:
- * (find-file a.txt b.txt. c.txt)
+ * (find-file "a.txt" "b.txt" "c.txt")
  *
  * 2. Define a single value variable:
- * (define myfile d.txt)
+ * (define myfile "d.txt")
  *
  * 3. Define a list:
- * (define myfiles(list e.txt f.txt))
+ * (define myfiles(list "e.txt" "f.txt"))
  *
  * 4. Use the previously defined variable or list:
  * (find-file myfiles)
  * 1. multiline parsing - currently only single lines supported.
  * 2. parsing for '(' and ')' throughout whole string and evaluate correctly.
  * 3. conditional execution.
- * 4. deal with quotes around a string: "x x"
- * 5. oh so many things....
+ * 4. deal with special characters in a string: "x\" x" etc
+ * 5. do symbol names need more complex regex patterns? A-Za-z- at the moment. 
+ * 6. oh so many things....
  * [...]
  * n. implement user definable functions.
+ * 
  */
 #include <sys/queue.h>
 #include <regex.h>
@@ -95,8 +97,9 @@ foundparen(char *funstr)
        char            *p, *valp, *endp = NULL, *regs;
        char             expbuf[BUFSIZE], tmpbuf[BUFSIZE];
        int              ret, pctr, fndstart, expctr, blkid, fndchr, fndend;
+       int              inquote;
 
-       pctr = fndstart = expctr = fndchr = fndend = 0;
+       pctr = fndstart = expctr = fndchr = fndend = inquote = 0;
        blkid = 1;
        /*
         * Check for blocks of code with opening and closing ().
@@ -116,7 +119,8 @@ foundparen(char *funstr)
                return(dobeep_msg("Empty lists not supported at moment"));
        regs = "[(]+[\t ]*[(]+";
         if (doregex(regs, funstr))
-               return(dobeep_msg("Multiple left parantheses found"));
+               return(dobeep_msg("Multiple consecutive left parantheses "\
+                   "found."));
        /*
         * load expressions into a list called 'expentry', to be processd
         * when all are obtained.
@@ -131,11 +135,16 @@ foundparen(char *funstr)
                                else
                                        *endp = '\0';
                                e1->par2 = 1;
-                               if ((e1->exp = strndup(valp, BUFSIZE)) == NULL)
+                               if ((e1->exp = strndup(valp, BUFSIZE)) ==
+                                   NULL) {
+                                       cleanup();
                                        return(dobeep_msg("strndup error"));
+                               }
                        }
-                       if ((e1 = malloc(sizeof(struct expentry))) == NULL)
+                       if ((e1 = malloc(sizeof(struct expentry))) == NULL) {
+                               cleanup();
                                        return (dobeep_msg("malloc Error"));
+                       }
                                SLIST_INSERT_HEAD(&exphead, e1, eentry);
                        e1->exp = NULL;
                                e1->expctr = ++expctr;
@@ -147,12 +156,19 @@ foundparen(char *funstr)
                        endp = NULL;
                        pctr++;
                } else if (*p == ')') {
+                       if (inquote == 1) {
+                               cleanup();
+                               return(dobeep_msg("Opening and closing quote "\
+                                   "char error"));
+                       }
                        if (endp == NULL)
                                *p = '\0';
                        else
                                *endp = '\0';
-                       if ((e1->exp = strndup(valp, BUFSIZE)) == NULL)
+                       if ((e1->exp = strndup(valp, BUFSIZE)) == NULL) {
+                               cleanup();
                                return(dobeep_msg("strndup error"));
+                       }
                        fndstart = 0;
                        pctr--;
                } else if (*p != ' ' && *p != '\t') {
@@ -160,6 +176,12 @@ foundparen(char *funstr)
                                valp = p;
                                fndchr = 1;
                        }
+                       if (*p == '"') {
+                               if (inquote == 0)
+                                       inquote = 1;
+                               else
+                                       inquote = 0;
+                       }
                        fndend = 0;
                        endp = NULL;
                } else if (fndend == 0 && (*p == ' ' || *p == '\t')) {
@@ -167,18 +189,23 @@ foundparen(char *funstr)
                        fndend = 1;
                        endp = p;
                } else if (*p == '\t') /* need to check not between "" */
-                       *p = ' ';
+                       if (inquote == 0)
+                               *p = ' ';
                if (pctr == 0)
                        blkid++;
                p++;
        }
-       expbuf[0] = tmpbuf[0] = '\0';
 
+       if (pctr != 0) {
+               cleanup();
+               return(dobeep_msg("Opening and closing parentheses error"));
+       }
        /*
         * Join expressions together for the moment, to progess.
         * This needs to be totally redone and
         * iterate in-to-out, evaluating as we go. Eventually.
         */
+       expbuf[0] = tmpbuf[0] = '\0';
        SLIST_FOREACH(e1, &exphead, eentry) {
                if (strlcpy(tmpbuf, expbuf, sizeof(tmpbuf)) >= sizeof(tmpbuf))
                        return (dobeep_msg("strlcpy error"));
@@ -195,19 +222,20 @@ foundparen(char *funstr)
                mglog_misc("exp|%s|\n", e1->exp);
 #endif
        }
-       if (pctr != 0) {
-               clearexp();
-               return(dobeep_msg("Opening and closing parentheses error"));
-       }
        
        ret = parseexp(expbuf);
-       clearexp();
+       if (ret == FALSE)
+               cleanup();
+       else
+               clearexp();     /* leave lists but remove expressions */
 
        return (ret);
 }
 
 /*
- * At the moment, only paring list defines. Much more to do.
+ * At the moment, only parsing list defines. Much more to do.
+ * Also only use basic chars for symbol names like ones found in
+ * mg functions.
  */
 static int
 parseexp(char *funstr)
@@ -216,19 +244,19 @@ parseexp(char *funstr)
 
         /* Does the line have a list 'define' like: */
         /* (define alist(list 1 2 3 4)) */
-        regs = "^define[ ]+.*[ ]+list[ ]+.*[ ]*";
+        regs = "^define[ ]+[A-Za-z-]+[ ]+list[ ]+.*[ ]*";
         if (doregex(regs, funstr))
                 return(foundvar(funstr));
 
         /* Does the line have a incorrect variable 'define' like: */
         /* (define i y z) */
-        regs = "^define[ ]+.*[ ]+.*[ ]+.*$";
+        regs = "^define[ ]+[A-Za-z-]+[ ]+.*[ ]+.*$";
         if (doregex(regs, funstr))
                 return(dobeep_msg("Invalid use of define."));
 
         /* Does the line have a single variable 'define' like: */
         /* (define i 0) */
-        regs = "^define[ ]+.*[ ]+.*$";
+        regs = "^define[ ]+[A-Za-z-]+[ ]+.*$";
         if (doregex(regs, funstr))
                 return(foundvar(funstr));
 
@@ -250,9 +278,11 @@ multiarg(char *funstr)
        char     excbuf[BUFSIZE], argbuf[BUFSIZE];
        char     contbuf[BUFSIZE], varbuf[BUFSIZE];
        char    *cmdp = NULL, *argp, *fendp = NULL, *endp, *p, *v, *s = " ";
+       char    *regs;
        int      spc, numparams, numspc;
-       int      inlist, sizof, fin;
-       
+       int      inlist, sizof, fin, inquote;
+
+       /* mg function name regex */    
         if (doregex("^[A-Za-z-]+$", funstr))
                return(excline(funstr));
 
@@ -277,23 +307,29 @@ multiarg(char *funstr)
                return (dobeep_msg("strlcpy error"));
        argp = argbuf;
        numspc = spc = 1; /* initially fake a space so we find first argument */
-       inlist = fin = 0;
+       inlist = fin = inquote = 0;
 
        for (p = argbuf; *p != '\0'; p++) {
                if (*(p + 1) == '\0')
                        fin = 1;
 
                if (*p != ' ') {
+                       if (*p == '"') {
+                               if (inquote == 1)
+                                       inquote = 0;    
+                               else
+                                       inquote = 1;
+                       }
                        if (spc == 1)
                                argp = p;
                        spc = 0;
                }
-               if (*p == ' ' || fin) {
+               if ((*p == ' ' && inquote == 0) || fin) {
                        if (spc == 1)
                                continue;
 
                        if (*p == ' ') {
-                               *p = '\0';      /* terminate arg string */
+                               *p = '\0';              /* terminate arg string */
                        }
                        endp = p + 1;
                        excbuf[0] = '\0';
@@ -301,7 +337,10 @@ multiarg(char *funstr)
                        contbuf[0] = '\0';                      
                        sizof = sizeof(varbuf);
                        v = varbuf;
-                       if (isvar(&argp, &v, sizof)) {
+                       regs = "[\"]+.*[\"]+";
+                               if (doregex(regs, argp))
+                               ;                       /* found quotes */
+                       else if (isvar(&argp, &v, sizof)) {
                                (void)(strlcat(varbuf, " ",
                                     sizof) >= sizof);
 
@@ -312,20 +351,19 @@ multiarg(char *funstr)
 
                                (void)(strlcat(varbuf, contbuf,
                                    sizof) >= sizof);
-
-                               (void)(strlcpy(argbuf, varbuf,
+                               
+                               argbuf[0] = ' ';
+                               argbuf[1] = '\0';
+                               (void)(strlcat(argbuf, varbuf,
                                    sizof) >= sizof);
 
                                p = argp = argbuf;
-                               while (*p != ' ') {
-                                       if (*p == '\0')
-                                               break;
-                                       p++;
-                               }
-                               *p = '\0';
                                spc = 1;
                                fin = 0;
-                       }
+                               continue;
+                       } else
+                               return (dobeep_msgs("Var not found:", argp));
+
                        if (strlcpy(excbuf, cmdp, sizeof(excbuf))
                            >= sizeof(excbuf))
                                return (dobeep_msg("strlcpy error"));
@@ -348,7 +386,6 @@ multiarg(char *funstr)
        return (TRUE);
 }
 
-
 /*
  * Is an item a value or a variable?
  */
@@ -371,7 +408,6 @@ isvar(char **argp, char **varbuf, int sizof)
        return (FALSE);
 }
 
-
 /*
  * The define string _must_ adhere to the regex in parsexp().
  * This is not the correct way to do parsing but it does highlight
@@ -385,8 +421,11 @@ foundvar(char *defstr)
        char            *p, *vnamep, *vendp = NULL, *valp;
        int              spc;
 
+       /* vars names can't start with these. */
+       /* char *spchrs = "+-.#";       */
+
        p = strstr(defstr, " ");        /* move to first ' ' char.    */
-       vnamep = skipwhite(p);          /* find first char of var name. */
+       vnamep = skipwhite(p);          /* find first char of var name. */
        vendp = vnamep;
 
        /* now find the end of the list name */
@@ -455,7 +494,7 @@ foundvar(char *defstr)
  * Finished with buffer evaluation, so clean up any vars.
  * Perhaps keeps them in mg even after use,...
  */
-int
+static int
 clearvars(void)
 {
        struct varentry *v1 = NULL;
@@ -487,6 +526,16 @@ clearexp(void)
        return;
 }
 
+/*
+ * Cleanup before leaving.
+ */
+void
+cleanup(void)
+{
+       clearexp();
+       clearvars();
+}
+
 /*
  * Test a string against a regular expression.
  */