zsh-workers
 help / color / mirror / code / Atom feed
* Handling for ZLE modules
@ 1996-11-08 15:26 Peter Stephenson
       [not found] ` <pws@ifh.de>
  1996-11-08 17:16 ` Handling for ZLE modules Zefram
  0 siblings, 2 replies; 13+ messages in thread
From: Peter Stephenson @ 1996-11-08 15:26 UTC (permalink / raw)
  To: Zsh hackers list

I'm so impressed with the dynamic library code I couldn't resist
implementing a way of allowing you to load new ZLE functions from
modules.

My thinking was this: there are 162 builtin functions and you're
presumably never going to add more than a half dozen or so new ones
(very likely none).  Thus it didn't seem sensible to reorganize the
existing function table into malloc'd memory.  Instead, I've made a
new table for any functions that are loaded and modified the zle code
via a #define, ZLEGETCMD, to choose between the arrays based on
number.  I don't think this should be too inefficient; the worst case
is in executenamedcommand() when looping through looking for a prefix.
If it ever seems a good idea to allow overloading of builtin functions
this may well need changing.  That's the only major change to zle
itself; note that for non-dynamic zsh's it will work quite happily
without the functions (add|delete)zlefunction() defined in
module.c. I'd be glad to hear of better ways of doing it.

The other question is how to handle unloading.  One has to be careful
when bindings remain which point to the function; also, the functions
are in a linear array like the builtin functions and you may not be
deleting at the end.  I have arranged it so that the function is
marked as deleted with name "<deleted>" (which should only be used for
output), but the table entry is kept. Executing the binding performs a
feep().  That's probably fine, the only problem arises when you load
another module which then inherits the slot in the table and hence the
binding will point to that.  This seems to me a problem to be fixed in
any script code associated with the (z?)modload -u, in particular via
    bindkey | grep '<deleted>' | while read -A line; do
        eval bindkey -r $line[0]
    done
-- I don't think it's worthwhile adding that code to the shell, though
it wouldn't be hard.

The sample module mod_deltochar implements Emacs' zap-to-char (except
it's here called delete-to-char) which reads a key and deletes up to
and including the next occurrence of that character on the command
line.  Multipliers work as expected.  (I've always wanted
zap-to-char.)  Just do `make mod_deltochar.so'.

All this code is as up-in-the-air as Zoltan's, of course.

begin 644 zle_mod.dif.gz
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
4;_\'N;SB-)Z%N_\$F6-O9?XV``#X
`
end

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77413
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


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

* Re: Handling for ZLE modules
       [not found] ` <pws@ifh.de>
@ 1996-11-08 16:45   ` Bart Schaefer
  1996-11-11 16:02   ` Bart Schaefer
  1996-11-13 18:53   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
  2 siblings, 0 replies; 13+ messages in thread
From: Bart Schaefer @ 1996-11-08 16:45 UTC (permalink / raw)
  To: Zsh hackers list

On Nov 8,  4:26pm, Peter Stephenson wrote:
} Subject: Handling for ZLE modules
}
} I'm so impressed with the dynamic library code I couldn't resist
} implementing a way of allowing you to load new ZLE functions from
} modules.

Could I suggest that we immediately identify a subdirectory other than
Src/ where contributed modules can live and have their own Makefile?
I think this would be far preferable to cluttering Src/ with a bunch of
files with "mod_" prefixed to their names.

It might also be useful to have a standard (but by default not present)
directory where the build process looks for locally-supplied modules to
compile.

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Handling for ZLE modules
  1996-11-08 15:26 Handling for ZLE modules Peter Stephenson
       [not found] ` <pws@ifh.de>
@ 1996-11-08 17:16 ` Zefram
  1996-11-08 17:26   ` Bruce Stephens
                     ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Zefram @ 1996-11-08 17:16 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

>The other question is how to handle unloading.  One has to be careful
>when bindings remain which point to the function; also, the functions
>are in a linear array like the builtin functions and you may not be
>deleting at the end.  I have arranged it so that the function is
>marked as deleted with name "<deleted>" (which should only be used for
>output), but the table entry is kept.

I don't like this.  Do we retain the binding or not?  If not, we have
to go through every key binding, changing them to undefined-key.  The
alternative would be to maintain link counts for loaded bindings, to
avoid reusing a slot that is bound to some key.

>                             This seems to me a problem to be fixed in
>any script code associated with the (z?)modload -u,

No.  It's a question of the integrity of zsh's internal data
structures, and should be handled by the code itself.

