zsh-workers
 help / color / mirror / code / Atom feed
* Re: wrapper functions in modules
@ 1998-12-15 12:03 Sven Wischnowsky
  1998-12-15 17:05 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 1998-12-15 12:03 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ...
> 
> Is the new first parameter of doshfunc() needed any longer?  runshfunc()
> doesn't do anything with it except pass it to wrap->handler(), and at
> least in the example module the handler doesn't do anything with it but
> pass it back to runshfunc() again.  Why are we slinging this around?

[For those who don't want to look at the code: the argument is the
name of the function to be executed.]

I added the argument since modules may be interested in it and there
may be no other way to get at this information (depending on FUNCTIONARGZERO).

The example uses it in the call to strncmp().

Bye
 Sven


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


^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: wrapper functions in modules
@ 1998-12-16  8:05 Sven Wischnowsky
  1998-12-16  9:50 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 1998-12-16  8:05 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> 
> On Dec 15,  1:03pm, Sven Wischnowsky wrote:
> } Subject: Re: wrapper functions in modules
> }
> } Bart Schaefer wrote:
> } > Is the new first parameter of doshfunc() needed any longer?
> } 
> } [For those who don't want to look at the code: the argument is the
> } name of the function to be executed.]
> } 
> } I added the argument since modules may be interested in it
> 
> Hm.  I'm not sure that modules *ought* to be interested in it, but...

It's just that wrappers can't get at this information. But I wouldn't
resist to remove this or to use a global variable for it.
Apropos variables: we could use two static variables for the other
arguments a wrapper function gets and which are only passed to
runshfunc()... hm, I might produce a patch for this some time.

> 
> One thing a wrapper function might legitimately be interested in is the
> context in which it was called.  By that I mean, the wrapper might want
> to do something different if the function is being run by the completion
> widget code (the call to doshfunc() in zle_main.c), the compctl -K code
> or -Y code (zle_tricky.c), or the signal traps (signals.c).  The signal
> handlers can sort of be determined by examination of the name, but that's
> not what I'd call the best way to do it (e.g. it's possible to invoke the
> trap functions manually without a signal having been received), and that
> doesn't work for the other cases.

Yes, that would be good to have. Using a global integer variable or an 
argument and a couple of constants?

Bye
 Sven


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


^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: wrapper functions in modules
@ 1998-12-14 10:11 Sven Wischnowsky
  1998-12-14 18:42 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 1998-12-14 10:11 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> 
> On Dec 11,  3:16pm, Sven Wischnowsky wrote:
> } Subject: Re: wrapper functions in modules
> }
> } [...] my first idea was to let modules register only one function
> } which would have to call back the execution code [...]
> } This would solve the call stack problems you mentioned. Also, writing
> } wrappers would be easier in modules since you can use local variables, 
> } static local variables for number-of-calls and so on...
> 
> This would indeed be an improvement.  An interesting side-effect is that
> it would permit a module to decide not to run the shell function at all;
> it could instead branch off into any code it liked.
> 

The patch below implements this suggestion with a slight modification: 
the wrapper function now returns an integer value. Returning zero
means that the shell function was executed (by calling
runshfunc()). Returning non-zero means that the execution code has to
execute the function itself. This way a module can easily define
wrapper function that are to be used only under certain conditions or
that don't need cleanup code.

> That in turn probably makes modules even more dangerous than before, from
> a run-time perspective.  An innoccuous module placed in root's module path
> could suddenly have someone else driving the shell.  It might even be a
> good idea to have zsh refuse to dynamically load modules when EUID==0, or
> at least refuse to auto-load them.

The fact that module can choose not to execute shell functions was one 
of the reasons why I first implemented to separate functions (the
other was that unloading-modules-thing, I didn't realise all the
implications that has).

> } About the problems with unloading: I would vote for completely
> } disallowing to unload a module if a wrapper is active for it.
> } This is relatively easy to keep track of and seems to be the savest
> 
> (Safest.)  This still isn't quite good enough -- you can't unload
> modules upon which other modules depend, so if X has a wrapper and
> depends on Y, you can't unload Y even though Y has no wrapper.
> 
> This probably means you end up refusing to unload any modules at all
> whenever there are any wrappers at all, which may be problematic.

