Logo Search packages:      
Sourcecode: yasm version File versions  Download package

bytecode.c

/*
 * Bytecode utility functions
 *
 *  Copyright (C) 2001  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#define YASM_LIB_INTERNAL
#include "util.h"
/*@unused@*/ RCSID("$Id: bytecode.c 1147 2004-09-13 02:44:00Z peter $");

#include "coretype.h"
#include "file.h"

#include "errwarn.h"
#include "intnum.h"
#include "expr.h"

#include "bytecode.h"
#include "objfmt.h"
#include "dbgfmt.h"

#include "bc-int.h"
#include "expr-int.h"


struct yasm_dataval {
    /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;

    enum { DV_EMPTY, DV_EXPR, DV_STRING } type;

    union {
      /*@only@*/ yasm_expr *expn;
      /*@only@*/ char *str_val;
    } data;
};

/* Standard bytecode types */

typedef struct bytecode_data {
    yasm_bytecode bc;   /* base structure */

    /* non-converted data (linked list) */
    yasm_datavalhead datahead;

    /* final (converted) size of each element (in bytes) */
    unsigned char size;
} bytecode_data;

typedef struct bytecode_reserve {
    yasm_bytecode bc;   /* base structure */

    /*@only@*/ yasm_expr *numitems; /* number of items to reserve */
    unsigned char itemsize;       /* size of each item (in bytes) */
} bytecode_reserve;

typedef struct bytecode_incbin {
    yasm_bytecode bc;   /* base structure */

    /*@only@*/ char *filename;            /* file to include data from */

    /* starting offset to read from (NULL=0) */
    /*@only@*/ /*@null@*/ yasm_expr *start;

    /* maximum number of bytes to read (NULL=no limit) */
    /*@only@*/ /*@null@*/ yasm_expr *maxlen;
} bytecode_incbin;

typedef struct bytecode_align {
    yasm_bytecode bc;   /* base structure */

    unsigned long boundary;   /* alignment boundary */
} bytecode_align;

/* Standard bytecode callback function prototypes */

static void bc_data_destroy(yasm_bytecode *bc);
static void bc_data_print(const yasm_bytecode *bc, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_data_resolve
    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                     yasm_output_expr_func output_expr,
                     /*@null@*/ yasm_output_reloc_func output_reloc);

static void bc_reserve_destroy(yasm_bytecode *bc);
static void bc_reserve_print(const yasm_bytecode *bc, FILE *f,
                       int indent_level);
static yasm_bc_resolve_flags bc_reserve_resolve
    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                        yasm_output_expr_func output_expr,
                        /*@null@*/ yasm_output_reloc_func output_reloc);

static void bc_incbin_destroy(yasm_bytecode *bc);
static void bc_incbin_print(const yasm_bytecode *bc, FILE *f,
                      int indent_level);
static yasm_bc_resolve_flags bc_incbin_resolve
    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                       yasm_output_expr_func output_expr,
                       /*@null@*/ yasm_output_reloc_func output_reloc);

static void bc_align_destroy(yasm_bytecode *bc);
static void bc_align_print(const yasm_bytecode *bc, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_align_resolve
    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                      yasm_output_expr_func output_expr,
                      /*@null@*/ yasm_output_reloc_func output_reloc);

/* Standard bytecode callback structures */

static const yasm_bytecode_callback bc_data_callback = {
    bc_data_destroy,
    bc_data_print,
    bc_data_resolve,
    bc_data_tobytes
};

static const yasm_bytecode_callback bc_reserve_callback = {
    bc_reserve_destroy,
    bc_reserve_print,
    bc_reserve_resolve,
    bc_reserve_tobytes
};

static const yasm_bytecode_callback bc_incbin_callback = {
    bc_incbin_destroy,
    bc_incbin_print,
    bc_incbin_resolve,
    bc_incbin_tobytes
};

static const yasm_bytecode_callback bc_align_callback = {
    bc_align_destroy,
    bc_align_print,
    bc_align_resolve,
    bc_align_tobytes
};

/* Static structures for when NULL is passed to conversion functions. */
/*  for Convert*ToBytes() */
unsigned char bytes_static[16];


yasm_immval *
00166 yasm_imm_create_int(unsigned long int_val, unsigned long line)
{
    return yasm_imm_create_expr(
      yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(int_val)),
                         line));
}

