zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: module-defined conditions
@ 1998-12-09 12:17 Sven Wischnowsky
  0 siblings, 0 replies; 3+ messages in thread
From: Sven Wischnowsky @ 1998-12-09 12:17 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> On Dec 8,  4:30pm, Sven Wischnowsky wrote:
> } Subject: PATCH: module-defined conditions
> }
> } (I can easily be convinced to remove the code that
> } allows one to redefine builtin conditions, maybe it's too dangerous
> 
> I think removing that code is a very good idea, especially if:
> 
> } it would also simplify the code and zmodload...).

Yes, I thought a bit more about all this yesterday evening and came to 
the same conclusion.

The patch below removes the possibility to define conditions that take 
precedence over the builtin ones.

It also fixes the last patch: I forgot to change text.c. This required 
changing a bit more so I just went ahead and modified the thing to
allow the definition of prefix conditions that take more than one (and 
evan an variable number of) string(s).

E.g. the example module now defines a prefix condition `-len' that can 
take one or two strings.

Bye
 Sven

P.S.: This patch also inserts some braces in parse.c and utils.c,
      keeping gcc from complaining about `possibly ambiguous else's.

diff -c os/builtin.c Src/builtin.c
*** os/builtin.c	Tue Dec  8 16:31:15 1998
--- Src/builtin.c	Wed Dec  9 09:09:26 1998
***************
*** 120,126 ****
      BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
  
  #ifdef DYNAMIC
!     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicCI", NULL),
  #endif
  };
  
--- 120,126 ----
      BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
  
  #ifdef DYNAMIC
!     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicI", NULL),
  #endif
  };
  
diff -c os/cond.c Src/cond.c
*** os/cond.c	Tue Dec  8 16:31:15 1998
--- Src/cond.c	Wed Dec  9 12:01:23 1998
***************
*** 43,48 ****
--- 43,68 ----
  	return evalcond(c->left) && evalcond(c->right);
      case COND_OR:
  	return evalcond(c->left) || evalcond(c->right);
+     case COND_MOD:
+     case COND_MODI:
+ 	{
+ 	    Conddef cd;
+ 
+ 	    if ((cd = getconddef((c->type == COND_MODI), (char *) c->left, 1))) {
+ 		if (c->type == COND_MOD) {
+ 		    int l = arrlen((char **) c->right);
+ 
+ 		    if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
+ 			zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
+ 			return 0;
+ 		    }
+ 		}
+ 		return cd->handler(cd, (char **) c->right);
+ 	    }
+ 	    else
+ 		zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
+ 	    return 0;
+ 	}
      }
      singsub((char **)&c->left);
      untokenize(c->left);
***************
*** 148,161 ****
  	    return d == st->st_dev && i == st->st_ino;
  	}
      default:
! 	{
! 	    Conddef cd;
! 
! 	    if ((cd = getnumconddef(c->type)))
! 		return cd->handler(cd, c->left, c->right);
! 	    else
! 		zerr("bad cond structure", NULL, 0);
! 	}
      }
      return 0;
  }
--- 168,174 ----
  	    return d == st->st_dev && i == st->st_ino;
  	}
      default:
! 	zerr("bad cond structure", NULL, 0);
      }
      return 0;
  }
diff -c os/init.c Src/init.c
*** os/init.c	Tue Dec  8 16:31:16 1998
--- Src/init.c	Wed Dec  9 09:11:05 1998
***************
*** 592,598 ****
      createnameddirtable();  /* create hash table for named directories */
      createparamtable();     /* create paramater hash table             */
  
!     pre_conds = post_conds = NULL;
  
  #ifdef TIOCGWINSZ
      adjustwinsize();
--- 592,598 ----
      createnameddirtable();  /* create hash table for named directories */
      createparamtable();     /* create paramater hash table             */
  
!     condtab = NULL;
  
  #ifdef TIOCGWINSZ
      adjustwinsize();
diff -c os/module.c Src/module.c
*** os/module.c	Tue Dec  8 16:31:17 1998
--- Src/module.c	Wed Dec  9 12:05:53 1998
***************
*** 161,232 ****
      return hadf ? hads : 1;
  }
  
! /* The lists of module-defined conditions. pre_conds contains the ones *
!  * that take precedence over the builtin ones. */
  
  /**/
! Conddef pre_conds;
! 
! /**/
! Conddef post_conds;
! 
! /* Used to number module-defined conditions. */
! 
! static int cond_num = 256;
  
  /* This gets a condition definition with the given name. The first        *
!  * argument says if we have to look for a condition that takes precedence *
!  * over the builtin ones and the second argument says if we have to look  *
!  * for an infix condition. */
! 
! /**/
! Conddef
! getconddef(int prec, int inf, char *name)
! {
!     Conddef p = (prec ? pre_conds : post_conds);
! 
!     for (; p; p = p->next) {
! 	if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
! 	    !strcmp(name, p->name))
! 	    return p;
!     }
!     return NULL;
! }
! 
! /* Find a condition definition given its number. */
  
  /**/
  Conddef
! getnumconddef(int n)
  {
      Conddef p;
      int f = 1;
  
      do {
! 	for (p = pre_conds; p; p = p->next) {
! 	    if (n == p->num)
  		break;
  	}
! 	if (!p)
! 	    for(p = post_conds; p; p = p->next) {
! 		if (n == p->num)
! 		    break;
! 	    }
! 	if (p && p->module) {
  	    /* This is a definition for an autoloaded condition, load the *
  	     * module if we haven't tried that already. */
  	    if (f) {
  		load_module(p->module);
  		f = 0;
  		p = NULL;
! 	    }
! 	    else
  		break;
! 	}
! 	else
  	    break;
      } while (!p);
- 
      return p;
  }
  
--- 161,200 ----
      return hadf ? hads : 1;
  }
  
! /* The list of module-defined conditions. */
  
  /**/
! Conddef condtab;
  
  /* This gets a condition definition with the given name. The first        *
!  * argument says if we have to look for an infix condition. The last      *
!  * argument is non-zero if we should autoload modules if needed. */
  
  /**/
  Conddef
! getconddef(int inf, char *name, int autol)
  {
      Conddef p;
      int f = 1;
  
      do {
! 	for (p = condtab; p; p = p->next) {
! 	    if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
! 		!strcmp(name, p->name))
  		break;
  	}
! 	if (autol && p && p->module) {
  	    /* This is a definition for an autoloaded condition, load the *
  	     * module if we haven't tried that already. */
  	    if (f) {
  		load_module(p->module);
  		f = 0;
  		p = NULL;
! 	    } else
  		break;
! 	} else
  	    break;
      } while (!p);
      return p;
  }
  