But this interferes only with wrappers that are currently being
executed.
The patch doesn't change the unloading stuff, though we will have to
find a solution for it.

> 
> } the question is: how often does one want to unload modules in shell
> } functions?
> 
> I could envision someone wanting to write a pair of functions, one that
> installs several related modules and another that uninstalls them again.

Hm, right. Which brings us back to the separation of user-interface
and internals you mentioned.
We could keep the current function interface and offer a more basic
one for separately defining and deleting the user-visible and internal 
things so that only modules with wrapper functions that call
runshfunc() would be affected.

> 
> } Finally about the order in which installed wrappers are to be called:
> } looking at load_module() it should be enough to build the wrappers
> } list by appending new definitions to the end.
> 
> Yes, as I said, if the only constraint is module dependencies this will
> work fine.

The patch does this.

Another things this patch doesn't do is: add documentation. I agree
that we should have documentation for all this, but the file
Util/zsh-development-guide you mentioned doesn't contain anything
about modules...

Maybe I find some time to add it in the next days (although others are 
certainly more qualified to describe the basic module loading
mechanisms).


Bye
 Sven

*** os/zsh.h	Mon Dec 14 10:53:29 1998
--- Src/zsh.h	Mon Dec 14 10:24:28 1998
***************
*** 774,795 ****
  
  /* node in list of function call wrappers */
  
! typedef void (*WrapBefore) _((FuncWrap, char *));
! typedef void (*WrapAfter) _((FuncWrap, char *, int));
  
  struct funcwrap {
      FuncWrap next;
      int flags;
!     WrapBefore before;
!     WrapAfter after;
      Module module;
      int count;
  };
  
  #define WRAPF_ADDED 1
  
! #define WRAPDEF(before, after) \
!     { NULL, 0, before, after, NULL, 0 }
  
  /* node in builtin command hash table (builtintab) */
  
--- 774,793 ----
  
  /* node in list of function call wrappers */
  
! typedef int (*WrapFunc) _((List, FuncWrap, char *));
  
  struct funcwrap {
      FuncWrap next;
      int flags;
!     WrapFunc handler;
      Module module;
      int count;
  };
  
  #define WRAPF_ADDED 1
  
! #define WRAPDEF(func) \
!     { NULL, 0, func, NULL, 0 }
  
  /* node in builtin command hash table (builtintab) */
  
*** os/exec.c	Mon Dec 14 10:53:28 1998
--- Src/exec.c	Mon Dec 14 10:36:29 1998
***************
*** 2657,2667 ****
  {
      char **tab, **x, *oargv0 = NULL;
      int xexittr, newexittr, oldzoptind, oldlastval;
-     char *ou;
      void *xexitfn, *newexitfn;
      char saveopts[OPT_SIZE];
      int obreaks = breaks;
-     FuncWrap wrap, nwrap;
  
      HEAPALLOC {
  	pushheap();
--- 2657,2665 ----
***************
*** 2706,2740 ****
  		argzero = ztrdup(argzero);
  	    }
  	}
! 	for (wrap = wrappers; wrap; wrap = wrap->next) {
! 	    if (wrap->before)
! 		wrap->before(wrap, name);
! 	    if (wrap->after) {
! 		wrap->module->flags |= MOD_WRAPPER;
! 		wrap->count++;
! 	    }
! 	}
! 	startparamscope();
! 	ou = underscore;
! 	underscore = ztrdup(underscore);
! 	execlist(dupstruct(list), 1, 0);
! 	zsfree(underscore);
! 	underscore = ou;
! 	endparamscope();
! 	for (wrap = wrappers; wrap; wrap = nwrap) {
! 	    nwrap = wrap->next;
! 	    if (wrap->after) {
! 		wrap->after(wrap, name, lastval);
! 		wrap->count--;
! 		if (!wrap->count) {
! 		    wrap->module->flags &= ~MOD_WRAPPER;
! 		    if (wrap->module->flags & MOD_UNLOAD) {
! 			wrap->module->flags &= ~MOD_UNLOAD;
! 			unload_module(wrap->module, NULL);
! 		    }
! 		}
! 	    }
! 	}
  	if (retflag) {
  	    retflag = 0;
  	    breaks = obreaks;
--- 2704,2710 ----
  		argzero = ztrdup(argzero);
  	    }
  	}