yasm_immval *
00174 yasm_imm_create_expr(yasm_expr *expr_ptr)
{
    yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval));

    im->val = expr_ptr;
    im->len = 0;
    im->sign = 0;

    return im;
}

const yasm_expr *
00186 yasm_ea_get_disp(const yasm_effaddr *ptr)
{
    return ptr->disp;
}

void
00192 yasm_ea_set_len(yasm_effaddr *ptr, unsigned int len)
{
    if (!ptr)
      return;

    /* Currently don't warn if length truncated, as this is called only from
     * an explicit override, where we expect the user knows what they're doing.
     */

    ptr->len = (unsigned char)len;
}

void
00205 yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit)
{
    if (!ptr)
      return;

    ptr->nosplit = (unsigned char)nosplit;
}

/*@-nullstate@*/
void
00215 yasm_ea_destroy(yasm_effaddr *ea)
{
    ea->callback->destroy(ea);
    yasm_expr_destroy(ea->disp);
    yasm_xfree(ea);
}
/*@=nullstate@*/

/*@-nullstate@*/
void
00225 yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
{
    fprintf(f, "%*sDisp=", indent_level, "");
    yasm_expr_print(ea->disp, f);
    fprintf(f, "\n%*sLen=%u\n", indent_level, "", (unsigned int)ea->len);
    fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit);
    ea->callback->print(ea, f, indent_level);
}
/*@=nullstate@*/

void
00236 yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
{
    if (bc->multiple)
      bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
                                   e->line);
    else
      bc->multiple = e;
}

yasm_bytecode *
yasm_bc_create_common(const yasm_bytecode_callback *callback, size_t size,
                  unsigned long line)
{
    yasm_bytecode *bc = yasm_xmalloc(size);

    bc->callback = callback;

    bc->section = NULL;

    bc->multiple = (yasm_expr *)NULL;
    bc->len = 0;

    bc->line = line;

    bc->offset = 0;

    bc->opt_flags = 0;

    bc->symrecs = NULL;

    return bc;
}

static void
bc_data_destroy(yasm_bytecode *bc)
{
    bytecode_data *bc_data = (bytecode_data *)bc;
    yasm_dvs_destroy(&bc_data->datahead);
}

static void
bc_data_print(const yasm_bytecode *bc, FILE *f, int indent_level)
{
    const bytecode_data *bc_data = (const bytecode_data *)bc;
    fprintf(f, "%*s_Data_\n", indent_level, "");
    fprintf(f, "%*sFinal Element Size=%u\n", indent_level+1, "",
          (unsigned int)bc_data->size);
    fprintf(f, "%*sElements:\n", indent_level+1, "");
    yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
}

static yasm_bc_resolve_flags
bc_data_resolve(yasm_bytecode *bc, int save,
            yasm_calc_bc_dist_func calc_bc_dist)
{
    bytecode_data *bc_data = (bytecode_data *)bc;
    yasm_dataval *dv;
    size_t slen;

    /* Count up element sizes, rounding up string length. */
    STAILQ_FOREACH(dv, &bc_data->datahead, link) {
      switch (dv->type) {
          case DV_EMPTY:
            break;
          case DV_EXPR:
            bc->len += bc_data->size;
            break;
          case DV_STRING:
            slen = strlen(dv->data.str_val);
            /* find count, rounding up to nearest multiple of size */
            slen = (slen + bc_data->size - 1) / bc_data->size;
            bc->len += slen*bc_data->size;
            break;
      }
    }

    return YASM_BC_RESOLVE_MIN_LEN;
}

static int
bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
            yasm_output_expr_func output_expr,
            /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    bytecode_data *bc_data = (bytecode_data *)bc;
    yasm_dataval *dv;
    size_t slen;
    size_t i;
    unsigned char *bufp_orig = *bufp;

    STAILQ_FOREACH(dv, &bc_data->datahead, link) {
      switch (dv->type) {
          case DV_EMPTY:
            break;
          case DV_EXPR:
            if (output_expr(&dv->data.expn, *bufp, bc_data->size,
                        (size_t)(bc_data->size*8), 0,
                        (unsigned long)(*bufp-bufp_orig), bc, 0, 1, d))
                return 1;
            *bufp += bc_data->size;
            break;
          case DV_STRING:
            slen = strlen(dv->data.str_val);
            strncpy((char *)*bufp, dv->data.str_val, slen);
            *bufp += slen;
            /* pad with 0's to nearest multiple of size */
            slen %= bc_data->size;
            if (slen > 0) {
                slen = bc_data->size-slen;
                for (i=0; i<slen; i++)
                  YASM_WRITE_8(*bufp, 0);
            }
            break;
      }
    }

    return 0;
}

