<commit_before>#include "ops.h"
// obj.h is included for RLC_* flags ; reconsider their location
#include "obj.h"
#include "parser.h"
#include "parser_global.h"
#include "lexer.h"
#include "common.h"
#include "asm.h"

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <search.h>
#include <string.h>
#include <strings.h>

#if _WIN32
#include <fcntl.h>
#include <io.h>
#endif

// flag to mark flipping value of relocations after a '-'
#define RHS_FLIP 1

static const char shortopts[] = "df:o:s" "hV";

static const struct option longopts[] = {
    { "disassemble" ,       no_argument, NULL, 'd' },
    { "format"      , required_argument, NULL, 'f' },
    { "output"      , required_argument, NULL, 'o' },
    { "strict"      ,       no_argument, NULL, 's' },

    { "help"        ,       no_argument, NULL, 'h' },
    { "version"     ,       no_argument, NULL, 'V' },

    { NULL, 0, NULL, 0 },
};

#define version() "tas version " STR(BUILD_NAME)

typedef int reloc_handler(struct parse_data *pd, struct instruction *context, int flags, struct const_expr *ce, void *ud);

static int ce_eval(struct parse_data *pd, struct instruction *context, struct
        const_expr *ce, int flags, reloc_handler *rhandler, void *rud, uint32_t *result);

static int format_has_output(const struct format *f)
{
    return !!f->out;
}

static int usage(const char *me)
{
    char format_list[256];
    make_format_list(format_has_output, formats_count, formats, sizeof format_list, format_list, ", ");

    printf("Usage:\n"
           "  %s [ OPTIONS ] assembly-or-image-file [ assembly-or-image-file ... ] \n"
           "  -d, --disassemble     disassemble (default is to assemble)\n"
           "  -f, --format=F        select output format (%s)\n"
           "  -o, --output=X        write output to filename X\n"
           "  -s, --strict          disable syntax sugar in disassembly\n"
           "  -h, --help            display this message\n"
           "  -V, --version         print the string '%s'\n"
           , me, format_list, version());

    return 0;
}

struct symbol *symbol_find(struct symbol_list *list, const char *name)
{
    list_foreach(symbol_list, elt, list)
        if (!strncmp(elt->symbol->name, name, SYMBOL_LEN))
            return elt->symbol;

    return NULL;
}

// symbol_lookup returns 1 on success
static int symbol_lookup(struct parse_data *pd, struct symbol_list *list, const
        char *name, uint32_t *result)
{
    struct symbol *symbol = NULL;
    if ((symbol = symbol_find(list, name))) {
        if (result) {
            if (symbol->ce) {
                struct instruction_list **prev = symbol->ce->deferred;
                struct instruction *c = (prev && *prev) ? (*prev)->insn : NULL;
                return ce_eval(pd, c, symbol->ce, 0, NULL, NULL, result);
            } else {
                *result = symbol->reladdr;
            }
        }
        return 1;
    }

    // unresolved symbols get a zero value, but this is still success in CE_EXT
    // case (not in CE_SYM case)
    if (result) *result = 0;
    return 0;
}

// add_relocation returns 1 on success
static int add_relocation(struct parse_data *pd, const char *name, struct instruction *insn, int width, int flags)
{
    struct reloc_list *node = calloc(1, sizeof *node);

    if (name && name[0]) {
        if (insn)
            debug(5, "Adding relocation for `%s' of width %d @ 0x%08x with flags %#x", name, width, insn->reladdr, flags);
        else
            debug(5, "Adding relocation for `%s' of width %d for NULL with flags %#x", name, width, flags);
        strcopy(node->reloc.name, name, sizeof node->reloc.name);
    } else {
        if (insn)
            debug(5, "Adding null relocation of width %d @ 0x%08x with flags %#x", width, insn->reladdr, flags);
        else
            // XXX what does a relocation with (insn == NULL) mean ?
            debug(5, "Adding null relocation of width %d for NULL with flags %#x", width, flags);
        node->reloc.name[0] = 0;
    }
    node->reloc.insn  = insn;
    node->reloc.width = width;
    node->reloc.flags = flags;

    node->next = pd->relocs;
    pd->relocs = node;

    if (insn)
        insn->reloc = &node->reloc;

    return 1;
}

