pike.git / src / pike_types.c

version» Context lines:

pike.git/src/pike_types.c: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.   */      #include "global.h"   #include <ctype.h>   #include "svalue.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_allocator.h" -  + #include "bitvector.h" + #include "gc_header.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 - #define NO_MAX_ARGS 4 - #define NO_SHORTCUTS 8 +     - #define TYPE_GROUPING -  - /* -  * Flags used by pike_types_le() -  */ - #define LE_WEAK_OBJECTS 1 /* Perform weaker checking of objects. */ - #define LE_A_B_SWAPPED 2 /* Argument A and B have been swapped. -  * Relevant for markers. -  */ - #ifdef TYPE_GROUPING - #define LE_A_GROUPED 4 /* Argument A has been grouped. -  * Perform weaker checking for OR-nodes. */ - #define LE_B_GROUPED 8 /* Argument B has been grouped. -  * Perform weaker checking for OR-nodes. */ - #define LE_A_B_GROUPED 12 /* Both the above two flags. */ - #endif - #define LE_USE_HANDLERS 16 /* Call handlers if appropriate. */ - #define LE_EXPLICIT_ZERO 32 /* Zero is not subtype of all others. */ -  - /* -  * Flags used by low_get_first_arg_type() -  * -  * Note that these differ for the flags to get_first_arg_type(). -  */ - #define FILTER_KEEP_VOID 1 /* Keep void during the filtering. */ -  - /* -  * 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 65535 + /* 256Kb */ + #define PIKE_TYPE_HASH_SIZE 32767    -  +    #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;   PMOD_EXPORT struct pike_type *int_type_string;   PMOD_EXPORT struct pike_type *float_type_string;   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 *inheritable_type_string; + PMOD_EXPORT struct pike_type *typeable_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; + PMOD_EXPORT struct pike_type *utf8_type_string;    -  + PMOD_EXPORT struct pike_string *literal_string_string; + PMOD_EXPORT struct pike_string *literal_int_string; + PMOD_EXPORT struct pike_string *literal_float_string; + PMOD_EXPORT struct pike_string *literal_function_string; + PMOD_EXPORT struct pike_string *literal_object_string; + PMOD_EXPORT struct pike_string *literal_program_string; + PMOD_EXPORT struct pike_string *literal_array_string; + PMOD_EXPORT struct pike_string *literal_multiset_string; + PMOD_EXPORT struct pike_string *literal_mapping_string; + PMOD_EXPORT struct pike_string *literal_type_string; + PMOD_EXPORT struct pike_string *literal_mixed_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];      static struct program *implements_a;   static struct program *implements_b;   static int implements_mode;      #ifdef PIKE_DEBUG - void TYPE_STACK_DEBUG(const char *fun) + void TYPE_STACK_DEBUG(const char *UNUSED(fun))   {   #if 0    fprintf(stderr, "%25s(): stack_depth:%ld mark_stack_depth:%ld\n",    fun, (long)(Pike_compiler->type_stackp - type_stack),    (long)(Pike_compiler->pike_type_mark_stackp - pike_type_mark_stack));   #endif /* 0 */   }   #endif /* PIKE_DEBUG */      static void clear_markers(void)
pike.git/src/pike_types.c:278:    * a many argument just have a MANY node, and no FUNCTION node.    *    */   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 struct pike_type * alloc_pike_type(void) { +  struct pike_type *t = ba_alloc(&type_allocator); +  gc_init_marker(t); +  return t;   }      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)
pike.git/src/pike_types.c:339:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    /* Free car & cdr */    free_type(car);    t = (struct pike_type *) cdr;    debug_free_type_preamble (t);    goto loop;    +  case PIKE_T_AUTO: +  if (!car) +  break; +  /* FALLTHRU */    case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING:    /* Free car */    t = (struct pike_type *) car;    debug_free_type_preamble (t);    goto loop;
pike.git/src/pike_types.c:402:   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.    */    struct pike_type *t;    unsigned INT32 index, -  hash = DO_NOT_WARN((unsigned INT32) +  hash = (unsigned INT32)    ((ptrdiff_t)type*0x10204081)^    (0x8003*PTR_TO_INT(car))^ -  ~(0x10001*PTR_TO_INT(cdr))); +  ~(0x10001*PTR_TO_INT(cdr));       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 */
pike.git/src/pike_types.c:516:       case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING:    /* Free car */    free_type((struct pike_type *)debug_malloc_pass(car));    break; +  case PIKE_T_AUTO: +  if( car ) +  free_type((struct pike_type *)debug_malloc_pass(car)); +  break;       case T_SCOPE:    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));
pike.git/src/pike_types.c:566:    }      #ifdef PIKE_DEBUG    if ((type == T_OR) && (car->type == T_OR)) {    Pike_fatal("Invalid CAR to OR node.\n");    }   #endif       debug_malloc_pass(t = ba_alloc(&type_allocator));    - #ifdef ATOMIC_SVALUE -  t->ref_type = PIKE_T_TYPE; - #endif +     t->refs = 0; -  +  gc_init_marker(t);    add_ref(t); /* For DMALLOC... */    t->type = type;    t->flags = 0;    t->car = car;    t->cdr = cdr;       t->hash = hash;    t->next = pike_type_hash[index];    pike_type_hash[index] = t;   
pike.git/src/pike_types.c:615: Inside #if defined(DEBUG_MALLOC)
   debug_malloc_pass(car);    debug_malloc_pass(cdr);    break;       case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING: +  case PIKE_T_AUTO:    debug_malloc_pass(car);    break;       case T_ASSIGN:    t->flags |= PT_FLAG_ASSIGN_0 << PTR_TO_INT(car); -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_SCOPE:    debug_malloc_pass(cdr);    break;       case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    debug_malloc_pass(car);    debug_malloc_pass(cdr);    break;   
