zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
@ 1999-10-25  9:53 Sven Wischnowsky
  1999-10-25 10:27 ` Zefram
  1999-10-25 22:15 ` Parameters, disable, modules (Re: Self-loading auto-functions) Bart Schaefer
  0 siblings, 2 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-10-25  9:53 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> One change that may be controversial is the output of "functions".  As was
> mentioned in the exchange I had with Zefram, it no longer puts "undefined"
> in front of an autoloaded function name.  In the course of changing that,
> I found that it might also output "traced" in that position, which for the
> purposes of making `eval $(functions)' work was equally annoying.  Further,
> it might be useful to differentiate an actual autoloaded function from one
> that merely calls "autoload -X".
> 
> So it now outputs comments like this:
> 
> foo() {
> 	# undefined
> 	# traced
> 	builtin autoload -X
> }
> 
> The comments use the user's $histchars[2], and you can tell a defined
> function from an undefined one because of course defined functions always
> have their comments stripped.  If anyone has a better idea for this, I'd
> be glad to see it changed.

I've fiddled with `parameter.c' a lot over the weekend, adding
parameters for the `compgen'-replacement. There I made `functions'
prepend a `<disabled>' prefix to report disabled shell functions (and
the same string in other parameters). I was thinking about using
comments, too, and I still think they are ok for functions, but in my
case I needed something that also worked for aliases -- and I hope
`<disabled>' is uncommen enough to be usable there.

> ...
> 
> There's one partial bug fix in the paramter.c diff below: Unloading the
> module would dump core when trying to unset the $dirstack parameter.  The
> remaining badness after the patch is that the dirstack gets erased as a
> side-effect of unloading the module, but at 2:15 AM I didn't feel like
> tackling that part.

There were some other problems. E.g. the strings stored in the pparam
struct should all be dupstring()ed (because the new pattern matching
code may try to store the trailing '\0' again). Also, they shouldn't
be tricat()ed, because that uses zalloc()ed memory which isn't freed
anywhere.

Since my code is currently far too different from anyone else's, I
don't send a patch for it now, it'll come together with the completion 
code stuff.

