static void bc_incbin_destroy(void *contents) { bytecode_incbin *incbin = (bytecode_incbin *)contents; yasm_xfree(incbin->filename); yasm_expr_destroy(incbin->start); yasm_expr_destroy(incbin->maxlen); yasm_xfree(contents); }
static void bc_align_destroy(void *contents) { bytecode_align *align = (bytecode_align *)contents; if (align->boundary) yasm_expr_destroy(align->boundary); if (align->fill) yasm_expr_destroy(align->fill); if (align->maxskip) yasm_expr_destroy(align->maxskip); yasm_xfree(contents); }
void yasm_vps_delete(yasm_valparamhead *headp) { yasm_valparam *cur, *next; cur = STAILQ_FIRST(headp); while (cur) { next = STAILQ_NEXT(cur, link); if (cur->val) yasm_xfree(cur->val); switch (cur->type) { case YASM_PARAM_ID: yasm_xfree(cur->param.id); break; case YASM_PARAM_STRING: yasm_xfree(cur->param.str); break; case YASM_PARAM_EXPR: yasm_expr_destroy(cur->param.e); break; } yasm_xfree(cur); cur = next; } STAILQ_INIT(headp); }
void yasm_value_delete(yasm_value *value) { if (value->abs) yasm_expr_destroy(value->abs); value->abs = NULL; value->rel = NULL; }
void yasm_bc_destroy(yasm_bytecode *bc) { if (!bc) return; if (bc->callback) bc->callback->destroy(bc->contents); yasm_expr_destroy(bc->multiple); if (bc->symrecs) yasm_xfree(bc->symrecs); yasm_xfree(bc); }
int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line, void *data, uintptr_t arg) { yasm_object *object = (yasm_object *)obj; /*@only@*/ /*@null@*/ yasm_expr *e; /*@dependent@*/ /*@null@*/ yasm_intnum *local; yasm_intnum **intn = (yasm_intnum **)data; if (*intn) yasm_intnum_destroy(*intn); if (!(e = yasm_vp_expr(vp, object->symtab, line)) || !(local = yasm_expr_get_intnum(&e, 0))) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("argument to `%s' is not an integer"), vp->val); if (e) yasm_expr_destroy(e); return -1; } *intn = yasm_intnum_copy(local); yasm_expr_destroy(e); return 0; }
int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line, void *data, uintptr_t arg) { yasm_object *object = (yasm_object *)obj; yasm_expr **expr = (yasm_expr **)data; if (*expr) yasm_expr_destroy(*expr); if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) { yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"), vp->val); return -1; } return 0; }
static void x86_dir_bits(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch; yasm_valparam *vp; /*@only@*/ /*@null@*/ yasm_expr *e = NULL; const yasm_intnum *intn; long lval; if ((vp = yasm_vps_first(valparams)) && !vp->val && (e = yasm_vp_expr(vp, object->symtab, line)) != NULL && (intn = yasm_expr_get_intnum(&e, 0)) != NULL && (lval = yasm_intnum_get_int(intn)) && (lval == 16 || lval == 32 || lval == 64)) arch_x86->mode_bits = (unsigned char)lval; else yasm_error_set(YASM_ERROR_VALUE, N_("invalid argument to [%s]"), "BITS"); if (e) yasm_expr_destroy(e); }
int yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf, size_t destsize, yasm_bytecode *bc, int warn, yasm_arch *arch) { /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; /*@only@*/ yasm_intnum *outval; int sym_local; int retval = 1; unsigned int valsize = value->size; if (value->no_warn) warn = 0; if (value->abs) { /* Handle floating point expressions */ if (!value->rel && value->abs->op == YASM_EXPR_IDENT && value->abs->terms[0].type == YASM_EXPR_FLOAT) { if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt, buf, destsize, valsize, 0, warn)) return -1; else return 1; } /* Check for complex float expressions */ if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) { yasm_error_set(YASM_ERROR_FLOATING_POINT, N_("floating point expression too complex")); return -1; } /* Handle normal integer expressions */ intn = yasm_expr_get_intnum(&value->abs, 1); if (!intn) { /* Second try before erroring: yasm_expr_get_intnum doesn't handle * SEG:OFF, so try simplifying out any to just the OFF portion, * then getting the intnum again. */ yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs); if (seg) yasm_expr_destroy(seg); intn = yasm_expr_get_intnum(&value->abs, 1); } if (!intn) { /* Still don't have an integer! */ yasm_error_set(YASM_ERROR_TOO_COMPLEX, N_("expression too complex")); return -1; } } /* Adjust warn for signed/unsigned integer warnings */ if (warn != 0) warn = value->sign ? -1 : 1; if (value->rel) { /* If relative portion is not in bc section, don't try to handle it * here. Otherwise get the relative portion's offset. */ /*@dependent@*/ yasm_bytecode *rel_prevbc; unsigned long dist; sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); if (value->wrt || value->seg_of || value->section_rel || !sym_local) return 0; /* we can't handle SEG, WRT, or external symbols */ if (rel_prevbc->section != bc->section) return 0; /* not in this section */ if (!value->curpos_rel) return 0; /* not PC-relative */ /* Calculate value relative to current assembly position */ dist = yasm_bc_next_offset(rel_prevbc); if (dist < bc->offset) { outval = yasm_intnum_create_uint(bc->offset - dist); yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); } else { dist -= bc->offset; outval = yasm_intnum_create_uint(dist); } if (value->rshift > 0) { /*@only@*/ yasm_intnum *shamt = yasm_intnum_create_uint((unsigned long)value->rshift); yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); yasm_intnum_destroy(shamt); } /* Add in absolute portion */ if (intn) yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); /* Output! */ if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, bc, warn)) retval = -1; yasm_intnum_destroy(outval); return retval; } if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel || value->section_rel) return 0; /* We can't handle this with just an absolute */ if (intn) { /* Output just absolute portion */ if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc, warn)) retval = -1; } else { /* No absolute or relative portions: output 0 */ outval = yasm_intnum_create_uint(0); if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, bc, warn)) retval = -1; yasm_intnum_destroy(outval); } return retval; }
int yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc) { if (!value->abs) return 0; value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); /* quit early if there was an issue in simplify() */ if (yasm_error_occurred()) return 1; /* Strip top-level AND masking to an all-1s mask the same size * of the value size. This allows forced avoidance of overflow warnings. */ if (value->abs->op == YASM_EXPR_AND) { int term; /* Calculate 1<<size - 1 value */ yasm_intnum *mask = yasm_intnum_create_uint(1); yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size); yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp); yasm_intnum_set_uint(mask_tmp, 1); yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp); yasm_intnum_destroy(mask_tmp); /* Walk terms and delete matching masks */ for (term=value->abs->numterms-1; term>=0; term--) { if (value->abs->terms[term].type == YASM_EXPR_INT && yasm_intnum_compare(value->abs->terms[term].data.intn, mask) == 0) { /* Delete the intnum */ yasm_intnum_destroy(value->abs->terms[term].data.intn); /* Slide everything to its right over by 1 */ if (term != value->abs->numterms-1) /* if it wasn't last.. */ memmove(&value->abs->terms[term], &value->abs->terms[term+1], (value->abs->numterms-1-term)* sizeof(yasm_expr__item)); /* Update numterms */ value->abs->numterms--; /* Indicate warnings have been disabled */ value->no_warn = 1; } } if (value->abs->numterms == 1) value->abs->op = YASM_EXPR_IDENT; yasm_intnum_destroy(mask); } /* Handle trivial (IDENT) cases immediately */ if (value->abs->op == YASM_EXPR_IDENT) { switch (value->abs->terms[0].type) { case YASM_EXPR_INT: if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { yasm_expr_destroy(value->abs); value->abs = NULL; } return 0; case YASM_EXPR_REG: case YASM_EXPR_FLOAT: return 0; case YASM_EXPR_SYM: value->rel = value->abs->terms[0].data.sym; yasm_expr_destroy(value->abs); value->abs = NULL; return 0; case YASM_EXPR_EXPR: /* Bring up lower values. */ while (value->abs->op == YASM_EXPR_IDENT && value->abs->terms[0].type == YASM_EXPR_EXPR) { yasm_expr *sube = value->abs->terms[0].data.expn; yasm_xfree(value->abs); value->abs = sube; } break; default: yasm_internal_error(N_("unexpected expr term type")); } } if (value_finalize_scan(value, value->abs, precbc, 0)) return 1; value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); /* Simplify 0 in abs to NULL */ if (value->abs->op == YASM_EXPR_IDENT && value->abs->terms[0].type == YASM_EXPR_INT && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { yasm_expr_destroy(value->abs); value->abs = NULL; } return 0; }
static int value_finalize_scan(yasm_value *value, yasm_expr *e, /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok) { int i; /*@dependent@*/ yasm_section *sect; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; unsigned long shamt; /* for SHR */ /* Yes, this has a maximum upper bound on 32 terms, based on an * "insane number of terms" (and ease of implementation) WAG. * The right way to do this would be a stack-based alloca, but that's * not ISO C. We really don't want to malloc here as this function is * hit a lot! * * This is a bitmask to keep things small, as this is a recursive * routine and we don't want to eat up stack space. */ unsigned long used; /* for ADD */ /* Thanks to this running after a simplify, we don't need to iterate * down through IDENTs or handle SUB. * * We scan for a single symrec, gathering info along the way. After * we've found the symrec, we keep scanning but error if we find * another one. We pull out the single symrec and any legal operations * performed on it. * * Also, if we find a float anywhere, we don't allow mixing of a single * symrec with it. */ switch (e->op) { case YASM_EXPR_ADD: /* Okay for single symrec anywhere in expr. * Check for single symrec anywhere. * Handle symrec-symrec by checking for (-1*symrec) * and symrec term pairs (where both symrecs are in the same * segment). */ if (e->numterms > 32) yasm__fatal(N_("expression on line %d has too many add terms;" " internal limit of 32"), e->line); used = 0; for (i=0; i<e->numterms; i++) { int j; yasm_expr *sube; yasm_intnum *intn; yasm_symrec *sym; /*@dependent@*/ yasm_section *sect2; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2; /* First look for an (-1*symrec) term */ if (e->terms[i].type != YASM_EXPR_EXPR) continue; sube = e->terms[i].data.expn; if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) { /* recurse instead */ if (value_finalize_scan(value, sube, expr_precbc, ssym_not_ok)) return 1; continue; } if (sube->terms[0].type == YASM_EXPR_INT && sube->terms[1].type == YASM_EXPR_SYM) { intn = sube->terms[0].data.intn; sym = sube->terms[1].data.sym; } else if (sube->terms[0].type == YASM_EXPR_SYM && sube->terms[1].type == YASM_EXPR_INT) { sym = sube->terms[0].data.sym; intn = sube->terms[1].data.intn; } else { if (value_finalize_scan(value, sube, expr_precbc, ssym_not_ok)) return 1; continue; } if (!yasm_intnum_is_neg1(intn)) { if (value_finalize_scan(value, sube, expr_precbc, ssym_not_ok)) return 1; continue; } /* Look for the same symrec term; even if both are external, * they should cancel out. */ for (j=0; j<e->numterms; j++) { if (e->terms[j].type == YASM_EXPR_SYM && e->terms[j].data.sym == sym && (used & (1<<j)) == 0) { /* Mark as used */ used |= 1<<j; /* Replace both symrec portions with 0 */ yasm_expr_destroy(sube); e->terms[i].type = YASM_EXPR_INT; e->terms[i].data.intn = yasm_intnum_create_uint(0); e->terms[j].type = YASM_EXPR_INT; e->terms[j].data.intn = yasm_intnum_create_uint(0); break; /* stop looking */ } } if (j != e->numterms) continue; if (!yasm_symrec_get_label(sym, &precbc)) { if (value_finalize_scan(value, sube, expr_precbc, ssym_not_ok)) return 1; continue; } sect2 = yasm_bc_get_section(precbc); /* Now look for a unused symrec term in the same segment */ for (j=0; j<e->numterms; j++) { if (e->terms[j].type == YASM_EXPR_SYM && yasm_symrec_get_label(e->terms[j].data.sym, &precbc2) && (sect = yasm_bc_get_section(precbc2)) && sect == sect2 && (used & (1<<j)) == 0) { /* Mark as used */ used |= 1<<j; break; /* stop looking */ } } /* We didn't match in the same segment. If the * -1*symrec is actually -1*curpos, we can match * unused symrec terms in other segments and generate * a curpos-relative reloc. * * Similarly, handle -1*symrec in other segment via the * following transformation: * other-this = (other-.)+(.-this) * We can only do this transformation if "this" is in * this expr's segment. * * Don't do this if we've already become curpos-relative. * The unmatched symrec will be caught below. */ if (j == e->numterms && !value->curpos_rel && (yasm_symrec_is_curpos(sym) || (expr_precbc && sect2 == yasm_bc_get_section(expr_precbc)))) { for (j=0; j<e->numterms; j++) { if (e->terms[j].type == YASM_EXPR_SYM && !yasm_symrec_get_equ(e->terms[j].data.sym) && !yasm_symrec_is_special(e->terms[j].data.sym) && (used & (1<<j)) == 0) { /* Mark as used */ used |= 1<<j; /* Mark value as curpos-relative */ if (value->rel || ssym_not_ok) return 1; value->rel = e->terms[j].data.sym; value->curpos_rel = 1; if (yasm_symrec_is_curpos(sym)) { /* Replace both symrec portions with 0 */ yasm_expr_destroy(sube); e->terms[i].type = YASM_EXPR_INT; e->terms[i].data.intn = yasm_intnum_create_uint(0); e->terms[j].type = YASM_EXPR_INT; e->terms[j].data.intn = yasm_intnum_create_uint(0); } else { /* Replace positive portion with curpos */ yasm_object *object = yasm_section_get_object(sect2); yasm_symtab *symtab = object->symtab; e->terms[j].data.sym = yasm_symtab_define_curpos (symtab, ".", expr_precbc, e->line); } break; /* stop looking */ } } } if (j == e->numterms) return 1; /* We didn't find a match! */ } /* Look for unmatched symrecs. If we've already found one or * we don't WANT to find one, error out. */ for (i=0; i<e->numterms; i++) { if (e->terms[i].type == YASM_EXPR_SYM && (used & (1<<i)) == 0) { if (value->rel || ssym_not_ok) return 1; value->rel = e->terms[i].data.sym; /* and replace with 0 */ e->terms[i].type = YASM_EXPR_INT; e->terms[i].data.intn = yasm_intnum_create_uint(0); } } break; case YASM_EXPR_SHR: /* Okay for single symrec in LHS and constant on RHS. * Single symrecs are not okay on RHS. * If RHS is non-constant, don't allow single symrec on LHS. * XXX: should rshift be an expr instead?? */ /* Check for single sym on LHS */ if (e->terms[0].type != YASM_EXPR_SYM) break; /* If we already have a sym, we can't take another one */ if (value->rel || ssym_not_ok) return 1; /* RHS must be a positive integer */ if (e->terms[1].type != YASM_EXPR_INT) return 1; /* can't shift sym by non-constant integer */ shamt = yasm_intnum_get_uint(e->terms[1].data.intn); if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX) return 1; /* total shift would be too large */ /* Update value */ value->rshift += shamt; value->rel = e->terms[0].data.sym; /* Replace symbol with 0 */ e->terms[0].type = YASM_EXPR_INT; e->terms[0].data.intn = yasm_intnum_create_uint(0); /* Just leave SHR in place */ break; case YASM_EXPR_SEG: /* Okay for single symrec (can only be done once). * Not okay for anything BUT a single symrec as an immediate * child. */ if (e->terms[0].type != YASM_EXPR_SYM) return 1; if (value->seg_of) return 1; /* multiple SEG not legal */ value->seg_of = 1; if (value->rel || ssym_not_ok) return 1; /* got a relative portion somewhere else? */ value->rel = e->terms[0].data.sym; /* replace with ident'ed 0 */ e->op = YASM_EXPR_IDENT; e->terms[0].type = YASM_EXPR_INT; e->terms[0].data.intn = yasm_intnum_create_uint(0); break; case YASM_EXPR_WRT: /* Okay for single symrec in LHS and either a register or single * symrec (as an immediate child) on RHS. * If a single symrec on RHS, can only be done once. * WRT reg is left in expr for arch to look at. */ /* Handle RHS */ switch (e->terms[1].type) { case YASM_EXPR_SYM: if (value->wrt) return 1; value->wrt = e->terms[1].data.sym; /* and drop the WRT portion */ e->op = YASM_EXPR_IDENT; e->numterms = 1; break; case YASM_EXPR_REG: break; /* ignore */ default: return 1; } /* Handle LHS */ switch (e->terms[0].type) { case YASM_EXPR_SYM: if (value->rel || ssym_not_ok) return 1; value->rel = e->terms[0].data.sym; /* and replace with 0 */ e->terms[0].type = YASM_EXPR_INT; e->terms[0].data.intn = yasm_intnum_create_uint(0); break; case YASM_EXPR_EXPR: /* recurse */ return value_finalize_scan(value, e->terms[0].data.expn, expr_precbc, ssym_not_ok); default: break; /* ignore */ } break; default: /* Single symrec not allowed anywhere */ for (i=0; i<e->numterms; i++) { switch (e->terms[i].type) { case YASM_EXPR_SYM: return 1; case YASM_EXPR_EXPR: /* recurse */ return value_finalize_scan(value, e->terms[i].data.expn, expr_precbc, 1); default: break; } } break; } return 0; }
static int xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) { /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d; yasm_sym_vis vis = yasm_symrec_get_visibility(sym); assert(info != NULL); if (info->all_syms || vis != YASM_SYM_LOCAL) { /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object); const yasm_expr *equ_val; const yasm_intnum *intn; size_t len = strlen(name); unsigned long value = 0; long scnum = -3; /* -3 = debugging symbol */ /*@dependent@*/ /*@null@*/ yasm_section *sect; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; unsigned long flags = 0; unsigned char *localbuf; if (vis & YASM_SYM_GLOBAL) flags = XDF_SYM_GLOBAL; /* Look at symrec for value/scnum/etc. */ if (yasm_symrec_get_label(sym, &precbc)) { if (precbc) sect = yasm_bc_get_section(precbc); else sect = NULL; /* it's a label: get value and offset. * If there is not a section, leave as debugging symbol. */ if (sect) { /*@dependent@*/ /*@null@*/ xdf_section_data *csectd; csectd = yasm_section_get_data(sect, &xdf_section_data_cb); if (csectd) scnum = csectd->scnum; else yasm_internal_error(N_("didn't understand section")); if (precbc) value += yasm_bc_next_offset(precbc); } } else if ((equ_val = yasm_symrec_get_equ(sym))) { yasm_expr *equ_val_copy = yasm_expr_copy(equ_val); intn = yasm_expr_get_intnum(&equ_val_copy, 1); if (!intn) { if (vis & YASM_SYM_GLOBAL) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("global EQU value not an integer expression")); yasm_errwarn_propagate(info->errwarns, equ_val->line); } } else value = yasm_intnum_get_uint(intn); yasm_expr_destroy(equ_val_copy); flags |= XDF_SYM_EQU; scnum = -2; /* -2 = absolute symbol */ } else { if (vis & YASM_SYM_EXTERN) { flags = XDF_SYM_EXTERN; scnum = -1; } } localbuf = info->buf; YASM_WRITE_32_L(localbuf, scnum); /* section number */ YASM_WRITE_32_L(localbuf, value); /* value */ YASM_WRITE_32_L(localbuf, info->strtab_offset); info->strtab_offset += (unsigned long)(len+1); YASM_WRITE_32_L(localbuf, flags); /* flags */ fwrite(info->buf, 16, 1, info->f); yasm_xfree(name); } return 0; }
/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single * expritems if possible. Uses a simple n^2 algorithm because n is usually * quite small. Also works for precbc-precbc (or symrec-precbc, * precbc-symrec). */ static /*@only@*/ yasm_expr * expr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *cbd, int (*callback) (yasm_expr__item *ei, yasm_bytecode *precbc, yasm_bytecode *precbc2, void *cbd)) { int i; /*@dependent@*/ yasm_section *sect; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; int numterms; /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and * symrec term pairs (where both symrecs are in the same segment). */ if (e->op != YASM_EXPR_ADD) return e; for (i=0; i<e->numterms; i++) { int j; yasm_expr *sube; yasm_intnum *intn; yasm_symrec *sym = NULL; /*@dependent@*/ yasm_section *sect2; /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2; /* First look for an (-1*symrec) term */ if (e->terms[i].type != YASM_EXPR_EXPR) continue; sube = e->terms[i].data.expn; if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) continue; if (sube->terms[0].type == YASM_EXPR_INT && (sube->terms[1].type == YASM_EXPR_SYM || sube->terms[1].type == YASM_EXPR_PRECBC)) { intn = sube->terms[0].data.intn; if (sube->terms[1].type == YASM_EXPR_PRECBC) precbc = sube->terms[1].data.precbc; else sym = sube->terms[1].data.sym; } else if ((sube->terms[0].type == YASM_EXPR_SYM || sube->terms[0].type == YASM_EXPR_PRECBC) && sube->terms[1].type == YASM_EXPR_INT) { if (sube->terms[0].type == YASM_EXPR_PRECBC) precbc = sube->terms[0].data.precbc; else sym = sube->terms[0].data.sym; intn = sube->terms[1].data.intn; } else continue; if (!yasm_intnum_is_neg1(intn)) continue; if (sym && !yasm_symrec_get_label(sym, &precbc)) continue; sect2 = yasm_bc_get_section(precbc); /* Now look for a symrec term in the same segment */ for (j=0; j<e->numterms; j++) { if (((e->terms[j].type == YASM_EXPR_SYM && yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) || (e->terms[j].type == YASM_EXPR_PRECBC && (precbc2 = e->terms[j].data.precbc))) && (sect = yasm_bc_get_section(precbc2)) && sect == sect2 && callback(&e->terms[j], precbc, precbc2, cbd)) { /* Delete the matching (-1*symrec) term */ yasm_expr_destroy(sube); e->terms[i].type = YASM_EXPR_NONE; break; /* stop looking for matching symrec term */ } } } /* Clean up any deleted (EXPR_NONE) terms */ numterms = 0; for (i=0; i<e->numterms; i++) { if (e->terms[i].type != YASM_EXPR_NONE) e->terms[numterms++] = e->terms[i]; /* structure copy */ } if (e->numterms != numterms) { e->numterms = numterms; e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 : sizeof(yasm_expr__item)*(numterms-2))); if (numterms == 1) e->op = YASM_EXPR_IDENT; } return e; }