yasm_bytecode *
00356 yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
                unsigned long line)
{
    bytecode_data *data;

    data = (bytecode_data *)
      yasm_bc_create_common(&bc_data_callback, sizeof(bytecode_data), line);

    data->datahead = *datahead;
    data->size = (unsigned char)size;

    return (yasm_bytecode *)data;
}

static void
bc_reserve_destroy(yasm_bytecode *bc)
{
    bytecode_reserve *reserve = (bytecode_reserve *)bc;
    yasm_expr_destroy(reserve->numitems);
}

static void
bc_reserve_print(const yasm_bytecode *bc, FILE *f, int indent_level)
{
    const bytecode_reserve *reserve = (const bytecode_reserve *)bc;
    fprintf(f, "%*s_Reserve_\n", indent_level, "");
    fprintf(f, "%*sNum Items=", indent_level, "");
    yasm_expr_print(reserve->numitems, f);
    fprintf(f, "\n%*sItem Size=%u\n", indent_level, "",
          (unsigned int)reserve->itemsize);
}

static yasm_bc_resolve_flags
bc_reserve_resolve(yasm_bytecode *bc, int save,
               yasm_calc_bc_dist_func calc_bc_dist)
{
    bytecode_reserve *reserve = (bytecode_reserve *)bc;
    yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
    /*@null@*/ yasm_expr *temp;
    yasm_expr **tempp;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;

    if (save) {
      temp = NULL;
      tempp = &reserve->numitems;
    } else {
      temp = yasm_expr_copy(reserve->numitems);
      assert(temp != NULL);
      tempp = &temp;
    }
    num = yasm_expr_get_intnum(tempp, calc_bc_dist);
    if (!num) {
      /* For reserve, just say non-constant quantity instead of allowing
       * the circular reference error to filter through.
       */
      if (temp && yasm_expr__contains(temp, YASM_EXPR_FLOAT))
          yasm__error(bc->line,
            N_("expression must not contain floating point value"));
      else
          yasm__error(bc->line,
            N_("attempt to reserve non-constant quantity of space"));
      retval = YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
    } else
      bc->len += yasm_intnum_get_uint(num)*reserve->itemsize;
    yasm_expr_destroy(temp);
    return retval;
}

static int
bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
               yasm_output_expr_func output_expr,
               /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    yasm_internal_error(N_("bc_reserve_tobytes called"));
    /*@notreached@*/
    return 1;
}

yasm_bytecode *
00435 yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
                   unsigned long line)
{
    bytecode_reserve *reserve;

    reserve = (bytecode_reserve *)
      yasm_bc_create_common(&bc_reserve_callback, sizeof(bytecode_reserve),
                        line);

    /*@-mustfree@*/
    reserve->numitems = numitems;
    /*@=mustfree@*/
    reserve->itemsize = (unsigned char)itemsize;

    return (yasm_bytecode *)reserve;
}

static void
bc_incbin_destroy(yasm_bytecode *bc)
{
    bytecode_incbin *incbin = (bytecode_incbin *)bc;
    yasm_xfree(incbin->filename);
    yasm_expr_destroy(incbin->start);
    yasm_expr_destroy(incbin->maxlen);
}

static void
bc_incbin_print(const yasm_bytecode *bc, FILE *f, int indent_level)
{
    const bytecode_incbin *incbin = (const bytecode_incbin *)bc;
    fprintf(f, "%*s_IncBin_\n", indent_level, "");
    fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
          incbin->filename);
    fprintf(f, "%*sStart=", indent_level, "");
    if (!incbin->start)
      fprintf(f, "nil (0)");
    else
      yasm_expr_print(incbin->start, f);
    fprintf(f, "%*sMax Len=", indent_level, "");
    if (!incbin->maxlen)
      fprintf(f, "nil (unlimited)");
    else
      yasm_expr_print(incbin->maxlen, f);
    fprintf(f, "\n");
}

