Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Reserved words and aliases



In a reply to Bart about the behaviour of exec (which didn't go to the
list since I forgot about the new reply behaviour), I pointed out that
exec couldn't be an alias, and said I couldn't be bothered to fix
this.

I lied.

The problem is a Z-shell Kludge (TM):  the aliases and reserved words
shared the same hash table.  The old behaviour was that making exec
an alias stopped the real exec from being recognised as a shell
reserved word and this couldn't be undone.

I could have fixed this by compounding the kludge, e.g. by adding an
extra flag if an alias was a reserved word that was aliased.  Instead
I decided to do it properly and put the reserved words in their own
hash table.  This enabled some minor data size optimisations at the
expense of some minor code increase.  It also opens the way in future
to turn off aliases as an option if that ever becomes necessary.

Since reswdtab is never altered, I made some attempt at finding a
suitable size: 23 seemed to be a reasonable trade off, though it
leaves five hash buckets empty.

There is the odd minor but reasonable change in behaviour, for example
compctl's alias flag won't produce reserved words any more (they still
appear for command completion and spell checking).

You can now do

% alias exec="((SHLVL++, SAVEHIST=0)); exec"

if you really want.

*** Src/builtin.c.ali	Fri May 19 10:10:25 1995
--- Src/builtin.c	Thu May 25 13:33:19 1995
***************
*** 3292,3297 ****
--- 3292,3298 ----
  {
      struct cmdnam *chn;
      struct alias *a;
+     struct reswd *rw;
      int retval = 0;
      int csh = ops[(int)'c'], all = ops[(int)'a'];
      int v = ops['v'] || csh;
***************
*** 3315,3321 ****
  	    }
  	    if (!ops['p']) {
  		/* -p option is for path search only.  We're not using it, so
! 		search for reserved words, aliases, builtins and functions. */
  		n = aliastab->hsize;
  		for (i = 0; i < n; i++) {
  		    for (a = (struct alias *)aliastab->nodes[i]; a;
--- 3316,3322 ----
  	    }
  	    if (!ops['p']) {
  		/* -p option is for path search only.  We're not using it, so
! 		search for aliases ... */
  		n = aliastab->hsize;
  		for (i = 0; i < n; i++) {
  		    for (a = (struct alias *)aliastab->nodes[i]; a;
***************
*** 3323,3332 ****
  			/* Going through the alias table.  Display a match if
  			there is one. */
  			if (a->nam && domatch(a->nam, com, 0)) {
! 			    if (a->cmd < 0)
! 				printf((csh) ? "%s: shell reserved word\n" :
! 				       (v) ? "%s is a reserved word\n" : "%s\n", a->nam);
! 			    else if (!v)
  				puts(a->text);
  			    else if (a->cmd)
  				printf((csh) ? "%s: aliased to %s\n" :
--- 3324,3330 ----
  			/* Going through the alias table.  Display a match if
  			there is one. */
  			if (a->nam && domatch(a->nam, com, 0)) {
! 			    if (!v)
  				puts(a->text);
  			    else if (a->cmd)
  				printf((csh) ? "%s: aliased to %s\n" :
***************
*** 3337,3342 ****
--- 3335,3352 ----
  			}
  		    }
  		}
+ 		/* ... reserved words ... */
+ 		n = reswdtab->hsize;
+ 		for (i = 0; i < n; i++) {
+ 		    for (rw = (struct reswd *)reswdtab->nodes[i]; rw;
+ 			 rw = (struct reswd *)rw->next) {
+ 			if (rw->nam && domatch(rw->nam, com, 0))
+ 			    printf((csh) ? "%s: shell reserved word\n" :
+ 				   (v) ? "%s is a reserved word\n" : "%s\n",
+ 				   rw->nam);
+ 		    }
+ 		}
+ 		/* ... and builtins and shell functions. */
  		n = cmdnamtab->hsize;
  		for (i = 0; i < n; i++) {
  		    for (chn = (struct cmdnam *)cmdnamtab->nodes[i]; chn;
***************
*** 3389,3400 ****
  	} else {
  	    /* Not treating args as glob patterns. */
  	    informed = 0;
! 	    /* Look for reserved word or alias, unless -p was used. */
  	    if (!ops['p'] && (a = (Alias) gethnode(*argv, aliastab))) {
! 		if (a->cmd < 0)
! 		    printf((csh) ? "%s: shell reserved word\n" :
! 			   (v) ? "%s is a reserved word\n" : "%s\n", *argv);
! 		else if (!v)
  		    puts(a->text);
  		else if (a->cmd)
  		    printf((csh) ? "%s: aliased to %s\n" :
--- 3399,3407 ----
  	} else {
  	    /* Not treating args as glob patterns. */
  	    informed = 0;
! 	    /* Look for alias, unless -p was used. */
  	    if (!ops['p'] && (a = (Alias) gethnode(*argv, aliastab))) {
! 		if (!v)
  		    puts(a->text);
  		else if (a->cmd)
  		    printf((csh) ? "%s: aliased to %s\n" :
***************
*** 3406,3411 ****
--- 3413,3426 ----
  		    continue;
  		informed = 1;
  	    }
+ 	    /* Look for reserved word unless -p was used. */
+ 	    if (!ops['p'] && gethnode(*argv, reswdtab)) {
+ 		printf((csh) ? "%s: shell reserved word\n" :
+ 		       (v) ? "%s is a reserved word\n" : "%s\n", *argv);
+ 		if (!all)
+ 		    continue;
+ 		informed = 1;
+ 	    }
  	    /* Look for builtin or function, if -p was not used. */
  	    if (!ops['p'] && (chn = (Cmdnam) gethnode(*argv, cmdnamtab)) &&
  		(chn->flags & (SHFUNC | BUILTIN))) {
***************
*** 3895,3901 ****
  	    for (i = 0; i < n; i++) {
  		for (a = (Alias) aliastab->nodes[i]; a; a = dat) {
  		    dat = (Alias) a->next;
! 		    if (a->nam && a->cmd >= 0 && domatch(a->nam, com, 0))
  			freeanode(remhnode(a->nam, aliastab)), match++;
  		}
  	    }
--- 3910,3916 ----
  	    for (i = 0; i < n; i++) {
  		for (a = (Alias) aliastab->nodes[i]; a; a = dat) {
  		    dat = (Alias) a->next;
! 		    if (a->nam && domatch(a->nam, com, 0))
  			freeanode(remhnode(a->nam, aliastab)), match++;
  		}
  	    }
***************
*** 3903,3909 ****
  		ret = 1;
  	} else {
  	    /* remove the specified alias */
! 	    if ((dat = (Alias) gethnode(*argv++, aliastab)) && dat->cmd >= 0)
  		freeanode(remhnode(dat->nam, aliastab));
  	    else
  		ret = 1;
--- 3918,3924 ----
  		ret = 1;
  	} else {
  	    /* remove the specified alias */
! 	    if ((dat = (Alias) gethnode(*argv++, aliastab)))
  		freeanode(remhnode(dat->nam, aliastab));
  	    else
  		ret = 1;
***************
*** 3921,3929 ****
      char *ptr;
      int special = 0, inquote = 0;
  
!     if (a->cmd >= 0 && (!showflag ||		/* a single requested alias */
! 			(showflag == 1 && !a->cmd) ||	/* global alias */
! 			(showflag == 2 && a->cmd))) {	/* regular alias */
  	/* check for special characters in the expansion text */
  	for (ptr = a->text; *ptr; ptr++)
  	    if (ispecial(*ptr))
--- 3936,3944 ----
      char *ptr;
      int special = 0, inquote = 0;
  
!     if (!showflag ||			/* a single requested alias */
! 	(showflag == 1 && !a->cmd) ||   /* global alias */
! 	(showflag == 2 && a->cmd)) {	/* regular alias */
  	/* check for special characters in the expansion text */
  	for (ptr = a->text; *ptr; ptr++)
  	    if (ispecial(*ptr))
*** Src/globals.h.ali	Wed May 24 18:14:18 1995
--- Src/globals.h	Wed May 24 18:13:44 1995
***************
*** 250,259 ****
   
  EXTERN int prevjob;
   
! /* hash table containing the aliases and reserved words */
   
  EXTERN Hashtab aliastab;
   
  /* hash table containing the parameters */
   
  EXTERN Hashtab paramtab;
--- 250,263 ----
   
  EXTERN int prevjob;
   
! /* hash table containing the aliases */
   
  EXTERN Hashtab aliastab;
   
+ /* hash table containing the reserved words */
+ 
+ EXTERN Hashtab reswdtab;
+ 
  /* hash table containing the parameters */
   
  EXTERN Hashtab paramtab;
*** Src/init.c.ali	Wed May 24 18:19:11 1995
--- Src/init.c	Thu May 25 12:06:28 1995
***************
*** 666,671 ****
--- 666,672 ----
  void
  addreswords(void)
  {
+ /* add the reserved words to their hash table:  should only be called once. */
      static char *reswds[] =
      {
  	"do", "done", "esac", "then", "elif", "else", "fi", "for", "case",
***************
*** 674,681 ****
      };
      int t0;
  
!     for (t0 = 0; reswds[t0]; t0++)
! 	addhnode(ztrdup(reswds[t0]), mkanode(NULL, -1 - t0), aliastab, NULL);
  }
  
  /**/
--- 675,690 ----
      };
      int t0;
  
!     /* twenty four reserved words; any advance on the following? */
!     reswdtab = newhtable(23);
!     /* Add the actual words, not copies, to the table, as we do not
!      * expect to modify the table again.
!      */
!     for (t0 = 0; reswds[t0]; t0++) {
! 	struct reswd *ptr = (struct reswd *) zcalloc(sizeof *ptr);
! 	ptr->cmd = t0 + DO;
! 	addhnode(reswds[t0], ptr, reswdtab, NULL);
!     }
  }
  
  /**/
*** Src/lex.c.ali	Fri May 19 10:10:38 1995
--- Src/lex.c	Thu May 25 12:13:01 1995
***************
*** 919,924 ****
--- 919,925 ----
  exalias(void)
  {
      struct alias *an;
+     struct reswd *rw;
      char *s, *t;
  
      s = yytext = hwadd();
***************
*** 940,965 ****
  	    return 0;
  	}
      }
      an = noaliases ? NULL : (struct alias *)gethnode(s, aliastab);
!     if (t)
! 	*t = HISTSPACE;
!     if (alstackind != MAXAL && an && !an->inuse)
! 	if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE)) {
! 	    if (an->cmd < 0) {
! 		tok = DO - an->cmd - 1;
! 		return 0;
! 	    } else {
! 		an->inuse = 1;
! 		hungets(ALPOPS);
! 		hungets((alstack[alstackind++] = an)->text);
! 		alstat = 0;
  	    /* remove from history if it begins with space */
! 		if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
! 		    remhist();
! 		lexstop = 0;
! 		return 1;
! 	    }
  	}
      return 0;
  }
  
--- 941,971 ----
  	    return 0;
  	}
      }
+ 
+     /* Check for an alias */
      an = noaliases ? NULL : (struct alias *)gethnode(s, aliastab);
!     if (alstackind != MAXAL && an && !an->inuse
! 	&& (!an->cmd || incmdpos || alstat == ALSTAT_MORE)) {
! 	    an->inuse = 1;
! 	    hungets(ALPOPS);
! 	    hungets((alstack[alstackind++] = an)->text);
! 	    alstat = 0;
  	    /* remove from history if it begins with space */
! 	    if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
! 		remhist();
! 	    lexstop = 0;
! 	    if (t)
! 		*t = HISTSPACE;
! 	    return 1;
  	}
+ 
+     /* Then check for a reserved word (ignored if noaliases is set) */
+     rw = (noaliases || !incmdpos) ? NULL
+ 	: (struct reswd *)gethnode(s, reswdtab);
+     if (rw)
+ 	tok = rw->cmd;
+     if (t)
+ 	*t = HISTSPACE;
      return 0;
  }
  
*** Src/utils.c.ali	Tue May 23 14:20:31 1995
--- Src/utils.c	Thu May 25 10:35:43 1995
***************
*** 1145,1151 ****
  	return;
      if (!(*s)[0] || !(*s)[1])
  	return;
!     if (gethnode(*s, cmdnamtab) || gethnode(*s, aliastab))
  	return;
      else if (isset(HASHLISTALL)) {
  	fullhash();
--- 1151,1158 ----
  	return;
      if (!(*s)[0] || !(*s)[1])
  	return;
!     if (gethnode(*s, cmdnamtab) || gethnode(*s, aliastab)
! 	|| gethnode(*s, reswdtab))
  	return;
      else if (isset(HASHLISTALL)) {
  	fullhash();
***************
*** 1183,1188 ****
--- 1190,1196 ----
  		return;
  	    guess = *s;
  	    d = 100;
+ 	    listhtable(reswdtab, spscan);
  	    listhtable(aliastab, spscan);
  	    listhtable(cmdnamtab, spscan);
  	}
*** Src/zle_tricky.c.ali	Tue May 23 14:20:34 1995
--- Src/zle_tricky.c	Wed May 24 18:41:11 1995
***************
*** 2705,2710 ****
--- 2705,2711 ----
      if (!ic && (cc->mask & CC_COMMPATH) && !*ppre && !*psuf) {
  	/* If we have to complete commands, add alias names, too. */
  	dumphtable(aliastab, -2);
+ 	dumphtable(reswdtab, -2);
  	if (isset(HASHLISTALL))
  	    fullhash();
  	dumphtable(cmdnamtab, -3);

-- 
Peter Stephenson <P.Stephenson@xxxxxxxxxxxxx>  Tel: +44 1792 205678 extn. 4461
WWW:  http://python.swan.ac.uk/~pypeters/      Fax: +44 1792 295324
Department of Physics, University of Wales, Swansea,
Singleton Park, Swansea, SA2 8PP, U.K.



Messages sorted by: Reverse Date, Date, Thread, Author