From 0667cc8e3fed825780d8f53b7a1318a000adeba9 Mon Sep 17 00:00:00 2001 From: Jaromil Date: Sat, 28 Dec 2024 14:03:48 +0100 Subject: [PATCH] feat: cjit compile and add file wrappers to tcc started to move quite some cjit operations inside cjit_ function wrappers taking care of path and extensions --- src/cjit.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++----- src/cjit.h | 6 ++-- src/file.c | 2 +- src/main.c | 82 ++++++++++++++++++++++++++++-------------------------- 4 files changed, 119 insertions(+), 49 deletions(-) diff --git a/src/cjit.c b/src/cjit.c index b3c5616..4041f0d 100644 --- a/src/cjit.c +++ b/src/cjit.c @@ -133,7 +133,7 @@ CJITState* cjit_new() { bool cjit_setup(CJITState *cjit) { // set output in memory for just in time execution - + if(cjit->done_setup) return(true); tcc_set_output_type(cjit->TCC, cjit->tcc_output? cjit->tcc_output: @@ -190,36 +190,98 @@ bool cjit_setup(CJITState *cjit) { free(sdkpath); } #endif + cjit->done_setup = true; return(true); } -int cjit_compile_obj(CJITState *cjit, const char *_path) { +bool cjit_add_file(CJITState *cjit, const char *path) { + char *ext; + size_t extlen; + bool is_source = false; + bool res = cwk_path_get_extension(path,(const char**)&ext,&extlen); + // no filename extension: still good to add + if(!res) { + cjit_setup(cjit); + if(tcc_add_file(cjit->TCC, path)<0) { + _err("%s: tcc_add_file error",__func__); + return false; + } + return true; + } + // if C source then use tcc_compile_string + if(extlen==1 && (ext[1]=='c' || ext[1]=='C')) is_source = true; + if(extlen==3 + && (ext[1]=='c' || ext[1]=='C') + && (ext[2]=='c' || ext[2]=='C')) is_source = true; + if(extlen==4 + && (ext[1]=='c' || ext[1]=='C') + && (ext[2]=='x' || ext[2]=='X') + && (ext[3]=='x' || ext[3]=='X')) is_source = true; + if(is_source) { + long length = file_size(path); + if (length == -1) return false; + FILE *file = fopen(path, "r"); + if (!file) { + _err("%s: fopen error: ", __func__, strerror(errno)); + return false; + } + char *contents = (char*)malloc((length + 1) * sizeof(char)); + if (!contents) { + _err("%s: malloc error: %s",__func__, strerror(errno)); + fclose(file); + return false; + } + fread(contents, 1, length, file); + contents[length] = 0x0; // Null-terminate the string + fclose(file); + cjit_setup(cjit); + tcc_compile_string(cjit->TCC,contents); + free(contents); + } else { + cjit_setup(cjit); + if(tcc_add_file(cjit->TCC, path)<0) { + _err("%s: tcc_add_file error",__func__); + return false; + } + } + return true; +} + +bool cjit_compile_file(CJITState *cjit, const char *path) { char *restrict tmp; const char *basename; char *ext; size_t len; - cwk_path_get_basename((char*)_path, &basename, &len); + cwk_path_get_basename((char*)path, &basename, &len); tmp = malloc(len+2); strncpy(tmp,basename,len+1); // _err("basename: %s",tmp); if( !cwk_path_get_extension(tmp,(const char**)&ext,&len) ) { - _err("Filename has no extension: %s",basename); + _err("%s: filename has no extension: %s", + __func__,basename); return 1; } // _err("extension: %s",ext); if( *(ext+1) != 'c' ) { - _err("Filename has wrong extension: %s",ext); + _err("%s: filename has wrong extension: %s", + __func__,basename); return 1; } strcpy(ext,".o"); - tcc_add_file(cjit->TCC, _path); - _err("Compiling: %s -> %s",_path,tmp); + cjit_setup(cjit); + tcc_add_file(cjit->TCC, path); + _err("Compiling: %s -> %s",path,tmp); tcc_output_file(cjit->TCC,tmp); free(tmp); return 0; } int cjit_exec(CJITState *cjit, int argc, char **argv) { + if(cjit->done_exec) { + _err("%s: CJIT already executed once",__func__); + return 1; + } + int res = 1; int (*_ep)(int, char**); // relocate the code (link symbols) @@ -244,10 +306,12 @@ int cjit_exec(CJITState *cjit, int argc, char **argv) { fprintf(fd,"%d\n",pid); fclose(fd); } + cjit->done_exec = true; res = _ep(argc, argv); return(res); #else // we assume anything else but WINDOWS has fork() pid_t pid; + cjit->done_exec = true; pid = fork(); if (pid == 0) { res = _ep(argc, argv); diff --git a/src/cjit.h b/src/cjit.h index 6be48d0..702c76e 100644 --- a/src/cjit.h +++ b/src/cjit.h @@ -40,13 +40,15 @@ struct CJITState { // #define TCC_OUTPUT_OBJ 3 /* object file */ // #define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */ char *output_filename; // output in case of compilation mode - + bool done_setup; + bool done_exec; }; typedef struct CJITState CJITState; extern CJITState* cjit_new(); -int cjit_compile_obj(CJITState *cjit, const char *_path); +bool cjit_compile_file(CJITState *cjit, const char *_path); +bool cjit_add_file(CJITState *cjit, const char *path); extern int cjit_exec(CJITState *cjit, int argc, char **argv); diff --git a/src/file.c b/src/file.c index add0ae6..09b8432 100644 --- a/src/file.c +++ b/src/file.c @@ -109,7 +109,7 @@ bool prepend_path(char **stored_path, const char *new_path) { long file_size(const char *filename) { FILE *file = fopen(filename, "rb"); if (file == NULL) { - perror("Error opening file"); + _err("%s: fopen error: %s",__func__,strerror(errno)); return -1; } fseek(file, 0, SEEK_END); diff --git a/src/main.c b/src/main.c index 16b6e6f..f3ff884 100644 --- a/src/main.c +++ b/src/main.c @@ -246,51 +246,55 @@ int main(int argc, char **argv) { } cjit_setup(CJIT); //if(!CJIT->quiet)_err("Compile: %s",argv[opt.ind]); - res = cjit_compile_obj(CJIT, argv[opt.ind]); + res = cjit_compile_file(CJIT, argv[opt.ind]) ?0:1; // 0 on success goto endgame; //////////////////////////// } else if(opt.ind < left_args) { - // process files on commandline before separator - if(!CJIT->quiet)_err("Source code:"); - for (i = opt.ind; i < left_args; ++i) { - const char *code_path = argv[i]; - if(!CJIT->quiet)_err("%c %s",(*code_path=='-'?'|':'+'), - (*code_path=='-'?"standard input":code_path)); - if(*code_path=='-') { // stdin explicit + // process files on commandline before separator + if(!CJIT->quiet)_err("Source code:"); + for (i = opt.ind; i < left_args; ++i) { + const char *code_path = argv[i]; + if(!CJIT->quiet)_err("%c %s",(*code_path=='-'?'|':'+'), + (*code_path=='-'?"standard input":code_path)); + if(*code_path=='-') { // stdin explicit #if defined(_WIN32) - _err("Code from standard input not supported on Windows"); - goto endgame; + _err("Code from standard input not supported on Windows"); + goto endgame; #endif - stdin_code = load_stdin(); // allocated returned buffer, needs free - if(!stdin_code) { - _err("Error reading from standard input"); - } else if( tcc_compile_string(CJIT->TCC,stdin_code) < 0) { - _err("Code runtime error in stdin"); - free(stdin_code); - goto endgame; - } else free(stdin_code); - } else { // load any file path - int res = detect_bom(code_path); - // returned values: - // 0 : no BOM, all OK - // <0 : file not found - // 1 : BOM found, UTF16-LE - // 2 : BOM found, UTF16-BE - // 3 : BOM found, UTF8 - if(res ==0) { - tcc_add_file(CJIT->TCC, code_path); - } else if(res<0) { - _err("Cannot open file: %s",code_path); - _err("Execution aborted."); - goto endgame; - } else { - _err("UTF BOM detected in file: %s",code_path); - _err("Encoding is not yet supported, execution aborted."); - goto endgame; - } - } - } + stdin_code = load_stdin(); // allocated returned buffer, needs free + if(!stdin_code) { + _err("Error reading from standard input"); + goto endgame; + } + cjit_setup(CJIT); + if( tcc_compile_string(CJIT->TCC,stdin_code) < 0) { + _err("Code runtime error in stdin"); + free(stdin_code); + goto endgame; + } else free(stdin_code); + } else { // load any file path + int res = detect_bom(code_path); + // returned values: + // 0 : no BOM, all OK + // <0 : file not found + // 1 : BOM found, UTF16-LE + // 2 : BOM found, UTF16-BE + // 3 : BOM found, UTF8 + if(res ==0) { + cjit_setup(CJIT); + tcc_add_file(CJIT->TCC, code_path); + } else if(res<0) { + _err("Cannot open file: %s",code_path); + _err("Execution aborted."); + goto endgame; + } else { + _err("UTF BOM detected in file: %s",code_path); + _err("Encoding is not yet supported, execution aborted."); + goto endgame; + } + } + } } // number of args at the left hand of arg separator, or all of them