Branch: Tag:

2000-11-20

2000-11-20 01:26:26 by Martin Stjernholm <mast@lysator.liu.se>

Did away with some recursion done from describe_backtrace to make it
consume less stack space. Added code to describe_backtrace to compact
repeated lines.

Rev: lib/master.pike.in:1.135

1:   /* -*- Pike -*-    * -  * $Id: master.pike.in,v 1.134 2000/09/28 03:38:23 hubbe Exp $ +  * $Id: master.pike.in,v 1.135 2000/11/20 01:26:26 mast Exp $    *    * Master-file for Pike.    *
456:   }      /* This function is called when an error occurs that is not caught -  * with catch(). It's argument consists of: -  * ({ error_string, backtrace }) where backtrace is the output from the -  * backtrace() efun. +  * with catch().    */   void handle_error(array(mixed)|object trace)   { -  predef::trace(0); +     if(mixed x=catch {    werror(describe_backtrace(trace));    })    { -  +  // One reason for this might be too little stack space, which +  // easily can occur for "out of stack" errors. It should help to +  // tune up the STACK_MARGIN values in interpret.c then.    werror("Error in handle_error in master object:\n");    if(catch {    werror("%O\nOriginal error:\n%O\n",x,trace);
474:    werror("sprintf() failed to write error.\n");    }    } -  +    }      object new(mixed prog, mixed ... args)
1490:       void identify_parts (mixed stuff)    { +  // Use an array as stack here instead of recursing directly; we +  // might be pressed for stack space if the backtrace being +  // described is a stack overflow. +  array identify_stack = ({stuff}); +  while (sizeof (identify_stack)) { +  stuff = identify_stack[-1]; +  identify_stack = identify_stack[..sizeof (identify_stack) - 2];    if (arrayp (stuff)) {    if (!ident[stuff]++) -  foreach (stuff, mixed elem) -  identify_parts (elem); +  identify_stack += stuff;    }    else if (multisetp (stuff)) {    if (!ident[stuff]++) -  foreach (indices (stuff), mixed elem) -  identify_parts (elem); +  identify_stack += indices (stuff);    }    else if (mappingp (stuff)) {    if (!ident[stuff]++) -  foreach (indices (stuff), mixed elem) -  identify_parts (elem), identify_parts (stuff[elem]); +  identify_stack += indices (stuff) + values (stuff);    }    else if (objectp (stuff) || functionp (stuff) || programp (stuff))    ident[stuff]++;    } -  +  }       string describe_string (string m, int maxlen)    {
1749:    else    if (catch (name = function_name (f))) name = "function";    -  if(object o=function_object(f)) { +  object o = function_object(f); +  if(o != 0) { // Testing simply on o here could invoke a `!.    string s;    if (!catch (s = sprintf("%O",o)) && s != "object")    return s+"->"+name;
1797:    Describer desc = Describer();    desc->identify_parts (trace);    -  for(e = sizeof(trace)-1; e>=0; e--) +  int end = 0; +  if( (sizeof(trace)>1) && +  arrayp(trace[0]) && +  (sizeof(trace[0]) > 2) && +  (trace[0][2] == _main)) +  end = 1; +  +  mapping(string:int) prev_pos = ([]); +  array(string) frames = ({}); +  int loop_start = 0, loop_next, loops; +  +  for(e = sizeof(trace)-1; e>=end; e--)    {    mixed tmp;    string row; -  if( arrayp(trace[e]) && -  (sizeof(trace[e]) > 2) && -  (trace[e][2] == _main) && -  (sizeof(trace)>1) ) -  continue; -  if (mixed err=catch { +  // The continue's below jump wrong when this catch is here.. :P + // if (mixed err=catch {    tmp = trace[e];    if(stringp(tmp))    {
1817:    string pos;    if(sizeof(tmp)>=2 && stringp(tmp[0])) {    if (intp(tmp[1])) { +  +  string exact_pos = tmp[0] + ":" + tmp[1]; +  int dup_frame; +  if (!zero_type (dup_frame = prev_pos[exact_pos])) { +  dup_frame -= sizeof (frames); +  if (!loop_start) { +  loop_start = dup_frame; +  loop_next = dup_frame + 1; +  loops = 0; +  continue; +  } +  else { +  int new_loop = 0; +  if (!loop_next) loop_next = loop_start, new_loop = 1; +  if (dup_frame == loop_next++) { +  loops += new_loop; +  continue; +  } +  } +  } +  prev_pos[exact_pos] = sizeof (frames); +     pos=trim_file_name(tmp[0])+":"+tmp[1];    } else {    pos = sprintf("%s:Bad line %t", trim_file_name(tmp[0]), tmp[1]);
1836:    pos=desc;    }    +  if (loop_start) { +  array(string) tail; +  if (!loop_next) tail = ({}), loops++; +  else tail = frames[loop_start + sizeof (frames) .. +  loop_next - 1 + sizeof (frames)]; +  if (loops) +  frames += ({sprintf ("... last %d frames above repeated %d times ...\n", +  -loop_start, loops)}); +  frames += tail; +  prev_pos = ([]); +  loop_start = 0; +  } +     string data;       if(sizeof(tmp)>=3)
1871:    row = "Destructed object";    }    } -  }) { -  row = sprintf("Error indexing backtrace line %d: %s (%O)!", e, err[0], err[1]); + // }) { + // row = sprintf("Error indexing backtrace line %d: %s (%O)!", e, err[0], err[1]); + // } +  frames += ({row + "\n"});    } -  ret += row + "\n"; +  +  if (loop_start) { +  // Want tail to contain a full loop rather than being empty; it +  // looks odd when the repeat message ends the backtrace. +  array(string) tail = frames[loop_start + sizeof (frames) .. +  loop_next - 1 + sizeof (frames)]; +  if (loops) +  frames += ({sprintf ("... last %d frames above repeated %d times ...\n", +  -loop_start, loops)}); +  frames += tail;    } -  +  +  ret += frames * "";    }       return ret;