version 1.10, 2021/03/20 19:39:30 |
version 1.11, 2021/03/21 12:56:16 |
|
|
* like: |
* like: |
* |
* |
* 1. Give multiple arguments to a function that usually would accept only one: |
* 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: |
* 2. Define a single value variable: |
* (define myfile d.txt) |
* (define myfile "d.txt") |
* |
* |
* 3. Define a list: |
* 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: |
* 4. Use the previously defined variable or list: |
* (find-file myfiles) |
* (find-file myfiles) |
|
|
* 1. multiline parsing - currently only single lines supported. |
* 1. multiline parsing - currently only single lines supported. |
* 2. parsing for '(' and ')' throughout whole string and evaluate correctly. |
* 2. parsing for '(' and ')' throughout whole string and evaluate correctly. |
* 3. conditional execution. |
* 3. conditional execution. |
* 4. deal with quotes around a string: "x x" |
* 4. deal with special characters in a string: "x\" x" etc |
* 5. oh so many things.... |
* 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. |
* n. implement user definable functions. |
|
* |
*/ |
*/ |
#include <sys/queue.h> |
#include <sys/queue.h> |
#include <regex.h> |
#include <regex.h> |
|
|
char *p, *valp, *endp = NULL, *regs; |
char *p, *valp, *endp = NULL, *regs; |
char expbuf[BUFSIZE], tmpbuf[BUFSIZE]; |
char expbuf[BUFSIZE], tmpbuf[BUFSIZE]; |
int ret, pctr, fndstart, expctr, blkid, fndchr, fndend; |
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; |
blkid = 1; |
/* |
/* |
* Check for blocks of code with opening and closing (). |
* Check for blocks of code with opening and closing (). |
|
|
return(dobeep_msg("Empty lists not supported at moment")); |
return(dobeep_msg("Empty lists not supported at moment")); |
regs = "[(]+[\t ]*[(]+"; |
regs = "[(]+[\t ]*[(]+"; |
if (doregex(regs, funstr)) |
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 |
* load expressions into a list called 'expentry', to be processd |
* when all are obtained. |
* when all are obtained. |
|
|
else |
else |
*endp = '\0'; |
*endp = '\0'; |
e1->par2 = 1; |
e1->par2 = 1; |
if ((e1->exp = strndup(valp, BUFSIZE)) == NULL) |
if ((e1->exp = strndup(valp, BUFSIZE)) == |
|
NULL) { |
|
cleanup(); |
return(dobeep_msg("strndup error")); |
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")); |
return (dobeep_msg("malloc Error")); |
|
} |
SLIST_INSERT_HEAD(&exphead, e1, eentry); |
SLIST_INSERT_HEAD(&exphead, e1, eentry); |
e1->exp = NULL; |
e1->exp = NULL; |
e1->expctr = ++expctr; |
e1->expctr = ++expctr; |
|
|
endp = NULL; |
endp = NULL; |
pctr++; |
pctr++; |
} else if (*p == ')') { |
} else if (*p == ')') { |
|
if (inquote == 1) { |
|
cleanup(); |
|
return(dobeep_msg("Opening and closing quote "\ |
|
"char error")); |
|
} |
if (endp == NULL) |
if (endp == NULL) |
*p = '\0'; |
*p = '\0'; |
else |
else |
*endp = '\0'; |
*endp = '\0'; |
if ((e1->exp = strndup(valp, BUFSIZE)) == NULL) |
if ((e1->exp = strndup(valp, BUFSIZE)) == NULL) { |
|
cleanup(); |
return(dobeep_msg("strndup error")); |
return(dobeep_msg("strndup error")); |
|
} |
fndstart = 0; |
fndstart = 0; |
pctr--; |
pctr--; |
} else if (*p != ' ' && *p != '\t') { |
} else if (*p != ' ' && *p != '\t') { |
|
|
valp = p; |
valp = p; |
fndchr = 1; |
fndchr = 1; |
} |
} |
|
if (*p == '"') { |
|
if (inquote == 0) |
|
inquote = 1; |
|
else |
|
inquote = 0; |
|
} |
fndend = 0; |
fndend = 0; |
endp = NULL; |
endp = NULL; |
} else if (fndend == 0 && (*p == ' ' || *p == '\t')) { |
} else if (fndend == 0 && (*p == ' ' || *p == '\t')) { |
|
|
fndend = 1; |
fndend = 1; |
endp = p; |
endp = p; |
} else if (*p == '\t') /* need to check not between "" */ |
} else if (*p == '\t') /* need to check not between "" */ |
*p = ' '; |
if (inquote == 0) |
|
*p = ' '; |
if (pctr == 0) |
if (pctr == 0) |
blkid++; |
blkid++; |
p++; |
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. |
* Join expressions together for the moment, to progess. |
* This needs to be totally redone and |
* This needs to be totally redone and |
* iterate in-to-out, evaluating as we go. Eventually. |
* iterate in-to-out, evaluating as we go. Eventually. |
*/ |
*/ |
|
expbuf[0] = tmpbuf[0] = '\0'; |
SLIST_FOREACH(e1, &exphead, eentry) { |
SLIST_FOREACH(e1, &exphead, eentry) { |
if (strlcpy(tmpbuf, expbuf, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
if (strlcpy(tmpbuf, expbuf, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
return (dobeep_msg("strlcpy error")); |
return (dobeep_msg("strlcpy error")); |
|
|
mglog_misc("exp|%s|\n", e1->exp); |
mglog_misc("exp|%s|\n", e1->exp); |
#endif |
#endif |
} |
} |
if (pctr != 0) { |
|
clearexp(); |
|
return(dobeep_msg("Opening and closing parentheses error")); |
|
} |
|
|
|
ret = parseexp(expbuf); |
ret = parseexp(expbuf); |
clearexp(); |
if (ret == FALSE) |
|
cleanup(); |
|
else |
|
clearexp(); /* leave lists but remove expressions */ |
|
|
return (ret); |
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 |
static int |
parseexp(char *funstr) |
parseexp(char *funstr) |
|
|
|
|
/* Does the line have a list 'define' like: */ |
/* Does the line have a list 'define' like: */ |
/* (define alist(list 1 2 3 4)) */ |
/* (define alist(list 1 2 3 4)) */ |
regs = "^define[ ]+.*[ ]+list[ ]+.*[ ]*"; |
regs = "^define[ ]+[A-Za-z-]+[ ]+list[ ]+.*[ ]*"; |
if (doregex(regs, funstr)) |
if (doregex(regs, funstr)) |
return(foundvar(funstr)); |
return(foundvar(funstr)); |
|
|
/* Does the line have a incorrect variable 'define' like: */ |
/* Does the line have a incorrect variable 'define' like: */ |
/* (define i y z) */ |
/* (define i y z) */ |
regs = "^define[ ]+.*[ ]+.*[ ]+.*$"; |
regs = "^define[ ]+[A-Za-z-]+[ ]+.*[ ]+.*$"; |
if (doregex(regs, funstr)) |
if (doregex(regs, funstr)) |
return(dobeep_msg("Invalid use of define.")); |
return(dobeep_msg("Invalid use of define.")); |
|
|
/* Does the line have a single variable 'define' like: */ |
/* Does the line have a single variable 'define' like: */ |
/* (define i 0) */ |
/* (define i 0) */ |
regs = "^define[ ]+.*[ ]+.*$"; |
regs = "^define[ ]+[A-Za-z-]+[ ]+.*$"; |
if (doregex(regs, funstr)) |
if (doregex(regs, funstr)) |
return(foundvar(funstr)); |
return(foundvar(funstr)); |
|
|
|
|
char excbuf[BUFSIZE], argbuf[BUFSIZE]; |
char excbuf[BUFSIZE], argbuf[BUFSIZE]; |
char contbuf[BUFSIZE], varbuf[BUFSIZE]; |
char contbuf[BUFSIZE], varbuf[BUFSIZE]; |
char *cmdp = NULL, *argp, *fendp = NULL, *endp, *p, *v, *s = " "; |
char *cmdp = NULL, *argp, *fendp = NULL, *endp, *p, *v, *s = " "; |
|
char *regs; |
int spc, numparams, numspc; |
int spc, numparams, numspc; |
int inlist, sizof, fin; |
int inlist, sizof, fin, inquote; |
|
|
|
/* mg function name regex */ |
if (doregex("^[A-Za-z-]+$", funstr)) |
if (doregex("^[A-Za-z-]+$", funstr)) |
return(excline(funstr)); |
return(excline(funstr)); |
|
|
|
|
return (dobeep_msg("strlcpy error")); |
return (dobeep_msg("strlcpy error")); |
argp = argbuf; |
argp = argbuf; |
numspc = spc = 1; /* initially fake a space so we find first argument */ |
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++) { |
for (p = argbuf; *p != '\0'; p++) { |
if (*(p + 1) == '\0') |
if (*(p + 1) == '\0') |
fin = 1; |
fin = 1; |
|
|
if (*p != ' ') { |
if (*p != ' ') { |
|
if (*p == '"') { |
|
if (inquote == 1) |
|
inquote = 0; |
|
else |
|
inquote = 1; |
|
} |
if (spc == 1) |
if (spc == 1) |
argp = p; |
argp = p; |
spc = 0; |
spc = 0; |
} |
} |
if (*p == ' ' || fin) { |
if ((*p == ' ' && inquote == 0) || fin) { |
if (spc == 1) |
if (spc == 1) |
continue; |
continue; |
|
|
if (*p == ' ') { |
if (*p == ' ') { |
*p = '\0'; /* terminate arg string */ |
*p = '\0'; /* terminate arg string */ |
} |
} |
endp = p + 1; |
endp = p + 1; |
excbuf[0] = '\0'; |
excbuf[0] = '\0'; |
|
|
contbuf[0] = '\0'; |
contbuf[0] = '\0'; |
sizof = sizeof(varbuf); |
sizof = sizeof(varbuf); |
v = varbuf; |
v = varbuf; |
if (isvar(&argp, &v, sizof)) { |
regs = "[\"]+.*[\"]+"; |
|
if (doregex(regs, argp)) |
|
; /* found quotes */ |
|
else if (isvar(&argp, &v, sizof)) { |
(void)(strlcat(varbuf, " ", |
(void)(strlcat(varbuf, " ", |
sizof) >= sizof); |
sizof) >= sizof); |
|
|
|
|
|
|
(void)(strlcat(varbuf, contbuf, |
(void)(strlcat(varbuf, contbuf, |
sizof) >= sizof); |
sizof) >= sizof); |
|
|
(void)(strlcpy(argbuf, varbuf, |
argbuf[0] = ' '; |
|
argbuf[1] = '\0'; |
|
(void)(strlcat(argbuf, varbuf, |
sizof) >= sizof); |
sizof) >= sizof); |
|
|
p = argp = argbuf; |
p = argp = argbuf; |
while (*p != ' ') { |
|
if (*p == '\0') |
|
break; |
|
p++; |
|
} |
|
*p = '\0'; |
|
spc = 1; |
spc = 1; |
fin = 0; |
fin = 0; |
} |
continue; |
|
} else |
|
return (dobeep_msgs("Var not found:", argp)); |
|
|
if (strlcpy(excbuf, cmdp, sizeof(excbuf)) |
if (strlcpy(excbuf, cmdp, sizeof(excbuf)) |
>= sizeof(excbuf)) |
>= sizeof(excbuf)) |
return (dobeep_msg("strlcpy error")); |
return (dobeep_msg("strlcpy error")); |
|
|
return (TRUE); |
return (TRUE); |
} |
} |
|
|
|
|
/* |
/* |
* Is an item a value or a variable? |
* Is an item a value or a variable? |
*/ |
*/ |
|
|
return (FALSE); |
return (FALSE); |
} |
} |
|
|
|
|
/* |
/* |
* The define string _must_ adhere to the regex in parsexp(). |
* The define string _must_ adhere to the regex in parsexp(). |
* This is not the correct way to do parsing but it does highlight |
* This is not the correct way to do parsing but it does highlight |
|
|
char *p, *vnamep, *vendp = NULL, *valp; |
char *p, *vnamep, *vendp = NULL, *valp; |
int spc; |
int spc; |
|
|
|
/* vars names can't start with these. */ |
|
/* char *spchrs = "+-.#"; */ |
|
|
p = strstr(defstr, " "); /* move to first ' ' char. */ |
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; |
vendp = vnamep; |
|
|
/* now find the end of the list name */ |
/* now find the end of the list name */ |
|
|
* Finished with buffer evaluation, so clean up any vars. |
* Finished with buffer evaluation, so clean up any vars. |
* Perhaps keeps them in mg even after use,... |
* Perhaps keeps them in mg even after use,... |
*/ |
*/ |
int |
static int |
clearvars(void) |
clearvars(void) |
{ |
{ |
struct varentry *v1 = NULL; |
struct varentry *v1 = NULL; |
|
|
free(e1); |
free(e1); |
} |
} |
return; |
return; |
|
} |
|
|
|
/* |
|
* Cleanup before leaving. |
|
*/ |
|
void |
|
cleanup(void) |
|
{ |
|
clearexp(); |
|
clearvars(); |
} |
} |
|
|
/* |
/* |