***************
*** 238,246 ****
  int
  addconddef(Conddef c)
  {
!     Conddef p = getconddef((c->flags & CONDF_PREC), (c->flags & CONDF_INFIX),
! 			   c->name);
!     int nu = cond_num++;
  
      if (p) {
  	if (!p->module || (p->flags & CONDF_ADDED))
--- 206,212 ----
  int
  addconddef(Conddef c)
  {
!     Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0);
  
      if (p) {
  	if (!p->module || (p->flags & CONDF_ADDED))
***************
*** 248,269 ****
  
  	/* There is an autoload definition. */
  
- 	nu = p->num;
- 
  	deleteconddef(p);
      }
!     if (c->flags & CONDF_PREC) {
! 	c->next = pre_conds;
! 	pre_conds = c;
!     } else {
! 	c->next = post_conds;
! 	post_conds = c;
!     }
!     c->num = nu;
      return 0;
  }
  
! /* This add multiple condition definitions. This is like addbuiltins(). */
  
  /**/
  int
--- 214,227 ----
  
  	/* There is an autoload definition. */
  
  	deleteconddef(p);
      }
!     c->next = condtab;
!     condtab = c;
      return 0;
  }
  
! /* This adds multiple condition definitions. This is like addbuiltins(). */
  
  /**/
  int
***************
*** 290,303 ****
  
  /**/
  int
