stack trace on error and critical logs; set logging level

This commit is contained in:
John Alanbrook 2023-04-24 22:22:18 +00:00
parent 2ab0f33d3f
commit a39aee66f5
12 changed files with 320 additions and 302 deletions

View file

@ -1,148 +1,91 @@
#include "model.h" #include "model.h"
#include "log.h"
#include "mesh.h" #include "mesh.h"
#include "resources.h" #include "resources.h"
#include "shader.h" #include "shader.h"
#include "stb_ds.h"
#include <cgltf.h> #include <cgltf.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "log.h" #include <string.h>
static struct model *lastRendered; static struct {
static struct model *loadedModels[100]; char *key;
static struct model **lastModel = loadedModels; struct Texture *value;
} *modelhash = NULL;
static void processnode(); static void processnode();
static void processmesh(); static void processmesh();
static void processtexture(); static void processtexture();
struct model *GetExistingModel(const char *path) {
if (!path || path[0] == '\0') return NULL;
struct model *GetExistingModel(const char *path) int index = shgeti(modelhash, path);
{ if (index != -1) return modelhash[index].value;
struct model **model = loadedModels;
while (model++ != lastModel) {
if (!strcmp(path, (*model)->path))
goto end;
return MakeModel(path); return MakeModel(path);
}
end:
return NULL;
} }
/* TODO: Make this a hash compare for speedup */ /* TODO: Make this a hash compare for speedup */
struct model *MakeModel(const char *path) struct model *MakeModel(const char *path) {
{
char *modelPath =
(char *) malloc(sizeof(char) *
(strlen(DATA_PATH) + strlen(path) + 1));
modelPath[0] = '\0';
strcat(modelPath, DATA_PATH);
strcat(modelPath, path);
printf
("Created new model with modelPath %s, from data_path %s and path %s\n",
modelPath, DATA_PATH, path);
struct model *newmodel =
(struct model *) malloc(sizeof(struct model));
newmodel->path = path;
loadmodel(newmodel);
*lastModel++ = newmodel;
return newmodel;
}
// TODO: Come back to this; simple optimization
void draw_model(struct model *model, struct shader *shader)
{
if (lastRendered != model) {
lastRendered = model;
for (int i = 0; i < (model->mp - model->meshes); i++)
DrawMesh(&model->meshes[i], shader);
} else {
for (uint32_t i = 0; i < (model->mp - model->meshes); i++)
DrawMeshAgain(&model->meshes[i]);
}
}
void loadmodel(struct model *model)
{
YughInfo("Loading model at path %s", model->path);
/*
// Load model with cgltf
cgltf_options options = {0}; cgltf_options options = {0};
cgltf_data *data = NULL; cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, model->path, &data); cgltf_result result = cgltf_parse_file(&options, path, &data);
meshes = (struct mesh*)malloc(sizeof(Mesh)*cgltf_data->meshes_count); if (!result == cgltf_result_success) {
YughError("Could not read file %s.", path);
return;
}
directory = get_directory_from_path(model->path); result = cgltf_load_buffers(&options, data, path);
if (!result == cgltf_result_success) {
YughError("Could not load buffers for file %s.", path);
return;
}
struct model *model = malloc(sizeof(struct model));
model->meshes = malloc(sizeof(struct mesh) * data->meshes_count);
for (int i = 0; i < data->nodes_count; i++) { for (int i = 0; i < data->nodes_count; i++) {
if (data->nodes[i]->mesh) {
for (int j = 0; j < data->nodes[i]->mesh->primatives_count; j++) {
if (data->nodes[i].mesh) {
cgltf_mesh *mesh = data->nodes[i].mesh;
for (int j = 0; j < mesh->primitives_count; j++) {
cgltf_primitive primitive = mesh->primitives[j];
for (int k = 0; k < primitive.attributes_count; k++) {
cgltf_attribute attribute = primitive.attributes[k];
switch (attribute.type) {
for (int k = 0; k < data->nodes[i]->mesh->primatives[j]->attributes_count; k++) {
switch(data->nodes[i]->mesh->primatives[j]->attributes[k]->type) {
case cgltf_attribute_type_position: case cgltf_attribute_type_position:
Vertex *vs = (Vertex*)malloc(sizeof(Vertex) * cgltf_accessor_unpack_floats(:::attributes[k]->accesor, NULL, attributes[k]->accessor.count); // float *vs = malloc(sizeof(float) * cgltf_accessor_unpack_floats(attribute.accessor, NULL, attribute.accessor.count);
cgltf_accessor_unpack_floats(:::attributes[k]->accessor, vs, attributes[k]->accessor.count); // cgltf_accessor_unpack_floats(attribute.accessor, vs, attribute.accessor.count);
break; break;
case cgltf_attribute_type_normal: case cgltf_attribute_type_normal:
break; break;
case cgltf_attribute_type_tangent: case cgltf_attribute_type_tangent:
break; break;
case cgltf_attribute_type_texcoord: case cgltf_attribute_type_texcoord:
break; break;
} }
} }
} }
} }
} }
} }
*/
/* TODO: DELETE /* TODO: DELETE
static void processnode() {
// read file via ASSIMP
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path,
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace);
// check for errors
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE
|| !scene->mRootNode) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"ASSIMP error: %s",
importer.GetErrorString());
return;
}
directory = get_directory_from_path(path);
meshes = (Mesh *) malloc(sizeof(Mesh) * 100);
mp = meshes;
// process ASSIMP's root node recursively
processNode(scene->mRootNode, scene); */
}
static void processnode()
{
/*
for (uint32_t i = 0; i < node->mNumMeshes; i++) { for (uint32_t i = 0; i < node->mNumMeshes; i++) {
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
*mp = processMesh(mesh, scene); *mp = processMesh(mesh, scene);
@ -152,11 +95,10 @@ static void processnode()
for (uint32_t i = 0; i < node->mNumChildren; i++) { for (uint32_t i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene); processnode(node->mChildren[i], scene);
} }
*/
}
static void processmesh() }
{ */
static void processmesh() {
/* /*
Vertex *vertices = Vertex *vertices =
(Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices); (Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices);
@ -252,12 +194,10 @@ static void processmesh()
return Mesh(vertices, vp, indices, ip, textures_loaded, tp); return Mesh(vertices, vp, indices, ip, textures_loaded, tp);
*/ */
} }
// TODO: This routine mallocs inside the function // TODO: This routine mallocs inside the function
static void processtexture() static void processtexture() {
{
/* /*
for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) { for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) {
aiString str; aiString str;
@ -280,3 +220,13 @@ static void processtexture()
} }
*/ */
} }
void draw_models(struct model *model, struct shader *shader)
{
}
// TODO: Come back to this; simple optimization
void draw_model(struct model *model, struct shader *shader) {
}