! 	runshfunc(list, wrappers, name);
  	if (retflag) {
  	    retflag = 0;
  	    breaks = obreaks;
***************
*** 2787,2792 ****
--- 2757,2798 ----
  	    lastval = oldlastval;
  	popheap();
      } LASTALLOC;
+ }
+ 
+ /* This finally executes a shell function and any function wrappers     *
+  * defined by modules. This works by calling the wrapper function which *
+  * in turn has to call back this function with the arguments it gets.   */
+ 
+ /**/
+ void
+ runshfunc(List list, FuncWrap wrap, char *name)
+ {
+     int cont;
+     char *ou;
+ 
+     while (wrap) {
+ 	wrap->module->flags |= MOD_WRAPPER;
+ 	wrap->count++;
+ 	cont = wrap->handler(list, wrap->next, name);
+ 	wrap->count--;
+ 	if (!wrap->count) {
+ 	    wrap->module->flags &= ~MOD_WRAPPER;
+ 	    if (wrap->module->flags & MOD_UNLOAD) {
+ 		wrap->module->flags &= ~MOD_UNLOAD;
+ 		unload_module(wrap->module, NULL);
+ 	    }
+ 	}
+ 	if (!cont)
+ 	    return;
+ 	wrap = wrap->next;
+     }
+     startparamscope();
+     ou = underscore;
+     underscore = ztrdup(underscore);
+     execlist(dupstruct(list), 1, 0);
+     zsfree(underscore);
+     underscore = ou;
+     endparamscope();
  }
  
  /* Search fpath for an undefined function.  Finds the file, and returns the *
*** os/module.c	Mon Dec 14 10:53:29 1998
--- Src/module.c	Mon Dec 14 10:26:21 1998
***************
*** 328,337 ****
  int
  addwrapper(Module m, FuncWrap w)
  {
      if (w->flags & WRAPF_ADDED)
  	return 1;
!     w->next = wrappers;
!     wrappers = w;
      w->flags |= WRAPF_ADDED;
      w->module = m;
      w->count = 0;
--- 328,343 ----
  int
  addwrapper(Module m, FuncWrap w)
  {
+     FuncWrap p, q;
+ 
      if (w->flags & WRAPF_ADDED)
  	return 1;
!     for (p = wrappers, q = NULL; p; q = p, p = p->next);
!     if (q)
! 	q->next = w;
!     else
! 	wrappers = w;
!     w->next = NULL;
      w->flags |= WRAPF_ADDED;
      w->module = m;
      w->count = 0;
*** os/Modules/example.c	Wed Dec  9 15:45:33 1998
--- Src/Modules/example.c	Mon Dec 14 10:45:05 1998
***************
*** 79,112 ****
      return !strcmp("example", dyncat(s1, s2));
  }
  
- struct ogd {
-     struct ogd *next;
-     int val;
- };
- 
- static struct ogd *ogds;
- 
  /**/
! static void
! wrap_before(FuncWrap w, char *name)
  {
!     if (!strncmp(name, "example", 7)) {
! 	struct ogd *n = (struct ogd *) halloc(sizeof(*n));
  
- 	n->next = ogds;
- 	ogds = n;
- 	n->val = opts[GLOBDOTS];
  	opts[GLOBDOTS] = 1;
!     }
! }
  
! /**/
! static void
! wrap_after(FuncWrap w, char *name, int ret)
! {
!     if (!strncmp(name, "example", 7)) {
! 	opts[GLOBDOTS] = ogds->val;
! 	ogds = ogds->next;
      }
  }
  
--- 79,98 ----
      return !strcmp("example", dyncat(s1, s2));
  }
  
  /**/
! static int
! ex_wrapper(List list, FuncWrap w, char *name)
  {
!     if (strncmp(name, "example", 7))
! 	return 1;
!     else {
! 	int ogd = opts[GLOBDOTS];
  
  	opts[GLOBDOTS] = 1;
! 	runshfunc(list, w, name);
! 	opts[GLOBDOTS] = ogd;
  
! 	return 0;
      }
  }
  