pike.git/src/pike_types.c:669:       return t;   }      #ifdef DEBUG_MALLOC   #define mk_type(T,CAR,CDR,FLAG) ((struct pike_type *)debug_malloc_pass(debug_mk_type(T,CAR,CDR,FLAG)))   #else /* !DEBUG_MALLOC */   #define mk_type debug_mk_type   #endif /* DEBUG_MALLOC */    - #ifdef PIKE_DEBUG - void debug_check_type_string(struct pike_type *s) - { -  /* FIXME: Add verification code here */ - } + struct pike_type **type_stack; + struct pike_type ***pike_type_mark_stack;    - #endif /* PIKE_DEBUG */ -  - struct pike_type *type_stack[PIKE_TYPE_STACK_SIZE]; - struct pike_type **pike_type_mark_stack[PIKE_TYPE_STACK_SIZE/4]; -  +    ptrdiff_t pop_stack_mark(void)   {    Pike_compiler->pike_type_mark_stackp--;    if(Pike_compiler->pike_type_mark_stackp<pike_type_mark_stack)    Pike_fatal("Type mark stack underflow\n");       TYPE_STACK_DEBUG("pop_stack_mark");       return Pike_compiler->type_stackp - *Pike_compiler->pike_type_mark_stackp;   }
pike.git/src/pike_types.c:711:   struct pike_type *debug_peek_type_stack(void)   {    return *(Pike_compiler->type_stackp);   }      void debug_push_int_type(INT_TYPE min, INT_TYPE max)   {   #if SIZEOF_INT_TYPE > 4   /* a bit kludgy: should maybe really allow 64 bit INT_TYPE */   /* see also extract_type_int */ -  +     if (min<MIN_INT32) min=MIN_INT32;    else if (min>MAX_INT32) min=MAX_INT32;    if (max<MIN_INT32) max=MIN_INT32;    else if (max>MAX_INT32) max=MAX_INT32; -  - #if 0 -  if (min!=(INT32)min || -  max!=(INT32)max) -  Pike_fatal("push_int_type(): int outside INT32 range (sorry)" -  " (%"PRINTPIKEINT"d..%"PRINTPIKEINT"d)\n", -  min,max); +    #endif - #endif +     - #ifdef PIKE_DEBUG -  if (min > max) + #ifdef PIKE_DEBUG /* FIXME: Kludge to support 2^32-1 */ +  if (((min>0 && max>0) || (min<0 && max<0)) && min > max)    Pike_fatal("push_int_type(): Bad integer range:"    " min:%"PRINTPIKEINT"d, max:%"PRINTPIKEINT"d.\n",    min, max);   #endif /* PIKE_DEBUG */       if (!min && !max) {    /* Special case... */    push_type(T_ZERO);    } else {    *(++Pike_compiler->type_stackp) = mk_type(T_INT,    (void *)(ptrdiff_t)min,    (void *)(ptrdiff_t)max, 0);    }    TYPE_STACK_DEBUG("push_int_type");   }    -  + static int (*program_id_to_id)(int) = NULL; +  + PMOD_EXPORT void set_program_id_to_id( int (*to)(int) ) + { +  program_id_to_id = to; + } +    void debug_push_object_type(int flag, INT32 id)   { -  +  if( program_id_to_id ) +  id = program_id_to_id(id);    *(++Pike_compiler->type_stackp) = mk_type(T_OBJECT,    (void *)(ptrdiff_t)flag,    (void *)(ptrdiff_t)id, 0);       TYPE_STACK_DEBUG("push_object_type");   }      void debug_push_object_type_backwards(int flag, INT32 id)   {    push_object_type(flag, id);
pike.git/src/pike_types.c:813:    TYPE_STACK_DEBUG("push_type_name");   }      void debug_push_finished_type(struct pike_type *t)   {    copy_pike_type(*(++Pike_compiler->type_stackp), t);       TYPE_STACK_DEBUG("push_finished_type");   }    - /* Only to be used from {or,and}_pike_types() et al! */ - static void push_joiner_type(unsigned int type) - { -  /* fprintf(stderr, "push_joiner_type(%d)\n", type); */ -  -  switch(type) { -  case T_OR: -  case T_AND: -  /* Special case: Check if the two top elements are equal. */ -  if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) { -  free_type(*(Pike_compiler->type_stackp--)); -  return; -  } -  /* Make a new type of the top two types. */ -  --Pike_compiler->type_stackp; - #ifdef PIKE_DEBUG -  if ((*Pike_compiler->type_stackp+1)->type == type) { -  Pike_fatal("Invalid CAR to push_joiner_type().\n"); -  } - #endif /* PIKE_DEBUG */ -  *Pike_compiler->type_stackp = mk_type(type, -  *(Pike_compiler->type_stackp+1), -  *Pike_compiler->type_stackp, -  PT_COPY_BOTH); -  break; -  default: -  Pike_fatal("Illegal joiner type: %d\n", type); -  } - } -  +    static void push_reverse_joiner_type(unsigned int type)   {    /* fprintf(stderr, "push_reverse_joiner_type(%d)\n", type); */       switch(type) {    case T_OR:    case T_AND:    /* Special case: Check if the two top elements are equal. */    if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) {    free_type(*(Pike_compiler->type_stackp--));
pike.git/src/pike_types.c:908:    return;    }    if (type == T_OR) {    struct pike_type *t1 = *(Pike_compiler->type_stackp--);    struct pike_type *t2 = *(Pike_compiler->type_stackp--);    low_or_pike_types(t1, t2, 0);    free_type(t2);    free_type(t1);    return;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case PIKE_T_RING:    /* Make a new type of the top two types. */    --Pike_compiler->type_stackp;    *Pike_compiler->type_stackp = mk_type(type,    *(Pike_compiler->type_stackp+1),    *Pike_compiler->type_stackp,    PT_COPY_BOTH);    break;    -  +  case T_PROGRAM: +  if ((*Pike_compiler->type_stackp)->type != T_OBJECT) { +  struct pike_type *t = (*Pike_compiler->type_stackp); +  while ((t->type == PIKE_T_NAME) || (t->type == PIKE_T_ATTRIBUTE)) { +  t = t->cdr; +  } +  if (t->type != T_OBJECT) { +  /* Not a program type, convert it to a type type. */ +  type = T_TYPE; +  } +  } +  /* FALLTHRU */    case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE: -  case T_PROGRAM: +     case T_STRING: -  +  case PIKE_T_AUTO:    /* Make a new type of the top type, and put it in car. */    *Pike_compiler->type_stackp = mk_type(type,    *Pike_compiler->type_stackp, NULL,    PT_COPY_CAR);    break;       case T_SCOPE:    case T_ASSIGN:    case T_INT:    case T_OBJECT:
pike.git/src/pike_types.c:1012:    /* Both car & cdr. */    push_finished_type(top->cdr);    push_finished_type(top->car);    break;    case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING: +  case PIKE_T_AUTO:    /* car */    push_finished_type(top->car);    break;    case T_SCOPE:    case T_ASSIGN:    /* cdr */    push_finished_type(top->cdr);    break;    case T_INT:    case T_OBJECT:
pike.git/src/pike_types.c:1373:    if (field & BIT_FLOAT) {    push_type(T_FLOAT);    push_type(T_OR);    }    }    }   }      INT32 extract_type_int(char *p)   { -  int e; -  INT32 ret=0; -  for(e=0;e<(int)sizeof(INT32);e++) -  ret=(ret<<8) | EXTRACT_UCHAR(p+e); -  return ret; +  return get_unaligned_be32(p);   }      struct pike_type *debug_pop_unfinished_type(void)   {    ptrdiff_t len;       len = pop_stack_mark();       if (len != 1) {    Pike_fatal("pop_unfinished_type(): Unexpected len: %"PRINTPTRDIFFT"d\n", len);
pike.git/src/pike_types.c:1402:    return *(Pike_compiler->type_stackp--);   }      /******/      static struct pike_string *internal_parse_type_string(const char **_s)   {    const unsigned char **s = (const unsigned char **)_s;    const unsigned char *p;    struct string_builder tmp; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s != '\"') yyerror("Expected '\"'.");    else    ++*s;    init_string_builder(&tmp, 0);    p = *s;    while(1) {    int c;    do {    c = *p++;    } while ((c > '\\') || ((c != '\"') && (c != '\\') && (c != '\n')));
pike.git/src/pike_types.c:1441:    }    return finish_string_builder(&tmp);   }      static void internal_parse_typeA(const char **_s)   {    char buf[80];    unsigned int len;    const unsigned char **s = (const unsigned char **)_s;    -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;       for(len=0;isidchar(EXTRACT_UCHAR(s[0]+len));len++)    {    if(len>=sizeof(buf)-1) {    my_yyerror("Buffer overflow in parse_type(\"%s\") (limit %"PRINTSIZET"d).",    *s, sizeof(buf));    push_type(T_MIXED);    return;    }    buf[len] = s[0][len];
pike.git/src/pike_types.c:1465:       switch(buf[0])    {    case 'z':    if(!strcmp(buf,"zero")) { push_type(T_ZERO); break; }    goto bad_type;       case 'i':    if(!strcmp(buf,"int"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s=='(')    {    INT32 min,max;    ++*s; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if (**s != '.') { -  min=STRTOL((const char *)*s,(char **)s,0); -  while(ISSPACE(**s)) ++*s; +  min=strtol((const char *)*s,(char **)s,0); +  while(isspace(**s)) ++*s;    } else {    min = MIN_INT32;    }    if(s[0][0]=='.' && s[0][1]=='.')    s[0]+=2;    else {    yyerror("Missing .. in integer type.");    }    -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if (**s != ')') { -  max=STRTOL((const char *)*s,(char **)s,0); -  while(ISSPACE(**s)) ++*s; +  max=strtol((const char *)*s,(char **)s,0); +  while(isspace(**s)) ++*s;    } else {    max = MAX_INT32;    }       if(**s != ')') yyerror("Missing ')' in integer range.");    else    ++*s;    push_int_type(min, max);    }else{    push_int_type(MIN_INT32, MAX_INT32);    }    break;    }    goto bad_type;       case 'f':    if(!strcmp(buf,"function"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    int nargs = 0;    ++*s; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    while(1)    {    if(**s == ':')    {    push_type(T_VOID);    break;    }    internal_parse_type(_s);    if(**s==',')    {    nargs++;    ++*s; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    }    else if(s[0][0]=='.' && s[0][1]=='.' && s[0][2]=='.')    {    *s+=3; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s != ':') {    yyerror("Missing ':' after ... in function type.");    --*s;    }    break;    } else {    nargs++;    }    }    /* Skip the colon. */
pike.git/src/pike_types.c:1567:    push_type(T_MANY);    }    break;    }    if(!strcmp(buf,"float")) { push_type(T_FLOAT); break; }    goto bad_type;       case 'o':    if(!strcmp(buf,"object"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(') /* object({,is,implements} {id,this_program}) */    {    int is = 0, id;    ++*s; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if( **s != 'i' )    goto no_is_implements;    ++*s;    if( **s == 's' ) {    ++*s;    if (**s != ' ') {    goto bad_type;    }    is = 1;    ++*s;    } else {    if (strncmp((const char *)*s, "mplements ", 10)) {    goto bad_type;    }    *s += 10;    } -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    no_is_implements:    if( !**s )    goto bad_type;    if (!strncmp((const char *)*s, "this_program", 12)) {    id = Pike_compiler->new_program->id;    *s += 12;    } else {    id = atoi( (const char *)*s );    while( **s >= '0' && **s <= '9' )    ++*s;    } -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if( !**s || **s != ')' )    goto bad_type;    ++*s;    push_object_type(is, id);    }    else    push_object_type(0, 0);    break;    }    goto bad_type;
pike.git/src/pike_types.c:1625:    if(!strcmp(buf,"program")) {    push_object_type(0, 0);    push_type(T_PROGRAM);    break;    }    goto bad_type;          case 's':    if(!strcmp(buf,"string")) { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    INT32 min,max;    ++*s; -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if (**s != '.') { -  min=STRTOL((const char *)*s,(char **)s,0); -  while(ISSPACE(**s)) ++*s; +  min=strtol((const char *)*s,(char **)s,0); +  while(isspace(**s)) ++*s;    } else {    min = MIN_INT32;    }    if(s[0][0]=='.' && s[0][1]=='.')    s[0]+=2;    else {    yyerror("Missing .. in integer type.");    }    -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if (**s != ')') { -  max=STRTOL((const char *)*s,(char **)s,0); -  while(ISSPACE(**s)) ++*s; +  max=strtol((const char *)*s,(char **)s,0); +  while(isspace(**s)) ++*s;    } else {    max = MAX_INT32;    }    if(**s != ')') yyerror("Missing ')' in string width.");    else    ++*s;    push_int_type(min, max);    } else {    push_finished_type(int_type_string);    }
pike.git/src/pike_types.c:1669:    }    goto bad_type;       case 'v':    if(!strcmp(buf,"void")) { push_type(T_VOID); break; }    goto bad_type;       case 't':    if (!strcmp(buf,"tuple"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    ++*s;    internal_parse_type(_s);    if(**s != ',') yyerror("Expected ','.");    else    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else
pike.git/src/pike_types.c:1696:    break;    }    /* FIXME: Handle type(T) */    if(!strcmp(buf,"type")) { push_type(T_MIXED); push_type(T_TYPE); break; }    goto bad_type;       case 'm':    if(!strcmp(buf,"mixed")) { push_type(T_MIXED); break; }    if(!strcmp(buf,"mapping"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    ++*s;    internal_parse_type(_s);    if(**s != ':') yyerror("Expected ':'.");    else    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else    ++*s;    }else{    push_type(T_MIXED);    push_type(T_MIXED);    }    push_reverse_type(T_MAPPING);    break;    }    if(!strcmp(buf,"multiset"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else    ++*s;    }else{    push_type(T_MIXED);    }
pike.git/src/pike_types.c:1740:    }    goto bad_type;       case 'u':    if(!strcmp(buf,"unknown")) { push_type(PIKE_T_UNKNOWN); break; }    goto bad_type;       case 'a':    if(!strcmp(buf,"array"))    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else    ++*s;    }else{    push_type(T_MIXED);    }    push_type(T_ARRAY);    break;    }    goto bad_type;       case '_':    if (!strcmp(buf, "__attribute__")) { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    struct pike_string *attr;    ++*s;    attr = internal_parse_type_string(_s); -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s != ',') yyerror("Expected ','.");    else    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else    ++*s;    push_type_attribute(attr);    free_string(attr);    }else{    push_type(T_MIXED);    }    break;    } else if (!strcmp(buf, "__deprecated__")) {    struct pike_string *deprecated_string;    MAKE_CONST_STRING(deprecated_string, "deprecated"); -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s == '(')    {    ++*s;    internal_parse_type(_s);    if(**s != ')') yyerror("Expected ')'.");    else    ++*s;    }else{    push_type(T_MIXED);    }
pike.git/src/pike_types.c:1810:    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':    if(atoi(buf)<10)    { -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;    if(**s=='=')    {    ++*s;    internal_parse_type(_s);    push_assign_type(buf[0]);    }else{    push_type(buf[0]);    }    break;    } -  +  /* FALLTHRU */       default:    bad_type:    push_type(T_MIXED);    my_yyerror("Couldn't parse type. (%s).", buf);    }    -  while(ISSPACE(**s)) ++*s; +  while(isspace(**s)) ++*s;   }         static void internal_parse_typeB(const char **s)   { -  while(ISSPACE(EXTRACT_UCHAR(*s))) ++*s; +  while(isspace(EXTRACT_UCHAR(*s))) ++*s;    switch(**s)    {    case '!':    ++*s;    internal_parse_typeB(s);    push_type(T_NOT);    break;       case '(':    ++*s;    internal_parse_type(s); -  while(ISSPACE(EXTRACT_UCHAR(*s))) ++*s; +  while(isspace(EXTRACT_UCHAR(*s))) ++*s;    if(**s != ')') {    yyerror("Expected ')' in type.");    }    ++*s;    break;       default:       internal_parse_typeA(s);    }   }      static void internal_parse_typeCC(const char **s)   {    internal_parse_typeB(s);    -  while(ISSPACE(EXTRACT_UCHAR(*s))) ++*s; +  while(isspace(EXTRACT_UCHAR(*s))) ++*s;       while(**s == '*')    {    ++*s; -  while(ISSPACE(EXTRACT_UCHAR(*s))) ++*s; +  while(isspace(EXTRACT_UCHAR(*s))) ++*s;    push_type(T_ARRAY);    }   }      static void internal_parse_typeC(const char **s)   {    internal_parse_typeCC(s);       if(**s == '&')    {
pike.git/src/pike_types.c:2100:    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))) { +  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {    int j = 0;    while (max) {    max >>= 1;    j++;    }    fprintf(stderr, "%dbit", j);    } else {    if (min != MIN_INT32) {    fprintf(stderr, "%d", min);    }
pike.git/src/pike_types.c:2135:    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))) { +  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {    int j = 0;    while (max) {    max >>= 1;    j++;    }    fprintf(stderr, "%dbit", j);    } else {    if (min != MIN_INT32) {    fprintf(stderr, "%d", min);    }
pike.git/src/pike_types.c:2242:    fprintf(stderr, ")");    break;    case T_NOT:    fprintf(stderr, "not(");    simple_describe_type(s->car);    fprintf(stderr, ")");    break;    case T_VOID: fprintf(stderr, "void"); break;    case T_ZERO: fprintf(stderr, "zero"); break;    case T_MIXED: fprintf(stderr, "mixed"); break; -  +  case PIKE_T_AUTO: +  fprintf(stderr, "auto"); +  if (s->car && (s->car->type != T_ZERO)) { +  fprintf(stderr, "("); +  simple_describe_type(s->car); +  fprintf(stderr, ")"); +  } +  break;    default:    fprintf(stderr, "Unknown type node: %d, %p:%p",    s->type, s->car, s->cdr);   #ifdef DEBUG_MALLOC    debug_malloc_dump_references(s, 0, 2, 0);   #endif    break;    }    if (s->flags) {    fprintf(stderr, "[%06x]", s->flags);    }    } else {    fprintf(stderr, "NULL");    }   }    - static void low_describe_type(struct pike_type *t) + void low_describe_type(struct string_builder *s, struct pike_type *t)   { -  char buffer[100]; -  +     check_c_stack(1024); -  /**** FIXME: ****/ +     switch(t->type)    {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9': -  my_putchar(t->type); +  string_builder_putchar(s, t->type);    break;       case T_ASSIGN: -  my_putchar('('); -  my_putchar('0' + CAR_TO_INT(t)); -  my_putchar('='); -  my_describe_type(t->cdr); -  my_putchar(')'); +  string_builder_sprintf(s, "(%c=%T)", '0' + CAR_TO_INT(t), t->cdr);    break;       case T_SCOPE: -  my_strcat("scope("); -  my_putchar('0' + CAR_TO_INT(t)); -  my_putchar(','); -  my_describe_type(t->cdr); -  my_putchar(')'); +  string_builder_sprintf(s, "scope(%c,%T)", '0' + CAR_TO_INT(t), t->cdr);    break;       case T_TUPLE: -  my_putchar('['); -  my_describe_type(t->car); -  my_putchar(','); -  my_describe_type(t->cdr); -  my_putchar(']'); +  string_builder_sprintf(s, "[%T,%T]", t->car, t->cdr);    break;    -  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_VOID: string_builder_strcat(s, "void"); break; +  case T_ZERO: string_builder_strcat(s, "zero"); break; +  case T_MIXED: string_builder_strcat(s, "mixed"); break; +  case PIKE_T_UNKNOWN: string_builder_strcat(s, "unknown"); break;    case T_INT:    {    INT32 min=CAR_TO_INT(t);    INT32 max=CDR_TO_INT(t); -  my_strcat("int"); +     -  if (!min && max && !(max & (max+1))) { +  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {    int j = 0;    while (max) {    max >>= 1;    j++;    } -  sprintf(buffer, "(%dbit)", j); -  my_strcat(buffer); +  string_builder_sprintf(s, "int(%dbit)", j);    } else if(min!=MIN_INT32 || max!=MAX_INT32) { -  sprintf(buffer,"(%ld..%ld)",(long)min,(long)max); -  my_strcat(buffer); +  string_builder_sprintf(s, "int(%ld..%ld)", (long)min, (long)max); +  } else { +  string_builder_strcat(s, "int");    }    break;    } -  case T_FLOAT: my_strcat("float"); break; +  case T_FLOAT: string_builder_strcat(s, "float"); break;    case T_PROGRAM:    if ((t->car->type == T_OBJECT) &&    (!t->car->cdr)) { -  my_strcat("program"); +  string_builder_strcat(s, "program");    } else { -  my_strcat("program("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "program(%T)", t->car);    }    break;    case T_OBJECT:    if (t->cdr)    { -  dynamic_buffer save_buf; -  ONERROR err; -  struct svalue s; +  struct svalue sval;    if (t->car) { -  my_strcat("object(is "); +  string_builder_strcat(s, "object(is ");    } else { -  my_strcat("object(implements "); +  string_builder_strcat(s, "object(implements ");    }    /* We need to save the global buffer, in case id_to_program()    * starts running Pike code. */ -  save_buffer(&save_buf); -  SET_ONERROR(err, restore_buffer, &save_buf); -  s.u.program = id_to_program(CDR_TO_INT(t)); -  CALL_AND_UNSET_ONERROR(err); -  if (s.u.program) { -  SET_SVAL_TYPE(s, T_PROGRAM); -  SET_SVAL_SUBTYPE(s, 0); -  describe_svalue(&s, 0, NULL); -  my_strcat(")"); +  sval.u.program = id_to_program(CDR_TO_INT(t)); +  if (sval.u.program) { +  SET_SVAL_TYPE(sval, T_PROGRAM); +  SET_SVAL_SUBTYPE(sval, 0); +  string_builder_sprintf(s, "%O)", &sval);    } else { -  char buffer[100]; -  sprintf(buffer,"%"PRINTPTRDIFFT"d)", -  CDR_TO_INT(t)); -  my_strcat(buffer); +  string_builder_sprintf(s, "%"PRINTPTRDIFFT"d)", CDR_TO_INT(t));    }    }else{ -  my_strcat("object"); +  string_builder_strcat(s, "object");    }    break;       case T_STRING:    {    INT32 min;    INT32 max;    t = t->car; -  my_strcat("string"); +     if (t->type == T_ZERO) { -  my_strcat("(zero)"); +  string_builder_strcat(s, "string(zero)");    } else if (t != int_type_string) { -  my_strcat("("); +  string_builder_strcat(s, "string(");    while (t->type == T_OR) {    struct pike_type *char_type = t->car;    while(char_type->type == T_ASSIGN) {    char_type = char_type->cdr;    }    if (char_type->type != T_INT) { -  low_describe_type(char_type); +  low_describe_type(s, char_type);    } else {    min = CAR_TO_INT(char_type);    max = CDR_TO_INT(char_type); -  if (!min && max && !(max & (max+1))) { +  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {    int j = 0;    while (max) {    max >>= 1;    j++;    } -  sprintf(buffer, "%dbit", j); -  my_strcat(buffer); +  string_builder_sprintf(s, "%dbit", j);    } else {    if (min != MIN_INT32) { -  sprintf(buffer, "%d", min); -  my_strcat(buffer); +  string_builder_sprintf(s, "%d", min);    } -  my_strcat(".."); +  string_builder_strcat(s, "..");    if (max != MAX_INT32) { -  sprintf(buffer, "%d", max); -  my_strcat(buffer); +  string_builder_sprintf(s, "%d", max);    }    }    } -  my_strcat(" | "); +  string_builder_strcat(s, " | ");    t = t->cdr;    }    while(t->type == T_ASSIGN) {    t = t->cdr;    }    if (t->type != T_INT) { -  low_describe_type(t); +  low_describe_type(s, t);    } else {    min = CAR_TO_INT(t);    max = CDR_TO_INT(t); -  if (!min && max && !(max & (max+1))) { +  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {    int j = 0;    while (max) {    max >>= 1;    j++;    } -  sprintf(buffer, "%dbit", j); -  my_strcat(buffer); +  string_builder_sprintf(s, "%dbit", j);    } else {    if (min != MIN_INT32) { -  sprintf(buffer, "%d", min); -  my_strcat(buffer); +  string_builder_sprintf(s, "%d", min);    } -  my_strcat(".."); +  string_builder_strcat(s, "..");    if (max != MAX_INT32) { -  sprintf(buffer, "%d", max); -  my_strcat(buffer); +  string_builder_sprintf(s, "%d", max);    }    }    } -  my_strcat(")"); +  string_builder_putchar(s, ')'); +  } else { +  string_builder_strcat(s, "string");    }    break;    }    case T_TYPE: -  my_strcat("type("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "type(%T)", t->car);    break;       case PIKE_T_NAME: -  if (!((struct pike_string *)t->car)->size_shift) { -  my_strcat("{ "); -  my_binary_strcat(((struct pike_string *)t->car)->str, -  ((struct pike_string *)t->car)->len); -  my_strcat(" = "); -  my_describe_type(t->cdr); -  my_strcat(" }"); -  } else { -  my_describe_type(t->cdr); -  } +  string_builder_sprintf(s, "{ %S = %T }", +  (struct pike_string *)t->car, t->cdr);    break;       case PIKE_T_ATTRIBUTE: -  if (!((struct pike_string *)t->car)->size_shift) { +  {    struct pike_string *deprecated;    MAKE_CONST_STRING(deprecated, "deprecated");    if (((struct pike_string *)t->car) == deprecated) { -  my_strcat("__deprecated__("); +  string_builder_sprintf(s, "__deprecated__(%T)", t->cdr); +  } else if (t == utf8_type_string) { +  string_builder_sprintf(s, "utf8_string");    } else { -  my_strcat("__attribute__(\""); -  my_binary_strcat(((struct pike_string *)t->car)->str, -  ((struct pike_string *)t->car)->len); -  my_strcat("\", "); +  struct svalue sval; +  SET_SVAL(sval, PIKE_T_STRING, 0, string, +  (struct pike_string *)t->car); +  string_builder_sprintf(s, "__attribute__(%O, %T)", &sval, t->cdr);    } -  my_describe_type(t->cdr); -  my_strcat(")"); -  } else { -  my_describe_type(t->cdr); +     }    break;       case T_FUNCTION:    case T_MANY:    { -  int s; -  my_strcat("function"); +     if(t->type == T_MANY &&    t->cdr->type == T_OR &&    ((t->cdr->car->type == T_MIXED && t->cdr->cdr->type == T_VOID) ||    (t->cdr->cdr->type == T_MIXED && t->cdr->car->type == T_VOID)) &&    (t->car->type == T_ZERO ||    (t->car->type == T_OR &&    ((t->car->car->type == T_ZERO && t->car->cdr->type == T_VOID) ||    (t->car->cdr->type == T_ZERO && t->car->car->type == T_VOID)))))    {    /* function == function(zero...:mixed|void) or    * function(zero|void...:mixed|void)    */ -  +  string_builder_strcat(s, "function");    /* done */ -  +  break;    } else { -  my_strcat("("); -  s=0; +  int arg = 0; +  string_builder_strcat(s, "function(");    while(t->type != T_MANY)    { -  if(s++) my_strcat(", "); -  my_describe_type(t->car); +  if(arg++) string_builder_strcat(s, ", "); +  low_describe_type(s, t->car);    t = t->cdr;    while(t->type == T_ASSIGN) { -  my_putchar('0' + CAR_TO_INT(t)); -  my_putchar('='); +  string_builder_sprintf(s, "%c=", '0' + CAR_TO_INT(t));    t = t->cdr;    }    }    if(t->car->type != T_VOID)    { -  if(s++) my_strcat(", "); -  my_describe_type(t->car); -  my_strcat(" ..."); +  if(arg++) string_builder_strcat(s, ", "); +  low_describe_type(s, t->car); +  string_builder_strcat(s, " ...");    } -  my_strcat(" : "); -  my_describe_type(t->cdr); -  my_strcat(")"); +  string_builder_sprintf(s, " : %T)", t->cdr);    }    break;    }       case T_ARRAY: -  my_strcat("array"); +     if(t->car->type != T_MIXED) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "array(%T)", t->car); +  } else { +  string_builder_strcat(s, "array");    }    break;       case T_MULTISET: -  my_strcat("multiset"); +     if(t->car->type != T_MIXED) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "multiset(%T)", t->car); +  } else { +  string_builder_strcat(s, "multiset");    }    break;       case T_NOT: -  my_strcat("!"); +     if (t->car->type > T_NOT) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "!(%T)", t->car);    } else { -  my_describe_type(t->car); +  string_builder_sprintf(s, "!%T", t->car);    }    break;       case PIKE_T_RING:    /* FIXME: Should be renumbered for correct parenthesing. */ -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")°("); -  my_describe_type(t->cdr); -  my_strcat(")"); +  string_builder_sprintf(s, "(%T)\260(%T)", t->car, t->cdr);    break;       case T_OR:    if (t->car->type > T_OR) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "(%T)", t->car);    } else { -  my_describe_type(t->car); +  low_describe_type(s, t->car);    } -  my_strcat(" | "); +  string_builder_strcat(s, " | ");    if (t->cdr->type > T_OR) { -  my_strcat("("); -  my_describe_type(t->cdr); -  my_strcat(")"); +  string_builder_sprintf(s, "(%T)", t->cdr);    } else { -  my_describe_type(t->cdr); +  low_describe_type(s, t->cdr);    }    break;       case T_AND:    if (t->car->type > T_AND) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(")"); +  string_builder_sprintf(s, "(%T)", t->car);    } else { -  my_describe_type(t->car); +  low_describe_type(s, t->car);    } -  my_strcat(" & "); +  string_builder_strcat(s, " & ");    if (t->cdr->type > T_AND) { -  my_strcat("("); -  my_describe_type(t->cdr); -  my_strcat(")"); +  string_builder_sprintf(s, "(%T)", t->cdr);    } else { -  my_describe_type(t->cdr); +  low_describe_type(s, t->cdr);    }    break;       case T_MAPPING: -  my_strcat("mapping"); +     if(t->car->type != T_MIXED || t->cdr->type != T_MIXED) { -  my_strcat("("); -  my_describe_type(t->car); -  my_strcat(":"); -  my_describe_type(t->cdr); -  my_strcat(")"); +  string_builder_sprintf(s, "mapping(%T:%T)", t->car, t->cdr); +  } else { +  string_builder_strcat(s, "mapping");    }    break; -  +  case PIKE_T_AUTO: +  if (t->car->type != T_ZERO) { +  string_builder_sprintf(s, "auto(%T)", t->car); +  } else { +  string_builder_strcat(s, "auto"); +  } +  break;    default:    { -  char buf[20]; -  my_strcat("unknown code("); -  sprintf(buf, "%d", t->type); -  my_strcat(buf); -  my_strcat(")"); +  string_builder_sprintf(s, "unknown code(%d)", t->type);    break;    }    }   }    - void my_describe_type(struct pike_type *type) - { -  low_describe_type(type); - } -  +    struct pike_string *describe_type(struct pike_type *type)   { -  dynamic_buffer save_buf; -  check_type_string(type); +  struct string_builder s; +  ONERROR err;    if(!type) return make_shared_string("mixed"); -  init_buf(&save_buf); -  low_describe_type(type); -  return free_buf(&save_buf); +  init_string_builder(&s, 0); +  SET_ONERROR(err, free_string_builder, &s); +  low_describe_type(&s, type); +  UNSET_ONERROR(err); +  return finish_string_builder(&s);   }         /******/    - static int low_is_same_type(struct pike_type *a, struct pike_type *b) - { -  return a == b; - } -  +    TYPE_T compile_type_to_runtime_type(struct pike_type *t)   {    switch(t->type)    {    case PIKE_T_RING:    return compile_type_to_runtime_type(t->car);       case T_OR:    {    TYPE_T tmp = compile_type_to_runtime_type(t->car);    if(tmp == compile_type_to_runtime_type(t->cdr))    return tmp; -  -  /* FALL_THROUGH */ +     } -  +  /* FALLTHRU */ +     case T_TUPLE:    /* FIXME: Shouldn't occur/should be converted to array? */ -  /* FALL_THROUGH */ +  /* FALLTHRU */    default:    return T_MIXED;       case T_ZERO:    return T_INT;       case T_SCOPE:    case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE:    return compile_type_to_runtime_type(t->cdr);
pike.git/src/pike_types.c:2689:    case T_FUNCTION:       case T_STRING:    case T_TYPE:    case T_INT:    case T_FLOAT:    return t->type;    }   }    -  - static int low_find_exact_type_match(struct pike_type *needle, -  struct pike_type *haystack, -  unsigned int separator) + int get_int_type_range(struct pike_type *t, INT_TYPE *range)   { -  while(haystack->type == separator) +  int ret = 0; +  loop: +  switch(t->type) { +  case T_INT:    { -  if(low_find_exact_type_match(needle, haystack->car, separator)) +  INT_TYPE min = CAR_TO_INT(t); +  INT_TYPE max = CDR_TO_INT(t); +  if (range[0] > min) range[0] = min; +  if (range[1] < max) range[1] = max;    return 1; -  haystack = haystack->cdr; +     } -  return low_is_same_type(needle, haystack); +  break; +  case T_ZERO: +  case T_VOID: +  if (range[0] > 0) range[0] = 0; +  if (range[1] < 0) range[1] = 0; +  return 1; +  case T_SCOPE: +  case T_ASSIGN: +  case PIKE_T_NAME: +  case PIKE_T_ATTRIBUTE: +  t = t->cdr; +  goto loop; +  case T_OR: +  case T_AND: +  ret = get_int_type_range(t->car, range); +  t = t->cdr; +  goto loop; +  default: +  break;    } -  +  return ret; + }      static void low_or_pike_types(struct pike_type *t1,    struct pike_type *t2,    int zero_implied);      /* Push either t1, t2 or the OR of t1 and t2.    * Returns -1 if t1 was pushed.    * 0 if the OR was pushed. (Successful join)    * 1 if t2 was pushed.    *
pike.git/src/pike_types.c:2824:    case T_MULTISET:    if (t1->car->type < t2->car->type) {    t = t1;    ret = -1;    break;    } else if (t1->car->type > t2->car->type) {    t = t2;    ret = 1;    break;    } -  /* FALL_THOUGH */ +  /* FALLTHRU */    default:   #if 0    if (pike_types_le(t1, t2)) {    t = t2;    } else if (pike_types_le(t2, t1)) {    t = t1;    } else   #endif /* 0 */    if (t1 < t2) {    t = t1;    ret = -1;    } else {    t = t2;    ret = 1;    }    break;    }    }    if (!elem_on_stack) { -  +  if (t) {    push_finished_type(t); -  +  } else { +  push_type(T_ZERO); +  } +  } else if (!t) { +  /* No need to do anything. */    } else if ((top = peek_type_stack())->type != t->type) {    if (zero_implied && (top->type == T_ZERO)) {    Pike_compiler->type_stackp--;    free_type(top);    push_finished_type(t);    } else if (zero_implied && (t->type == T_ZERO)) {    /* The zero is implied. */    } else {    push_finished_type(t);    }
pike.git/src/pike_types.c:2956:    free_type(top);    break;    } else if (t->cdr == top->cdr) {    Pike_compiler->type_stackp--;    push_finished_type(t->cdr);    low_or_pike_types(t->car, top->car, zero_implied);    push_type(T_MAPPING);    free_type(top);    break;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    default:    if (t < top) {    Pike_compiler->type_stackp--;    push_finished_type(t);    push_finished_type(top);    free_type(top);    } else {    push_finished_type(t);    }    break;
pike.git/src/pike_types.c:3325:   #endif   static struct pike_type *low_match_types(struct pike_type *a,    struct pike_type *b,    int flags)   #ifdef PIKE_TYPE_DEBUG   {    int e;    char *s;       if (l_flag>2) { -  dynamic_buffer save_buf; -  init_buf(&save_buf); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat("low_match_types("); -  my_describe_type(a); -  my_strcat(",\n"); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat(" "); -  my_describe_type(b); -  my_strcat(",\n"); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat(" "); +  fprintf(stderr, "%*slow_match_types(", indent*2, ""); +  simple_describe_type(a); +  fprintf(stderr, ",\n"); +  fprintf(stderr, "%*s%s", indent*2, "", " "); +  simple_describe_type(b); +  fprintf(stderr, ",\n"); +  fprintf(stderr, "%*s%s", indent*2, "", " ");       if (flags) {    int f = 0;    if (flags & A_EXACT) { -  my_strcat("A_EXACT"); +  fprintf(stderr, "A_EXACT");    f = 1;    }    if (flags & B_EXACT) {    if (f) { -  my_strcat(" | "); +  fprintf(stderr, " | ");    } -  my_strcat("B_EXACT"); +  fprintf(stderr, "B_EXACT");    f = 1;    }    if (flags & NO_MAX_ARGS) {    if (f) { -  my_strcat(" | "); +  fprintf(stderr," | ");    } -  my_strcat("NO_MAX_ARGS"); +  fprintf(stderr, "NO_MAX_ARGS");    f = 1;    }    if (flags & NO_SHORTCUTS) {    if (f) { -  my_strcat(" | "); +  fprintf(stderr, " | ");    } -  my_strcat("NO_SHORTCUTS"); +  fprintf(stderr, "NO_SHORTCUTS");    f = 1;    }    } else { -  my_strcat("0"); +  fputc('0', stderr);    } -  my_strcat(");\n"); -  fprintf(stderr,"%s",(s=simple_free_buf(&save_buf))); -  free(s); +  fprintf(stderr, ");\n");    indent++;    }       a = low_match_types2(a, b, flags);       if (l_flag>2) { -  dynamic_buffer save_buf; +     indent--; -  init_buf(&save_buf); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat("= "); +  fprintf(stderr, "%*s= ", indent*2, "");    if(a) -  my_describe_type(a); +  simple_describe_type(a);    else -  my_strcat("NULL"); -  my_strcat("\n"); -  fprintf(stderr,"%s",(s=simple_free_buf(&save_buf))); -  free(s); +  fprintf(stderr, "NULL"); +  fputc('\n', stderr);    }    return a;   }      static struct pike_type *low_match_types2(struct pike_type *a,    struct pike_type *b,    int flags)   #endif   {    int correct_args;
pike.git/src/pike_types.c:3463:    tmp = pop_unfinished_type();       type_stack_mark();    low_or_pike_types(a_markers[m], tmp, 0);    if(a_markers[m]) free_type(a_markers[m]);    free_type(tmp);    a_markers[m] = pop_unfinished_type();      #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) { -  dynamic_buffer save_buf; -  char *s; -  int e; -  init_buf(&save_buf); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat("a_markers["); -  my_putchar((char)(m+'0')); -  my_strcat("]="); -  my_describe_type(a_markers[m]); -  my_strcat("\n"); -  fprintf(stderr,"%s",(s=simple_free_buf(&save_buf))); -  free(s); +  fprintf(stderr, "%*sa_markers[%d]=", +  indent*2, "", m); +  simple_describe_type(a_markers[m]); +  fputc('\n', stderr);    }   #endif   #ifdef PIKE_DEBUG    if(a_markers[m]->type == m+'0')    Pike_fatal("Cyclic type!\n");   #endif    }    return ret;    }    case '0': case '1': case '2': case '3': case '4':
pike.git/src/pike_types.c:3566:    push_finished_type_with_markers(a, a_markers, 0);    tmp=pop_unfinished_type();       type_stack_mark();    low_or_pike_types(b_markers[m], tmp, 0);    if(b_markers[m]) free_type(b_markers[m]);    free_type(tmp);    b_markers[m] = pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) { -  dynamic_buffer save_buf; -  char *s; -  int e; -  init_buf(&save_buf); -  for(e=0;e<indent;e++) my_strcat(" "); -  my_strcat("b_markers["); -  my_putchar((char)(m+'0')); -  my_strcat("]="); -  my_describe_type(b_markers[m]); -  my_strcat("\n"); -  fprintf(stderr,"%s",(s=simple_free_buf(&save_buf))); -  free(s); +  fprintf(stderr, "%*sb_markers[%d]=", +  indent*2, "", m); +  simple_describe_type(b_markers[m]); +  fputc('\n', stderr);    }   #endif   #ifdef PIKE_DEBUG    if(b_markers[m]->type == m+'0')    Pike_fatal("Cyclic type!\n");   #endif    }    return ret;    }    case '0': case '1': case '2': case '3': case '4':
pike.git/src/pike_types.c:3840: Inside #if 0
   stupid_describe_type(b,type_length(b));    }   #endif       /* object(* 0) matches any object */    if(!a->cdr || !b->cdr) break;       /* object(* x) =? object(* x) */    if (a->cdr == b->cdr) break;    -  /* object(x *) =? object(x *) */ -  if(TEST_COMPAT(7,4) && a->car == b->car) -  { -  /* x? */ -  if(a->car) -  { -  /* object(1 x) =? object(1 x) */ -  return 0; -  }else{ -  /* object(0 *) =? object(0 *) */ -  break; -  } -  } -  +     /* Note: In Pike 7.4 and earlier the following was only done    * when a->car != b->car.    */    {    struct program *ap,*bp;    ap = id_to_program(CDR_TO_INT(a));    bp = id_to_program(CDR_TO_INT(b));       if(!ap || !bp) break;   