! add_autocond(char *nam, int prec, int inf, char *module)
  {
      Conddef c = zalloc(sizeof(*c));
  
      c->name = ztrdup(nam);
!     c->flags =
! 	(prec ? CONDF_PREC  : 0) |
! 	(inf  ? CONDF_INFIX : 0);
      c->module = ztrdup(module);
  
      if (addconddef(c)) {
--- 248,259 ----
  
  /**/
  int
! add_autocond(char *nam, int inf, char *module)
  {
      Conddef c = zalloc(sizeof(*c));
  
      c->name = ztrdup(nam);
!     c->flags = (inf  ? CONDF_INFIX : 0);
      c->module = ztrdup(module);
  
      if (addconddef(c)) {
***************
*** 317,333 ****
  int
  deleteconddef(Conddef c)
  {
!     Conddef p = ((c->flags & CONDF_PREC) ? pre_conds : post_conds), q = NULL;
  
!     for (; p && p != c; q = p, p = p->next);
  
      if (p) {
  	if (q)
  	    q->next = p->next;
! 	else if (c->flags & CONDF_PREC)
! 	    pre_conds = p->next;
! 	else
! 	    post_conds = p->next;
  		
  	if (p->module) {
  	    /* autoloaded, free it */
--- 273,287 ----
  int
  deleteconddef(Conddef c)
  {
!     Conddef p, q;
  
!     for (p = condtab, q = NULL; p && p != c; q = p, p = p->next);
  
      if (p) {
  	if (q)
  	    q->next = p->next;
! 	else 
! 	    condtab = p->next;
  		
  	if (p->module) {
  	    /* autoloaded, free it */
***************
*** 781,787 ****
      if (ops['u']) {
  	/* remove autoloaded conditions */
  	for (; *args; args++) {
! 	    Conddef cd = getconddef(ops['C'], ops['I'], *args);
  
  	    if (!cd) {
  		if (!ops['i']) {
--- 735,741 ----
      if (ops['u']) {
  	/* remove autoloaded conditions */
  	for (; *args; args++) {
! 	    Conddef cd = getconddef(ops['I'], *args, 0);
  
  	    if (!cd) {
  		if (!ops['i']) {
***************
*** 799,836 ****
  	/* list autoloaded conditions */
  	Conddef p;
  
! 	if (ops['C'])
! 	    for (p = pre_conds; p; p = p->next) {
! 		if (p->module) {
! 		    if (ops['L']) {
! 			fputs("zmodload -C", stdout);
! 			if (p->flags & CONDF_INFIX)
! 			    putchar('I');
! 			printf(" %s %s\n", p->module, p->name);
! 		    } else {
! 			fputs("pre ", stdout);
! 			if (p->flags & CONDF_INFIX)
! 			    fputs("infix ", stdout);
! 			printf("%s (%s)\n",p->name, p->module);
! 		    }
! 		}
! 	    }
! 	if (ops['c'])
! 	    for (p = post_conds; p; p = p->next) {
! 		if (p->module) {
! 		    if (ops['L']) {
! 			fputs("zmodload -c", stdout);
! 			if (p->flags & CONDF_INFIX)
! 			    putchar('I');
! 			printf(" %s %s\n", p->module, p->name);
! 		    } else {
! 			fputs("post ", stdout);
! 			if (p->flags & CONDF_INFIX)
! 			    fputs("infix ", stdout);
! 			printf("%s (%s)\n",p->name, p->module);
! 		    }
  		}
  	    }
  	return 0;
      } else {
  	/* add autoloaded conditions */
--- 753,773 ----
  	/* list autoloaded conditions */
  	Conddef p;
  
! 	for (p = condtab; p; p = p->next) {
! 	    if (p->module) {
! 		if (ops['L']) {
! 		    fputs("zmodload -c", stdout);
! 		    if (p->flags & CONDF_INFIX)
! 			putchar('I');
! 		    printf(" %s %s\n", p->module, p->name);
! 		} else {
! 		    fputs("post ", stdout);
! 		    if (p->flags & CONDF_INFIX)
! 			fputs("infix ", stdout);
! 		    printf("%s (%s)\n",p->name, p->module);
  		}
  	    }
+ 	}
  	return 0;
      } else {
  	/* add autoloaded conditions */
***************
*** 846,852 ****
  	    if (strchr(cnam, '/')) {
  		zwarnnam(nam, "%s: `/' is illegal in a condition", cnam, 0);
  		ret = 1;
! 	    } else if (add_autocond(cnam, ops['C'], ops['I'], modnam) && !ops['i']) {
  		zwarnnam(nam, "failed to add condition %s", cnam, 0);
  		ret = 1;
  	    }
--- 783,789 ----
  	    if (strchr(cnam, '/')) {
  		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);
  		ret = 1;
  	    }
diff -c os/parse.c Src/parse.c
*** os/parse.c	Tue Dec  8 16:31:18 1998
--- Src/parse.c	Wed Dec  9 11:51:47 1998
***************
*** 114,120 ****
      }
      if (tok == ENDINPUT)
  	return NULL;
!     if ((sl = par_sublist()))
  	if (tok == ENDINPUT) {
  	    l = (List) make_list();
  	    l->type = Z_SYNC;
--- 114,120 ----
      }
      if (tok == ENDINPUT)
  	return NULL;
!     if ((sl = par_sublist())) {
  	if (tok == ENDINPUT) {
  	    l = (List) make_list();
  	    l->type = Z_SYNC;
***************
*** 137,142 ****
--- 137,143 ----
  	    yylex();
  	} else
  	    l = NULL;
+     }
      if (!l) {
  	if (errflag) {
  	    yyerror();
***************
*** 181,187 ****
  
      while (tok == SEPER)
  	yylex();
!     if ((sl = par_sublist()))
  	if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
  	    l = (List) make_list();
  	    l->left = sl;
--- 182,188 ----
  
      while (tok == SEPER)
  	yylex();
!     if ((sl = par_sublist())) {
  	if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
  	    l = (List) make_list();
  	    l->left = sl;
***************
*** 197,202 ****
--- 198,204 ----
  	    l->left = sl;
  	    l->type = Z_SYNC;
  	}
+     }
      return l;
  }
  
***************
*** 1139,1151 ****
  	condlex();
  	return c;
      }
!     if (tok != STRING)
  	if (tok && tok != LEXERR && condlex == testlex) {
  	    s1 = tokstr;
  	    condlex();
  	    return par_cond_double("-n", s1);
  	} else
  	    YYERROR;
      s1 = tokstr;
      if (condlex == testlex)
  	dble = (*s1 == '-' && strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1
--- 1141,1154 ----
  	condlex();
  	return c;
      }
!     if (tok != STRING) {
  	if (tok && tok != LEXERR && condlex == testlex) {
  	    s1 = tokstr;
  	    condlex();
  	    return par_cond_double("-n", s1);
  	} else
  	    YYERROR;
+     }
      s1 = tokstr;
      if (condlex == testlex)
  	dble = (*s1 == '-' && strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1
***************
*** 1165,1171 ****
  	c->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
  	return c;
      }
!     if (tok != STRING)
  	if (tok != LEXERR && condlex == testlex) {
  	    if (!dble)
  		return par_cond_double("-n", s1);
--- 1168,1174 ----
  	c->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
  	return c;
      }
!     if (tok != STRING) {
  	if (tok != LEXERR && condlex == testlex) {
  	    if (!dble)
  		return par_cond_double("-n", s1);
***************
*** 1173,1178 ****
--- 1176,1182 ----
  		return par_cond_double(s1, "1");
  	} else
  	    YYERROR;
+     }
      s2 = tokstr;
      incond++;			/* parentheses do globbing */
      condlex();
***************
*** 1180,1186 ****
      if (tok == STRING && !dble) {
  	s3 = tokstr;
  	condlex();
! 	return par_cond_triple(s1, s2, s3);
      } else
  	return par_cond_double(s1, s2);
  }
--- 1184,1202 ----
      if (tok == STRING && !dble) {
  	s3 = tokstr;
  	condlex();
! 	if (tok == STRING) {
! 	    LinkList l = newlinklist();
! 
! 	    addlinknode(l, s2);
! 	    addlinknode(l, s3);
! 
! 	    while (tok == STRING) {
! 		addlinknode(l, tokstr);
! 		condlex();
! 	    }
! 	    return par_cond_multi(s1, l);
! 	} else
! 	    return par_cond_triple(s1, s2, s3);
      } else
  	return par_cond_double(s1, s2);
  }
***************
*** 1311,1330 ****
  par_cond_double(char *a, char *b)
  {
      Cond n = (Cond) make_cond();
-     Conddef cd;
  
!     if ((cd = getconddef(1, 0, a+1)))
! 	n->type = cd->num;
!     else if (a[0] != '-' || !a[1])
  	COND_ERROR("parse error: condition expected: %s", a);
      else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1)
  	n->type = a[1];
!     else if ((cd = getconddef(0, 0, a+1)))
! 	n->type = cd->num;
!     else
! 	COND_ERROR("parse error: unrecognized condition: %s", a);
!     n->left = (void *) b;
!     n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
      return n;
  }
  
--- 1327,1349 ----
  par_cond_double(char *a, char *b)
  {
      Cond n = (Cond) make_cond();
  
!     n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
!     n->left = (void *) b;
!     if (a[0] != '-' || !a[1])
  	COND_ERROR("parse error: condition expected: %s", a);
      else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1)
  	n->type = a[1];
!     else {
! 	char *d[2];
! 
! 	n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
! 	n->type = COND_MOD;
! 	n->left = (void *) (a + 1);
! 	d[0] = b;
! 	d[1] = NULL;
! 	n->right = (void *) arrdup(d);
!     }
      return n;
  }
  
***************
*** 1349,1360 ****
  par_cond_triple(char *a, char *b, char *c)
  {
      Cond n = (Cond) make_cond();
-     Conddef cd;
      int t0;
  
!     if ((cd = getconddef(1, 1, b+1)))
! 	n->type = cd->num;
!     else if ((b[0] == Equals || b[0] == '=') &&
  	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2])))
  	n->type = COND_STREQ;
      else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
--- 1368,1379 ----
  par_cond_triple(char *a, char *b, char *c)
  {
      Cond n = (Cond) make_cond();
      int t0;
  
!     n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
!     n->left = (void *) a;
!     n->right = (void *) c;
!     if ((b[0] == Equals || b[0] == '=') &&
  	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2])))
  	n->type = COND_STREQ;
      else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
***************
*** 1362,1376 ****
      else if (b[0] == '-') {
  	if ((t0 = get_cond_num(b + 1)) > -1)
  	    n->type = t0 + COND_NT;
! 	else if ((cd = getconddef(0, 1, b+1)))
! 	    n->type = cd->num;
! 	else
! 	    COND_ERROR("unrecognized condition: %s", b);
      } else
  	COND_ERROR("condition expected: %s", b);
!     n->left = (void *) a;
!     n->right = (void *) c;
!     n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
      return n;
  }
  
--- 1381,1426 ----
      else if (b[0] == '-') {
  	if ((t0 = get_cond_num(b + 1)) > -1)
  	    n->type = t0 + COND_NT;
! 	else {
! 	    char *d[3];
! 
! 	    n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
! 	    n->type = COND_MODI;
! 	    n->left = (void *) (b + 1);
! 	    d[0] = a;
! 	    d[1] = c;
! 	    d[2] = NULL;
! 	    n->right = (void *) arrdup(d);
! 	}
!     } else if (a[0] == '-' && a[1]) {
! 	char *d[3];
! 
! 	n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
! 	n->type = COND_MOD;
! 	n->left = (void *) (a + 1);
! 	d[0] = b;
! 	d[1] = c;
! 	d[2] = NULL;
! 	n->right = (void *) arrdup(d);
      } else
  	COND_ERROR("condition expected: %s", b);
!     return n;
! }
! 
! /**/
! static Cond
! par_cond_multi(char *a, LinkList l)
! {
!     Cond n = (Cond) make_cond();
! 
!     n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
!     if (a[0] != '-' || !a[1])
! 	COND_ERROR("condition expected: %s", a);
!     else {
! 	n->type = COND_MOD;
! 	n->left = (void *) a;
! 	n->right = (void *) listarr(l);
!     }
      return n;
  }
  
diff -c os/text.c Src/text.c
*** os/text.c	Tue Dec  8 16:31:19 1998
--- Src/text.c	Wed Dec  9 11:47:08 1998
***************
*** 410,415 ****
--- 410,436 ----
  	taddstr(" || ");
  	getcond(nm->right, _Cond(nm->right)->type == COND_AND);
  	break;
+     case COND_MOD:
+ 	{
+ 	    /* Module defined prefix condition. */
+ 	    char **p = (char **) nm->right;
+ 
+ 	    taddstr("-");
+ 	    taddstr(nm->left);
+ 	    for (; *p; p++) {
+ 		taddstr(" ");
+ 		taddstr(*p);
+ 	    }
+ 	}
+ 	break;
+     case COND_MODI:
+ 	/* Module defined infix condition. */
+ 	taddstr(((char **) nm->right)[0]);
+ 	taddstr(" -");
+ 	taddstr(nm->left);
+ 	taddstr(" ");
+ 	taddstr(((char **) nm->right)[1]);
+ 	break;
      default:
  	if (nm->type <= COND_GE) {
  	    /* Binary test: `a = b' etc. */
diff -c os/utils.c Src/utils.c
*** os/utils.c	Tue Dec  8 16:31:20 1998
--- Src/utils.c	Wed Dec  9 11:54:50 1998
***************
*** 734,740 ****
  	    }
  	} else {
  	    if (st.st_size && st.st_atime <= st.st_mtime &&
! 		st.st_mtime > lastmailcheck)
  		if (!u) {
  		    fprintf(shout, "You have new mail.\n");
  		    fflush(shout);
--- 734,740 ----
  	    }
  	} else {
  	    if (st.st_size && st.st_atime <= st.st_mtime &&
! 		st.st_mtime > lastmailcheck) {
  		if (!u) {
  		    fprintf(shout, "You have new mail.\n");
  		    fflush(shout);
***************
*** 753,758 ****
--- 753,759 ----
  			underscore = usav;
  		    } LASTALLOC;
  		}
+ 	    }
  	    if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
  		st.st_atime > lastmailcheck && st.st_size) {
  		fprintf(shout, "The mail in %s has been read.\n", unmeta(*s));
***************
*** 1068,1081 ****
      else if (*s == '+')
  	s++;
  
!     if (!base)
  	if (*s != '0')
  	    base = 10;
  	else if (*++s == 'x' || *s == 'X')
  	    base = 16, s++;
  	else
  	    base = 8;
!  
      if (base <= 10)
  	for (; *s >= '0' && *s < ('0' + base); s++)
  	    ret = ret * base + *s - '0';
--- 1069,1082 ----
      else if (*s == '+')
  	s++;
  
!     if (!base) {
  	if (*s != '0')
  	    base = 10;
  	else if (*++s == 'x' || *s == 'X')
  	    base = 16, s++;
  	else
  	    base = 8;
!     }
      if (base <= 10)
  	for (; *s >= '0' && *s < ('0' + base); s++)
  	    ret = ret * base + *s - '0';
***************
*** 2139,2160 ****
  		n = dupstring(on);
  		break;
  	    case NT_LIST | NT_NODE:
! 		if (heap)
  		    if (useheap)
  			n =  duplist(on, (VFunc) dupstruct2);
  		    else
  			n = list2arr(on, (VFunc) dupstruct2);
  		else if (useheap)
  		    n = arr2list(on, (VFunc) dupstruct2);
  		else
  		    n = duparray(on, (VFunc) dupstruct2);
  		break;
  	    case NT_LIST | NT_STR:
! 		if (heap)
  		    if (useheap)
  			n = duplist(on, (VFunc) dupstring);
  		    else
  			n = list2arr(on, (VFunc) ztrdup);
  		else if (useheap)
  		    n = arr2list(on, (VFunc) dupstring);
  		else
--- 2140,2163 ----
  		n = dupstring(on);
  		break;
  	    case NT_LIST | NT_NODE:
! 		if (heap) {
  		    if (useheap)
  			n =  duplist(on, (VFunc) dupstruct2);
  		    else
  			n = list2arr(on, (VFunc) dupstruct2);
+ 		}
  		else if (useheap)
  		    n = arr2list(on, (VFunc) dupstruct2);
  		else
  		    n = duparray(on, (VFunc) dupstruct2);
  		break;
  	    case NT_LIST | NT_STR:
! 		if (heap) {
  		    if (useheap)
  			n = duplist(on, (VFunc) dupstring);
  		    else
  			n = list2arr(on, (VFunc) ztrdup);
+ 		}
  		else if (useheap)
  		    n = arr2list(on, (VFunc) dupstring);
  		else
***************
*** 2380,2390 ****
      for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
  	typtab[t0] |= ITOK | IMETA;
      for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
! 	if (inblank(*s))
  	    if (s[1] == *s)
  		s++;
  	    else
  		typtab[STOUC(*s)] |= IWSEP;
  	typtab[STOUC(*s == Meta ? *++s ^ 32 : *s)] |= ISEP;
      }
      for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++)
--- 2383,2394 ----
      for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
  	typtab[t0] |= ITOK | IMETA;
      for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
! 	if (inblank(*s)) {
  	    if (s[1] == *s)
  		s++;
  	    else
  		typtab[STOUC(*s)] |= IWSEP;
+ 	}
  	typtab[STOUC(*s == Meta ? *++s ^ 32 : *s)] |= ISEP;
      }
      for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++)