static int sym_reloc_handler(struct parse_data *pd, struct instruction *context, int flags, struct const_expr *ce, void *ud)
{
    int rc = 0;
    int *width = ud;

    int rlc_flags = 0;

    if (flags & RHS_FLIP)
        rlc_flags |= RLC_NEGATE;

    switch (ce->type) {
        case CE_SYM:
        case CE_EXT:
            if (ce->symbol && ce->symbol->ce) {
                struct instruction_list **prev = ce->symbol->ce->deferred;
                // XXX ": context" is voodoo ; hasn't been justified
                struct instruction *c = (prev && *prev) ? (*prev)->insn : context;
                return c ?  add_relocation(pd, NULL, c, *width, rlc_flags) : 0;
            } else if (ce->type == CE_EXT) {
                const char *name = ce->symbol ? ce->symbol->name : ce->symbolname;
                return add_relocation(pd, rc ? name : NULL, context, *width, rlc_flags);
            }
        case CE_ICI:
            return add_relocation(pd, NULL, context, *width, rlc_flags);
        default:
            return 0;
    }

    return rc;
}

// ce_eval should be idempotent. returns 1 on fully-successful evaluation, 0 on incomplete evaluation
static int ce_eval(struct parse_data *pd, struct instruction *context, struct
        const_expr *ce, int flags, reloc_handler *rhandler, void *rud, uint32_t *result)
{
    uint32_t left, right;

    switch (ce->type) {
        case CE_SYM:
        case CE_EXT:
            if (ce->symbol && ce->symbol->ce) {
                return ce_eval(pd, (*ce->symbol->ce->deferred)->insn, ce->symbol->ce, flags, rhandler, rud, result)
                    || (rhandler ? rhandler(pd, context, flags, ce, rud) : 0);
            } else {
                const char *name = ce->symbol ? ce->symbol->name : ce->symbolname;
                return symbol_lookup(pd, pd->symbols, name, result)
                    || (rhandler ? rhandler(pd, context, flags, ce, rud) : 0);
            }<commit_msg>Bit hacky, but hello.tas.cpp works again<commit_after>#include "ops.h"
// obj.h is included for RLC_* flags ; reconsider their location
#include "obj.h"
#include "parser.h"
#include "parser_global.h"
#include "lexer.h"
#include "common.h"
#include "asm.h"

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <search.h>
#include <string.h>
#include <strings.h>

#if _WIN32
#include <fcntl.h>
#include <io.h>
#endif

// flag to mark flipping value of relocations after a '-'
#define RHS_FLIP 1

#define NO_NAMED_RELOC 2

static const char shortopts[] = "df:o:s" "hV";

static const struct option longopts[] = {
    { "disassemble" ,       no_argument, NULL, 'd' },
    { "format"      , required_argument, NULL, 'f' },
    { "output"      , required_argument, NULL, 'o' },
    { "strict"      ,       no_argument, NULL, 's' },

    { "help"        ,       no_argument, NULL, 'h' },
    { "version"     ,       no_argument, NULL, 'V' },

    { NULL, 0, NULL, 0 },
};

#define version() "tas version " STR(BUILD_NAME)

typedef int reloc_handler(struct parse_data *pd, struct instruction *context, int flags, struct const_expr *ce, void *ud);

static int ce_eval(struct parse_data *pd, struct instruction *context, struct
        const_expr *ce, int flags, reloc_handler *rhandler, void *rud, uint32_t *result);

static int add_relocation(struct parse_data *pd, const char *name, struct instruction *insn, int width, int flags);

static int format_has_output(const struct format *f)
{
    return !!f->out;
}

static int usage(const char *me)
{
    char format_list[256];
    make_format_list(format_has_output, formats_count, formats, sizeof format_list, format_list, ", ");

    printf("Usage:\n"
           "  %s [ OPTIONS ] assembly-or-image-file [ assembly-or-image-file ... ] \n"
           "  -d, --disassemble     disassemble (default is to assemble)\n"
           "  -f, --format=F        select output format (%s)\n"
           "  -o, --output=X        write output to filename X\n"
           "  -s, --strict          disable syntax sugar in disassembly\n"
           "  -h, --help            display this message\n"
           "  -V, --version         print the string '%s'\n"
           , me, format_list, version());

    return 0;
}

struct symbol *symbol_find(struct symbol_list *list, const char *name)
{
    list_foreach(symbol_list, elt, list)
        if (!strncmp(elt->symbol->name, name, SYMBOL_LEN))
            return elt->symbol;

    return NULL;
}

// symbol_lookup returns 1 on success
static int symbol_lookup(struct parse_data *pd, struct symbol_list *list, const
        char *name, uint32_t *result)
{
    struct symbol *symbol = NULL;
    if ((symbol = symbol_find(list, name))) {
        if (result) {
            if (symbol->ce) {
                struct instruction_list **prev = symbol->ce->deferred;
                struct instruction *c = (prev && *prev) ? (*prev)->insn : NULL;
                return ce_eval(pd, c, symbol->ce, 0, NULL, NULL, result);
            } else {
                *result = symbol->reladdr;
            }
        }
        return 1;
    }

    // unresolved symbols get a zero value, but this is still success in CE_EXT
    // case (not in CE_SYM case)
    if (result) *result = 0;
    return 0;
}

// add_relocation returns 1 on success
static int add_relocation(struct parse_data *pd, const char *name, struct instruction *insn, int width, int flags)
{
    struct reloc_list *node = calloc(1, sizeof *node);

    if (name && name[0]) {
        if (insn)
            debug(5, "Adding relocation for `%s' of width %d @ 0x%08x with flags %#x", name, width, insn->reladdr, flags);
        else
            debug(5, "Adding relocation for `%s' of width %d for NULL with flags %#x", name, width, flags);
        strcopy(node->reloc.name, name, sizeof node->reloc.name);
    } else {
        if (insn)
            debug(5, "Adding null relocation of width %d @ 0x%08x with flags %#x", width, insn->reladdr, flags);
        else
            // XXX what does a relocation with (insn == NULL) mean ?
            debug(5, "Adding null relocation of width %d for NULL with flags %#x", width, flags);
        node->reloc.name[0] = 0;
    }
    node->reloc.insn  = insn;
    node->reloc.width = width;
    node->reloc.flags = flags;

    node->next = pd->relocs;
    pd->relocs = node;

    if (insn)
        insn->reloc = &node->reloc;

    return 1;
}

static int sym_reloc_handler(struct parse_data *pd, struct instruction *context, int flags, struct const_expr *ce, void *ud)
{
    int rc = 0;
    int *width = ud;

    int rlc_flags = 0;

    if (flags & RHS_FLIP)
        rlc_flags |= RLC_NEGATE;

    switch (ce->type) {
        case CE_SYM:
        case CE_EXT:
            if (ce->symbol && ce->symbol->ce) {
                struct instruction_list **prev = ce->symbol->ce->deferred;
                // XXX ": context" is voodoo ; hasn't been justified
                struct instruction *c = (prev && *prev) ? (*prev)->insn : context;
                return c ? add_relocation(pd, NULL, c, *width, rlc_flags) : 0;
            } else if (ce->type == CE_EXT) {
                const char *name = ce->symbol ? ce->symbol->name : ce->symbolname;
                const char *n = (flags & NO_NAMED_RELOC) ? NULL : name;
                return add_relocation(pd, n, context, *width, rlc_flags);
            }
        case CE_ICI:
            return add_relocation(pd, NULL, context, *width, rlc_flags);
        default:
            return 0;
    }

    return rc;
}

// ce_eval should be idempotent. returns 1 on fully-successful evaluation, 0 on incomplete evaluation
static int ce_eval(struct parse_data *pd, struct instruction *context, struct
        const_expr *ce, int flags, reloc_handler *rhandler, void *rud, uint32_t *result)
{
    uint32_t left, right;

    switch (ce->type) {
        case CE_SYM:
        case CE_EXT:
            if (ce->symbol && ce->symbol->ce) {
                return ce_eval(pd, (*ce->symbol->ce->deferred)->insn, ce->symbol->ce, flags, rhandler, rud, result)
                    || (rhandler ? rhandler(pd, context, flags, ce, rud) : 0);
            } else {
                const char *name = ce->symbol ? ce->symbol->name : ce->symbolname;
                int found = symbol_lookup(pd, pd->symbols, name, result);
                int hflags = flags;
                if (found)
                    hflags |= NO_NAMED_RELOC;
                int handled = (rhandler ? rhandler(pd, context, hflags, ce, rud) : 0);
                return found || handled;
            }
{'fraction_non_alphanumeric': 0.13102315394242803, 'fraction_numerical': 0.007274718397997497, 'mean_word_length': 2.290862290862291, 'pattern_counts': {'":': 2, '<': 21, '<?xml version=': 0, '>': 123, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1810052', 'n_tokens_mistral': 4213, 'n_tokens_neox': 4047, 'n_words': 1243}