From 6f698f634a85d0b3d34b5566d1adb807de577e86 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Wed, 22 Sep 1999 13:04:17 +0000 Subject: zsh-workers/7976 --- Src/Modules/example.c | 48 ++++++++++ Src/Modules/example.mdd | 1 + Src/builtin.c | 2 +- Src/math.c | 79 ++++++++++++++-- Src/mkbltnmlst.sh | 4 + Src/mkmakemod.sh | 3 +- Src/module.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++-- Src/zsh.h | 24 +++++ 8 files changed, 378 insertions(+), 17 deletions(-) (limited to 'Src') diff --git a/Src/Modules/example.c b/Src/Modules/example.c index b0bbee967..fbe392e94 100644 --- a/Src/Modules/example.c +++ b/Src/Modules/example.c @@ -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; } diff --git a/Src/Modules/example.mdd b/Src/Modules/example.mdd index 5ed55e6f1..e32e8182e 100644 --- a/Src/Modules/example.mdd +++ b/Src/Modules/example.mdd @@ -3,5 +3,6 @@ autobins="example" autoinfixconds="ex" autoprefixconds="len" autoparams="exint exstr exarr" +automathfuncs="sum length" objects="example.o" diff --git a/Src/builtin.c b/Src/builtin.c index ca765ccfc..ae608cc39 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -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 diff --git a/Src/math.c b/Src/math.c index e044cbd9f..3fb741854 100644 --- a/Src/math.c +++ b/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) { diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh index c174cbac6..e11972794 100644 --- a/Src/mkbltnmlst.sh +++ b/Src/mkbltnmlst.sh @@ -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 "*) diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh index cd92c7f07..9584474a9 100644 --- a/Src/mkmakemod.sh +++ b/Src/mkmakemod.sh @@ -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= diff --git a/Src/module.c b/Src/module.c index dab2c0350..69a43cc3c 100644 --- a/Src/module.c +++ b/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 */ diff --git a/Src/zsh.h b/Src/zsh.h index 51df16313..651515fc5 100644 --- a/Src/zsh.h +++ b/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 * -- cgit 1.4.1