about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-04-28 22:08:46 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-04-28 22:08:46 +0000
commitf330bdf21e67f45ada205022c66fe0a84eefdcbe (patch)
treed8f243d1b7139d3b7648cd2b43a82e9225cfa094
parent51b33d87027832e46edbfbddb107b72fed1719fc (diff)
downloadzsh-f330bdf21e67f45ada205022c66fe0a84eefdcbe.tar.gz
zsh-f330bdf21e67f45ada205022c66fe0a84eefdcbe.tar.xz
zsh-f330bdf21e67f45ada205022c66fe0a84eefdcbe.zip
zsh-workers:6133
-rw-r--r--Doc/Zsh/builtins.yo10
-rw-r--r--Src/Modules/example.c39
-rw-r--r--Src/Modules/example.mdd1
-rw-r--r--Src/builtin.c10
-rw-r--r--Src/mkbltnmlst.sh5
-rw-r--r--Src/mkmakemod.sh3
-rw-r--r--Src/module.c160
-rw-r--r--Src/params.c25
-rw-r--r--Src/zsh.h24
9 files changed, 260 insertions, 17 deletions
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index ffc9f3cfe..e9bc2ab16 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1175,9 +1175,12 @@ xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) [ var(dep) ... ] ])
 xitem(tt(zmodload) tt(-du) var(name) [ var(dep) ... ])
 xitem(tt(zmodload) tt(-a) [ tt(-iL) ] [ var(name) [ var(builtin) ... ] ])
 xitem(tt(zmodload) tt(-au) [ tt(-i) ] var(builtin) ...)
-xitem(tt(zmodload) tt(-c) [ tt(-iI) ] [ var(name) [ var(cond) ... ] ])
+xitem(tt(zmodload) tt(-c) [ tt(-iI) ] var(name) [ var(cond) ... ])
 xitem(tt(zmodload) tt(-cu) [ tt(-iI) ] var(cond) ...)
-item(tt(zmodload) tt(-c) [ tt(-IL) ])(
+xitem(tt(zmodload) tt(-c) [ tt(-IL) ])
+xitem(tt(zmodload) tt(-p) [ tt(-i) ] var(name) [ var(parameter) ... ])
+xitem(tt(zmodload) tt(-pu) [ tt(-i) ] var(parameter) ... ])
+item(tt(zmodload) tt(-p) [ tt(-L) ])(
 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.
@@ -1253,5 +1256,8 @@ names. Without this option prefix condition names are defined.
 Together with the tt(-u) option definitions for autoloaded conditions
 are removed. If given no condition names all defined names are listed
 (as a series of tt(zmodload) commands if the tt(-L) option is given).
+
+The tt(-p) option is like the tt(-c) option, but makes tt(zmodload)
+work on autoloaded parameters instead of condition codes.
 )
 enditem()
diff --git a/Src/Modules/example.c b/Src/Modules/example.c
index 95545172f..50b8c1626 100644
--- a/Src/Modules/example.c
+++ b/Src/Modules/example.c
@@ -30,22 +30,45 @@
 #include "example.mdh"
 #include "example.pro"
 