View file

@ -7,9 +7,6 @@ struct shader;
struct model { struct model {
struct mesh *meshes; struct mesh *meshes;
struct mesh *mp; struct mesh *mp;
char *directory;
const char *path;
char *name;
}; };
/* Get the model at a path, or create and return if it doesn't exist */ /* Get the model at a path, or create and return if it doesn't exist */
@ -22,5 +19,6 @@ struct model *MakeModel(const char *path);
void loadmodel(struct model *model); void loadmodel(struct model *model);
void draw_model(struct model *model, struct shader *shader); void draw_model(struct model *model, struct shader *shader);
void draw_models(struct model *model, struct shader *shader);
#endif #endif

View file

@ -8,7 +8,14 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#define logLevel 0 int logLevel = 1;
/* Four levels of log:
0 info
1 warn
2 error
3 critical
*/
//char *logstr[] = { "INFO", "WARN", "\x1b[1;31mERROR\x1b[0m", "CRITICAL" }; //char *logstr[] = { "INFO", "WARN", "\x1b[1;31mERROR\x1b[0m", "CRITICAL" };
char *logstr[] = { "info", "warn", "error", "critical" }; char *logstr[] = { "info", "warn", "error", "critical" };
@ -37,19 +44,23 @@ void mYughLog(int category, int priority, int line, const char *file, const char
char buffer[ERROR_BUFFER] = { '\0' }; char buffer[ERROR_BUFFER] = { '\0' };
snprintf(buffer, ERROR_BUFFER, "%s:%d: %s, %s: %s\n", file, line, logstr[priority], catstr[category], msgbuffer); snprintf(buffer, ERROR_BUFFER, "%s:%d: %s, %s: %s\n", file, line, logstr[priority], catstr[category], msgbuffer);
fprintf(stderr, "%s", buffer); log_print(buffer);
}
}
void log_print(const char *str)
{
fprintf(stderr, "%s", str);
fflush(stderr); fflush(stderr);
strncat(consolelog, buffer, CONSOLE_BUF); strncat(consolelog, str, CONSOLE_BUF);
if (logfile) { if (logfile) {
fprintf(logfile, "%s", buffer); fprintf(logfile, "%s", str);
fflush(logfile); fflush(logfile);
} }
snprintf(lastlog, ERROR_BUFFER, "%s", buffer); snprintf(lastlog, ERROR_BUFFER, "%s", str);
}
} }
void log_setfile(char *file) { void log_setfile(char *file) {

View file

@ -14,6 +14,7 @@
extern char lastlog[]; extern char lastlog[];
extern char consolelog[]; extern char consolelog[];
extern int logLevel;
#if DBG #if DBG
#define YughLog(cat, pri, msg, ...) mYughLog(cat, pri, __LINE__, __FILE__, msg, ##__VA_ARGS__) #define YughLog(cat, pri, msg, ...) mYughLog(cat, pri, __LINE__, __FILE__, msg, ##__VA_ARGS__)
@ -35,5 +36,6 @@ void FlushGLErrors();
void log_setfile(char *file); void log_setfile(char *file);
void log_cat(FILE *f); void log_cat(FILE *f);
void log_print(const char *str);
#endif #endif

View file

@ -608,13 +608,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 11: case 11:
str = JS_ToCString(js, argv[1]); str = JS_ToCString(js, argv[1]);
ret = JS_NewInt64(js, file_mod_secs(str)); ret = JS_NewInt64(js, file_mod_secs(str));
JS_FreeCString(js,str); break;
return ret;
case 12: case 12:
str = JS_ToCString(js,argv[2]); str = JS_ToCString(js,argv[2]);
sprite_loadtex(id2sprite(js2int(argv[1])), str, js2glrect(argv[3])); sprite_loadtex(id2sprite(js2int(argv[1])), str, js2glrect(argv[3]));
JS_FreeCString(js,str);
break; break;
case 13: case 13:
@ -722,16 +720,13 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 38: case 38:
str = JS_ToCString(js,argv[1]); str = JS_ToCString(js,argv[1]);
ret = JS_NewString(js, slurp_text(str)); ret = JS_NewString(js, slurp_text(str));
JS_FreeCString(js,str); break;
return ret;
case 39: case 39:
str = JS_ToCString(js,argv[1]); str = JS_ToCString(js,argv[1]);
str2 = JS_ToCString(js,argv[2]); str2 = JS_ToCString(js,argv[2]);
ret = JS_NewInt64(js, slurp_write(str, str2)); ret = JS_NewInt64(js, slurp_write(str, str2));
JS_FreeCString(js,str); break;
JS_FreeCString(js,str2);
return ret;
case 40: case 40:
id2go(js2int(argv[1]))->filter.categories = js2bitmask(argv[2]); id2go(js2int(argv[1]))->filter.categories = js2bitmask(argv[2]);
@ -923,6 +918,18 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
str = JS_ToCString(js, argv[1]); str = JS_ToCString(js, argv[1]);
window_set_icon(str); window_set_icon(str);
break; break;
case 91:
str = JS_ToCString(js,argv[1]);
log_print(str);
break;
case 92:
logLevel = js2int(argv[1]);
break;
case 93:
ret = int2js(logLevel);
} }
if (str) if (str)