***************
*** 2408,2413 ****
--- 2412,2432 ----
  }
  
  /**/
+ char **
+ listarr(LinkList l)
+ {
+     char **x, **y;
+     LinkNode n;
+ 
+     x = y = (char **) ncalloc((countlinknodes(l) + 1) * sizeof(char *));
+ 
+     for (n = firstnode(l); n; incnode(n))
+ 	*x++ = dupstring((char *) getdata(n));
+     *x = NULL;
+     return y;
+ }
+ 
+ /**/
  static char *
  spname(char *oldname)
  {
***************
*** 3011,3021 ****
      char *p = buf, *n, *ret;
  
      while ((c = *s++)) {
! 	if (itok(c))
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	n = nicechar(c);
--- 3030,3041 ----
      char *p = buf, *n, *ret;
  
      while ((c = *s++)) {
! 	if (itok(c)) {
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
+ 	}
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	n = nicechar(c);
***************
*** 3036,3046 ****
      int c;
  
      while ((c = *s++)) {
! 	if (itok(c))
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	if(fputs(nicechar(c), stream) < 0)
--- 3056,3067 ----
      int c;
  
      while ((c = *s++)) {
! 	if (itok(c)) {
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
+ 	}
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	if(fputs(nicechar(c), stream) < 0)
***************
*** 3059,3069 ****
      int c;
  
      while ((c = *s++)) {
! 	if (itok(c))
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	l += strlen(nicechar(STOUC(c)));
--- 3080,3091 ----
      int c;
  
      while ((c = *s++)) {
! 	if (itok(c)) {
  	    if (c <= Comma)
  		c = ztokens[c - Pound];
  	    else 
  		continue;
+ 	}
  	if (c == Meta)
  	    c = *s++ ^ 32;
  	l += strlen(nicechar(STOUC(c)));
***************
*** 3330,3342 ****
  		}
  	    default:
  		if ((idigit(*s) && *s < '8') || *s == 'x') {
! 		    if (!fromwhere)
  			if (*s == '0')
  			    s++;
  			else if (*s != 'x') {
  			    *t++ = '\\', s--;
  			    continue;
  			}
  		    if (s[1] && s[2] && s[3]) {
  			svchar = s[3];
  			s[3] = '\0';
--- 3352,3365 ----
  		}
  	    default:
  		if ((idigit(*s) && *s < '8') || *s == 'x') {
! 		    if (!fromwhere) {
  			if (*s == '0')
  			    s++;
  			else if (*s != 'x') {
  			    *t++ = '\\', s--;
  			    continue;
  			}
+ 		    }
  		    if (s[1] && s[2] && s[3]) {
  			svchar = s[3];
  			s[3] = '\0';
diff -c os/zsh.h Src/zsh.h
*** os/zsh.h	Tue Dec  8 16:31:20 1998
--- Src/zsh.h	Wed Dec  9 11:20:05 1998
***************
*** 456,479 ****
  #define COND_GT    13
  #define COND_LE    14
  #define COND_GE    15
  
! typedef int (*CondHandler) _((Conddef, char *, char *));
  
  struct conddef {
!     Conddef next;
!     int num;
!     char *name;
!     int flags;
!     CondHandler handler;
!     char *module;
  };
  
  #define CONDF_INFIX  1
  #define CONDF_ADDED  2
- #define CONDF_PREC   4
  
! #define CONDDEF(name, flags, handler) \
!     { NULL, 0, name, flags, handler, NULL }
  
  struct forcmd {			/* for/select */
  /* Cmd->args contains list of words to loop thru */
--- 456,481 ----
  #define COND_GT    13
  #define COND_LE    14
  #define COND_GE    15
+ #define COND_MOD   16
+ #define COND_MODI  17
  
! typedef int (*CondHandler) _((Conddef, char **));
  
  struct conddef {
!     Conddef next;		/* next in list                       */
!     char *name;			/* the condition name                 */
!     int flags;			/* see CONDF_* below                  */
!     int min;			/* minimum number of strings          */
!     int max;			/* maximum number of strings          */
!     CondHandler handler;	/* handler function                   */
!     char *module;		/* module to autoload                 */
  };
  
  #define CONDF_INFIX  1
  #define CONDF_ADDED  2
  
! #define CONDDEF(name, flags, min, max, handler) \
!     { NULL, name, flags, min, max, handler, NULL }
  
  struct forcmd {			/* for/select */
  /* Cmd->args contains list of words to loop thru */
diff -c os/Modules/example.c Src/Modules/example.c
*** os/Modules/example.c	Tue Dec  8 16:31:28 1998
--- Src/Modules/example.c	Wed Dec  9 12:13:58 1998
***************
*** 51,66 ****
  
  /**/
  static int
! cond_p_ex(Conddef c, char *a, char *dummy)
  {
!     return !strcmp("example", a);
  }
  
  /**/
  static int
! cond_i_ex(Conddef c, char *a, char *b)
  {
!     return !strcmp("example", dyncat(a, b));
  }
  
  /*
--- 51,82 ----
  
  /**/
  static int
! cond_p_len(Conddef c, char **a)
  {
!     char *s1 = a[0], *s2 = a[1];
! 
!     singsub(&s1);
!     untokenize(s1);
!     if (s2) {
! 	singsub(&s2);
! 	untokenize(s2);
! 	return strlen(s1) == matheval(s2);
!     } else {
! 	return !s1[0];
!     }
  }
  
  /**/
  static int
! cond_i_ex(Conddef c, char **a)
  {
!     char *s1 = a[0], *s2 = a[1];
! 
!     singsub(&s1);
!     untokenize(s1);
!     singsub(&s2);
!     untokenize(s2);
!     return !strcmp("example", dyncat(s1, s2));
  }
  
  /*
***************
*** 71,79 ****
      BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
  };
  
! static struct conddef condtab[] = {
!     CONDDEF("ex", 0, cond_p_ex),
!     CONDDEF("ex", CONDF_INFIX, cond_i_ex),
  };
  
  /**/
--- 87,95 ----
      BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
  };
  
! static struct conddef cotab[] = {
!     CONDDEF("len", 0, 1, 2, cond_p_len),
!     CONDDEF("ex", CONDF_INFIX, 0, 0, cond_i_ex),
  };
  
  /**/
***************
*** 81,87 ****
  boot_example(Module m)
  {
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
! 	     addconddefs(m->nam, condtab, sizeof(condtab)/sizeof(*condtab)));
  }
  
  #ifdef MODULE
--- 97,103 ----
  boot_example(Module m)
  {
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
! 	     addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)));
  }
  
  #ifdef MODULE
***************
*** 91,97 ****
  cleanup_example(Module m)
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
!     deleteconddefs(m->nam, condtab, sizeof(condtab)/sizeof(*condtab));
      return 0;
  }
  #endif
--- 107,113 ----
  cleanup_example(Module m)
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
!     deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
      return 0;
  }
  #endif
diff -c od/Zsh/builtins.yo Doc/Zsh/builtins.yo
*** od/Zsh/builtins.yo	Tue Dec  8 16:31:39 1998
--- Doc/Zsh/builtins.yo	Wed Dec  9 12:19:12 1998
***************
*** 1117,1127 ****
  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) ...)
! xitem(tt(zmodload) tt(-Cu) [ tt(-iI) ] var(cond) ...)
! xitem(tt(zmodload) tt(-c) [ tt(-IL) ])
! item(tt(zmodload) tt(-C) [ 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.
--- 1117,1124 ----
  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(-cu) [ tt(-iI) ] var(cond) ...)
! item(tt(zmodload) tt(-c) [ 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.
***************
*** 1189,1202 ****
  loaded.  tt(-i) suppresses the error if the builtin is already
  removed (or never existed).
  
! The tt(-c) and tt(-C) options are used to define autoloaded condition
! codes. The var(cond) strings give the names of the conditions defined
! by the module. The tt(-C) option is used for conditions that take
! precedence over the builtin ones, whereas the tt(-c) option is used
! for normal (lower precedence) conditions. The optional tt(-I) option
! is used to define infix condition names (taking two
! strings). Without this option prefix condition names are defined
! (taking one string).
  
  Together with the tt(-u) option definitions for autoloaded conditions
  are removed. If given no condition names all defined names are listed
--- 1186,1195 ----
  loaded.  tt(-i) suppresses the error if the builtin is already
  removed (or never existed).
  
! The tt(-c) option is used to define autoloaded condition codes. The
! var(cond) strings give the names of the conditions defined by the
! module. The optional tt(-I) option is used to define infix condition
! 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


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: module-defined conditions
  1998-12-08 15:30 Sven Wischnowsky
@ 1998-12-08 16:08 ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 1998-12-08 16:08 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On Dec 8,  4:30pm, Sven Wischnowsky wrote:
} Subject: PATCH: module-defined conditions
}
} (I can easily be convinced to remove the code that
} allows one to redefine builtin conditions, maybe it's too dangerous

I think removing that code is a very good idea, especially if:

} it would also simplify the code and zmodload...).


