From 40dcdf68a2368b0e889a6be5d7b6323101fcbe9f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 28 Oct 2003 16:52:17 +0000 Subject: 19209: Rename zcalloc to zshcalloc. --- Src/module.c | 413 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 336 insertions(+), 77 deletions(-) (limited to 'Src/module.c') diff --git a/Src/module.c b/Src/module.c index 63e0dc2f6..e943fb397 100644 --- a/Src/module.c +++ b/Src/module.c @@ -88,6 +88,27 @@ register_module(char *n, Module_func setup, Module_func boot, zaddlinknode(linkedmodules, m); } +/* Print an alias. */ + +/**/ +static void +printmodalias(Module m, char *ops) +{ + if (ops['L']) { + printf("zmodload -A "); + if (m->nam[0] == '-') + fputs("-- ", stdout); + quotedzputs(m->nam, stdout); + putchar('='); + quotedzputs(m->u.alias, stdout); + } else { + nicezputs(m->nam, stdout); + fputs(" -> ", stdout); + nicezputs(m->u.alias, stdout); + } + putchar('\n'); +} + /* Check if a module is linked in. */ /**/ @@ -164,6 +185,15 @@ addwrapper(Module m, FuncWrap w) { FuncWrap p, q; + /* + * We can't add a wrapper to an alias, since it's supposed + * to behave identically to the resolved module. This shouldn't + * happen since we usually add wrappers when a real module is + * loaded. + */ + if (m->flags & MOD_ALIAS) + return 1; + if (w->flags & WRAPF_ADDED) return 1; for (p = wrappers, q = NULL; p; q = p, p = p->next); @@ -196,7 +226,7 @@ mod_export LinkList modules; int add_autobin(char *nam, char *module) { - Builtin bn = zcalloc(sizeof(*bn)); + Builtin bn = zshcalloc(sizeof(*bn)); bn->nam = ztrdup(nam); bn->optstr = ztrdup(module); return addbuiltin(bn); @@ -256,6 +286,9 @@ deletewrapper(Module m, FuncWrap w) { FuncWrap p, q; + if (m->flags & MOD_ALIAS) + return 1; + if (w->flags & WRAPF_ADDED) { for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next); @@ -292,7 +325,8 @@ load_and_bind(const char *fn) int err = loadbind(0, (void *) addbuiltin, ret); for (node = firstnode(modules); !err && node; incnode(node)) { Module m = (Module) getdata(node); - if (m->u.handle && !(m->flags & MOD_LINKED)) + if (!(m->flags & MOD_ALIAS) && + m->u.handle && !(m->flags & MOD_LINKED)) err |= loadbind(0, m->u.handle, ret); } @@ -431,21 +465,78 @@ do_load_module(char const *name) /**/ #endif /* !DYNAMIC */ +/* + * Find a module in the list. + * If aliasp is non-zero, resolve any aliases to the underlying module. + * If namep is set, this is set to point to the last alias value resolved, + * even if that module was not loaded. or the module name if no aliases. + * Hence this is always the physical module to load in a chain of aliases. + * Return NULL if the module named is not stored as a structure, or if we were + * resolving aliases and the final module named is not stored as a + * structure. + * + * TODO: now we have aliases, there may be some merit in using a hash + * table instead of a linked list. + */ /**/ static LinkNode -find_module(const char *name) +find_module(const char *name, int aliasp, const char **namep) { Module m; LinkNode node; for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (!strcmp(m->nam, name)) + if (!strcmp(m->nam, name)) { + if (aliasp && (m->flags & MOD_ALIAS)) { + if (namep) + *namep = m->u.alias; + return find_module(m->u.alias, 1, namep); + } + if (namep) + *namep = m->nam; return node; + } } return NULL; } +/* + * Unlink and free a module node from the linked list. + */ + +/**/ +static void +delete_module(LinkNode node) +{ + Module m = (Module) remnode(modules, node); + + if (m->flags & MOD_ALIAS) + zsfree(m->u.alias); + zsfree(m->nam); + if (m->deps) + freelinklist(m->deps, freestr); + zfree(m, sizeof(*m)); +} + +/**/ +mod_export int +module_loaded(const char *name) +{ + LinkNode node; + Module m; + + return ((node = find_module(name, 1, NULL)) && + (m = ((Module) getdata(node)))->u.handle && + !(m->flags & MOD_UNLOAD)); +} + +/* + * Setup and cleanup functions: we don't search for aliases here, + * since they should have been resolved before we try to load or unload + * the module. + */ + /**/ #ifdef DYNAMIC @@ -654,7 +745,7 @@ modname_ok(char const *p) } /**/ -int +mod_export int load_module(char const *name) { Module m; @@ -667,11 +758,19 @@ load_module(char const *name) zerr("invalid module name `%s'", name, 0); return 0; } - if (!(node = find_module(name))) { + /* + * The following function call may alter name to the final name in a + * chain of aliases. This makes sure the actual module loaded + * is the right one. + */ + queue_signals(); + if (!(node = find_module(name, 1, &name))) { if (!(linked = module_linked(name)) && - !(handle = do_load_module(name))) + !(handle = do_load_module(name))) { + unqueue_signals(); return 0; - m = zcalloc(sizeof(*m)); + } + m = zshcalloc(sizeof(*m)); m->nam = ztrdup(name); if (handle) { m->u.handle = handle; @@ -685,23 +784,26 @@ load_module(char const *name) if ((set = setup_module(m)) || boot_module(m)) { if (!set) finish_module(m); - remnode(modules, node); - zsfree(m->nam); - zfree(m, sizeof(*m)); - m->flags &= ~MOD_SETUP; + delete_module(node); + unqueue_signals(); return 0; } m->flags |= MOD_INIT_S | MOD_INIT_B; m->flags &= ~MOD_SETUP; + unqueue_signals(); return 1; } m = (Module) getdata(node); - if (m->flags & MOD_SETUP) + if (m->flags & MOD_SETUP) { + unqueue_signals(); return 1; + } if (m->flags & MOD_UNLOAD) m->flags &= ~MOD_UNLOAD; - else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) + else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) { + unqueue_signals(); return 1; + } if (m->flags & MOD_BUSY) { zerr("circular dependencies for module %s", name, 0); return 0; @@ -711,14 +813,17 @@ load_module(char const *name) for (n = firstnode(m->deps); n; incnode(n)) if (!load_module((char *) getdata(n))) { m->flags &= ~MOD_BUSY; + unqueue_signals(); return 0; } m->flags &= ~MOD_BUSY; if (!m->u.handle) { handle = NULL; if (!(linked = module_linked(name)) && - !(handle = do_load_module(name))) + !(handle = do_load_module(name))) { + unqueue_signals(); return 0; + } if (handle) { m->u.handle = handle; m->flags |= MOD_SETUP; @@ -732,6 +837,7 @@ load_module(char const *name) else m->u.linked = NULL; m->flags &= ~MOD_SETUP; + unqueue_signals(); return 0; } m->flags |= MOD_INIT_S; @@ -744,10 +850,12 @@ load_module(char const *name) else m->u.handle = NULL; m->flags &= ~MOD_SETUP; + unqueue_signals(); return 0; } m->flags |= MOD_INIT_B; m->flags &= ~MOD_SETUP; + unqueue_signals(); return 1; } @@ -761,38 +869,50 @@ load_module(char const *name) /**/ mod_export int -require_module(char *nam, char *module, int res, int test) +require_module(char *nam, const char *module, int res, int test) { Module m = NULL; LinkNode node; + int ret = 1; - /* First see if the module is linked in. */ - for (node = firstnode(linkedmodules); node; incnode(node)) { - if (!strcmp((char *) getdata(node), nam)) - return 1; - } - node = find_module(module); + /* Resolve aliases and actual loadable module as for load_module */ + queue_signals(); + node = find_module(module, 1, &module); if (node && (m = ((Module) getdata(node)))->u.handle && !(m->flags & MOD_UNLOAD)) { if (test) { + unqueue_signals(); zwarnnam(nam, "module %s already loaded.", module, 0); return 0; } } else - return load_module(module); + ret = load_module(module); + unqueue_signals(); - return 1; + return ret; } /**/ void -add_dep(char *name, char *from) +add_dep(const char *name, char *from) { LinkNode node; Module m; - if (!(node = find_module(name))) { - m = zcalloc(sizeof(*m)); + /* + * If we were passed an alias, we must resolve it to a final + * module name (and maybe add the corresponding struct), since otherwise + * we would need to check all modules to see if they happen + * to be aliased to the same thing to implement depencies properly. + * + * This should mean that an attempt to add an alias which would + * have the same name as a module which has dependencies is correctly + * rejected, because then the module named already exists as a non-alias. + * Better make sure. (There's no problem making a an alias which + * *points* to a module with dependencies, of course.) + */ + if (!(node = find_module(name, 1, &name))) { + m = zshcalloc(sizeof(*m)); m->nam = ztrdup(name); zaddlinknode(modules, m); } else @@ -838,12 +958,23 @@ autoloadscan(HashNode hn, int printflags) int bin_zmodload(char *nam, char **args, char *ops, int func) { - if ((ops['b'] || ops['c'] || ops['p'] || ops['f']) && - !(ops['a'] || ops['u'])) { + int ops_bcpf = ops['b'] || ops['c'] || ops['p'] || ops['f']; + int ops_au = ops['a'] || ops['u']; + int ret = 1; + + if (ops_bcpf && !ops_au) { zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u", NULL, 0); return 1; } + if (ops['A'] || ops['R']) { + if (ops_bcpf || ops_au || ops['d'] || (ops['R'] && ops['e'])) { + zwarnnam(nam, "illegal flags combined with -A or -R", NULL, 0); + return 1; + } + if (!ops['e']) + return bin_zmodload_alias(nam, args, ops); + } if (ops['d'] && ops['a']) { zwarnnam(nam, "-d cannot be combined with -a", NULL, 0); return 1; @@ -857,24 +988,137 @@ bin_zmodload(char *nam, char **args, char *ops, int func) zwarnnam(nam, "-e cannot be combined with other options", NULL, 0); return 1; } + queue_signals(); if (ops['e']) - return bin_zmodload_exist(nam, args, ops); + ret = bin_zmodload_exist(nam, args, ops); else if (ops['d']) - return bin_zmodload_dep(nam, args, ops); + ret = bin_zmodload_dep(nam, args, ops); else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'] || ops['f'])) - return bin_zmodload_auto(nam, args, ops); + ret = bin_zmodload_auto(nam, args, ops); else if (ops['c'] && !(ops['b'] || ops['p'])) - return bin_zmodload_cond(nam, args, ops); + ret = bin_zmodload_cond(nam, args, ops); else if (ops['f'] && !(ops['b'] || ops['p'])) - return bin_zmodload_math(nam, args, ops); + ret = bin_zmodload_math(nam, args, ops); else if (ops['p'] && !(ops['b'] || ops['c'])) - return bin_zmodload_param(nam, args, ops); + ret = bin_zmodload_param(nam, args, ops); else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p'])) - return bin_zmodload_load(nam, args, ops); + ret = bin_zmodload_load(nam, args, ops); else zwarnnam(nam, "use only one of -b, -c, or -p", NULL, 0); + unqueue_signals(); - return 1; + return ret; +} + +/**/ +static int +bin_zmodload_alias(char *nam, char **args, char *ops) +{ + /* + * TODO: while it would be too nasty to have aliases, as opposed + * to real loadable modules, with dependencies --- just what would + * we need to load when, exactly? --- there is in principle no objection + * to making it possible to force an alias onto an existing unloaded + * module which has dependencies. This would simply transfer + * the dependencies down the line to the aliased-to module name. + * This is actually useful, since then you can alias zsh/zle=mytestzle + * to load another version of zle. But then what happens when the + * alias is removed? Do you transfer the dependencies back? And + * suppose other names are aliased to the same file? It might be + * kettle of fish best left unwormed. + */ + LinkNode node; + Module m; + int ret = 0; + + if (!*args) { + if (ops['R']) { + zwarnnam(nam, "no module alias to remove", NULL, 0); + return 1; + } + for (node = firstnode(modules); node; incnode(node)) { + m = (Module) getdata(node); + if (m->flags & MOD_ALIAS) + printmodalias(m, ops); + } + return 0; + } + + for (; !ret && *args; args++) { + char *eqpos = strchr(*args, '='); + char *aliasname = eqpos ? eqpos+1 : NULL; + if (eqpos) + *eqpos = '\0'; + if (!modname_ok(*args)) { + zwarnnam(nam, "invalid module name `%s'", *args, 0); + return 1; + } + if (ops['R']) { + if (aliasname) { + zwarnnam(nam, "bad syntax for removing module alias: %s", + *args, 0); + return 1; + } + node = find_module(*args, 0, NULL); + if (node) { + m = (Module) getdata(node); + if (!(m->flags & MOD_ALIAS)) { + zwarnnam(nam, "module is not an alias: %s", *args, 0); + ret = 1; + break; + } + delete_module(node); + } else { + zwarnnam(nam, "no such module alias: %s", *args, 0); + return 1; + } + } else { + if (aliasname) { + const char *mname = aliasname; + if (!modname_ok(aliasname)) { + zwarnnam(nam, "invalid module name `%s'", aliasname, 0); + return 1; + } + find_module(aliasname, 1, &mname); + if (!strcmp(mname, *args)) { + zwarnnam(nam, "module alias would refer to itself: %s", + *args, 0); + return 1; + } + node = find_module(*args, 0, NULL); + if (node) { + m = (Module) getdata(node); + if (!(m->flags & MOD_ALIAS)) { + zwarnnam(nam, "module is not an alias: %s", *args, 0); + return 1; + } + zsfree(m->u.alias); + } else { + m = (Module) zshcalloc(sizeof(*m)); + m->nam = ztrdup(*args); + m->flags = MOD_ALIAS; + zaddlinknode(modules, m); + } + m->u.alias = ztrdup(aliasname); + } else { + if ((node = find_module(*args, 0, NULL))) { + m = (Module) getdata(node); + if (m->flags & MOD_ALIAS) + printmodalias(m, ops); + else { + zwarnnam(nam, "module is not an alias: %s", + *args, 0); + return 1; + } + } else { + zwarnnam(nam, "no such module alias: %s", *args, 0); + return 1; + } + } + } + } + + return 0; } /**/ @@ -883,28 +1127,33 @@ bin_zmodload_exist(char *nam, char **args, char *ops) { LinkNode node; Module m; + char *modname; if (!*args) { for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); + modname = m->nam; + if (m->flags & MOD_ALIAS) { + LinkNode node2; + if (ops['A'] && (node2 = find_module(m->u.alias, 1, NULL))) + m = (Module) getdata(node2); + else + continue; + } if (m->u.handle && !(m->flags & MOD_UNLOAD)) { - nicezputs(m->nam, stdout); + nicezputs(modname, stdout); putchar('\n'); } } return 0; } else { - int ret = 0, f; + int ret = 0; for (; !ret && *args; args++) { - f = 0; - for (node = firstnode(modules); - !f && node; incnode(node)) { - m = (Module) getdata(node); - if (m->u.handle && !(m->flags & MOD_UNLOAD)) - f = !strcmp(*args, m->nam); - } - ret = !f; + if (!(node = find_module(*args, 1, NULL)) + || !(m = (Module) getdata(node))->u.handle + || (m->flags & MOD_UNLOAD)) + ret = 1; } return ret; } @@ -916,23 +1165,24 @@ bin_zmodload_dep(char *nam, char **args, char *ops) { LinkNode node; Module m; - if(ops['u']) { - /* remove dependencies */ - char *tnam = *args++; - node = find_module(tnam); + if (ops['u']) { + /* remove dependencies, which can't pertain to aliases */ + const char *tnam = *args++; + node = find_module(tnam, 1, &tnam); if (!node) return 0; m = (Module) getdata(node); - if(*args && m->deps) { + if (*args && m->deps) { do { - for(node = firstnode(m->deps); node; incnode(node)) - if(!strcmp(*args, getdata(node))) { - zsfree(getdata(node)); - remnode(m->deps, node); + LinkNode dnode; + for (dnode = firstnode(m->deps); dnode; incnode(dnode)) + if (!strcmp(*args, getdata(dnode))) { + zsfree(getdata(dnode)); + remnode(m->deps, dnode); break; } } while(*++args); - if(empty(m->deps)) { + if (empty(m->deps)) { freelinklist(m->deps, freestr); m->deps = NULL; } @@ -942,19 +1192,16 @@ bin_zmodload_dep(char *nam, char **args, char *ops) m->deps = NULL; } } - if (!m->deps && !m->u.handle) { - remnode(modules, node); - zsfree(m->nam); - zfree(m, sizeof(*m)); - } + if (!m->deps && !m->u.handle) + delete_module(node); return 0; - } else if(!args[0] || !args[1]) { + } else if (!args[0] || !args[1]) { /* list dependencies */ for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); if (m->deps && (!args[0] || !strcmp(args[0], m->nam))) { LinkNode n; - if(ops['L']) { + if (ops['L']) { printf("zmodload -d "); if(m->nam[0] == '-') fputs("-- ", stdout); @@ -979,7 +1226,7 @@ bin_zmodload_dep(char *nam, char **args, char *ops) int ret = 0; char *tnam = *args++; - for(; *args; args++) + for (; *args; args++) add_dep(tnam, *args); return ret; } @@ -1099,7 +1346,7 @@ bin_zmodload_math(char *nam, char **args, char *ops) int ret = 0; if (ops['u']) { - /* remove autoloaded conditions */ + /* remove autoloaded math functions */ for (; *args; args++) { MathFunc f = getmathfunc(*args, 0); @@ -1108,7 +1355,7 @@ bin_zmodload_math(char *nam, char **args, char *ops) zwarnnam(nam, "%s: no such math function", *args, 0); ret = 1; } - } else if (f->flags & CONDF_ADDED) { + } else if (f->flags & MFF_ADDED) { zwarnnam(nam, "%s: math function is already defined", *args, 0); ret = 1; } else @@ -1130,7 +1377,7 @@ bin_zmodload_math(char *nam, char **args, char *ops) } return 0; } else { - /* add autoloaded conditions */ + /* add autoloaded math functions */ char *modnam; modnam = *args++; @@ -1209,6 +1456,15 @@ bin_zmodload_param(char *nam, char **args, char *ops) int unload_module(Module m, LinkNode node) { + /* + * Only unload the real module, so resolve aliases. + */ + if (m->flags & MOD_ALIAS) { + LinkNode node = find_module(m->u.alias, 1, NULL); + if (!node) + return 1; + m = (Module) getdata(node); + } if ((m->flags & MOD_INIT_S) && !(m->flags & MOD_UNLOAD) && ((m->flags & MOD_LINKED) ? @@ -1242,7 +1498,7 @@ unload_module(Module m, LinkNode node) LinkNode n; for (n = firstnode(m->deps); n; incnode(n)) { - LinkNode dn = find_module((char *) getdata(n)); + LinkNode dn = find_module((char *) getdata(n), 1, NULL); Module dm; if (dn && (dm = (Module) getdata(dn)) && @@ -1280,9 +1536,7 @@ unload_module(Module m, LinkNode node) if (!node) return 1; } - remnode(modules, node); - zsfree(m->nam); - zfree(m, sizeof(*m)); + delete_module(node); } } return 0; @@ -1297,8 +1551,9 @@ bin_zmodload_load(char *nam, char **args, char *ops) int ret = 0; if(ops['u']) { /* unload modules */ + const char *mname = *args; for(; *args; args++) { - node = find_module(*args); + node = find_module(*args, 1, &mname); if (node) { LinkNode mn, dn; int del = 0; @@ -1307,11 +1562,11 @@ bin_zmodload_load(char *nam, char **args, char *ops) m = (Module) getdata(mn); if (m->deps && m->u.handle) for (dn = firstnode(m->deps); dn; incnode(dn)) - if (!strcmp((char *) getdata(dn), *args)) { + if (!strcmp((char *) getdata(dn), mname)) { if (m->flags & MOD_UNLOAD) del = 1; else { - zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0); + zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname, 0); ret = 1; goto cont; } @@ -1335,7 +1590,7 @@ bin_zmodload_load(char *nam, char **args, char *ops) /* list modules */ for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (m->u.handle && !(m->flags & MOD_UNLOAD)) { + if (m->u.handle && !(m->flags & (MOD_UNLOAD|MOD_ALIAS))) { if(ops['L']) { printf("zmodload "); if(m->nam[0] == '-') @@ -1761,12 +2016,14 @@ add_autoparam(char *nam, char *module) { Param pm; + queue_signals(); if ((pm = (Param) gethashnode2(paramtab, nam))) unsetparam_pm(pm, 0, 1); - pm = setsparam(ztrdup(nam), ztrdup(module)); + pm = setsparam(nam, ztrdup(module)); pm->flags |= PM_AUTOLOAD; + unqueue_signals(); } /* List of math functions. */ @@ -1862,6 +2119,8 @@ add_automathfunc(char *nam, char *module) return 1; } + f->flags &= ~MFF_ADDED; /* still to autoload, not added yet */ + return 0; } -- cgit 1.4.1