static yasm_bc_resolve_flags
bc_incbin_resolve(yasm_bytecode *bc, int save,
              yasm_calc_bc_dist_func calc_bc_dist)
{
    bytecode_incbin *incbin = (bytecode_incbin *)bc;
    FILE *f;
    /*@null@*/ yasm_expr *temp;
    yasm_expr **tempp;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
    unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;

    /* Try to convert start to integer value */
    if (incbin->start) {
      if (save) {
          temp = NULL;
          tempp = &incbin->start;
      } else {
          temp = yasm_expr_copy(incbin->start);
          assert(temp != NULL);
          tempp = &temp;
      }
      num = yasm_expr_get_intnum(tempp, calc_bc_dist);
      if (num)
          start = yasm_intnum_get_uint(num);
      yasm_expr_destroy(temp);
      if (!num)
          return YASM_BC_RESOLVE_UNKNOWN_LEN;
    }

    /* Try to convert maxlen to integer value */
    if (incbin->maxlen) {
      if (save) {
          temp = NULL;
          tempp = &incbin->maxlen;
      } else {
          temp = yasm_expr_copy(incbin->maxlen);
          assert(temp != NULL);
          tempp = &temp;
      }
      num = yasm_expr_get_intnum(tempp, calc_bc_dist);
      if (num)
          maxlen = yasm_intnum_get_uint(num);
      yasm_expr_destroy(temp);
      if (!num)
          return YASM_BC_RESOLVE_UNKNOWN_LEN;
    }

    /* FIXME: Search include path for filename.  Save full path back into
     * filename if save is true.
     */

    /* Open file and determine its length */
    f = fopen(incbin->filename, "rb");
    if (!f) {
      yasm__error(bc->line, N_("`incbin': unable to open file `%s'"),
                incbin->filename);
      return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
    }
    if (fseek(f, 0L, SEEK_END) < 0) {
      yasm__error(bc->line, N_("`incbin': unable to seek on file `%s'"),
                incbin->filename);
      return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
    }
    flen = (unsigned long)ftell(f);
    fclose(f);

    /* Compute length of incbin from start, maxlen, and len */
    if (start > flen) {
      yasm__warning(YASM_WARN_GENERAL, bc->line,
                  N_("`incbin': start past end of file `%s'"),
                  incbin->filename);
      start = flen;
    }
    flen -= start;
    if (incbin->maxlen)
      if (maxlen < flen)
          flen = maxlen;
    bc->len += flen;
    return YASM_BC_RESOLVE_MIN_LEN;
}

static int
bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
              yasm_output_expr_func output_expr,
              /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    bytecode_incbin *incbin = (bytecode_incbin *)bc;
    FILE *f;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
    unsigned long start = 0;

    /* Convert start to integer value */
    if (incbin->start) {
      num = yasm_expr_get_intnum(&incbin->start, NULL);
      if (!num)
          yasm_internal_error(
            N_("could not determine start in bc_tobytes_incbin"));
      start = yasm_intnum_get_uint(num);
    }

    /* Open file */
    f = fopen(incbin->filename, "rb");
    if (!f) {
      yasm__error(bc->line, N_("`incbin': unable to open file `%s'"),
                incbin->filename);
      return 1;
    }

    /* Seek to start of data */
    if (fseek(f, (long)start, SEEK_SET) < 0) {
      yasm__error(bc->line, N_("`incbin': unable to seek on file `%s'"),
                incbin->filename);
      fclose(f);
      return 1;
    }

    /* Read len bytes */
    if (fread(*bufp, (size_t)bc->len, 1, f) < (size_t)bc->len) {
      yasm__error(bc->line,
                N_("`incbin': unable to read %lu bytes from file `%s'"),
                bc->len, incbin->filename);
      fclose(f);
      return 1;
    }

    *bufp += bc->len;
    fclose(f);
    return 0;
}

yasm_bytecode *
00612 yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
                  unsigned long line)
{
    bytecode_incbin *incbin;

    incbin = (bytecode_incbin *)
      yasm_bc_create_common(&bc_incbin_callback, sizeof(bytecode_incbin),
                        line);

    /*@-mustfree@*/
    incbin->filename = filename;
    incbin->start = start;
    incbin->maxlen = maxlen;
    /*@=mustfree@*/

    return (yasm_bytecode *)incbin;
}

static void
bc_align_destroy(yasm_bytecode *bc)
{
}

