version 1.20, 2021/03/26 12:31:37 |
version 1.21, 2021/04/20 14:26:19 |
|
|
#include "log.h" |
#include "log.h" |
#endif |
#endif |
|
|
static int multiarg(char *); |
static int multiarg(char *, char *, int); |
static int isvar(char **, char **, int); |
static int isvar(char **, char **, int); |
static int foundvar(char *); |
/*static int dofunc(char **, char **, int);*/ |
|
static int founddef(char *, int, int, int); |
|
static int foundlst(char *, int, int); |
|
static int expandvals(char *, char *, char *); |
|
static int foundfun(char *, int); |
static int doregex(char *, char *); |
static int doregex(char *, char *); |
static int parseexp_tmp(char *); |
|
static void clearexp(void); |
static void clearexp(void); |
static int addexp(char *, int, int, int, int); |
static int parse(char *, const char *, const char *, int, int); |
static int exitinterpreter(void); |
static int parsdef(char *, const char *, const char *, int, int); |
|
static int parsval(char *, const char *, const char *, int, int); |
|
static int parsexp(char *, const char *, const char *, int, int); |
|
|
|
static int exitinterpreter(char *, char *, int); |
|
|
TAILQ_HEAD(exphead, expentry) ehead; |
TAILQ_HEAD(exphead, expentry) ehead; |
struct expentry { |
struct expentry { |
TAILQ_ENTRY(expentry) eentry; |
TAILQ_ENTRY(expentry) eentry; |
char *exp; /* The string found between paraenthesis. */ |
char *fun; /* The 1st string found between parens. */ |
int par1; /* Parenthesis at start of string (=1 */ |
char funbuf[BUFSIZE]; |
int par2; /* Parenthesis at end of string )=2 */ |
const char *par1; /* Parenthesis at start of string */ |
|
const char *par2; /* Parenthesis at end of string */ |
int expctr; /* An incremental counter:+1 for each exp */ |
int expctr; /* An incremental counter:+1 for each exp */ |
int blkid; /* Which block are we in? */ |
int blkid; /* Which block are we in? */ |
}; |
}; |
|
|
*/ |
*/ |
struct varentry { |
struct varentry { |
SLIST_ENTRY(varentry) entry; |
SLIST_ENTRY(varentry) entry; |
|
char valbuf[BUFSIZE]; |
char *name; |
char *name; |
char *vals; |
char *vals; |
int count; |
int count; |
|
int expctr; |
|
int blkid; |
}; |
}; |
SLIST_HEAD(vlisthead, varentry) varhead = SLIST_HEAD_INITIALIZER(varhead); |
SLIST_HEAD(vlisthead, varentry) varhead = SLIST_HEAD_INITIALIZER(varhead); |
|
|
|
|
"lambda" |
"lambda" |
}; |
}; |
|
|
|
const char lp = '('; |
|
const char rp = ')'; |
|
char *defnam = NULL; |
|
|
/* |
/* |
* Line has a '(' as the first non-white char. |
* Line has a '(' as the first non-white char. |
|
|
int |
int |
foundparen(char *funstr, int llen) |
foundparen(char *funstr, int llen) |
{ |
{ |
struct expentry *e1 = NULL, *e2 = NULL; |
const char *lrp = NULL; |
char *p, *begp = NULL, *endp = NULL, *regs; |
char *p, *begp = NULL, *endp = NULL, *regs; |
char expbuf[BUFSIZE], tmpbuf[BUFSIZE]; |
|
int i, ret, pctr, expctr, blkid, inquote; |
int i, ret, pctr, expctr, blkid, inquote; |
|
|
pctr = expctr = inquote = 0; |
pctr = expctr = inquote = 0; |
|
|
|
|
for (i = 0; i < llen; ++i, p++) { |
for (i = 0; i < llen; ++i, p++) { |
if (*p == '(') { |
if (*p == '(') { |
|
if (inquote == 1) { |
|
cleanup(); |
|
return(dobeep_msg("Opening and closing quote "\ |
|
"char error")); |
|
} |
if (begp != NULL) { |
if (begp != NULL) { |
if (endp == NULL) |
if (endp == NULL) |
*p = '\0'; |
*p = '\0'; |
else |
else |
*endp = '\0'; |
*endp = '\0'; |
|
|
ret = addexp(begp, 1, 1, blkid, ++expctr); |
ret = parse(begp, lrp, &lp, blkid, ++expctr); |
if (!ret) { |
if (!ret) { |
cleanup(); |
cleanup(); |
return(ret); |
return(ret); |
} |
} |
} |
} |
|
lrp = &lp; |
begp = endp = NULL; |
begp = endp = NULL; |
pctr++; |
pctr++; |
} else if (*p == ')') { |
} else if (*p == ')') { |
|
|
else |
else |
*endp = '\0'; |
*endp = '\0'; |
|
|
ret = addexp(begp, 1, 2, blkid, ++expctr); |
ret = parse(begp, lrp, &rp, blkid, ++expctr); |
if (!ret) { |
if (!ret) { |
cleanup(); |
cleanup(); |
return(ret); |
return(ret); |
} |
} |
} |
} |
|
lrp = &rp; |
begp = endp = NULL; |
begp = endp = NULL; |
pctr--; |
pctr--; |
} else if (*p != ' ' && *p != '\t') { |
} else if (*p != ' ' && *p != '\t') { |
|
|
if (inquote == 0) |
if (inquote == 0) |
*p = ' '; |
*p = ' '; |
|
|
if (pctr == 0) |
if (pctr == 0) { |
blkid++; |
blkid++; |
|
expctr = 0; |
|
defnam = NULL; |
|
} |
} |
} |
|
|
if (pctr != 0) { |
if (pctr != 0) { |
cleanup(); |
cleanup(); |
return(dobeep_msg("Opening and closing parentheses error")); |
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'; |
|
TAILQ_FOREACH_SAFE(e1, &ehead, eentry, e2) { |
|
if (strlcpy(tmpbuf, expbuf, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
|
return (dobeep_msg("strlcpy error")); |
|
expbuf[0] = '\0'; |
|
if (strlcpy(expbuf, e1->exp, sizeof(expbuf)) >= sizeof(expbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
if (*tmpbuf != '\0') |
|
if (strlcat(expbuf, " ", sizeof(expbuf)) >= |
|
sizeof(expbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
if (strlcat(expbuf, tmpbuf, sizeof(expbuf)) >= sizeof(expbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
#ifdef MGLOG |
|
mglog_misc("exp|%s|\n", e1->exp); |
|
#endif |
|
} |
|
|
|
ret = parseexp_tmp(expbuf); |
|
if (ret == FALSE) |
if (ret == FALSE) |
cleanup(); |
cleanup(); |
else |
else |
|
|
|
|
|
|
static int |
static int |
addexp(char *begp, int par1, int par2, int blkid, int expctr) |
parse(char *begp, const char *par1, const char *par2, int blkid, int expctr) |
{ |
{ |
struct expentry *e1 = NULL; |
char *regs; |
|
int ret = FALSE; |
|
|
if ((e1 = malloc(sizeof(struct expentry))) == NULL) { |
if (strncmp(begp, "define", 6) == 0) { |
cleanup(); |
ret = parsdef(begp, par1, par2, blkid, expctr); |
return (dobeep_msg("malloc Error")); |
if (ret == TRUE || ret == FALSE) |
} |
return (ret); |
TAILQ_INSERT_HEAD(&ehead, e1, eentry); |
} else if (strncmp(begp, "list", 4) == 0) |
if ((e1->exp = strndup(begp, BUFSIZE)) == NULL) { |
return(parsval(begp, par1, par2, blkid, expctr)); |
cleanup(); |
|
return(dobeep_msg("strndup error")); |
|
} |
|
e1->expctr = expctr; |
|
e1->blkid = blkid; |
|
/* need to think about these two */ |
|
e1->par1 = par1; |
|
e1->par2 = par2; |
|
|
|
return (TRUE); |
regs = "^exit$"; |
|
if (doregex(regs, begp)) |
|
return(exitinterpreter(NULL, NULL, FALSE)); |
|
|
|
/* mg function name regex */ |
|
regs = "^[A-Za-z-]+$"; |
|
if (doregex(regs, begp)) |
|
return(excline(begp, 0)); |
|
|
|
/* Corner case 1 */ |
|
if (strncmp(begp, "global-set-key ", 15) == 0) |
|
/* function name as 2nd param screws up multiarg. */ |
|
return(excline(begp, 0)); |
|
|
|
/* Corner case 2 */ |
|
if (strncmp(begp, "define-key ", 11) == 0) |
|
/* function name as 3rd param screws up multiarg. */ |
|
return(excline(begp, 0)); |
|
|
|
return (parsexp(begp, par1, par2, blkid, expctr)); |
} |
} |
|
|
/* |
|
* At the moment, use parseexp_tmp in lieu of proper block parsing. |
|
* Move away from this eventually. |
|
*/ |
|
static int |
static int |
parseexp_tmp(char *funstr) |
parsdef(char *begp, const char *par1, const char *par2, int blkid, int expctr) |
{ |
{ |
char *regs; |
char *regs; |
|
|
/* Does the line have a list 'define' like: */ |
if ((defnam == NULL) && (expctr != 1)) |
/* (define alist(list 1 2 3 4)) */ |
return(dobeep_msg("'define' incorrectly used")); |
regs = "^define[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+list[ ]+.*[ ]*"; |
|
if (doregex(regs, funstr)) |
|
return(foundvar(funstr)); |
|
|
|
/* Does the line have a variable 'define' like: */ |
|
/* (define i (function-name j)) */ |
|
regs = "^define[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+[A-Za-z-]+[ ]+.*$"; |
|
if (doregex(regs, 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[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+.*[ ]+.*$"; |
regs = "^define[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+.+[ ]+.+$"; |
if (doregex(regs, funstr)) |
if (doregex(regs, begp)) |
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[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+.*$"; |
regs = "^define[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]+.*$"; |
if (doregex(regs, funstr)) |
if (doregex(regs, begp)) { |
return(foundvar(funstr)); |
if (par1 == &lp && par2 == &rp && expctr == 1) |
|
return(founddef(begp, blkid, expctr, 1)); |
|
return(dobeep_msg("Invalid use of define.")); |
|
} |
|
/* Does the line have '(define i(' */ |
|
regs = "^define[ ]+[A-Za-z][.0-9_A-Z+a-z-]*[ ]*$"; |
|
if (doregex(regs, begp)) { |
|
if (par1 == &lp && par2 == &lp && expctr == 1) |
|
return(founddef(begp, blkid, expctr, 0)); |
|
return(dobeep_msg("Invalid use of 'define'")); |
|
} |
|
/* Does the line have '(define (' */ |
|
regs = "^define$"; |
|
if (doregex(regs, begp)) { |
|
if (par1 == &lp && par2 == &lp && expctr == 1) |
|
return(foundfun(begp, expctr)); |
|
return(dobeep_msg("Invalid use of 'define'.")); |
|
} |
|
|
/* Does the line have an unrecognised 'define' */ |
return (ABORT); |
regs = "^define[\t ]+"; |
} |
if (doregex(regs, funstr)) |
|
return(dobeep_msg("Invalid use of define")); |
|
|
|
/* Exit? */ |
static int |
regs = "^exit$"; |
parsval(char *begp, const char *par1, const char *par2, int blkid, int expctr) |
if (doregex(regs, funstr)) |
{ |
return(exitinterpreter()); |
char *regs; |
|
|
return(multiarg(funstr)); |
/* Does the line have 'list' */ |
|
regs = "^list$"; |
|
if (doregex(regs, begp)) |
|
return(dobeep_msg("Invalid use of list")); |
|
|
|
/* Does the line have a 'list' like: */ |
|
/* (list "a" "b") */ |
|
regs = "^list[ ]+.*$"; |
|
if (doregex(regs, begp)) { |
|
if (expctr == 1) |
|
return(dobeep_msg("list with no-where to go.")); |
|
|
|
if (par1 == &lp && expctr > 1) |
|
return(foundlst(begp, blkid, expctr)); |
|
|
|
return(dobeep_msg("Invalid use of list.")); |
|
} |
|
return (FALSE); |
} |
} |
|
|
/* |
|
* Pass a list of arguments to a function. |
|
*/ |
|
static int |
static int |
multiarg(char *funstr) |
parsexp(char *begp, const char *par1, const char *par2, int blkid, int expctr) |
{ |
{ |
PF funcp; |
struct expentry *e1 = NULL; |
char excbuf[BUFSIZE], argbuf[BUFSIZE]; |
PF funcp; |
char contbuf[BUFSIZE], varbuf[BUFSIZE]; |
char *cmdp, *fendp, *valp, *fname, *funb = NULL;; |
char *cmdp = NULL, *argp, *fendp = NULL, *endp, *p, *v, *s = " "; |
int numparams, ret; |
char *regs; |
|
int spc, numparams, numspc; |
|
int inlist, sizof, fin, inquote; |
|
|
|
/* mg function name regex */ |
cmdp = begp; |
if (doregex("^[A-Za-z-]+$", funstr)) |
|
return(excline(funstr, 0)); |
|
|
|
cmdp = funstr; |
|
fendp = strchr(cmdp, ' '); |
fendp = strchr(cmdp, ' '); |
*fendp = '\0'; |
*fendp = '\0'; |
|
|
/* |
/* |
* If no extant mg command found, just return. |
* If no extant mg command found, just return. |
*/ |
*/ |
|
|
|
|
numparams = numparams_function(funcp); |
numparams = numparams_function(funcp); |
if (numparams == 0) |
if (numparams == 0) |
return (dobeep_msgs("Command takes no arguments: ", cmdp)); |
return (dobeep_msgs("Command takes no arguments:", cmdp)); |
|
|
/* now find the first argument */ |
if ((e1 = malloc(sizeof(struct expentry))) == NULL) { |
p = fendp + 1; |
cleanup(); |
p = skipwhite(p); |
return (dobeep_msg("malloc Error")); |
|
} |
|
TAILQ_INSERT_HEAD(&ehead, e1, eentry); |
|
if ((e1->fun = strndup(cmdp, BUFSIZE)) == NULL) { |
|
cleanup(); |
|
return(dobeep_msg("strndup error")); |
|
} |
|
cmdp = e1->fun; |
|
fname = e1->fun; |
|
e1->funbuf[0] = '\0'; |
|
funb = e1->funbuf; |
|
e1->expctr = expctr; |
|
e1->blkid = blkid; |
|
/* need to think about these two */ |
|
e1->par1 = par1; |
|
e1->par2 = par2; |
|
|
if (strlcpy(argbuf, p, sizeof(argbuf)) >= sizeof(argbuf)) |
*fendp = ' '; |
return (dobeep_msg("strlcpy error")); |
valp = fendp + 1; |
|
|
|
ret = expandvals(cmdp, valp, funb); |
|
if (!ret) |
|
return (ret); |
|
|
|
return (multiarg(fname, funb, numparams)); |
|
} |
|
|
|
/* |
|
* Pass a list of arguments to a function. |
|
*/ |
|
static int |
|
multiarg(char *cmdp, char *argbuf, int numparams) |
|
{ |
|
char excbuf[BUFSIZE]; |
|
char *argp, *p, *s = " "; |
|
char *regs; |
|
int spc, numspc; |
|
int fin, inquote; |
|
|
argp = argbuf; |
argp = argbuf; |
numspc = spc = 1; /* initially fake a space so we find first argument */ |
spc = 1; /* initially fake a space so we find first argument */ |
inlist = fin = inquote = 0; |
numspc = fin = inquote = 0; |
|
|
for (p = argbuf; *p != '\0'; p++) { |
for (p = argbuf; *p != '\0'; p++) { |
if (*(p + 1) == '\0') |
if (*(p + 1) == '\0') |
|
|
inquote = 1; |
inquote = 1; |
} |
} |
if (spc == 1) |
if (spc == 1) |
argp = p; |
if ((numspc % numparams) == 0) { |
|
argp = p; |
|
} |
spc = 0; |
spc = 0; |
} |
} |
if ((*p == ' ' && inquote == 0) || fin) { |
if ((*p == ' ' && inquote == 0) || fin) { |
if (spc == 1) |
if (spc == 1)/* || (numspc % numparams == 0))*/ |
continue; |
continue; |
|
if ((numspc % numparams) != (numparams - 1)) { |
|
numspc++; |
|
continue; |
|
} |
if (*p == ' ') { |
if (*p == ' ') { |
*p = '\0'; /* terminate arg string */ |
*p = '\0'; /* terminate arg string */ |
} |
} |
endp = p + 1; |
|
excbuf[0] = '\0'; |
excbuf[0] = '\0'; |
varbuf[0] = '\0'; |
|
contbuf[0] = '\0'; |
|
sizof = sizeof(varbuf); |
|
v = varbuf; |
|
regs = "[\"]+.*[\"]+"; |
regs = "[\"]+.*[\"]+"; |
if (doregex(regs, argp)) |
|
; /* found quotes */ |
|
else if (isvar(&argp, &v, sizof)) { |
|
(void)(strlcat(varbuf, " ", |
|
sizof) >= sizof); |
|
|
|
*p = ' '; |
if (!doregex(regs, argp)) { |
|
|
(void)(strlcpy(contbuf, endp, |
|
sizeof(contbuf)) >= sizeof(contbuf)); |
|
|
|
(void)(strlcat(varbuf, contbuf, |
|
sizof) >= sizof); |
|
|
|
argbuf[0] = ' '; |
|
argbuf[1] = '\0'; |
|
(void)(strlcat(argbuf, varbuf, |
|
sizof) >= sizof); |
|
|
|
p = argp = argbuf; |
|
spc = 1; |
|
fin = 0; |
|
continue; |
|
} else { |
|
const char *errstr; |
const char *errstr; |
int iters; |
int iters; |
|
|
|
|
break; |
break; |
|
|
*p = ' '; /* unterminate arg string */ |
*p = ' '; /* unterminate arg string */ |
|
numspc++; |
spc = 1; |
spc = 1; |
} |
} |
} |
} |
|
|
#endif |
#endif |
SLIST_FOREACH(v1, &varhead, entry) { |
SLIST_FOREACH(v1, &varhead, entry) { |
if (strcmp(*argp, v1->name) == 0) { |
if (strcmp(*argp, v1->name) == 0) { |
(void)(strlcpy(*varbuf, v1->vals, sizof) >= sizof); |
(void)(strlcpy(*varbuf, v1->valbuf, sizof) >= sizof); |
return (TRUE); |
return (TRUE); |
} |
} |
} |
} |
return (FALSE); |
return (FALSE); |
} |
} |
|
|
|
|
|
static int |
|
foundfun(char *defstr, int expctr) |
|
{ |
|
return (TRUE); |
|
} |
|
|
|
static int |
|
foundlst(char *defstr, int blkid, int expctr) |
|
{ |
|
char *p; |
|
|
|
p = strstr(defstr, " "); |
|
p = skipwhite(p); |
|
expandvals(NULL, p, defnam); |
|
|
|
return (TRUE); |
|
} |
|
|
/* |
/* |
* The define string _must_ adhere to the regex in parsexp(). |
* 'define' strings follow the regex in parsdef(). |
* This is not the correct way to do parsing but it does highlight |
|
* the issues. Also, vars should find their way into one list only. |
|
* Currently they go into two. |
|
*/ |
*/ |
static int |
static int |
foundvar(char *defstr) |
founddef(char *defstr, int blkid, int expctr, int hasval) |
{ |
{ |
struct varentry *vt, *v1 = NULL; |
struct varentry *vt, *v1 = NULL; |
char *p, *vnamep, *vendp = NULL, *valp; |
char *p, *vnamep, *vendp = NULL, *valp; |
char tmpbuf[BUFSIZE]; |
|
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 define/list name */ |
while (1) { |
while (1) { |
++vendp; |
++vendp; |
if (*vendp == ' ') |
if (*vendp == ' ') |
|
|
*vendp = '\0'; |
*vendp = '\0'; |
|
|
/* |
/* |
* Check list name is not an existing function. |
* Check list name is not an existing mg function. |
*/ |
*/ |
if (name_function(vnamep) != NULL) |
if (name_function(vnamep) != NULL) |
return(dobeep_msgs("Variable/function name clash:", vnamep)); |
return(dobeep_msgs("Variable/function name clash:", vnamep)); |
|
|
p = ++vendp; |
|
p = skipwhite(p); |
|
|
|
/* |
|
* Now what have we found? A keyword (e.g list)? A value? |
|
* We only deal with values and a couple of keywords at moment. |
|
*/ |
|
if (strncmp(p, "list ", 5) == 0) { |
|
p = strstr(p, " "); /* find ' ' after 'list'. */ |
|
valp = skipwhite(p); /* find first value */ |
|
} else if (strncmp(p, "get-environment-variable ", 25) == 0) { |
|
const char *t; |
|
char *tmp; |
|
const char *q = "\""; |
|
|
|
p = strstr(p, " "); /* find ' ' after keyword. */ |
|
t = skipwhite(p); /* find first value */ |
|
|
|
if (t[0] == *q || t[strlen(t) - 1] == *q) |
|
return (dobeep_msgs("Please remove '\"' around:", |
|
t)); |
|
if ((tmp = getenv(t)) == NULL || *tmp == '\0') |
|
return(dobeep_msgs("Envar not found:", t)); |
|
/* envar is returned without "" around the string */ |
|
tmpbuf[0] = '\0'; |
|
if (strlcat(tmpbuf, q, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
if (strlcat(tmpbuf, tmp, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
if (strlcat(tmpbuf, q, sizeof(tmpbuf)) >= sizeof(tmpbuf)) |
|
return (dobeep_msg("strlcat error")); |
|
|
|
valp = tmpbuf; |
|
} else |
|
valp = p; |
|
/* |
|
* Now we have the name of the list starting at 'vnamep', |
|
* and the first value is at 'valp', record the details |
|
* in a linked list. But first remove variable, if existing already. |
|
*/ |
|
if (!SLIST_EMPTY(&varhead)) { |
if (!SLIST_EMPTY(&varhead)) { |
SLIST_FOREACH_SAFE(v1, &varhead, entry, vt) { |
SLIST_FOREACH_SAFE(v1, &varhead, entry, vt) { |
if (strcmp(vnamep, v1->name) == 0) |
if (strcmp(vnamep, v1->name) == 0) |
|
|
SLIST_INSERT_HEAD(&varhead, v1, entry); |
SLIST_INSERT_HEAD(&varhead, v1, entry); |
if ((v1->name = strndup(vnamep, BUFSIZE)) == NULL) |
if ((v1->name = strndup(vnamep, BUFSIZE)) == NULL) |
return(dobeep_msg("strndup error")); |
return(dobeep_msg("strndup error")); |
|
vnamep = v1->name; |
v1->count = 0; |
v1->count = 0; |
vendp = NULL; |
v1->expctr = expctr; |
|
v1->blkid = blkid; |
/* initially fake a space so we find first value */ |
v1->vals = NULL; |
spc = 1; |
v1->valbuf[0] = '\0'; |
/* now loop through values in list value string while counting them */ |
|
for (p = valp; *p != '\0'; p++) { |
defnam = v1->valbuf; |
if (*p != ' ' && *p != '\t') { |
|
|
if (hasval) { |
|
valp = skipwhite(vendp + 1); |
|
|
|
expandvals(NULL, valp, defnam); |
|
defnam = NULL; |
|
} |
|
*vendp = ' '; |
|
return (TRUE); |
|
} |
|
|
|
|
|
static int |
|
expandvals(char *cmdp, char *valp, char *bp) |
|
{ |
|
char excbuf[BUFSIZE], argbuf[BUFSIZE]; |
|
char contbuf[BUFSIZE], varbuf[BUFSIZE]; |
|
char *argp, *endp, *p, *v, *s = " "; |
|
char *regs; |
|
int spc, cnt; |
|
int inlist, sizof, fin, inquote; |
|
|
|
/* now find the first argument */ |
|
p = skipwhite(valp); |
|
|
|
if (strlcpy(argbuf, p, sizeof(argbuf)) >= sizeof(argbuf)) |
|
return (dobeep_msg("strlcpy error")); |
|
argp = argbuf; |
|
spc = 1; /* initially fake a space so we find first argument */ |
|
inlist = fin = inquote = cnt = spc = 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) |
if (spc == 1) |
v1->count++; |
argp = p; |
spc = 0; |
spc = 0; |
} |
} |
} |
if ((*p == ' ' && inquote == 0) || fin) { |
if ((v1->vals = strndup(valp, BUFSIZE)) == NULL) |
if (spc == 1) |
return(dobeep_msg("strndup error")); |
continue; |
|
/* terminate arg string */ |
|
if (*p == ' ') { |
|
*p = '\0'; |
|
} |
|
endp = p + 1; |
|
excbuf[0] = '\0'; |
|
varbuf[0] = '\0'; |
|
contbuf[0] = '\0'; |
|
sizof = sizeof(varbuf); |
|
v = varbuf; |
|
regs = "[\"]+.*[\"]+"; |
|
if (doregex(regs, argp)) |
|
; /* found quotes */ |
|
else if (isvar(&argp, &v, sizof)) { |
|
|
|
(void)(strlcat(varbuf, " ", |
|
sizof) >= sizof); |
|
|
|
*p = ' '; |
|
(void)(strlcpy(contbuf, endp, |
|
sizeof(contbuf)) >= sizeof(contbuf)); |
|
|
|
(void)(strlcat(varbuf, contbuf, |
|
sizof) >= sizof); |
|
|
|
argbuf[0] = ' '; |
|
argbuf[1] = '\0'; |
|
(void)(strlcat(argbuf, varbuf, |
|
sizof) >= sizof); |
|
|
|
p = argp = argbuf; |
|
spc = 1; |
|
fin = 0; |
|
continue; |
|
} else { |
|
const char *errstr; |
|
int iters; |
|
|
|
iters = strtonum(argp, 0, INT_MAX, &errstr); |
|
if (errstr != NULL) |
|
return (dobeep_msgs("Var not found:", |
|
argp)); |
|
} |
#ifdef MGLOG |
#ifdef MGLOG |
mglog_misc("var:%s\t#items:%d\tvals:|%s|\n", vnamep, v1->count, v1->vals); |
mglog_misc("x|%s|%p|%d|\n", bp, defnam, BUFSIZE); |
#endif |
#endif |
|
if (*bp != '\0') { |
|
if (strlcat(bp, s, BUFSIZE) >= BUFSIZE) |
|
return (dobeep_msg("strlcat error")); |
|
} |
|
if (strlcat(bp, argp, BUFSIZE) >= BUFSIZE) { |
|
return (dobeep_msg("strlcat error")); |
|
} |
|
/* v1->count++;*/ |
|
|
|
if (fin) |
|
break; |
|
|
|
*p = ' '; /* unterminate arg string */ |
|
spc = 1; |
|
} |
|
} |
return (TRUE); |
return (TRUE); |
} |
} |
|
|
|
|
while (!SLIST_EMPTY(&varhead)) { |
while (!SLIST_EMPTY(&varhead)) { |
v1 = SLIST_FIRST(&varhead); |
v1 = SLIST_FIRST(&varhead); |
SLIST_REMOVE_HEAD(&varhead, entry); |
SLIST_REMOVE_HEAD(&varhead, entry); |
free(v1->vals); |
/* free(v1->vals);*/ |
free(v1->name); |
free(v1->name); |
free(v1); |
free(v1); |
} |
} |
|
|
while (!TAILQ_EMPTY(&ehead)) { |
while (!TAILQ_EMPTY(&ehead)) { |
e1 = TAILQ_FIRST(&ehead); |
e1 = TAILQ_FIRST(&ehead); |
TAILQ_REMOVE(&ehead, e1, eentry); |
TAILQ_REMOVE(&ehead, e1, eentry); |
free(e1->exp); |
free(e1->fun); |
free(e1); |
free(e1); |
} |
} |
return; |
return; |
|
|
void |
void |
cleanup(void) |
cleanup(void) |
{ |
{ |
|
defnam = NULL; |
|
|
clearexp(); |
clearexp(); |
clearvars(); |
clearvars(); |
} |
} |
|
|
* execution. |
* execution. |
*/ |
*/ |
static int |
static int |
exitinterpreter() |
exitinterpreter(char *ptr, char *dobuf, int dosiz) |
{ |
{ |
cleanup(); |
cleanup(); |
if (batch == 0) |
if (batch == 0) |
return(dobeep_msg("Interpreter exited via exit command.")); |
return(dobeep_msg("Interpreter exited via exit command.")); |
return(FALSE); |
return(FALSE); |
} |
} |
|
|
|
/* |
|
* All code below commented out (until end of file). |
|
* |
|
* Need to think about how interpreter functions are done. |
|
* Probably don't have a choice with string-append(). |
|
|
|
static int getenvironmentvariable(char *, char *, int); |
|
static int stringappend(char *, char *, int); |
|
|
|
typedef int (*PFI)(char *, char *, int); |
|
|
|
|
|
struct ifunmap { |
|
PFI fn_funct; |
|
const char *fn_name; |
|
struct ifunmap *fn_next; |
|
}; |
|
static struct ifunmap *ifuns; |
|
|
|
static struct ifunmap ifunctnames[] = { |
|
{exitinterpreter, "exit"}, |
|
{getenvironmentvariable, "get-environment-variable"}, |
|
{stringappend, "string-append"}, |
|
{NULL, NULL} |
|
}; |
|
|
|
void |
|
ifunmap_init(void) |
|
{ |
|
struct ifunmap *fn; |
|
|
|
for (fn = ifunctnames; fn->fn_name != NULL; fn++) { |
|
fn->fn_next = ifuns; |
|
ifuns = fn; |
|
} |
|
} |
|
|
|
PFI |
|
name_ifun(const char *ifname) |
|
{ |
|
struct ifunmap *fn; |
|
|
|
for (fn = ifuns; fn != NULL; fn = fn->fn_next) { |
|
if (strcmp(fn->fn_name, ifname) == 0) |
|
return (fn->fn_funct); |
|
} |
|
|
|
return (NULL); |
|
} |
|
|
|
|
|
int |
|
dofunc(char **ifname, char **tmpbuf, int sizof) |
|
{ |
|
PFI fnc; |
|
char *p, *tmp; |
|
|
|
p = strstr(*ifname, " "); |
|
*p = '\0'; |
|
|
|
fnc = name_ifun(*ifname); |
|
if (fnc == NULL) |
|
return (FALSE); |
|
|
|
*p = ' '; |
|
|
|
tmp = *tmpbuf; |
|
|
|
fnc(p, tmp, sizof); |
|
|
|
return (TRUE); |
|
} |
|
|
|
static int |
|
getenvironmentvariable(char *ptr, char *dobuf, int dosiz) |
|
{ |
|
char *t; |
|
char *tmp; |
|
const char *q = "\""; |
|
|
|
t = skipwhite(ptr); |
|
|
|
if (t[0] == *q || t[strlen(t) - 1] == *q) |
|
return (dobeep_msgs("Please remove '\"' around:", t)); |
|
if ((tmp = getenv(t)) == NULL || *tmp == '\0') |
|
return(dobeep_msgs("Envar not found:", t)); |
|
|
|
dobuf[0] = '\0'; |
|
if (strlcat(dobuf, q, dosiz) >= dosiz) |
|
return (dobeep_msg("strlcat error")); |
|
if (strlcat(dobuf, tmp, dosiz) >= dosiz) |
|
return (dobeep_msg("strlcat error")); |
|
if (strlcat(dobuf, q, dosiz) >= dosiz) |
|
return (dobeep_msg("strlcat error")); |
|
|
|
return (TRUE); |
|
} |
|
|
|
static int |
|
stringappend(char *ptr, char *dobuf, int dosiz) |
|
{ |
|
char varbuf[BUFSIZE], funbuf[BUFSIZE]; |
|
char *p, *f, *v, *vendp; |
|
int sizof, fin = 0; |
|
|
|
varbuf[0] = funbuf[0] = '\0'; |
|
f = funbuf; |
|
v = varbuf; |
|
sizof = sizeof(varbuf); |
|
*dobuf = '\0'; |
|
|
|
p = skipwhite(ptr); |
|
|
|
while (*p != '\0') { |
|
vendp = p; |
|
while (1) { |
|
if (*vendp == ' ') { |
|
break; |
|
} else if (*vendp == '\0') { |
|
fin = 1; |
|
break; |
|
} |
|
++vendp; |
|
} |
|
*vendp = '\0'; |
|
|
|
if (isvar(&p, &v, sizof)) { |
|
if (v[0] == '"' && v[strlen(v) - 1] == '"' ) { |
|
v[strlen(v) - 1] = '\0'; |
|
v = v + 1; |
|
} |
|
if (strlcat(f, v, sizof) >= sizof) |
|
return (dobeep_msg("strlcat error")); |
|
} else { |
|
if (p[0] == '"' && p[strlen(p) - 1] == '"' ) { |
|
p[strlen(p) - 1] = '\0'; |
|
p = p + 1; |
|
} |
|
if (strlcat(f, p, sizof) >= sizof) |
|
return (dobeep_msg("strlcat error")); |
|
} |
|
if (fin) |
|
break; |
|
vendp++; |
|
if (*vendp == '\0') |
|
break; |
|
p = skipwhite(vendp); |
|
} |
|
|
|
(void)snprintf(dobuf, dosiz, "\"%s\"", f); |
|
|
|
return (TRUE); |
|
} |
|
|
|
Index: main.c |
|
=================================================================== |
|
RCS file: /cvs/src/usr.bin/mg/main.c,v |
|
retrieving revision 1.89 |
|
diff -u -p -u -p -r1.89 main.c |
|
--- main.c 20 Mar 2021 09:00:49 -0000 1.89 |
|
+++ main.c 12 Apr 2021 17:58:52 -0000 |
|
@@ -133,10 +133,12 @@ main(int argc, char **argv) |
|
extern void grep_init(void); |
|
extern void cmode_init(void); |
|
extern void dired_init(void); |
|
+ extern void ifunmap_init(void); |
|
|
|
dired_init(); |
|
grep_init(); |
|
cmode_init(); |
|
+ ifunmap_init(); |
|
} |
|
|
|
|
|
*/ |