<commit_before>/*
 * Copyright 2011 <NAME> <<EMAIL>>
 *
 * This file is part of cphVB <http://code.google.com/p/cphvb/>.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cphvb.h>
#include <iniparser.h>
#include <string.h>
#include <assert.h>

#ifdef _WIN32

#include <windows.h>
#include <dlfcn-win32.h>

#define HOME_INI_PATH "%APPDATA%\\cphvb\\config.ini"
#define SYSTEM_INI_PATH "%PROGRAMFILES%\\cphvb\\config.ini"

//We need a buffer for path expansion
char _expand_buffer1[MAX_PATH];
char _expand_buffer2[MAX_PATH];

//Nasty function renaming
#define snprintf _snprintf
#define strcasecmp _stricmp

#else

#include <dlfcn.h>

#define HOME_INI_PATH "~/.cphvb/config.ini"
#define SYSTEM_INI_PATH "/opt/cphvb/config.ini"

#endif


static cphvb_com_type get_type(dictionary *dict, const char *name)
{
    char tmp[CPHVB_COM_NAME_SIZE];
    snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:type", name);
    char *s = iniparser_getstring(dict, tmp, NULL);
    if(s == NULL)
    {
        fprintf(stderr,"In section \"%s\" type is not set. "\
                       "Should be bridge, vem or ve.\n",name);
        return CPHVB_COMPONENT_ERROR;
    }
    else
    {
        if(!strcasecmp(s, "bridge"))
            return CPHVB_BRIDGE;
        if(!strcasecmp(s, "vem"))
            return CPHVB_VEM;
        if(!strcasecmp(s, "ve"))
            return CPHVB_VE;
    }
    fprintf(stderr,"In section \"%s\" type is unknown: \"%s\" \n",
            name, s);
    return CPHVB_COMPONENT_ERROR;
}

static void *get_dlsym(void *handle, const char *name,
                       cphvb_com_type type, const char *fun)
{
    char tmp[1024];
    char *stype;
    void *ret;
    if(type == CPHVB_BRIDGE)
        stype = "bridge";
    else if(type == CPHVB_VEM)
        stype = "vem";
    else if(type == CPHVB_VE)
        stype = "ve";
    else
    {
        fprintf(stderr, "get_dlsym - unknown component type.\n");
        return NULL;
    }

    snprintf(tmp, CPHVB_COM_NAME_SIZE, "cphvb_%s_%s_%s", stype, name, fun);
    dlerror();//Clear old errors.
    ret = dlsym(handle, tmp);
    char *err = dlerror();
    if(err != NULL)
    {
        fprintf(stderr, "[%s:type]%s\n", name, err);
        return NULL;
    }
    return ret;
}

/* Setup the root component, which normally is the bridge.
 *
 * @return The root component in the configuration.
 */
cphvb_com *cphvb_com_setup(void)
{
	const char* homepath = HOME_INI_PATH;
	const char* syspath = SYSTEM_INI_PATH;
	
    cphvb_com *com = (cphvb_com*)malloc(sizeof(cphvb_com));
    const char *env;
    if(com == NULL)
    {
        fprintf(stderr, "cphvb_com_setup(): out of memory.\n");
        exit(CPHVB_OUT_OF_MEMORY);
    }
    strcpy(com->name, "bridge"); //The config root keyword.

    //The environment variable has precedence.
    env = getenv("CPHVB_CONFIG");
    if (env != NULL)
    {
		FILE *fp = fopen(env,"r");
		if( fp )
			fclose(fp);
		else
			env = NULL;//Did not exist.
    }
    
    //Then the home directory.
    if(env == NULL)
    { 
    	
#if _WIN32
		DWORD result = ExpandEnvironmentStrings(
			homepath,
			_expand_buffer1,
			MAX_PATH-1
		);
		
		if (result != 0) 
		{
			homepath = _expand_buffer1;
		}
#endif

		FILE *fp = fopen(homepath,"r");
        if( fp ) {
            env = homepath;
            fclose(fp);
        }
    
    }
        
    //And finally system-wide.
    if(env == NULL)
    {
#if _WIN32
		DWORD result = ExpandEnvironmentStrings(
			syspath,
			_expand_buffer2,
			MAX_PATH-1
		);
		
		if (result != 0) 
		{
			syspath = _expand_buffer2;
		}
#endif

        FILE *fp = fopen(syspath,"r");
        if( fp ) {
            env = syspath;
            fclose(fp);
        }
    }
    
    if(env == NULL)
    {
        fprintf(stderr, "Error: cphVB could not find the config file."
            " The search is:\n"
            "\t* The environment variable CPHVB_CONFIG.\n"
            "\t* The home directory \"%s\".\n"
            "\t* And system-wide \"%s\".\n", homepath, syspath);
        exit(-1);
    }

    com->config = iniparser_load(env);
    if(com->config == NULL)
        exit(-1);

    com->type = get_type(com->config, com->name);

    if(com->type != CPHVB_BRIDGE)
    {
        fprintf(stderr, "Error in the configuration: the root "
                        "component must be of type bridge.\n");
        exit(-1);
    }
    return com;
}

