* Request: a way to get the subshell level nesting @ 2008-09-05 14:11 Rocky Bernstein 2008-09-05 19:49 ` Phil Pennock 2008-09-05 20:45 ` Peter Stephenson 0 siblings, 2 replies; 6+ messages in thread From: Rocky Bernstein @ 2008-09-05 14:11 UTC (permalink / raw) To: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 962 bytes --] It would be great if there were a way to get the subshell level nesting. ksh uses .sh.level and bash BASH_SUBSHELL. A debugger uses this in two ways. First to indicate the level of subshell nesting on prompts, so that as you are following along you won't be surprised when a variable which had a value get unset or the value restored to its previous value. And second to maintain global state. The general pattern here is debug_hook: if ((subshell_level < old_subshell_level)) ; then eval journal file fi save old subshell level work, work, ... something that should set or change global state: save global variable and value in journal file, e.g. cmd='x=5'; eval $cmd; echo "$cmd" >> journal_file It also occurs to me that if there were a variable that automatically got *unset* and stayed that way until explicitly set, then that could be used to sumulate such a variable. [-- Attachment #2: Type: text/html, Size: 1515 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Request: a way to get the subshell level nesting 2008-09-05 14:11 Request: a way to get the subshell level nesting Rocky Bernstein @ 2008-09-05 19:49 ` Phil Pennock 2008-09-05 19:55 ` Rocky Bernstein 2008-09-05 20:45 ` Peter Stephenson 1 sibling, 1 reply; 6+ messages in thread From: Phil Pennock @ 2008-09-05 19:49 UTC (permalink / raw) To: Rocky Bernstein; +Cc: Zsh hackers list On 2008-09-05 at 10:11 -0400, Rocky Bernstein wrote: > It would be great if there were a way to get the subshell level nesting. ksh > uses .sh.level and bash BASH_SUBSHELL. I don't think zsh has that directly as a variable, but it does have %_ for prompt substitution, producing on stdout a list of words identifying the nested parser states. It's output text, not a data structure internal to the shell (so not an array). zsh% for i in 1; do if [[ x == x ]]; then print -P %_ ; fi; done for then zsh% Of course, capturing that in $(...) will add a cmdsubst to the end. -Phil ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Request: a way to get the subshell level nesting 2008-09-05 19:49 ` Phil Pennock @ 2008-09-05 19:55 ` Rocky Bernstein 0 siblings, 0 replies; 6+ messages in thread From: Rocky Bernstein @ 2008-09-05 19:55 UTC (permalink / raw) To: Rocky Bernstein, Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 1243 bytes --] Thanks for the information. Alas, I don't believe this is does what is needed. Here is output from no subshell nesting, one subshell, and then two: $ for i in 1; do if [[ x == x ]]; then print -P %_ ; fi; done for then $ (for i in 1; do if [[ x == x ]]; then print -P %_ ; fi; done) for then $ ( (for i in 1; do if [[ x == x ]]; then print -P %_ ; fi; done) ) for then In all cases I get the same output with no indication in the last two cases that they are inside one or two subshells. On Fri, Sep 5, 2008 at 3:49 PM, Phil Pennock < zsh-workers+phil.pennock@spodhuis.org<zsh-workers%2Bphil.pennock@spodhuis.org> > wrote: > On 2008-09-05 at 10:11 -0400, Rocky Bernstein wrote: > > It would be great if there were a way to get the subshell level nesting. > ksh > > uses .sh.level and bash BASH_SUBSHELL. > > I don't think zsh has that directly as a variable, but it does have %_ > for prompt substitution, producing on stdout a list of words identifying > the nested parser states. It's output text, not a data structure > internal to the shell (so not an array). > > zsh% for i in 1; do if [[ x == x ]]; then print -P %_ ; fi; done > for then > zsh% > > Of course, capturing that in $(...) will add a cmdsubst to the end. > > -Phil > [-- Attachment #2: Type: text/html, Size: 1658 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Request: a way to get the subshell level nesting 2008-09-05 14:11 Request: a way to get the subshell level nesting Rocky Bernstein 2008-09-05 19:49 ` Phil Pennock @ 2008-09-05 20:45 ` Peter Stephenson 2008-09-05 21:36 ` Rocky Bernstein 1 sibling, 1 reply; 6+ messages in thread From: Peter Stephenson @ 2008-09-05 20:45 UTC (permalink / raw) To: Zsh hackers list On Fri, 5 Sep 2008 10:11:45 -0400"Rocky Bernstein" <rocky.bernstein@gmail.com> wrote: > It would be great if there were a way to get the subshell level nesting. ksh > uses .sh.level and bash BASH_SUBSHELL. This is easy; the only decision is whether the value should reflect a logical or an actual subshell. I think the former, since the only difference is to optimise out an exec when the shell is going to exit anyway, and I think from the user's point of view that should be treated identically to a real exec. To explain: in, for example, ( (print $ZSH_SUBSHELL) ) the shell forks, looks at what it's got to do, realises it's the last command to execute in the current subshell, and so doesn't bother to fork again. If the first subshell were not about to exit it would fork, so in ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL ) it does fork again for the inner subshell. I've made these print "2", and "2" and "1", respectively, which is what you'd naively expect. Also, eval 'print $ZSH_SUBSHELL' & prints 1. It's explicitly forked from the main shell, so I think that's reasonable. Bash works this way, too. Index: Doc/Zsh/params.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/params.yo,v retrieving revision 1.48 diff -u -r1.48 params.yo --- Doc/Zsh/params.yo 31 Jul 2008 13:53:28 -0000 1.48 +++ Doc/Zsh/params.yo 5 Sep 2008 20:40:41 -0000 @@ -731,6 +731,13 @@ See ifzman(the section `The zsh/sched Module' in zmanref(zshmodules))\ ifnzman(noderef(The zsh/sched Module)). ) +vindex(ZSH_SUBSHELL <S>) +item(tt(ZSH_SUBSHELL))( +Readonly integer. Initially zero, incremented each time the shell forks +to create a subshell for executing code. Hence `tt((print $ZSH_SUBSHELL))' +and `tt(print $(print $ZSH_SUBSHELL))' output 1, while +`tt(( (print $ZSH_SUBSHELL) ))' outputs 2. +) vindex(ZSH_VERSION) item(tt(ZSH_VERSION))( The version number of this zsh. Index: Src/exec.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/exec.c,v retrieving revision 1.147 diff -u -r1.147 exec.c --- Src/exec.c 5 Sep 2008 09:05:23 -0000 1.147 +++ Src/exec.c 5 Sep 2008 20:40:43 -0000 @@ -910,6 +910,13 @@ } if (!(flags & ESUB_FAKE)) subsh = 1; + /* + * Increment the visible parameter ZSH_SUBSHELL even if this + * is a fake subshell because we are exec'ing at the end. + * Logically this should be equivalent to a real subshell so + * we don't hang out the dirty washing. + */ + zsh_subshell++; if ((flags & ESUB_REVERTPGRP) && getpid() == mypgrp) release_pgrp(); if (SHTTY != -1) { Index: Src/params.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/params.c,v retrieving revision 1.144 diff -u -r1.144 params.c --- Src/params.c 31 Jul 2008 13:53:28 -0000 1.144 +++ Src/params.c 5 Sep 2008 20:40:44 -0000 @@ -85,7 +85,8 @@ lastpid, /* $! */ columns, /* $COLUMNS */ lines, /* $LINES */ - ppid; /* $PPID */ + ppid, /* $PPID */ + zsh_subshell; /* $ZSH_SUBSHELL */ /**/ zlong lineno, /* $LINENO */ zoptind, /* $OPTIND */ @@ -291,6 +292,7 @@ IPDEF4("HISTCMD", &curhist), IPDEF4("LINENO", &lineno), IPDEF4("PPID", &ppid), +IPDEF4("ZSH_SUBSHELL", &zsh_subshell), #define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(varinteger_gsu),10,0,NULL,NULL,NULL,0} IPDEF5("COLUMNS", &columns, zlevar_gsu), Index: Test/D04parameter.ztst =================================================================== RCS file: /cvsroot/zsh/zsh/Test/D04parameter.ztst,v retrieving revision 1.33 diff -u -r1.33 D04parameter.ztst --- Test/D04parameter.ztst 25 Mar 2008 17:47:11 -0000 1.33 +++ Test/D04parameter.ztst 5 Sep 2008 20:40:44 -0000 @@ -1047,3 +1047,18 @@ >and !that! >of *this* >or (the|other) + + print $ZSH_SUBSHELL + (print $ZSH_SUBSHELL) + ( (print $ZSH_SUBSHELL) ) + ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL ) + print $(print $ZSH_SUBSHELL) + cat =(print $ZSH_SUBSHELL) +0:ZSH_SUBSHELL +>0 +>1 +>2 +>2 +>1 +>1 +>1 -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Request: a way to get the subshell level nesting 2008-09-05 20:45 ` Peter Stephenson @ 2008-09-05 21:36 ` Rocky Bernstein 2008-09-06 21:23 ` Peter Stephenson 0 siblings, 1 reply; 6+ messages in thread From: Rocky Bernstein @ 2008-09-05 21:36 UTC (permalink / raw) To: Zsh hackers list [-- Attachment #1: Type: text/plain, Size: 2599 bytes --] Again, many thanks. I'll probably start putting this in prompt information over the weekend. And again, alas it removes my excuse to blame zsh for why my code is so broken in this regard ;-) Comments in line. On Fri, Sep 5, 2008 at 4:45 PM, Peter Stephenson < p.w.stephenson@ntlworld.com> wrote: > On Fri, 5 Sep 2008 10:11:45 -0400"Rocky Bernstein" < > rocky.bernstein@gmail.com> wrote: > > It would be great if there were a way to get the subshell level nesting. > ksh > > uses .sh.level and bash BASH_SUBSHELL. > > This is easy; (Thought it would; but it's good to get that confirmed.) > the only decision is whether the value should reflect a > logical or an actual subshell. I think the former, since the only > difference is to optimise out an exec when the shell is going to exit > anyway, and I think from the user's point of view that should be treated > identically to a real exec. I described my motivation. First as status information, second to let folks realize that values may have gotten discarded and third to make facilitate picking up state information to be passed back (without doing unnecessary work in the majority of the cases where there is no subshell change.) I think some in some of the optimization cases it doesn't matter all that much, so I leave it to your judgment. However, I find it interesting because I had a discussion about something very similar with David Korn regarding SHLVL which should be added soon to ksh. He had the same question because in some cases he optimizes a recursive shell out if the say the shell call is in fact the last line of the script. What was done there was to set SHLVL to be exactly what goes on, not trying to hide the optimization done. And in that case there is a reason why this is desirable. In a program such as bashdb when a "quit" is done we may really need to quit several levels of shells that may have gotten invoked in between. Suppose you were writing a debugger for GNU Make. You'd have the same issue. Or any program that might call itself recursively and you don't have control in between of how many *other* recursive shell invocations might have gone on. So here we need the actual number counting whatever optimization was done, not the virtual number of shells. And here I don't think it too bad to have the user aware that an optimization was done. When one debugs optimized C code in gcc there are corresponding issues that any competent programmer just needs to be aware of. Like in-lined functions or statements which appear out of order because that's the way assembly code was reorganized. [-- Attachment #2: Type: text/html, Size: 3343 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Request: a way to get the subshell level nesting 2008-09-05 21:36 ` Rocky Bernstein @ 2008-09-06 21:23 ` Peter Stephenson 0 siblings, 0 replies; 6+ messages in thread From: Peter Stephenson @ 2008-09-06 21:23 UTC (permalink / raw) To: Zsh hackers list On Fri, 5 Sep 2008 17:36:37 -0400 "Rocky Bernstein" <rocky.bernstein@gmail.com> wrote: > In a program such > as bashdb when a "quit" is done we may really need to quit several levels of > shells that may have gotten invoked in between. > Suppose you were writing a debugger for GNU Make. You'd have the same issue. > Or any program > that might call itself recursively and you don't have control in between of > how many *other* recursive shell invocations might have gone on. > > So here we need the actual number counting whatever optimization was done, > not the virtual number of shells. And here I don't think it too bad to have > the user aware that an optimization was done. When one debugs optimized C > code in gcc there are corresponding issues that any competent programmer > just needs to be aware of. Like in-lined functions or statements which > appear out of order because that's the way assembly code was reorganized. We'll have to see how this works out; I'm hoping that in fact any time the debugger is hanging around the subshell won't be optimized out and the question doesn't arise. However, if you encounter oddities we can certainly look at this again. The trade off between expectation and reality can be a bit elastic down here. pws ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-09-06 21:24 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-09-05 14:11 Request: a way to get the subshell level nesting Rocky Bernstein 2008-09-05 19:49 ` Phil Pennock 2008-09-05 19:55 ` Rocky Bernstein 2008-09-05 20:45 ` Peter Stephenson 2008-09-05 21:36 ` Rocky Bernstein 2008-09-06 21:23 ` 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).