On a related note, we really need to make addbuiltin() and so on handle
failure cases gracefully.  Try loading mod_example.so twice ("modload
./mod_example.so; modload ~+/mod_example.so"): when I tried it it
segmentated.  Modules are going to have to cope with the possibility
that they can't add the builtins, key bindings or whatever that they
want.

And if anyone's counting, I, too, favour the name `zmodload'.

-zefram

(Own up, how many of us are planning how to implement autoloaded modules?)


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

* Re: Handling for ZLE modules
  1996-11-08 17:16 ` Handling for ZLE modules Zefram
@ 1996-11-08 17:26   ` Bruce Stephens
  1996-11-10 23:55   ` Zoltan Hidvegi
  1996-11-11 13:07   ` Peter Stephenson
  2 siblings, 0 replies; 13+ messages in thread
From: Bruce Stephens @ 1996-11-08 17:26 UTC (permalink / raw)
  To: zsh-workers

> And if anyone's counting, I, too, favour the name `zmodload'.
> 
> -zefram
> 
> (Own up, how many of us are planning how to implement autoloaded modules?)

Well, of course modules should be autoloaded!  More generally, are
people making sure that this mechanism is nice on machines which can't
do autoloading?  i.e., are the modules written in such a way that they
can be statically linked too?   

I note in passing that Tcl7.5 and above also have dynamic loading,
complete with autoconf support.  It's not as portable as Perl's, I
think, but it may be easier to follow and adapt for zsh.  (ksh93 is
also an obvious model to copy, although we don't have source to that.
It would presumably be nice to allow people to load ksh93 modules into
zsh, if that's feasible.)


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

* zle_refresh trial patch
@ 1996-11-09 10:22 Geoff Wing
       [not found] ` <gwing@primenet.com.au>
  0 siblings, 1 reply; 13+ messages in thread
From: Geoff Wing @ 1996-11-09 10:22 UTC (permalink / raw)
  To: zsh-workers

Heyla,
here's a trial patch for nicer scrolling.  Scrolling in a multiple-screen
buffer should be pretty much emacs style.  There is one quirk:  if you are
at last screen of the buffer and you go up, the scroll point will not
necessarily be the top of the screen - it is unavoidable without a large
style change.
There is also a bug fix for the status line (unfortunately I wrote it after
I was doing the other stuff so it is dependant on it - though I could
separate if needed).
"<....>" has been added, so if you see that on the right hand side of the
first line of the status line it means there is stuff missing there.  It's
a complement to <.... and ....> which are used in the normal text area.
Also, the single line scrolling which was dependant on BAUD has also been
removed.

This patch is dependant on patch zsh-workers/2336

The type of command I've mainly checked it with is:
% zed -f zed

on 24/25 line screens.

Anyway, try and find some bugs.  It'll make me happier :-)


*** zle_refresh.c.~1~	Sat Nov  9 20:15:01 1996
--- zle_refresh.c	Sat Nov  9 21:08:12 1996
***************
*** 113,185 ****
  }
  
  /*
!  * Jul 96: <mason> changed to single line scroll for higher speed terminals
!  *  I've seperated the loops for readability (and it's slightly faster)
!  *  Returns line number to be used next
   */
  
  /**/
! int
  scrollwindow(int tline)
  {
!     int t0, hwinh;
      char *s;
  
!     if (tline || baud >= 19200) {	/* single line scroll */
! 	hwinh = 1;
! 	s = nbuf[tline];
! 	for (t0 = tline; t0 < winh - 1; t0++)
! 	    nbuf[t0] = nbuf[t0 + 1];
! 	nbuf[winh - 1] = s;
!     } else { 				/* half screen scroll */
! 	hwinh = winh / 2;
! 	for (t0 = 0; t0 != winh - hwinh; t0++) {
! 	    s = nbuf[t0];
! 	    nbuf[t0] = nbuf[t0 + hwinh];
! 	    nbuf[t0 + hwinh] = s;
! 	}
!     }
      if (!tline)
  	more_start = 1;
!     return winh - hwinh;
  }
  
  /* this is the messy part. */
  /* this define belongs where it's used!!! */
  
! #define nextline				\
! {						\
!     *s = '\0';					\
!     if (++ln == winh)				\
! 	if (nvln != --ln && nvln != -1)		\
! 	    break;				\
! 	else {					\
! 	    ln = scrollwindow(0);		\
! 	    if(nvln != -1)			\
! 		nvln -= winh - ln;		\
! 	}					\
!     if (!nbuf[ln])				\
! 	nbuf[ln] = (char *)zalloc(winw + 1);	\
!     s = (unsigned char *)nbuf[ln];		\
!     sen = s + winw;				\
  }
  
! #define snextline				\
! {						\
!     *s = '\0';					\
!     if (++ln == winh)				\
! 	if (tosln <= nvln + 1) {		\
! 	    ln = scrollwindow(0);		\
! 	    if (nvln)				\
! 		nvln--, tosln--;		\
! 	} else {				\
! 	    tosln--;				\
! 	    ln = scrollwindow(tosln);		\
! 	}					\
!     if (!nbuf[ln])				\
! 	nbuf[ln] = (char *)zalloc(winw + 1);	\
!     s = (unsigned char *)nbuf[ln];		\
!     sen = s + winw;				\
  }
  
  #ifdef TIOCGWINSZ
--- 113,186 ----
  }
  
  /*
!  * Nov 96: <mason> changed to single line scroll
   */
  
  /**/
! void
  scrollwindow(int tline)
  {
!     int t0;
      char *s;
  
!     s = nbuf[tline];
!     for (t0 = tline; t0 < winh - 1; t0++)
! 	nbuf[t0] = nbuf[t0 + 1];
!     nbuf[winh - 1] = s;
      if (!tline)
  	more_start = 1;
!     return;
  }
  
  /* this is the messy part. */
  /* this define belongs where it's used!!! */
  
! #define nextline					\
! {							\
!     *s = '\0';						\
!     if (ln != winh - 1)					\
! 	ln++;						\
!     else {						\
! 	if (!canscroll)	{				\
! 	    if (nvln != -1 && nvln != winh - 1		\
! 		&& (numscrolls != onumscrolls - 1	\
! 		    || nvln <= winh / 2))		\
! 	        break;					\
! 	    numscrolls++;				\
! 	    canscroll = winh / 2;			\
! 	}						\
! 	canscroll--;					\
! 	scrollwindow(0);				\
! 	if (nvln != -1)					\
! 	    nvln--;					\
!     }							\
!     if (!nbuf[ln])					\
! 	nbuf[ln] = (char *)zalloc(winw + 1);		\
!     s = (unsigned char *)nbuf[ln];			\
!     sen = s + winw;					\
  }
  
! #define snextline					\
! {							\
!     *s = '\0';						\
!     if (ln != winh - 1)					\
! 	ln++;						\
!     else						\
! 	if (tosln < 3) {				\
! 	    more_status = 1;				\
! 	    scrollwindow(tosln + 1);			\
! 	} else if (tosln - 1 <= nvln) {			\
! 	    scrollwindow(0);				\
! 	    if (nvln)					\
! 		nvln--, tosln--;			\
! 	} else {					\
! 	    tosln--;					\
! 	    scrollwindow(tosln);			\
! 	}						\
!     if (!nbuf[ln])					\
! 	nbuf[ln] = (char *)zalloc(winw + 1);		\
!     s = (unsigned char *)nbuf[ln];			\
!     sen = s + winw;					\
  }
  
  #ifdef TIOCGWINSZ
***************
*** 191,197 ****
      hasam;			/* terminal should have auto-margin	    */
  static int put_rpmpt,		/* whether we should display right-prompt   */
      oput_rpmpt,			/* whether displayed right-prompt last time */
!     oxtabs;			/* oxtabs - tabs expand to spaces if set    */
  extern int clearflag;		/* set to non-zero if alwayslastprompt used */
  
  /**/
--- 192,199 ----
      hasam;			/* terminal should have auto-margin	    */
  static int put_rpmpt,		/* whether we should display right-prompt   */
      oput_rpmpt,			/* whether displayed right-prompt last time */
!     oxtabs,			/* oxtabs - tabs expand to spaces if set    */
!     numscrolls, onumscrolls;
  extern int clearflag;		/* set to non-zero if alwayslastprompt used */
  
  /**/
***************
*** 199,205 ****
  refresh(void)
  {
      static int inlist;		/* avoiding recursion                        */
!     int ln = 0,			/* current line we're working on	     */
  	nvcs = 0, nvln = -1,	/* video cursor column and line		     */
  	t0 = -1,		/* tmp					     */
  	tosln = 0;		/* tmp in statusline stuff		     */
--- 201,209 ----
  refresh(void)
  {
      static int inlist;		/* avoiding recursion                        */
!     int canscroll = 0,		/* number of lines we are allowed to scroll  */
! 	ln = 0,			/* current line we're working on	     */
! 	more_status = 0,	/* more stuff in status line		     */
  	nvcs = 0, nvln = -1,	/* video cursor column and line		     */
  	t0 = -1,		/* tmp					     */
  	tosln = 0;		/* tmp in statusline stuff		     */
***************
*** 240,245 ****
--- 244,250 ----
      cleareol = 0;		/* unset */
      more_start = more_end = 0;	/* unset */
      if (resetneeded) {
+ 	onumscrolls = 0;
  	setterm();
  #ifdef TIOCGWINSZ
  	if (winchanged) {
***************
*** 269,278 ****
  	}
  	fflush(shout);
  	clearf = clearflag;
!     } else if (winw != columns)
  	resetvideo();
  
! /* now winw equals columns; now all width comparisons can be made to winw */
  
      if (isset(SINGLELINEZLE) || termok != TERM_OK) {
  	singlerefresh();
--- 274,284 ----
  	}
  	fflush(shout);
  	clearf = clearflag;
!     } else if (winw != columns || winh != lines)
  	resetvideo();
  
! /* now winw equals columns and winh equals lines 
!    width comparisons can be made with winw, height comparisons with winh */
  
      if (isset(SINGLELINEZLE) || termok != TERM_OK) {
  	singlerefresh();
***************
*** 287,292 ****
--- 293,299 ----
  	cs = 0;
      }
      scs = line + cs;
+     numscrolls = 0;
  
  /* first, we generate the video line buffers so we know what to put on
     the screen - also determine final cursor position (nvln, nvcs) */
***************
*** 326,334 ****
  /* if we're really on the next line, don't fake it; do everything properly */
      if (t == scs && (nvcs = s - (unsigned char *)(nbuf[nvln = ln])) == winw) {
  	*s = '\0';
! 	if (!nbuf[++ln])
! 	    nbuf[ln] = (char *)zalloc(winw + 1);
! 	s = (unsigned char *)nbuf[ln];
  	nvcs = 0;
  	nvln++;
      }
--- 333,343 ----
  /* if we're really on the next line, don't fake it; do everything properly */
      if (t == scs && (nvcs = s - (unsigned char *)(nbuf[nvln = ln])) == winw) {
  	*s = '\0';
! 	switch (*s) { 		/* a sad hack to make the break */
! 	case '\0':		/* in nextline work */
! 	    nextline
! 	}
! 	*s = '\0';
  	nvcs = 0;
  	nvln++;
      }
***************
*** 340,346 ****
  	tosln = ln + 1;
  	snextline
  	t = (unsigned char *)statusline;
! 	for (; t < (unsigned char *)statusline+statusll; t++) {
  	    if (icntrl(*t)) {	/* simplified processing in the status line */
  		*s++ = '^';
  		if (s == sen)
--- 349,355 ----
  	tosln = ln + 1;
  	snextline
  	t = (unsigned char *)statusline;
! 	for (; t < (unsigned char *)statusline + statusll; t++) {
  	    if (icntrl(*t)) {	/* simplified processing in the status line */
  		*s++ = '^';
  		if (s == sen)
***************
*** 361,366 ****
--- 370,381 ----
  	nbuf[tosln - 1][winw] = '\0';
      }
  
+ /* insert <....> at end of first status line if status is too big */
+     if (more_status) {
+ 	strncpy(nbuf[tosln] + winw - 8, " <....> ", 8);
+ 	nbuf[tosln][winw] = '\0';
+     }
+ 
      *s = '\0';
      nlnct = ln + 1;
      for (ln = nlnct; ln < winh; ln++)
***************
*** 478,483 ****
--- 493,499 ----
      ovln = nvln;
      olnct = nlnct;
      oput_rpmpt = put_rpmpt;
+     onumscrolls = numscrolls;
      if (nlnct > vmaxln)
  	vmaxln = nlnct;
      fflush(shout);		/* make sure everything is written out */



-- 
Geoff Wing [gwing@primenet.com.au]   Technical Manager
  Phone    : +61-3-9818 2977	     PrimeNet - Internet Consultancy
  Facsimile: +61-3-9819 3788	     Web : <URL:http://www.primenet.com.au/>
  Mobile   : 0412 162 441


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

* Re: zle_refresh trial patch (and unrelated bug)
       [not found] ` <gwing@primenet.com.au>
@ 1996-11-09 17:09   ` Bart Schaefer
  1996-11-12 12:40     ` Peter Stephenson
  0 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 1996-11-09 17:09 UTC (permalink / raw)
  To: zsh-workers

On Nov 9,  9:22pm, Geoff Wing wrote:
} Subject: zle_refresh trial patch
}
} here's a trial patch for nicer scrolling.

