Skip to content

Commit

Permalink
Do not rely on argv[0] to locate the executable (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Jan 22, 2023
1 parent ae5daa5 commit 3cc760c
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 18 deletions.
58 changes: 48 additions & 10 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#ifndef _WIN32
// readlink() stuff
#define _POSIX_C_SOURCE 200112L
#include <unistd.h>
#endif // _WIN32

#include <assert.h>
#include <libgen.h>
#include <errno.h>
#include <stdio.h>
Expand Down Expand Up @@ -202,27 +209,58 @@ static void compile_ast_to_llvm(struct CompileState *compst, struct FileState *f
}
}

static char *find_stdlib(const char *argv0)
// argv[0] doesn't work as expected when Jou is ran through PATH.
char *find_this_executable(void)
{
char *s = strdup(argv0);
const char *exedir = dirname(s);
char *result;
const char *err;

#ifdef _WIN32
extern char *_pgmptr; // A documented global variable in Windows. Full path to executable.
result = strdup(_pgmptr);
err = NULL;
#else
int n = 10000;
result = calloc(1, n);
ssize_t ret = readlink("/proc/self/exe", result, n);

if (ret < 0)
err = strerror(errno);
else if (ret == n) {
static char s[100];
sprintf(s, "path is more than %d bytes long", n);
err=s;
} else {
assert(0<ret && ret<n);
err = NULL;
}
#endif

// ./stdlib looks a bit ugly in error messages and debug output IMO
if (!strcmp(exedir, ".")) {
free(s);
return strdup("stdlib");
if(err) {
fprintf(stderr, "error finding current executable, needed to find the Jou standard library: %s\n", err);
exit(1);
}
return result;
}

static char *find_stdlib()
{
char *exe = find_this_executable();
const char *exedir = dirname(exe);

char *path = malloc(strlen(exedir) + 10);
strcpy(path, exedir);
free(s);
strcat(path, "/stdlib");
free(exe);

char *iojou = malloc(strlen(path) + 10);
sprintf(iojou, "%s/io.jou", path);
struct stat st;
if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) {
if (stat(iojou, &st) != 0) {
fprintf(stderr, "error: cannot find the Jou standard library in %s\n", path);
exit(1);
}
free(iojou);

return path;
}
Expand All @@ -231,7 +269,7 @@ int main(int argc, char **argv)
{
init_types();

struct CompileState compst = { .stdlib_path = find_stdlib(argv[0]) };
struct CompileState compst = { .stdlib_path = find_stdlib() };
const char *filename;
parse_arguments(argc, argv, &compst.flags, &filename);

Expand Down
2 changes: 1 addition & 1 deletion tests/404/file.jou
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from "stdlib/foobar.jou" import x # Error: cannot import from "stdlib/foobar.jou": No such file or directory
from "stdlib/foobar.jou" import x # Error: cannot import from "<joudir>/stdlib/foobar.jou": No such file or directory
2 changes: 1 addition & 1 deletion tests/404/import_symbol.jou
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from "stdlib/io.jou" import asd # Error: file "stdlib/io.jou" does not contain a function named 'asd'
from "stdlib/io.jou" import asd # Error: file "<joudir>/stdlib/io.jou" does not contain a function named 'asd'
2 changes: 1 addition & 1 deletion tests/404/import_symbol_multiline.jou
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
from "stdlib/io.jou" import (
printf,
scanf,
asd, # Error: file "stdlib/io.jou" does not contain a function named 'asd'
asd, # Error: file "<joudir>/stdlib/io.jou" does not contain a function named 'asd'
puts,
)
5 changes: 3 additions & 2 deletions tests/runtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ function post_process_output()
# mentions "Segmentation fault" somewhere inside it.
grep -oE "Segmentation fault|Exit code: .*"
else
# Pass the output through unchanged.
cat
# Pass the output through almost unchanged, but replace
# path to the project (e.g. /home/akuli/jou) with <joudir>.
sed "s,$(pwd),<joudir>,g"
fi
}

Expand Down
6 changes: 3 additions & 3 deletions tests/should_succeed/compiler_cli.jou
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def main() -> int:

# With optimizations enabled, we see also the optimized LLVM IR.
system("./jou --verbose -O1 examples/hello.jou | grep 'LLVM IR for file'")
# Output: ===== Unoptimized LLVM IR for file "stdlib/io.jou" =====
# Output: ===== Optimized LLVM IR for file "stdlib/io.jou" =====
# Output: ===== Unoptimized LLVM IR for file "<joudir>/stdlib/io.jou" =====
# Output: ===== Optimized LLVM IR for file "<joudir>/stdlib/io.jou" =====
# Output: ===== Unoptimized LLVM IR for file "examples/hello.jou" =====
# Output: ===== Optimized LLVM IR for file "examples/hello.jou" =====

Expand All @@ -37,6 +37,6 @@ def main() -> int:

# Executable in weird place
system("cp jou tmp/tests/jou_executable")
system("tmp/tests/jou_executable 2>&1") # Output: error: cannot find the Jou standard library in tmp/tests/stdlib
system("tmp/tests/jou_executable 2>&1") # Output: error: cannot find the Jou standard library in <joudir>/tmp/tests/stdlib

return 0

0 comments on commit 3cc760c

Please sign in to comment.