-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 3+ messages in thread

* PATCH: module-defined conditions
@ 1998-12-08 15:30 Sven Wischnowsky
  1998-12-08 16:08 ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Sven Wischnowsky @ 1998-12-08 15:30 UTC (permalink / raw)
  To: zsh-workers


Hi

Planning to implement the new completion stuff I started doing some
preparatory work.

The patch below is the first result: it allows modules to define
condition codes. The function interface is like the one used to define 
builtins.

Two types of condition names can be defined: names that take
precedence over the builtin ones (so they can be redefined by modules) 
and names that are tried only if there is no builtin condition with
the same name (I can easily be convinced to remove the code that
allows one to redefine builtin conditions, maybe it's too dangerous,
and it would also simplify the code and zmodload...).

For each of these types prefix and infix conditions can be defined.

I have modified the example module to define to conditions which can
be tested with:

  [[ -ex <str> ]]      # yields true if <str> is `example'

and

  [[ <s1> -ex <s2> ]]  # yield true if <s1> and <s2> concatenated
                       # give `example'

Of course, zmodload has been enhanced to allow autoloaded condition
code (using the `c' and `C' options).

Now, some enhancements can be thought of:

- it should be possible to allow the definition of prefix conditions
  that take more than one string
- it wouldn't be too hard to add a builtin (say condctl) that allows
  the definition of condition names from user level, attaching a
  condition name to a shell function name

Bye
 Sven

diff -c os/builtin.c Src/builtin.c
*** os/builtin.c	Thu Dec  3 09:10:42 1998
--- Src/builtin.c	Tue Dec  8 14:30:38 1998
***************
*** 120,126 ****
      BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
  
  #ifdef DYNAMIC
!     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "Laudi", NULL),
  #endif
  };
  