/* Retrieves the children components of the parent.
 *
 * @parent The parent component (input).
 * @count Number of children components(output).
 * @children Array of children components (output).
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_children(cphvb_com *parent, cphvb_intp *count,
                               cphvb_com **children[])
{
    char tmp[CPHVB_COM_NAME_SIZE];
    char *child;
    *count = 0;
    snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:children",parent->name);
    char *tchildren = iniparser_getstring(parent->config, tmp, NULL);
    if(tchildren == NULL)
        exit(CPHVB_ERROR);

    *children = (cphvb_com**)malloc(10 * sizeof(cphvb_com *));
    if(*children == NULL)
    {
        fprintf(stderr, "cphvb_com_setup(): out of memory.\n");
        exit(CPHVB_OUT_OF_MEMORY);
    }

    //Handle one child at a time.
    child = strtok(tchildren,",");
    while(child != NULL)
    {
    	(*children)[*count] = (cphvb_com*)malloc(sizeof(cphvb_com));
        cphvb_com *com = (*children)[*count];

        //Save component name.
        strncpy(com->name, child, CPHVB_COM_NAME_SIZE);
        //Save configuration dictionary.
        com->config = parent->config;
        //Save component type.
        com->type = get_type(parent->config,child);
        if(com->type == CPHVB_COMPONENT_ERROR)
        {
            exit(CPHVB_ERROR);
        }

        if(!iniparser_find_entry(com->config,child))
        {
            fprintf(stderr,"Reference \"%s\" is not declared.\n",child);
            exit(CPHVB_ERROR);
        }

        snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:impl", child);
        char *impl = iniparser_getstring(com->config, tmp, NULL);
        if(impl == NULL)
        {
            fprintf(stderr,"In section \"%s\" impl is not set.\n",child);
            exit(CPHVB_ERROR);
        }

        com->lib_handle = dlopen(impl, RTLD_NOW);
        if(com->lib_handle == NULL)
        {
            fprintf(stderr, "Error in [%s:impl]: %s\n", child, dlerror());
            exit(CPHVB_ERROR);
        }

        com->init = (cphvb_init)get_dlsym(com->lib_handle, child, com->type, "init");
        if(com->init == NULL)
            exit(CPHVB_ERROR);

        com->shutdown = (cphvb_shutdown)get_dlsym(com->lib_handle, child, com->type,
                                  "shutdown");
        if(com->shutdown == NULL)
            exit(CPHVB_ERROR);

        com->execute = (cphvb_execute)get_dlsym(com->lib_handle, child, com->type,
                                 "execute");
        if(com->execute == NULL)
            exit(CPHVB_ERROR);

        com->reg_func = (cphvb_reg_func)get_dlsym(com->lib_handle, child, com->type,
                                  "reg_func");
        if(com->reg_func == NULL)
            exit(CPHVB_ERROR);

        if(com->type == CPHVB_VEM)//VEM functions only.
        {
            com->create_array = (cphvb_create_array)get_dlsym(com->lib_handle, child,
                                          com->type, "create_array");
            if(com->create_array == NULL)
                exit(CPHVB_ERROR);
        }
        child = strtok(NULL,",");
        ++(*count);
    }

    if(*count == 0)//No children.
        free(*children);

    return CPHVB_SUCCESS;
}

/* Retrieves an user-defined function.
 *
 * @self The component.
 * @lib Name of the shared library e.g. libmyfunc.so
*       When NULL the default library is used.
 * @fun Name of the function e.g. myfunc
 * @ret_func Pointer to the function (output)
 *           Is NULL if the function doesn't exist
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_com_get_func(cphvb_com *self, char *lib, char *func,
                               cphvb_userfunc_impl *ret_func)
{
    if(lib != NULL)
    {
        fprintf(stderr, "cphvb_com_get_func() does'nt support the "
                        "specification of library name. At the moment "
                        "we only support the default library.\n");
        exit(-1);
    }

    dlerror();//Clear old errors.
    *ret_func = (cphvb_userfunc_impl)dlsym(self->lib_handle, func);
    char *err = dlerror();
    if(err != NULL)
        *ret_func = NULL;//Make sure it is NULL on error.

    if(*ret_func == NULL)
        printf("Warning - the user-defined function (%s, %s) was not "
               "found.\n", lib, func);

    return CPHVB_SUCCESS;
}

/* Frees the component.
 *
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_free(cphvb_com *component)
{
    if(component->type == CPHVB_BRIDGE)
        iniparser_freedict(component->config);
    else
        dlclose(component->lib_handle);
    free(component);
    return CPHVB_SUCCESS;
}

/* Frees allocated data.
 *
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_free_ptr(void* data)
{
	free(data);
	return CPHVB_SUCCESS;
}

/* Trace an array creation.
 *
 * @self The component.
 * @ary  The array to trace.
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_trace_array(cphvb_com *self, cphvb_array *ary)
{
    int i;
    FILE *f = fopen("/tmp/cphvb_trace.ary", "a");
    fprintf(f,"array: %p;\t ndim: %ld;\t shape:", ary, ary->ndim);
    for(i=0; i<ary->ndim; ++i)
        fprintf(f," %ld", ary->shape[i]);
    fprintf(f,";\t stride:");
    for(i=0; i<ary->ndim; ++i)
        fprintf(f," %ld", ary->stride[i]);
    fprintf(f,";\t start: %ld;\t base: %p;\n",ary->start, ary->base);

    fclose(f);
    return CPHVB_SUCCESS;
}

/* Trace an instruction.
 *
 * @self The component.
 * @inst  The instruction to trace.
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_trace_inst(cphvb_com *self, cphvb_instruction *inst)
{
    int i;
    cphvb_intp nop;
    cphvb_array *ops[CPHVB_MAX_NO_OPERANDS];

    FILE *f = fopen("/tmp/cphvb_trace.inst", "a");

    fprintf(f,"%s\t", cphvb_opcode_text(inst->opcode));

    if(inst->opcode == CPHVB_USERFUNC)
    {
        nop = inst->userfunc->nout + inst->userfunc->nin;
        for(i=0; i<nop; ++i)
            ops[i] = inst->userfunc->operand[i];
    }
    else
    {
        nop = cphvb_operands(inst->opcode);
        for(i=0; i<nop; ++i)
            ops[i] = inst->operand[i];
    }
    for(i=0; i<nop; ++i)
        fprintf(f," \t%p", ops[i]);

    fprintf(f,"\n");

    fclose(f);
    return CPHVB_SUCCESS;
}
<commit_msg>Fixed the way ~ (HOME) is parsed on OSX/Linux<commit_after>/*
 * Copyright 2011 <NAME> <<EMAIL>>
 *
 * This file is part of cphVB <http://code.google.com/p/cphvb/>.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cphvb.h>
#include <iniparser.h>
#include <string.h>
#include <assert.h>

#ifdef _WIN32

#include <windows.h>
#include <dlfcn-win32.h>

#define HOME_INI_PATH "%APPDATA%\\cphvb\\config.ini"
#define SYSTEM_INI_PATH "%PROGRAMFILES%\\cphvb\\config.ini"

//We need a buffer for path expansion
char _expand_buffer1[MAX_PATH];
char _expand_buffer2[MAX_PATH];

//Nasty function renaming
#define snprintf _snprintf
#define strcasecmp _stricmp

#else

#include <dlfcn.h>
#include <limits.h>

#define HOME_INI_PATH "~/.cphvb/config.ini"
#define SYSTEM_INI_PATH "/opt/cphvb/config.ini"

//We need a buffer for path expansion
char _expand_buffer[PATH_MAX];

#endif


static cphvb_com_type get_type(dictionary *dict, const char *name)
{
    char tmp[CPHVB_COM_NAME_SIZE];
    snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:type", name);
    char *s = iniparser_getstring(dict, tmp, NULL);
    if(s == NULL)
    {
        fprintf(stderr,"In section \"%s\" type is not set. "\
                       "Should be bridge, vem or ve.\n",name);
        return CPHVB_COMPONENT_ERROR;
    }
    else
    {
        if(!strcasecmp(s, "bridge"))
            return CPHVB_BRIDGE;
        if(!strcasecmp(s, "vem"))
            return CPHVB_VEM;
        if(!strcasecmp(s, "ve"))
            return CPHVB_VE;
    }
    fprintf(stderr,"In section \"%s\" type is unknown: \"%s\" \n",
            name, s);
    return CPHVB_COMPONENT_ERROR;
}

static void *get_dlsym(void *handle, const char *name,
                       cphvb_com_type type, const char *fun)
{
    char tmp[1024];
    char *stype;
    void *ret;
    if(type == CPHVB_BRIDGE)
        stype = "bridge";
    else if(type == CPHVB_VEM)
        stype = "vem";
    else if(type == CPHVB_VE)
        stype = "ve";
    else
    {
        fprintf(stderr, "get_dlsym - unknown component type.\n");
        return NULL;
    }

    snprintf(tmp, CPHVB_COM_NAME_SIZE, "cphvb_%s_%s_%s", stype, name, fun);
    dlerror();//Clear old errors.
    ret = dlsym(handle, tmp);
    char *err = dlerror();
    if(err != NULL)
    {
        fprintf(stderr, "[%s:type]%s\n", name, err);
        return NULL;
    }
    return ret;
}

/* Setup the root component, which normally is the bridge.
 *
 * @return The root component in the configuration.
 */
