This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: 2 vms specific build files in perl @ 27383
[perl5.git] / deb.c
diff --git a/deb.c b/deb.c
index 0af6110..3907201 100644 (file)
--- a/deb.c
+++ b/deb.c
-/* $RCSfile: op.c,v $$Revision: 4.1 $$Date: 92/08/07 17:19:16 $
+/*    deb.c
  *
- *    Copyright (c) 1991, Larry Wall
+ *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
  *
- * $Log:       op.c,v $
- * Revision 4.1  92/08/07  17:19:16  lwall
- * Stage 6 Snapshot
- * 
- * Revision 4.0.1.5  92/06/08  12:00:39  lwall
- * patch20: the switch optimizer didn't do anything in subroutines
- * patch20: removed implicit int declarations on funcions
- * 
- * Revision 4.0.1.4  91/11/11  16:29:33  lwall
- * patch19: do {$foo ne "bar";} returned wrong value
- * patch19: some earlier patches weren't propagated to alternate 286 code
- * 
- * Revision 4.0.1.3  91/11/05  16:07:43  lwall
- * patch11: random cleanup
- * patch11: "foo\0" eq "foo" was sometimes optimized to true
- * patch11: foreach on null list could spring memory leak
- * 
- * Revision 4.0.1.2  91/06/07  10:26:45  lwall
- * patch4: new copyright notice
- * patch4: made some allowances for "semi-standard" C
- * 
- * Revision 4.0.1.1  91/04/11  17:36:16  lwall
- * patch1: you may now use "die" and "caller" in a signal handler
- * 
- * Revision 4.0  91/03/20  01:04:18  lwall
- * 4.0 baseline.
- * 
  */
 
-#include "EXTERN.h"
-#include "perl.h"
+/*
+ * "Didst thou think that the eyes of the White Tower were blind?  Nay, I
+ * have seen more than thou knowest, Gray Fool."  --Denethor
+ */
 
-#ifdef I_VARARGS
-#  include <varargs.h>
-#endif
+/*
+ * This file contains various utilities for producing debugging output
+ * (mainly related to displaying the stack)
+ */
 
-void deb_growlevel();
+#include "EXTERN.h"
+#define PERL_IN_DEB_C
+#include "perl.h"
 
-#  ifndef I_VARARGS
-/*VARARGS1*/
-void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
-char *pat;
+#if defined(PERL_IMPLICIT_CONTEXT)
+void
+Perl_deb_nocontext(const char *pat, ...)
 {
-    register I32 i;
-
-    fprintf(stderr,"%-4ld",(long)curop->cop_line);
-    for (i=0; i<dlevel; i++)
-       fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
-    fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
-}
-#  else
-/*VARARGS1*/
-#ifdef __STDC__
-void deb(char *pat,...)
+#ifdef DEBUGGING
+    dTHX;
+    va_list args;
+    va_start(args, pat);
+    vdeb(pat, &args);
+    va_end(args);
 #else
-void deb(va_alist)
-va_dcl
+    PERL_UNUSED_ARG(pat);
+#endif /* DEBUGGING */
+}
 #endif
+
+void
+Perl_deb(pTHX_ const char *pat, ...)
 {
+#ifdef DEBUGGING
     va_list args;
-    char *pat;
-    register I32 i;
-
-    va_start(args);
-    fprintf(stderr,"%-4ld",(long)curcop->cop_line);
-    for (i=0; i<dlevel; i++)
-       fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
-
-    pat = va_arg(args, char *);
-    (void) vfprintf(stderr,pat,args);
-    va_end( args );
+    va_start(args, pat);
+    vdeb(pat, &args);
+    va_end(args);
+#else
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(pat);
+#endif /* DEBUGGING */
 }
-#  endif
 
 void
-deb_growlevel()
+Perl_vdeb(pTHX_ const char *pat, va_list *args)
 {
-    dlmax += 128;
-    Renew(debname, dlmax, char);
-    Renew(debdelim, dlmax, char);
+#ifdef DEBUGGING
+    dVAR;
+    const char* const file = OutCopFILE(PL_curcop);
+
+    PerlIO_printf(Perl_debug_log, "(%s:%ld)\t", (file ? file : "<free>"),
+                 (long)CopLINE(PL_curcop));
+    (void) PerlIO_vprintf(Perl_debug_log, pat, *args);
+#else
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(pat);
+    PERL_UNUSED_ARG(args);
+#endif /* DEBUGGING */
 }
 
 I32