pike.git/src/pike_types.c:4040:    }       case PIKE_T_RING:    a = a->car;    goto recurse;       case PIKE_T_SCOPE:   #ifdef TYPE_GROUPING    flags |= LE_A_GROUPED;   #endif -  /* FALL_THROUGH */ +  /* FALLTHRU */    case PIKE_T_NAME:    a = a->cdr;    goto recurse;    case PIKE_T_ATTRIBUTE:    if ((b->type == PIKE_T_ATTRIBUTE) && (a->car == b->car)) {    a = a->cdr;    b = b->cdr;    goto recurse;    }    if (!c) {
pike.git/src/pike_types.c:4247:    (!Pike_sp[-1].u.integer)) {    pop_stack();    return 0;    }    pop_stack();    return 1;    case PIKE_T_SCOPE:   #ifdef TYPE_GROUPING    flags |= LE_B_GROUPED;   #endif -  /* FALL_THROUGH */ +  /* FALLTHRU */    case PIKE_T_NAME:    b = b->cdr;    goto recurse;       case T_NOT:    /* Some common cases. */    switch(b->car->type) {    case T_NOT:    b = b->car->car;    goto recurse;
pike.git/src/pike_types.c:4537:    if (b->type == T_FUNCTION)    {    b = b->cdr;    }       if (a_tmp->type != T_VOID) {    /* Note: flags never has grouping at this point. */    if (!low_pike_types_le(b_tmp, a_tmp, 0, flags ^ LE_A_B_SWAPPED)) {    return 0;    } +  } else if (flags & LE_TYPE_SVALUE) { +  /* Note: flags never has grouping at this point. */ +  if (!low_pike_types_le(b_tmp, zero_type_string, 0, +  flags ^ LE_A_B_SWAPPED)) { +  return 0;    }    } -  /* FALL_THROUGH */ +  } +  /* FALLTHRU */    case TWOT(T_MANY, T_MANY):    /* check the 'many' type */    if ((a->car->type != T_VOID) && (b->car->type != T_VOID)) {    /* Note: flags never has grouping at this point. */    if (!low_pike_types_le(b->car, a->car, 0, flags ^ LE_A_B_SWAPPED)) {    return 0;    } -  +  } else if ((flags & LE_TYPE_SVALUE) && (a->car->type != b->car->type)) { +  if (a->car->type == T_VOID) { +  /* Note: flags never has grouping at this point. */ +  if (!low_pike_types_le(b->car, zero_type_string, 0, +  flags ^ LE_A_B_SWAPPED)) { +  return 0;    } -  +  } else { +  /* Note: flags never has grouping at this point. */ +  if (!low_pike_types_le(zero_type_string, a->car, 0, +  flags ^ LE_A_B_SWAPPED)) { +  return 0; +  } +  } +  }       a = a->cdr;    b = b->cdr;       /* check the returntype */ -  +  if (flags & LE_TYPE_SVALUE) return 1;    /* FIXME: Check array_cnt */    if ((b->type != T_VOID) && (a->type != T_VOID)) {    if(!low_pike_types_le(a, b, array_cnt, flags)) return 0;    }    return 1;    }       if(a->type != b->type) return 0;       if (array_cnt) return 0;       switch(a->type)    {    case T_MAPPING: -  +  if (flags & LE_TYPE_SVALUE) return 1;    /*    * mapping(A:B) <= mapping(C:D) iff A <= C && B <= D.    */    if(!low_pike_types_le(a->car, b->car, 0, flags)) return 0;    array_cnt = 0;    a = a->cdr;    b = b->cdr;    goto recurse;       case T_OBJECT:
pike.git/src/pike_types.c:4610:    if(!b->cdr)    return 1;       if(!a->cdr)    return 0;       /* The 'is' flag is now ignored.    * /grubba 2003-11-11    */    -  if (TEST_COMPAT(7,4)) { -  if ((a->car || !b->car) && -  (a->cdr == b->cdr)) -  return 1; -  -  if (b->car) { -  return 0; -  } -  } -  else { +     if (a->cdr == b->cdr)    return 1; -  } +        {    struct program *ap = id_to_program(CDR_TO_INT(a));    struct program *bp = id_to_program(CDR_TO_INT(b));      #if 0    fprintf(stderr,    "id_to_program(%d) ==> %p\n"    "id_to_program(%d) ==> %p\n",    CDR_TO_INT(a), ap,    CDR_TO_INT(b), bp);   #endif /* 0 */       if (!ap || !bp) {    /* Shouldn't happen... */    /* fprintf(stderr, "ap:%p bp:%p\n", ap, bp); */    return 0;    } -  if ((flags & LE_WEAK_OBJECTS) && -  (!TEST_COMPAT(7,4) || (!a->car))) { +  if ((flags & LE_WEAK_OBJECTS) && !a->car) {    implements_mode = 0;   #if 0    fprintf(stderr, " is_compat(%p(%d), %p(%d))\n",    ap, ap->id, bp, bp->id);   #endif /* 0 */    return is_compatible(implements_a=ap, implements_b=bp);    }    implements_mode = 1;   #if 0    fprintf(stderr, " implements(%p(%d), %p(%d))\n",
pike.git/src/pike_types.c:4683:    if(amin < bmin || amax > bmax) return 0;    break;    }          case T_TYPE:    case T_PROGRAM:    case T_MULTISET:    case T_ARRAY:    case T_STRING: +  if (flags & LE_TYPE_SVALUE) return 1;    a = a->car;    b = b->car;    array_cnt = 0;    goto recurse;       case T_FLOAT:    case T_ZERO:    case T_VOID:    case T_MIXED:    break;
pike.git/src/pike_types.c:4817: Inside #if 0
   yyreport_type(REPORT_WARNING, NULL, 0, b, NULL, 0, a, 0, "Type mismatch");    }   #endif /* 0 */    switch(a->type)    {    case T_FUNCTION:    a = a->cdr;    while(a->type == T_FUNCTION) {    a = a->cdr;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_MANY:    a = a->cdr;    push_finished_type_with_markers(a, a_markers, 0);    return 1;       case T_TYPE:    case T_PROGRAM:    push_finished_type(a->car);    return 1;   