static void
bc_align_print(const yasm_bytecode *bc, FILE *f, int indent_level)
{
    const bytecode_align *align = (const bytecode_align *)bc;
    fprintf(f, "%*s_Align_\n", indent_level, "");
    fprintf(f, "%*sBoundary=%lu\n", indent_level, "", align->boundary);
}

static yasm_bc_resolve_flags
bc_align_resolve(yasm_bytecode *bc, int save,
             yasm_calc_bc_dist_func calc_bc_dist)
{
    yasm_internal_error(N_("TODO: align bytecode not implemented!"));
    /*@notreached@*/
    return YASM_BC_RESOLVE_ERROR;
}

static int
bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
             yasm_output_expr_func output_expr,
             /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    yasm_internal_error(N_("TODO: align bytecode not implemented!"));
    /*@notreached@*/
    return 1;
}

yasm_bytecode *
00663 yasm_bc_create_align(unsigned long boundary, unsigned long line)
{
    bytecode_align *align;

    align = (bytecode_align *)
      yasm_bc_create_common(&bc_align_callback, sizeof(bytecode_align),
                        line);

    align->boundary = boundary;

    return (yasm_bytecode *)align;
}

yasm_section *
00677 yasm_bc_get_section(yasm_bytecode *bc)
{
    return bc->section;
}

void
yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
{
    if (!bc->symrecs) {
      bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
      bc->symrecs[0] = sym;
      bc->symrecs[1] = NULL;
    } else {
      /* Very inefficient implementation for large numbers of symbols.  But
       * that would be very unusual, so use the simple algorithm instead.
       */
      size_t count = 1;
      while (bc->symrecs[count])
          count++;
      bc->symrecs = yasm_xrealloc(bc->symrecs,
                            (count+2)*sizeof(yasm_symrec *));
      bc->symrecs[count] = sym;
      bc->symrecs[count+1] = NULL;
    }
}

void
00704 yasm_bc_destroy(yasm_bytecode *bc)
{
    if (!bc)
      return;

    if (bc->callback)
      bc->callback->destroy(bc);
    yasm_expr_destroy(bc->multiple);
    yasm_xfree(bc->symrecs);
    yasm_xfree(bc);
}

void
00717 yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
{
    if (!bc->callback)
      fprintf(f, "%*s_Empty_\n", indent_level, "");
    else
      bc->callback->print(bc, f, indent_level);
    fprintf(f, "%*sMultiple=", indent_level, "");
    if (!bc->multiple)
      fprintf(f, "nil (1)");
    else
      yasm_expr_print(bc->multiple, f);
    fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
    fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
    fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}

/*@null@*/ yasm_intnum *
00734 yasm_common_calc_bc_dist(/*@null@*/ yasm_bytecode *precbc1,
                   /*@null@*/ yasm_bytecode *precbc2)
{
    unsigned int dist;
    yasm_intnum *intn;

    if (precbc2) {
      dist = precbc2->offset + precbc2->len;
      if (precbc1) {
          if (dist < precbc1->offset + precbc1->len) {
            intn = yasm_intnum_create_uint(precbc1->offset + precbc1->len
                                     - dist);
            yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, precbc1->line);
            return intn;
          }
          dist -= precbc1->offset + precbc1->len;
      }
      return yasm_intnum_create_uint(dist);
    } else {
      if (precbc1) {
          intn = yasm_intnum_create_uint(precbc1->offset + precbc1->len);
          yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, precbc1->line);
          return intn;
      } else {
          return yasm_intnum_create_uint(0);
      }
    }
}

yasm_bc_resolve_flags
00764 yasm_bc_resolve(yasm_bytecode *bc, int save,
            yasm_calc_bc_dist_func calc_bc_dist)
{
    yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
    /*@null@*/ yasm_expr *temp;
    yasm_expr **tempp;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;

    bc->len = 0;  /* start at 0 */

    if (!bc->callback)
      yasm_internal_error(N_("got empty bytecode in bc_resolve"));
    else
      retval = bc->callback->resolve(bc, save, calc_bc_dist);

    /* Multiply len by number of multiples */
    if (bc->multiple) {
      if (save) {
          temp = NULL;
          tempp = &bc->multiple;
      } else {
          temp = yasm_expr_copy(bc->multiple);
          assert(temp != NULL);
          tempp = &temp;
      }
      num = yasm_expr_get_intnum(tempp, calc_bc_dist);
      if (!num) {
          retval = YASM_BC_RESOLVE_UNKNOWN_LEN;
          if (temp && yasm_expr__contains(temp, YASM_EXPR_FLOAT)) {
            yasm__error(bc->line,
                N_("expression must not contain floating point value"));
            retval |= YASM_BC_RESOLVE_ERROR;
          }
      } else
          bc->len *= yasm_intnum_get_uint(num);
      yasm_expr_destroy(temp);
    }

    /* If we got an error somewhere along the line, clear out any calc len */
    if (retval & YASM_BC_RESOLVE_UNKNOWN_LEN)
      bc->len = 0;

    return retval;
}