Looks pretty good to me.

} The type of command I've mainly checked it with is:
} % zed -f zed

I tried that, and when I accept-line I get

zsh: = not found

But I get that in 3.0.0 too, so it has nothing to do with your patch.
This seems to be the culprit:

	builtin let fun == 0 && eval function "$var"

Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))"
into "builtin let fun == 0", which is not being parsed correctly.

Either the output of "functions" needs to get fixed for this case, or
(probably better) the parser has to make "==" a reserved word so it is
not interpeted as "$(which -p '=')".

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: Handling for ZLE modules
  1996-11-08 17:16 ` Handling for ZLE modules Zefram
  1996-11-08 17:26   ` Bruce Stephens
@ 1996-11-10 23:55   ` Zoltan Hidvegi
  1996-11-11 13:07   ` Peter Stephenson
  2 siblings, 0 replies; 13+ messages in thread
From: Zoltan Hidvegi @ 1996-11-10 23:55 UTC (permalink / raw)
  To: Zefram; +Cc: pws, zsh-workers

> >deleting at the end.  I have arranged it so that the function is
> >marked as deleted with name "<deleted>" (which should only be used for
> >output), but the table entry is kept.
> 
> I don't like this.  Do we retain the binding or not?  If not, we have

I do not like it either.  A clueless user can have hard time to track down
what changed his keybindings so unexpectedly.