pike.git/src/pike_types.c:4839:    push_type(T_MIXED);    return 1;    }    }    return 0;   }         int match_types(struct pike_type *a, struct pike_type *b)   { -  check_type_string(a); -  check_type_string(b); +     clear_markers();    return !!low_match_types(a, b, 0);   }      int pike_types_le(struct pike_type *a,struct pike_type *b)   { -  check_type_string(a); -  check_type_string(b); +     clear_markers();    return low_pike_types_le(a, b, 0, 0);   }    -  + int check_variant_overload(struct pike_type *a, struct pike_type *b) + { +  clear_markers(); +  return !low_pike_types_le(b, a, 0, LE_TYPE_SVALUE); + }      #ifdef DEBUG_MALLOC   #define low_index_type(X,Y,Z) ((struct pike_type *)debug_malloc_pass(debug_low_index_type((X),(Y),(Z))))   #else   #define low_index_type debug_low_index_type   #endif      /* FIXME, add the index */   static struct pike_type *debug_low_index_type(struct pike_type *t,    struct pike_type *index_type,
pike.git/src/pike_types.c:4954:    {    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 */ +  /* FALLTHRU */       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: -  /* 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(); +  p=bignum_program;    goto comefrom_int_index;       case T_ZERO:    case T_TYPE:    case PIKE_T_RING:    case T_VOID:    case T_FLOAT:    return 0;       case T_OR:
pike.git/src/pike_types.c:5009:       case T_STRING: /* always int */    {    if (t->car->type == T_ZERO) {    yywarning("Indexing the empty string.");    }    add_ref(t->car);    return t->car;    }    -  case T_MULTISET: /* always int */ -  add_ref(int_type_string); -  return int_type_string; +  case T_MULTISET: /* always int(0..1) */ +  type_stack_mark(); +  push_int_type(0, 1); +  return pop_unfinished_type();       case T_MAPPING:    add_ref(t = t->cdr);    return t;       case T_ARRAY:    {    struct pike_type *a;       if(low_pike_types_le(string0_type_string, index_type, 0, 0) &&
pike.git/src/pike_types.c:5450:    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 */ +  /* FALLTHRU */    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. */
pike.git/src/pike_types.c:5492:       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;    +  case T_FUNCTION: +  while ((type = type->cdr) && (type->type == T_FUNCTION)) +  ; +  if (!type) return 0; +  +  /* FALLTHRU */ +  +  case T_MANY: +  type = type->cdr; +  if (!type || (type->type != T_OBJECT) || !type->car) +  return 0; +  /* function(... : object(is foo)) -- ie probably program(foo). */ +  +  /* FALLTHRU */ +     case T_INT:    case T_PROGRAM:    return !!low_match_types(string_type_string, index_type, 0);       case T_MIXED:    return 1;       default:    return 0;    }   }      int check_indexing(struct pike_type *type,    struct pike_type *index_type,    node *n)   { -  check_type_string(type); -  check_type_string(index_type); -  +     return low_check_indexing(type, index_type, n);   }      static int low_count_arguments(struct pike_type *q)   {    int num=0, num2;       switch(q->type)    {    case T_OR:
pike.git/src/pike_types.c:5550:    return low_count_arguments(q->cdr);       default: return MAX_INT32;       case T_FUNCTION:    while(q->type == T_FUNCTION)    {    num++;    q = q->cdr;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_MANY:    q = q->car;    if(q->type != T_VOID) return ~num;    return num;    }   }      /* Count the number of arguments for a funciton type.    * return -1-n if the function can take number of arguments    * >= n (varargs)    */   int count_arguments(struct pike_type *s)   { -  check_type_string(s); -  +     return low_count_arguments(s);   }         static int low_minimum_arguments(struct pike_type *q)   {    int num;       switch(q->type)    {
pike.git/src/pike_types.c:5610:    case T_MANY:    return 0;    }   }      /* Count the minimum number of arguments for a function type.    */   int minimum_arguments(struct pike_type *s)   {    int ret; -  check_type_string(s); +        ret = low_minimum_arguments(s);      #if 0    fprintf(stderr,"minimum_arguments(");    simple_describe_type(s);    fprintf(stderr," ) -> %d\n",ret);   #endif       return ret;   }      struct pike_type *check_call(struct pike_type *args,    struct pike_type *type,    int strict)   { -  check_type_string(args); -  check_type_string(type); +     clear_markers();    type_stack_mark();    max_correct_args=0;       if(low_get_return_type(type, args))    {    if (strict) {    if (!strict_check_call(type, args)) {    struct pike_type *func_zero_type;   
pike.git/src/pike_types.c:5667:    return 0;    }   }      /* Get the type for the specified argument in a function type.    * Argument number -1 is the return type.    * True arguments are counted from zero.    */   struct pike_type *get_argument_type(struct pike_type *fun, int arg_no)   { +  struct pike_type *tmp, *tmp2; +     loop:    switch(fun->type) {    case T_OR: -  return or_pike_types(get_argument_type(fun->car, arg_no), -  get_argument_type(fun->cdr, arg_no), +  fun = or_pike_types(tmp = get_argument_type(fun->car, arg_no), +  tmp2 = get_argument_type(fun->cdr, arg_no),    1); -  +  free_type(tmp); +  free_type(tmp2); +  return fun; +     case T_FUNCTION:    if (arg_no > 0) {    arg_no--;    fun = fun->cdr;    goto loop;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_MANY:    if (arg_no < 0) {    add_ref(fun->cdr);    return fun->cdr;    }    add_ref(fun->car);    return fun->car;       case T_MIXED:    add_ref(fun);
pike.git/src/pike_types.c:5702:    case T_ARRAY:    if (arg_no < 0) {    type_stack_mark();    push_finished_type(fun = get_argument_type(fun->car, arg_no));    push_type(T_ARRAY);    free_type(fun);    return pop_unfinished_type();    }    return get_argument_type(fun->car, arg_no);    +  case PIKE_T_ATTRIBUTE: +  type_stack_mark(); +  push_finished_type(tmp = get_argument_type(fun->cdr, arg_no)); +  push_type_attribute((struct pike_string *)(fun->car)); +  free_type(tmp); +  return pop_unfinished_type(); +  +  case PIKE_T_SCOPE: +  case T_ASSIGN: +  case PIKE_T_NAME: +  fun = fun->cdr; +  goto loop; +     default: -  + #if 0 +  fprintf(stderr, +  "Failed to resolve argument type for argument %d.\n" +  "Type: ", +  arg_no); +  simple_describe_type(fun); +  fprintf(stderr, "\n" +  "Node type: %d\n", +  fun->type); + #endif    add_ref(zero_type_string);    return zero_type_string;    }   }      /* Get the resulting type from a soft cast.    *    * Flags:    * 1 SOFT_WEAKER Weaker type.    */
pike.git/src/pike_types.c:5889:    case T_PROGRAM:    /* Convert to a function returning an object. */    copy_pike_type(tmp3, soft_type->car); /* Return type */    if ((tmp2 = low_object_lfun_type(tmp3, LFUN_CREATE))) {    soft_type = tmp2;    tmp2 = NULL;    } else {    /* FIXME: Multiple cases. */    soft_type = function_type_string;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_FUNCTION:    case T_MANY:    {    int array_cnt = 0;    int loop_cnt = 0;    while(orig_type->type == T_ARRAY) {    array_cnt++;    orig_type = orig_type->car;    }    if (orig_type->type == T_PROGRAM) {
pike.git/src/pike_types.c:6139:    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) || +  res = match_type_svalue(type->car, 0, sval) &&    match_type_svalue(type->cdr, 0, sval); -  +  break;    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: -  +  { +  struct pike_type *t = NULL;    /* Identify if sval is callable. */ -  +  if (TYPEOF(*sval) == PIKE_T_OBJECT) { +  struct program *p; +  int f; +  struct identifier *id; +  if (!sval->u.object || !(p = sval->u.object->prog)) break; +  p = p->inherits[SUBTYPEOF(*sval)].prog; +  if ((f = FIND_LFUN(p, LFUN_CALL)) == -1) break; +  id = ID_FROM_INT(p, f); +  t = id->type; +  res = 1; +  } else {    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 ); +  res = is_compatible( o->prog, mark );    else -  res = implements( mark, o->prog ); +  res = implements( o->prog, mark );    }    }    }    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; +  res = (sval->u.string->len == 0); +  break;    }    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 );   
pike.git/src/pike_types.c:6309:    * 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, ""); +  if (Pike_interpreter.trace_level > 2) { +  fprintf(stderr, " check_call_svalue(");    simple_describe_type(fun_type); -  fprintf(stderr, ", 0x%08x, %p)...\n", flags, sval); +  fprintf(stderr, ", 0x%08x, ", flags); +  debug_describe_svalue(sval); +  fprintf(stderr, ")...\n");    }   #endif /* PIKE_DEBUG */       loop:    /* Count the number of array levels. */    while(fun_type->type == PIKE_T_ARRAY) {    array_cnt++;    fun_type = fun_type->car;    }   
pike.git/src/pike_types.c:6427:    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 */ +  /* FALLTHRU */    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;
pike.git/src/pike_types.c:6457:    }    res = NULL;    break;    default:    /* Not a callable. */    break;    }       if (!array_cnt || !res) {   #ifdef PIKE_DEBUG -  if (l_flag>2) { +  if (Pike_interpreter.trace_level > 2) {    if (res) { -  fprintf(stderr, "%*s==> ", indent*2, ""); +  fprintf(stderr, " ==> ");    simple_describe_type(res);    } else { -  fprintf(stderr, "%*s==> NULL", indent*2, ""); +  fprintf(stderr, " ==> NULL");    }    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, ""); +  if (Pike_interpreter.trace_level > 2) { +  fprintf(stderr, " ==> ");    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.
pike.git/src/pike_types.c:6703:    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 */ +  /* FALLTHRU */    case PIKE_T_MIXED:    copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION:    case T_MANY:    /* Special case to detect workarounds for the old    * function call checker.    */    tmp = NULL;
pike.git/src/pike_types.c:6747: Inside #if defined(PIKE_DEBUG)
   if (l_flag>2) {    fprintf(stderr, "%*sChecking argument type ", indent*2+2, "");    simple_describe_type(arg_type);    fprintf(stderr, " against function type ");    simple_describe_type(fun_type);    fprintf(stderr, ".\n");    }   #endif /* PIKE_DEBUG */    /* No need to perform advanced checking in the trivial case... */    if (arg_type != (tmp2 = fun_type->car)) { -  if ((flags & CALL_7_6) && (arg_type == void_type_string)) { -  /* Compat with Pike 7.6 and earlier. */ -  arg_type = zero_type_string; -  } -  +     if (!((flags & CALL_INVERTED_TYPES)?    low_pike_types_le(tmp2, arg_type, 0,    LE_A_B_SWAPPED|LE_EXPLICIT_ZERO):    low_pike_types_le(arg_type, tmp2, 0, 0)) &&    ((flags & CALL_STRICT) ||    !low_match_types(arg_type, tmp2, NO_SHORTCUTS))) {    /* No match. */   #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*sNo match.\n", indent*2+2, "");
pike.git/src/pike_types.c:6798: Inside #if 0
   if (tmp) free_type(tmp);    break;    }   #endif /* 0 */    }    type_stack_mark();    push_finished_type_with_markers(fun_type, b_markers, 0);    res = pop_unfinished_type();    if (tmp) free_type(tmp);    -  if ((Pike_compiler->compiler_pass == 2) && sval) { +  if ((Pike_compiler->compiler_pass == COMPILER_PASS_LAST) && sval) {    while (tmp2->type == PIKE_T_NAME) {    tmp2 = tmp2->cdr;    }       if (tmp2->type == PIKE_T_ATTRIBUTE) {    struct compilation *c = MAYBE_THIS_COMPILATION;    if (c) {    /* Perform extra argument checking based on the attribute. */    ref_push_string((struct pike_string *)tmp2->car);    push_svalue(sval);
