Branch: Tag:

2003-06-02

2003-06-02 21:16:51 by Martin Stjernholm <mast@lysator.liu.se>

Improved error messages during decode.

Rev: src/encode.c:1.175

2:   || 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. - || $Id: encode.c,v 1.174 2003/06/01 18:37:19 mast Exp $ + || $Id: encode.c,v 1.175 2003/06/02 21:16:51 mast Exp $   */      #include "global.h"
27:   #include "bignum.h"   #include "pikecode.h"    - RCSID("$Id: encode.c,v 1.174 2003/06/01 18:37:19 mast Exp $"); + RCSID("$Id: encode.c,v 1.175 2003/06/02 21:16:51 mast Exp $");      /* #define ENCODE_DEBUG */   
450:    EDB(1,fprintf(stderr, "%*sEncoding TAG_AGAIN from <%d>\n",    data->depth, "", tmp->u.integer));    code_entry(TAG_AGAIN, tmp->u.integer, data); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto encode_done;    }else if (val->type != T_TYPE) {    EDB(1,fprintf(stderr, "%*sEncoding to <%d>: ",    data->depth, "", data->counter.u.integer);
492: Inside #if SIZEOF_INT_TYPE > 4
   Pike_error ("Cannot encode integers with more than 32 bits "    "without bignum support.\n");   #endif -  return; +  goto encode_done;    }    else    code_entry(TAG_INT, i,data);
882:       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto encode_done;    }    } -  Pike_error("Encoding of efuns is not supported yet.\n"); +  Pike_error("Cannot encode builtin functions.\n");    }       code_entry(TAG_FUNCTION, 0, data);
940:       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto encode_done;    }    if( p->event_handler )    Pike_error("Cannot encode programs with event handlers.\n");
1457:    }    }    + encode_done:; +    #ifdef ENCODE_DEBUG    data->depth -= 2;   #endif
1783:    INT32 what, e, num, numh; \    DECODE("decode_number"); \    X=(what & TAG_MASK) | (num<<4); \ -  EDB(5, fprintf(stderr, "%*s ==>%d\n", \ -  data->depth, "", X)); \ +  EDB(5, fprintf(stderr, "%*s ==>%ld\n", \ +  data->depth, "", (long) X)); \    }while(0) \      
2021:    compilation_depth = *orig_compilation_depth;   }    + static DECLSPEC(noreturn) void decode_error (struct svalue *decoding, +  struct svalue *other, +  char *msg, ...) +  ATTRIBUTE((noreturn,format (printf, 3, 4))); +  + static DECLSPEC(noreturn) void decode_error (struct svalue *decoding, +  struct svalue *other, +  char *msg, ...) + { +  int n = 0; +  char buf[4096]; +  va_list args; +  va_start (args, msg); + #ifdef HAVE_VSNPRINTF +  vsnprintf(buf, 4090, msg, args); + #else /* !HAVE_VSNPRINTF */ +  VSPRINTF(buf, msg, args); + #endif /* HAVE_VSNPRINTF */ +  va_end (args); +  +  if (decoding) { +  push_constant_text ("Error while decoding "); n++; +  push_constant_text ("%O"); +  push_svalue (decoding); +  f_sprintf (2); n++; +  push_constant_text (":\n"); n++; +  } +  push_text (buf); n++; +  if (other) { +  push_constant_text ("%O\n"); +  push_svalue (other); +  f_sprintf (2); n++; +  } +  f_add (n); +  +  f_backtrace (0); +  f_aggregate (2); +  +  free_svalue(& throw_value); +  dmalloc_touch_svalue(Pike_sp-1); +  throw_value = *--Pike_sp; +  throw_severity = THROW_ERROR; +  pike_throw(); + } +    static void decode_value2(struct decode_data *data)      #ifdef PIKE_DEBUG
2291:    break;       case 1: -  if(UNSAFE_IS_ZERO(Pike_sp-1)) +     { -  +  int fun; +  /* decode_value_clone_object does not call __INIT, so +  * we want to do that ourselves... +  */ +  struct object *o=decode_value_clone_object(Pike_sp-1); +  +  if (!o) { +  if (data->pickyness) +  decode_error (NULL, Pike_sp - 1, +  "Failed to decode program for object. Got: ");    EDB(1,fprintf(stderr, "%*sDecoded a failed object to <%d>: ",    data->depth, "", tmp.u.integer);    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr););    decode_value2(data); -  pop_stack(); -  }else{ -  int fun; -  struct object *o; -  /* decode_value_clone_object does not call __INIT, so -  * we want to do that ourselves... -  */ -  o=decode_value_clone_object(Pike_sp-1); +  pop_n_elems(2); +  push_undefined(); +  break; +  } +     debug_malloc_touch(o);    pop_stack();    push_object(o);
2334:    ref_push_object(o);    decode_value2(data);    if(!data->codec) -  Pike_error("Failed to decode object (no codec)\n"); +  decode_error(Pike_sp - 1, NULL, +  "Cannot decode object without codec.\n");       fun = find_identifier("decode_object", data->codec->prog);    if (fun < 0) -  Pike_error("Cannot decode objects without a " +  decode_error(Pike_sp - 1, NULL, +  "Cannot decode objects without a "    "\"decode_object\" function in the codec.\n");    apply_low(data->codec,fun,2);    pop_stack();
2373:    Pike_error("Object coding not compatible.\n");    break;    } -  if(Pike_sp[-1].type != T_OBJECT) -  if(data->pickyness) -  Pike_error("Failed to decode object.\n"); +     -  +  if(Pike_sp[-1].type != T_OBJECT && data->pickyness) +  decode_error(NULL, Pike_sp - 1, "Failed to decode object. Got: "); +     break;    }   
2398:       case 1: {    struct program *p; +  if(Pike_sp[-1].type != T_OBJECT && data->pickyness) +  decode_error(NULL, Pike_sp - 1, +  "Failed to decode function object. Got: "); +     decode_value2(data); -  +  if(Pike_sp[-1].type != T_STRING && data->pickyness) +  decode_error(NULL, Pike_sp - 1, +  "Failed to decode function identifier. Got: "); +     if (Pike_sp[-2].type == T_OBJECT &&    Pike_sp[-1].type == T_STRING &&    (p = Pike_sp[-2].u.object->prog)) {
2414:    dmalloc_touch_svalue(Pike_sp-1);    break;    } +  else if (data->pickyness) { +  if (Pike_sp[-1].u.string->size_shift) +  decode_error(NULL, Pike_sp - 2, "Couldn't find identifier in "); +  else +  decode_error(NULL, Pike_sp - 2, "Couldn't find identifier %s in ", +  Pike_sp[-1].u.string->str);    } -  +  }    pop_stack();    break;    }
2423:    Pike_error("Function coding not compatible.\n");    break;    } -  if(data->pickyness && Pike_sp[-1].type != T_FUNCTION) -  Pike_error("Failed to decode function.\n"); +  +  if(Pike_sp[-1].type != T_FUNCTION && data->pickyness) +  decode_error(NULL, Pike_sp - 1, "Failed to decode function. Got: "); +     break;      
2436:    {    case 0:    { -  struct svalue *prog_code; +     struct program *p;       tmp=data->counter;    data->counter.u.integer++;    decode_value2(data);    -  /* Keep the value so that we can make a good error-message. */ -  prog_code = Pike_sp-1; -  stack_dup(); -  +     if(data->codec)    {    apply(data->codec,"programof", 1);
2457:    p = program_from_svalue(Pike_sp-1);       if (!p) { -  if(data->pickyness) { -  if ((prog_code->type == T_STRING) && -  (prog_code->u.string->len < 128) && -  (!prog_code->u.string->size_shift)) { -  Pike_error("Failed to decode program \"%s\".\n", -  prog_code->u.string->str); -  } -  Pike_error("Failed to decode program.\n"); -  } -  pop_n_elems(2); +  if(data->pickyness) +  decode_error(NULL, Pike_sp - 1, +  "Failed to decode program. Got: "); +  pop_stack();    push_undefined();    break;    } -  /* Remove the extra entry from the stack. */ -  ref_push_program(p); -  stack_pop_2_elems_keep_top(); +  +  add_ref(p); +  pop_stack(); +  push_program(p);    break;    }    -  case 1: +  case 1: /* Old-style encoding. */    {    int d, in;    size_t size=0;
2534:    Pike_error("Cannot decode programs encoded with other pike version.\n");    pop_n_elems(2);    +  data->pickyness++; +     debug_malloc_touch(p);    decode_number(p->flags,data);   
2570:    p->parent=program_from_svalue(Pike_sp-1);    break;    default: -  Pike_error("Program decode failed!\n"); +  decode_error(NULL, Pike_sp - 1, "Program decode failed. Got: ");    }    if(p->parent) {    add_ref(p->parent);
2634:       getdata2(p->linenumbers, p->num_linenumbers);    +  /* Now with the linenumber info in place it gets useful to +  * include the program in error messages. */ +    #ifdef DEBUG_MALLOC    if(p->num_linenumbers && p->linenumbers &&    EXTRACT_UCHAR(p->linenumbers)==127)
2657:    if(p->identifier_index[d] > p->num_identifier_references)    {    p->identifier_index[d]=0; -  Pike_error("Malformed program in decode.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, "Malformed program in decode.\n");    }    }   
2668:    if(p->variable_index[d] > p->num_identifiers)    {    p->variable_index[d]=0; -  Pike_error("Malformed program in decode.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, "Malformed program in decode.\n");    }    }   
2679:    if(p->identifier_references[d].inherit_offset > p->num_inherits)    {    p->identifier_references[d].inherit_offset=0; -  Pike_error("Malformed program in decode.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, "Malformed program in decode.\n");    }    decode_number(p->identifier_references[d].identifier_offset,data);    decode_number(p->identifier_references[d].id_flags,data);
2698:    debug_malloc_touch(p);    debug_malloc_touch(dat);    -  data->pickyness++; -  -  +    /* p->inherits[0].prog=p;    p->inherits[0].parent_offset=1;   */
2710:    if(placeholder->prog != null_program)    {    debug_malloc_touch(placeholder); -  Pike_error("Placeholder argument is not a null_program clone!"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Placeholder argument is not a null_program clone.\n");    }else{    free_program(placeholder->prog);    add_ref(placeholder->prog = p);
2733:    if(d==0)    {    if(Pike_sp[-1].type != T_PROGRAM || -  Pike_sp[-1].u.program != p) -  Pike_error("Program decode failed!\n"); +  Pike_sp[-1].u.program != p) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Program decode of self inherit failed. Got: "); +  }    sub_ref(p);    }   
2755:       switch(Pike_sp[-1].type)    { -  case T_FUNCTION: -  if(Pike_sp[-1].subtype == FUNCTION_BUILTIN) -  Pike_error("Failed to decode parent.\n"); +  case T_PROGRAM: +  EDB(3, fprintf(stderr,"INHERIT%x = prog\n",p->id); ); +  p->inherits[d].prog=Pike_sp[-1].u.program; +  Pike_sp--; +  dmalloc_touch_svalue(Pike_sp); +  break;    -  +  case T_FUNCTION: +  if(Pike_sp[-1].subtype != FUNCTION_BUILTIN) {    EDB(3, fprintf(stderr,"INHERIT%x = func { %p, %d} \n",p->id,Pike_sp[-1].u.object, Pike_sp[-1].subtype); );       p->inherits[d].parent_identifier=Pike_sp[-1].subtype;    p->inherits[d].prog=program_from_svalue(Pike_sp-1); -  if(!p->inherits[d].prog) -  Pike_error("Failed to decode parent.\n"); +  if(!p->inherits[d].prog) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Failed to decode inherited program. Got: "); +  }    add_ref(p->inherits[d].prog);    p->inherits[d].parent=Pike_sp[-1].u.object;    Pike_sp--;    dmalloc_touch_svalue(Pike_sp);    break; -  +  } +  /* Fall through */    -  case T_PROGRAM: -  EDB(3, fprintf(stderr,"INHERIT%x = prog\n",p->id); ); -  p->inherits[d].prog=Pike_sp[-1].u.program; -  Pike_sp--; -  dmalloc_touch_svalue(Pike_sp); -  break; +     default: -  Pike_error("Failed to decode inheritance.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Failed to decode inherited program. Got: ");    }       p->num_inherits=d+1;
2809:    {    decode_number(p->identifiers[d].func.offset,data);    } else { -  Pike_error("Cannot decode functions implemented in C " -  "(identifier='%s').\n", -  p->identifiers[d].name->str); +  ref_push_program (p); +  ref_push_string (p->identifiers[d].name); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Cannot decode function implemented in C: ");    }    }   
2864:       if(placeholder && data->pass == 1)    { -  if(!p || (placeholder->storage)) +  if(placeholder->storage)    { -  Pike_error("Placeholder already has storage!\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, "Placeholder already has storage!\n");    } else {    placeholder->storage=p->storage_needed ?    (char *)xalloc(p->storage_needed) :
3006:    }else{    f_arrow(2);    } -  if(data->pickyness && Pike_sp[-1].type != T_PROGRAM) -  Pike_error("Failed to decode program.\n"); +  if(Pike_sp[-1].type != T_PROGRAM && data->pickyness) +  decode_error(NULL, Pike_sp - 1, "Failed to decode program. Got: ");    break;       case 3:
3019:    (Pike_sp[-1].u.integer > 0)) {    struct program *p = id_to_program(Pike_sp[-1].u.integer);    if (!p) { -  Pike_error("Failed to decode program %"PRINTPIKEINT"d\n", +  Pike_error("Failed to get program from ID %"PRINTPIKEINT"d\n",    Pike_sp[-1].u.integer);    }    pop_stack();    ref_push_program(p);    } else { -  Pike_error("Failed to decode program.\n"); +  decode_error(NULL, Pike_sp - 1, +  "Failed to decode program by ID. Expected integer, got: ");    }    break;    -  case 4: +  case 4: /* New-style encoding. */    {    struct program *p;    ONERROR err;
3171:    add_to_linenumbers(lineno_info);    }    +  /* Now with the linenumber info in place it gets useful to +  * include the program in error messages. */ +     /* identifier_index & variable_index are created by    * fixate_program() and optimize_program().    */
3179:    for (e=0; e<local_num_strings; e++) {    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) { -  Pike_error("Non strings in string table.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Nonstrings in string table: ");    }    add_to_strings(Pike_sp[-1].u.string);    dmalloc_touch_svalue(Pike_sp-1);
3236:       if (no > p->num_identifier_references) {    EDB (3, dump_program_tables (p, data->depth)); -  Pike_error("Bad identifier reference offset: %d != %d\n", no, +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad identifier reference offset: %d != %d\n", no,    Pike_compiler->new_program->    num_identifier_references);    } else if (no == p->num_identifier_references) {
3255:    /* name */    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) { -  Pike_error("Bad variable name (not a string)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad variable name (not a string): ");    }       /* type */    decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) { -  Pike_error("Bad variable type (not a type)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad variable type (not a type): ");    }       /* Expected identifier offset */
3281:    if (no != define_variable(Pike_sp[-2].u.string,    Pike_sp[-1].u.type,    id_flags)) { -  Pike_error("Bad variable identifier offset: %d\n", no); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad variable identifier offset: %d\n", no);    }       pop_n_elems(2);
3298:    /* name */    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) { -  Pike_error("Bad function name (not a string)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad function name (not a string): ");    }       /* type */    decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) { -  Pike_error("Bad function type (not a type)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad function type (not a type): ");    }       /* func_flags (aka identifier_flags) */
3352:    p->identifier_references[no].identifier_offset !=    p->identifier_references[n].identifier_offset ||    p->identifier_references[no].inherit_offset != 0)) { -  Pike_error("Bad function identifier offset: %d\n", no); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad function identifier offset: %d\n", no);    }       pop_n_elems(2);
3368:    /* name */    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) { -  Pike_error("Bad function name (not a string)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad constant name (not a string): ");    }    id.name = Pike_sp[-1].u.string;   
3385:    /* type */    decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) { -  Pike_error("Bad function type (not a type)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad constant type (not a type): ");    }    id.type = Pike_sp[-1].u.type;   
3430:    }       if (no != n) { -  if (id.name->size_shift) -  Pike_error("Bad constant identifier offset: %d\n", no); -  else -  Pike_error("Bad constant identifier offset %d for %s\n", -  no, id.name->str); +  ref_push_program (p); +  ref_push_string (id.name); +  decode_error(Pike_sp - 2, Pike_sp - 1, +  "Bad function identifier offset %d for ", no);    }       add_to_identifiers(id);
3455:    decode_number(no, data);    if (no !=    Pike_compiler->new_program->num_identifier_references) { -  Pike_error("Bad inherit identifier offset: %d\n", no); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad inherit identifier offset: %d\n", no);    }       /* name */
3464:    name = Pike_sp[-1].u.string;    } else if ((Pike_sp[-1].type != T_INT) ||    Pike_sp[-1].u.integer) { -  Pike_error("Bad function name (not a string)\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad inherit name (not a string): ");    }       /* prog */    decode_value2(data);    if (Pike_sp[-1].type != T_PROGRAM) { -  Pike_error("Bad inherit: Expected program, got %s\n", -  get_name_of_type(Pike_sp[-1].type)); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad inherit: Expected program, got ");    }    prog = Pike_sp[-1].u.program; -  +  if (prog == placeholder_program) { +  ref_push_program (p); +  decode_error (Pike_sp - 1, NULL, +  "Trying to inherit placeholder program " +  "(resolver or codec problem).\n"); +  } +  if(!(prog->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) { +  ref_push_program (p); +  decode_error (Pike_sp - 1, Pike_sp - 2, +  "Cannot inherit a program which is not " +  "fully compiled yet (resolver or codec problem):\n"); +  }       /* parent */    decode_value2(data);
3481:    parent = Pike_sp[-1].u.object;    } else if ((Pike_sp[-1].type != T_INT) ||    Pike_sp[-1].u.integer) { -  Pike_error("Bad inherit: Parent isn't an object.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Bad inherit: Parent isn't an object: ");    }       /* parent_identifier */
3494:    decode_number(no, data);       if (prog->num_identifier_references != no) { -  Pike_error("Bad number of identifiers in inherit: %d\n", no); +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad number of identifiers in inherit: %d != %d\n", +  no, prog->num_identifier_references);    }       EDB(5,
3536:    *    * lfuns and identifier_index    */ +  ref_push_program (p);    if (!(p = end_first_pass(2))) { -  Pike_error("Failed to decode program.\n"); +  decode_error(Pike_sp - 1, NULL, "Failed to decode program.\n");    } -  +  pop_stack();    compilation_depth = orig_compilation_depth;    push_program(p);       /* Verify... */ - #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ -  if (PIKE_CONCAT(local_num_, NAME) != p->PIKE_CONCAT(num_,NAME)) { \ -  Pike_error("Value mismatch for num_" TOSTR(NAME) ": %d != %d\n", \ -  PIKE_CONCAT(local_num_, NAME), \ -  p->PIKE_CONCAT(num_, NAME)); \ + #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ +  if (PIKE_CONCAT(local_num_, NAME) != p->PIKE_CONCAT(num_,NAME)) { \ +  ref_push_program (p); \ +  decode_error(Pike_sp - 1, NULL, \ +  "Value mismatch for num_" TOSTR(NAME) ": %d != %d\n", \ +  PIKE_CONCAT(local_num_, NAME), \ +  p->PIKE_CONCAT(num_, NAME)); \    }   #include "program_areas.h"   
3567:    !Pike_sp[-1].u.integer) {    constant->name = NULL;    } else { -  Pike_error("Name of constant is not a string.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Name of constant is not a string: ");    }    constant->sval = Pike_sp[-2];    dmalloc_touch_svalue(Pike_sp-1);