Inline XML python.

This commit is contained in:
Themaister 2011-06-07 15:33:29 +02:00
parent e02d9f41e8
commit 3717f7442c
6 changed files with 150 additions and 14 deletions

View File

@ -17,11 +17,15 @@
#include <Python.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "dynamic.h"
#include "libsnes.hpp"
#include <stdlib.h>
#include "py_state.h"
#include "general.h"
#include "strl.h"
#define PY_READ_FUNC_DECL(RAMTYPE) py_read_##RAMTYPE
#define PY_READ_FUNC(RAMTYPE) \
@ -85,7 +89,62 @@ struct py_state
bool warned_type;
};
py_state_t *py_state_new(const char *script_path, const char *pyclass)
static char *dupe_newline(const char *str)
{
if (!str)
return NULL;
unsigned size = strlen(str) + 2;
char *ret = malloc(size);
if (!ret)
return NULL;
strlcpy(ret, str, size);
ret[size - 2] = '\n';
ret[size - 1] = '\0';
return ret;
}
// Need to make sure that first-line indentation is 0. :(
static char* align_program(const char *program)
{
char *prog = strdup(program);
if (!prog)
return NULL;
size_t prog_size = strlen(program) + 1;
char *new_prog = calloc(1, prog_size);
if (!new_prog)
return NULL;
char *line = dupe_newline(strtok(prog, "\n"));
if (!line)
{
free(prog);
return NULL;
}
unsigned skip_chars = 0;
while (isblank(line[skip_chars]) && line[skip_chars])
skip_chars++;
while (line)
{
unsigned length = strlen(line);
unsigned skip_len = skip_chars > length ? length : skip_chars;
strlcat(new_prog, line + skip_len, prog_size);
free(line);
line = dupe_newline(strtok(NULL, "\n"));
}
free(prog);
return new_prog;
}
py_state_t *py_state_new(const char *script, bool is_file, const char *pyclass)
{
PyImport_AppendInittab("snes", &PyInit_SNES);
Py_Initialize();
@ -96,11 +155,23 @@ py_state_t *py_state_new(const char *script_path, const char *pyclass)
if (!handle->main)
goto error;
FILE *file = fopen(script_path, "r");
if (!file)
goto error;
PyRun_SimpleFile(file, script_path);
fclose(file);
if (is_file)
{
FILE *file = fopen(script, "r");
if (!file)
goto error;
PyRun_SimpleFile(file, script);
fclose(file);
}
else
{
char *script_ = align_program(script);
if (script_)
{
PyRun_SimpleString(script_);
free(script_);
}
}
handle->dict = PyModule_GetDict(handle->main);
if (!handle->dict)

View File

@ -19,10 +19,11 @@
#define __SSNES_PY_STATE_H
#include <stdint.h>
#include <stdbool.h>
typedef struct py_state py_state_t;
py_state_t *py_state_new(const char *program, const char *pyclass);
py_state_t *py_state_new(const char *program, bool is_file, const char *pyclass);
void py_state_free(py_state_t *handle);
int py_state_get(py_state_t *handle,

View File

@ -527,6 +527,8 @@ static bool load_imports(const char *dir_path, config_file_t *conf)
}
if (config_get_string(conf, "import_script_class", &script_class))
tracker_info.script_class = script_class;
tracker_info.script_is_file = true;
#endif
snes_tracker = snes_tracker_init(&tracker_info);

View File

@ -118,6 +118,7 @@ static struct snes_tracker_uniform_info gl_tracker_info[MAX_VARIABLES];
static unsigned gl_tracker_info_cnt = 0;
static char gl_tracker_script[256];
static char gl_tracker_script_class[64];
static xmlChar *gl_script_program = NULL;
struct shader_program
{
@ -380,6 +381,43 @@ error:
return false;
}
static bool get_script(xmlNodePtr ptr)
{
if (*gl_tracker_script)
{
SSNES_ERR("Script already imported.\n");
return false;
}
xmlChar *script_class = xmlGetProp(ptr, (const xmlChar*)"class");
if (script_class)
{
strlcpy(gl_tracker_script_class, (const char*)script_class, sizeof(gl_tracker_script_class));
xmlFree(script_class);
}
xmlChar *language = xmlGetProp(ptr, (const xmlChar*)"language");
if (!language || strcmp((const char*)language, "python") != 0)
{
SSNES_ERR("Script language is not Python!\n");
if (language)
xmlFree(language);
return false;
}
if (language)
xmlFree(language);
xmlChar *script = xmlNodeGetContent(ptr);
if (!script)
{
SSNES_ERR("No content in script!\n");
return false;
}
gl_script_program = script;
return true;
}
static bool get_import_value(const char *path, xmlNodePtr ptr)
{
if (gl_tracker_info_cnt >= MAX_VARIABLES)
@ -390,7 +428,7 @@ static bool get_import_value(const char *path, xmlNodePtr ptr)
#ifdef HAVE_PYTHON
xmlChar *script = xmlGetProp(ptr, (const xmlChar*)"script");
if (script && *gl_tracker_script)
if (script && (*gl_tracker_script || gl_script_program))
{
SSNES_ERR("Cannot define more than one script!\n");
return false;
@ -635,6 +673,14 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s
goto error;
}
}
else if (strcmp((const char*)cur->name, "script") == 0)
{
if (!get_script(cur))
{
SSNES_ERR("Script is invalid.\n");
goto error;
}
}
}
if (num == 0)
@ -860,11 +906,20 @@ bool gl_glsl_init(const char *path)
.oam = psnes_get_memory_data(SNES_MEMORY_OAM),
.info = gl_tracker_info,
.info_elem = gl_tracker_info_cnt,
#ifdef HAVE_PYTHON
.script = *gl_tracker_script ? gl_tracker_script : NULL,
.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL
#endif
};
#ifdef HAVE_PYTHON
if (*gl_tracker_script)
info.script = gl_tracker_script;
else if (gl_script_program)
info.script = (const char*)gl_script_program;
else
info.script = NULL;
info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL;
info.script_is_file = *gl_tracker_script;
#endif
gl_snes_tracker = snes_tracker_init(&info);
if (!gl_snes_tracker)
SSNES_WARN("Failed to init SNES tracker!\n");
@ -911,6 +966,11 @@ void gl_glsl_deinit(void)
memset(gl_tracker_info, 0, sizeof(gl_tracker_info));
memset(gl_tracker_script, 0, sizeof(gl_tracker_script));
memset(gl_tracker_script_class, 0, sizeof(gl_tracker_script_class));
if (gl_script_program)
{
xmlFree(gl_script_program);
gl_script_program = NULL;
}
if (gl_snes_tracker)
{
snes_tracker_free(gl_snes_tracker);

View File

@ -64,7 +64,7 @@ snes_tracker_t* snes_tracker_init(const struct snes_tracker_info *info)
#ifdef HAVE_PYTHON
if (info->script)
{
tracker->py = py_state_new(info->script, info->script_class ? info->script_class : "GameAware");
tracker->py = py_state_new(info->script, info->script_is_file, info->script_class ? info->script_class : "GameAware");
if (!tracker->py)
{
free(tracker);

View File

@ -19,6 +19,7 @@
#define __SSNES_SNES_STATE_H
#include <stdint.h>
#include <stdbool.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -68,6 +69,7 @@ struct snes_tracker_info
#ifdef HAVE_PYTHON
const char *script;
const char *script_class;
bool script_is_file;
#endif
};