about summary refs log tree commit diff
path: root/Src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/module.c')
-rw-r--r--Src/module.c136
1 files changed, 96 insertions, 40 deletions
diff --git a/Src/module.c b/Src/module.c
index a89010d74..c4fb95c78 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -1967,7 +1967,7 @@ finish_module(Module m)
 
 /**/
 static int
-do_module_features(Module m, char **enablesstr, int flags)
+do_module_features(Module m, Feature_enables enablesarr, int flags)
 {
     char **features;
     int ret = 0;
@@ -2019,19 +2019,26 @@ do_module_features(Module m, char **enablesstr, int flags)
 		    (void)autofeatures(NULL, m->node.nam, arg, 0,
 				       FEAT_IGNORE|FEAT_REMOVE);
 		    /*
-		     * don't want to try to enable *that*... 
+		     * don't want to try to enable *that*...
 		     * expunge it from the enable string.
 		     */
-		    if (enablesstr) {
-			for (ptr = enablesstr; *ptr; ptr++) {
-			    if (!strcmp(al, *ptr)) {
+		    if (enablesarr) {
+			Feature_enables fep;
+			for (fep = enablesarr; fep->str; fep++) {
+			    char *str = fep->str;
+			    if (*str == '+' || *str == '-')
+				str++;
+			    if (fep->pat ? pattry(fep->pat, al) :
+				!strcmp(al, str)) {
 				/* can't enable it after all, so return 1 */
 				ret = 1;
-				while (*ptr) {
-				    *ptr = ptr[1];
-				    ptr++;
+				while (fep->str) {
+				    fep->str = fep[1].str;
+				    fep->pat = fep[1].pat;
+				    fep++;
 				}
-				break;
+				if (!fep->pat)
+				    break;
 			    }
 			}
 		    }
@@ -2039,11 +2046,11 @@ do_module_features(Module m, char **enablesstr, int flags)
 	    }
 	}
 
-	if (enablesstr) {
-	    char **ep;
-	    for (ep = enablesstr; *ep; ep++) {
-		char **fp, *esp = *ep;
-		int on = 1;
+	if (enablesarr) {
+	    Feature_enables fep;
+	    for (fep = enablesarr; fep->str; fep++) {
+		char **fp, *esp = fep->str;
+		int on = 1, found = 0;
 		if (*esp == '+')
 		    esp++;
 		else if (*esp == '-') {
@@ -2051,13 +2058,17 @@ do_module_features(Module m, char **enablesstr, int flags)
 		    esp++;
 		}
 		for (fp = features; *fp; fp++)
-		    if (!strcmp(*fp, esp)) {
+		    if (fep->pat ? pattry(fep->pat, *fp) : !strcmp(*fp, esp)) {
 			enables[fp - features] = on;
-			break;
+			found++;
+			if (!fep->pat)
+			    break;
 		    }
-		if (!*fp) {
+		if (!found) {
 		    if (!(flags & FEAT_IGNORE))
-			zwarn("module `%s' has no such feature: `%s'",
+			zwarn(fep->pat ?
+			      "module `%s' has no feature matching: `%s'" :
+			      "module `%s' has no such feature: `%s'",
 			      m->node.nam, esp);
 		    return 1;
 		}
@@ -2075,7 +2086,7 @@ do_module_features(Module m, char **enablesstr, int flags)
 
 	if (enables_module(m, &enables))
 	    return 2;
-    } else if (enablesstr) {
+    } else if (enablesarr) {
 	if (!(flags & FEAT_IGNORE))
 	    zwarn("module `%s' does not support features", m->node.nam);
 	return 1;
@@ -2097,9 +2108,9 @@ do_module_features(Module m, char **enablesstr, int flags)
 
 /**/
 static int
-do_boot_module(Module m, char **enablesstr, int silent)
+do_boot_module(Module m, Feature_enables enablesarr, int silent)
 {
-    int ret = do_module_features(m, enablesstr,
+    int ret = do_module_features(m, enablesarr,
 				 silent ? FEAT_IGNORE|FEAT_CHECKAUTO :
 				 FEAT_CHECKAUTO);
 
@@ -2159,7 +2170,7 @@ modname_ok(char const *p)
 
 /**/
 mod_export int
-load_module(char const *name, char **enablesstr, int silent)
+load_module(char const *name, Feature_enables enablesarr, int silent)
 {
     Module m;
     void *handle = NULL;
@@ -2194,7 +2205,7 @@ load_module(char const *name, char **enablesstr, int silent)
 	modulestab->addnode(modulestab, ztrdup(name), m);
 
 	if ((set = setup_module(m)) ||
-	    (bootret = do_boot_module(m, enablesstr, silent)) == 1) {
+	    (bootret = do_boot_module(m, enablesarr, silent)) == 1) {
 	    if (!set)
 		do_cleanup_module(m);
 	    finish_module(m);
@@ -2263,7 +2274,7 @@ load_module(char const *name, char **enablesstr, int silent)
 	m->node.flags |= MOD_INIT_S;
     }
     m->node.flags |= MOD_SETUP;
-    if ((bootret = do_boot_module(m, enablesstr, silent)) == 1) {
+    if ((bootret = do_boot_module(m, enablesarr, silent)) == 1) {
 	do_cleanup_module(m);
 	finish_module(m);
 	if (m->node.flags & MOD_LINKED)
@@ -2301,7 +2312,7 @@ load_module(char const *name, char **enablesstr, int silent)
 
 /**/
 mod_export int
-require_module(const char *module, char **features)
+require_module(const char *module, Feature_enables features)
 {
     Module m = NULL;
     int ret = 0;
@@ -2962,7 +2973,10 @@ bin_zmodload_load(char *nam, char **args, Options ops)
 static int
 bin_zmodload_features(const char *nam, char **args, Options ops)
 {
+    int iarg;
     char *modname = *args;
+    Patprog *patprogs;
+    Feature_enables features, fep;
 
     if (modname)
 	args++;
@@ -2986,6 +3000,23 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 	return 1;
     }
 
+    if (OPT_ISSET(ops,'m')) {
+	char **argp;
+	Patprog *patprogp;
+
+	/* not NULL terminated */
+	patprogp = patprogs =
+	    (Patprog *)zhalloc(arrlen(args)*sizeof(Patprog));
+	for (argp = args; *argp; argp++, patprogp++) {
+	    char *arg = *argp;
+	    if (*arg == '+' || *arg == '-')
+		arg++;
+	    tokenize(arg);
+	    *patprogp = patcompile(arg, 0, 0);
+	}
+    } else
+	patprogs = NULL;
+
     if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) {
 	/*
 	 * With option 'l', list all features one per line with + or -.
@@ -3063,9 +3094,9 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 		     m->node.nam);
 	    return 1;
 	}
-	for (arrp = args; *arrp; arrp++) {
+	for (arrp = args, iarg = 0; *arrp; arrp++, iarg++) {
 	    char *arg = *arrp;
-	    int on;
+	    int on, found = 0;
 	    if (*arg == '-') {
 		on = 0;
 		arg++;
@@ -3075,17 +3106,22 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 	    } else
 		on = -1;
 	    for (fp = features, ep = enables; *fp; fp++, ep++) {
-		if (!strcmp(arg, *fp)) {
+		if (patprogs ? pattry(patprogs[iarg], *fp) :
+		    !strcmp(arg, *fp)) {
 		    /* for -e, check given state, if any */
 		    if (OPT_ISSET(ops,'e') && on != -1 &&
 			on != (*ep & 1))
 			return 1;
-		    break;
+		    found++;
+		    if (!patprogs)
+			break;
 		}
 	    }
-	    if (!*fp) {
+	    if (!found) {
 		if (!OPT_ISSET(ops,'e'))
-		    zwarnnam(nam, "module `%s' has no such feature: `%s'",
+		    zwarnnam(nam, patprogs ?
+			     "module `%s' has no feature matching: `%s'" :
+			     "module `%s' has no such feature: `%s'",
 			     *arrp);
 		return 1;
 	    }
@@ -3100,12 +3136,13 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 		    continue;
 		if (*args) {
 		    char **argp;
-		    for (argp = args; *argp; argp++) {
+		    for (argp = args, iarg = 0; *argp; argp++, iarg++) {
 			char *arg = *argp;
 			/* ignore +/- for consistency */
 			if (*arg == '+' || *arg == '-')
 			    arg++;
-			if (!strcmp(*fp, arg))
+			if (patprogs ? pattry(patprogs[iarg], *fp) :
+			    !strcmp(*fp, arg))
 			    break;
 		    }
 		    if (!*argp)
@@ -3121,11 +3158,12 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 	    int term;
 	    if (*args) {
 		char **argp;
-		for (argp = args; *argp; argp++) {
+		for (argp = args, iarg = 0; *argp; argp++, iarg++) {
 		    char *arg = *argp;
 		    if (*arg == '+' || *arg == '-')
 			arg++;
-		    if (!strcmp(*fp, *argp))
+		    if (patprogs ? pattry(patprogs[iarg], *fp) :
+			!strcmp(*fp, *argp))
 			break;
 		}
 		if (!*argp)
@@ -3161,6 +3199,10 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 	zwarnnam(nam, "-P can only be used with -l or -L");
 	return 1;
     } else if (OPT_ISSET(ops,'a')) {
+	if (OPT_ISSET(ops,'m')) {
+	    zwarnnam(nam, "-m cannot be used with -a");
+	    return 1;
+	}
 	/*
 	 * With zmodload -aF, we always use the effect of -i.
 	 * The thinking is that marking a feature for
@@ -3175,7 +3217,18 @@ bin_zmodload_features(const char *nam, char **args, Options ops)
 	return autofeatures(nam, modname, args, 0, FEAT_IGNORE);
     }
 
-    return require_module(modname, args);
+    fep = features =
+	(Feature_enables)zhalloc((arrlen(args)+1)*sizeof(*fep));
+
+    while (*args) {
+	fep->str = *args++;
+	fep->pat = patprogs ? *patprogs++ : NULL;
+	fep++;
+    }
+    fep->str = NULL;
+    fep->pat = NULL;
+
+    return require_module(modname, features);
 }
 
 
@@ -3330,14 +3383,17 @@ handlefeatures(Module m, Features f, int **enables)
 mod_export int
 ensurefeature(const char *modname, const char *prefix, const char *feature)
 {
-    char *f, *features[2];
+    char *f;
+    struct feature_enables features[2];
 
     if (!feature)
 	return require_module(modname, NULL);
     f = dyncat(prefix, feature);
 
-    features[0] = f;
-    features[1] = NULL;
+    features[0].str = f;
+    features[0].pat = NULL;
+    features[1].str = NULL;
+    features[1].pat = NULL;
     return require_module(modname, features);
 }
 
@@ -3435,7 +3491,7 @@ autofeatures(const char *cmdnam, const char *module, char **features,
 	    zwarnnam(cmdnam, "%s: `/' is illegal in a %s", fnam, typnam);
 	    ret = 1;
 	    continue;
-	} 
+	}
 
 	if (!module) {
 	    /*