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

Re: Request: a way to get the subshell level nesting



On Fri, 5 Sep 2008 10:11:45 -0400"Rocky Bernstein" <rocky.bernstein@xxxxxxxxx> 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@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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