View file

@ -50,6 +50,24 @@ time_t file_mod_secs(const char *file) {
return attr.st_mtime; return attr.st_mtime;
} }
void js_dump_stack()
{
JSValue exception = JS_GetException(js);
JSValue val = JS_GetPropertyStr(js, exception, "stack");
if (!JS_IsUndefined(val)) {
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
const char *stack = JS_ToCString(js, val);
YughError("%s :: %s\n%s", name, msg, stack);
JS_FreeCString(js, name);
JS_FreeCString(js, msg);
JS_FreeCString(js, stack);
}
}
int js_print_exception(JSValue v) int js_print_exception(JSValue v)
{ {
if (JS_IsException(v)) { if (JS_IsException(v)) {
@ -73,7 +91,7 @@ int script_dofile(const char *file) {
const char *script = slurp_text(file); const char *script = slurp_text(file);
if (!script) { if (!script) {
YughError("Can't find file %s.", file); YughError("Can't find file %s.", file);
return 1; return 0;
} }
JSValue obj = JS_Eval(js, script, strlen(script), file, 0); JSValue obj = JS_Eval(js, script, strlen(script), file, 0);
js_print_exception(obj); js_print_exception(obj);

View file

@ -20,6 +20,7 @@ void script_update(double dt);
void script_draw(); void script_draw();
void duk_run_err(); void duk_run_err();
void js_dump_stack();
void script_editor(); void script_editor();
void script_call(const char *f); void script_call(const char *f);

View file

@ -20,8 +20,6 @@ struct Texture *tex_default;
/* If an empty string or null is put for path, loads default texture */ /* If an empty string or null is put for path, loads default texture */
struct Texture *texture_pullfromfile(const char *path) struct Texture *texture_pullfromfile(const char *path)
{ {
if (!path || path[0] == '\0') { return NULL; }
int index = shgeti(texhash, path); int index = shgeti(texhash, path);
if (index != -1) if (index != -1)
return texhash[index].value; return texhash[index].value;
@ -49,8 +47,9 @@ struct Texture *texture_pullfromfile(const char *path)
unsigned char *data = stbi_load(path, &tex->width, &tex->height, &n, 4); unsigned char *data = stbi_load(path, &tex->width, &tex->height, &n, 4);
if (data == NULL) { if (data == NULL) {
YughError("STBI failed to load file %s with message: %s", path, stbi_failure_reason()); YughError("STBI failed to load file %s with message: %s\nOpening default instead.", path, stbi_failure_reason());
return NULL; print_stacktrace();
return texture_pullfromfile("./icons/no_tex.png");
} }
tex->data = data; tex->data = data;
@ -94,11 +93,6 @@ struct Texture *texture_pullfromfile(const char *path)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// stbi_image_free(data);
if (shlen(texhash) == 0) if (shlen(texhash) == 0)
sh_new_arena(texhash); sh_new_arena(texhash);
@ -122,8 +116,6 @@ struct Texture *texture_loadfromfile(const char *path)
{ {
struct Texture *new = texture_pullfromfile(path); struct Texture *new = texture_pullfromfile(path);
if (new == NULL) { new = texture_pullfromfile("./icons/no_tex.png"); }
if (new->id == 0) { if (new->id == 0) {
glGenTextures(1, &new->id); glGenTextures(1, &new->id);

View file

@ -58,19 +58,12 @@ int fps;
#define SIM_PAUSE 2 #define SIM_PAUSE 2
#define SIM_STEP 3 #define SIM_STEP 3
void seghandle(int sig) { void print_stacktrace()
/* {
#ifdef __linux__
void *ents[512]; void *ents[512];
size_t size; size_t size;
size = backtrace(ents, 512); size = backtrace(ents, 512);
if (strsignal(sig)) {
YughCritical("CRASH! Signal: %s.", strsignal(sig));
}
else {
YughCritical("CRASH! Signal: %d.", sig);
}
YughCritical("====================BACKTRACE===================="); YughCritical("====================BACKTRACE====================");
char **stackstr = backtrace_symbols(ents, size); char **stackstr = backtrace_symbols(ents, size);
@ -81,11 +74,23 @@ void seghandle(int sig) {
YughCritical(stackstr[i]); YughCritical(stackstr[i]);
} }
duk_dump_stack(duk); js_dump_stack();
}
void seghandle(int sig) {
#ifdef __linux__
if (strsignal(sig)) {
YughCritical("CRASH! Signal: %s.", strsignal(sig));
}
else {
YughCritical("CRASH! Signal: %d.", sig);
}
print_stacktrace();
exit(1); exit(1);
#endif #endif
*/
} }
void compile_script(const char *file) void compile_script(const char *file)
@ -135,6 +140,10 @@ int main(int argc, char **args) {
compile_script(args[2]); compile_script(args[2]);
exit(0); exit(0);
case 'm':
logLevel = atoi(args[2]);
break;
case 'h': case 'h':
printf("-l Set log file\n"); printf("-l Set log file\n");
printf("-p Launch engine in play mode instead of editor mode\n"); printf("-p Launch engine in play mode instead of editor mode\n");
@ -172,6 +181,8 @@ int main(int argc, char **args) {
signal(SIGSEGV, seghandle); signal(SIGSEGV, seghandle);
signal(SIGABRT, seghandle); signal(SIGABRT, seghandle);
signal(SIGFPE, seghandle); signal(SIGFPE, seghandle);
signal(SIGBUS, seghandle);
#endif #endif
FILE *gameinfo = NULL; FILE *gameinfo = NULL;
@ -186,13 +197,14 @@ int main(int argc, char **args) {
renderMS = 1.0/vidmode->refreshRate; renderMS = 1.0/vidmode->refreshRate;
input_init();
openglInit();
if (ed) if (ed)
script_dofile("scripts/editor.js"); script_dofile("scripts/editor.js");
else else
script_dofile("game.js"); script_dofile("scripts/play.js");
input_init();
openglInit();
while (!want_quit()) { while (!want_quit()) {
double elapsed = glfwGetTime() - lastTick; double elapsed = glfwGetTime() - lastTick;
deltaT = elapsed; deltaT = elapsed;

View file

@ -9,6 +9,7 @@ void sim_stop();
void sim_step(); void sim_step();
int phys_stepping(); int phys_stepping();
void set_timescale(float val); void set_timescale(float val);
void print_stacktrace();
int frame_fps(); int frame_fps();

View file

@ -169,39 +169,3 @@ var Nuke = {
Object.defineProperty(Nuke, "curwin", {enumerable:false}); Object.defineProperty(Nuke, "curwin", {enumerable:false});
Object.defineProperty(Nuke, "defaultrect", {enumerable:false}); Object.defineProperty(Nuke, "defaultrect", {enumerable:false});
var Log = {
print(msg, lvl) {
var lg;
if (typeof msg === 'object') {
lg = JSON.stringify(msg, null, 2);
} else {
lg = msg;
}
var stack = (new Error()).stack;
var n = stack.next('\n',0)+1;
n = stack.next('\n', n)+1;
var nnn = stack.slice(n);
var fmatch = nnn.match(/\(.*\:/);
var file = fmatch ? fmatch[0].shift(1).shift(-1) : "nofile";
var lmatch = nnn.match(/\:\d*\)/);
var line = lmatch ? lmatch[0].shift(1).shift(-1) : "0";
yughlog(lvl, lg, file, line);
},
info(msg) {
this.print(msg, 0);
},
warn(msg) {
this.print(msg, 1);
},
error(msg) {
this.print(msg, 2);
},
};

View file

@ -1,6 +1,68 @@
var Log = {
set level(x) { cmd(92,x); },
get level() { return cmd(93); },
print(msg, lvl) {
var lg;
if (typeof msg === 'object') {
lg = JSON.stringify(msg, null, 2);
} else {
lg = msg;
}
var stack = (new Error()).stack;
var n = stack.next('\n',0)+1;
n = stack.next('\n', n)+1;
var nnn = stack.slice(n);
var fmatch = nnn.match(/\(.*\:/);
var file = fmatch ? fmatch[0].shift(1).shift(-1) : "nofile";
var lmatch = nnn.match(/\:\d*\)/);
var line = lmatch ? lmatch[0].shift(1).shift(-1) : "0";
yughlog(lvl, lg, file, line);
},
info(msg) {
this.print(msg, 0);
},
warn(msg) {
this.print(msg, 1);
},
error(msg) {
this.print(msg, 2);
this.stack(1);
},
critical(msg) {
this.print(msg,3);
this.stack(1);
},
write(msg) {
cmd(91,msg);
},
stack(skip) {
var stack = (new Error()).stack;
var n = stack.next('\n',0)+1;
for (var i = 0; i < skip; i++)
n = stack.next('\n', n)+1;
this.write(stack.slice(n));
},
};
var files = {}; var files = {};
function load(file) { function load(file) {
var modtime = cmd(0, file); var modtime = cmd(0, file);
if (modtime === 0) {
Log.stack();
return false;
}
files[file] = modtime; files[file] = modtime;
} }