> On a related note, we really need to make addbuiltin() and so on handle
> failure cases gracefully.  Try loading mod_example.so twice ("modload
> ./mod_example.so; modload ~+/mod_example.so"): when I tried it it
> segmentated.  Modules are going to have to cope with the possibility
> that they can't add the builtins, key bindings or whatever that they
> want.

The coredump is caused by the attempt to free the previously defined
builtin in addhashnode().  I think the best is to refuse adding the builtin
if it already exists.  A well behaved module should be prepared to handle
situations when it is loaded multiple times.  The patch below does a
dlclose() and does not add the module to the module list if the boot
function returns nonzero.  Patch to mod_example.c is not included since I'm
writing this from home and the current version is not here with me.

> And if anyone's counting, I, too, favour the name `zmodload'.

That's fine for me.

> (Own up, how many of us are planning how to implement autoloaded modules?)

I am.  We can add a flag to zmodload to define auloaded builtins.  It adds
a builtin with NULL as a handlerfunc.  When such a builtin is executed
execbuiltin() looks up the module with the same name in the MODULE_PATH.
We also have to add some hacks to specify the module which should be loaded
since a package will opten want to define a bunch of builtins which sould
be autoloaded if either one is refered.  The patch below modifies
addbuiltin() so that it allows adding an already defined builtin if its
handler function is NULL.  In that case addbuiltin simply overwrites the
existing structure.  That can be used in the future for autoloading.

Unfortunately it seems to be impossible to handle BINF_MAGICEQUALS and
BINF_PSPECIAL this way (unless we add other options to zmodload for that).

Instead of zmodload it may be better to use the autoload with an option
(e.g. autoload -b).

Zoltan

*** Src/module.c	1996/10/31 01:38:10	3.1.0.1
--- Src/module.c	1996/11/10 23:43:44
***************
*** 159,166 ****
  		    cleanup_module(m);
  		    dlclose(m->handle);
  		    if (! --(m->count)) {
- 			zsfree(m->nam);
  			remnode(modules, node);
  		    }
  		}
  		break;
--- 159,167 ----
  		    cleanup_module(m);
  		    dlclose(m->handle);
  		    if (! --(m->count)) {
  			remnode(modules, node);
+ 			zsfree(m->nam);
+ 			zfree(m, sizeof(*m));
  		    }
  		}
  		break;
***************
*** 175,186 ****
  	    if (! ops['f']) {
  		zwarnnam(nam, "module %s already loaded.", *args, 0);
  		ret++;
! 	    } else if (load_module(*args) != m->handle) {
  		zwarnnam(nam, "reloaded module %s have new handle?", *args, 0);
  		ret++;
  	    } else {
  		m->count++;
- 		ret = init_module(m);
  	    }
  	} else if (! (handle = load_module(*args))) {
  	    zwarnnam(nam, "failed to load module: %s", *args, 0);
--- 176,191 ----
  	    if (! ops['f']) {
  		zwarnnam(nam, "module %s already loaded.", *args, 0);
  		ret++;
! 	    } else if ((handle = load_module(*args)) != m->handle) {
  		zwarnnam(nam, "reloaded module %s have new handle?", *args, 0);
+ 		if (handle)
+ 		    dlclose(handle);
+ 		ret++;
+ 	    } else if (init_module(m)) {
+ 		dlclose(handle);
  		ret++;
  	    } else {
  		m->count++;
  	    }
  	} else if (! (handle = load_module(*args))) {
  	    zwarnnam(nam, "failed to load module: %s", *args, 0);
***************
*** 190,228 ****
  	    m->nam = ztrdup(*args);
  	    m->handle = handle;
  	    m->count = 1;
! 	    PERMALLOC {
! 		addlinknode(modules, m);
! 	    } LASTALLOC;
! 	    ret = init_module(m);
  	}
      }
      return ret;
  }
  
  /**/
! void
  addbuiltin(char *nam, int flags, HandlerFunc hfunc, int minargs, int maxargs, char *optstr)
  {
      Builtin bn;
  
!     bn = zcalloc(sizeof(*bn));
!     bn->nam = nam;
      bn->flags = flags;
      bn->handlerfunc = hfunc;
      bn->minargs = minargs;
      bn->maxargs = maxargs;
      bn->optstr = optstr;
!     PERMALLOC {
! 	builtintab->addnode(builtintab, bn->nam, bn);
!     } LASTALLOC;
  }
  
  /**/
! void
  deletebuiltin(char *nam)
  {
      Builtin bn;
  
      bn = (Builtin) builtintab->removenode(builtintab, nam);
      zfree(bn, sizeof(struct builtin));
  }
--- 195,262 ----
  	    m->nam = ztrdup(*args);
  	    m->handle = handle;
  	    m->count = 1;
! 	    if (init_module(m)) {
! 		dlclose(handle);
! 		ret++;
! 		zsfree(m->nam);
! 		zfree(m, sizeof(*m));
! 	    } else {
! 		PERMALLOC {
! 		    addlinknode(modules, m);
! 		} LASTALLOC;
! 	    }
  	}
      }
      return ret;
  }
  
+ /* addbuiltin() can be used to add a new builtin.  It has six arguments: *
+  *  - the name of the new builtin                                        *
+  *  - BINF_* flags (see zsh.h).  Normally it is 0.                       *
+  *  - the handler function of the builtin                                *
+  *  - minimum number of arguments                                        *
+  *  - maximum number of argument (-1 means unlimited)                    *
+  *  - possible option leters                                             *
+  * It returns zero on succes 1 on failure                                */
+ 
  /**/