--- 120,126 ----
      BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
  
  #ifdef DYNAMIC
!     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicCI", NULL),
  #endif
  };
  
diff -c os/cond.c Src/cond.c
*** os/cond.c	Thu Dec  3 09:10:42 1998
--- Src/cond.c	Tue Dec  8 14:00:53 1998
***************
*** 148,154 ****
  	    return d == st->st_dev && i == st->st_ino;
  	}
      default:
! 	zerr("bad cond structure", NULL, 0);
      }
      return 0;
  }
--- 148,161 ----
  	    return d == st->st_dev && i == st->st_ino;
  	}
      default:
! 	{
! 	    Conddef cd;
! 
! 	    if ((cd = getnumconddef(c->type)))
! 		return cd->handler(cd, c->left, c->right);
! 	    else
! 		zerr("bad cond structure", NULL, 0);
! 	}
      }
      return 0;
  }
diff -c os/init.c Src/init.c
*** os/init.c	Thu Dec  3 09:10:43 1998
--- Src/init.c	Tue Dec  8 11:39:15 1998
***************
*** 592,597 ****
--- 592,599 ----
      createnameddirtable();  /* create hash table for named directories */
      createparamtable();     /* create paramater hash table             */
  
+     pre_conds = post_conds = NULL;
+ 
  #ifdef TIOCGWINSZ
      adjustwinsize();
  #else
diff -c os/module.c Src/module.c
*** os/module.c	Thu Dec  3 09:10:44 1998
--- Src/module.c	Tue Dec  8 15:50:26 1998
***************
*** 161,166 ****
--- 161,368 ----
      return hadf ? hads : 1;
  }
  