***************
*** 124,140 ****
  };
  
  static struct funcwrap wrapper[] = {
!     WRAPDEF(wrap_before, wrap_after),
  };
  
  /**/
  int
  boot_example(Module m)
  {
-     ogds = NULL;
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
  	     addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
! 	     !addwrapper(wrapper));
  }
  
  #ifdef MODULE
--- 110,125 ----
  };
  
  static struct funcwrap wrapper[] = {
!     WRAPDEF(ex_wrapper),
  };
  
  /**/
  int
  boot_example(Module m)
  {
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
  	     addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
! 	     !addwrapper(m, wrapper));
  }
  
  #ifdef MODULE
***************
*** 145,151 ****
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
      deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
!     deletewrapper(wrapper);
      return 0;
  }
  #endif
--- 130,136 ----
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
      deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
!     deletewrapper(m, wrapper);
      return 0;
  }
  #endif

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


^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: wrapper functions in modules
@ 1998-12-11 14:16 Sven Wischnowsky
  1998-12-11 17:40 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 1998-12-11 14:16 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ... [ several serious problems with the wrapper functions ]

I stand corrected.

And damn, my first idea was to let modules register only one function
which would have to call back the execution code, i.e.:

doshfunc(...)
{
  ...
  runshfunc(list, wrappers);
  ...
}

runshfunc(List list, FuncWrap wrap)
{
  if (wrap)
    wrap->func(list, wrap->next);
  else {
    ...
    execlist(...);
    ...
  }
}

example_wrapper(List list, FuncWrap wrap)  // from module
{
  ... do something

  runshfunc(list, wrap);

  ... restore something
}

This would solve the call stack problems you mentioned. Also, writing
wrappers would be easier in modules since you can use local variables, 
static local variables for number-of-calls and so on...

About the problems with unloading: I would vote for completely
disallowing to unload a module if a wrapper is active for it.
This is relatively easy to keep track of and seems to be the savest,
the question is: how often does one want to unload modules in shell
functions?

Finally about the order in which installed wrappers are to be called:
looking at load_module() it should be enough to build the wrappers
list by appending new definitions to the end.

Ok. No patch for now, just the question: does this sound ok?

And, of course, if someone has ideas for a completely different
solution, I would like to hear about it.

Bye
 Sven


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


^ permalink raw reply	[flat|nested] 9+ messages in thread
* PATCH: wrapper functions in modules
@ 1998-12-09 14:44 Sven Wischnowsky
  1998-12-11 13:18 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 1998-12-09 14:44 UTC (permalink / raw)
  To: zsh-workers


Hello

This is the next bit prepared for the new completion stuff that might
be interesting to have elsewhere.

The patch below allows modules to register functions that are to be
executed before and after a function is called. This is completely
hidden from the user so there is no documentation for it.