-debstackptrs()
+Perl_debstackptrs(pTHX)
 {
-    fprintf(stderr, "%8lx %8lx %8ld %8ld %8ld\n",
-       stack, stack_base, *markstack_ptr, stack_sp-stack_base, stack_max-stack_base);
-    fprintf(stderr, "%8lx %8lx %8ld %l8d %8ld\n",
-       mainstack, AvARRAY(stack), mainstack, AvFILL(stack), AvMAX(stack));
+#ifdef DEBUGGING
+    dVAR;
+    PerlIO_printf(Perl_debug_log,
+                 "%8"UVxf" %8"UVxf" %8"IVdf" %8"IVdf" %8"IVdf"\n",
+                 PTR2UV(PL_curstack), PTR2UV(PL_stack_base),
+                 (IV)*PL_markstack_ptr, (IV)(PL_stack_sp-PL_stack_base),
+                 (IV)(PL_stack_max-PL_stack_base));
+    PerlIO_printf(Perl_debug_log,
+                 "%8"UVxf" %8"UVxf" %8"UVuf" %8"UVuf" %8"UVuf"\n",
+                 PTR2UV(PL_mainstack), PTR2UV(AvARRAY(PL_curstack)),
+                 PTR2UV(PL_mainstack), PTR2UV(AvFILLp(PL_curstack)),
+                 PTR2UV(AvMAX(PL_curstack)));
+#endif /* DEBUGGING */
     return 0;
 }
 