+ /* The lists of module-defined conditions. pre_conds contains the ones *
+  * that take precedence over the builtin ones. */
+ 
+ /**/
+ Conddef pre_conds;
+ 
+ /**/
+ Conddef post_conds;
+ 
+ /* Used to number module-defined conditions. */
+ 
+ static int cond_num = 256;
+ 
+ /* This gets a condition definition with the given name. The first        *
+  * argument says if we have to look for a condition that takes precedence *
+  * over the builtin ones and the second argument says if we have to look  *
+  * for an infix condition. */
+ 
+ /**/
+ Conddef
+ getconddef(int prec, int inf, char *name)
+ {
+     Conddef p = (prec ? pre_conds : post_conds);
+ 
+     for (; p; p = p->next) {
+ 	if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
+ 	    !strcmp(name, p->name))
+ 	    return p;
+     }
+     return NULL;
+ }
+ 
+ /* Find a condition definition given its number. */
+ 
+ /**/
+ Conddef
+ getnumconddef(int n)
+ {
+     Conddef p;
+     int f = 1;
+ 
+     do {
+ 	for (p = pre_conds; p; p = p->next) {
+ 	    if (n == p->num)
+ 		break;
+ 	}
+ 	if (!p)
+ 	    for(p = post_conds; p; p = p->next) {
+ 		if (n == p->num)
+ 		    break;
+ 	    }
+ 	if (p && p->module) {
+ 	    /* This is a definition for an autoloaded condition, load the *
+ 	     * module if we haven't tried that already. */
+ 	    if (f) {
+ 		load_module(p->module);
+ 		f = 0;
+ 		p = NULL;
+ 	    }
+ 	    else
+ 		break;
+ 	}
+ 	else
+ 	    break;
+     } while (!p);
+ 
+     return p;
+ }
+ 
+ /* This adds the given condition definition. The return value is zero on *
+  * success and 1 on failure. If there is a matching definition for an    *
+  * autoloaded condition, it is removed. */
+ 
+ /**/
+ int
+ addconddef(Conddef c)
+ {
+     Conddef p = getconddef((c->flags & CONDF_PREC), (c->flags & CONDF_INFIX),
+ 			   c->name);
+     int nu = cond_num++;
+ 
+     if (p) {
+ 	if (!p->module || (p->flags & CONDF_ADDED))
+ 	    return 1;
+ 
+ 	/* There is an autoload definition. */
+ 
+ 	nu = p->num;
+ 
+ 	deleteconddef(p);
+     }
+     if (c->flags & CONDF_PREC) {
+ 	c->next = pre_conds;
+ 	pre_conds = c;
+     } else {
+ 	c->next = post_conds;
+ 	post_conds = c;
+     }
+     c->num = nu;
+     return 0;
+ }
+ 
+ /* This add multiple condition definitions. This is like addbuiltins(). */
+ 
+ /**/
+ int
+ addconddefs(char const *nam, Conddef c, int size)
+ {
+     int hads = 0, hadf = 0;
+ 
+     while (size--) {
+ 	if (c->flags & CONDF_ADDED)
+ 	    continue;
+ 	if (addconddef(c)) {
+ 	    zwarnnam(nam, "name clash when adding condition `%s'", c->name, 0);
+ 	    hadf = 1;
+ 	} else {
+ 	    c->flags |= CONDF_ADDED;
+ 	    hads = 2;
+ 	}
+ 	c++;
+     }
+     return hadf ? hads : 1;
+ }
+ 
+ /* This adds a definition for autoloading a module for a condition. */
+ 
+ /**/
+ int
+ add_autocond(char *nam, int prec, int inf, char *module)
+ {
+     Conddef c = zalloc(sizeof(*c));
+ 
+     c->name = ztrdup(nam);
+     c->flags =
+ 	(prec ? CONDF_PREC  : 0) |
+ 	(inf  ? CONDF_INFIX : 0);
+     c->module = ztrdup(module);
+ 
+     if (addconddef(c)) {
+ 	zsfree(c->name);
+ 	zsfree(c->module);
+ 	zfree(c, sizeof(*c));
+ 
+ 	return 1;
+     }
+     return 0;
+ }
+ 
+ /* This removes the given condition definition from the list(s). If this *
+  * is a definition for a autoloaded condition, the memory is freed. */
+ 
+ /**/
+ int
+ deleteconddef(Conddef c)
+ {
+     Conddef p = ((c->flags & CONDF_PREC) ? pre_conds : post_conds), q = NULL;
+ 
+     for (; p && p != c; q = p, p = p->next);
+ 
+     if (p) {
+ 	if (q)
+ 	    q->next = p->next;
+ 	else if (c->flags & CONDF_PREC)
+ 	    pre_conds = p->next;
+ 	else
+ 	    post_conds = p->next;
+ 		
+ 	if (p->module) {
+ 	    /* autoloaded, free it */
+ 	    zsfree(p->name);
+ 	    zsfree(p->module);
+ 	    zfree(p, sizeof(*p));
+ 	}
+ 	return 0;
+     }
+     return -1;
+ }
+ 
+ /* This removes multiple condition definitions (like deletebuiltins()). */
+ 
+ /**/
+ int
+ deleteconddefs(char const *nam, Conddef c, int size)
+ {
+     int hads = 0, hadf = 0;
+ 
+     while (size--) {
+ 	if (!(c->flags & CONDF_ADDED))
+ 	    continue;
+ 	if (deleteconddef(c)) {
+ 	    zwarnnam(nam, "condition `%s' already deleted", c->name, 0);
+ 	    hadf = 1;
+ 	} else
+ 	    hads = 2;
+ 	c->flags &= ~CONDF_ADDED;
+ 	c++;
+     }
+     return hadf ? hads : 1;
+ }
+ 
+ 
  #ifdef HAVE_DLFCN_H
  # include <dlfcn.h>
  #else
***************
*** 436,441 ****
--- 638,645 ----
  	return bin_zmodload_dep(nam, args, ops);
      else if(ops['a'])
  	return bin_zmodload_auto(nam, args, ops);
+     else if (ops['c'] || ops['C'])
+ 	return bin_zmodload_cond(nam, args, ops);
      else
  	return bin_zmodload_load(nam, args, ops);
  }
***************
*** 561,566 ****
--- 765,853 ----
  		ret = 1;
  	    } else if (add_autobin(bnam, modnam) && !ops['i']) {
  		zwarnnam(nam, "failed to add builtin %s", bnam, 0);
+ 		ret = 1;
+ 	    }
+ 	} while(*args);
+ 	return ret;
+     }
+ }
+ 
+ /**/
+ static int
+ bin_zmodload_cond(char *nam, char **args, char *ops)
+ {
+     int ret = 0;
+ 
+     if (ops['u']) {
+ 	/* remove autoloaded conditions */
+ 	for (; *args; args++) {
+ 	    Conddef cd = getconddef(ops['C'], ops['I'], *args);
+ 
+ 	    if (!cd) {
+ 		if (!ops['i']) {
+ 		    zwarnnam(nam, "%s: no such condition", *args, 0);
+ 		    ret = 1;
+ 		}
+ 	    } else if (cd->flags & CONDF_ADDED) {
+ 		zwarnnam(nam, "%s: condition is already defined", *args, 0);
+ 		ret = 1;
+ 	    } else
+ 		deleteconddef(cd);
+ 	}
+ 	return ret;
+     } else if (!*args) {
+ 	/* list autoloaded conditions */
+ 	Conddef p;
+ 
+ 	if (ops['C'])
+ 	    for (p = pre_conds; p; p = p->next) {
+ 		if (p->module) {
+ 		    if (ops['L']) {
+ 			fputs("zmodload -C", stdout);
+ 			if (p->flags & CONDF_INFIX)
+ 			    putchar('I');
+ 			printf(" %s %s\n", p->module, p->name);
+ 		    } else {
+ 			fputs("pre ", stdout);
+ 			if (p->flags & CONDF_INFIX)
+ 			    fputs("infix ", stdout);
+ 			printf("%s (%s)\n",p->name, p->module);
+ 		    }
+ 		}
+ 	    }
+ 	if (ops['c'])
+ 	    for (p = post_conds; p; p = p->next) {
+ 		if (p->module) {
+ 		    if (ops['L']) {
+ 			fputs("zmodload -c", stdout);
+ 			if (p->flags & CONDF_INFIX)
+ 			    putchar('I');
+ 			printf(" %s %s\n", p->module, p->name);
+ 		    } else {
+ 			fputs("post ", stdout);
+ 			if (p->flags & CONDF_INFIX)
+ 			    fputs("infix ", stdout);
+ 			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 *cnam = *args ? *args++ : modnam;
+ 	    if (strchr(cnam, '/')) {
+ 		zwarnnam(nam, "%s: `/' is illegal in a condition", cnam, 0);
+ 		ret = 1;
+ 	    } else if (add_autocond(cnam, ops['C'], ops['I'], modnam) && !ops['i']) {
+ 		zwarnnam(nam, "failed to add condition %s", cnam, 0);
  		ret = 1;
  	    }
  	} while(*args);
diff -c os/parse.c Src/parse.c
*** os/parse.c	Thu Dec  3 09:10:45 1998
--- Src/parse.c	Tue Dec  8 15:45:50 1998
***************
*** 1311,1321 ****
  par_cond_double(char *a, char *b)
  {
      Cond n = (Cond) make_cond();
  
!     if (a[0] != '-' || !a[1] || a[2])
  	COND_ERROR("parse error: condition expected: %s", a);
      n->left = (void *) b;
-     n->type = a[1];
      n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
      return n;
  }
--- 1311,1329 ----
  par_cond_double(char *a, char *b)
  {
      Cond n = (Cond) make_cond();
+     Conddef cd;
  
!     if ((cd = getconddef(1, 0, a+1)))
! 	n->type = cd->num;
!     else if (a[0] != '-' || !a[1])
  	COND_ERROR("parse error: condition expected: %s", a);
+     else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1)
+ 	n->type = a[1];
+     else if ((cd = getconddef(0, 0, a+1)))
+ 	n->type = cd->num;
+     else
+ 	COND_ERROR("parse error: unrecognized condition: %s", a);
      n->left = (void *) b;
      n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
      return n;
  }
***************
*** 1341,1349 ****
  par_cond_triple(char *a, char *b, char *c)
  {
      Cond n = (Cond) make_cond();
      int t0;
  
!     if ((b[0] == Equals || b[0] == '=') &&
  	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2])))
  	n->type = COND_STREQ;
      else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
--- 1349,1360 ----
  par_cond_triple(char *a, char *b, char *c)
  {
      Cond n = (Cond) make_cond();
+     Conddef cd;
      int t0;
  
!     if ((cd = getconddef(1, 1, b+1)))
! 	n->type = cd->num;
!     else if ((b[0] == Equals || b[0] == '=') &&
  	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2])))
  	n->type = COND_STREQ;
      else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
