summaryrefslogtreecommitdiff
path: root/usr.bin/mg
diff options
context:
space:
mode:
authorMark Lumsden <lum@cvs.openbsd.org>2021-03-21 12:56:17 +0000
committerMark Lumsden <lum@cvs.openbsd.org>2021-03-21 12:56:17 +0000
commitfcfff489169c028ac61c8e62a03666fd8056e964 (patch)
tree9dddb1d475c76e6b1190c0f00535df9b95466c6a /usr.bin/mg
parentaab02ce60720010e6e0658b748c0a558de545376 (diff)
Add quoted strings capability in list values, no special chars
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.
Diffstat (limited to 'usr.bin/mg')
-rw-r--r--usr.bin/mg/def.h4
-rw-r--r--usr.bin/mg/extend.c6
-rw-r--r--usr.bin/mg/interpreter.c131
3 files changed, 95 insertions, 46 deletions
diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h
index 7b7d90088ec..0c436ef5bc2 100644
--- a/usr.bin/mg/def.h
+++ b/usr.bin/mg/def.h
@@ -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.
diff --git a/usr.bin/mg/extend.c b/usr.bin/mg/extend.c
index 4cb08fea1c0..31c7f378074 100644
--- a/usr.bin/mg/extend.c
+++ b/usr.bin/mg/extend.c
@@ -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);
}
diff --git a/usr.bin/mg/interpreter.c b/usr.bin/mg/interpreter.c
index 3fb64508bea..4a156e0d9a7 100644
--- a/usr.bin/mg/interpreter.c
+++ b/usr.bin/mg/interpreter.c
@@ -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.
*
@@ -20,13 +20,13 @@
* 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)
@@ -35,10 +35,12 @@
* 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;
@@ -488,6 +527,16 @@ clearexp(void)
}
/*
+ * Cleanup before leaving.
+ */
+void
+cleanup(void)
+{
+ clearexp();
+ clearvars();
+}
+
+/*
* Test a string against a regular expression.
*/
static int