#include "imports_exports.h"

#include "ctinfo.h"
#include "dbug.h"
#include "globals.h"
#include "memory.h"
#include "print_enum.h"
#include "queue.h"
#include "symbol_table.h"
#include "traverse.h"
#include "tree_basic.h"
#include "types.h"
#include <assert.h>
#include <string.h>
#include "mymacros.h"


typedef struct ie_item q_item;

struct INFO
{
    int n_fun_imports;
    int n_fun_exports;
    int n_var_imports;
    int n_var_exports;
    /* Holds the functions and variables that are in the im- and export tables */
    struct queue* import_exports;
};

static info* info_init(void)
{
    DBUG_ENTER("info_init");

    info* result = (info*)MEMmalloc(sizeof(struct INFO));
    if (!result) return NULL;

    *result = (info){0};
    result->import_exports = q_init();

    DBUG_RETURN(result);
}

static void info_free(info* inf)
{
    DBUG_ENTER("info_free");

    MEMfree(inf);

    DBUG_VOID_RETURN
}

node* GEORGEglobaldef(node* arg_node, info* arg_info)
{
    DBUG_ENTER("GEORGEglobaldef");

    struct st_entry* var = GLOBALDEF_STLINK(arg_node);

    if (!var->isextern && !var->isexported) DBUG_RETURN(arg_node);

    if (var->isextern)
        var->import_export_num = arg_info->n_var_imports++;
    else
        var->import_export_num = arg_info->n_var_exports++;

    q_nq(arg_info->import_exports, var);

    DBUG_RETURN(arg_node);
}

node* GEORGEfundef(node* arg_node, info* arg_info)
{
    DBUG_ENTER("GEORGEfundef");

    struct st_entry_fn* fun         = FUNDEF_STLINK(arg_node);

    if (!fun->isexported && !fun->isextern) DBUG_RETURN(arg_node);

    if (fun->isextern)
        fun->import_export_num = arg_info->n_fun_imports++;
    else
        fun->import_export_num = arg_info->n_fun_exports++;

    q_nq(arg_info->import_exports, (struct st_entry*)fun);

    DBUG_RETURN(arg_node);
}

/*
 * Traversal start function
 */

node* GEORGEdoImportExport(node* syntaxtree)
{
    DBUG_ENTER("GEORGEdoImportExport");

    global.outfileptr = (!global.outfile) ? stdout : fopen(global.outfile, "w");

    info* arg_info = info_init();

    TRAVpush(TR_george);
    syntaxtree = TRAVdo(syntaxtree, arg_info);
    TRAVpop();

    PROGRAM_IMPORTSEXPORTS(syntaxtree) = arg_info->import_exports;

    info_free(arg_info);

    DBUG_RETURN(syntaxtree);
}