/*@null@*/ /*@only@*/ unsigned char *
00810 yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
            /*@out@*/ unsigned long *multiple, /*@out@*/ int *gap,
            void *d, yasm_output_expr_func output_expr,
            /*@null@*/ yasm_output_reloc_func output_reloc)
    /*@sets *buf@*/
{
    /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
    unsigned char *origbuf, *destbuf;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
    unsigned long datasize;
    int error = 0;

    if (bc->multiple) {
      num = yasm_expr_get_intnum(&bc->multiple, NULL);
      if (!num)
          yasm_internal_error(
            N_("could not determine multiple in bc_tobytes"));
      *multiple = yasm_intnum_get_uint(num);
      if (*multiple == 0) {
          *bufsize = 0;
          return NULL;
      }
    } else
      *multiple = 1;

    datasize = bc->len / (*multiple);
    *bufsize = datasize;

    /* special case for reserve bytecodes */
    if (bc->callback == &bc_reserve_callback) {
      *gap = 1;
      return NULL;      /* we didn't allocate a buffer */
    }

    *gap = 0;

    if (*bufsize < datasize) {
      mybuf = yasm_xmalloc(sizeof(bc->len));
      origbuf = mybuf;
      destbuf = mybuf;
    } else {
      origbuf = buf;
      destbuf = buf;
    }

    if (!bc->callback)
      yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
    else
      error = bc->callback->tobytes(bc, &destbuf, d, output_expr,
                              output_reloc);

    if (!error && ((unsigned long)(destbuf - origbuf) != datasize))
      yasm_internal_error(
          N_("written length does not match optimized length"));
    return mybuf;
}

yasm_dataval *
00868 yasm_dv_create_expr(yasm_expr *expn)
{
    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));

    retval->type = DV_EXPR;
    retval->data.expn = expn;

    return retval;
}

yasm_dataval *
00879 yasm_dv_create_string(char *str_val)
{
    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));

    retval->type = DV_STRING;
    retval->data.str_val = str_val;

    return retval;
}

void
00890 yasm_dvs_destroy(yasm_datavalhead *headp)
{
    yasm_dataval *cur, *next;

    cur = STAILQ_FIRST(headp);
    while (cur) {
      next = STAILQ_NEXT(cur, link);
      switch (cur->type) {
          case DV_EXPR:
            yasm_expr_destroy(cur->data.expn);
            break;
          case DV_STRING:
            yasm_xfree(cur->data.str_val);
            break;
          default:
            break;
      }
      yasm_xfree(cur);
      cur = next;
    }
    STAILQ_INIT(headp);
}

yasm_dataval *
00914 yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
{
    if (dv) {
      STAILQ_INSERT_TAIL(headp, dv, link);
      return dv;
    }
    return (yasm_dataval *)NULL;
}

void
00924 yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
{
    yasm_dataval *cur;

    STAILQ_FOREACH(cur, head, link) {
      switch (cur->type) {
          case DV_EMPTY:
            fprintf(f, "%*sEmpty\n", indent_level, "");
            break;
          case DV_EXPR:
            fprintf(f, "%*sExpr=", indent_level, "");
            yasm_expr_print(cur->data.expn, f);
            fprintf(f, "\n");
            break;
          case DV_STRING:
            fprintf(f, "%*sString=%s\n", indent_level, "",
                  cur->data.str_val);
            break;
      }
    }
}

/* Non-macro yasm_dvs_initialize() for non-YASM_LIB_INTERNAL users. */
#undef yasm_dvs_initialize
void
00949 yasm_dvs_initialize(yasm_datavalhead *headp)
{
    STAILQ_INIT(headp);
}

Generated by  Doxygen 1.6.0   Back to index