cphvb_com *cphvb_com_setup(void)
{
	const char* homepath = HOME_INI_PATH;
	const char* syspath = SYSTEM_INI_PATH;
	
    cphvb_com *com = (cphvb_com*)malloc(sizeof(cphvb_com));
    const char *env;
    if(com == NULL)
    {
        fprintf(stderr, "cphvb_com_setup(): out of memory.\n");
        exit(CPHVB_OUT_OF_MEMORY);
    }
    strcpy(com->name, "bridge"); //The config root keyword.

    //The environment variable has precedence.
    env = getenv("CPHVB_CONFIG");
    if (env != NULL)
    {
		FILE *fp = fopen(env,"r");
		if( fp )
			fclose(fp);
		else
			env = NULL;//Did not exist.
    }
    
    //Then the home directory.
    if(env == NULL)
    { 
    	
#if _WIN32
		DWORD result = ExpandEnvironmentStrings(
			homepath,
			_expand_buffer1,
			MAX_PATH-1
		);
		
		if (result != 0) 
		{
			homepath = _expand_buffer1;
		}
#else
		
		char* h = getenv("HOME");
		if (h != NULL) 
		{
			snprintf(_expand_buffer, PATH_MAX, "%s/%s", h, homepath+1);
			homepath = _expand_buffer;
		}
#endif

		FILE *fp = fopen(homepath,"r");
        if( fp ) {
            env = homepath;
            fclose(fp);
        }
    
    }
        
    //And finally system-wide.
    if(env == NULL)
    {
#if _WIN32
		DWORD result = ExpandEnvironmentStrings(
			syspath,
			_expand_buffer2,
			MAX_PATH-1
		);
		
		if (result != 0) 
		{
			syspath = _expand_buffer2;
		}
#endif

        FILE *fp = fopen(syspath,"r");
        if( fp ) {
            env = syspath;
            fclose(fp);
        }
    }
    
    if(env == NULL)
    {
        fprintf(stderr, "Error: cphVB could not find the config file."
            " The search is:\n"
            "\t* The environment variable CPHVB_CONFIG.\n"
            "\t* The home directory \"%s\".\n"
            "\t* And system-wide \"%s\".\n", homepath, syspath);
        exit(-1);
    }

    com->config = iniparser_load(env);
    if(com->config == NULL)
        exit(-1);

    com->type = get_type(com->config, com->name);

    if(com->type != CPHVB_BRIDGE)
    {
        fprintf(stderr, "Error in the configuration: the root "
                        "component must be of type bridge.\n");
        exit(-1);
    }
    return com;
}