+/* parameters */
+
+static long intparam;
+static char *strparam;
+static char **arrparam;
+
+
 /**/
 static int
 bin_example(char *nam, char **args, char *ops, int func)
 {
     unsigned char c;
+    char **oargs = args, **p = arrparam;
+    long i = 0;
 
     printf("Options: ");
     for (c = 32; ++c < 128;)
 	if (ops[c])
 	    putchar(c);
     printf("\nArguments:");
-    for (; *args; args++) {
+    for (; *args; i++, args++) {
 	putchar(' ');
 	fputs(*args, stdout);
     }
     printf("\nName: %s\n", nam);
+    printf("\nInteger Parameter: %ld\n", intparam);
+    printf("String Parameter: %s\n", strparam ? strparam : "");
+    printf("Array Parameter:");
+    if (p)
+	while (*p) printf(" %s", *p++);
+    printf("\n");
+
+    intparam = i;
+    zsfree(strparam);
+    strparam = ztrdup(*oargs ? *oargs : "");
+    freearray(arrparam);
+    PERMALLOC {
+	arrparam = arrdup(oargs);
+    } LASTALLOC;
     return 0;
 }
 
@@ -103,6 +126,12 @@ static struct conddef cotab[] = {
     CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
 };
 
+static struct paramdef patab[] = {
+    INTPARAMDEF("exint", &intparam),
+    STRPARAMDEF("exstr", &strparam),
+    ARRPARAMDEF("exarr", &arrparam),
+};
+
 static struct funcwrap wrapper[] = {
     WRAPDEF(ex_wrapper),
 };
@@ -120,8 +149,15 @@ setup_example(Module m)
 int
 boot_example(Module m)
 {
+    intparam = 42;
+    strparam = ztrdup("example");
+    arrparam = (char **) zalloc(3 * sizeof(char *));
+    arrparam[0] = ztrdup("example");
+    arrparam[1] = ztrdup("array");
+    arrparam[2] = NULL;
     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)) |
 	     !addwrapper(m, wrapper));
 }
 
@@ -133,6 +169,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));
     deletewrapper(m, wrapper);
     return 0;
 }
diff --git a/Src/Modules/example.mdd b/Src/Modules/example.mdd
index f2cd50693..5ed55e6f1 100644
--- a/Src/Modules/example.mdd
+++ b/Src/Modules/example.mdd
@@ -2,5 +2,6 @@ autobins="example"
 
 autoinfixconds="ex"
 autoprefixconds="len"
+autoparams="exint exstr exarr"
 
 objects="example.o"
diff --git a/Src/builtin.c b/Src/builtin.c
index c042537f4..03beb13d9 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -120,7 +120,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, "LaudicI", NULL),
+    BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicIp", NULL),
 #endif
 };
 
@@ -1485,7 +1485,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
     int usepm, tc, keeplocal = 0;
 
     /* use the existing pm? */
-    usepm = pm && !(pm->flags & PM_UNSET);
+    usepm = pm && !(pm->flags & (PM_UNSET | PM_AUTOLOAD));
 
     /* Always use an existing pm if special at current locallevel */
     if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
@@ -1793,7 +1793,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	    continue;
 	}
 	if (!typeset_single(name, asg->name,
-			    (Param)paramtab->getnode(paramtab, asg->name),
+			    (Param)gethashnode2(paramtab, asg->name),
 			    func, on, off, roff, asg->value, NULL))
 	    returnval = 1;
     }
@@ -1945,7 +1945,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
 			next = (Param) pm->next;
 			if ((!(pm->flags & PM_RESTRICTED) ||
 			    unset(RESTRICTED)) && domatch(pm->nam, com, 0)) {
-			    unsetparam(pm->nam);
+			    unsetparam_pm(pm, 0, 1);
 			    match++;
 			}
 		    }
@@ -1974,7 +1974,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
 	    }
 	    *ss = 0;
 	}
-	pm = (Param) paramtab->getnode(paramtab, s);
+	pm = (Param) gethashnode2(paramtab, s);
 	if (!pm)
 	    returnval = 1;
 	else if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh
index b58d1e1dd..c174cbac6 100644
--- a/Src/mkbltnmlst.sh
+++ b/Src/mkbltnmlst.sh
@@ -24,7 +24,7 @@ for x_mod in $x_mods; do
 	*" $x_mod "*) ;;
 	*)  echo "/* non-linked-in known module \`$x_mod' */"
 	    eval "loc=\$loc_$x_mod"
-	    unset moddeps autobins autoinfixconds autoprefixconds
+	    unset moddeps autobins autoinfixconds autoprefixconds autoparams
 	    . $srcdir/../$loc/${x_mod}.mdd
 	    for bin in $autobins; do
 		echo "    add_autobin(\"$bin\", \"$x_mod\");"
@@ -35,6 +35,9 @@ for x_mod in $x_mods; do
 	    for cond in $autoprefixconds; do
 		echo "    add_autocond(\"$cond\", 0, \"$x_mod\");"
 	    done