While I'm at it: does anyone have an idea how we can make the
parameter module report stuff about zle widgets and keymaps? I don't
see a solution (other than making parameter depend on zle which I
don't want to do). So in the first implementation at least, parameters 
for them will be in the zle module. Sigh.

Bye
 Sven


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


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

* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
  1999-10-25  9:53 PATCH: 3.1.6-bart-7: Self-loading auto-functions Sven Wischnowsky
@ 1999-10-25 10:27 ` Zefram
  1999-10-25 22:15 ` Parameters, disable, modules (Re: Self-loading auto-functions) Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Zefram @ 1999-10-25 10:27 UTC (permalink / raw)
  To: Sven Wischnowsky; +Cc: zsh-workers

Sven Wischnowsky wrote:
>While I'm at it: does anyone have an idea how we can make the
>parameter module report stuff about zle widgets and keymaps? I don't
>see a solution (other than making parameter depend on zle which I
>don't want to do). So in the first implementation at least, parameters 
>for them will be in the zle module. Sigh.

Logically, there should be a separate module for ZLE-related parameters,
dependent on the ZLE module.

-zefram


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

* Parameters, disable, modules (Re: Self-loading auto-functions)
  1999-10-25  9:53 PATCH: 3.1.6-bart-7: Self-loading auto-functions Sven Wischnowsky
  1999-10-25 10:27 ` Zefram
@ 1999-10-25 22:15 ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-10-25 22:15 UTC (permalink / raw)
  To: Sven Wischnowsky; +Cc: zsh-workers

On Mon, 25 Oct 1999, Sven Wischnowsky wrote:

> I've fiddled with `parameter.c' a lot over the weekend, adding
> parameters for the `compgen'-replacement. There I made `functions'
> prepend a `<disabled>' prefix to report disabled shell functions (and
> the same string in other parameters).

Waitaminute.  "functions" doesn't output ANYTHING for disabled functions;
it acts as if they don't exist, and you can't get to them via $functions.  
Did you really change that?

Same goes for aliases, etc.

Disable doesn't work very well on functions anyway; all you have to do
is redefine one to re-enable it:

zagzig[27] fnord() { echo foo }
zagzig[28] disable -f fnord
zagzig[29] fnord           
zsh: command not found: fnord
zagzig[30] fnord() { echo foo }
zagzig[31] fnord
foo
zagzig[32] 

Oh, by the way:  autoload +X will happily (re)load the definition for a
disabled function, causing it to become enabled again.  That was not an
intended side-effect, and I rather suspect that both the example above
and this +X side-effect are doing bad things to the hash table internals.

> While I'm at it: does anyone have an idea how we can make the
> parameter module report stuff about zle widgets and keymaps?

Introduce a registry:  A hash table mapping strings with a well-defined
syntax to function pointers with a corresponding call signature.  The zle
module registers its function pointers and the parameters module looks
them up, and vice-versa.  A fallback of some sort is used by each when it
doesn't find the other.

There are some obscure architectures where you can't cast a function
pointer to (void *) and back and so this wouldn't work, but they probably
can't deal with dynamic loading anyway.


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

* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
  1999-10-25 17:48 ` Oliver Kiddle
@ 1999-10-25 20:32   ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-10-25 20:32 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: zsh-workers

On Mon, 25 Oct 1999, Oliver Kiddle wrote:

> Bart Schaefer wrote:
> 
> > purposes of making `eval $(functions)' work was equally annoying.  Further,
> > it might be useful to differentiate an actual autoloaded function from one
> > that merely calls "autoload -X".
> 
> Also, does it differentiate at all between an autoloaded function that
> was autoloaded with -U at all.

Yes.  The example in my previous message was incomplete; the output for an
"unaliased" and execution-traced function actually looks like this:

foo() {
        # undefined
        # traced
        builtin autoload -XUt
}

> The autoload -X seems like it could be interesting from the perspective
> of using it intentionally in a function so that it does some extra stuff
> the first time it is executed.

Yes.  One interesting application is to have it fiddle around with the
positional parameters ("shift" or "set" or assign to argv) before loading
itself.  Another would be to have it fiddle with $fpath, particularly with
a local copy of $fpath!

Note that the old definition of the function does continue executing after
"autoload -X".  So you can have functions that do extra stuff AFTER the
first time they're executed, too.

> or to force it to reload every time it is run (though I don't think
> that can be done without infinite recursion or reloading after
> running).

"Force it to reload every time it is run" is just this:

    foo() {
	local +h PATH=$PATH
	path=($fpath $path)
	. foo "$@"
    }

(You have to use the scalar PATH so that you can assign to it and mark it
local at the same time.  Otherwise you end up with an empty path.  More on
this below.  Note that external commands run from foo get the original
$PATH in their environment, because locals are not exported!  This may
change for ksh emulation if someone gets around to it.)

> Actually, it'd be useful to have an option to autoload (-f for force
> maybe) which does the unfunction first.

Adding options to autoload is messy because "typeset -fu" is supposed to
be the same as "functions -u" is supposed to be the same as "autoload".
I chose -X because it's NOT a valid option to "typeset" (and in this case
I deliberately wanted to require that the command name be "autoload").

Anyway, I considered making "autoload +X" always reload the function, but
decided against it.  Perhaps a better approach would be an option to
"unfunction" to implicitly autoload the just-removed function ... but
as "unfunction" is "unhash -f" (and so is "unset -f"), that's nearly as
bad.

> Do these changes allow you to now declare local functions (which was
> what started this all off).

Yes, the changes to the parameter module make "typeset +h functions" work.

> From what I can gather, the +h option saves the value of the
> parameter, clears it and it is restored when returning.

"local +h" saves the current value and creates a new parameter with the
same special properties as the original.  Since the original is a view on
the functions hash table, so is the new parameter.  The new parameter is
not explicitly cleared; that happens to $path because of the way creating
a new path parameter is defined, but it's not true in general.

(Probably we should try harder to make +h act consistently across all the
special paramters.)

"local -h" on the other hand, creates a new parameter that has no special
properties at all.  So it will have an empty value.

The issue is the "restored when returning" part:  For any local parameter
(with or without -h/+h), the original special parameter is assigned-to
from the saved copy; which for $functions triggers the special assign-
through-to-the-hash-table property of the parameter, so all the function
definitions are recreated.

> Does this mean that after typeset +h functions, all existing functions
> are lost until you return?

No.

zagzig<1> zmodload parameter
zagzig<2> foo() { typeset +h functions; echo $#functions }
zagzig<3> foo
63
zagzig<4> 

> How efficiently would this work - saving and restoring all the functions
> might not be very efficient.

I wouldn't want to make frequent use of it in its present state.  There's
probably something that could be done to avoid recreating definitions that
haven't changed.

A better idea might be to write a localfunctions module.  Now that modules
can define wrappers to be called around every user-defined function scope,
it should be possible.  In fact, the only thing the module would need to
define is the wrapper.


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

* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
  1999-10-25  9:31 Bart Schaefer
  1999-10-25  9:46 ` Bart Schaefer
@ 1999-10-25 17:48 ` Oliver Kiddle
  1999-10-25 20:32   ` Bart Schaefer
  1 sibling, 1 reply; 8+ messages in thread
From: Oliver Kiddle @ 1999-10-25 17:48 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:

> purposes of making `eval $(functions)' work was equally annoying.  Further,
> it might be useful to differentiate an actual autoloaded function from one
> that merely calls "autoload -X".

Also, does it differentiate at all between an autoloaded function that
was autoloaded with -U at all. I only actually realised what the -U does
when checking the documentation now (suppressing alias expansion). It
might be clear if this would expand to 'builtin autoload -XU' (if it
doesn't already).

The autoload -X seems like it could be interesting from the perspective
of using it intentionally in a function so that it does some extra stuff
the first time it is executed. or to force it to reload every time it is
run (though I don't think that can be done without infinite recursion or
reloading after running). The latter could be especially useful when I'm
debugging completion functions - it can be quite tedious to constantly
have to do unfunction _foo; autoload _foo. Actually, it'd be useful to
have an option to autoload (-f for force maybe) which does the
unfunction first.

Do these changes allow you to now declare local functions (which was
what started this all off). From what I can make out, it should work
with typeset +h functions with the parameter module loaded. I can see
one possible problem in this approach. From what I can gather, the +h
option saves the value of the parameter, clears it and it is restored
when returning. Does this mean that after typeset +h functions, all
existing functions are lost until you return? 
How efficiently would this work - saving and restoring all the functions
might not be very efficient. Anyway, I certainly agree that local
functions would be useful to have. I'm often forgetting that nested
functions aren't local.

Oliver Kiddle


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

* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
@ 1999-10-25 10:40 Sven Wischnowsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-10-25 10:40 UTC (permalink / raw)
  To: zsh-workers


Zefram wrote:

> Sven Wischnowsky wrote:
> >While I'm at it: does anyone have an idea how we can make the
> >parameter module report stuff about zle widgets and keymaps? I don't
> >see a solution (other than making parameter depend on zle which I
> >don't want to do). So in the first implementation at least, parameters 
> >for them will be in the zle module. Sigh.
> 
> Logically, there should be a separate module for ZLE-related parameters,
> dependent on the ZLE module.

Yep, it's just that currently I'm planning only two of them (for
widgets and keymap-names). But then maybe someone would like to add a
real parameter-interface for setting keymaps. Hm, that may actually be 
useful...

Bye
 Sven


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


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

* Re: PATCH: 3.1.6-bart-7: Self-loading auto-functions
  1999-10-25  9:31 Bart Schaefer
@ 1999-10-25  9:46 ` Bart Schaefer
  1999-10-25 17:48 ` Oliver Kiddle
  1 sibling, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-10-25  9:46 UTC (permalink / raw)
  To: zsh-workers

On Oct 25,  9:31am, Bart Schaefer wrote:
} Subject: PATCH: 3.1.6-bart-7: Self-loading auto-functions
}
} at 2:15 AM I didn't feel like tackling that part.

Apparently I shouldn't have tackled doc, either.  The following should
back out an incorrect hunk of the previous doc patch.

Index: Doc/Zsh/builtins.yo
@@ -1062,8 +1062,8 @@
 )
 item(tt(-f))(
 The names refer to functions rather than parameters.  No assignments
-can be made, and the only other valid flags are tt(-t), tt(-u), tt(-U),
-tt(-X) and tt(+X).  The flag tt(-t) turns on execution tracing for this
+can be made, and the only other valid flags are tt(-t), tt(-u) and
+tt(-U).  The flag tt(-t) turns on execution tracing for this
 function.  The tt(-u) and tt(-U) flags cause the function to be
 marked for autoloading; tt(-U) also causes alias expansion to be
 suppressed when the function is loaded.  The tt(fpath) parameter

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


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

* PATCH: 3.1.6-bart-7: Self-loading auto-functions
@ 1999-10-25  9:31 Bart Schaefer
  1999-10-25  9:46 ` Bart Schaefer
  1999-10-25 17:48 ` Oliver Kiddle
  0 siblings, 2 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-10-25  9:31 UTC (permalink / raw)
  To: zsh-workers

The first hunk of added text in the builtins.yo diff explains this pretty
completely.  There may be a more elegant way to implement it than the way
I did, but it was pretty straightforward this way.

One change that may be controversial is the output of "functions".  As was
mentioned in the exchange I had with Zefram, it no longer puts "undefined"
in front of an autoloaded function name.  In the course of changing that,
I found that it might also output "traced" in that position, which for the
purposes of making `eval $(functions)' work was equally annoying.  Further,
it might be useful to differentiate an actual autoloaded function from one
that merely calls "autoload -X".

So it now outputs comments like this:

foo() {
	# undefined
	# traced
	builtin autoload -X
}

The comments use the user's $histchars[2], and you can tell a defined
function from an undefined one because of course defined functions always
have their comments stripped.  If anyone has a better idea for this, I'd
be glad to see it changed.

Note that saving/restoring the value of the $functions special parameter
(from `zmodload parameter') has the side-effect of converting undefined
functions into functions defined to call autoload -X.  Oh, well.

There's one partial bug fix in the paramter.c diff below: Unloading the
module would dump core when trying to unset the $dirstack parameter.  The
remaining badness after the patch is that the dirstack gets erased as a
side-effect of unloading the module, but at 2:15 AM I didn't feel like
tackling that part.

Index: Doc/Zsh/builtins.yo
===================================================================
@@ -71,7 +71,24 @@
 findex(autoload)
 cindex(functions, autoloading)
 cindex(autoloading functions)
-alias(autoload)(functions -u)
+item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(UXmt) ] [ var(name) ... ])(
+Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X).
+
+The flag tt(-X) may be used only inside a shell function, and may not be
+followed by a var(name).  It causes the calling function to be marked for
+autoloading and then immediately loaded and executed, with the current
+array of positional parameters as arguments.  This replaces the previous
+definition of the function.  If no function definition is found, an error
+is printed and the function remains undefined and marked for autoloading.
+
+The flag tt(+X) attempts to load each var(name) as an autoloaded function,
+but does em(not) execute it.  The exit status is zero (success) if the
+function was not previously defined em(and) a definition for it was found.
+This does em(not) replace any existing definition of the function.  The
+exit status is nonzero (failure) if the function was already defined or
+when no definition was found.  In the latter case the function remains
+undefined and marked for autoloading.
+)
 findex(bg)
 cindex(jobs, backgrounding)
 xitem(tt(bg) [ var(job) ... ])
@@ -353,7 +370,7 @@
 point numbers are not permitted.
 )
 findex(functions)
-item(tt(functions) [ {tt(PLUS())|tt(-)}tt(tum) ] [ var(name) ... ])(
+item(tt(functions) [ {tt(PLUS())|tt(-)}tt(UXmtu) ] [ var(name) ... ])(
 Equivalent to tt(typeset -f).
 )
 findex(getln)
@@ -1028,6 +1045,7 @@
 For arrays (but not for associative arrays), keep only the first
 occurrence of each duplicated value.  This may also be set for
 colon-separated special parameters like tt(PATH) or tt(FIGNORE), etc.
+This flag has a different meaning when used with tt(-f); see below.
 )
 item(tt(-Z))(
 Right justify and fill with leading zeros if the first non-blank
@@ -1044,8 +1062,8 @@
 )
 item(tt(-f))(
 The names refer to functions rather than parameters.  No assignments
-can be made, and the only other valid flags are tt(-t), tt(-u) and
-tt(-U).  The flag tt(-t) turns on execution tracing for this
+can be made, and the only other valid flags are tt(-t), tt(-u), tt(-U),
+tt(-X) and tt(+X).  The flag tt(-t) turns on execution tracing for this
 function.  The tt(-u) and tt(-U) flags cause the function to be
 marked for autoloading; tt(-U) also causes alias expansion to be
 suppressed when the function is loaded.  The tt(fpath) parameter
@@ -1096,10 +1114,12 @@
 )
 item(tt(-t))(
 Tags the named parameters.  Tags have no special meaning to the shell.
+This flag has a different meaning when used with tt(-f); see above.
 )
 item(tt(-u))(
 Convert the result to upper case whenever the parameter is expanded.
 The value is em(not) converted when assigned.
+This flag has a different meaning when used with tt(-f); see above.
 )
 item(tt(-x))(
 Mark for automatic export to the environment of subsequently
Index: Doc/Zsh/func.yo
===================================================================
@@ -74,6 +74,29 @@
 the initialization message on the first call, and the other message on the
 second and subsequent calls.
 
+It is also possible to create a function that is not marked autoloaded,
+yet loads its own definition by searching tt(fpath): `tt(autoload -X)',
+when called from within a shell function tt(myfunc), is equivalent to:
+
+example(unfunction myfunc
+autoload myfunc
+myfunc "$@")
+
+In fact, the tt(functions) command outputs `tt(builtin autoload -X)' as
+the body of an autoloaded function.  A true autoloaded function can be
+identifed by the presence of the comment `tt(# undefined)' in the body,
+because all comments are discarded from defined functions.  This is done
+so that
+
+example(eval "$(functions)")
+
+produces a reasonable result.
+
+To load the definition of an autoloaded function tt(myfunc) without
+executing tt(myfunc), use:
+
+example(autoload +X myfunc)
+
 sect(Special Functions)
 The following functions, if defined, have special meaning to
 the shell:
Index: Src/builtin.c
===================================================================
@@ -43,7 +43,7 @@
     BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
     BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
     BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmr", NULL),
-    BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tU", "u"),
+    BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tUX", "u"),
     BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
     BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
     BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -1998,6 +1998,29 @@
     return returnval;
 }
 
+/* Helper for bin_functions() when run as "autoload -X" */
+
+static int
+eval_autoload(Shfunc shf, char *name, char *ops, int func)
+{
+    if (!(shf->flags & PM_UNDEFINED))
+	return 1;
+
+    if (shf->funcdef)
+	freestruct(shf->funcdef);
+
+    if (ops['X'] == 1) {
+	char *fargv[3];
+	fargv[0] = name;
+	fargv[1] = "\"$@\"";
+	fargv[2] = 0;
+	shf->funcdef = mkautofn(shf);
+	return bin_eval(name, fargv, ops, func);
+    }
+
+    return loadautofn(shf);
+}
+
 /* Display or change the attributes of shell functions.   *
  * If called as autoload, it will define a new autoloaded *
  * (undefined) shell function.                            */
@@ -2012,10 +2035,10 @@
     int on = 0, off = 0, pflags = 0;
 
     /* Do we have any flags defined? */
-    if (ops['u'] == 1)
-	on |= PM_UNDEFINED;
-    else if (ops['u'] == 2)
+    if (ops['u'] == 2)
 	off |= PM_UNDEFINED;
+    else if (ops['u'] == 1 || ops['X'])
+	on |= PM_UNDEFINED;
     if (ops['U'] == 1)
 	on |= PM_UNALIASED|PM_UNDEFINED;
     else if (ops['U'] == 2)
@@ -2025,7 +2048,8 @@
     else if (ops['t'] == 2)
 	off |= PM_TAGGED;
 
-    if (off & PM_UNDEFINED) {
+    if ((off & PM_UNDEFINED) ||
+	(ops['X'] == 1 && (ops['m'] || *argv || !scriptname))) {
 	zwarnnam(name, "invalid option(s)", NULL, 0);
 	return 1;
     }
@@ -2037,10 +2061,22 @@
      * are given, we will print only functions containing these  *
      * flags, else we'll print them all.                         */
     if (!*argv) {
-	if (ops['U'] && !ops['u'])
-	    on &= ~PM_UNDEFINED;
-	scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode,
-		      pflags);
+	if (ops['X'] == 1) {
+	    if ((shf = (Shfunc) shfunctab->getnode(shfunctab, scriptname))) {
+		DPUTS(!shf->funcdef,
+		      "BUG: Calling autoload from empty function");
+	    } else {
+		shf = (Shfunc) zcalloc(sizeof *shf);
+		shfunctab->addnode(shfunctab, ztrdup(scriptname), shf);
+	    }
+	    shf->flags = on;
+	    return eval_autoload(shf, scriptname, ops, func);
+	} else {
+	    if (ops['U'] && !ops['u'])
+		on &= ~PM_UNDEFINED;
+	    scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode,
+			  pflags);
+	}
 	return 0;
     }
 
@@ -2061,8 +2097,14 @@
 			for (shf = (Shfunc) shfunctab->nodes[i]; shf;
 			     shf = (Shfunc) shf->next)
 			    if (pattry(pprog, shf->nam) &&
-				!(shf->flags & DISABLED))
-				shf->flags = (shf->flags | on) & (~off);
+				!(shf->flags & DISABLED)) {
+				shf->flags = (shf->flags |
+					      (on & ~PM_UNDEFINED)) & ~off;
+				if (ops['X'] &&
+				    eval_autoload(shf, shf->nam, ops, func)) {
+				    returnval = 1;
+				}
+			    }
 		    }
 		}
 	    } else {
@@ -2078,10 +2120,12 @@
     for (; *argv; argv++) {
 	if ((shf = (Shfunc) shfunctab->getnode(shfunctab, *argv))) {
 	    /* if any flag was given */
-	    if (on|off)
+	    if (on|off) {
 		/* turn on/off the given flags */
 		shf->flags = (shf->flags | (on & ~PM_UNDEFINED)) & ~off;
-	    else
+		if (ops['X'] && eval_autoload(shf, shf->nam, ops, func))
+		    returnval = 1;
+	    } else
 		/* no flags, so just print */
 		shfunctab->printnode((HashNode) shf, pflags);
 	} else if (on & PM_UNDEFINED) {
@@ -2091,6 +2135,8 @@
 	    shf->flags = on;
 	    shf->funcdef = mkautofn(shf);
 	    shfunctab->addnode(shfunctab, ztrdup(*argv), shf);
+	    if (ops['X'] && eval_autoload(shf, shf->nam, ops, func))
+		returnval = 1;
 	} else
 	    returnval = 1;
     }
Index: Src/exec.c
===================================================================
@@ -2911,11 +2911,11 @@
     l = getfpfunc(shf->nam);
     noaliases = noalias;
 
-    if(l == &dummy_list) {
+    if (l == &dummy_list) {
 	zerr("%s: function definition file not found", shf->nam, 0);
 	return 1;
     }
-    if(isset(KSHAUTOLOAD)) {
+    if (isset(KSHAUTOLOAD)) {
 	VARARR(char, n, strlen(shf->nam) + 1);
 	strcpy(n, shf->nam);
 	execlist(l, 1, 0);
@@ -2933,6 +2933,31 @@
     }
     execlist(shf->funcdef, 1, 0);
     return lastval;
+}
+
+/**/
+int
+loadautofn(Shfunc shf)
+{
+    /* Copied from execautofn() -- should consolidate someday */
+
+    int noalias = noaliases;
+    List l;
+
+    noaliases = (shf->flags & PM_UNALIASED);
+    l = getfpfunc(shf->nam);
+    noaliases = noalias;
+
+    if (l == &dummy_list) {
+	zerr("%s: function definition file not found", shf->nam, 0);
+	return 1;
+    }
+    PERMALLOC {
+	shf->funcdef = dupstruct(stripkshdef(l, shf->nam));
+    } LASTALLOC;
+    shf->flags &= ~PM_UNDEFINED;
+
+    return 0;
 }
 
 /* execute a shell function */
Index: Src/hashtable.c
===================================================================
@@ -872,21 +872,29 @@
     }
  
     if (f->flags & PM_UNDEFINED)
-	printf("undefined ");
-    if (f->flags & PM_TAGGED)
-	printf("traced ");
-    if ((f->flags & PM_UNDEFINED) || !f->funcdef) {
-	nicezputs(f->nam, stdout);
-	printf(" () { }\n");
-	return;
+	t = tricat("builtin autoload -X",
+		   ((f->flags & PM_UNALIASED)? "U" : ""),
+		   ((f->flags & PM_TAGGED)? "t" : ""));
+    else {
+	if (!f->funcdef)
+	    t = 0;
+	else
+	    t = getpermtext((void *) f->funcdef);
     }
- 
-    t = getpermtext((void *) f->funcdef);
+
     quotedzputs(f->nam, stdout);
-    printf(" () {\n\t");
-    zputs(t, stdout);
-    printf("\n}\n");
-    zsfree(t);
+    if (t) {
+	printf(" () {\n\t");
+	if (f->flags & PM_UNDEFINED)
+	    printf("%c undefined\n\t", hashchar);
+	if (f->flags & PM_TAGGED)
+	    printf("%c traced\n\t", hashchar);
+	zputs(t, stdout);
+	printf("\n}\n");
+	zsfree(t);
+    } else {
+	printf(" () { }\n");
+    }
 }
 
 /**************************************/
Index: Src/Modules/parameter.c
===================================================================
@@ -424,7 +424,9 @@
 
 	if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) {
 	    if (shf->flags & PM_UNDEFINED)
-		pm->u.str = "undefined";
+		pm->u.str = tricat("builtin autoload -X",
+				   ((shf->flags & PM_UNALIASED)? "U" : ""),
+				   ((shf->flags & PM_TAGGED)? "t" : ""));
 	    else {
 		char *t = getpermtext((void *) dupstruct((void *)
 							 shf->funcdef)), *h;
@@ -467,9 +469,12 @@
 	    if (!(hn->flags & DISABLED)) {
 		pm.nam = hn->nam;
 		if (func != scancountparams) {
-		    if (((Shfunc) hn)->flags & PM_UNDEFINED)
-			pm.u.str = "undefined";
-		    else {
+		    if (((Shfunc) hn)->flags & PM_UNDEFINED) {
+			Shfunc shf = (Shfunc) hn;
+			pm.u.str = tricat("builtin autoload -X",
+					  ((shf->flags & PM_UNALIASED)? "U" : ""),
+					  ((shf->flags & PM_TAGGED)? "t" : ""));
+		    } else {
 			char *t = getpermtext((void *)
 					      dupstruct((void *) ((Shfunc) hn)->funcdef));
 
@@ -779,7 +784,7 @@
     PERMALLOC {
 	freelinklist(dirstack, freestr);
 	dirstack = newlinklist();
-	while (*x)
+	while (x && *x)
 	    addlinknode(dirstack, ztrdup(*x++));
     } LASTALLOC;
 }

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


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

end of thread, other threads:[~1999-10-25 22:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-10-25  9:53 PATCH: 3.1.6-bart-7: Self-loading auto-functions Sven Wischnowsky
1999-10-25 10:27 ` Zefram
1999-10-25 22:15 ` Parameters, disable, modules (Re: Self-loading auto-functions) Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
1999-10-25 10:40 PATCH: 3.1.6-bart-7: Self-loading auto-functions Sven Wischnowsky
1999-10-25  9:31 Bart Schaefer
1999-10-25  9:46 ` Bart Schaefer
1999-10-25 17:48 ` Oliver Kiddle
1999-10-25 20:32   ` 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).