MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

reorganize CLI argument parsing for better readability

+190 -115
+1 -1
examples/embed/embed.c
··· 25 25 } 26 26 27 27 static struct js *create_js_runtime(void *stack_base) { 28 - struct js *js = js_create_dynamic(0, 0); 28 + struct js *js = js_create_dynamic(); 29 29 if (!js) { 30 30 fprintf(stderr, "Failed to create JS runtime\n"); 31 31 return NULL;
+1 -1
include/ant.h
··· 38 38 #define JS_DESC_C (1 << 2) 39 39 40 40 ant_t *js_create(void *buf, size_t len); 41 - ant_t *js_create_dynamic(size_t initial_size, size_t max_size); 41 + ant_t *js_create_dynamic(); 42 42 43 43 jsval_t js_glob(ant_t *); 44 44 jsval_t js_mkscope(ant_t *);
+16
include/cli/misc.h
··· 1 + #ifndef MISC_H 2 + #define MISC_H 3 + #include <stdio.h> 4 + 5 + typedef struct { 6 + const char *s; 7 + const char *l; 8 + const char *d; 9 + const char *g; 10 + int opt; 11 + } flag_help_t; 12 + 13 + void print_flags_help(FILE *fp, void **argtable); 14 + void print_flag(FILE *fp, flag_help_t f); 15 + 16 + #endif
+7
include/cli/version.h
··· 1 + #ifndef VERSION_H 2 + #define VERSION_H 3 + 4 + const char *ant_semver(void); 5 + int ant_version(void *argtable[]); 6 + 7 + #endif
+1 -3
include/utils.h
··· 1 1 #ifndef ANT_UTILS_H 2 2 #define ANT_UTILS_H 3 - #define ARGTABLE_COUNT 10 3 + #define ARGTABLE_COUNT 8 4 4 5 5 #include <stdlib.h> 6 6 #include <stdint.h> ··· 11 11 char *heap; 12 12 } cstr_buf_t; 13 13 14 - const char *ant_semver(void); 15 14 char *resolve_js_file(const char *filename); 16 15 uint64_t hash_key(const char *key, size_t len); 17 16 18 17 int hex_digit(char c); 19 18 int is_typescript_file(const char *filename); 20 - int ant_version(void *argtable[]); 21 19 22 20 void *try_oom(size_t size); 23 21 void cstr_free(cstr_buf_t *buf);
+2
meson.build
··· 36 36 'src/snapshot.c', 37 37 'src/esm/remote.c', 38 38 'src/cli/pkg.c', 39 + 'src/cli/misc.c', 40 + 'src/cli/version.c', 39 41 'src/cli/cprintf.c', 40 42 ) + files(module_files) 41 43
+7 -10
src/ant.c
··· 22870 22870 return js; 22871 22871 } 22872 22872 22873 - struct js *js_create_dynamic(size_t initial_size, size_t max_size) { 22874 - if (initial_size < sizeof(struct js) + esize(T_OBJ)) initial_size = ANT_ARENA_MIN; 22875 - if (max_size == 0 || max_size < initial_size) max_size = ANT_ARENA_MAX; 22876 - 22877 - void *init_buf = ant_calloc(initial_size); 22873 + struct js *js_create_dynamic() { 22874 + void *init_buf = ant_calloc(ANT_ARENA_MIN); 22878 22875 if (init_buf == NULL) return NULL; 22879 22876 22880 - struct js *js = js_create(init_buf, initial_size); 22877 + struct js *js = js_create(init_buf, ANT_ARENA_MIN); 22881 22878 if (js == NULL) { free(init_buf); return NULL; } 22882 22879 22883 - uint8_t *arena = (uint8_t *)ant_arena_reserve(max_size); 22880 + uint8_t *arena = (uint8_t *)ant_arena_reserve(ANT_ARENA_MAX); 22884 22881 if (arena == NULL) { free(init_buf); return NULL; } 22885 22882 22886 22883 if (ant_arena_commit(arena, 0, js->size) != 0) { 22887 - ant_arena_free(arena, max_size); 22884 + ant_arena_free(arena, ANT_ARENA_MAX); 22888 22885 free(init_buf); return NULL; 22889 22886 } 22890 22887 ··· 22892 22889 js->mem = arena; 22893 22890 22894 22891 js->owns_mem = true; 22895 - js->max_size = (jsoff_t) max_size; 22892 + js->max_size = (jsoff_t) ANT_ARENA_MAX; 22896 22893 22897 22894 struct js *new_js = (struct js *)malloc(sizeof(struct js)); 22898 22895 if (new_js == NULL) { 22899 - ant_arena_free(arena, max_size); 22896 + ant_arena_free(arena, ANT_ARENA_MAX); 22900 22897 free(init_buf); 22901 22898 return NULL; 22902 22899 }
+15
src/cli/cprintf.c
··· 48 48 OP_PAD_BEGIN, 49 49 OP_RPAD_BEGIN, 50 50 OP_PAD_END, 51 + OP_EMIT_SPACES, 51 52 OP_HALT, 52 53 OP_MAX 53 54 } opcode_t; ··· 360 361 361 362 if (tag_prefix(tag, len, "pad=")) { emit_op(p, OP_PAD_BEGIN, (uint32_t)atoi(tag + 4)); return 1; } 362 363 if (tag_prefix(tag, len, "rpad=")) { emit_op(p, OP_RPAD_BEGIN, (uint32_t)atoi(tag + 5)); return 1; } 364 + 365 + if (tag_prefix(tag, len, "space=") && tag[len-1] == '/') { 366 + emit_op(p, OP_EMIT_SPACES, (uint32_t)atoi(tag + 6)); 367 + return 1; 368 + } 363 369 364 370 emit_op(p, OP_STYLE_PUSH, 0); 365 371 ··· 559 565 [OP_PAD_BEGIN] = &&op_pad_begin, 560 566 [OP_RPAD_BEGIN] = &&op_rpad_begin, 561 567 [OP_PAD_END] = &&op_pad_end, 568 + [OP_EMIT_SPACES] = &&op_emit_spaces, 562 569 [OP_HALT] = &&op_halt, 563 570 }; 564 571 ··· 685 692 } else memset(out + pos, ' ', pad_n); 686 693 687 694 pos += pad_n; 695 + NEXT(); 696 + } 697 + 698 + op_emit_spaces: { 699 + size_t n = (size_t)ip->operand; 700 + ENSURE(n); 701 + memset(out + pos, ' ', n); 702 + pos += n; 688 703 NEXT(); 689 704 } 690 705
+37
src/cli/misc.c
··· 1 + #include <stdio.h> 2 + #include <argtable3.h> 3 + 4 + #include "cli/misc.h" 5 + #include "cli/cprintf.h" 6 + 7 + void print_flag(FILE *fp, flag_help_t f) { 8 + const char *s = f.s, *l = f.l, *d = f.d, *g = f.g; 9 + int opt = f.opt; 10 + 11 + char syn[200]; 12 + csprintf(syn, sizeof(syn), 13 + "<cyan>%s</cyan>%s<cyan>%s%s%s%s</cyan>", 14 + s ? (char[]){'-', s[0], '\0'} : (l ? " " : ""), 15 + s && l ? ", " : "", 16 + l ? "--" : "", 17 + l ? l : "", 18 + d && l && opt ? "[=" : 19 + d && l ? "=" : 20 + d && s ? " " : "", 21 + d ? d : ""); 22 + 23 + cfprintf(fp, "<space=2/><pad=32>%s</pad> %s</>\n", syn, g); 24 + } 25 + 26 + void print_flags_help(FILE *fp, void **argtable) { 27 + struct arg_hdr **table = (struct arg_hdr **)argtable; 28 + for (int i = 0; !(table[i]->flag & ARG_TERMINATOR); i++) { 29 + struct arg_hdr *hdr = table[i]; 30 + if (!hdr->glossary) continue; 31 + print_flag(fp, (flag_help_t){ 32 + .s = hdr->shortopts, .l = hdr->longopts, 33 + .d = hdr->datatype, .g = hdr->glossary, 34 + .opt = hdr->flag & ARG_HASOPTVALUE, 35 + }); 36 + } 37 + }
+3 -1
src/cli/pkg.c
··· 1 1 #include <compat.h> // IWYU pragma: keep 2 2 3 3 #include <pkg.h> 4 - #include <cli/pkg.h> 5 4 #include <stdio.h> 6 5 #include <stdlib.h> 7 6 #include <string.h> ··· 11 10 #include <time.h> 12 11 #include <argtable3.h> 13 12 #include <yyjson.h> 13 + 14 + #include "cli/pkg.h" 15 + #include "cli/version.h" 14 16 15 17 #include "utils.h" 16 18 #include "config.h"
+74
src/cli/version.c
··· 1 + #include "utils.h" 2 + #include "config.h" 3 + 4 + #include <string.h> 5 + #include <argtable3.h> 6 + #include <pthread.h> 7 + 8 + static char ant_semver_buf[32]; 9 + static pthread_once_t ant_semver_once = PTHREAD_ONCE_INIT; 10 + 11 + static void ant_semver_init(void) { 12 + const char *s = ANT_VERSION; 13 + int d = 0, i = 0; 14 + while (s[i] && d < 3 && i < 31) { 15 + if (s[i] == '.') d++; 16 + ant_semver_buf[i] = s[i]; i++; 17 + } 18 + ant_semver_buf[i - (d == 3)] = '\0'; 19 + } 20 + 21 + const char *ant_semver(void) { 22 + pthread_once(&ant_semver_once, ant_semver_init); 23 + return ant_semver_buf; 24 + } 25 + 26 + int ant_version(void *argtable[]) { 27 + time_t build_time = (time_t)ANT_BUILD_TIMESTAMP; 28 + time_t now = time(NULL); 29 + long diff = (long)difftime(now, build_time); 30 + 31 + struct { long secs; const char *suffix; } units[] = { 32 + {86400, "d"}, {3600, "h"}, {60, "m"}, {1, "s"} 33 + }; 34 + 35 + const char *suffix = "s"; 36 + long value = diff; 37 + 38 + for (size_t i = 0; i < sizeof(units) / sizeof(units[0]); i++) { 39 + if (diff >= units[i].secs) { 40 + value = diff / units[i].secs; 41 + suffix = units[i].suffix; break; 42 + } 43 + } 44 + 45 + struct tm *tm = gmtime(&build_time); 46 + char date_buf[32]; 47 + strftime(date_buf, sizeof(date_buf), "%Y-%m-%d", tm); 48 + 49 + #define RED "\033[38;5;197m" 50 + #define RESET "\033[0m" 51 + 52 + const char *logo = 53 + RED 54 + " ___ __ __ _____ _ __\n" 55 + " / | ____ / /_ / /___ __ ______ _/ ___/__________(_)___ / /_\n" 56 + " / /| | / __ \\/ __/ __ / / __ `/ | / / __ `/\\__ \\/ ___/ ___/ / __ \\/ __/\n" 57 + " / ___ |/ / / / /_ / /_/ / /_/ /| |/ / /_/ /___/ / /__/ / / / /_/ / /_\n" 58 + "/_/ |_/_/ /_/\\__/ \\____/\\__,_/ |___/\\__,_//____/\\___/_/ /_/ .___/\\__/\n" 59 + " /_/" RESET " by @themackabu\n" 60 + RESET; 61 + 62 + fputs(logo, stdout); 63 + 64 + printf("%s (released %s, %ld%s ago)\n", 65 + ANT_VERSION, 66 + date_buf, 67 + value, suffix 68 + ); 69 + 70 + printf("built for %s\n", ANT_TARGET_TRIPLE); 71 + arg_freetable(argtable, ARGTABLE_COUNT); 72 + 73 + return EXIT_SUCCESS; 74 + }
+25 -26
src/main.c
··· 20 20 #include "internal.h" 21 21 22 22 #include "cli/pkg.h" 23 + #include "cli/misc.h" 24 + #include "cli/version.h" 23 25 #include "cli/cprintf.h" 24 26 25 27 #include "modules/builtin.h" ··· 267 269 argc = filtered_argc; 268 270 argv = filtered_argv; 269 271 270 - struct arg_lit *help = arg_lit0("h", "help", "display this help and exit"); 271 - struct arg_lit *version = arg_lit0("v", "version", "display version information and exit"); 272 - struct arg_lit *version_raw = arg_lit0(NULL, "version-raw", "raw version number for scripts"); 273 272 struct arg_str *eval = arg_str0("e", "eval", "<script>", "evaluate script"); 274 273 struct arg_lit *print = arg_lit0("p", "print", "evaluate script and print result"); 275 - struct arg_int *initial_mem = arg_int0(NULL, "initial-mem", "<size>", "initial memory size in KB (default: 16kb)"); 276 - struct arg_int *max_mem = arg_int0(NULL, "max-mem", "<size>", "maximum memory size in MB (default: 1024mb)"); 274 + 275 + struct arg_file *file = arg_file0(NULL, NULL, NULL, NULL); 277 276 struct arg_file *localstorage_file = arg_file0(NULL, "localstorage-file", "<path>", "file path for localStorage persistence"); 278 - struct arg_file *file = arg_file0(NULL, NULL, "<module.js>", "JavaScript module file to execute"); 277 + 278 + struct arg_lit *version = arg_lit0("v", "version", "display version information and exit"); 279 + struct arg_lit *version_raw = arg_lit0(NULL, "version-raw", "raw version number for scripts"); 280 + 281 + struct arg_lit *help = arg_lit0("h", "help", "display this help and exit"); 279 282 struct arg_end *end = arg_end(20); 280 283 281 284 void *argtable[] = { 282 - help, version, version_raw, 283 - eval, print, initial_mem, max_mem, 284 - localstorage_file, file, end 285 + eval, print, 286 + localstorage_file, file, 287 + version, version_raw, 288 + help, end 285 289 }; 286 290 287 291 int nerrors = arg_parse(argc, argv, argtable); 288 292 289 293 if (help->count > 0) { 290 294 cprintf("<bold_red>Ant</> is a tiny JavaScript runtime and package manager (%s)\n\n", ANT_VERSION); 291 - cprintf("<bold>Usage: ant <cyan>[...options]</cyan> <yellow>[module.js]\n</>"); 292 - cprintf("<bold> ant <command> <cyan>[...args]</>\n\n"); 295 + cprintf("<bold>Usage: ant <yellow>[module.js]</yellow> <cyan>[...flags]\n</>"); 296 + cprintf("<bold><space=7/>ant <command><space=3/><cyan>[...args]</>\n\n"); 297 + printf("If no module file is specified, ant starts in REPL mode.\n\n"); 293 298 print_subcommands(); 294 - printf("If no module file is specified, ant starts in REPL mode.\n\n"); 295 - printf("<bold>Options:</>\n"); 296 - printf(" %-28s %s\n", "--verbose", "enable verbose output"); 297 - printf(" %-28s %s\n", "--no-color", "disable colored output"); 298 - arg_print_glossary(stdout, argtable, " %-28s %s\n"); 299 + cprintf("<bold>Flags:</>\n"); 300 + print_flags_help(stdout, argtable); 301 + print_flag(stdout, (flag_help_t){ .l = "verbose", .g = "enable verbose output" }); 302 + print_flag(stdout, (flag_help_t){ .l = "no-color", .g = "disable colored output" }); 299 303 arg_freetable(argtable, ARGTABLE_COUNT); 300 304 free(filtered_argv); 301 305 return EXIT_SUCCESS; ··· 326 330 ? NULL 327 331 : (file->count > 0 ? file->filename[0] : NULL); 328 332 329 - struct js *js = js_create_dynamic( 330 - initial_mem->count > 0 ? (size_t)initial_mem->ival[0] * 1024 : 0, 331 - max_mem->count > 0 ? (size_t)max_mem->ival[0] * 1024 * 1024 : 0 332 - ); 333 + ant_t *js; 334 + volatile char stack_base; 333 335 334 - if (js == NULL) { 335 - fprintf(stderr, "Error: Failed to allocate JavaScript runtime\n"); 336 - arg_freetable(argtable, ARGTABLE_COUNT); 337 - free(filtered_argv); 336 + if (!(js = js_create_dynamic())) { 337 + cfprintf(stderr, "<bold_red>FATAL</>: Failed to allocate for Ant.\n"); 338 + arg_freetable(argtable, ARGTABLE_COUNT); free(filtered_argv); 338 339 return EXIT_FAILURE; 339 340 } 340 - 341 - volatile char stack_base; 342 341 343 342 js_setstackbase(js, (void *)&stack_base); 344 343 ant_runtime_init(js, argc, argv, localstorage_file);
+1 -73
src/utils.c
··· 1 1 #include "utils.h" 2 - #include "config.h" 3 2 4 - #include <string.h> 5 - #include <stdint.h> 3 + #include <stdio.h> 6 4 #include <stdbool.h> 7 - #include <pthread.h> 8 - #include <argtable3.h> 9 5 #include <sys/stat.h> 10 6 11 - static char ant_semver_buf[32]; 12 - static pthread_once_t ant_semver_once = PTHREAD_ONCE_INIT; 13 - 14 7 static const char *const js_extensions[] = { 15 8 ".js", ".ts", 16 9 ".cjs", ".mjs", 17 10 ".jsx", ".tsx", NULL 18 11 }; 19 - 20 - static void ant_semver_init(void) { 21 - const char *s = ANT_VERSION; 22 - int d = 0, i = 0; 23 - while (s[i] && d < 3 && i < 31) { 24 - if (s[i] == '.') d++; 25 - ant_semver_buf[i] = s[i]; i++; 26 - } 27 - ant_semver_buf[i - (d == 3)] = '\0'; 28 - } 29 - 30 - const char *ant_semver(void) { 31 - pthread_once(&ant_semver_once, ant_semver_init); 32 - return ant_semver_buf; 33 - } 34 12 35 13 int hex_digit(char c) { 36 14 if (c >= '0' && c <= '9') return c - '0'; ··· 105 83 } 106 84 107 85 return NULL; 108 - } 109 - 110 - int ant_version(void *argtable[]) { 111 - time_t build_time = (time_t)ANT_BUILD_TIMESTAMP; 112 - time_t now = time(NULL); 113 - long diff = (long)difftime(now, build_time); 114 - 115 - struct { long secs; const char *suffix; } units[] = { 116 - {86400, "d"}, {3600, "h"}, {60, "m"}, {1, "s"} 117 - }; 118 - 119 - const char *suffix = "s"; 120 - long value = diff; 121 - 122 - for (size_t i = 0; i < sizeof(units) / sizeof(units[0]); i++) { 123 - if (diff >= units[i].secs) { 124 - value = diff / units[i].secs; 125 - suffix = units[i].suffix; break; 126 - } 127 - } 128 - 129 - struct tm *tm = gmtime(&build_time); 130 - char date_buf[32]; 131 - strftime(date_buf, sizeof(date_buf), "%Y-%m-%d", tm); 132 - 133 - #define RED "\033[38;5;197m" 134 - #define RESET "\033[0m" 135 - 136 - const char *logo = 137 - RED 138 - " ___ __ __ _____ _ __\n" 139 - " / | ____ / /_ / /___ __ ______ _/ ___/__________(_)___ / /_\n" 140 - " / /| | / __ \\/ __/ __ / / __ `/ | / / __ `/\\__ \\/ ___/ ___/ / __ \\/ __/\n" 141 - " / ___ |/ / / / /_ / /_/ / /_/ /| |/ / /_/ /___/ / /__/ / / / /_/ / /_\n" 142 - "/_/ |_/_/ /_/\\__/ \\____/\\__,_/ |___/\\__,_//____/\\___/_/ /_/ .___/\\__/\n" 143 - " /_/" RESET " by @themackabu\n" 144 - RESET; 145 - 146 - fputs(logo, stdout); 147 - 148 - printf("%s (released %s, %ld%s ago)\n", 149 - ANT_VERSION, 150 - date_buf, 151 - value, suffix 152 - ); 153 - 154 - printf("built for %s\n", ANT_TARGET_TRIPLE); 155 - arg_freetable(argtable, ARGTABLE_COUNT); 156 - 157 - return EXIT_SUCCESS; 158 86 } 159 87 160 88 void *try_oom(size_t size) {