+	    for param in $autoparams; do
+		echo "    add_autoparam(\"$param\", \"$x_mod\");"
+	    done
 	    for dep in $moddeps; do
 		case $bin_mods in
 		    *" $dep "*)
diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh
index 2f79acbc3..cd92c7f07 100644
--- a/Src/mkmakemod.sh
+++ b/Src/mkmakemod.sh
@@ -24,6 +24,7 @@
 #   autoinfixconds  infix condition codes defined by the module, for
 #                   autoloading (without the leading `-')
 #   autoprefixconds like autoinfixconds, but for prefix condition codes
+#   autoparams      parameters 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)
@@ -170,7 +171,7 @@ if $first_stage; then
     for module in $here_modules; do
 
 	unset moddeps nozshdep alwayslink hasexport
-	unset autobins autoinfixconds autoprefixconds
+	unset autobins autoinfixconds autoprefixconds autoparams
 	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 ff386c630..09f1fd5db 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -539,18 +539,24 @@ load_module(char const *name)
 	m = zcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	m->handle = handle;
+	m->flags |= MOD_SETUP;
+	PERMALLOC {
+	    node = addlinknode(modules, m);
+	} LASTALLOC;
 	if (setup_module(m) || init_module(m)) {
 	    finish_module(m);
+	    remnode(modules, node);
 	    zsfree(m->nam);
 	    zfree(m, sizeof(*m));
+	    m->flags &= ~MOD_SETUP;
 	    return NULL;
 	}
-	PERMALLOC {
-	    addlinknode(modules, m);
-	} LASTALLOC;
+	m->flags &= ~MOD_SETUP;
 	return m;
     } 
     m = (Module) getdata(node);
+    if (m->flags & MOD_SETUP)
+	return m;
     if (m->flags & MOD_UNLOAD)
 	m->flags &= ~MOD_UNLOAD;
     else if (m->handle)
@@ -570,17 +576,22 @@ load_module(char const *name)
     if (!m->handle) {
 	if (!(m->handle = do_load_module(name)))
 	    return NULL;
+	m->flags |= MOD_SETUP;
 	if (setup_module(m)) {
 	    finish_module(m->handle);
 	    m->handle = NULL;
+	    m->flags &= ~MOD_SETUP;
 	    return NULL;
 	}
     }
+    m->flags |= MOD_SETUP;
     if (init_module(m)) {
 	finish_module(m->handle);
 	m->handle = NULL;
+	m->flags &= ~MOD_SETUP;
 	return NULL;
     }
+    m->flags &= ~MOD_SETUP;
     return m;
 }
 
@@ -690,6 +701,8 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
 	return bin_zmodload_auto(nam, args, ops);
     else if (ops['c'] || ops['C'])
 	return bin_zmodload_cond(nam, args, ops);
+    else if (ops['p'])
+	return bin_zmodload_param(nam, args, ops);
     else
 	return bin_zmodload_load(nam, args, ops);
 }
@@ -888,6 +901,66 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
     }
 }
 