-I32
-debstack()
+
+/* dump the contents of a particular stack
+ * Display stack_base[stack_min+1 .. stack_max],
+ * and display the marks whose offsets are contained in addresses
+ * PL_markstack[mark_min+1 .. mark_max] and whose values are in the range
+ * of the stack values being displayed
+ *
+ * Only displays top 30 max
+ */
+
+STATIC void
+S_deb_stack_n(pTHX_ SV** stack_base, I32 stack_min, I32 stack_max,
+       I32 mark_min, I32 mark_max)
 {
-    register I32 i;
-    I32 markoff = markstack_ptr > markstack ? *markstack_ptr : -1;
-
-    fprintf(stderr, "     =>");
-    if (stack_base[0] || stack_sp < stack_base)
-       fprintf(stderr, " [STACK UNDERFLOW!!!]\n");
-    for (i = 1; i <= 30; i++) {
-       if (stack_sp >= &stack_base[i])
-       {
-           fprintf(stderr, "\t%-4s%s%s", SvPEEK(stack_base[i]),
-               markoff == i ? " [" : "",
-               stack_sp == &stack_base[i] ?
-                       (markoff == i ? "]" : " ]") : "");
+#ifdef DEBUGGING
+    dVAR;
+    register I32 i = stack_max - 30;
+    const I32 *markscan = PL_markstack + mark_min;
+    if (i < stack_min)
+       i = stack_min;
+    
+    while (++markscan <= PL_markstack + mark_max)
+       if (*markscan >= i)
+           break;
+
+    if (i > stack_min)
+       PerlIO_printf(Perl_debug_log, "... ");
+
+    if (stack_base[0] != &PL_sv_undef || stack_max < 0)
+       PerlIO_printf(Perl_debug_log, " [STACK UNDERFLOW!!!]\n");
+    do {
+       ++i;
+       if (markscan <= PL_markstack + mark_max && *markscan < i) {
+           do {
+               ++markscan;
+               PerlIO_putc(Perl_debug_log, '*');
+           }
+           while (markscan <= PL_markstack + mark_max && *markscan < i);
+           PerlIO_printf(Perl_debug_log, "  ");
        }
+       if (i > stack_max)
+           break;
+       PerlIO_printf(Perl_debug_log, "%-4s  ", SvPEEK(stack_base[i]));
     }
-    fprintf(stderr, "\n");
+    while (1);
+    PerlIO_printf(Perl_debug_log, "\n");
+#else
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(stack_base);
+    PERL_UNUSED_ARG(stack_min);
+    PERL_UNUSED_ARG(stack_max);
+    PERL_UNUSED_ARG(mark_min);
+    PERL_UNUSED_ARG(mark_max);
+#endif /* DEBUGGING */
+}
+
+
+/* dump the current stack */
+
+I32
+Perl_debstack(pTHX)
+{
+#ifndef SKIP_DEBUGGING
+    dVAR;
+    if (CopSTASH_eq(PL_curcop, PL_debstash) && !DEBUG_J_TEST_)
+       return 0;
+
+    PerlIO_printf(Perl_debug_log, "    =>  ");
+    deb_stack_n(PL_stack_base,
+               0,
+               PL_stack_sp - PL_stack_base,
+               PL_curstackinfo->si_markoff,
+               PL_markstack_ptr - PL_markstack);
+
+
+#endif /* SKIP_DEBUGGING */
     return 0;
 }
+
+
+#ifdef DEBUGGING
+static const char * const si_names[] = {
+    "UNKNOWN",
+    "UNDEF",
+    "MAIN",
+    "MAGIC",
+    "SORT",
+    "SIGNAL",
+    "OVERLOAD",
+    "DESTROY",
+    "WARNHOOK",
+    "DIEHOOK",
+    "REQUIRE"
+};
+#endif
+
+/* display all stacks */
+
+
+void
+Perl_deb_stack_all(pTHX)
+{
+#ifdef DEBUGGING
+    dVAR;
+    I32 si_ix;
+    const PERL_SI *si;
+
+    /* rewind to start of chain */
+    si = PL_curstackinfo;
+    while (si->si_prev)
+       si = si->si_prev;
+
+    si_ix=0;
+    for (;;)
+    {
+        const int si_name_ix = si->si_type+1; /* -1 is a valid index */
+        const char * const si_name = (si_name_ix>= sizeof(si_names)) ? "????" : si_names[si_name_ix];
+       I32 ix;
+       PerlIO_printf(Perl_debug_log, "STACK %"IVdf": %s\n",
+                                               (IV)si_ix, si_name);
+
+       for (ix=0; ix<=si->si_cxix; ix++) {
+
+           const PERL_CONTEXT * const cx = &(si->si_cxstack[ix]);
+           PerlIO_printf(Perl_debug_log,
+                   "  CX %"IVdf": %-6s => ",
+                   (IV)ix, PL_block_type[CxTYPE(cx)]
+           );
+           /* substitution contexts don't save stack pointers etc) */
+           if (CxTYPE(cx) == CXt_SUBST)
+               PerlIO_printf(Perl_debug_log, "\n");
+           else {
+
+               /* Find the the current context's stack range by searching
+                * forward for any higher contexts using this stack; failing
+                * that, it will be equal to the size of the stack for old
+                * stacks, or PL_stack_sp for the current stack
+                */
+
+               I32 i, stack_min, stack_max, mark_min, mark_max;
+               const PERL_CONTEXT *cx_n = NULL;
+               const PERL_SI *si_n;
+
+               /* there's a separate stack per SI, so only search
+                * this one */
+
+               for (i=ix+1; i<=si->si_cxix; i++) {
+                   if (CxTYPE(cx) == CXt_SUBST)
+                       continue;
+                   cx_n = &(si->si_cxstack[i]);
+                   break;
+               }
+
+               stack_min = cx->blk_oldsp;
+
+               if (cx_n) {
+                   stack_max = cx_n->blk_oldsp;
+               }
+               else if (si == PL_curstackinfo) {
+                   stack_max = PL_stack_sp - AvARRAY(si->si_stack);
+               }
+               else {
+                   stack_max = AvFILLp(si->si_stack);
+               }
+
+               /* for the other stack types, there's only one stack
+                * shared between all SIs */
+
+               si_n = si;
+               i = ix;
+               cx_n = NULL;
+               for (;;) {
+                   i++;
+                   if (i > si_n->si_cxix) {
+                       if (si_n == PL_curstackinfo)
+                           break;
+                       else {
+                           si_n = si_n->si_next;
+                           i = 0;
+                       }
+                   }
+                   if (CxTYPE(&(si_n->si_cxstack[i])) == CXt_SUBST)
+                       continue;
+                   cx_n = &(si_n->si_cxstack[i]);
+                   break;
+               }
+
+               mark_min  = cx->blk_oldmarksp;
+               if (cx_n) {
+                   mark_max  = cx_n->blk_oldmarksp;
+               }
+               else {
+                   mark_max = PL_markstack_ptr - PL_markstack;
+               }
+
+               deb_stack_n(AvARRAY(si->si_stack),
+                       stack_min, stack_max, mark_min, mark_max);
+
+               if (CxTYPE(cx) == CXt_EVAL || CxTYPE(cx) == CXt_SUB
+                       || CxTYPE(cx) == CXt_FORMAT)
+               {
+                   const OP * const retop = (CxTYPE(cx) == CXt_EVAL)
+                           ? cx->blk_eval.retop : cx->blk_sub.retop;
+
+                   PerlIO_printf(Perl_debug_log, "  retop=%s\n",
+                           retop ? OP_NAME(retop) : "(null)"
+                   );
+               }
+           }
+       } /* next context */
+
+
+       if (si == PL_curstackinfo)
+           break;
+       si = si->si_next;
+       si_ix++;
+       if (!si)
+           break; /* shouldn't happen, but just in case.. */
+    } /* next stackinfo */
+
+    PerlIO_printf(Perl_debug_log, "\n");
+#else
+    PERL_UNUSED_CONTEXT;
+#endif /* DEBUGGING */
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */