pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:3879:   #endif   }            /******/      struct remap_state {    unsigned char map[0x20];    unsigned INT32 allocated; +  struct mapping *markers;   };    -  + #ifdef PIKE_NULL_IS_SPECIAL + #define INIT_REMAP_STATE(REMAP) do { \ +  memset(&REMAP, 0, sizeof(struct remap_state)); \ +  REMAP.markers = NULL; \ +  } while(0) + #else + #define INIT_REMAP_STATE(REMAP) do { \ +  memset(&REMAP, 0, sizeof(struct remap_state)); \ +  } while(0) + #endif + static inline void exit_remap_state(struct remap_state *remap) + { +  if (remap && remap->markers) { +  free_mapping(remap->markers); +  remap->markers = NULL; +  } + } + #define EXIT_REMAP_STATE(REMAP) exit_remap_state(&REMAP) +    static int alloc_remap_marker(struct remap_state *remap, int marker,    enum pt_remap_flags flags)   {    int ret;       marker = marker & 0x0f;       if (!remap || (flags & PT_FLAG_REMAP_INHIBIT)) return '0' | marker;       if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10;
pike.git/src/pike_types.cmod:3948:    marker &= 0x0f;       if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10;       if (!(m = remap->map[marker])) return;       remap->map[marker] = 0;    remap->allocated &= ~(1 << (m & 0x0f));   }    - static struct pike_type *lookup_marker(struct mapping *markers, int marker) + static struct pike_type *lookup_marker(struct remap_state *remap, int marker)   {    struct svalue key, *val;    -  if (!markers || !marker) return NULL; +  if (!remap || !remap->markers || !marker) return NULL;       SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker);    -  val = low_mapping_lookup(markers, &key); +  val = low_mapping_lookup(remap->markers, &key);    if (!val) return NULL;       if (TYPEOF(*val) == PIKE_T_TYPE) {    return val->u.type;    }    return NULL;   } - #define lookup_marker(MAP, M) ((struct pike_type *)debug_malloc_pass(lookup_marker(debug_malloc_pass(MAP), M))) + #define lookup_marker(REMAP, M) ((struct pike_type *)debug_malloc_pass(lookup_marker(REMAP, M)))    - static void store_marker(struct mapping *markers, int marker, + static void store_marker(struct remap_state *remap, int marker,    struct pike_type *value)   {    struct svalue key, val;    -  if (!markers || !marker) return; +  if (!remap || !marker) return;    -  +  if (!remap->markers) { +  remap->markers = allocate_mapping(10); +  } +     SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker);    SET_SVAL(val, T_TYPE, 0, type, value); -  mapping_insert(markers, &key, &val); +  mapping_insert(remap->markers, &key, &val);   } - #define store_marker(MAP, M, T) store_marker(debug_malloc_pass(MAP), M, debug_malloc_pass(T)) + #define store_marker(REMAP, M, T) store_marker(REMAP, M, debug_malloc_pass(T))      static void push_remap_markers(struct pike_type *t, -  struct mapping *markers, +     struct remap_state *remap,    enum pt_remap_flags flags)   {    if (!t || (flags & PT_FLAG_REMAP_INHIBIT) || -  (!remap && !markers && !(flags & PT_FLAG_REMAP_EVAL_MARKERS))) { +  (!remap && !(flags & PT_FLAG_REMAP_EVAL_MARKERS))) {    push_finished_type(t);    return;    }       /* FIXME: Use the type flags to detect whether we can just push    * the type verbatim.    */       switch(t->type & PIKE_T_MASK) {    case T_ASSIGN:    {    int marker = alloc_remap_marker(remap, CAR_TO_INT(t), flags);    -  if (!markers || !(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { -  push_remap_markers(t->cdr, markers, remap, flags); +  if (!(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  push_remap_markers(t->cdr, remap, flags);    push_assign_type(marker);    } else { -  struct pike_type *old = lookup_marker(markers, marker); +  struct pike_type *old = lookup_marker(remap, marker);    struct pike_type *new = t->cdr;    if (new) {    if (old) {    new = or_pike_types(old, new, 0);    } else {    add_ref(new);    } -  store_marker(markers, marker, new); +  store_marker(remap, marker, new);    free_pike_type(new);    } -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    }       if (flags & PT_FLAG_REMAP_BOTH_MARKERS) {    marker = alloc_remap_marker(remap, CAR_TO_INT(t),    flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    -  if (!markers || !(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  if (!(flags & PT_FLAG_REMAP_EVAL_MARKERS)) {    push_assign_type(marker);    } else { -  struct pike_type *old = lookup_marker(markers, marker); +  struct pike_type *old = lookup_marker(remap, marker);    struct pike_type *new = t->cdr;    if (old) {    new = or_pike_types(old, new, 0);    } else {    add_ref(new);    } -  store_marker(markers, marker, new); +  store_marker(remap, marker, new);    free_pike_type(new); -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);       switch(flags & PT_FLAG_REMAP_BOTH_MARKERS_MASK) {    case PT_FLAG_REMAP_BOTH_MARKERS_AND:    push_type(T_AND);    break;    case PT_FLAG_REMAP_BOTH_MARKERS_OR:    push_type(T_OR);    break;    default:    Pike_fatal("Unsupported marker joining method.\n");
pike.git/src/pike_types.cmod:4055:    }    }    }    break;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, t->type, flags); -  struct pike_type *value = lookup_marker(markers, marker); +  struct pike_type *value = lookup_marker(remap, marker);       if (value) { -  push_remap_markers(value, markers, remap, flags); -  } else if ((markers) && (flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  push_remap_markers(value, remap, flags); +  } else if (flags & PT_FLAG_REMAP_EVAL_MARKERS) {    /* Marker without matching assign. */    /* FIXME: Report error? */    push_type(T_MIXED);    } else {       /* Remap the marker. */       if (!marker) {    /* FIXME: Improve error handling here. */    push_type(T_MIXED);    } else {    push_type(marker);    }    }       if (flags & PT_FLAG_REMAP_BOTH_MARKERS) {    marker = remap_marker(remap, t->type,    flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  value = lookup_marker(markers, marker); +  value = lookup_marker(remap, marker);       if (value) { -  push_remap_markers(value, markers, remap, flags); -  } else if ((markers) && (flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  push_remap_markers(value, remap, flags); +  } else if (flags & PT_FLAG_REMAP_EVAL_MARKERS) {    /* Marker without matching assign. */    /* FIXME: Report error? */    push_type(T_MIXED);    } else {       /* Remap the marker. */       if (!marker) {    /* FIXME: Improve error handling here. */    push_type(T_MIXED);
pike.git/src/pike_types.cmod:4114:    break;    default:    Pike_fatal("Unsupported marker joining method.\n");    break;    }    }    break;    }       case PIKE_T_NAME: -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    push_type_name((struct pike_string *)(t->car));    break;       case PIKE_T_ATTRIBUTE: -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    push_type_attribute((struct pike_string *)(t->car));    break;       case T_SCOPE: -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    push_scope_type(CAR_TO_INT(t));    break;       case PIKE_T_OPERATOR: -  push_remap_markers(t->car, markers, remap, flags); +  push_remap_markers(t->car, remap, flags);       if (t->type & 0x8000) { -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    push_reverse_type(t->type);    } else {    switch(t->type) {    case PIKE_T_GET_RETURN:    push_type_operator(t->type, NULL);    break;    case PIKE_T_FIND_LFUN:    push_type_operator(t->type, t->cdr);    break;    default:
pike.git/src/pike_types.cmod:4166:    case PIKE_T_MIXED:    push_finished_type(t);    break;       /* Unary */    case T_PROGRAM:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case PIKE_T_AUTO: -  push_remap_markers(t->car, markers, remap, flags); +  push_remap_markers(t->car, remap, flags);    push_type(t->type);    break;       /* Binary */    case T_OR:    case T_AND:    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    case PIKE_T_TRANSITIVE: -  push_remap_markers(t->car, markers, remap, flags); -  push_remap_markers(t->cdr, markers, remap, flags); +  push_remap_markers(t->car, remap, flags); +  push_remap_markers(t->cdr, remap, flags);    push_reverse_type(t->type);    break;    }   }      /**    * Remap markers (if any) in the type.    */   static struct pike_type *remap_markers(struct pike_type *t, -  struct mapping *markers, +     struct remap_state *remap,    enum pt_remap_flags flags)   {    if (!t) return NULL;       if (flags & PT_FLAG_REMAP_TRACE) {    fprintf(stderr, "remap_markers(");    simple_describe_type(t);    fprintf(stderr, ", "); -  simple_describe_mapping(markers); +  simple_describe_mapping(remap->markers);    fprintf(stderr, ", %p, 0x%02x)\n", remap, flags);    }       type_stack_mark(); -  push_remap_markers(t, markers, remap, flags); +  push_remap_markers(t, remap, flags);       if (flags & PT_FLAG_REMAP_TRACE) {    fprintf(stderr, "remap ==> ");    simple_describe_type(peek_type_stack());    fprintf(stderr, "\n");    }    return pop_unfinished_type();   }      static struct pike_type *low_intersect_types(struct pike_type *a,
pike.git/src/pike_types.cmod:4428:    a = b;    b = tmp;    avoidable = aflags;    aflags = bflags;    bflags = avoidable;    remap_flags ^= PT_FLAG_REMAP_SWAP_MARKERS;    op = PT_BINOP_MINUS;    break;    case PT_BINOP_NOR:    type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    push_type(T_NOT);    return pop_unfinished_type();    case PT_BINOP_OR:    type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    return pop_unfinished_type();       case PT_BINOP_XOR:    /* A XOR B == (A OR B) - (A AND B) */    tmp = low_type_binop(PT_BINOP_OR, a, b, remap,    aflags, bflags, remap_flags);    if (!tmp) return NULL;       tmp2 = low_type_binop(PT_BINOP_AND, a, b, remap,
pike.git/src/pike_types.cmod:4484:   #ifdef PIKE_DEBUG    Pike_fatal("Unsupported binary type operation: 0x%02x\n", op);   #endif    break;    }       full_loop:    if (a == b) {    if (op & PT_BINOP_AND) {    /* FIXME: Perform masking of remap_flags here. */ -  return remap_markers(a, NULL, remap, +  return remap_markers(a, remap,    remap_flags | PT_FLAG_REMAP_BOTH_MARKERS_AND);    } else {    return NULL;    }    }       /* First check for markers. */    switch(a?a->type:PIKE_T_UNKNOWN) {    case T_ASSIGN:    {
pike.git/src/pike_types.cmod:4633:    }       switch(op) {    case PT_BINOP_AND:    /* NB: Attempt to avoid keeping the result from inverted types,    * in order to reduce type expansion.    */    if (a->car->type == T_NOT) {    /* (!a1 & a2) & b <==> (a2 & b) & !a1 */    free_type(tmp); -  tmp = remap_markers(a->car, NULL, remap, remap_flags); +  tmp = remap_markers(a->car, remap, remap_flags);    } else if (a->cdr->type == T_NOT) {    /* (a1 & !a2) & b <==> (a1 & b) & !a2 */    free_type(tmp2); -  tmp2 = remap_markers(a->cdr, NULL, remap, remap_flags); +  tmp2 = remap_markers(a->cdr, remap, remap_flags);    }    break;    default:    /* Make the C-compiler happy. */    break;    }       type_stack_mark();    push_finished_type(tmp);    push_finished_type(tmp2);
pike.git/src/pike_types.cmod:4676:    *    * A - (B | C) == (A - B) - C    * rather than    * A - (B | C) == (A - B) & (A - C)    *    * A | (B | C) == (A | B) | C    * rather than    * A | (B | C) == (A | B) | (A | C)    */    tmp = low_type_binop(op, a, b->car, remap, aflags, bflags, remap_flags); -  tmp2 = remap_markers(b->cdr, NULL, remap, +  tmp2 = remap_markers(b->cdr, remap,    remap_flags | PT_FLAG_REMAP_SWAP_MARKERS);    ret = low_type_binop(op, tmp, tmp2, NULL, aflags, bflags, 0);    free_type(tmp);    free_type(tmp2);    return ret;    }    /* FALLTHRU */    case T_AND:    /* op secondary(T_AND) secondary(T_OR)    * 0 0000 0 0000 0 0000
pike.git/src/pike_types.cmod:4726:    free_type(tmp2);    return NULL;    }       if ((b->type == T_AND) && (op == PT_BINOP_AND)) {    /* NB: Attempt to avoid keeping the result from inverted types,    * in order to reduce type expansion.    */    if (b->car->type == T_NOT) {    free_type(tmp); -  tmp = remap_markers(b->car, NULL, remap, +  tmp = remap_markers(b->car, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    } else if (b->cdr->type == T_NOT) {    free_type(tmp2); -  tmp2 = remap_markers(b->cdr, NULL, remap, +  tmp2 = remap_markers(b->cdr, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    }       type_stack_mark();    push_finished_type(tmp);    push_finished_type(tmp2);    push_reverse_type(T_AND);    } else {    /* Secondary operator is OR. */
pike.git/src/pike_types.cmod:4778:    switch(a ? a->type : PIKE_T_UNKNOWN) {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, a->type, remap_flags);    if (!marker) {    a = NULL;    break;    }    -  tmp = remap_markers(b, NULL, remap, +  tmp = remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!tmp) {    b = NULL;    break;    }    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_binop(op);    free_type(tmp);
pike.git/src/pike_types.cmod:4803:    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, b->type,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!marker) {    b = NULL;    break;    }    -  tmp = remap_markers(a, NULL, remap, remap_flags); +  tmp = remap_markers(a, remap, remap_flags);    if (!tmp) {    a = NULL;    break;    }    type_stack_mark();    push_type(marker);    push_finished_type(tmp);    push_binop(op);    free_type(tmp);    return pop_unfinished_type();
pike.git/src/pike_types.cmod:5158:    complex_function:       nargs = peek_stack_mark();    if (op != PT_BINOP_AND) {    nargs = 0;    ai = a;    bi = b;    }       /* Either of a and/or b is a complex type. */ -  push_remap_markers(bi, NULL, remap, +  push_remap_markers(bi, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  push_remap_markers(ai, NULL, remap, remap_flags); +  push_remap_markers(ai, remap, remap_flags);       push_binop(op);       while (nargs--) {    push_reverse_type(T_FUNCTION);    }    return pop_unfinished_type();       function_fail:    compiler_discard_type();
pike.git/src/pike_types.cmod:5312:    goto recur;    }    }       if (a->type != T_VOID) {    if (b->type == T_MIXED) {    switch(op & PT_BINOP_B) {    case 0:    return NULL;    case PT_BINOP_AND: -  return remap_markers(a, NULL, remap, remap_flags); +  return remap_markers(a, remap, remap_flags);    case PT_BINOP_INVERSE_MINUS:    if (bflags & PT_FLAG_CMP_INSEPARABLE) {    return NULL;    }    type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    push_type(T_NOT);    return pop_unfinished_type();    default:    add_ref(b);    return b;    }    }    }    if (b->type != T_VOID) {    if (a->type == T_MIXED) {    switch(op & PT_BINOP_A) {    case 0:    return NULL;    case PT_BINOP_AND: -  return remap_markers(b, NULL, remap, +  return remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    case PT_BINOP_MINUS:    if (aflags & PT_FLAG_CMP_INSEPARABLE) {    return NULL;    }    type_stack_mark(); -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    return pop_unfinished_type();    default:    add_ref(a);    return a;    }    }    }   
pike.git/src/pike_types.cmod:5374:    if (op == PT_BINOP_AND) {    a = zero_type_string;    }    aflags &= ~PT_FLAG_CMP_NULLABLE;    goto recur;    }       if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) ||    ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) {    type_stack_mark(); -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    push_binop(op);    return pop_unfinished_type();    } -  +     /* NB: We know that a and b do not intersect, so the operations    * come in pairs and complementary pairs.    */    type_stack_mark();    switch(op) {    case PT_BINOP_NONE:    case PT_BINOP_AND:    pop_stack_mark();    return NULL;    case PT_BINOP_NAND:    case PT_BINOP_ALL:    push_type(T_MIXED);    break;       case PT_BINOP_MINUS:    case PT_BINOP_A: -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    break;    case PT_BINOP_NOT_A:    case PT_BINOP_NOT_A_OR_B:    if (aflags & PT_FLAG_CMP_INSEPARABLE) {    pop_stack_mark();    return NULL;    } -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    push_type(T_NOT);    break;       case PT_BINOP_INVERSE_MINUS:    case PT_BINOP_B: -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    break;    case PT_BINOP_NOT_B:    case PT_BINOP_A_OR_NOT_B:    if (bflags & PT_FLAG_CMP_INSEPARABLE) {    pop_stack_mark();    return NULL;    } -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    break;       case PT_BINOP_OR:    case PT_BINOP_XOR: -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    push_type(T_OR);    break;    case PT_BINOP_NOR:    case PT_BINOP_XNOR:    if ((aflags | bflags) & PT_FLAG_CMP_INSEPARABLE) {    pop_stack_mark();    return NULL;    } -  push_remap_markers(b, NULL, remap, +  push_remap_markers(b, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    push_type(T_OR);    push_type(T_NOT);    break;    }    return pop_unfinished_type();    }       /* Invariant: a->type == b->type. */       switch(a->type) {
pike.git/src/pike_types.cmod:5788:   }      struct pike_type *type_binop(enum pt_binop op,    struct pike_type *a,    struct pike_type *b,    enum pt_cmp_flags aflags,    enum pt_cmp_flags bflags,    enum pt_remap_flags remap_flags)   {    struct remap_state remap; +  struct pike_type *ret;    -  memset(&remap, 0, sizeof(remap)); +  INIT_REMAP_STATE(remap);    -  return low_type_binop(op, a, b, &remap, aflags, bflags, remap_flags); +  ret = low_type_binop(op, a, b, &remap, aflags, bflags, remap_flags); +  +  EXIT_REMAP_STATE(remap); +  +  return ret;   }      /**    * Low-level subtraction (aka And-not) of two types.    *    * Note:    * There are two major operating modes; the external, where    * the two types have unrelated markers, which then need to    * be remapped in the result, and the internal, where the    * two types have related markers (this mode is used mainly
pike.git/src/pike_types.cmod:5847:    free_marker(remap, CAR_TO_INT(a), remap_flags);    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, a->type, remap_flags);    if (!marker) return NULL;    -  tmp = remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(T_NOT);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }
pike.git/src/pike_types.cmod:5884:    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, b->type,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!marker) return NULL;    -  tmp = remap_markers(a, NULL, remap, remap_flags); +  tmp = remap_markers(a, remap, remap_flags);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_type(T_NOT);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }
pike.git/src/pike_types.cmod:5986:    case T_OR:    /* DeMorgan    *    * a & ~(b1 | b2) <==> a & ~b1 & ~b2    */    tmp = low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    /* NB: We need to remap b->cdr separately to avoid remapping    * markers in a and b->car twice.    */ -  tmp2 = remap_markers(b->cdr, NULL, remap, +  tmp2 = remap_markers(b->cdr, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    ret = low_subtract_types(tmp, tmp2, NULL, aflags, bflags, 0);    free_type(tmp);    free_type(tmp2);    return ret;       case T_AND:    /* DeMorgan    *    * a & ~(b1 & b2) <==> a & (~b1 | ~b2) <==> (a & ~b1) | (a & ~b2)
pike.git/src/pike_types.cmod:6164:    }    free_type(tmp);    if (got_empty) break;    }       if (!got_full) {    return NULL;    }       type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(a, remap, remap_flags);    return pop_unfinished_type();    }       /* Advance to the next argument. */    if (ai->type == T_FUNCTION) {    ai = ai->cdr;    }    if (bi->type == T_FUNCTION) {    bi = bi->cdr;    }
pike.git/src/pike_types.cmod:6186:    break;    }    if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) {    break;    }    }       /* Either of a and/or b is a complex type, or a partial overlap. */       type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    push_reverse_type(T_AND);       return pop_unfinished_type();    }       case TWOT(T_ZERO, T_INT):    if ((CAR_TO_INT(b) <= 0) && (CDR_TO_INT(b) >= 0)) {    return NULL;    }
pike.git/src/pike_types.cmod:6291:    add_ref(a);    return a;    }       if (b->type == T_MIXED) {    /* NB: a being void has been handled above. */    return NULL;    }    if (a->type == T_MIXED) {    type_stack_mark(); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    return pop_unfinished_type();    }       if (b->type == T_NOT) {    return low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    }    if (a->type == T_NOT) {    /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */    type_stack_mark(); -  push_remap_markers(a->car, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a->car, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    push_type(T_NOT);    return pop_unfinished_type();    }       if (a->type != b->type) {    if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) ||    ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) {    type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    push_reverse_type(T_AND);    return pop_unfinished_type();    }    add_ref(a);    return a;    }       switch(a->type) {    case T_VOID:
pike.git/src/pike_types.cmod:6454:    return NULL;   }      struct pike_type *subtract_types(struct pike_type *a,    struct pike_type *b,    enum pt_cmp_flags aflags,    enum pt_cmp_flags bflags,    enum pt_remap_flags remap_flags)   {    struct remap_state remap; +  struct pike_type *sub_res;    -  memset(&remap, 0, sizeof(remap)); +  INIT_REMAP_STATE(remap);    -  return low_subtract_types(a, b, &remap, aflags, bflags, remap_flags); +  sub_res = low_subtract_types(a, b, &remap, aflags, bflags, remap_flags); +  +  EXIT_REMAP_STATE(remap); +  +  return sub_res;   }      /**    * Low-level intersection (aka And) of two types.    *    * Note:    * There are two major operating modes; the external, where    * the two types have unrelated markers, which then need to    * be remapped in the result, and the internal, where the    * two types have related markers (this mode is used mainly
pike.git/src/pike_types.cmod:6488:   {    struct pike_type *tmp, *tmp2, *ret;    struct pike_type *aret = NULL, *bret = NULL;    enum pt_cmp_flags avoidable;    enum pt_cmp_flags bvoidable;       if (!a || !b) return NULL;       if (a == b) {    /* FIXME: Perform masking of remap_flags here. */ -  return remap_markers(a, NULL, remap, +  return remap_markers(a, remap,    remap_flags | PT_FLAG_REMAP_BOTH_MARKERS_AND);    }       /* First check for markers. */    switch(a->type) {    case T_ASSIGN:    {    int marker = alloc_remap_marker(remap, CAR_TO_INT(a), remap_flags);    tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (tmp) {
pike.git/src/pike_types.cmod:6612:    */    if (a->car->type == T_NOT) {    tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (!tmp2) return NULL;    tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags);    if (!tmp) {    free_type(tmp2);    return NULL;    }    free_type(tmp); -  tmp = remap_markers(a->car, NULL, remap, remap_flags); +  tmp = remap_markers(a->car, remap, remap_flags);    } else {    tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (!tmp2) {    free_type(tmp);    return NULL;    }    if (a->cdr->type == T_NOT) {    free_type(tmp2); -  tmp2 = remap_markers(a->cdr, NULL, remap, remap_flags); +  tmp2 = remap_markers(a->cdr, remap, remap_flags);    }    }       type_stack_mark();    push_finished_type(tmp);    push_finished_type(tmp2);    push_reverse_type(T_AND);    free_type(tmp);    free_type(tmp2);    return pop_unfinished_type();
pike.git/src/pike_types.cmod:6660:    case T_AND:    /* NB: Attempt to avoid keeping the result from inverted types,    * in order to reduce type expansion.    */    if (b->car->type == T_NOT) {    tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    if (tmp2) {    free_type(tmp2); -  tmp2 = remap_markers(b->car, NULL, remap, +  tmp2 = remap_markers(b->car, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    } else {    tmp = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags);    if (tmp2 && (b->cdr->type == T_NOT)) {    free_type(tmp2); -  tmp2 = remap_markers(b->cdr, NULL, remap, +  tmp2 = remap_markers(b->cdr, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    }    if (!tmp2) {    free_type(tmp);    return NULL;    }       type_stack_mark();    push_finished_type(tmp);
pike.git/src/pike_types.cmod:6856:    if (bret) {    Pike_fatal("Unsupported type operation.\n");    }    break;    }    }       nargs = pop_stack_mark();       /* Either of a and/or b is a complex type. */ -  tmp = remap_markers(a, NULL, remap, remap_flags); +  tmp = remap_markers(a, remap, remap_flags);    push_finished_type(tmp);    free_type(tmp);    -  tmp = remap_markers(b, NULL, remap, remap_flags); +  tmp = remap_markers(b, remap, remap_flags);    push_finished_type(tmp);    free_type(tmp);       push_reverse_type(T_AND);       while (nargs--) {    push_reverse_type(T_FUNCTION);    }    return pop_unfinished_type();   
pike.git/src/pike_types.cmod:6972:    }    if (b->type == T_VOID) {    if (avoidable) {    add_ref(b);    return b;    }    return NULL;    }       if (a->type == T_MIXED) { -  return remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  return remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    if (b->type == T_MIXED) { -  return remap_markers(a, NULL, remap, remap_flags); +  return remap_markers(a, remap, remap_flags);    }       if (a->type == T_NOT) {    if (b->type == T_NOT) {    /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */    type_stack_mark(); -  push_remap_markers(a->car, NULL, remap, remap_flags); -  push_remap_markers(b->car, NULL, remap, +  push_remap_markers(a->car, remap, remap_flags); +  push_remap_markers(b->car, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    push_type(T_NOT);    return pop_unfinished_type();    }    /* NB: Swapped argument order! */    return low_subtract_types(b, a->car, remap, bflags, aflags,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    if (b->type == T_NOT) {    return low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags);    }       switch(a->type) {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, a->type, remap_flags);    if (!marker) return NULL;    -  tmp = remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }    switch(b->type) {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, b->type,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!marker) return NULL;    -  tmp = remap_markers(a, NULL, remap, remap_flags); +  tmp = remap_markers(a, remap, remap_flags);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }       if (a->type != b->type) {    if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) ||    ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) {    type_stack_mark(); -  push_remap_markers(a, NULL, remap, remap_flags); -  push_remap_markers(b, NULL, remap, -  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_reverse_type(T_AND);    return pop_unfinished_type();    }    return NULL;    }       switch(a->type) {    case T_VOID:    case T_ZERO:    case T_FLOAT:
pike.git/src/pike_types.cmod:7175:    return a;   }      struct pike_type *intersect_types(struct pike_type *a,    struct pike_type *b,    enum pt_cmp_flags aflags,    enum pt_cmp_flags bflags,    enum pt_remap_flags remap_flags)   {    struct remap_state remap; +  struct pike_type *and_res;    -  memset(&remap, 0, sizeof(remap)); +  INIT_REMAP_STATE(remap);    -  return low_intersect_types(a, b, &remap, aflags, bflags, remap_flags); +  and_res = low_intersect_types(a, b, &remap, aflags, bflags, remap_flags); +  +  EXIT_REMAP_STATE(remap); +  +  return and_res;   }      /*    * match two type strings, return zero if they don't match, and return    * the part of 'a' that _did_ match if it did.    */   static struct pike_type *low_match_types2(struct pike_type *a,    struct pike_type *b,    int flags);   static struct pike_type *low_match_types(struct pike_type *a,
pike.git/src/pike_types.cmod:9110:    }    return 0;   }         int match_types(struct pike_type *a, struct pike_type *b)   {    struct pike_type *res;   #ifdef PIKE_EXTRA_DEBUG    struct remap_state remap; -  struct mapping *markers; +     struct pike_type *tmp, *tmp2;    -  memset(&remap, 0, sizeof(remap)); +  INIT_REMAP_STATE(remap);       tmp = low_type_binop(PT_BINOP_AND, a, b, &remap, 0, 0, 0);    -  markers = allocate_mapping(10); -  tmp2 = remap_markers(tmp, markers, NULL, PT_FLAG_REMAP_EVAL_MARKERS); +  clear_mapping(remap.markers); +  +  tmp2 = remap_markers(tmp, &remap, PT_FLAG_REMAP_EVAL_MARKERS); +  +  EXIT_REMAP_STATE(remap);   #endif       clear_markers();    res = low_match_types(a, b, 0);    free_type(res);      #ifdef PIKE_EXTRA_DEBUG    if ((!!res) != (!!tmp2)) {    fprintf(stderr, "match_types mismatch!\n"    "a: ");
pike.git/src/pike_types.cmod:9160:    enum pt_cmp_flags aflags, enum pt_cmp_flags bflags)   {    struct remap_state remap;    struct pike_type *tmp, *tmp2 = NULL;   #ifdef PIKE_EXTRA_DEBUG    int res;    struct pike_type **save_type_stackp = Pike_compiler->type_stackp;    struct pike_type ***save_mark_stackp = Pike_compiler->pike_type_mark_stackp;   #endif    -  memset(&remap, 0, sizeof(remap)); +  INIT_REMAP_STATE(remap);       tmp = low_type_binop(PT_BINOP_MINUS, a, b, &remap, aflags, bflags, 0);       if (tmp) { -  struct mapping *markers = allocate_mapping(10); -  tmp2 = remap_markers(tmp, markers, NULL, PT_FLAG_REMAP_EVAL_MARKERS); -  free_mapping(markers); +  clear_mapping(remap.markers); +  +  tmp2 = remap_markers(tmp, &remap, PT_FLAG_REMAP_EVAL_MARKERS);    }      #ifdef PIKE_EXTRA_DEBUG    clear_markers();    res = low_pike_types_le(a, b, 0, 0);       if ((save_type_stackp != Pike_compiler->type_stackp) ||    (save_mark_stackp != Pike_compiler->pike_type_mark_stackp) ||    (res != !tmp2)) {    struct pike_type *tmp3;
pike.git/src/pike_types.cmod:9190:    "a: ");    simple_describe_type(a);    fprintf(stderr, "\nb: ");    simple_describe_type(b);    fprintf(stderr, "\nres: %d\ntmp: ", res);    simple_describe_type(tmp);    fprintf(stderr, "\ntmp2: ");    simple_describe_type(tmp2);    fprintf(stderr, "\n\n");    +  clear_mapping(remap.markers); +     tmp3 = low_type_binop(PT_BINOP_MINUS, a, b, &remap,    aflags, bflags, PT_FLAG_REMAP_TRACE);    fprintf(stderr, "tmp3: ");    simple_describe_type(tmp3);    fprintf(stderr, "\n\n");       if ((save_type_stackp != Pike_compiler->type_stackp) ||    (save_mark_stackp != Pike_compiler->pike_type_mark_stackp)) {    Pike_fatal("Stack level corruption!\n"    "type stack: %p (expected: %p)\n"    "mark stack: %p (expected: %p)\n",    Pike_compiler->type_stackp, save_type_stackp,    Pike_compiler->pike_type_mark_stackp, save_mark_stackp);    }       free_type(tmp3);    }   #endif    -  +  EXIT_REMAP_STATE(remap); +     free_type(tmp);    free_type(tmp2);       return !tmp2;   }      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);