+static void
+printautoparams(HashNode hn, int lon)
+{
+    Param pm = (Param) hn;
+
+    if (pm->flags & PM_AUTOLOAD) {
+	if (lon)
+	    printf("zmodload -p %s %s\n", pm->u.str, pm->nam);
+	else
+	    printf("%s (%s)\n", pm->nam, pm->u.str);
+    }
+}
+
+/**/
+static int
+bin_zmodload_param(char *nam, char **args, char *ops)
+{
+    int ret = 0;
+
+    if (ops['u']) {
+	/* remove autoloaded parameters */
+	for (; *args; args++) {
+	    Param pm = (Param) gethashnode2(paramtab, *args);
+
+	    if (!pm) {
+		if (!ops['i']) {
+		    zwarnnam(nam, "%s: no such parameter", *args, 0);
+		    ret = 1;
+		}
+	    } else if (!(pm->flags & PM_AUTOLOAD)) {
+		zwarnnam(nam, "%s: parameter is already defined", *args, 0);
+		ret = 1;
+	    } else
+		unsetparam_pm(pm, 0, 1);
+	}
+	return ret;
+    } else if (!*args) {
+	scanhashtable(paramtab, 1, 0, 0, printautoparams, ops['L']);
+	return 0;
+    } else {
+	/* add autoloaded parameters */
+	char *modnam;
+
+	modnam = *args++;
+	if(isset(RESTRICTED) && strchr(modnam, '/')) {
+	    zwarnnam(nam, "%s: restricted", modnam, 0);
+	    return 1;
+	}
+	do {
+	    char *pnam = *args ? *args++ : modnam;
+	    if (strchr(pnam, '/')) {
+		zwarnnam(nam, "%s: `/' is illegal in a parameter", pnam, 0);
+		ret = 1;
+	    } else
+		add_autoparam(pnam, modnam);
+	} while(*args);
+	return ret;
+    }
+}
+
 /**/
 int
 unload_module(Module m, LinkNode node)
@@ -1114,6 +1187,71 @@ addconddefs(char const *nam, Conddef c, int size)
     return hadf ? hads : 1;
 }
 
+/* This adds the given parameter definition. The return value is zero on *
+ * success and 1 on failure. */
+
+/**/
+int
+addparamdef(Paramdef d)
+{
+    Param pm;
+
+    if ((pm = (Param) gethashnode2(paramtab, d->name)))
+	unsetparam_pm(pm, 0, 1);
+
+    if (!(pm = createparam(d->name, d->flags)) &&
+	!(pm = (Param) paramtab->getnode(paramtab, d->name)))
+	return 1;
+
+    pm->level = 0;
+    pm->u.data = d->var;
+    pm->sets.ifn = (void (*)(Param, long)) d->set;
+    pm->gets.ifn = (long (*)(Param)) d->get;
+    pm->unsetfn = (void (*)(Param, int)) d->unset;
+
+    return 0;
+}
+
+/* This adds multiple parameter definitions. This is like addbuiltins(). */
+
+/**/
+int
+addparamdefs(char const *nam, Paramdef d, int size)
+{
+    int hads = 0, hadf = 0;
+
+    while (size--) {
+	if (addparamdef(d)) {
+	    zwarnnam(nam, "error when adding parameter `%s'", d->name, 0);
+	    hadf = 1;
+	} else
+	    hads = 2;
+	d++;
+    }
+    return hadf ? hads : 1;
+}
+
+/* Delete parameters defined. No error checking yet. */
+
+/**/
+int
+deleteparamdef(Paramdef d)
+{
+    unsetparam(d->name);
+    return 0;
+}
+
+/**/
+int
+deleteparamdefs(char const *nam, Paramdef d, int size)
+{
+    while (size--) {
+	deleteparamdef(d);
+	d++;
+    }
+    return 1;
+}
+
 #ifdef DYNAMIC
 
 /* This adds a definition for autoloading a module for a condition. */
@@ -1188,4 +1326,20 @@ deleteconddefs(char const *nam, Conddef c, int size)
     return hadf ? hads : 1;
 }
 
+/* This adds a definition for autoloading a module for a parameter. */
+
+/**/
+void
+add_autoparam(char *nam, char *module)
+{
+    Param pm;
+
+    if ((pm = (Param) gethashnode2(paramtab, nam)))
+	unsetparam_pm(pm, 0, 1);
+
+    pm = setsparam(ztrdup(nam), ztrdup(module));
+
+    pm->flags |= PM_AUTOLOAD;
+}
+
 #endif
diff --git a/Src/params.c b/Src/params.c
index dbc6ce8d8..079b89cf6 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -267,8 +267,8 @@ newparamtable(int size, char const *name)
     ht->emptytable  = emptyhashtable;
     ht->filltable   = NULL;
     ht->addnode     = addhashnode;