/* Retrieves the children components of the parent.
 *
 * @parent The parent component (input).
 * @count Number of children components(output).
 * @children Array of children components (output).
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_children(cphvb_com *parent, cphvb_intp *count,
                               cphvb_com **children[])
{
    char tmp[CPHVB_COM_NAME_SIZE];
    char *child;
    *count = 0;
    snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:children",parent->name);
    char *tchildren = iniparser_getstring(parent->config, tmp, NULL);
    if(tchildren == NULL)
        exit(CPHVB_ERROR);

    *children = (cphvb_com**)malloc(10 * sizeof(cphvb_com *));
    if(*children == NULL)
    {
        fprintf(stderr, "cphvb_com_setup(): out of memory.\n");
        exit(CPHVB_OUT_OF_MEMORY);
    }

    //Handle one child at a time.
    child = strtok(tchildren,",");
    while(child != NULL)
    {
    	(*children)[*count] = (cphvb_com*)malloc(sizeof(cphvb_com));
        cphvb_com *com = (*children)[*count];

        //Save component name.
        strncpy(com->name, child, CPHVB_COM_NAME_SIZE);
        //Save configuration dictionary.
        com->config = parent->config;
        //Save component type.
        com->type = get_type(parent->config,child);
        if(com->type == CPHVB_COMPONENT_ERROR)
        {
            exit(CPHVB_ERROR);
        }

        if(!iniparser_find_entry(com->config,child))
        {
            fprintf(stderr,"Reference \"%s\" is not declared.\n",child);
            exit(CPHVB_ERROR);
        }

        snprintf(tmp, CPHVB_COM_NAME_SIZE, "%s:impl", child);
        char *impl = iniparser_getstring(com->config, tmp, NULL);
        if(impl == NULL)
        {
            fprintf(stderr,"In section \"%s\" impl is not set.\n",child);
            exit(CPHVB_ERROR);
        }

        com->lib_handle = dlopen(impl, RTLD_NOW);
        if(com->lib_handle == NULL)
        {
            fprintf(stderr, "Error in [%s:impl]: %s\n", child, dlerror());
            exit(CPHVB_ERROR);
        }

        com->init = (cphvb_init)get_dlsym(com->lib_handle, child, com->type, "init");
        if(com->init == NULL)
            exit(CPHVB_ERROR);

        com->shutdown = (cphvb_shutdown)get_dlsym(com->lib_handle, child, com->type,
                                  "shutdown");
        if(com->shutdown == NULL)
            exit(CPHVB_ERROR);

        com->execute = (cphvb_execute)get_dlsym(com->lib_handle, child, com->type,
                                 "execute");
        if(com->execute == NULL)
            exit(CPHVB_ERROR);

        com->reg_func = (cphvb_reg_func)get_dlsym(com->lib_handle, child, com->type,
                                  "reg_func");
        if(com->reg_func == NULL)
            exit(CPHVB_ERROR);

        if(com->type == CPHVB_VEM)//VEM functions only.
        {
            com->create_array = (cphvb_create_array)get_dlsym(com->lib_handle, child,
                                          com->type, "create_array");
            if(com->create_array == NULL)
                exit(CPHVB_ERROR);
        }
        child = strtok(NULL,",");
        ++(*count);
    }

    if(*count == 0)//No children.
        free(*children);

    return CPHVB_SUCCESS;
}

/* Retrieves an user-defined function.
 *
 * @self The component.
 * @lib Name of the shared library e.g. libmyfunc.so
*       When NULL the default library is used.
 * @fun Name of the function e.g. myfunc
 * @ret_func Pointer to the function (output)
 *           Is NULL if the function doesn't exist
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_com_get_func(cphvb_com *self, char *lib, char *func,
                               cphvb_userfunc_impl *ret_func)
{
    if(lib != NULL)
    {
        fprintf(stderr, "cphvb_com_get_func() does'nt support the "
                        "specification of library name. At the moment "
                        "we only support the default library.\n");
        exit(-1);
    }

    dlerror();//Clear old errors.
    *ret_func = (cphvb_userfunc_impl)dlsym(self->lib_handle, func);
    char *err = dlerror();
    if(err != NULL)
        *ret_func = NULL;//Make sure it is NULL on error.

    if(*ret_func == NULL)
        printf("Warning - the user-defined function (%s, %s) was not "
               "found.\n", lib, func);

    return CPHVB_SUCCESS;
}

/* Frees the component.
 *
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_free(cphvb_com *component)
{
    if(component->type == CPHVB_BRIDGE)
        iniparser_freedict(component->config);
    else
        dlclose(component->lib_handle);
    free(component);
    return CPHVB_SUCCESS;
}

/* Frees allocated data.
 *
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_free_ptr(void* data)
{
	free(data);
	return CPHVB_SUCCESS;
}

/* Trace an array creation.
 *
 * @self The component.
 * @ary  The array to trace.
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_trace_array(cphvb_com *self, cphvb_array *ary)
{
    int i;
    FILE *f = fopen("/tmp/cphvb_trace.ary", "a");
    fprintf(f,"array: %p;\t ndim: %ld;\t shape:", ary, ary->ndim);
    for(i=0; i<ary->ndim; ++i)
        fprintf(f," %ld", ary->shape[i]);
    fprintf(f,";\t stride:");
    for(i=0; i<ary->ndim; ++i)
        fprintf(f," %ld", ary->stride[i]);
    fprintf(f,";\t start: %ld;\t base: %p;\n",ary->start, ary->base);

    fclose(f);
    return CPHVB_SUCCESS;
}

/* Trace an instruction.
 *
 * @self The component.
 * @inst  The instruction to trace.
 * @return Error code (CPHVB_SUCCESS).
 */
cphvb_error cphvb_com_trace_inst(cphvb_com *self, cphvb_instruction *inst)
{
    int i;
    cphvb_intp nop;
    cphvb_array *ops[CPHVB_MAX_NO_OPERANDS];

    FILE *f = fopen("/tmp/cphvb_trace.inst", "a");

    fprintf(f,"%s\t", cphvb_opcode_text(inst->opcode));

    if(inst->opcode == CPHVB_USERFUNC)
    {
        nop = inst->userfunc->nout + inst->userfunc->nin;
        for(i=0; i<nop; ++i)
            ops[i] = inst->userfunc->operand[i];
    }
    else
    {
        nop = cphvb_operands(inst->opcode);
        for(i=0; i<nop; ++i)
            ops[i] = inst->operand[i];
    }
    for(i=0; i<nop; ++i)
        fprintf(f," \t%p", ops[i]);

    fprintf(f,"\n");

    fclose(f);
    return CPHVB_SUCCESS;
}

{'fraction_non_alphanumeric': 0.13925274725274725, 'fraction_numerical': 0.0035604395604395605, 'mean_word_length': 2.3590727890152072, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 150, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5863040', 'n_tokens_mistral': 8134, 'n_tokens_neox': 7911, 'n_words': 1848}