pike.git/src/pike_types.c:6855:   #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(); +  res = pop_unfinished_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;
pike.git/src/pike_types.c:6955:    flags & ~CALL_WEAK_VOID, sval))) {    free_type(tmp);    return NULL;    }    res = and_pike_types(tmp, tmp2);    free_type(tmp);    free_type(tmp2);    return res;       case T_VOID: -  if (!(flags & CALL_7_6)) { +     if ((flags & (CALL_WEAK_VOID|CALL_STRICT)) == CALL_STRICT) {    return NULL;    }    /* Promote void arguments to zero. */    arg_type = zero_type_string; -  } +     break;    }       if (!(tmp = lower_new_check_call(fun_type, arg_type,    flags & ~CALL_WEAK_VOID, sval   #ifdef PIKE_TYPE_DEBUG    , 0   #endif    ))) { -  +  struct pike_type *tmp2; +  if (!(flags & CALL_STRICT) || (arg_type->type != T_INT) || +  (CAR_TO_INT(arg_type) >= 0) || (CDR_TO_INT(arg_type) <= 0)) {    return NULL;    } -  +  /* KLUDGE: Special case for integers spanning zero. +  * +  * Try splitting the argument at zero. The proper fix would be +  * to split at all the integer range limits for the first +  * declared argument to the function. +  * +  * Test the most likely problematic range first (ie negative). +  */ +  type_stack_mark(); +  push_int_type(CAR_TO_INT(arg_type), -1); +  tmp2 = pop_unfinished_type(); +  if (!(tmp = lower_new_check_call(fun_type, tmp2, +  flags & ~CALL_WEAK_VOID, sval + #ifdef PIKE_TYPE_DEBUG +  , 0 + #endif +  ))) { +  free_type(tmp2); +  return NULL; +  } +  free_type(tmp2); +  +  type_stack_mark(); +  push_finished_type(tmp); +  free_type(tmp); +  +  /* Then the positive range. */ +  type_stack_mark(); +  push_int_type(1, CDR_TO_INT(arg_type)); +  tmp2 = pop_unfinished_type(); +  if (!(tmp = lower_new_check_call(fun_type, tmp2, +  flags & ~CALL_WEAK_VOID, sval + #ifdef PIKE_TYPE_DEBUG +  , 0 + #endif +  ))) { +  free_type(tmp2); +  free_type(pop_unfinished_type()); +  return NULL; +  } +  free_type(tmp2); +  +  push_finished_type(tmp); +  free_type(tmp); +  +  /* NB: Zero always succeeds. */ +  push_type(T_OR); +  tmp = pop_unfinished_type(); +  }    return tmp;   }      /* Return the return type for the function type fun_type, if    * no further arguments are passed.    *    * Returns NULL if more arguments are required.    *    * Returns a the type of the return value otherwise.    */
pike.git/src/pike_types.c:7083:    res = NULL;    break;    }    res = and_pike_types(tmp2 = res, tmp);    free_type(tmp);    free_type(tmp2);    break;    case T_NOT:    if (!(res = new_get_return_type(fun_type->car, flags))) {    copy_pike_type(res, mixed_type_string); -  } else if (res->type == T_INT) { +  } else if (res->type == T_NOT) {    tmp = res;    copy_pike_type(res, tmp->car);    free_type(tmp);    } else {    type_stack_mark();    push_finished_type(res);    push_type(T_NOT);    free_type(res);    res = pop_unfinished_type();    }
pike.git/src/pike_types.c:7121:    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.    * Failed to lookup program id.    * Program does not have the lfun `()().    */    -  /* FALL_THROUGH */ +  /* FALLTHRU */    case PIKE_T_MIXED:    copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION:    do {    if (!match_types(fun_type->car, void_type_string)) {    /* Too few arguments. */    break;    }    fun_type = fun_type->cdr;    } while(fun_type->type == PIKE_T_FUNCTION);    if (fun_type->type != T_MANY) {    /* Still too few arguments. */    break;    } -  +  /* FALLTHRU */    case T_MANY:    copy_pike_type(res, fun_type->cdr);    break;       default:    /* Not a callable. */    break;    }       if (!res) {
pike.git/src/pike_types.c:7244:    } 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 */ +  /* FALLTHRU */       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:7273:    tmp = low_get_first_arg_type(arg_type->car, flags|FILTER_KEEP_VOID);    push_finished_type(tmp);    free_type(tmp);    push_type(arg_type->type);    return pop_unfinished_type();       case T_VOID:    if (!(flags & FILTER_KEEP_VOID)) {    return NULL;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    default:    break;    }    }    add_ref(arg_type);    return arg_type;   }      /* Return the type of the first argument to a function of the type fun_type    *
pike.git/src/pike_types.c:7406:    fun_type = low_object_lfun_type(fun_type, LFUN_CALL);    if (fun_type) {    goto loop;    }    /* FIXME: Multiple cases:    * Untyped object.    * Failed to lookup program id.    * Program does not have the lfun `()().    */    -  /* FALL_THROUGH */ +  /* FALLTHRU */    case PIKE_T_MIXED:    copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION:    if (!(flags & CALL_NOT_LAST_ARG) &&    (fun_type->cdr->type == PIKE_T_FUNCTION) &&    !low_match_types(fun_type->cdr->car, void_type_string, 0)) {    /* Last argument and more arguments required. */    res = NULL;    break;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_MANY:    if ((res = fun_type->car)->type == T_VOID) {    res = NULL;    break;    }    res = low_get_first_arg_type(res, 0);    break;       default:    /* Not a callable. */
pike.git/src/pike_types.c:7552: Inside #if defined(PIKE_DEBUG)
   simple_describe_type(args->type);    if (sval) {    fprintf(stderr, "\n Constant of type %s",    get_name_of_type(TYPEOF(*sval)));    }    fprintf(stderr, "\n fun_type: ");    simple_describe_type(fun_type);    }   #endif /* PIKE_DEBUG */    -  if (TEST_COMPAT(7, 6)) { -  /* Attempt to reduce strictness to Pike 7.6 levels. */ -  flags |= CALL_7_6; -  } -  +     if (args->token == F_PUSH_ARRAY) {   #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "\n The argument is a splice operator.\n");    }   #endif /* PIKE_DEBUG */       res = check_splice_call(fun_name, fun_type, *argno,    args->type, sval, flags);   
pike.git/src/pike_types.c:8278:    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]);    break;    case T_OR:    case T_AND:    /* Order independant */ -  /* FALL_THROUGH */ +  /* FALLTHRU */       case T_MANY:    case T_TUPLE:    case T_MAPPING:    case PIKE_T_RING:    /* Order dependant */    low_make_pike_type(type_string+1, cont);    low_make_pike_type(*cont, cont);    push_reverse_type(type);    break;
pike.git/src/pike_types.c:8311:    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':    case '8':    case '9':    /* Marker type */ -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_FLOAT:    case T_MIXED:    case T_VOID:    case T_ZERO:    case PIKE_T_UNKNOWN:    /* Leaf type */    *cont = type_string+1;    push_type(type);    break;   
pike.git/src/pike_types.c:8399:    break;    break;    case 6:    for(bytes=0; ; bytes+=4)    if(!type_string[bytes+2] && !type_string[bytes+3] &&    !type_string[bytes+4] && !type_string[bytes+5])    break;    break;    }    str = begin_wide_shared_string(bytes>>size_shift, size_shift); -  MEMCPY(str->str, type_string+2, bytes); +  memcpy(str->str, type_string+2, bytes);    if (size_shift &&   #if (PIKE_BYTEORDER == 1234)    /* Little endian */    !(type_string[1] & 0x04)   #else /* PIKE_BYTEORDER != 1234 */    /* Big endian */    (type_string[1] & 0x04)   #endif /* PIKE_BYTEORDER == 1234 */    ) {    int len;
pike.git/src/pike_types.c:8440:    push_type_name(str = end_shared_string(str));    } else {    push_type_attribute(str = end_shared_string(str));    }    free_string(str);    break;    }   #ifdef PIKE_DEBUG    default:    Pike_fatal("compile_type_string(): Error in type string %d.\n", type); -  /* NOT_REACHED */ -  break; +  UNREACHABLE(break);   #endif    }   }    -  + void type_stack_mark(void) + { +  if(UNLIKELY(Pike_compiler->pike_type_mark_stackp >= pike_type_mark_stack + (PIKE_TYPE_STACK_SIZE>>4))) +  Pike_fatal("Type mark stack overflow.\n"); +  *Pike_compiler->pike_type_mark_stackp=Pike_compiler->type_stackp; +  Pike_compiler->pike_type_mark_stackp++; +  TYPE_STACK_DEBUG("type_stack_mark"); + } +    /* Make a pike-type from a serialized (old-style) type. */   struct pike_type *debug_make_pike_type(const char *serialized_type)   {    unsigned char *dummy;    type_stack_mark();    low_make_pike_type((unsigned char *)serialized_type, &dummy);   #if 1    if ((Pike_compiler->type_stackp[0]->flags &    (PT_FLAG_MARKER|PT_FLAG_ASSIGN)) ||    (((Pike_compiler->type_stackp[0]->type == T_OR) ||
pike.git/src/pike_types.c:8477: Inside #if 0
  #if 0    fprintf(stderr, "pike_type_allow_premature_toss(): Type: %d\n",    type->type);   #endif /* 0 */    switch(type->type)    {    default:   #ifdef PIKE_DEBUG    Pike_fatal("pike_type_allow_premature_toss: Unknown type (code: %d)\n",    type->type); -  /* NOT_REACHED */ -  return 0; +  UNREACHABLE(return 0);   #endif    case T_NOT:    return !pike_type_allow_premature_toss(type->car);       case T_OBJECT:    case T_MIXED:    case T_FUNCTION:    case T_MANY:    return 0;   