-    ht->getnode     = gethashnode2;
-    ht->getnode2    = gethashnode2;
+    ht->getnode     = getparamnode;
+    ht->getnode2    = getparamnode;
     ht->removenode  = removehashnode;
     ht->disablenode = NULL;
     ht->enablenode  = NULL;
@@ -278,6 +278,23 @@ newparamtable(int size, char const *name)
     return ht;
 }
 
+/**/
+static HashNode
+getparamnode(HashTable ht, char *nam)
+{
+    HashNode hn = gethashnode2(ht, nam);
+    Param pm = (Param) hn;
+
+    if (pm && pm->u.str && (pm->flags & PM_AUTOLOAD)) {
+	char *mn = dupstring(pm->u.str);
+
+	if (!load_module(mn))
+	    return NULL;
+	hn = gethashnode2(ht, nam);
+    }
+    return hn;
+}
+
 /* Copy a parameter hash table */
 
 static HashTable outtable;
@@ -542,7 +559,7 @@ createparam(char *name, int flags)
     Param pm, oldpm;
 
     if (name != nulstring) {
-	oldpm = (Param) paramtab->getnode(paramtab, name);
+	oldpm = (Param) gethashnode2(paramtab, name);
 
 	if (oldpm && oldpm->level == locallevel) {
 	    if (!(oldpm->flags & PM_UNSET) || (oldpm->flags & PM_SPECIAL)) {
@@ -2698,7 +2715,7 @@ printparamnode(HashNode hn, int printflags)
     Param p = (Param) hn;
     char *t, **u;
 
-    if (p->flags & PM_UNSET)
+    if (p->flags & (PM_UNSET | PM_AUTOLOAD))
 	return;
 
     /* Print the attributes of the parameter */
diff --git a/Src/zsh.h b/Src/zsh.h
index c3c853dfd..1eefc51c1 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -231,6 +231,7 @@ typedef struct hashtable *HashTable;
 typedef struct reswd     *Reswd;
 typedef struct alias     *Alias;
 typedef struct param     *Param;
+typedef struct paramdef  *Paramdef;
 typedef struct cmdnam    *Cmdnam;
 typedef struct shfunc    *Shfunc;
 typedef struct funcwrap  *FuncWrap;
@@ -850,6 +851,7 @@ struct module {
 
 #define MOD_BUSY    (1<<0)
 #define MOD_UNLOAD  (1<<1)
+#define MOD_SETUP   (1<<2)
 
 /* node used in parameter hash table (paramtab) */
 
@@ -923,6 +925,7 @@ struct param {
 #define PM_RESTRICTED	(1<<15) /* cannot be changed in restricted mode       */
 #define PM_UNSET	(1<<16)	/* has null value                             */
 #define PM_REMOVABLE	(1<<17)	/* special can be removed from paramtab */
+#define PM_AUTOLOAD     (1<<18) /* autoloaded from module */
 
 /* Flags for extracting elements of arrays and associative arrays */
 #define SCANPM_WANTVALS   (1<<0)
@@ -955,6 +958,27 @@ struct param {
 #define PF_ASSIGN	0x02	/* argument handled like the RHS of foo=bar */
 #define PF_SINGLE	0x04	/* single word substitution */
 
+struct paramdef {
+    char *name;
+    int flags;
+    void *var;
+    void *set;
+    void *get;
+    void *unset;
+};
+
+#define PARAMDEF(name, flags, var, set, get, unset) \
+    { name, flags, (void *) var, (void *) set, (void *) get, (void *) unset }
+#define INTPARAMDEF(name, var) \
+    { name, PM_INTEGER, (void *) var, (void *) intvarsetfn, \
+      (void *) intvargetfn, (void *) stdunsetfn }
+#define STRPARAMDEF(name, var) \
+    { name, PM_SCALAR, (void *) var, (void *) strvarsetfn, \
+      (void *) strvargetfn, (void *) stdunsetfn }
+#define ARRPARAMDEF(name, var) \
+    { name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \
+      (void *) arrvargetfn, (void *) stdunsetfn }
+
 /* node for named directory hash table (nameddirtab) */
 
 struct nameddir {