Skip to content

Commit

Permalink
fix: now using cjit_add_file, various fixes and improvements
Browse files Browse the repository at this point in the history
correctly executes object files, improved help docs and better code
organization
  • Loading branch information
jaromil committed Dec 28, 2024
1 parent e10073c commit 70c6a4e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 51 deletions.
93 changes: 61 additions & 32 deletions src/cjit.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,30 +194,39 @@ bool cjit_setup(CJITState *cjit) {
return(true);
}

bool cjit_add_file(CJITState *cjit, const char *path) {
static int has_source_extension(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) {
bool is_source;
is_source = cwk_path_get_extension(path,(const char**)&ext,&extlen);
//_err("%s: extension: %s",__func__,ext);
if(!is_source) // no extension at all
return 0;
if(extlen==2 && (ext[1]=='c' || ext[1]=='C')) is_source = true;
else if(extlen==3
&& (ext[1]=='c' || ext[1]=='C')
&& (ext[2]=='c' || ext[2]=='C')) is_source = true;
else if(extlen==4
&& (ext[1]=='c' || ext[1]=='C')
&& (ext[2]=='x' || ext[2]=='X')
&& (ext[3]=='x' || ext[3]=='X')) is_source = true;
else is_source = false;
return (is_source? 1 : -1);
}

bool cjit_add_file(CJITState *cjit, const char *path) {
// _err("%s",__func__);
int is_source = has_source_extension(path);
if(is_source == 0) { // no extension, we still add
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) {
if(is_source>0) {
// _err("%s: is source(%i): %s",__func__, is_source, path);
long length = file_size(path);
if (length == -1) return false;
FILE *file = fopen(path, "r");
Expand All @@ -235,6 +244,15 @@ bool cjit_add_file(CJITState *cjit, const char *path) {
contents[length] = 0x0; // Null-terminate the string
fclose(file);
cjit_setup(cjit);
size_t dirname;
cwk_path_get_dirname(path,&dirname);
if(dirname) {
char *tmp = malloc(dirname+1);
strncpy(tmp,path,dirname);
tmp[dirname] = 0x0;
tcc_add_include_path(cjit->TCC,tmp);
free(tmp);
}
tcc_compile_string(cjit->TCC,contents);
free(contents);
} else {
Expand All @@ -248,32 +266,43 @@ bool cjit_add_file(CJITState *cjit, const char *path) {
}

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);
tmp = malloc(len+2);
strncpy(tmp,basename,len+1);
int is_source = has_source_extension(path);
// _err("basename: %s",tmp);
if( !cwk_path_get_extension(tmp,(const char**)&ext,&len) ) {
if( is_source == 0) {
_err("%s: filename has no extension: %s",
__func__,basename);
return 1;
return false;
}
// _err("extension: %s",ext);
if( *(ext+1) != 'c' ) {
if( is_source < 0) {
_err("%s: filename has wrong extension: %s",
__func__,basename);
return 1;
return false;
}
strcpy(ext,".o");
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;
if(cjit->output_filename) {
if(!cjit->quiet)
_err("Compiling: %s -> %s",path,
cjit->output_filename);
tcc_output_file(cjit->TCC,
cjit->output_filename);
} else {
char *ext;
size_t extlen;
char *restrict tmp;
const char *basename;
size_t len;
cwk_path_get_basename((char*)path, &basename, &len);
tmp = malloc(len+2);
strncpy(tmp,basename,len+1);
cwk_path_get_extension(tmp,(const char**)&ext,&extlen);
strcpy(ext,".o");
if(!cjit->quiet)
_err("Compiling: %s -> %s",path,tmp);
tcc_output_file(cjit->TCC,tmp);
free(tmp);
}
return true;
}

int cjit_exec(CJITState *cjit, int argc, char **argv) {
Expand Down
41 changes: 22 additions & 19 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,28 @@ static int parse_value(char *str) {
}

const char cli_help[] =
"\n"
"Synopsis: cjit [options] files(*) -- app arguments\n"
" (*) can be any source (.c) or built object (dll, dylib, .so)\n"
"Options:\n"
" -h \t print this help\n"
" -v \t print version information\n"
" -q \t stay quiet and only print errors and output\n"
" -D sym\t define a macro symbol or key=value\n"
" -C \t set compiler flags (default from env var CFLAGS)\n"
" -I dir\t also search folder 'dir' for header files\n"
" -l lib\t search the library named 'lib' when linking\n"
" -L dir\t also search inside folder 'dir' for -l libs\n"
" -e fun\t entry point function (default 'main')\n"
" -p pid\t write pid of executed program to file\n"
" --temp\t create the runtime temporary dir and exit\n"
"CJIT %s by Dyne.org\n"
"\n"
"Synopsis: cjit [options] files(*) -- app arguments\n"
" (*) can be any source (.c) or built object (dll, dylib, .so)\n"
"Options:\n"
" -h \t print this help\n"
" -v \t print version information\n"
" -q \t stay quiet and only print errors and output\n"
" -D sym\t define a macro symbol or key=value\n"
" -C \t set compiler flags (default from env var CFLAGS)\n"
" -I dir\t also search folder 'dir' for header files\n"
" -l lib\t search the library named 'lib' when linking\n"
" -L dir\t also search inside folder 'dir' for -l libs\n"
" -e fun\t entry point function (default 'main')\n"
" -p pid\t write pid of executed program to file\n"
" -c \t compile a single source file, do not execute\n"
" -o exe\t compile to an 'exe' file, do not execute\n"
" --temp\t create the runtime temporary dir and exit\n"
#if defined(SELFHOST)
" --src\t extract source code to cjit_source\n"
" --src\t extract source code to cjit_source\n"
#endif
" --xtgz\t extract all contents from a USTAR tar.gz\n";
" --xtgz\t extract all contents from a USTAR tar.gz\n";


int main(int argc, char **argv) {
Expand All @@ -101,7 +104,7 @@ int main(int argc, char **argv) {
};
ketopt_t opt = KETOPT_INIT;
// tolerated and ignored: -f -W -O -g -U -E -S -M
while ((c = ketopt(&opt, argc, argv, 1, "qhvD:L:l:C:I:e:p:co:f:W:O:gU:ESM:", longopts)) >= 0) {
while ((c = ketopt(&opt, argc, argv, 1, "qhvD:L:l:C:I:e:p:co:f:W:O:gU:ESM:m:", longopts)) >= 0) {
if(c == 'q') {
CJIT->quiet = true;
}
Expand Down Expand Up @@ -284,7 +287,7 @@ int main(int argc, char **argv) {
// 3 : BOM found, UTF8
if(res ==0) {
cjit_setup(CJIT);
tcc_add_file(CJIT->TCC, code_path);
cjit_add_file(CJIT, code_path);
} else if(res<0) {
_err("Cannot open file: %s",code_path);
_err("Execution aborted.");
Expand Down
16 changes: 16 additions & 0 deletions test/cli.bats
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ load bats_setup
assert_output --partial 'Please compile with -DALLOWED=1'
}

@test "Compile to object and execute" {
run ${CJIT} -c test/hello.c
assert_success
run ${CJIT} hello.o
assert_success
assert_output 'Hello World!'
}

@test "Compile to custom object and execute" {
run ${CJIT} -o world.o -c test/hello.c
assert_success
run ${CJIT} world.o
assert_success
assert_output 'Hello World!'
}

@test "Execute multiple files" {
run ${CJIT} -q test/multifile/*
assert_success
Expand Down

0 comments on commit 70c6a4e

Please sign in to comment.