/*
 * Bytecode utility functions
 *
 *  Copyright (C) 2001-2007  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.
 */
#include "util.h"
/*@unused@*/ RCSID("$Id$");

#include "libyasm-stdint.h"
#include "coretype.h"

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

#include "bytecode.h"


typedef struct bytecode_reserve {
    /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
    unsigned int itemsize;          /* size of each item (in bytes) */
} bytecode_reserve;

static void bc_reserve_destroy(void *contents);
static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
static int bc_reserve_elem_size(yasm_bytecode *bc);
static int bc_reserve_calc_len(yasm_bytecode *bc,
                               yasm_bc_add_span_func add_span,
                               void *add_span_data);
static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                              yasm_output_value_func output_value,
                              /*@null@*/ yasm_output_reloc_func output_reloc);

static const yasm_bytecode_callback bc_reserve_callback = {
    bc_reserve_destroy,
    bc_reserve_print,
    bc_reserve_finalize,
    bc_reserve_elem_size,
    bc_reserve_calc_len,
    yasm_bc_expand_common,
    bc_reserve_tobytes,
    YASM_BC_SPECIAL_RESERVE
};


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

static void
bc_reserve_print(const void *contents, FILE *f, int indent_level)
{
    const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
    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, "", reserve->itemsize);
}

static void
bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
{
    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
    /* multiply reserve expression into multiple */
    if (!bc->multiple)
        bc->multiple = reserve->numitems;
    else
        bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL,
                                             reserve->numitems, bc->line);
    reserve->numitems = NULL;
}

static int
bc_reserve_elem_size(yasm_bytecode *bc)
{
    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
    return reserve->itemsize;
}

static int
bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                    void *add_span_data)
{
    bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
    bc->len += reserve->itemsize;
    return 0;
}

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

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

    /*@-mustfree@*/
    reserve->numitems = numitems;
    /*@=mustfree@*/
    reserve->itemsize = itemsize;

    return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
}

const yasm_expr *
yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize)
{
    bytecode_reserve *reserve;

    if (bc->callback != &bc_reserve_callback)
        return NULL;

    reserve = (bytecode_reserve *)bc->contents;
    *itemsize = reserve->itemsize;
    return reserve->numitems;
}