! int
  addbuiltin(char *nam, int flags, HandlerFunc hfunc, int minargs, int maxargs, char *optstr)
  {
      Builtin bn;
  
!     bn = (Builtin) builtintab->getnode2(builtintab, nam);
!     if (bn && bn->handlerfunc)
! 	return 1;
!     if (!bn) {
! 	bn = zcalloc(sizeof(*bn));
! 	bn->nam = nam;
! 	PERMALLOC {
! 	    builtintab->addnode(builtintab, bn->nam, bn);
! 	} LASTALLOC;
!     }
      bn->flags = flags;
      bn->handlerfunc = hfunc;
      bn->minargs = minargs;
      bn->maxargs = maxargs;
      bn->optstr = optstr;
!     return 0;
  }
  
+ /* Remove the builtin added previously by addbuiltin().  Returns *
+  * zero on succes and 1 if there is no builtin with that name.   *
+  * Attempt to delete a builtin which is not defined by           *
+  * addbuiltin() will fail badly with unpredictable results.      */
+ 
  /**/
! int
  deletebuiltin(char *nam)
  {
      Builtin bn;
  
      bn = (Builtin) builtintab->removenode(builtintab, nam);
+     if (!bn)
+ 	return 1;
      zfree(bn, sizeof(struct builtin));
+     return 0;
  }


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

* Re: Handling for ZLE modules
  1996-11-08 17:16 ` Handling for ZLE modules Zefram
  1996-11-08 17:26   ` Bruce Stephens
  1996-11-10 23:55   ` Zoltan Hidvegi
@ 1996-11-11 13:07   ` Peter Stephenson
  2 siblings, 0 replies; 13+ messages in thread
From: Peter Stephenson @ 1996-11-11 13:07 UTC (permalink / raw)
  To: Zsh hackers list

Zefram wrote:
> >The other question is how to handle unloading.  One has to be careful
> >when bindings remain which point to the function; also, the functions
> >are in a linear array like the builtin functions and you may not be
> >deleting at the end.  I have arranged it so that the function is
> >marked as deleted with name "<deleted>" (which should only be used for
> >output), but the table entry is kept.
> 
> I don't like this.  Do we retain the binding or not?  If not, we have
> to go through every key binding, changing them to undefined-key.  The
> alternative would be to maintain link counts for loaded bindings, to
> avoid reusing a slot that is bound to some key.