***************
*** 1351,1356 ****
--- 1362,1369 ----
      else if (b[0] == '-') {
  	if ((t0 = get_cond_num(b + 1)) > -1)
  	    n->type = t0 + COND_NT;
+ 	else if ((cd = getconddef(0, 1, b+1)))
+ 	    n->type = cd->num;
  	else
  	    COND_ERROR("unrecognized condition: %s", b);
      } else
diff -c os/zsh.h Src/zsh.h
*** os/zsh.h	Thu Dec  3 09:10:46 1998
--- Src/zsh.h	Tue Dec  8 13:52:35 1998
***************
*** 242,247 ****
--- 242,248 ----
  typedef struct value     *Value;
  typedef struct varasg    *Varasg;
  typedef struct cond      *Cond;
+ typedef struct conddef   *Conddef;
  typedef struct cmd       *Cmd;
  typedef struct pline     *Pline;
  typedef struct sublist   *Sublist;
***************
*** 455,460 ****
--- 456,479 ----
  #define COND_GT    13
  #define COND_LE    14
  #define COND_GE    15
+ 
+ typedef int (*CondHandler) _((Conddef, char *, char *));
+ 
+ struct conddef {
+     Conddef next;
+     int num;
+     char *name;
+     int flags;
+     CondHandler handler;
+     char *module;
+ };
+ 
+ #define CONDF_INFIX  1
+ #define CONDF_ADDED  2
+ #define CONDF_PREC   4
+ 
+ #define CONDDEF(name, flags, handler) \
+     { NULL, 0, name, flags, handler, NULL }
  
  struct forcmd {			/* for/select */
  /* Cmd->args contains list of words to loop thru */
diff -c od/Zsh/builtins.yo Doc/Zsh/builtins.yo
*** od/Zsh/builtins.yo	Thu Dec  3 09:10:52 1998
--- Doc/Zsh/builtins.yo	Tue Dec  8 16:05:13 1998
***************
*** 1115,1121 ****
  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) ... ] ])
! item(tt(zmodload) tt(-au) [ tt(-i) ] var(builtin) ...)(
  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.
--- 1115,1127 ----
  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) ...)
! xitem(tt(zmodload) tt(-Cu) [ tt(-iI) ] var(cond) ...)
! xitem(tt(zmodload) tt(-c) [ tt(-IL) ])
! item(tt(zmodload) tt(-C) [ 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.
***************
*** 1182,1186 ****
--- 1188,1205 ----
  tt(zmodload -a).  This is only possible if the builtin is not yet
  loaded.  tt(-i) suppresses the error if the builtin is already
  removed (or never existed).
+ 
+ The tt(-c) and tt(-C) options are used to define autoloaded condition
+ codes. The var(cond) strings give the names of the conditions defined
+ by the module. The tt(-C) option is used for conditions that take
+ precedence over the builtin ones, whereas the tt(-c) option is used
+ for normal (lower precedence) conditions. The optional tt(-I) option
+ is used to define infix condition names (taking two
+ strings). Without this option prefix condition names are defined
+ (taking one string).
+ 
+ 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).
  )
  enditem()
diff -c os/Modules/example.c Src/Modules/example.c
*** os/Modules/example.c	Tue Nov  3 10:47:29 1998
--- Src/Modules/example.c	Tue Dec  8 15:34:31 1998
***************
*** 49,54 ****
--- 49,68 ----
      return 0;
  }
  
+ /**/
+ static int
+ cond_p_ex(Conddef c, char *a, char *dummy)
+ {
+     return !strcmp("example", a);
+ }
+ 
+ /**/
+ static int
+ cond_i_ex(Conddef c, char *a, char *b)
+ {
+     return !strcmp("example", dyncat(a, b));
+ }
+ 
  /*
   * boot_example is executed when the module is loaded.
   */
***************
*** 57,67 ****
      BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
  };
  
  /**/
  int
  boot_example(Module m)
  {
!     return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
  }
  
  #ifdef MODULE
--- 71,87 ----
      BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
  };
  
+ static struct conddef condtab[] = {
+     CONDDEF("ex", 0, cond_p_ex),
+     CONDDEF("ex", CONDF_INFIX, cond_i_ex),
+ };
+ 
  /**/
  int
  boot_example(Module m)
  {
!     return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
! 	     addconddefs(m->nam, condtab, sizeof(condtab)/sizeof(*condtab)));
  }
  
  #ifdef MODULE
***************
*** 71,76 ****
--- 91,97 ----
  cleanup_example(Module m)
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+     deleteconddefs(m->nam, condtab, sizeof(condtab)/sizeof(*condtab));
      return 0;
  }
  #endif

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1998-12-09 12:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-12-09 12:17 PATCH: module-defined conditions Sven Wischnowsky
  -- strict thread matches above, loose matches on Subject: below --
1998-12-08 15:30 Sven Wischnowsky
1998-12-08 16:08 ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).