pike.git/src/pike_types.c:8527:    case T_TYPE:    case T_INT:    case T_FLOAT:    case T_STRING:    case PIKE_T_ZERO:    case T_VOID:    return 1;    }   }    - static void low_type_to_string(struct pike_type *t) + static void low_type_to_string(struct byte_buffer *buf, struct pike_type *t)   {    recurse:    switch(t->type) {    case T_ARRAY:    case T_MULTISET:    case T_TYPE:    case T_PROGRAM: -  my_putchar(t->type ^ MIN_REF_TYPE); +  buffer_add_char(buf, t->type ^ MIN_REF_TYPE);    t = t->car;    goto recurse;       case T_NOT: -  my_putchar(t->type); +  buffer_add_char(buf, t->type);    t = t->car;    goto recurse;       case T_MAPPING: -  my_putchar(t->type ^ MIN_REF_TYPE); -  low_type_to_string(t->car); +  buffer_add_char(buf, t->type ^ MIN_REF_TYPE); +  low_type_to_string(buf, t->car);    t = t->cdr;    goto recurse;       case PIKE_T_RING:    case T_TUPLE:    case T_OR:    case T_AND: -  my_putchar(t->type); -  low_type_to_string(t->car); +  buffer_add_char(buf, t->type); +  low_type_to_string(buf, t->car);    t = t->cdr;    goto recurse;       case T_FLOAT:    case T_ZERO: -  my_putchar(t->type ^ MIN_REF_TYPE); +  buffer_add_char(buf, 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_VOID:    case T_MIXED: -  my_putchar(t->type); +  buffer_add_char(buf, t->type);    break;       case T_OBJECT:    {    INT32 i; -  my_putchar(T_OBJECT ^ MIN_REF_TYPE); +  buffer_add_char(buf, T_OBJECT ^ MIN_REF_TYPE);    i = (INT32)CAR_TO_INT(t); -  my_putchar( i ); +  buffer_add_char(buf, 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); +  buffer_add_be32(buf, i);    }    break;       case T_STRING:    {    if (t->car == int_type_string) { -  my_putchar(T_STRING ^ MIN_REF_TYPE); +  buffer_add_char(buf, T_STRING ^ MIN_REF_TYPE);    } else { -  my_putchar(PIKE_T_NSTRING); -  low_type_to_string(t->car); +  buffer_add_char(buf, PIKE_T_NSTRING); +  low_type_to_string(buf, t->car);    }    }    break;       case T_INT:    {    INT32 i; -  my_putchar(T_INT ^ MIN_REF_TYPE); +  buffer_add_char(buf, 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); +  buffer_add_be32(buf, i);    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); +  buffer_add_be32(buf, i);    }    break;       case T_FUNCTION:    case T_MANY: -  my_putchar(T_FUNCTION ^ MIN_REF_TYPE); +  buffer_add_char(buf, T_FUNCTION ^ MIN_REF_TYPE);    while(t->type == T_FUNCTION) { -  low_type_to_string(t->car); +  low_type_to_string(buf, t->car);    t = t->cdr;    } -  my_putchar(T_MANY); -  low_type_to_string(t->car); +  buffer_add_char(buf, T_MANY); +  low_type_to_string(buf, t->car);    t = t->cdr;    goto recurse;       case T_SCOPE:    case T_ASSIGN: -  my_putchar(t->type); -  my_putchar('0' + CAR_TO_INT(t)); +  buffer_add_char(buf, t->type); +  buffer_add_char(buf, '0' + CAR_TO_INT(t));    t = t->cdr;    goto recurse;       case PIKE_T_NAME:    case PIKE_T_ATTRIBUTE: -  my_putchar(t->type); -  my_putchar(0); -  my_strcat(((struct pike_string *)t->car)->str); -  my_putchar(0); +  buffer_add_char(buf, t->type); +  buffer_add_char(buf, 0); +  buffer_add_str(buf, ((struct pike_string *)t->car)->str); +  buffer_add_char(buf, 0);    t = t->cdr;    goto recurse;       default:    Pike_error("low_type_to_string(): Unsupported node: %d\n", t->type);    break;    }   }      struct pike_string *type_to_string(struct pike_type *t)   {    ONERROR err; -  dynamic_buffer save_buf; -  init_buf(&save_buf); -  SET_ONERROR(err, abandon_buf, &save_buf); -  low_type_to_string(t); +  struct byte_buffer buf = BUFFER_INIT(); +  SET_ONERROR(err, buffer_free, &buf); +  low_type_to_string(&buf, t);    UNSET_ONERROR(err); -  return free_buf(&save_buf); +  return buffer_finish_pike_string(&buf);   }      #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 */    -  + #ifdef HAVE_SYS_MMAN_H + #include <sys/mman.h> + #endif +  + #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) + #define MAP_ANONYMOUS MAP_ANON + #endif /* !MAP_ANONYMOUS && MAP_ANON */ +  + #ifdef MAP_ANONYMOUS + static int type_stack_mmap, pike_type_mark_stack_mmap; + #endif +    void init_types(void)   {    /* Initialize hashtable here. */ -  pike_type_hash = (struct pike_type **)xalloc(sizeof(struct pike_type *) * +  pike_type_hash = xcalloc(sizeof(struct pike_type *),    (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;    -  +  /* if possible, use mmap with on-demand allocation */ + #ifdef MAP_ANONYMOUS + #ifndef MAP_NORESERVE + #define MAP_NORESERVE 0 + #endif /* MAP_NORESERVE */ +  type_stack = mmap( NULL, sizeof(struct pike_type *)*PIKE_TYPE_STACK_SIZE, +  PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +  if( type_stack != MAP_FAILED ) { +  type_stack_mmap = 1; +  } else { +  type_stack = NULL; +  } +  pike_type_mark_stack = +  mmap( NULL, sizeof(struct pike_type **)*PIKE_TYPE_STACK_SIZE>>2, +  PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +  if( pike_type_mark_stack != MAP_FAILED ) { +  pike_type_mark_stack_mmap = 1; +  } else { +  pike_type_mark_stack = NULL; +  } + #endif /* MAP_ANONYMOUS */ +  if( !type_stack ) +  type_stack = xalloc(sizeof(struct pike_type *)*PIKE_TYPE_STACK_SIZE); +  if( !pike_type_mark_stack ) +  pike_type_mark_stack = xalloc(sizeof(struct pike_type *)*PIKE_TYPE_STACK_SIZE / 4); +  +  Pike_compiler->type_stackp = type_stack; +  Pike_compiler->pike_type_mark_stackp = pike_type_mark_stack; +     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); -  +  inheritable_type_string = CONSTTYPE(tOr3(tPrg(tObj), tObj, +  tFuncV(tNone, tOr(tVoid, tMix), +  tObj))); +  typeable_type_string = CONSTTYPE(tOr4(tPrg(tObj), tObj, +  tFuncV(tNone, tOr(tVoid, tMix), +  tObj), +  tType(tMix)));    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)); +  utf8_type_string = CONSTTYPE(tUtf8Str); +     /* add_ref(weak_type_string); *//* LEAK */    -  +  literal_string_string = make_shared_string("string"); +  literal_int_string = make_shared_string("int"); +  literal_float_string = make_shared_string("float"); +  literal_function_string = make_shared_string("function"); +  literal_object_string = make_shared_string("object"); +  literal_program_string = make_shared_string("program"); +  literal_array_string = make_shared_string("array"); +  literal_multiset_string = make_shared_string("multiset"); +  literal_mapping_string = make_shared_string("mapping"); +  literal_type_string = make_shared_string("type"); +  literal_mixed_string = make_shared_string("mixed"); +    #ifdef PIKE_DEBUG    pike_type_gc_callback = add_gc_callback(gc_mark_external_types, NULL, NULL);   #endif   }      void cleanup_pike_types(void)   {   #ifdef DO_PIKE_CLEANUP    while (all_pike_type_locations) {    free_type(all_pike_type_locations->t);    all_pike_type_locations = all_pike_type_locations->next;    } -  + #ifdef MAP_ANONYMOUS +  if( type_stack_mmap ) +  { +  munmap( type_stack, sizeof(struct pike_type *)*PIKE_TYPE_STACK_SIZE); +  type_stack = NULL; +  } +  if( pike_type_mark_stack_mmap ) +  { +  munmap( pike_type_mark_stack, sizeof(struct pike_type *)*PIKE_TYPE_STACK_SIZE>>2); +  pike_type_mark_stack = NULL; +  } + #endif +  free( type_stack ); +  free( pike_type_mark_stack );   #endif /* DO_PIKE_CLEANUP */       clear_markers();       free_type(string0_type_string);    string0_type_string = NULL;    free_type(string_type_string);    string_type_string = NULL;    free_type(int_type_string);    int_type_string = NULL;
pike.git/src/pike_types.c:8750:    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(inheritable_type_string); +  inheritable_type_string = NULL; +  free_type(typeable_type_string); +  typeable_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; +  free_type(utf8_type_string); +  utf8_type_string = NULL; +  +  free_string(literal_string_string); literal_string_string = NULL; +  free_string(literal_int_string); literal_int_string = NULL; +  free_string(literal_float_string); literal_float_string = NULL; +  free_string(literal_function_string); literal_function_string = NULL; +  free_string(literal_object_string); literal_object_string = NULL; +  free_string(literal_program_string); literal_program_string = NULL; +  free_string(literal_array_string); literal_array_string = NULL; +  free_string(literal_multiset_string); literal_multiset_string = NULL; +  free_string(literal_mapping_string); literal_mapping_string = NULL; +  free_string(literal_type_string); literal_type_string = NULL; +  free_string(literal_mixed_string); literal_mixed_string = NULL; +    #ifdef PIKE_DEBUG    remove_callback(pike_type_gc_callback);   #endif   }      void cleanup_pike_type_table(void)   {    /* Free the hashtable here. */    if (pike_type_hash) {    free(pike_type_hash);
pike.git/src/pike_types.c:8806:    switch(t->type) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING:    res = find_type(t->car, cb);    if (res) return res; -  /* FALL_THROUGH */ +  /* FALLTHRU */    case T_SCOPE:    case T_ASSIGN:    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME:    return find_type(t->cdr, cb);       case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:
pike.git/src/pike_types.c:8848: Inside #if defined(PIKE_DEBUG)
   case T_OBJECT:    break;    default:    Pike_fatal("find_type: Unhandled type-node: %d\n", t->type);    break;   #endif /* PIKE_DEBUG */    }    return NULL;   }    - PMOD_EXPORT void visit_type (struct pike_type *t, int action) + PMOD_EXPORT void visit_type (struct pike_type *t, int action, void *extra)   { -  switch (action) { +  visit_enter(t, PIKE_T_TYPE, extra); +  switch (action & VISIT_MODE_MASK) {   #ifdef PIKE_DEBUG    default:    Pike_fatal ("Unknown visit action %d.\n", action);    case VISIT_NORMAL:    break;   #endif    case VISIT_COMPLEX_ONLY: -  +  visit_leave(t, PIKE_T_TYPE, extra);    return;    case VISIT_COUNT_BYTES:    mc_counted_bytes += sizeof (struct pike_type);    break;    }       switch (t->type) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING: -  visit_type_ref (t->car, REF_TYPE_INTERNAL); -  /* FALL_THROUGH */ +  visit_type_ref (t->car, REF_TYPE_INTERNAL, extra); +  /* FALLTHRU */    case T_SCOPE:    case T_ASSIGN: -  visit_type_ref (t->cdr, REF_TYPE_INTERNAL); +  visit_type_ref (t->cdr, REF_TYPE_INTERNAL, extra);    break;    case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING: -  visit_type_ref (t->car, REF_TYPE_INTERNAL); +  visit_type_ref (t->car, REF_TYPE_INTERNAL, extra);    break;    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME: -  visit_string_ref ((struct pike_string *) t->car, REF_TYPE_INTERNAL); -  visit_type_ref (t->cdr, REF_TYPE_INTERNAL); +  visit_string_ref ((struct pike_string *) t->car, REF_TYPE_INTERNAL, +  extra); +  visit_type_ref (t->cdr, REF_TYPE_INTERNAL, extra);    break;   #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':    case '3':    case '4':    case '5':    case '6':    case '7':