Again, I have enhanced the example module. After you have loaded it it 
turns on GLOB_DOTS in every function whose name starts with `example'.

Several of the hunks are used to change calls to doshfunc(), since
this now gets the name of the function called as its first argument.


Bye
 Sven

diff -c os/builtin.c Src/builtin.c
*** os/builtin.c	Wed Dec  9 15:36:12 1998
--- Src/builtin.c	Wed Dec  9 14:40:24 1998
***************
*** 994,1000 ****
      if ((l = getshfunc("chpwd")) != &dummy_list) {
  	fflush(stdout);
  	fflush(stderr);
! 	doshfunc(l, NULL, 0, 1);
      }
  
      dirstacksize = getiparam("DIRSTACKSIZE");
--- 994,1000 ----
      if ((l = getshfunc("chpwd")) != &dummy_list) {
  	fflush(stdout);
  	fflush(stderr);
! 	doshfunc("chpwd", l, NULL, 0, 1);
      }
  
      dirstacksize = getiparam("DIRSTACKSIZE");
diff -c os/exec.c Src/exec.c
*** os/exec.c	Tue Dec  8 16:31:15 1998
--- Src/exec.c	Wed Dec  9 15:17:00 1998
***************
*** 2602,2608 ****
  	deletejob(jobtab + thisjob);
      }
  
!     doshfunc(shf->funcdef, cmd->args, shf->flags, 0);
  
      if (!list_pipe)
  	deletefilelist(last_file_list);
--- 2602,2608 ----
  	deletejob(jobtab + thisjob);
      }
  
!     doshfunc(shf->nam, shf->funcdef, cmd->args, shf->flags, 0);
  
      if (!list_pipe)
  	deletefilelist(last_file_list);
***************
*** 2650,2656 ****
  
  /**/
  void
! doshfunc(List list, LinkList doshargs, int flags, int noreturnval)
  /* If noreturnval is nonzero, then reset the current return *
   * value (lastval) to its value before the shell function   *
   * was executed.                                            */
--- 2650,2656 ----
  
  /**/
  void
! doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval)
  /* If noreturnval is nonzero, then reset the current return *
   * value (lastval) to its value before the shell function   *
   * was executed.                                            */
***************
*** 2661,2666 ****
--- 2661,2667 ----
      void *xexitfn, *newexitfn;
      char saveopts[OPT_SIZE];
      int obreaks = breaks;
+     FuncWrap wrap;
  
      HEAPALLOC {
  	pushheap();
***************
*** 2705,2710 ****
--- 2706,2715 ----
  		argzero = ztrdup(argzero);
  	    }
  	}
+ 	for (wrap = wrappers; wrap; wrap = wrap->next) {
+ 	    if (wrap->before)
+ 		wrap->before(wrap, name);
+ 	}
  	startparamscope();
  	ou = underscore;
  	underscore = ztrdup(underscore);
***************
*** 2712,2718 ****
  	zsfree(underscore);
  	underscore = ou;
  	endparamscope();
! 
  	if (retflag) {
  	    retflag = 0;
  	    breaks = obreaks;
--- 2717,2726 ----
  	zsfree(underscore);
  	underscore = ou;
  	endparamscope();
! 	for (wrap = wrappers; wrap; wrap = wrap->next) {
! 	    if (wrap->after)
! 		wrap->after(wrap, name, lastval);
! 	}
  	if (retflag) {
  	    retflag = 0;
  	    breaks = obreaks;
diff -c os/init.c Src/init.c
*** os/init.c	Wed Dec  9 15:36:12 1998
--- Src/init.c	Wed Dec  9 14:57:49 1998
***************
*** 117,123 ****
  		    if (he && he->text)
  			addlinknode(args, he->text);
  		} LASTALLOC;
! 		doshfunc(prelist, args, 0, 1);
  		freelinklist(args, (FreeFunc) NULL);
  		errflag = 0;
  	    }
--- 117,123 ----
  		    if (he && he->text)
  			addlinknode(args, he->text);
  		} LASTALLOC;
! 		doshfunc("preexec", prelist, args, 0, 1);
  		freelinklist(args, (FreeFunc) NULL);
  		errflag = 0;
  	    }
***************
*** 593,598 ****
--- 593,599 ----
      createparamtable();     /* create paramater hash table             */
  
      condtab = NULL;
+     wrappers = NULL;
  
  #ifdef TIOCGWINSZ
      adjustwinsize();
diff -c os/module.c Src/module.c
*** os/module.c	Wed Dec  9 15:36:13 1998
--- Src/module.c	Wed Dec  9 15:17:41 1998
***************
*** 316,321 ****
--- 316,366 ----
      return hadf ? hads : 1;
  }
  
+ /* The list of function wrappers defined. */
+ 
+ /**/
+ FuncWrap wrappers;
+ 
+ /* This adds a definition for a wrapper. Return value is one in case of *
+  * error and zero if all went fine. */
+ 
+ /**/
+ int
+ addwrapper(FuncWrap w)
+ {
+     if (w->flags & WRAPF_ADDED)
+ 	return 1;
+     w->next = wrappers;
+     wrappers = w;
+     w->flags |= WRAPF_ADDED;
+ 
+     return 0;
+ }
+ 
+ /* This removes the given wrapper definition from the list. Returned is *
+  * one in case of error and zero otherwise. */
+ 
+ /**/
+ int
+ deletewrapper(FuncWrap w)
+ {
+     FuncWrap p, q;
+ 
+     if (w->flags & WRAPF_ADDED) {
+ 	for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next);
+ 
+ 	if (p) {
+ 	    if (q)
+ 		q->next = p->next;
+ 	    else
+ 		wrappers = p->next;
+ 	    p->flags &= ~WRAPF_ADDED;
+ 
+ 	    return 0;
+ 	}
+     }
+     return 1;
+ }
  
  #ifdef HAVE_DLFCN_H
  # include <dlfcn.h>
diff -c os/signals.c Src/signals.c
*** os/signals.c	Tue Dec  8 16:31:19 1998
--- Src/signals.c	Wed Dec  9 14:39:54 1998
***************
*** 712,718 ****
  	    addlinknode(args, num);
  	} LASTALLOC;
  	trapreturn = -1;
! 	doshfunc(sigfn, args, 0, 1);
  	freelinklist(args, (FreeFunc) NULL);
  	zsfree(name);
      } else HEAPALLOC {
--- 712,718 ----
  	    addlinknode(args, num);
  	} LASTALLOC;
  	trapreturn = -1;
! 	doshfunc(name, sigfn, args, 0, 1);
  	freelinklist(args, (FreeFunc) NULL);
  	zsfree(name);
      } else HEAPALLOC {
diff -c os/utils.c Src/utils.c
*** os/utils.c	Wed Dec  9 15:36:14 1998
--- Src/utils.c	Wed Dec  9 14:39:41 1998
***************
*** 636,642 ****
      /* If a shell function named "precmd" exists, *
       * then execute it.                           */
      if ((list = getshfunc("precmd")) != &dummy_list)
! 	doshfunc(list, NULL, 0, 1);
      if (errflag)
  	return;
  
--- 636,642 ----
      /* If a shell function named "precmd" exists, *
       * then execute it.                           */
      if ((list = getshfunc("precmd")) != &dummy_list)
! 	doshfunc("precmd", list, NULL, 0, 1);
      if (errflag)
  	return;
  
***************
*** 645,651 ****
       * executed "periodic", then execute it now.                    */
      if (period && (time(NULL) > lastperiodic + period) &&
  	(list = getshfunc("periodic")) != &dummy_list) {
! 	doshfunc(list, NULL, 0, 1);
  	lastperiodic = time(NULL);
      }
      if (errflag)
--- 645,651 ----
       * executed "periodic", then execute it now.                    */
      if (period && (time(NULL) > lastperiodic + period) &&
  	(list = getshfunc("periodic")) != &dummy_list) {
! 	doshfunc("periodic", list, NULL, 0, 1);
  	lastperiodic = time(NULL);
      }
      if (errflag)
diff -c os/zsh.h Src/zsh.h
*** os/zsh.h	Wed Dec  9 15:36:14 1998
--- Src/zsh.h	Wed Dec  9 15:25:52 1998
***************
*** 233,238 ****
--- 233,239 ----
  typedef struct param     *Param;
  typedef struct cmdnam    *Cmdnam;
  typedef struct shfunc    *Shfunc;
+ typedef struct funcwrap  *FuncWrap;
  typedef struct builtin   *Builtin;
  typedef struct nameddir  *Nameddir;
  typedef struct module    *Module;
***************
*** 770,775 ****
--- 771,792 ----
      int flags;			/* various flags          */
      List funcdef;		/* function definition    */
  };
+ 
+ /* node in list of function call wrappers */
+ 
+ typedef void (*WrapBefore) _((FuncWrap, char *));
+ typedef void (*WrapAfter) _((FuncWrap, char *, int));
+ 
+ struct funcwrap {
+     FuncWrap next;
+     int flags;
+     WrapBefore before;
+     WrapAfter after;
+ };
+ 
+ #define WRAPF_ADDED 1
+ 
+ #define WRAPDEF(before, after) { NULL, 0, before, after }
  
  /* node in builtin command hash table (builtintab) */
  
diff -c os/Modules/example.c Src/Modules/example.c
*** os/Modules/example.c	Wed Dec  9 15:36:14 1998
--- Src/Modules/example.c	Wed Dec  9 15:13:58 1998
***************
*** 79,84 ****
--- 79,115 ----
      return !strcmp("example", dyncat(s1, s2));
  }
  
+ struct ogd {
+     struct ogd *next;
+     int val;
+ };
+ 
+ static struct ogd *ogds;
+ 
+ /**/
+ static void
+ wrap_before(FuncWrap w, char *name)
+ {
+     if (!strncmp(name, "example", 7)) {
+ 	struct ogd *n = (struct ogd *) halloc(sizeof(*n));
+ 
+ 	n->next = ogds;
+ 	ogds = n;
+ 	n->val = opts[GLOBDOTS];
+ 	opts[GLOBDOTS] = 1;
+     }
+ }
+ 
+ /**/
+ static void
+ wrap_after(FuncWrap w, char *name, int ret)
+ {
+     if (!strncmp(name, "example", 7)) {
+ 	opts[GLOBDOTS] = ogds->val;
+ 	ogds = ogds->next;
+     }
+ }
+ 
  /*
   * boot_example is executed when the module is loaded.
   */
***************
*** 92,103 ****
      CONDDEF("ex", CONDF_INFIX, 0, 0, cond_i_ex),
  };
  
  /**/
  int
  boot_example(Module m)
  {
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
! 	     addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)));
  }
  
  #ifdef MODULE
--- 123,140 ----
      CONDDEF("ex", CONDF_INFIX, 0, 0, cond_i_ex),
  };
  
+ static struct funcwrap wrapper[] = {
+     WRAPDEF(wrap_before, wrap_after),
+ };
+ 
  /**/
  int
  boot_example(Module m)
  {
+     ogds = NULL;
      return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
! 	     addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
! 	     !addwrapper(wrapper));
  }
  
  #ifdef MODULE
***************
*** 108,113 ****
--- 145,151 ----
  {
      deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
      deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
+     deletewrapper(wrapper);
      return 0;
  }
  #endif
diff -c os/Zle/zle_main.c Src/Zle/zle_main.c
*** os/Zle/zle_main.c	Tue Dec  8 16:31:51 1998
--- Src/Zle/zle_main.c	Wed Dec  9 14:41:29 1998
***************
*** 593,599 ****
  	} else {
  	  startparamscope();
  	  makezleparams();
! 	  doshfunc(l, NULL, 0, 1);
  	  endparamscope();
  	  lastcmd = 0;
  	}
--- 593,599 ----
  	} else {
  	  startparamscope();
  	  makezleparams();
! 	  doshfunc(w->u.fnnam, l, NULL, 0, 1);
  	  endparamscope();
  	  lastcmd = 0;
  	}
diff -c os/Zle/zle_tricky.c Src/Zle/zle_tricky.c
*** os/Zle/zle_tricky.c	Tue Dec  8 16:31:52 1998
--- Src/Zle/zle_tricky.c	Wed Dec  9 14:41:11 1998
***************
*** 4086,4092 ****
  	    /* This flag allows us to use read -l and -c. */
  	    incompctlfunc = 1;
  	    /* Call the function. */
! 	    doshfunc(list, args, 0, 1);
  	    incompctlfunc = 0;
  	    /* And get the result from the reply parameter. */
  	    if ((r = get_user_var("reply")))
--- 4086,4092 ----
  	    /* This flag allows us to use read -l and -c. */
  	    incompctlfunc = 1;
  	    /* Call the function. */
! 	    doshfunc(cc->func, list, args, 0, 1);
  	    incompctlfunc = 0;
  	    /* And get the result from the reply parameter. */
  	    if ((r = get_user_var("reply")))
***************
*** 4249,4255 ****
  
  	    /* No harm in allowing read -l and -c here, too */
  	    incompctlfunc = 1;
! 	    doshfunc(list, args, 0, 1);
  	    incompctlfunc = 0;
  	    uv = "reply";
  	}
--- 4249,4255 ----
  
  	    /* No harm in allowing read -l and -c here, too */
  	    incompctlfunc = 1;
! 	    doshfunc(cc->ylist, list, args, 0, 1);
  	    incompctlfunc = 0;
  	    uv = "reply";
  	}


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


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

end of thread, other threads:[~1998-12-16  9:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-12-15 12:03 wrapper functions in modules Sven Wischnowsky
1998-12-15 17:05 ` Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
1998-12-16  8:05 Sven Wischnowsky
1998-12-16  9:50 ` Bart Schaefer
1998-12-14 10:11 Sven Wischnowsky
1998-12-14 18:42 ` Bart Schaefer
1998-12-11 14:16 Sven Wischnowsky
1998-12-11 17:40 ` Bart Schaefer
1998-12-09 14:44 PATCH: " Sven Wischnowsky
1998-12-11 13:18 ` 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).