O.K., the only rational way of doing this is to seek and destroy any
binding to a function which is deleted.  Having written this, it
seemed stupid not to make it directly available to the user as well,
so I added the bindkey -u option which undefines any binding to the
given command, which could be a builtin just as easily as one loaded
(though if it is, bindkey -d will still restore any predefined binding
to it, just as if you'd removed it with bindkey -r).

Since bindkey usually restricts itself to the current (or with -a, the
alternate) keymap, I made -u do that, and added another option -U
which deletes the command in every keymap (which is what
deletezlefunction() requires) --- the addition is trivial.

(It's really time the manual entry for bindkey was tidied up, too.)

I made addzlefunction() safer in case the function is already defined,
and modified the sample accordingly.

I don't think this clashes with anything recent, but you need the
first ZLE module patch, of course.

Maybe a bug or maybe not:  `bindkey -s -u string' doesn't work.

*** Doc/zshbuiltins.man.mod2	Mon Nov 11 11:46:10 1996
--- Doc/zshbuiltins.man	Mon Nov 11 13:45:41 1996
***************
*** 64,69 ****
--- 64,71 ----
  .TP
  \fBbindkey\fP \-\fBr\fP \fIin-string\fP ...
  .TP
+ \fBbindkey\fP \-\fBuU\fP \fIcommand\fP ...
+ .TP
  \fBbindkey\fP [ \-\fBa\fP ] \fIin-string\fP [ \fIcommand\fP ] ...
  .TP
  \fBbindkey\fP \-\fBs\fP [ \-\fBa\fP ] \fIin-string\fP \fIout-string\fP ...
***************
*** 77,83 ****
  loads the compiled-in bindings of these characters for the mode determined by
  the preceding options, or the current mode if used alone. Any previous bindings
  done by the user will be preserved. If the \-\fBr\fP option is given, remove
! any binding for each \fIin-string\fP. If the \-\fBs\fP option is not
  specified, bind each \fIin-string\fP to a specified \fIcommand\fP. If no
  \fIcommand\fP is specified, print the binding of \fIin-string\fP if it is
  bound, or return a nonzero exit code if it is not bound. If the \-\fBs\fP
--- 79,88 ----
  loads the compiled-in bindings of these characters for the mode determined by
  the preceding options, or the current mode if used alone. Any previous bindings
  done by the user will be preserved. If the \-\fBr\fP option is given, remove
! any binding for each \fIin-string\fP. If the \-\fBu\fP option is
! given, undefine every key bound to \fIcommand\fP in the current
! keymap; with \-\fBU\fP, do so in every keymap.  If the \-\fBs\fP
! option is not
  specified, bind each \fIin-string\fP to a specified \fIcommand\fP. If no
  \fIcommand\fP is specified, print the binding of \fIin-string\fP if it is
  bound, or return a nonzero exit code if it is not bound. If the \-\fBs\fP
*** Src/hashtable.h.mod2	Mon Nov 11 10:08:33 1996
--- Src/hashtable.h	Mon Nov 11 13:44:40 1996
***************
*** 259,265 ****
      {NULL, "alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL},
      {NULL, "autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"},
      {NULL, "bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL},
!     {NULL, "bindkey", 0, bin_bindkey, 0, -1, 0, "asvemdr", NULL},
      {NULL, "break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL},
      {NULL, "bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL},
      {NULL, "cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL},
--- 259,265 ----
      {NULL, "alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL},
      {NULL, "autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"},
      {NULL, "bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL},
!     {NULL, "bindkey", 0, bin_bindkey, 0, -1, 0, "asvemdruU", NULL},
      {NULL, "break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL},
      {NULL, "bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL},
      {NULL, "cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL},
*** Src/mod_deltochar.c.mod2	Mon Nov 11 11:41:45 1996
--- Src/mod_deltochar.c	Mon Nov 11 11:43:01 1996
***************
*** 73,80 ****
  int
  boot_mod_deltochar(void *dummy)
  {
!     z_deltochar = addzlefunction("delete-to-char", deltochar, ZLE_DELETE);
!     return 0;
  }
  
  /**/
--- 73,84 ----
  int
  boot_mod_deltochar(void *dummy)
  {
!     int newfunc = addzlefunction("delete-to-char", deltochar, ZLE_DELETE);
!     if (newfunc > 0) {
! 	z_deltochar = newfunc;
! 	return 0;
!     } else
! 	return -1;
  }
  
  /**/
*** Src/module.c.mod2	Mon Nov 11 11:35:47 1996
--- Src/module.c	Mon Nov 11 13:33:00 1996
***************
*** 268,281 ****
      struct zlecmd *zc = NULL;
      int slot, addsize = zlecmdtot - ZLECMDCOUNT;
  
!     /* Should we check for a name clash, or let the module do it? */
  
!     /* First try and find a free slot.
!      * Slight problem:  if we re-use a slot then any key-binding
!      * which has not been deleted picks up the new function.
!      * It's not clear this is up to ZLE to deal with:  the
!      * use can fix it with bindkey if (s)he wants
!      */
      for (slot = 0; slot < addsize; slot++)
  	if (zlecmdadd[slot].flags & ZLE_DELETED) {
  	    zc = zlecmdadd + slot;
--- 268,278 ----
      struct zlecmd *zc = NULL;
      int slot, addsize = zlecmdtot - ZLECMDCOUNT;
  
!     /* Check for a clash */
!     if (zlefindfunc(name) != zlecmdtot)
! 	return -1;
  
!     /* First try and find a free slot. */
      for (slot = 0; slot < addsize; slot++)
  	if (zlecmdadd[slot].flags & ZLE_DELETED) {
  	    zc = zlecmdadd + slot;
***************
*** 309,318 ****
  
      if (zcn < ZLECMDCOUNT || zcn >= zlecmdtot)
  	return;
      zcn -= ZLECMDCOUNT;
  
      zc = zlecmdadd + zcn;
!     zc->name = "<deleted>";
      zc->func = feep;
      zc->flags = ZLE_DELETED;
  }
--- 306,317 ----
  
      if (zcn < ZLECMDCOUNT || zcn >= zlecmdtot)
  	return;
+     /* Remove all key bindings to zcn, wherever */
+     unbindzlefunc(zcn, 0);
      zcn -= ZLECMDCOUNT;
  
      zc = zlecmdadd + zcn;
!     zc->name = "";
      zc->func = feep;
      zc->flags = ZLE_DELETED;
  }
*** Src/zle_main.c.mod2	Mon Nov 11 09:52:17 1996
--- Src/zle_main.c	Mon Nov 11 13:44:27 1996
***************
*** 963,968 ****
--- 963,980 ----
  	char *s;
  	int func, len, firstzero = 0;
  
+ 	if (ops['u'] || ops['U']) {
+ 	    /* unbind all references to given function */
+ 	    func = zlefindfunc(*argv);
+ 	    if (func == zlecmdtot) {
+ 		zerr("undefined function: %s", *argv, 0);
+ 		return 1;
+ 	    }
+ 	    unbindzlefunc(func, ops['U'] ? 0 : ops['a'] ? 2 : 1);
+ 	    argv++;
+ 	    continue;
+ 	}
+ 
  	s = getkeystring(*argv++, &len, 2, NULL);
  	if (len > 1) {
  	    if (s[0])
***************
*** 989,1027 ****
  		    tab[STOUC(*s)] = z_undefinedkey;
  		    if (func == z_sendstring)
  			free(keybindtab->removenode(keybindtab, s));
! 		} else {
! 		    if (ky && ky->prefixct) {
! 			if (ky->func == z_sendstring) {
! 			    zfree(ky->str, ky->len);
! 			    ky->str = NULL;
! 			}
! 			ky->func = z_undefinedkey;
! 		    } else
! 			free(keybindtab->removenode(keybindtab, s));
! 		    if (len > 1) {
! 			s[--len] = '\0';
! 			while (len > 1) {
! 			    (ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--;
! 			    if (!ky->prefixct && ky->func == z_undefinedkey)
! 				free(keybindtab->removenode(keybindtab, s));
! 			    s[--len] = '\0';
! 			}
! 			(ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--;
! 			if (!ky->prefixct) {
! 			    int *otab = ops['a'] ? mainbindtab : altbindtab;
! 			    tab[STOUC(*s)] = ky->func;
! 			    /*
! 			     * If the bindtab we are not using also
! 			     * adds this key as a prefix, it must also
! 			     * be reset.
! 			     */
! 			    if (otab[STOUC(*s)] == z_prefix)
! 				otab[STOUC(*s)] = ky->func;
! 			    if (ky->func != z_sendstring)
! 				free(keybindtab->removenode(keybindtab, s));
! 			}
! 		    }
! 		}
  		zfree(s, len);
  		continue;
  	    }
--- 1001,1008 ----
  		    tab[STOUC(*s)] = z_undefinedkey;
  		    if (func == z_sendstring)
  			free(keybindtab->removenode(keybindtab, s));
! 		} else
! 		    delprefbinding(keybindtab, ky, s, len);
  		zfree(s, len);
  		continue;
  	    }
***************
*** 1094,1099 ****
--- 1075,1127 ----
      return 0;
  }
  
+ /* Delete a binding for a key sequence with prefixes */
+ 
+ /**/
+ void
+ delprefbinding(HashTable ktab, Key ky, char *s, int len)
+ {
+     if (ky && ky->prefixct) {
+ 	if (ky->func == z_sendstring) {
+ 	    zfree(ky->str, ky->len);
+ 	    ky->str = NULL;
+ 	}
+ 	ky->func = z_undefinedkey;
+     } else
+ 	free(ktab->removenode(ktab, s));
+     if (len > 1) {
+ 	s[--len] = '\0';
+ 	while (len > 1) {
+ 	    (ky = (Key) ktab->getnode(ktab, s))->prefixct--;
+ 	    if (!ky->prefixct && ky->func == z_undefinedkey)
+ 		free(ktab->removenode(ktab, s));
+ 	    s[--len] = '\0';
+ 	}
+ 	(ky = (Key) ktab->getnode(ktab, s))->prefixct--;
+ 	if (!ky->prefixct) {
+ 	    /*
+ 	     * Both the main and alternate binding tables use
+ 	     * the same keybindings, so we need to delete them here.
+ 	     * We need to pick the table associated with the right ktab
+ 	     * (i.e. vi or emacs).  If the ktab we are passed is not
+ 	     * current (i.e. not keybindtab), the alternate table
+ 	     * is not relevant, so don't touch it.
+ 	     */
+ 	    int *tab = (ktab == emkeybindtab) ? emacs_cur_bindtab :
+ 		viins_cur_bindtab;
+ 	    if (tab[STOUC(*s)] == z_prefix)
+ 		tab[STOUC(*s)] = ky->func;
+ 	    if (ktab == keybindtab) {
+ 		if (altbindtab[STOUC(*s)] == z_prefix)
+ 		    altbindtab[STOUC(*s)] = ky->func;
+ 	    }
+ 	    if (ky->func != z_sendstring)
+ 		free(ktab->removenode(ktab, s));
+ 	}
+     }
+ 
+ }
+ 
  /**/
  void
  freekeynode(HashNode hn)
***************
*** 1197,1202 ****
--- 1225,1301 ----
      else
  	putc('\n', shout);
      showinglist = 0;
+ }
+ 
+ LinkList bindremlist;
+ 
+ /**/
+ void
+ zerobinding(HashNode hn, int ifunc)
+ {
+     if (((Key)hn)->func == ifunc)
+ 	addlinknode(bindremlist, hn);
+ }
+ 
+ /*
+  * Unbind the given zle function ifunc wherever it occurs.
+  * With notall = 0, do this for all binding tables.
+  *	       = 1, do this in the main binding table.
+  *             = 2, do this in the alternate binding table.
+  * Note that the main and alternate binding tables share
+  * the same table for sequences with prefixes.
+  */
+ 
+ /**/
+ void
+ unbindzlefunc(int ifunc, int notall)
+ {
+     int i, **bindptr;
+     int *bindlist[] = { altbindtab, emacs_cur_bindtab, viins_cur_bindtab,
+ 			    NULL };
+     HashTable keybindlist[] = { emkeybindtab, vikeybindtab, NULL };
+     HashTable *keybindptr;
+ 
+     PERMALLOC {
+ 	for (keybindptr = keybindlist; *keybindptr; keybindptr++) {
+ 	    LinkNode ln;
+ 	    bindremlist = newlinklist();
+ 	    if (notall)
+ 		keybindptr = &keybindtab;
+ 
+ 	    /*
+ 	     * Search the key binding tables for the function.
+ 	     * It's dangerous to modify a hash table while scanning,
+ 	     * so put the bindings found in a list and
+ 	     * delete the bindings one by one later.
+ 	     */
+ 	    scanhashtable(*keybindptr, 0, 0, 0, zerobinding, ifunc);
+ 
+ 	    for (ln = firstnode(bindremlist); ln; incnode(ln)) {
+ 		Key k = (Key) ln->dat;
+ 		char *s = ztrdup(k->nam);
+ 		int sl = strlen(s);
+ 		delprefbinding(*keybindptr, k, s, sl);
+ 		zfree(s, sl);
+ 	    }
+ 
+ 	    freelinklist(bindremlist, NULL);
+ 	    if (notall)
+ 		break;
+ 	}
+ 	bindremlist = NULL;
+     } LASTALLOC;
+ 
+     for (bindptr = bindlist; *bindptr; bindptr++) {
+ 	/* if notall == 2, we are doing altbindtab first anyway */
+ 	if (notall == 1)
+ 	    bindptr = &mainbindtab;
+ 	for (i = 0; i < 256; i++)
+ 	    if ((*bindptr)[i] == ifunc)
+ 		(*bindptr)[i] = z_undefinedkey;
+ 	if (notall)
+ 	    break;
+     }
  }
  
  /**/

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77413
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


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

* Re: Handling for ZLE modules
       [not found] ` <pws@ifh.de>
  1996-11-08 16:45   ` Bart Schaefer
@ 1996-11-11 16:02   ` Bart Schaefer
  1996-11-13 18:53   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
  2 siblings, 0 replies; 13+ messages in thread
From: Bart Schaefer @ 1996-11-11 16:02 UTC (permalink / raw)
  To: Zsh hackers list

On Nov 11,  2:07pm, Peter Stephenson wrote:
} Subject: Re: Handling for ZLE modules
}
} O.K., the only rational way of doing this is to seek and destroy any
} binding to a function which is deleted.

