pike.git / src / pike_types.c

version» Context lines:

pike.git/src/pike_types.c:1:   /*   || 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 <ctype.h>   #include "svalue.h" - #include "pike_types.h" +    #include "stralloc.h" -  + #include "pike_types.h"   #include "stuff.h"   #include "array.h"   #include "program.h"   #include "constants.h"   #include "object.h"   #include "multiset.h"   #include "mapping.h"   #include "pike_macros.h"   #include "pike_error.h"   #include "las.h"   #include "lex.h"   #include "pike_memory.h"   #include "bignum.h"   #include "main.h"   #include "opcodes.h"   #include "cyclic.h"   #include "gc.h"   #include "pike_compiler.h" - #include "block_alloc.h" + #include "block_allocator.h"      #ifdef PIKE_DEBUG   #define PIKE_TYPE_DEBUG   #endif /* PIKE_DEBUG */      /*    * Flags used by low_match_types().    */   #define A_EXACT 1   #define B_EXACT 2
pike.git/src/pike_types.c:69:      /*    * Flags used as flag_method to mk_type()    */   #define PT_COPY_CAR 1   #define PT_COPY_CDR 2   #define PT_COPY_BOTH 3   #define PT_IS_MARKER 4 /* The node is a marker. */      /* Number of entries in the struct pike_type hash-table. */ - #define PIKE_TYPE_HASH_SIZE 32768 + #define PIKE_TYPE_HASH_SIZE 65535         #ifdef PIKE_TYPE_DEBUG   static int indent=0;   #endif      int max_correct_args;      PMOD_EXPORT struct pike_type *string0_type_string;   PMOD_EXPORT struct pike_type *string_type_string;
pike.git/src/pike_types.c:92:   PMOD_EXPORT struct pike_type *function_type_string;   PMOD_EXPORT struct pike_type *object_type_string;   PMOD_EXPORT struct pike_type *program_type_string;   PMOD_EXPORT struct pike_type *array_type_string;   PMOD_EXPORT struct pike_type *multiset_type_string;   PMOD_EXPORT struct pike_type *mapping_type_string;   PMOD_EXPORT struct pike_type *type_type_string;   PMOD_EXPORT struct pike_type *mixed_type_string;   PMOD_EXPORT struct pike_type *void_type_string;   PMOD_EXPORT struct pike_type *zero_type_string; + PMOD_EXPORT struct pike_type *enumerable_type_string;   PMOD_EXPORT struct pike_type *any_type_string;   PMOD_EXPORT struct pike_type *weak_type_string; /* array|mapping|multiset|function */   struct pike_type *sscanf_type_string;   struct pike_type *sscanf_76_type_string;      #ifdef DO_PIKE_CLEANUP   struct pike_type_location *all_pike_type_locations = NULL;   #endif /* DO_PIKE_CLEANUP */      static struct pike_type *a_markers[10], *b_markers[10];
pike.git/src/pike_types.c:270:    * INT min (int) max (int)    * OBJECT implements/is object id(int)    *    * Note that the cdr of a FUNCTION is a valid FUNCTION for the rest of    * the arguments.    *    * Note also that functions that don't take any arguments, or just    * a many argument just have a MANY node, and no FUNCTION node.    *    */ - #define PIKE_TYPE_CHUNK 128 - BLOCK_ALLOC(pike_type, PIKE_TYPE_CHUNK) + static struct block_allocator type_allocator = BA_INIT(sizeof(struct pike_type), 128);    -  + PMOD_EXPORT void really_free_pike_type(struct pike_type * t) { +  ba_free(&type_allocator, t); + } +  + ATTRIBUTE((malloc)) + PMOD_EXPORT struct pike_type * alloc_pike_type() { +  return ba_alloc(&type_allocator); + } +  + PMOD_EXPORT void count_memory_in_pike_types(size_t *n, size_t *s) { +  ba_count_all(&type_allocator, n, s); + } +    struct pike_type **pike_type_hash = NULL;   size_t pike_type_hash_size = 0;      void debug_free_type(struct pike_type *t)   {   #ifdef DEBUG_MALLOC    if (t == (struct pike_type *)(size_t)0x55555555) {    Pike_fatal("Freeing dead type.\n");    }   #endif /* DEBUG_MALLOC */    loop:    if (!sub_ref(t)) { -  unsigned INT32 hash = t->hash % pike_type_hash_size; +  unsigned INT32 hash = t->hash & pike_type_hash_size;    struct pike_type **t2 = pike_type_hash + hash;    struct pike_type *car, *cdr;    unsigned INT32 type; -  + #ifdef PIKE_DEBUG    /* PIKE_DEBUG code */ -  if (hash >= pike_type_hash_size) { +  if (hash > pike_type_hash_size) {    Pike_fatal("Modulo operation failed for hash:%u, index:%u, size:%u.\n",    t->hash, hash, pike_type_hash_size);    }    /* End PIKE_DEBUG code */ -  + #endif    while (*t2) {    if (*t2 == t) {    *t2 = t->next;    break;    }    t2 = &((*t2)->next);    }       car = t->car;    cdr = t->cdr;    type = t->type;    -  really_free_pike_type((struct pike_type *)debug_malloc_pass(t)); +  really_free_pike_type((struct pike_type*)debug_malloc_pass(t));       /* FIXME: Recursion: Should we use a stack? */    switch(type) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:
pike.git/src/pike_types.c:387:   }      static inline struct pike_type *debug_mk_type(unsigned INT32 type,    struct pike_type *car,    struct pike_type *cdr,    int flag_method)   {    /* FIXME: The hash ought to be based on the tree contents, regardless    * of what the adresses of the type nodes are.    */ -  unsigned INT32 hash = DO_NOT_WARN((unsigned INT32) +  struct pike_type *t; +  unsigned INT32 index, +  hash = DO_NOT_WARN((unsigned INT32)    ((ptrdiff_t)type*0x10204081)^    (0x8003*PTR_TO_INT(car))^    ~(0x10001*PTR_TO_INT(cdr))); -  unsigned INT32 index = hash % pike_type_hash_size; -  struct pike_type *t; +  +  hash ^= (hash >> 20) ^ (hash >> 12); +  hash ^= (hash >> 7) ^ (hash >> 4); +  +  index = hash & pike_type_hash_size;   #ifdef PIKE_EXTRA_DEBUG    static unsigned INT32 extra_debug_index = (unsigned INT32)~0;   #endif /* PIKE_EXTRA_DEBUG */ -  + #ifdef PIKE_DEBUG    /* PIKE_DEBUG code */    if (type & ~255) {    /* The bad type node on OSF/1 seems to be:    *    * type: 0xffff    * car: valid pointer.    * cdr: 0x400000000    * next: 0x100000000    */    Pike_fatal("Attempt to create an invalid type node: %d(%s)\n"    " car: %p\n"    " cdr: %p\n",    type, get_name_of_type(type),    car, cdr);    } -  if (index >= pike_type_hash_size) { +  if (index > pike_type_hash_size) {    Pike_fatal("Modulo operation failed for hash:%u, index:%u, "    "size:%"PRINTSIZET"d.\n",    hash, index, pike_type_hash_size);    }    /* End PIKE_DEBUG code */ -  + #endif   #ifdef PIKE_EXTRA_DEBUG    if ((!~extra_debug_index) &&    (type == T_FUNCTION) &&    (car->type == T_STRING) &&    (cdr->type == T_FUNCTION) &&    (cdr->car->type == T_STRING) &&    (cdr->cdr->type == T_MANY) &&    (cdr->cdr->car->type == T_VOID) &&    (cdr->cdr->cdr->type == T_STRING)) {    /* Attempt to detect why we get a core-dump on OSF/1
pike.git/src/pike_types.c:510:    case T_ASSIGN:    /* Free cdr */    free_type((struct pike_type *)debug_malloc_pass(cdr));    break;       case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    free_string((struct pike_string *)debug_malloc_pass(car));    free_type((struct pike_type *)debug_malloc_pass(cdr));    break; -  +    #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':
pike.git/src/pike_types.c:547:    return t;    }    }      #ifdef PIKE_DEBUG    if ((type == T_OR) && (car->type == T_OR)) {    Pike_fatal("Invalid CAR to OR node.\n");    }   #endif    -  debug_malloc_pass(t = alloc_pike_type()); +  debug_malloc_pass(t = ba_alloc(&type_allocator));      #ifdef ATOMIC_SVALUE    t->ref_type = PIKE_T_TYPE;   #endif    t->refs = 0;    add_ref(t); /* For DMALLOC... */    t->type = type;    t->flags = 0;    t->car = car;    t->cdr = cdr;
pike.git/src/pike_types.c:1061:    Pike_compiler->type_stackp[0] = Pike_compiler->type_stackp[-1];    Pike_compiler->type_stackp[-1] = tmp;    break;    }    }    push_type(type);       TYPE_STACK_DEBUG("push_reverse_type");   }    + static int is_int_type(struct pike_type *t) + { +  loop: +  switch(t->type) { +  case T_INT: +  case T_ZERO: +  case T_VOID: +  case '0': case '1': case '2': case '3': case '4': +  case '5': case '6': case '7': case '8': case '9': +  return 1; +  case T_OR: +  case T_AND: +  return is_int_type(t->car) && is_int_type(t->cdr); +  case PIKE_T_NAME: +  case PIKE_T_ATTRIBUTE: +  case PIKE_T_SCOPE: +  case T_ASSIGN: +  t = t->cdr; +  goto loop; +  default: +  return 0; +  } + } +    /* The marker_set is used as follows:    *    * PT_FLAG_MARKER_n Indicates that marker #n should be kept after    * expansion.    *    * PT_FLAG_ASSIGN_n Indicates that the assign to marker #n should    * NOT be removed.    */   static void debug_push_finished_type_with_markers(struct pike_type *type,    struct pike_type **markers,
pike.git/src/pike_types.c:1094:    */    if (!(type->flags & (~marker_set | PT_FLAG_MARKER) & PT_FLAG_MARK_ASSIGN)) {    /* Nothing to replace in this subtree. */   #ifdef PIKE_TYPE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "Nothing to replace in this subtree.\n");    simple_describe_type(type);    fprintf(stderr, "\n");    }   #endif /* PIKE_TYPE_DEBUG */ +  if ((marker_set & PT_FLAG_INT_ONLY) && !is_int_type(type)) { +  push_finished_type(int_type_string); +  } else {    push_finished_type(type); -  +  }    return;    }    if ((type->type >= '0') && (type->type <= '9')) {    /* Marker. */    unsigned int m = type->type - '0';   #ifdef PIKE_TYPE_DEBUG    if ((l_flag > 2) && m) {    fprintf(stderr, "Marker %d: %p.\n", m, markers[m]);    }   #endif /* PIKE_TYPE_DEBUG */    if (markers[m]) {    /* The marker has a value. */    struct pike_type *type = dmalloc_touch(struct pike_type *, markers[m]);   #ifdef PIKE_TYPE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "Marker value.\n");    }   #endif    /* FIXME: We probably ought to switch to the other marker set here. */    markers[m] = NULL; -  push_finished_type_with_markers(type, markers, 0); +  push_finished_type_with_markers(type, markers, +  marker_set & PT_FLAG_INT_ONLY);    if (type->flags & (PT_FLAG_MARKER|PT_FLAG_ASSIGN)) {    push_scope_type(0);    }    if (markers[m]) free_type(markers[m]);    markers[m] = dmalloc_touch(struct pike_type *, type);    } else {    /* The marker has not been set. */   #ifdef PIKE_TYPE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "No marker value.\n");
pike.git/src/pike_types.c:1183:    goto recurse;    }    } else if (type->type == PIKE_T_NAME) {    /* Strip the name, since it won't be correct anymore. */    type = type->cdr;    goto recurse;    } else if (type->type == PIKE_T_ATTRIBUTE) {    /* Keep the attribute. */    push_finished_type_with_markers(type->cdr, markers, marker_set);    push_type_attribute((struct pike_string *)type->car); +  goto done;    }    /* FIXME: T_SCOPE */       if (type->car) {    /* Keep markers for assigns in the car. */    cdr_set = marker_set |    ((type->car->flags & PT_FLAG_ASSIGN)>>PT_ASSIGN_SHIFT);    } else {    cdr_set = marker_set;    }
pike.git/src/pike_types.c:1240:    pop_stack_mark();    pop_stack_mark();    push_type(T_AND);    }    }    } else {    if (type->cdr) {    /* In all other cases type->cdr will be a valid node if is not NULL. */    push_finished_type_with_markers(type->cdr, markers, cdr_set);    } +  /* Make sure to filter invalid nodes from the marker in case +  * it is a string type. +  */ +  if (type->type == PIKE_T_STRING) car_set |= PT_FLAG_INT_ONLY;    /* In all other cases type->car will be a valid node. */    push_finished_type_with_markers(type->car, markers, car_set);    /* push_type has sufficient magic to recreate the type. */    push_type(type->type);    } -  +  done:    TYPE_STACK_DEBUG("push_finished_type_with_markers");   }      static void push_type_field(TYPE_FIELD field)   {    field &= (BIT_BASIC|BIT_COMPLEX);    if (!field) {    /* No values. */    push_type(T_ZERO);    } else if (field == (BIT_BASIC|BIT_COMPLEX)) {
pike.git/src/pike_types.c:1902: Inside #if defined(PIKE_DEBUG)
   break;       case T_SCOPE: fprintf(stderr, "scope"); break;    case T_TUPLE: fprintf(stderr, "tuple"); break;    case T_ASSIGN: fprintf(stderr, "="); break;    case T_INT:    {    INT32 min=extract_type_int(a+e+1);    INT32 max=extract_type_int(a+e+1+sizeof(INT32));    fprintf(stderr, "int"); -  if(min!=MIN_INT32 || max!=MAX_INT32) +  if(min!=MIN_INT32 || max!=MAX_INT32) { +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  fprintf(stderr, "(%dbit)", j); +  } else {    fprintf(stderr, "(%ld..%ld)",(long)min,(long)max); -  +  } +  }    e+=sizeof(INT32)*2;    break;    }    case T_FLOAT: fprintf(stderr, "float"); break;    case T_STRING: fprintf(stderr, "string"); break;    case T_TYPE: fprintf(stderr, "type"); break;    case T_PROGRAM: fprintf(stderr, "program"); break;    case T_OBJECT:    fprintf(stderr, "object(%s %ld)",    EXTRACT_UCHAR(a+e+1)?"is":"implements",
pike.git/src/pike_types.c:1991:    case T_ASSIGN:    fprintf(stderr, "(%"PRINTPTRDIFFT"d = ", CAR_TO_INT(s));    simple_describe_type(s->cdr);    fprintf(stderr, ")");    break;    case T_INT:    {    INT32 min = CAR_TO_INT(s);    INT32 max = CDR_TO_INT(s);    fprintf(stderr, "int"); -  if(min!=MIN_INT32 || max!=MAX_INT32) +  if(min!=MIN_INT32 || max!=MAX_INT32) { +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  fprintf(stderr, "(%dbit)", j); +  } else {    fprintf(stderr, "(%ld..%ld)",(long)min,(long)max); -  +  } +  }    break;    }    case T_FLOAT: fprintf(stderr, "float"); break;    case T_STRING:    {    INT32 min;    INT32 max;    s = s->car;    fprintf(stderr, "string");    if (s != int_type_string) {
pike.git/src/pike_types.c:2015:    struct pike_type *char_type = s->car;    while(char_type->type == T_ASSIGN) {    char_type = char_type->cdr;    }       if (char_type->type == T_ZERO) {    fprintf(stderr, "zero | ");    s = s->cdr;    continue;    } +  if ((char_type->type >= '0') && (char_type->type <= '9')) { +  fprintf(stderr, "$%c | ", char_type->type); +  s = s->cdr; +  continue; +  }   #ifdef PIKE_DEBUG    if (char_type->type != T_INT) {    Pike_fatal("Invalid node type (%d:%s) in string type.\n",    char_type->type, get_name_of_type(char_type->type));    }   #endif /* PIKE_DEBUG */    min = CAR_TO_INT(char_type);    max = CDR_TO_INT(char_type); -  +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  fprintf(stderr, "%dbit", j); +  } else {    if (min != MIN_INT32) {    fprintf(stderr, "%d", min);    }    fprintf(stderr, "..");    if (max != MAX_INT32) {    fprintf(stderr, "%d", max);    } -  +  }    fprintf(stderr, " | ");    s = s->cdr;    }    while(s->type == T_ASSIGN) {    s = s->cdr;    }    if (s->type == T_ZERO) {    fprintf(stderr, "zero"); -  +  } else if ((s->type >= '0') && (s->type <= '9')) { +  fprintf(stderr, "$%c", s->type);    } else {   #ifdef PIKE_DEBUG    if (s->type != T_INT) {    Pike_fatal("Invalid node type (%d:%s) in string type.\n",    s->type, get_name_of_type(s->type));    }   #endif /* PIKE_DEBUG */    min = CAR_TO_INT(s);    max = CDR_TO_INT(s); -  +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  fprintf(stderr, "%dbit", j); +  } else {    if (min != MIN_INT32) {    fprintf(stderr, "%d", min);    }    fprintf(stderr, "..");    if (max != MAX_INT32) {    fprintf(stderr, "%d", max);    }    } -  +  }    fprintf(stderr, ")");    }    break;    }    case T_TYPE:    fprintf(stderr, "type(");    simple_describe_type(s->car);    fprintf(stderr, ")");    break;    case T_PROGRAM:
pike.git/src/pike_types.c:2119:    case T_MULTISET:    fprintf(stderr, "multiset(");    simple_describe_type(s->car);    fprintf(stderr, ")");    break;       case PIKE_T_UNKNOWN: fprintf(stderr, "unknown"); break;    case PIKE_T_RING:    fprintf(stderr, "ring(");    simple_describe_type(s->car); -  fprintf(stderr, "°"); +  fprintf(stderr, "\260");    simple_describe_type(s->cdr);    fprintf(stderr, ")");    break;    case T_OR:    fprintf(stderr, "or(");    simple_describe_type(s->car);    fprintf(stderr, "|");    simple_describe_type(s->cdr);    fprintf(stderr, ")");    break;
pike.git/src/pike_types.c:2209:    case T_VOID: my_strcat("void"); break;    case T_ZERO: my_strcat("zero"); break;    case T_MIXED: my_strcat("mixed"); break;    case PIKE_T_UNKNOWN: my_strcat("unknown"); break;    case T_INT:    {    INT32 min=CAR_TO_INT(t);    INT32 max=CDR_TO_INT(t);    my_strcat("int");    -  if(min!=MIN_INT32 || max!=MAX_INT32) -  { +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  sprintf(buffer, "(%dbit)", j); +  my_strcat(buffer); +  } else if(min!=MIN_INT32 || max!=MAX_INT32) {    sprintf(buffer,"(%ld..%ld)",(long)min,(long)max);    my_strcat(buffer);    }    break;    }    case T_FLOAT: my_strcat("float"); break;    case T_PROGRAM:    if ((t->car->type == T_OBJECT) &&    (!t->car->cdr)) {    my_strcat("program");
pike.git/src/pike_types.c:2275:    my_strcat("string");    if (t->type == T_ZERO) {    my_strcat("(zero)");    } else if (t != int_type_string) {    my_strcat("(");    while (t->type == T_OR) {    struct pike_type *char_type = t->car;    while(char_type->type == T_ASSIGN) {    char_type = char_type->cdr;    } - #ifdef PIKE_DEBUG +     if (char_type->type != T_INT) { -  Pike_fatal("Invalid node type (%d:%s) in string type.\n", -  char_type->type, get_name_of_type(char_type->type)); -  } - #endif /* PIKE_DEBUG */ +  low_describe_type(char_type); +  } else {    min = CAR_TO_INT(char_type);    max = CDR_TO_INT(char_type); -  +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  sprintf(buffer, "%dbit", j); +  my_strcat(buffer); +  } else {    if (min != MIN_INT32) {    sprintf(buffer, "%d", min);    my_strcat(buffer);    }    my_strcat("..");    if (max != MAX_INT32) {    sprintf(buffer, "%d", max);    my_strcat(buffer);    } -  +  } +  }    my_strcat(" | ");    t = t->cdr;    }    while(t->type == T_ASSIGN) {    t = t->cdr;    } - #ifdef PIKE_DEBUG +     if (t->type != T_INT) { -  Pike_fatal("Invalid node type (%d:%s) in string type.\n", -  t->type, get_name_of_type(t->type)); -  } - #endif /* PIKE_DEBUG */ +  low_describe_type(t); +  } else {    min = CAR_TO_INT(t);    max = CDR_TO_INT(t); -  +  if (!min && max && !(max & (max+1))) { +  int j = 0; +  while (max) { +  max >>= 1; +  j++; +  } +  sprintf(buffer, "%dbit", j); +  my_strcat(buffer); +  } else {    if (min != MIN_INT32) {    sprintf(buffer, "%d", min);    my_strcat(buffer);    }    my_strcat("..");    if (max != MAX_INT32) {    sprintf(buffer, "%d", max);    my_strcat(buffer);    } -  +  } +  }    my_strcat(")");    }    break;    }    case T_TYPE:    my_strcat("type(");    my_describe_type(t->car);    my_strcat(")");    break;   
pike.git/src/pike_types.c:4764:       switch(low_check_indexing(t, index_type, n))    {    case 0: return 0;    case -1:    add_ref(zero_type_string);    return zero_type_string;    }       while((t->type == PIKE_T_NAME) || -  (t->type == PIKE_T_ATTRIBUTE)) { +  (t->type == PIKE_T_ATTRIBUTE) || +  (t->type == T_ASSIGN) || +  (t->type == T_SCOPE)) {    t = t->cdr;    }    while((index_type->type == PIKE_T_NAME) || -  (index_type->type == PIKE_T_ATTRIBUTE)) { +  (index_type->type == PIKE_T_ATTRIBUTE) || +  (index_type->type == T_ASSIGN) || +  (index_type->type == T_SCOPE)) {    index_type = index_type->cdr;    }       switch(t->type)    {    case T_OBJECT:    {    p = id_to_program(CDR_TO_INT(t));       comefrom_int_index:
pike.git/src/pike_types.c:4830:    {    add_ref(mixed_type_string);    return mixed_type_string;    }else{    add_ref(ID_FROM_INT(p, i)->type);    return ID_FROM_INT(p, i)->type;    }    }    }    } +  /* FALL_THROUGH */ +     default:    add_ref(mixed_type_string);    return mixed_type_string;       case T_MIXED:    if (pragmas & ID_STRICT_TYPES) {    yywarning("Indexing mixed.");    }    add_ref(mixed_type_string);    return mixed_type_string;       case T_INT: - #ifdef AUTO_BIGNUM +     /* Don't force Gmp.mpz to be loaded here since this function    * is called long before the master object is compiled...    * /Hubbe    */    p=get_auto_bignum_program_or_zero();    goto comefrom_int_index; - #endif +     case T_ZERO:    case T_TYPE:    case PIKE_T_RING:    case T_VOID:    case T_FLOAT:    return 0;       case T_OR:    {    struct pike_type *a,*b;
pike.git/src/pike_types.c:5317:       case T_AND:    return low_check_indexing(type->car, index_type, n) &&    low_check_indexing(type->cdr, index_type, n);       case T_NOT:    return low_check_indexing(type->car, index_type, n) != 1;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE: +  case T_ASSIGN: +  case T_SCOPE:    return low_check_indexing(type->cdr, index_type, n);       case T_ARRAY:    if(low_match_types(string_type_string, index_type, 0) &&    low_check_indexing(type->car, index_type, n))    return 1;    /* FALL_THROUGH */    case T_STRING:    return !!low_match_types(int_type_string, index_type, 0);       case T_OBJECT:    {    struct program *p = id_to_program(CDR_TO_INT(type));    if(p)    {    int i = -1;    /* Check against the LFUN types. */ -  if(n->token == F_ARROW) +  if(n && (n->token == F_ARROW))    {    (i = FIND_LFUN(p,LFUN_ARROW))!=-1 ||    (i = FIND_LFUN(p,LFUN_ASSIGN_ARROW));    }else{    (i = FIND_LFUN(p,LFUN_INDEX))!=-1 ||    (i = FIND_LFUN(p,LFUN_ASSIGN_INDEX));    }    if (i != -1) {    if ((type = low_new_check_call(ID_FROM_INT(p, i)->type, index_type,    CALL_NOT_LAST_ARG, NULL))) {
pike.git/src/pike_types.c:5365:       case T_MULTISET:    case T_MAPPING:    /* FIXME: Why -1 and not 0?    *    * - There were complaints when people got compilation errors    * for indexing operations that would always fail.    */    return low_match_types(type->car, index_type, 0) ? 1 : -1;    - #ifdef AUTO_BIGNUM +     case T_INT: - #endif +     case T_PROGRAM:    return !!low_match_types(string_type_string, index_type, 0);       case T_MIXED:    return 1;       default:    return 0;    }   }
pike.git/src/pike_types.c:5413:    case T_AND:    num = low_count_arguments(q->car);    num2 = low_count_arguments(q->cdr);    if(num<0 && num2>0) return num2;    if(num2<0 && num>0) return num;    if(num2<0 && num<0) return ~num<~num2?num:num2;    return num<num2?num:num2;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE: +  case T_ASSIGN: +  case T_SCOPE:    return low_count_arguments(q->cdr);       default: return MAX_INT32;       case T_FUNCTION:    while(q->type == T_FUNCTION)    {    num++;    q = q->cdr;    }
pike.git/src/pike_types.c:5458:    {    case T_OR:    case T_AND:    return MAXIMUM(low_count_arguments(q->car),    low_count_arguments(q->cdr));       default: return 0;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE: +  case T_ASSIGN: +  case T_SCOPE:    return low_minimum_arguments(q->cdr);       case T_FUNCTION:    num = 0;    while(q->type == T_FUNCTION)    {    if(low_match_types(void_type_string, q->car, B_EXACT))    return num;       num++;
pike.git/src/pike_types.c:5985:    }    break;    }    }    if (tmp) free_type(tmp);    if (tmp2) free_type(tmp2);    if (tmp3) free_type(tmp3);    return res;   }    + /** +  * Check whether sval is a valid value for a variable of +  * type type. +  * +  * Returns 1 if ok, and 0 (zero) otherwise. +  */ + static int match_type_svalue(struct pike_type *type, +  int flags, +  struct svalue *sval) + { +  int res = 0; +  struct pike_type *sub; +  loop: +  switch(type->type) { +  case T_SCOPE: +  case T_ASSIGN: +  case PIKE_T_NAME: +  case PIKE_T_ATTRIBUTE: +  type = type->cdr; +  goto loop; +  case T_OR: +  res = match_type_svalue(type->car, 0, sval) || +  match_type_svalue(type->cdr, 0, sval); +  break; +  case T_AND: +  res = match_type_svalue(type->car, 0, sval) || +  match_type_svalue(type->cdr, 0, sval); +  case T_NOT: +  flags ^= CALL_INVERTED_TYPES; +  type = type->car; +  goto loop; +  case T_VOID: +  /* Allow UNDEFINED for voidable arguments. */ +  res = (TYPEOF(*sval) == T_INT) && !sval->u.integer && SUBTYPEOF(*sval); +  break; +  case T_ZERO: +  res = SAFE_IS_ZERO(sval); +  break; +  case PIKE_T_TYPE: +  res = 1; +  break; +  case PIKE_T_PROGRAM: +  case PIKE_T_FUNCTION: +  case T_MANY: +  /* Identify if sval is callable. */ +  res = +  (TYPEOF(*sval) == T_FUNCTION) || +  (TYPEOF(*sval) == T_PROGRAM) || +  (TYPEOF(*sval) == T_ARRAY) || +  (TYPEOF(*sval) == T_OBJECT) || +  (TYPEOF(*sval) == T_TYPE); +  /* FIXME: Check arguments */ +  /* FIXME: Check return type */ +  break; +  case PIKE_T_MIXED: +  res = 1; +  break; +  case PIKE_T_OBJECT: +  if( TYPEOF( *sval ) == PIKE_T_OBJECT ) +  { +  struct object *o = sval->u.object; +  if( o->prog ) +  { +  if( !type->cdr ) +  { +  res = 1; +  } +  else +  { +  struct program *mark = id_to_program( CDR_TO_INT( type ) ); +  if( mark == o->prog ) +  res = 1; +  else if( type->car ) +  res = is_compatible( mark, o->prog ); +  else +  res = implements( mark, o->prog ); +  } +  } +  } +  break; +  case PIKE_T_STRING: +  if( TYPEOF( *sval ) == PIKE_T_STRING ) +  { +  sub = type->car; +  if (sub->type == T_ZERO) +  { +  res = sval->u.string->len == 0; +  } +  else if( sub->type == PIKE_T_INT ) +  { +  struct pike_string *s = sval->u.string; +  INT32 min = CAR_TO_INT( sub ), max = CDR_TO_INT( sub ); +  INT32 string_min, string_max; +  int checked = 0; +  +  check_string_range( s, 1, &string_min, &string_max ); +  +  if( min != MIN_INT32 ) +  { +  if( string_min < min ) +  { +  if( s->size_shift ) +  check_string_range( s, 0, &string_min, &string_max ); +  if( string_min < min ) +  goto do_return; +  checked = 1; +  } +  } +  +  if( max != MIN_INT32 ) +  { +  if( string_max > max ) +  { +  if( s->size_shift && !checked ) +  check_string_range( s, 0, NULL, &string_max ); +  +  if( string_max > max ) +  goto do_return; +  } +  } +  } +  res = 1; +  } +  break; +  case PIKE_T_INT: +  if( TYPEOF( *sval ) == PIKE_T_INT ) +  { +  INT_TYPE current = sval->u.integer; +  INT32 min, max; +  min = CAR_TO_INT( type ); +  max = CDR_TO_INT( type ); +  if( min != MIN_INT32 ) +  { +  if( current < min ) +  break; +  } +  if( max != MAX_INT32 ) +  { +  if( current > max ) +  break; +  } +  res = 1; +  } +  /* FIXME: Objects that emulate integers? */ +  else if( TYPEOF(*sval) == PIKE_T_OBJECT ) +  { +  if( is_bignum_object(sval->u.object) ) +  { +  INT32 min = CAR_TO_INT( type ); +  INT32 max = CDR_TO_INT( type ); +  if( min != MIN_INT32 && max != MAX_INT32 ) +  { +  struct svalue tmp; +  TYPEOF(tmp)=PIKE_T_INT; +  if( min != MIN_INT32 ) +  { +  tmp.u.integer = min; +  if( is_lt( sval, &tmp ) ) +  break; +  } +  if( max != MAX_INT32 ) +  { +  tmp.u.integer = max; +  if( is_gt( sval, &tmp ) ) +  break; +  } +  } +  res = 1; +  } +  } +  break; +  default: +  res = (type->type == TYPEOF(*sval)); +  break; +  } +  do_return: +  if (flags & CALL_INVERTED_TYPES) return !res; +  return res; + } +  + /** +  * Check whether sval is a valid first argument to fun_type. +  * +  * Returns NULL on failure. +  * +  * Returns continuation function type on success. +  */ + struct pike_type *check_call_svalue(struct pike_type *fun_type, +  INT32 flags, +  struct svalue *sval) + { +  struct pike_type *res = NULL; +  struct pike_type *tmp; +  struct pike_type *tmp2; +  INT32 array_cnt = 0; +  int indent = 2; +  + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, "%*scheck_call_svalue(", indent*2, ""); +  simple_describe_type(fun_type); +  fprintf(stderr, ", 0x%08x, %p)...\n", flags, sval); +  } + #endif /* PIKE_DEBUG */ +  +  loop: +  /* Count the number of array levels. */ +  while(fun_type->type == PIKE_T_ARRAY) { +  array_cnt++; +  fun_type = fun_type->car; +  } +  +  switch(fun_type->type) { +  case T_SCOPE: +  /* FIXME: Save and restore the corresponding marker set. */ +  case T_ASSIGN: +  case PIKE_T_NAME: +  fun_type = fun_type->cdr; +  goto loop; +  +  case PIKE_T_ATTRIBUTE: +  fun_type = fun_type->cdr; +  goto loop; +  +  case T_OR: +  res = check_call_svalue(fun_type->car, flags, sval); +  if (!res) { +  fun_type = fun_type->cdr; +  goto loop; +  } +  tmp = check_call_svalue(fun_type->cdr, flags, sval); +  if (!tmp) break; +  res = or_pike_types(tmp2 = res, tmp, 1); +  free_type(tmp); +  free_type(tmp2); +  break; +  +  case T_AND: +  res = check_call_svalue(fun_type->car, flags, sval); +  if (!res) break; +  tmp = check_call_svalue(fun_type->cdr, flags, sval); +  if (!tmp) { +  free_type(res); +  res = NULL; +  break; +  } +  if (res == tmp) { +  /* Common case. */ +  free_type(tmp); +  break; +  } +  /* and_pike_types() doesn't handle and of functions +  * in the way we want here. +  */ +  type_stack_mark(); +  push_finished_type(tmp); +  push_finished_type(res); +  push_type(T_AND); +  free_type(tmp); +  free_type(res); +  res = pop_unfinished_type(); +  break; +  +  case T_NOT: +  fun_type = fun_type->car; +  flags ^= CALL_INVERTED_TYPES; +  goto loop; +  +  case PIKE_T_TYPE: +  /* FIXME: Check that the cast is valid. */ +  type_stack_mark(); +  push_finished_type(fun_type->car); +  push_type(T_VOID); +  push_type(T_MANY); +  res = pop_unfinished_type(); +  break; +  +  case PIKE_T_PROGRAM: +  tmp = low_object_lfun_type(fun_type->car, LFUN_CREATE); +  if (!tmp) { +  /* No create() -- No arguments. */ +  /* FIXME: Multiple cases: +  * Untyped object. function(mixed|void...:obj) +  * Failed to lookup program id. function(mixed|void...:obj) +  * Program does not have a create(). function(:obj) +  * +  * We simply ignore the args. +  */ +  +  type_stack_mark(); +  push_finished_type(fun_type->car); +  push_type(T_MIXED); +  push_type(T_VOID); +  push_type(T_OR); +  push_type(T_MANY); +  fun_type = pop_unfinished_type(); +  } else { +  fun_type = zzap_function_return(tmp, fun_type->car); +  } +  res = check_call_svalue(fun_type, flags, sval); +  free_type(fun_type); +  break; +  +  case PIKE_T_OBJECT: +  fun_type = low_object_lfun_type(fun_type, LFUN_CALL); +  if (fun_type) goto loop; +  +  /* FIXME: Multiple cases: +  * Untyped object. mixed +  * Failed to lookup program id. mixed +  * Program does not have the lfun `()(). NULL +  */ +  +  /* FALL_THROUGH */ +  case PIKE_T_MIXED: +  copy_pike_type(res, mixed_type_string); +  break; +  +  case PIKE_T_FUNCTION: +  /* Note: Use the low variants of pike_types_le and match_types, +  * so that markers get set and kept. */ +  if (match_type_svalue(fun_type->car, flags, sval)) { +  add_ref(res = fun_type->cdr); +  break; +  } +  res = NULL; +  break; +  case T_MANY: +  /* Note: Use the low variants of pike_types_le and match_types, +  * so that markers get set and kept. */ +  if (match_type_svalue(fun_type->car, flags, sval)) { +  add_ref(res = fun_type); +  break; +  } +  res = NULL; +  break; +  default: +  /* Not a callable. */ +  break; +  } +  +  if (!array_cnt || !res) { + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  if (res) { +  fprintf(stderr, "%*s==> ", indent*2, ""); +  simple_describe_type(res); +  } else { +  fprintf(stderr, "%*s==> NULL", indent*2, ""); +  } +  fprintf(stderr, "\n"); +  } + #endif /* PIKE_DEBUG */ +  return res; +  } +  +  type_stack_mark(); +  push_finished_type(res); +  free_type(res); +  while(array_cnt--) { +  push_type(PIKE_T_ARRAY); +  } +  res = pop_type(); +  + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, "%*s==> ", indent*2, ""); +  simple_describe_type(res); +  fprintf(stderr, "\n"); +  } + #endif /* PIKE_DEBUG */ +  +  return res; + } +    /* Check whether arg_type may be used as the type of the first argument    * in a call to fun_type.    *    * The first argument has no OR or AND nodes.    *    * Returns NULL on failure.    *    * Returns continuation function type on success.    */   static struct pike_type *lower_new_check_call(struct pike_type *fun_type,
pike.git/src/pike_types.c:6740:    } else {    tmp = low_get_first_arg_type(arg_type->car->car,    flags|FILTER_KEEP_VOID);    }    type_stack_mark();    push_finished_type(tmp);    free_type(tmp);    push_type(arg_type->type);    return pop_unfinished_type();    } +  /* FALL_THROUGH */ +     case T_ARRAY:    case T_MULTISET:    /* Keep void! */    tmp = low_get_first_arg_type(arg_type->car, flags|FILTER_KEEP_VOID);    type_stack_mark();    push_finished_type(tmp);    free_type(tmp);    push_type(arg_type->type);    return pop_unfinished_type();   
pike.git/src/pike_types.c:7320:    push_type(T_MANY);    return pop_unfinished_type();    }   /* This error is bogus /Hubbe    Pike_fatal("zzap_function_return() called with unexpected value: %d\n",    EXTRACT_UCHAR(a));   */    return NULL;   }    + struct pike_type *get_lax_type_of_svalue( const struct svalue *c ) + { +  struct pike_type *res; +  if (TYPEOF(*c) == T_INT) +  { +  if (c->u.integer) +  copy_pike_type(res, int_type_string); +  else +  copy_pike_type(res, zero_type_string); +  } +  else if (TYPEOF(*c) == T_STRING ) +  copy_pike_type(res, string_type_string); +  else +  return get_type_of_svalue(c); +  +  return res; + } +    struct pike_type *get_type_of_svalue(const struct svalue *s)   {    struct pike_type *ret;    switch(TYPEOF(*s))    {    case T_FUNCTION:    if(SUBTYPEOF(*s) == FUNCTION_BUILTIN)    {    copy_pike_type(ret, s->u.efun->type);    }else{
pike.git/src/pike_types.c:7410:    push_type(T_ZERO);    push_type(T_ZERO);    }    push_type(T_MAPPING);    return pop_unfinished_type();       case T_OBJECT:    type_stack_mark();    if(s->u.object->prog)    { - #ifdef AUTO_BIGNUM +     if(is_bignum_object(s->u.object))    {    push_int_type(MIN_INT32, MAX_INT32);    }    else - #endif +     {    push_object_type(1, s->u.object->prog->id);    }    }else{    /* Destructed object */    push_type(T_ZERO);    }    return pop_unfinished_type();       case T_INT:
pike.git/src/pike_types.c:7501:       case T_TYPE:    type_stack_mark();    push_finished_type(s->u.type);    push_type(T_TYPE);    return pop_unfinished_type();       case T_STRING:    type_stack_mark();    if (s->u.string->len) { -  /* FIXME: Could be extended to detect 7-bit strings, etc. */ -  if (s->u.string->size_shift == 2) { -  push_int_type(MIN_INT32, MAX_INT32); +  INT32 min, max; +  check_string_range( s->u.string, 0, &min, &max ); +  push_int_type(min, max);    } else { -  push_int_type(0, (1<<(8 << s->u.string->size_shift)) - 1); -  } -  } else { +     push_type(T_ZERO);    }    push_type(T_STRING);    return pop_unfinished_type();       default:    type_stack_mark();    push_type(TYPEOF(*s));    return pop_unfinished_type();    }
pike.git/src/pike_types.c:7668:    if(implements_a && implements_b) {    if (implements_mode) {    yyexplain_not_implements(severity_level, implements_a, implements_b);    } else {    yyexplain_not_compatible(severity_level, implements_a, implements_b);    }    }    END_CYCLIC();   }    + /* FIXME: Code duplication! */ + void string_builder_explain_nonmatching_types(struct string_builder *s, +  struct pike_type *type_a, +  struct pike_type *type_b) + { +  DECLARE_CYCLIC();    -  +  implements_a=0; +  implements_b=0; +  implements_mode=0; +  +  /* Note the argument order. */ +  pike_types_le(type_b, type_a); +  + #if 0 +  if(!(implements_a && implements_b && +  type_a->str[0]==T_OBJECT && +  type_b->str[0]==T_OBJECT)) + #endif /* 0 */ +  { +  ref_push_type_value(type_a); +  ref_push_type_value(type_b); +  string_builder_sprintf(s, +  "Expected: %O.\n" +  "Got : %O.\n", +  Pike_sp-2, Pike_sp-1); +  } +  +  /* Protect against circularities. */ +  if (BEGIN_CYCLIC(type_a, type_b)) { +  END_CYCLIC(); +  return; +  } +  SET_CYCLIC_RET(1); +  +  if(implements_a && implements_b) { +  if (implements_mode) { +  string_builder_explain_not_implements(s, implements_a, implements_b); +  } else { +  string_builder_explain_not_compatible(s, implements_a, implements_b); +  } +  } +  END_CYCLIC(); + } +    /******/      static void low_make_pike_type(unsigned char *type_string,    unsigned char **cont);      static void low_make_function_type(unsigned char *type_string,    unsigned char **cont)   {    if (*type_string == T_MANY) {    low_make_pike_type(type_string+1, cont);
pike.git/src/pike_types.c:7691:    return;    }    low_make_pike_type(type_string, cont);    low_make_function_type(*cont, cont);    push_reverse_type(T_FUNCTION);   }      static void low_make_pike_type(unsigned char *type_string,    unsigned char **cont)   { -  unsigned INT32 type; +  unsigned INT32 type = *type_string;    -  switch(type = *type_string) { +  if (type <= MAX_TYPE) { +  /* Remap from old type enumeration to +  * keep compat with output from __parse_pike_type(). +  */ +  type ^= MIN_REF_TYPE; +  } +  +  switch(type) {   #ifdef PIKE_DEBUG    case T_SCOPE:    Pike_fatal("Not supported yet.\n");   #endif    case T_ASSIGN:    if ((type_string[1] < '0') || (type_string[1] > '9')) {    Pike_fatal("low_make_pike_type(): Bad marker: %d\n", type_string[1]);    }    low_make_pike_type(type_string+2, cont);    push_assign_type(type_string[1]);
pike.git/src/pike_types.c:7964:    }   }      static void low_type_to_string(struct pike_type *t)   {    recurse:    switch(t->type) {    case T_ARRAY:    case T_MULTISET:    case T_TYPE: -  case T_NOT: +     case T_PROGRAM: -  +  my_putchar(t->type ^ MIN_REF_TYPE); +  t = t->car; +  goto recurse; +  +  case T_NOT:    my_putchar(t->type); -  /* FALL_THROUGH */ +     t = t->car;    goto recurse;    -  +  case T_MAPPING: +  my_putchar(t->type ^ MIN_REF_TYPE); +  low_type_to_string(t->car); +  t = t->cdr; +  goto recurse; +     case PIKE_T_RING:    case T_TUPLE: -  case T_MAPPING: +     case T_OR:    case T_AND:    my_putchar(t->type);    low_type_to_string(t->car);    t = t->cdr;    goto recurse;    -  +  case T_FLOAT: +  case T_ZERO: +  my_putchar(t->type ^ MIN_REF_TYPE); +  break; +     case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9': -  case T_FLOAT: -  case T_ZERO: +     case T_VOID:    case T_MIXED:    my_putchar(t->type);    break;       case T_OBJECT:    {    INT32 i; -  my_putchar(T_OBJECT); +  my_putchar(T_OBJECT ^ MIN_REF_TYPE);    i = (INT32)CAR_TO_INT(t);    my_putchar( i );    i = (INT32)CDR_TO_INT(t);       if( i > 65535 ) i = 0; /* Not constant between recompilations */       my_putchar((i >> 24) & 0xff);    my_putchar((i >> 16) & 0xff);    my_putchar((i >> 8) & 0xff);    my_putchar(i & 0xff);    }    break;       case T_STRING:    {    if (t->car == int_type_string) { -  my_putchar(T_STRING); +  my_putchar(T_STRING ^ MIN_REF_TYPE);    } else {    my_putchar(PIKE_T_NSTRING);    low_type_to_string(t->car);    }    }    break;       case T_INT:    {    INT32 i; -  my_putchar(T_INT); +  my_putchar(T_INT ^ MIN_REF_TYPE);    i = (INT32)CAR_TO_INT(t);    my_putchar((i >> 24) & 0xff);    my_putchar((i >> 16) & 0xff);    my_putchar((i >> 8) & 0xff);    my_putchar(i & 0xff);    i = (INT32)CDR_TO_INT(t);    my_putchar((i >> 24) & 0xff);    my_putchar((i >> 16) & 0xff);    my_putchar((i >> 8) & 0xff);    my_putchar(i & 0xff);    }    break;       case T_FUNCTION:    case T_MANY: -  my_putchar(T_FUNCTION); +  my_putchar(T_FUNCTION ^ MIN_REF_TYPE);    while(t->type == T_FUNCTION) {    low_type_to_string(t->car);    t = t->cdr;    }    my_putchar(T_MANY);    low_type_to_string(t->car);    t = t->cdr;    goto recurse;       case T_SCOPE:
pike.git/src/pike_types.c:8097: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG   static void gc_mark_external_types(struct callback *cb, void *a, void *b);   static struct callback *pike_type_gc_callback = NULL;   #endif /* PIKE_DEBUG */      void init_types(void)   {    /* Initialize hashtable here. */    pike_type_hash = (struct pike_type **)xalloc(sizeof(struct pike_type *) * -  PIKE_TYPE_HASH_SIZE); -  MEMSET(pike_type_hash, 0, sizeof(struct pike_type *) * PIKE_TYPE_HASH_SIZE); +  (PIKE_TYPE_HASH_SIZE+1)); +  MEMSET(pike_type_hash, 0, sizeof(struct pike_type *) * (PIKE_TYPE_HASH_SIZE+1));    pike_type_hash_size = PIKE_TYPE_HASH_SIZE; -  init_pike_type_blocks(); +        int_type_string = CONSTTYPE(tInt); /* MUST come before string! */    string0_type_string = CONSTTYPE(tStr0);    string_type_string = CONSTTYPE(tStr32);    object_type_string = CONSTTYPE(tObj);    program_type_string = CONSTTYPE(tPrg(tObj));    float_type_string = CONSTTYPE(tFloat);    mixed_type_string = CONSTTYPE(tMix);    array_type_string = CONSTTYPE(tArray);    multiset_type_string = CONSTTYPE(tMultiset);    mapping_type_string = CONSTTYPE(tMapping);    function_type_string = CONSTTYPE(tFunction);    type_type_string = CONSTTYPE(tType(tMix));    void_type_string = CONSTTYPE(tVoid);    zero_type_string = CONSTTYPE(tZero); -  +  enumerable_type_string = CONSTTYPE(tOr3(tString,tInt,tFloat));    any_type_string = CONSTTYPE(tOr(tVoid,tMix));    weak_type_string = CONSTTYPE(tOr4(tArray,tMultiset,tMapping,    tFuncV(tNone,tZero,tOr(tMix,tVoid))));    sscanf_type_string = CONSTTYPE(tFuncV(tStr tAttr("sscanf_format", tStr),    tAttr("sscanf_args", tMix), tIntPos));    sscanf_76_type_string = CONSTTYPE(tFuncV(tStr tAttr("sscanf_76_format", tStr),    tAttr("sscanf_args", tMix), tIntPos));    /* add_ref(weak_type_string); *//* LEAK */      #ifdef PIKE_DEBUG
pike.git/src/pike_types.c:8169:    free_type(mapping_type_string);    mapping_type_string = NULL;    free_type(type_type_string);    type_type_string = NULL;    free_type(mixed_type_string);    mixed_type_string = NULL;    free_type(void_type_string);    void_type_string = NULL;    free_type(zero_type_string);    zero_type_string = NULL; +  free_type(enumerable_type_string); +  enumerable_type_string = NULL;    free_type(any_type_string);    any_type_string = NULL;    free_type(weak_type_string);    weak_type_string = NULL;    free_type(sscanf_type_string);    sscanf_type_string = NULL;    free_type(sscanf_76_type_string);    sscanf_76_type_string = NULL;   #ifdef PIKE_DEBUG    remove_callback(pike_type_gc_callback);
pike.git/src/pike_types.c:8200:    */    pike_type_hash = NULL;    }    /* Don't do this, it messes up stuff...    *    * It's needed for dmalloc to survive.    */    pike_type_hash_size = 0;      #ifdef DO_PIKE_CLEANUP -  free_all_pike_type_blocks(); +  ba_destroy(&type_allocator);   #endif /* DO_PIKE_CLEANUP */   }      PMOD_EXPORT void *find_type(struct pike_type *t,    void *(*cb)(struct pike_type *))   {    void *res;    if (!t) return NULL;       res = cb(t);
pike.git/src/pike_types.c:8412: Inside #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) and #if defined(PIKE_DEBUG)
   if (mapping_type_string)    gc_mark_external(mapping_type_string, " as mapping_type_string");    if (function_type_string)    gc_mark_external(function_type_string, " as function_type_string");    if (type_type_string)    gc_mark_external(type_type_string, " as type_type_string");    if (void_type_string)    gc_mark_external(void_type_string, " as void_type_string");    if (zero_type_string)    gc_mark_external(zero_type_string, " as zero_type_string"); +  if (enumerable_type_string) +  gc_mark_external(enumerable_type_string, " as enumerable_type_string");    if (any_type_string)    gc_mark_external(any_type_string, " as any_type_string");    if (weak_type_string)    gc_mark_external(weak_type_string, " as weak_type_string");      #ifdef DO_PIKE_CLEANUP    {    struct pike_type_location *t = all_pike_type_locations;    while(t) {    gc_mark_external (t->t, " as constant type");
pike.git/src/pike_types.c:8490: Inside #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) and #if defined(PIKE_DEBUG)
   "Unhandled type-node: %d\n", t->type);    break;   #endif /* PIKE_DEBUG */    }    } GC_LEAVE;   }      void gc_check_all_types (void)   {    unsigned INT32 e; -  for(e=0;e<pike_type_hash_size;e++) +  for(e=0;e<=pike_type_hash_size;e++)    {    struct pike_type *t;    for(t = pike_type_hash[e]; t; t=t->next) gc_check_type (t);    }   }      #endif /* PIKE_DEBUG || DO_PIKE_CLEANUP */