mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 10:01:11 +02:00
zsh-workers/7976
This commit is contained in:
parent
cf92dbd40b
commit
6f698f634a
11 changed files with 479 additions and 19 deletions
|
@ -78,6 +78,14 @@ short-circuiting, and only one of the latter two expressions in a ternary
|
|||
operator is evaluated. Note the precedence of the bitwise AND, OR,
|
||||
and XOR operators.
|
||||
|
||||
cindex(math functions)
|
||||
cindex(functions, math)
|
||||
Mathematical functions can be called with the syntax
|
||||
`var(func)tt(LPAR())var(args)tt(RPAR())', where the function decides
|
||||
if the var(args) is used as a string or a comma-separated list of
|
||||
arithmetic expressions. The shell currently defines no mathematical
|
||||
functions, but modules may define some.
|
||||
|
||||
An expression of the form `tt(#\)var(x)' where var(x) is any character
|
||||
sequence such as `tt(a)', `tt(^A)', or `tt(\M-\C-x)' gives the ascii
|
||||
value of this character and an expression of the form `tt(#)var(foo)'
|
||||
|
|
|
@ -1259,8 +1259,8 @@ cindex(modules, loading)
|
|||
cindex(loading modules)
|
||||
xitem(tt(zmodload) [ tt(-dL) ] [ ... ])
|
||||
xitem(tt(zmodload -e) [ ... ])
|
||||
xitem(tt(zmodload) [ tt(-a) [ tt(-bcp) [ tt(-I) ] ] ] [ tt(-iL) ] ...)
|
||||
item(tt(zmodload) tt(-u) [ tt(-abcdp) [ tt(-I) ] ] [ tt(-iL) ] ...)(
|
||||
xitem(tt(zmodload) [ tt(-a) [ tt(-bcpf) [ tt(-I) ] ] ] [ tt(-iL) ] ...)
|
||||
item(tt(zmodload) tt(-u) [ tt(-abcdpf) [ tt(-I) ] ] [ tt(-iL) ] ...)(
|
||||
tt(zmodload) performs operations relating to zsh's loadable modules.
|
||||
This feature is not available on all operating systems,
|
||||
or on all installations on a particular operating system.
|
||||
|
@ -1349,6 +1349,12 @@ item(tt(zmodload) tt(-up) [ tt(-i) ] var(parameter) ...)(
|
|||
The tt(-p) option is like the tt(-b) and tt(-c) options, but makes
|
||||
tt(zmodload) work on autoloaded parameters instead.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-af) [ tt(-L) ])
|
||||
xitem(tt(zmodload) tt(-af) [ tt(-i) ] var(name) [ var(function) ... ])
|
||||
item(tt(zmodload) tt(-uf) [ tt(-i) ] var(function) ...)(
|
||||
The tt(-p) option is like the tt(-b), tt(-p), and tt(-c) options, but
|
||||
makes tt(zmodload) work on autoloaded math functions instead.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-a) [ tt(-L) ])
|
||||
xitem(tt(zmodload) tt(-a) [ tt(-i) ] var(name) [ var(builtin) ... ])
|
||||
item(tt(zmodload) tt(-ua) [ tt(-i) ] var(builtin) ...)(
|
||||
|
|
|
@ -129,6 +129,7 @@ variables:
|
|||
autoloading (without the leading `-')
|
||||
- autoprefixconds like autoinfixconds, but for prefix condition codes
|
||||
- autoparams parameters defined by the module, for autoloading
|
||||
- automathfuncs math functions defined by the module, for autoloading
|
||||
- objects .o files making up this module (*must* be defined)
|
||||
- proto .pro files for this module (default generated from $objects)
|
||||
- headers extra headers for this module (default none)
|
||||
|
@ -398,6 +399,90 @@ builtins and condition codes:
|
|||
...
|
||||
}
|
||||
|
||||
Modules can also define math functions. Again, they are described
|
||||
using a table:
|
||||
|
||||
static struct mathfunc mftab[] = {
|
||||
NUMMATHFUNC("sum", math_sum, 1, -1, 0),
|
||||
STRMATHFUNC("length", math_length, 0),
|
||||
};
|
||||
|
||||
The `NUMMATHFUNC()' macro defines a math function that gets an array
|
||||
of mnumbers (the zsh type for representing values in arithmetic
|
||||
expressions) taken from the string in parentheses at the function
|
||||
call. Its arguments are the name of the function, the C-function
|
||||
implementing it, the minimum and maximum number of arguments (as
|
||||
usual, the later may be `-1' to specify that the function accepts any
|
||||
number of arguments), and finally an integer that is given unchanged
|
||||
to the C-function (to be able to implement multiple math functions in
|
||||
one C-function).
|
||||
|
||||
The `STRMATHFUNC()' macro defines a math function that gets the string
|
||||
in parentheses at the call as one string argument (without the
|
||||
parentheses). The arguments are the name of the function, the
|
||||
C-function, and an integer used like the last argument of
|
||||
`NUMMATHFUNC()'.
|
||||
|
||||
The C-functions implementing the math functions look like this:
|
||||
|
||||
/**/
|
||||
static mnumber
|
||||
math_sum(char *name, int argc, mnumber *argv, int id)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
/**/
|
||||
static mnumber
|
||||
math_length(char *name, char *arg, int id)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
Functions defined with `NUMMATHFUNC' get the name of the function, the
|
||||
number of numeric arguments, an array with these arguments, and the
|
||||
last argument from the macro-call. Functions defined with
|
||||
`STRMATHFUNC' get the name of the function, the string between the
|
||||
parentheses at the call, and the last argument from the macro-call.
|
||||
|
||||
Both types of functions return an mnumber which is a descriminated
|
||||
union looking like:
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
zlong l;
|
||||
double d;
|
||||
} u;
|
||||
int type;
|
||||
} mnumber;
|
||||
|
||||
The `type' field should be set to `MN_INTEGER' or `MN_FLOAT' and
|
||||
depending on its value either `u.l' or `u.d' contains the value.
|
||||
|
||||
To register and de-register math functions, the functions
|
||||
`addmathfuncs()' and `deletemathfuncs()' are used:
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_example(Module m)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
|
||||
...
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
cleanup_example(Module m)
|
||||
{
|
||||
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
|
||||
...
|
||||
}
|
||||
|
||||
The arguments and return values are as for the functions used to
|
||||
register and de-register parameters, conditions, etc.
|
||||
|
||||
Modules can also define function hooks. Other modules can then add
|
||||
functions to these hooks to make the first module call these functions
|
||||
instead of the default.
|
||||
|
|
|
@ -100,6 +100,47 @@ cond_i_ex(char **a, int id)
|
|||
return !strcmp("example", dyncat(s1, s2));
|
||||
}
|
||||
|
||||
/**/
|
||||
static mnumber
|
||||
math_sum(char *name, int argc, mnumber *argv, int id)
|
||||
{
|
||||
mnumber ret;
|
||||
int f = 0;
|
||||
|
||||
ret.u.l = 0;
|
||||
while (argc--) {
|
||||
if (argv->type == MN_INTEGER) {
|
||||
if (f)
|
||||
ret.u.d += (double) argv->u.l;
|
||||
else
|
||||
ret.u.l += argv->u.l;
|
||||
} else {
|
||||
if (f)
|
||||
ret.u.d += argv->u.d;
|
||||
else {
|
||||
ret.u.d = ((double) ret.u.l) + ((double) argv->u.d);
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
ret.type = (f ? MN_FLOAT : MN_INTEGER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**/
|
||||
static mnumber
|
||||
math_length(char *name, char *arg, int id)
|
||||
{
|
||||
mnumber ret;
|
||||
|
||||
ret.type = MN_INTEGER;
|
||||
ret.u.l = strlen(arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
ex_wrapper(List list, FuncWrap w, char *name)
|
||||
|
@ -136,6 +177,11 @@ static struct paramdef patab[] = {
|
|||
ARRPARAMDEF("exarr", &arrparam),
|
||||
};
|
||||
|
||||
static struct mathfunc mftab[] = {
|
||||
NUMMATHFUNC("sum", math_sum, 1, -1, 0),
|
||||
STRMATHFUNC("length", math_length, 0),
|
||||
};
|
||||
|
||||
static struct funcwrap wrapper[] = {
|
||||
WRAPDEF(ex_wrapper),
|
||||
};
|
||||
|
@ -162,6 +208,7 @@ boot_example(Module m)
|
|||
return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
|
||||
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
|
||||
addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) |
|
||||
addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab)) |
|
||||
!addwrapper(m, wrapper));
|
||||
}
|
||||
|
||||
|
@ -174,6 +221,7 @@ cleanup_example(Module m)
|
|||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
|
||||
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
|
||||
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
|
||||
deletewrapper(m, wrapper);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,5 +3,6 @@ autobins="example"
|
|||
autoinfixconds="ex"
|
||||
autoprefixconds="len"
|
||||
autoparams="exint exstr exarr"
|
||||
automathfuncs="sum length"
|
||||
|
||||
objects="example.o"
|
||||
|
|
|
@ -125,7 +125,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
|
||||
|
||||
#ifdef DYNAMIC
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipue", NULL),
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcfdipue", NULL),
|
||||
#else
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "e", NULL),
|
||||
#endif
|
||||
|
|
79
Src/math.c
79
Src/math.c
|
@ -141,7 +141,8 @@ static int unary = 1;
|
|||
#define POWER 49
|
||||
#define CID 50
|
||||
#define POWEREQ 51
|
||||
#define TOKCOUNT 52
|
||||
#define FUNC 52
|
||||
#define TOKCOUNT 53
|
||||
|
||||
/* precedences */
|
||||
|
||||
|
@ -157,7 +158,7 @@ static int prec[TOKCOUNT] =
|
|||
15, 15, 15, 15, 15,
|
||||
15, 15, 15, 16, 200,
|
||||
2, 2, 0, 0, 7,
|
||||
0, 15
|
||||
0, 15, 0
|
||||
};
|
||||
|
||||
#define TOPPREC 16
|
||||
|
@ -175,7 +176,7 @@ static int type[TOKCOUNT] =
|
|||
/* 35 */ RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
|
||||
/* 40 */ BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
|
||||
/* 45 */ RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
|
||||
/* 50 */ LR|OP_OPF, RL|OP_E2
|
||||
/* 50 */ LR|OP_OPF, RL|OP_E2, LR|OP_OPF
|
||||
};
|
||||
|
||||
#define LVCOUNT 32
|
||||
|
@ -392,6 +393,7 @@ zzlex(void)
|
|||
cct = 1;
|
||||
}
|
||||
if (iident(*ptr)) {
|
||||
int func = 0;
|
||||
char *p, q;
|
||||
|
||||
p = ptr;
|
||||
|
@ -400,12 +402,14 @@ zzlex(void)
|
|||
return EOI;
|
||||
}
|
||||
while (iident(*++ptr));
|
||||
if (*ptr == '[') {
|
||||
if (*ptr == '[' || (!cct && *ptr == '(')) {
|
||||
char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
|
||||
int l;
|
||||
func = (op == '(');
|
||||
for (ptr++, l = 1; *ptr && l; ptr++) {
|
||||
if (*ptr == '[')
|
||||
if (*ptr == op)
|
||||
l++;
|
||||
if (*ptr == ']')
|
||||
if (*ptr == cp)
|
||||
l--;
|
||||
if (*ptr == '\\' && ptr[1])
|
||||
ptr++;
|
||||
|
@ -415,7 +419,7 @@ zzlex(void)
|
|||
*ptr = '\0';
|
||||
lvals[yylval = lvc++] = ztrdup(p);
|
||||
*ptr = q;
|
||||
return cct ? CID : ID;
|
||||
return (func ? FUNC : (cct ? CID : ID));
|
||||
}
|
||||
else if (cct) {
|
||||
yyval.u.l = poundgetfn(NULL);
|
||||
|
@ -483,6 +487,64 @@ setvar(LV s, mnumber v)
|
|||
}
|
||||
|
||||
|
||||
/**/
|
||||
static mnumber
|
||||
callmathfunc(char *o)
|
||||
{
|
||||
MathFunc f;
|
||||
char *a, *n;
|
||||
static mnumber dummy;
|
||||
|
||||
n = a = dupstring(o);
|
||||
|
||||
while (*a != '(')
|
||||
a++;
|
||||
*a++ = '\0';
|
||||
a[strlen(a) - 1] = '\0';
|
||||
|
||||
if ((f = getmathfunc(n, 1))) {
|
||||
if (f->flags & MFF_STR)
|
||||
return f->sfunc(n, a, f->funcid);
|
||||
else {
|
||||
int argc = 0;
|
||||
mnumber *argv, *q;
|
||||
LinkList l = newlinklist();
|
||||
LinkNode node;
|
||||
char *p;
|
||||
|
||||
if (*a) {
|
||||
for (p = a; *a; a++) {
|
||||
if (*a == '\\' && a[1])
|
||||
a++;
|
||||
else if (*a == ',') {
|
||||
*a = '\0';
|
||||
addlinknode(l, p);
|
||||
argc++;
|
||||
p = a + 1;
|
||||
}
|
||||
}
|
||||
addlinknode(l, p);
|
||||
argc++;
|
||||
}
|
||||
if (argc >= f->minargs && (f->maxargs < 0 || argc <= f->maxargs)) {
|
||||
if (argc) {
|
||||
q = argv = (mnumber *) zhalloc(argc * sizeof(mnumber));
|
||||
for (node = firstnode(l); node; incnode(node))
|
||||
*q++ = matheval((char *) getdata(node));
|
||||
}
|
||||
return f->nfunc(n, argc, argv, f->funcid);
|
||||
} else
|
||||
zerr("wrong number of argument: %s", o, 0);
|
||||
}
|
||||
} else
|
||||
zerr("unknown function: %s", n, 0);
|
||||
|
||||
dummy.type = MN_INTEGER;
|
||||
dummy.u.l = 0;
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
notzero(mnumber a)
|
||||
|
@ -957,6 +1019,9 @@ mathparse(int pc)
|
|||
case CID:
|
||||
push(getcvar(yylval), yylval);
|
||||
break;
|
||||
case FUNC:
|
||||
push(callmathfunc(lvals[yylval]), yylval);
|
||||
break;
|
||||
case M_INPAR:
|
||||
mathparse(TOPPREC);
|
||||
if (mtok != M_OUTPAR) {
|
||||
|
|
|
@ -25,6 +25,7 @@ for x_mod in $x_mods; do
|
|||
*) echo "/* non-linked-in known module \`$x_mod' */"
|
||||
eval "loc=\$loc_$x_mod"
|
||||
unset moddeps autobins autoinfixconds autoprefixconds autoparams
|
||||
unset automathfuncs
|
||||
. $srcdir/../$loc/${x_mod}.mdd
|
||||
for bin in $autobins; do
|
||||
echo " add_autobin(\"$bin\", \"$x_mod\");"
|
||||
|
@ -38,6 +39,9 @@ for x_mod in $x_mods; do
|
|||
for param in $autoparams; do
|
||||
echo " add_autoparam(\"$param\", \"$x_mod\");"
|
||||
done
|
||||
for mfunc in $automathfuncs; do
|
||||
echo " add_automath(\"$mfunc\", \"$x_mod\");"
|
||||
done
|
||||
for dep in $moddeps; do
|
||||
case $bin_mods in
|
||||
*" $dep "*)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
# autoloading (without the leading `-')
|
||||
# autoprefixconds like autoinfixconds, but for prefix condition codes
|
||||
# autoparams parameters defined by the module, for autoloading
|
||||
# automathfuncs math functions defined by the module, for autoloading
|
||||
# objects .o files making up this module (*must* be defined)
|
||||
# proto .pro files for this module (default generated from $objects)
|
||||
# headers extra headers for this module (default none)
|
||||
|
@ -171,7 +172,7 @@ if $first_stage; then
|
|||
for module in $here_modules; do
|
||||
|
||||
unset moddeps nozshdep alwayslink hasexport
|
||||
unset autobins autoinfixconds autoprefixconds autoparams
|
||||
unset autobins autoinfixconds autoprefixconds autoparams automathfuncs
|
||||
unset objects proto headers hdrdeps otherincs
|
||||
. $top_srcdir/$the_subdir/${module}.mdd
|
||||
test -n "${moddeps+set}" || moddeps=
|
||||
|
|
234
Src/module.c
234
Src/module.c
|
@ -696,8 +696,9 @@ autoloadscan(HashNode hn, int printflags)
|
|||
int
|
||||
bin_zmodload(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
if ((ops['b'] || ops['c'] || ops['p']) && !(ops['a'] || ops['u'])) {
|
||||
zwarnnam(nam, "-b, -c, and -p must be combined with -a or -u",
|
||||
if ((ops['b'] || ops['c'] || ops['p'] || ops['f']) &&
|
||||
!(ops['a'] || ops['u'])) {
|
||||
zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -718,10 +719,12 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
|
|||
return bin_zmodload_exist(nam, args, ops);
|
||||
else if (ops['d'])
|
||||
return bin_zmodload_dep(nam, args, ops);
|
||||
else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p']))
|
||||
else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'] || ops['f']))
|
||||
return bin_zmodload_auto(nam, args, ops);
|
||||
else if (ops['c'] && !(ops['b'] || ops['p']))
|
||||
return bin_zmodload_cond(nam, args, ops);
|
||||
else if (ops['f'] && !(ops['b'] || ops['p']))
|
||||
return bin_zmodload_math(nam, args, ops);
|
||||
else if (ops['p'] && !(ops['b'] || ops['c']))
|
||||
return bin_zmodload_param(nam, args, ops);
|
||||
else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p']))
|
||||
|
@ -935,9 +938,10 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
|
|||
putchar('I');
|
||||
printf(" %s %s\n", p->module, p->name);
|
||||
} else {
|
||||
fputs("post ", stdout);
|
||||
if (p->flags & CONDF_INFIX)
|
||||
fputs("infix ", stdout);
|
||||
else
|
||||
fputs("post ", stdout);
|
||||
printf("%s (%s)\n",p->name, p->module);
|
||||
}
|
||||
}
|
||||
|
@ -958,7 +962,68 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
|
|||
zwarnnam(nam, "%s: `/' is illegal in a condition", cnam, 0);
|
||||
ret = 1;
|
||||
} else if (add_autocond(cnam, ops['I'], modnam) && !ops['i']) {
|
||||
zwarnnam(nam, "failed to add condition %s", cnam, 0);
|
||||
zwarnnam(nam, "failed to add condition `%s'", cnam, 0);
|
||||
ret = 1;
|
||||
}
|
||||
} while(*args);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_zmodload_math(char *nam, char **args, char *ops)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ops['u']) {
|
||||
/* remove autoloaded conditions */
|
||||
for (; *args; args++) {
|
||||
MathFunc f = getmathfunc(*args, 0);
|
||||
|
||||
if (!f) {
|
||||
if (!ops['i']) {
|
||||
zwarnnam(nam, "%s: no such math function", *args, 0);
|
||||
ret = 1;
|
||||
}
|
||||
} else if (f->flags & CONDF_ADDED) {
|
||||
zwarnnam(nam, "%s: math function is already defined", *args, 0);
|
||||
ret = 1;
|
||||
} else
|
||||
deletemathfunc(f);
|
||||
}
|
||||
return ret;
|
||||
} else if (!*args) {
|
||||
/* list autoloaded math functions */
|
||||
MathFunc p;
|
||||
|
||||
for (p = mathfuncs; p; p = p->next) {
|
||||
if (p->module) {
|
||||
if (ops['L']) {
|
||||
fputs("zmodload -af", stdout);
|
||||
printf(" %s %s\n", p->module, p->name);
|
||||
} else
|
||||
printf("%s (%s)\n",p->name, p->module);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
/* add autoloaded conditions */
|
||||
char *modnam;
|
||||
|
||||
modnam = *args++;
|
||||
if(isset(RESTRICTED) && strchr(modnam, '/')) {
|
||||
zwarnnam(nam, "%s: restricted", modnam, 0);
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
char *fnam = *args ? *args++ : modnam;
|
||||
if (strchr(fnam, '/')) {
|
||||
zwarnnam(nam, "%s: `/' is illegal in a math function",
|
||||
fnam, 0);
|
||||
ret = 1;
|
||||
} else if (add_automathfunc(fnam, modnam) && !ops['i']) {
|
||||
zwarnnam(nam, "failed to add math function `%s'", fnam, 0);
|
||||
ret = 1;
|
||||
}
|
||||
} while(*args);
|
||||
|
@ -1272,8 +1337,10 @@ addconddefs(char const *nam, Conddef c, int size)
|
|||
int hads = 0, hadf = 0;
|
||||
|
||||
while (size--) {
|
||||
if (c->flags & CONDF_ADDED)
|
||||
if (c->flags & CONDF_ADDED) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
if (addconddef(c)) {
|
||||
zwarnnam(nam, "name clash when adding condition `%s'", c->name, 0);
|
||||
hadf = 1;
|
||||
|
@ -1534,7 +1601,7 @@ deleteparamdefs(char const *nam, Paramdef d, int size)
|
|||
int
|
||||
add_autocond(char *nam, int inf, char *module)
|
||||
{
|
||||
Conddef c = zalloc(sizeof(*c));
|
||||
Conddef c = (Conddef) zalloc(sizeof(*c));
|
||||
|
||||
c->name = ztrdup(nam);
|
||||
c->flags = (inf ? CONDF_INFIX : 0);
|
||||
|
@ -1587,8 +1654,10 @@ deleteconddefs(char const *nam, Conddef c, int size)
|
|||
int hads = 0, hadf = 0;
|
||||
|
||||
while (size--) {
|
||||
if (!(c->flags & CONDF_ADDED))
|
||||
if (!(c->flags & CONDF_ADDED)) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
if (deleteconddef(c)) {
|
||||
zwarnnam(nam, "condition `%s' already deleted", c->name, 0);
|
||||
hadf = 1;
|
||||
|
@ -1618,3 +1687,152 @@ add_autoparam(char *nam, char *module)
|
|||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
/* List of math functions. */
|
||||
|
||||
/**/
|
||||
MathFunc mathfuncs;
|
||||
|
||||
/**/
|
||||
MathFunc
|
||||
getmathfunc(char *name, int autol)
|
||||
{
|
||||
MathFunc p, q = NULL;
|
||||
|
||||
for (p = mathfuncs; p; q = p, p = p->next)
|
||||
if (!strcmp(name, p->name)) {
|
||||
#ifdef DYNAMIC
|
||||
if (autol && p->module) {
|
||||
char *n = dupstring(p->module);
|
||||
|
||||
if (q)
|
||||
q->next = p->next;
|
||||
else
|
||||
mathfuncs = p->next;
|
||||
|
||||
zsfree(p->module);
|
||||
zfree(p, sizeof(*p));
|
||||
|
||||
load_module(n);
|
||||
|
||||
return getmathfunc(name, 0);
|
||||
}
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
addmathfunc(MathFunc f)
|
||||
{
|
||||
MathFunc p;
|
||||
|
||||
if (f->flags & MFF_ADDED)
|
||||
return 1;
|
||||
|
||||
for (p = mathfuncs; p; p = p->next)
|
||||
if (!strcmp(f->name, p->name))
|
||||
return 1;
|
||||
|
||||
f->flags |= MFF_ADDED;
|
||||
f->next = mathfuncs;
|
||||
mathfuncs = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
addmathfuncs(char const *nam, MathFunc f, int size)
|
||||
{
|
||||
int hads = 0, hadf = 0;
|
||||
|
||||
while (size--) {
|
||||
if (f->flags & MFF_ADDED) {
|
||||
f++;
|
||||
continue;
|
||||
}
|
||||
if (addmathfunc(f)) {
|
||||
zwarnnam(nam, "name clash when adding math function `%s'",
|
||||
f->name, 0);
|
||||
hadf = 1;
|
||||
} else
|
||||
hads = 2;
|
||||
f++;
|
||||
}
|
||||
return hadf ? hads : 1;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC
|
||||
|
||||
/**/
|
||||
int
|
||||
add_automathfunc(char *nam, char *module)
|
||||
{
|
||||
MathFunc f = (MathFunc) zalloc(sizeof(*f));
|
||||
|
||||
f->name = ztrdup(nam);
|
||||
f->module = ztrdup(module);
|
||||
|
||||
if (addmathfunc(f)) {
|
||||
zsfree(f->name);
|
||||
zsfree(f->module);
|
||||
zfree(f, sizeof(*f));
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
deletemathfunc(MathFunc f)
|
||||
{
|
||||
MathFunc p, q;
|
||||
|
||||
for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next);
|
||||
|
||||
if (p) {
|
||||
if (q)
|
||||
q->next = f->next;
|
||||
else
|
||||
mathfuncs = f->next;
|
||||
|
||||
if (f->module) {
|
||||
zsfree(f->name);
|
||||
zsfree(f->module);
|
||||
zfree(f, sizeof(*f));
|
||||
} else
|
||||
f->flags &= ~MFF_ADDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
deletemathfuncs(char const *nam, MathFunc f, int size)
|
||||
{
|
||||
int hads = 0, hadf = 0;
|
||||
|
||||
while (size--) {
|
||||
if (!(f->flags & MFF_ADDED)) {
|
||||
f++;
|
||||
continue;
|
||||
}
|
||||
if (deletemathfunc(f)) {
|
||||
zwarnnam(nam, "math function `%s' already deleted",
|
||||
f->name, 0);
|
||||
hadf = 1;
|
||||
} else
|
||||
hads = 2;
|
||||
f++;
|
||||
}
|
||||
return hadf ? hads : 1;
|
||||
}
|
||||
|
||||
#endif /* DYNAMIC */
|
||||
|
|
24
Src/zsh.h
24
Src/zsh.h
|
@ -79,6 +79,30 @@ typedef struct {
|
|||
|
||||
typedef int LV;
|
||||
|
||||
typedef struct mathfunc *MathFunc;
|
||||
typedef mnumber (*NumMathFunc)(char *, int, mnumber *, int);
|
||||
typedef mnumber (*StrMathFunc)(char *, char *, int);
|
||||
|
||||
struct mathfunc {
|
||||
MathFunc next;
|
||||
char *name;
|
||||
int flags;
|
||||
NumMathFunc nfunc;
|
||||
StrMathFunc sfunc;
|
||||
char *module;
|
||||
int minargs;
|
||||
int maxargs;
|
||||
int funcid;
|
||||
};
|
||||
|
||||
#define MFF_STR 1
|
||||
#define MFF_ADDED 2
|
||||
|
||||
#define NUMMATHFUNC(name, func, min, max, id) \
|
||||
{ NULL, name, 0, func, NULL, NULL, min, max, id }
|
||||
#define STRMATHFUNC(name, func, id) \
|
||||
{ NULL, name, MFF_STR, NULL, func, NULL, 0, 0, id }
|
||||
|
||||
/* Character tokens are sometimes casted to (unsigned char)'s. *
|
||||
* Unfortunately, some compilers don't correctly cast signed to *
|
||||
* unsigned promotions; i.e. (int)(unsigned char)((char) -1) evaluates *
|
||||
|
|
Loading…
Reference in a new issue