6816ee2015-03-15Martin Nilsson /* -*- c -*-
9944b02015-03-08Martin Nilsson || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ #include "global.h" #include "module.h" #include "pike_error.h" #include "interpret.h" #include "pike_embed.h" #include "module_support.h"
da8b642015-03-08Henrik Grubbström (Grubba) #include "builtin_functions.h"
48d1592015-03-16Martin Nilsson #include "mapping.h" #include "multiset.h"
da8b642015-03-08Henrik Grubbström (Grubba)  DECLARATIONS
34a6792015-03-08Martin Nilsson 
1fc83b2015-04-10Martin Nilsson /*! @module Debug */
34a6792015-03-08Martin Nilsson /*! @decl int(0..) map_all_objects(function(object:void) cb) *! *! Call cb for all objects that currently exist. The callback will *! not be called with destructed objects as it's argument. *! *! Objects might be missed if @[cb] creates new objects or destroys *! old ones. *! *! This function is only intended to be used for debug purposes. *! *! @returns *! The total number of objects *! *! @seealso *! @[next_object()] */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int(0..) map_all_objects(function(object:void) cb)
34a6792015-03-08Martin Nilsson { struct object *o = first_object; INT32 total = 0; while( o ) { struct object *next = o->next; if( o->prog ) { ref_push_object( o ); safe_apply_svalue( Pike_sp-2, 1, 1 ); pop_stack(); } total++; o = next; }
da8b642015-03-08Henrik Grubbström (Grubba)  RETURN total;
34a6792015-03-08Martin Nilsson }
9944b02015-03-08Martin Nilsson 
6816ee2015-03-15Martin Nilsson /*! @decl int refs(string|array|mapping|multiset|function|object|program o) *! *! Return the number of references @[o] has. *! *! It is mainly meant for debugging the Pike runtime, but can also be *! used to control memory usage. *! *! @note *! Note that the number of references will always be at least one since *! the value is located on the stack when this function is executed. *! *! @seealso
48d1592015-03-16Martin Nilsson  *! @[next()], @[prev()]
6816ee2015-03-15Martin Nilsson  */ PIKEFUN int refs(string|array|mapping|multiset|function|object|program o) { RETURN o->u.refs[0]; }
48d1592015-03-16Martin Nilsson /*! @decl object next_object(object o) *! @decl object next_object() *! *! Returns the next object from the list of all objects. *! *! All objects are stored in a linked list. *! *! @returns *! If no arguments have been given @[next_object()] will return the first *! object from the list. *! *! If @[o] has been specified the object after @[o] on the list will be *! returned. *! *! @note *! This function is not recomended to use. *! *! @seealso *! @[destruct()] */ PIKEFUN object next_object(void|object o) { if (!o) o = first_object; else o = Pike_sp[-args].u.object->next; while(o && !o->prog) o=o->next; pop_n_elems(args); if(o) ref_push_object(o); else push_int(0); } /*! @decl mixed next(mixed x) *! *! Find the next object/array/mapping/multiset/program or string. *! *! All objects, arrays, mappings, multisets, programs and strings are *! stored in linked lists inside Pike. This function returns the next *! item on the corresponding list. It is mainly meant for debugging *! the Pike runtime, but can also be used to control memory usage. *! *! @seealso *! @[next_object()], @[prev()] */
64226c2015-03-16Martin Nilsson PIKEFUN mixed next(mixed x) rawtype tOr6(tFunc(tStr,tStr), tFunc(tObj,tObj), tFunc(tMapping,tMapping), tFunc(tMultiset,tMultiset), tFunc(tPrg(tObj),tPrg(tObj)), tFunc(tArray,tArray));
48d1592015-03-16Martin Nilsson {
64226c2015-03-16Martin Nilsson  struct svalue tmp = *x;
48d1592015-03-16Martin Nilsson  switch(TYPEOF(tmp)) {
64226c2015-03-16Martin Nilsson  case T_OBJECT: tmp.u.object=tmp.u.object->next; while(tmp.u.object && !tmp.u.object->prog) tmp.u.object=tmp.u.object->next; break;
48d1592015-03-16Martin Nilsson  case T_ARRAY: tmp.u.array=tmp.u.array->next; break; case T_MAPPING: tmp.u.mapping=tmp.u.mapping->next; break; case T_MULTISET:tmp.u.multiset=tmp.u.multiset->next; break; case T_PROGRAM: tmp.u.program=tmp.u.program->next; break; case T_STRING: tmp.u.string=next_pike_string(tmp.u.string); break; default: SIMPLE_BAD_ARG_ERROR("next", 1, "object|array|mapping|multiset|program|string"); }
64226c2015-03-16Martin Nilsson 
48d1592015-03-16Martin Nilsson  if(tmp.u.refs)
64226c2015-03-16Martin Nilsson  assign_svalue(Pike_sp-1, &tmp); else
48d1592015-03-16Martin Nilsson  { pop_stack(); push_int(0); } } /*! @decl mixed prev(mixed x) *! *! Find the previous object/array/mapping/multiset or program. *! *! All objects, arrays, mappings, multisets and programs are *! stored in linked lists inside Pike. This function returns the previous *! item on the corresponding list. It is mainly meant for debugging *! the Pike runtime, but can also be used to control memory usage. *! *! @note *! Unlike @[next()] this function does not work on strings. *! *! @seealso *! @[next_object()], @[next()] */
64226c2015-03-16Martin Nilsson PIKEFUN mixed prev(mixed x) rawtype tOr5(tFunc(tObj,tObj), tFunc(tMapping,tMapping), tFunc(tMultiset,tMultiset), tFunc(tPrg(tObj),tPrg(tObj)), tFunc(tArray,tArray));
48d1592015-03-16Martin Nilsson {
64226c2015-03-16Martin Nilsson  struct svalue tmp = *x;
48d1592015-03-16Martin Nilsson  switch(TYPEOF(tmp)) {
64226c2015-03-16Martin Nilsson  case T_OBJECT: tmp.u.object=tmp.u.object->prev; while(tmp.u.object && !tmp.u.object->prog) tmp.u.object=tmp.u.object->prev; break;
48d1592015-03-16Martin Nilsson  case T_ARRAY: tmp.u.array=tmp.u.array->prev; break; case T_MAPPING: tmp.u.mapping=tmp.u.mapping->prev; break; case T_MULTISET:tmp.u.multiset=tmp.u.multiset->prev; break; case T_PROGRAM: tmp.u.program=tmp.u.program->prev; break; default: SIMPLE_BAD_ARG_ERROR("prev", 1, "object|array|mapping|multiset|program"); } if(tmp.u.refs)
64226c2015-03-16Martin Nilsson  assign_svalue(Pike_sp-1, &tmp); else
48d1592015-03-16Martin Nilsson  { pop_stack(); push_int(0); } }
9944b02015-03-08Martin Nilsson #ifdef PIKE_DEBUG /* This function is for debugging *ONLY* * do not document please. /Hubbe */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int leak(array|mapping|multiset|object|function|program|string|type val)
4a9aec2015-03-08Henrik Grubbström (Grubba)  export;
9944b02015-03-08Martin Nilsson { INT32 i;
da8b642015-03-08Henrik Grubbström (Grubba)  if(!REFCOUNTED_TYPE(TYPEOF(*val))) SIMPLE_BAD_ARG_ERROR("leak", 1,
9944b02015-03-08Martin Nilsson  "array|mapping|multiset|object|"
da8b642015-03-08Henrik Grubbström (Grubba)  "function|program|string|type");
9944b02015-03-08Martin Nilsson 
da8b642015-03-08Henrik Grubbström (Grubba)  add_ref(val->u.dummy); i = val->u.refs[0]; RETURN i;
9944b02015-03-08Martin Nilsson } /*! @decl int(0..) debug(int(0..) level) *! *! Set the run-time debug level. *! *! @returns *! The old debug level will be returned.
da8b642015-03-08Henrik Grubbström (Grubba)  *!
9944b02015-03-08Martin Nilsson  *! @note *! This function is only available if the Pike runtime has been compiled *! with RTL debug. */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int(0..) debug(int(0..) d)
4a9aec2015-03-08Henrik Grubbström (Grubba)  export;
9944b02015-03-08Martin Nilsson { pop_n_elems(args); push_int(d_flag); d_flag = d; } /*! @decl int(0..) optimizer_debug(int(0..) level) *! *! Set the optimizer debug level. *! *! @returns *! The old optimizer debug level will be returned.
da8b642015-03-08Henrik Grubbström (Grubba)  *!
9944b02015-03-08Martin Nilsson  *! @note *! This function is only available if the Pike runtime has been compiled *! with RTL debug. */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int(0..) optimizer_debug(int(0..) l)
4a9aec2015-03-08Henrik Grubbström (Grubba)  export;
9944b02015-03-08Martin Nilsson { pop_n_elems(args); push_int(l_flag); l_flag = l; } /*! @decl int(0..) assembler_debug(int(0..) level) *! *! Set the assembler debug level. *! *! @returns *! The old assembler debug level will be returned.
da8b642015-03-08Henrik Grubbström (Grubba)  *!
9944b02015-03-08Martin Nilsson  *! @note *! This function is only available if the Pike runtime has been compiled *! with RTL debug. */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int(0..) assembler_debug(int(0..) l)
4a9aec2015-03-08Henrik Grubbström (Grubba)  export;
9944b02015-03-08Martin Nilsson { pop_n_elems(args); push_int(a_flag); a_flag = l; } /*! @decl void dump_program_tables(program p, int(0..)|void indent) *! *! Dumps the internal tables for the program @[p] on stderr. *! *! @param p *! Program to dump. *! *! @param indent *! Number of spaces to indent the output. */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN void dump_program_tables(program p, int(0..)|void indent)
9944b02015-03-08Martin Nilsson {
da8b642015-03-08Henrik Grubbström (Grubba)  dump_program_tables(p, indent?indent->u.integer:0);
9944b02015-03-08Martin Nilsson  pop_n_elems(args); } #ifdef YYDEBUG /*! @decl int(0..) compiler_trace(int(0..) level) *! *! Set the compiler trace level. *! *! @returns *! The old compiler trace level will be returned.
da8b642015-03-08Henrik Grubbström (Grubba)  *!
9944b02015-03-08Martin Nilsson  *! @note *! This function is only available if the Pike runtime has been compiled *! with RTL debug. */
da8b642015-03-08Henrik Grubbström (Grubba) PIKEFUN int(0..) compiler_trace(int(0..) yyd)
4a9aec2015-03-08Henrik Grubbström (Grubba)  export;
9944b02015-03-08Martin Nilsson { extern int yydebug; pop_n_elems(args); push_int(yydebug); yydebug = yyd; } #endif /* YYDEBUG */
4e5a842015-04-10Martin Nilsson #if defined(PIKE_PORTABLE_BYTECODE) /*! @decl void disassemble(function fun) *! *! Disassemble a Pike function to @[Stdio.stderr]. *! *! @note *! This function is only available if the Pike runtime *! has been compiled with debug enabled. */ PIKEFUN void disassemble(function fun) { if ((TYPEOF(*fun) != T_FUNCTION) || (SUBTYPEOF(*fun) == FUNCTION_BUILTIN)) { fprintf(stderr, "Disassembly only supported for functions implemented in Pike.\n"); } else if (!fun->u.object->prog) { fprintf(stderr, "Function in destructed object.\n"); } else { int f = SUBTYPEOF(*fun); struct reference *ptr = PTR_FROM_INT(fun->u.object->prog, f); struct program *p = PROG_FROM_PTR(fun->u.object->prog, ptr); struct identifier *id = p->identifiers + ptr->identifier_offset; if (id->func.offset >= 0) { struct pike_string *tripples = p->strings[read_program_data(p->program + id->func.offset, -1)]; switch(tripples->size_shift) { #define CASE(SHIFT) \ case SHIFT: \ { \ PIKE_CONCAT(p_wchar, SHIFT) *str = \ PIKE_CONCAT(STR, SHIFT)(tripples); \ int i=0; \ while(i < tripples->len) { \ fprintf(stderr, "@@@ %d: %s, %d, %d\n", \ i/3, \ instrs[*str - F_OFFSET]. \ name, \ str[1], str[2]); \ str += 3; \ i += 3; \ } \ } \ break CASE(0); CASE(1); CASE(2); #undef CASE } } else { fprintf(stderr, "Prototype.\n"); } } pop_n_elems(args); push_int(0); } #endif /* PIKE_PORTABLE_BYTECODE */
9944b02015-03-08Martin Nilsson #endif /* PIKE_DEBUG */
19a3f32015-03-15Martin Nilsson 
1fc83b2015-04-10Martin Nilsson /*! @endmodule */
19a3f32015-03-15Martin Nilsson PIKE_MODULE_INIT { INIT; #ifdef PIKE_DEBUG ADD_INT_CONSTANT("HAVE_DEBUG", 1, 0); #endif }