Page MenuHomePhorge

main.c
No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None
#include <compat.h> // IWYU pragma: keep
#include <arena.h>
#include <oxc.h>
#include <cli/pkg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <argtable3.h>
#include "ant.h"
#include "config.h"
#include "repl.h"
#include "utils.h"
#include "reactor.h"
#include "runtime.h"
#include "snapshot.h"
#include "esm/remote.h"
#include "internal.h"
#include "modules/builtin.h"
#include "modules/buffer.h"
#include "modules/atomics.h"
#include "modules/os.h"
#include "modules/io.h"
#include "modules/fs.h"
#include "modules/crypto.h"
#include "modules/server.h"
#include "modules/timer.h"
#include "modules/json.h"
#include "modules/fetch.h"
#include "modules/shell.h"
#include "modules/process.h"
#include "modules/path.h"
#include "modules/ffi.h"
#include "modules/events.h"
#include "modules/performance.h"
#include "modules/uri.h"
#include "modules/url.h"
#include "modules/reflect.h"
#include "modules/symbol.h"
#include "modules/textcodec.h"
#include "modules/sessionstorage.h"
#include "modules/localstorage.h"
#include "modules/navigator.h"
#include "modules/child_process.h"
#include "modules/readline.h"
#include "modules/observable.h"
#include "modules/collections.h"
int js_result = EXIT_SUCCESS;
typedef int (*cmd_fn)(int argc, char **argv);
typedef struct {
const char *name;
const char *alias;
const char *desc;
cmd_fn fn;
} subcommand_t;
static const subcommand_t subcommands[] = {
{"init", NULL, "Create a new package.json", pkg_cmd_init},
{"install", "i", "Install dependencies from lockfile", pkg_cmd_install},
{"add", "a", "Add a package to dependencies", pkg_cmd_add},
{"remove", "rm", "Remove a package from dependencies", pkg_cmd_remove},
{"trust", NULL, "Run lifecycle scripts for packages", pkg_cmd_trust},
{"run", NULL, "Run a script from package.json", pkg_cmd_run},
{"exec", "x", "Run a command from node_modules/.bin", pkg_cmd_exec},
{"why", "explain", "Show why a package is installed", pkg_cmd_why},
{"info", NULL, "Show package information from registry", pkg_cmd_info},
{"ls", "list", "List installed packages", pkg_cmd_ls},
{"cache", NULL, "Manage the package cache", pkg_cmd_cache},
{NULL, NULL, NULL, NULL}
};
static const subcommand_t *find_subcommand(const char *name) {
for (const subcommand_t *cmd = subcommands; cmd->name; cmd++) {
if (strcmp(name, cmd->name) == 0) return cmd;
if (cmd->alias && strcmp(name, cmd->alias) == 0) return cmd;
}
return NULL;
}
static void print_subcommands(void) {
printf("Commands:\n");
for (const subcommand_t *cmd = subcommands; cmd->name; cmd++) {
printf(" %-12s %s\n", cmd->name, cmd->desc);
}
printf("\n");
}
static void eval_code(struct js *js, struct arg_str *eval, struct arg_lit *print) {
const char *script = eval->sval[0];
size_t len = strlen(script);
js_set_filename(js, "[eval]");
js_setup_import_meta(js, "[eval]");
js_mkscope(js);
js_set(js, js_glob(js), "__dirname", js_mkstr(js, ".", 1));
js_set(js, js_glob(js), "__filename", js_mkstr(js, "[eval]", 6));
jsval_t result = js_eval(js, script, len);
js_run_event_loop(js);
char cbuf_stack[512]; js_cstr_t cstr = js_to_cstr(
js, result, cbuf_stack, sizeof(cbuf_stack)
);
if (vtype(result) == T_ERR) {
fprintf(stderr, "%s\n", cstr.ptr);
js_result = EXIT_FAILURE;
} else if (print->count > 0) {
if (vtype(result) == T_STR) printf("%s\n", cstr.ptr ? cstr.ptr : "");
else if (cstr.ptr && strcmp(cstr.ptr, "undefined") != 0) {
print_value_colored(cstr.ptr, stdout); printf("\n");
}
} if (cstr.needs_free) free((void *)cstr.ptr);
}
static char *read_file(const char *filename, size_t *len) {
FILE *fp = fopen(filename, "rb");
if (!fp) return NULL;
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buffer = malloc(size + 1);
if (!buffer) {
fclose(fp);
return NULL;
}
*len = fread(buffer, 1, size, fp);
fclose(fp);
buffer[*len] = '\0';
return buffer;
}
static int execute_module(struct js *js, const char *filename) {
char *buffer = NULL;
size_t len = 0;
char abs_path[PATH_MAX];
const char *use_path = filename;
if (esm_is_url(filename)) {
char *error = NULL;
buffer = esm_fetch_url(filename, &len, &error);
if (!buffer) {
fprintf(stderr, "Error: Could not fetch '%s': %s\n", filename, error ? error : "unknown error");
free(error);
return EXIT_FAILURE;
}
js_set(js, js_glob(js), "__dirname", js_mkundef());
} else {
buffer = read_file(filename, &len);
if (!buffer) {
fprintf(stderr, "Error: Could not open file '%s'\n", filename);
return EXIT_FAILURE;
}
char *file_path = strdup(filename);
char *dir = dirname(file_path);
js_set(js, js_glob(js), "__dirname", js_mkstr(js, dir, strlen(dir)));
free(file_path);
if (realpath(filename, abs_path)) use_path = abs_path;
}
char *js_code = buffer;
size_t js_len = len;
if (is_typescript_file(filename)) {
int result = OXC_strip_types(buffer, filename, buffer, len + 1);
if (result < 0) {
fprintf(stderr, "TypeScript error: strip failed (%d)\n", result);
free(buffer);
return EXIT_FAILURE;
}
js_len = (size_t)result;
}
js_set_filename(js, use_path);
js_set(js, js_glob(js), "__filename", js_mkstr(js, filename, strlen(filename)));
js_setup_import_meta(js, use_path);
js_mkscope(js);
jsval_t result = js_eval_cached(js, js_code, js_len);
free(js_code);
if (vtype(result) == T_ERR) {
fprintf(stderr, "%s\n", js_str(js, result));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
int filtered_argc = 0;
const char *binary_name = strrchr(argv[0], '/');
binary_name = binary_name ? binary_name + 1 : argv[0];
if (strcmp(binary_name, "antx") == 0) {
char **exec_argv = try_oom(sizeof(char*) * (argc + 2));
exec_argv[0] = argv[0]; exec_argv[1] = "x";
for (int i = 1; i < argc; i++) exec_argv[i + 1] = argv[i];
exec_argv[argc + 1] = NULL;
int exitcode = pkg_cmd_exec(argc, exec_argv + 1);
free(exec_argv); return exitcode;
}
char **filtered_argv = try_oom(sizeof(char*) * argc);
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--verbose") == 0) pkg_verbose = true;
else if (strcmp(argv[i], "--no-color") == 0) io_no_color = true;
else filtered_argv[filtered_argc++] = argv[i];
}
if (filtered_argc >= 2 && filtered_argv[1][0] != '-') {
const subcommand_t *cmd = find_subcommand(filtered_argv[1]);
if (cmd) {
int exitcode = cmd->fn(filtered_argc - 1, filtered_argv + 1);
free(filtered_argv);
return exitcode;
}
if (pkg_script_exists("package.json", filtered_argv[1])) {
int exitcode = pkg_cmd_run(filtered_argc, filtered_argv);
free(filtered_argv);
return exitcode;
}
}
argc = filtered_argc;
argv = filtered_argv;
struct arg_lit *help = arg_lit0("h", "help", "display this help and exit");
struct arg_lit *version = arg_lit0("v", "version", "display version information and exit");
struct arg_lit *version_raw = arg_lit0(NULL, "version-raw", "raw version number for scripts");
struct arg_str *eval = arg_str0("e", "eval", "<script>", "evaluate script");
struct arg_lit *print = arg_lit0("p", "print", "evaluate script and print result");
struct arg_int *initial_mem = arg_int0(NULL, "initial-mem", "<size>", "initial memory size in KB (default: 16kb)");
struct arg_int *max_mem = arg_int0(NULL, "max-mem", "<size>", "maximum memory size in MB (default: 1024mb)");
struct arg_file *localstorage_file = arg_file0(NULL, "localstorage-file", "<path>", "file path for localStorage persistence");
struct arg_file *file = arg_file0(NULL, NULL, "<module.js>", "JavaScript module file to execute");
struct arg_end *end = arg_end(20);
void *argtable[] = {
help, version, version_raw,
eval, print, initial_mem, max_mem,
localstorage_file, file, end
};
int nerrors = arg_parse(argc, argv, argtable);
if (help->count > 0) {
printf("Ant sized JavaScript\n\n");
printf("Usage: ant [options] [module.js]\n");
printf(" ant <command> [args]\n\n");
print_subcommands();
printf("If no module file is specified, ant starts in REPL mode.\n\n");
printf("Options:\n");
printf(" %-28s %s\n", "--verbose", "enable verbose output");
printf(" %-28s %s\n", "--no-color", "disable colored output");
arg_print_glossary(stdout, argtable, " %-28s %s\n");
arg_freetable(argtable, ARGTABLE_COUNT);
free(filtered_argv);
return EXIT_SUCCESS;
}
if (version_raw->count > 0) {
fputs(ANT_VERSION "\n", stdout);
arg_freetable(argtable, ARGTABLE_COUNT);
free(filtered_argv); return EXIT_SUCCESS;
}
if (version->count > 0) {
int res = ant_version(argtable);
free(filtered_argv); return res;
}
if (nerrors > 0) {
arg_print_errors(stdout, end, "ant");
printf("Try 'ant --help' for more information.\n");
arg_freetable(argtable, ARGTABLE_COUNT);
free(filtered_argv); return EXIT_FAILURE;
}
bool repl_mode = (file->count == 0 && eval->count == 0);
const char *module_file = repl_mode ? NULL : (file->count > 0 ? file->filename[0] : NULL);
struct js *js = js_create_dynamic(
initial_mem->count > 0 ? (size_t)initial_mem->ival[0] * 1024 : 0,
max_mem->count > 0 ? (size_t)max_mem->ival[0] * 1024 * 1024 : 0
);
if (js == NULL) {
fprintf(stderr, "Error: Failed to allocate JavaScript runtime\n");
arg_freetable(argtable, ARGTABLE_COUNT);
free(filtered_argv);
return EXIT_FAILURE;
}
volatile char stack_base;
js_setstackbase(js, (void *)&stack_base);
ant_runtime_init(js, argc, argv, localstorage_file);
init_symbol_module();
init_collections_module();
init_builtin_module();
init_buffer_module();
init_fs_module();
init_atomics_module();
init_crypto_module();
init_fetch_module();
init_console_module();
init_json_module();
init_server_module();
init_timer_module();
init_process_module();
init_events_module();
init_performance_module();
init_uri_module();
init_url_module();
init_reflect_module();
init_textcodec_module();
init_sessionstorage_module();
init_localstorage_module();
init_navigator_module();
init_observable_module();
ant_register_library(shell_library, "ant:shell", NULL);
ant_register_library(ffi_library, "ant:ffi", NULL);
ant_standard_library("path", path_library);
ant_standard_library("fs", fs_library);
ant_standard_library("os", os_library);
ant_standard_library("crypto", crypto_library);
ant_standard_library("events", events_library);
ant_standard_library("readline", readline_library);
ant_standard_library("readline/promises", readline_promises_library);
ant_standard_library("child_process", child_process_library);
jsval_t snapshot_result = ant_load_snapshot(js);
if (vtype(snapshot_result) == T_ERR) {
fprintf(stderr, "Warning: Failed to load snapshot: %s\n", js_str(js, snapshot_result));
}
// Enable generational GC nursery after initialization is complete
nursery_enable(js);
if (eval->count > 0) eval_code(js, eval, print);
else if (repl_mode) ant_repl_run(); else {
struct stat path_stat;
char *resolved_file = NULL;
resolved_file = resolve_js_file(module_file);
if (resolved_file) module_file = resolved_file;
if (stat(module_file, &path_stat) == 0 && S_ISDIR(path_stat.st_mode)) {
size_t len = strlen(module_file);
int has_slash = (len > 0 && module_file[len - 1] == '/');
if (resolved_file) free(resolved_file);
resolved_file = try_oom(len + 10 + (has_slash ? 0 : 1));
sprintf(resolved_file, "%s%sindex.js", module_file, has_slash ? "" : "/");
module_file = resolved_file;
}
js_result = execute_module(js, module_file);
js_run_event_loop(js);
if (resolved_file) free(resolved_file);
}
js_destroy(js);
arg_freetable(argtable, ARGTABLE_COUNT);
free(filtered_argv);
return js_result;
}

File Metadata

Mime Type
text/x-c
Expires
Fri, Mar 27, 5:01 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
512536
Default Alt Text
main.c (12 KB)

Event Timeline