Skip to content

Commit

Permalink
feat: cjit compile and add file wrappers to tcc
Browse files Browse the repository at this point in the history
started to move quite some cjit operations inside cjit_ function
wrappers taking care of path and extensions
  • Loading branch information
jaromil committed Dec 28, 2024
1 parent a54d522 commit 0667cc8
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 49 deletions.
78 changes: 71 additions & 7 deletions src/cjit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);

Check warning on line 221 in src/cjit.c

View workflow job for this annotation

GitHub Actions / cpplint

[cpplint] src/cjit.c#L221

Use int16_t/int64_t/etc, rather than the C type long [runtime/int] [4]
Raw output
src/cjit.c:221:  Use int16_t/int64_t/etc, rather than the C type long  [runtime/int] [4]
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");

Check warning on line 270 in src/cjit.c

View workflow job for this annotation

GitHub Actions / cpplint

[cpplint] src/cjit.c#L270

Almost always, snprintf is better than strcpy [runtime/printf] [4]
Raw output
src/cjit.c:270:  Almost always, snprintf is better than strcpy  [runtime/printf] [4]
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)
Expand All @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions src/cjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
82 changes: 43 additions & 39 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 0667cc8

Please sign in to comment.