I agree with the changes made in this patch, but I wanted to point out
that this is the second patch in the last 24 hours that has clashed
with a previous patch.  The last patch from Zoltan, and now this one
from Peter, both conflict with Zefram's from a few days ago.  I can't
remember how long it has been since that last happened with patches I
applied from zsh-workers.

Fortunately, the resolution for the rejects was relatively obvious, and
it's nice that this has generated so much interest.  I'm beginning to
worry, however, that we're about to start producing contradictory fixes
for the same problems.  Should we try to get this organized somehow
before that happens?  Or are we just counting on Zoltan to have enough
free time to sort it all out?

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: zle_refresh trial patch (and unrelated bug)
  1996-11-09 17:09   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
@ 1996-11-12 12:40     ` Peter Stephenson
  0 siblings, 0 replies; 13+ messages in thread
From: Peter Stephenson @ 1996-11-12 12:40 UTC (permalink / raw)
  To: Zsh hackers list

"Bart Schaefer" wrote:
> 	builtin let fun == 0 && eval function "$var"
> 
> Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))"
> into "builtin let fun == 0", which is not being parsed correctly.

Nor will it ever be --- that's quite a serious bug.  `let' needs to
get each expression as one single argument, so it should be
   builtin let "fun == 0"
and I'm pretty sure it was until not all that long ago.

In fact, Zoltan has improved the lexing of ((...)) so that it's no
longer quite the same as a double quoted expression, so that my
original hack of turning the former into the latter for ease of
reconstructing the text is not quite so appropriate.

> Either the output of "functions" needs to get fixed for this case, or
> (probably better) the parser has to make "==" a reserved word so it is
> not interpeted as "$(which -p '=')".