pike.git/src/pike_types.c:8915: Inside #if defined(PIKE_DEBUG)
   case T_ZERO:    case PIKE_T_UNKNOWN:    case T_INT:    case T_OBJECT:    break;    default:    Pike_fatal("visit_type: Unhandled type-node: %d\n", t->type);    break;   #endif /* PIKE_DEBUG */    } +  visit_leave(t, PIKE_T_TYPE, extra);   }      #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)      /* This is only enough gc stuff to detect leaking pike_type structs    * and to locate references to them. More is needed if types are    * extended to contain pointers to other memory objects or if they    * might contain cycles. */      void gc_mark_type_as_referenced(struct pike_type *t)
pike.git/src/pike_types.c:8957: Inside #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
   case PIKE_T_TYPE:    case PIKE_T_PROGRAM:    if (t->car) gc_mark_type_as_referenced(t->car);    break;    }    } GC_LEAVE;    }   }      #ifdef PIKE_DEBUG - static void gc_mark_external_types(struct callback *cb, void *a, void *b) + static void gc_mark_external_types(struct callback *UNUSED(cb), +  void *UNUSED(a), void *UNUSED(b))   {    unsigned int e;    for (e = 0; e < NELEM (a_markers); e++) {    if (a_markers[e])    gc_mark_external (a_markers[e], " in a_markers");    if (b_markers[e])    gc_mark_external (b_markers[e], " in b_markers");    }       if (string0_type_string)
pike.git/src/pike_types.c:9027: Inside #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
      GC_ENTER (t, T_TYPE) {    switch (t->type) {    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case T_OR:    case T_AND:    case PIKE_T_RING: +  debug_gc_check (t->car, " as car in a type"); +  debug_gc_check (t->cdr, " as cdr in a type"); +  break;    case PIKE_T_ATTRIBUTE:    case PIKE_T_NAME: -  + #ifdef PIKE_DEBUG +  /* this is a string and without PIKE_DEBUG +  * they are not touched by the GC */    debug_gc_check (t->car, " as car in a type"); -  + #endif    debug_gc_check (t->cdr, " as cdr in a type");    break;    case T_ARRAY:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case T_PROGRAM:    case T_STRING: -  +  case PIKE_T_AUTO:    debug_gc_check (t->car, " as car in a type");    break;    case T_SCOPE:    case T_ASSIGN:    debug_gc_check (t->cdr, " as cdr in a type");    break;   #ifdef PIKE_DEBUG    case '0':    case '1':    case '2':
pike.git/src/pike_types.c:9074: Inside #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) and #if defined(PIKE_DEBUG)
   Pike_fatal("gc_check_type: "    "Unhandled type-node: %d\n", t->type);    break;   #endif /* PIKE_DEBUG */    }    } GC_LEAVE;   }      void gc_check_all_types (void)   { -  unsigned INT32 e; +  size_t 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); +  for(t = pike_type_hash[e]; t; t=t->next) { +  if (gc_keep_markers) { +  /* Make sure that leaked types also have markers at cleanup... */ +  (void)get_marker(t);    } -  +  gc_check_type(t);    } -  +  } + }      #endif /* PIKE_DEBUG || DO_PIKE_CLEANUP */