This won't help here, but maybe == is common enough as a test to have
a special case anyway.

*** Src/subst.c~	Thu Oct 10 12:05:11 1996
--- Src/subst.c	Tue Nov 12 13:31:18 1996
***************
*** 371,377 ****
  	    *namptr = dyncat(hom, ptr);
  	    return 1;
  	}
!     } else if (*str == Equals && isset(EQUALS) && str[1]) {   /* =foo */
  	char sav, *pp, *cnam;
  
  	for (pp = str + 1; !isend2(*pp); pp++);
--- 371,378 ----
  	    *namptr = dyncat(hom, ptr);
  	    return 1;
  	}
!     } else if (*str == Equals && isset(EQUALS) && str[1]
! 	       && str[1] != Equals) {   /* =foo */
  	char sav, *pp, *cnam;
  
  	for (pp = str + 1; !isend2(*pp); pp++);

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77413
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


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

* Re: zle_refresh trial patch (and unrelated bug)
       [not found] ` <pws@ifh.de>
  1996-11-08 16:45   ` Bart Schaefer
  1996-11-11 16:02   ` Bart Schaefer
@ 1996-11-13 18:53   ` Bart Schaefer
  1996-11-14  9:03     ` Peter Stephenson
  2 siblings, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 1996-11-13 18:53 UTC (permalink / raw)
  To: Zsh hackers list

On Nov 12,  1:40pm, Peter Stephenson wrote:
} Subject: Re: zle_refresh trial patch (and unrelated bug)
}
} "Bart Schaefer" wrote:
} > 	builtin let fun == 0 && eval function "$var"
} > 
} > Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))"
} > into "builtin let fun == 0", which is not being parsed correctly.
} 
} Nor will it ever be --- that's quite a serious bug.  `let' needs to
} get each expression as one single argument, so it should be
}    builtin let "fun == 0"
} and I'm pretty sure it was until not all that long ago.

So is somebody fixing this?  "zed -f" ("fned") is just about completely
useless because of this bug -- almost any function edited ends up broken.
Even with Peter's patch for "==", you get `bad math expression' errors.
	

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern


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

* Re: zle_refresh trial patch (and unrelated bug)
  1996-11-13 18:53   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
@ 1996-11-14  9:03     ` Peter Stephenson
  1996-11-14 14:57       ` Zefram
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Stephenson @ 1996-11-14  9:03 UTC (permalink / raw)
  To: zsh-workers

(By the way, I've been getting mail fine... I've passed Bart's error
on to the postmaster, but it seems you need a pretty sophisticated
mailer even to see it :-))

"Bart Schaefer" wrote:
> On Nov 12,  1:40pm, Peter Stephenson wrote:
> } Subject: Re: zle_refresh trial patch (and unrelated bug)
> }
> } "Bart Schaefer" wrote:
> } > 	builtin let fun == 0 && eval function "$var"
> 
> So is somebody fixing this?  "zed -f" ("fned") is just about completely
> useless because of this bug -- almost any function edited ends up broken.
> Even with Peter's patch for "==", you get `bad math expression' errors.

When I posted the first message I was worried that dquote_parse() was
doing something it was going to be hard to keep up with.  However,
since you get an immediate parse error if you include a " inside a
((...)), sticking a nulled-out "..."  around the argument for recovery
in text.c looks like it will do the trick.  Anything more
sophisticated probably needs (( to have it's own type flag in struct
Cmd.  This patch certainly ought to restore the previous
functionality, though.  Certainly seems to fix up zed -f zed.  (By the
way, how about adding a noflowcontrol setopt to zed?  I just
discovered I liked this.)

(Sorrysorry... it's against 3.1 again.  I don't have the luxury here
of space for arbitrary versions.  I really don't think that will make
a difference this time.)

*** Src/lex.c.dbp	Thu Nov 14 09:44:46 1996
--- Src/lex.c	Thu Nov 14 09:45:09 1996
***************
*** 378,384 ****
--- 378,386 ----
  	bptr = tokstr = (char *)ncalloc(bsiz = 256);
  	hungetc(c);
  	cmdpush(CS_MATH);
+ 	add(Dnull);
  	c = dquote_parse(')', 0);
+ 	add(Dnull);
  	cmdpop();
  	if (c || (c = hgetc()) != ')') {
  	    hungetc(c);

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77413
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


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

* Re: zle_refresh trial patch (and unrelated bug)
  1996-11-14  9:03     ` Peter Stephenson
@ 1996-11-14 14:57       ` Zefram
  0 siblings, 0 replies; 13+ messages in thread
From: Zefram @ 1996-11-14 14:57 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

>                                            Anything more
>sophisticated probably needs (( to have it's own type flag in struct
>Cmd.

I for one would like that to happen.  It's really annoying to have (())
changed to let when listing functions.  It's also confusing to have
(()) fail after "disable let".

>(Sorrysorry... it's against 3.1 again.  I don't have the luxury here
>of space for arbitrary versions.  I really don't think that will make
>a difference this time.)

It only really makes a difference when patching the module code
itself.  IMO we shouldn't be posting patches for `configure' itself
anyway; they are large and contain no information.  (zsh developers can
be assumed to have autoconf available.)

-zefram


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

end of thread, other threads:[~1996-11-14 15:04 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-11-09 10:22 zle_refresh trial patch Geoff Wing
     [not found] ` <gwing@primenet.com.au>
1996-11-09 17:09   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
1996-11-12 12:40     ` Peter Stephenson
  -- strict thread matches above, loose matches on Subject: below --
1996-11-08 15:26 Handling for ZLE modules Peter Stephenson
     [not found] ` <pws@ifh.de>
1996-11-08 16:45   ` Bart Schaefer
1996-11-11 16:02   ` Bart Schaefer
1996-11-13 18:53   ` zle_refresh trial patch (and unrelated bug) Bart Schaefer
1996-11-14  9:03     ` Peter Stephenson
1996-11-14 14:57       ` Zefram
1996-11-08 17:16 ` Handling for ZLE modules Zefram
1996-11-08 17:26   ` Bruce Stephens
1996-11-10 23:55   ` Zoltan Hidvegi
1996-11-11 13:07   ` Peter Stephenson

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).