diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-16 00:19:37 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-16 00:19:37 +0000 |
| commit | 23d18925df02157e9330c3612992e40553bb5da1 (patch) | |
| tree | 89a893944aa7555c59b7700aa608f39680c0a120 /src/main.c | |
| parent | 301d9582884ec7d180791e5c9c6ec649dc01ff68 (diff) | |
Working on reducing function pollution
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 540 |
1 files changed, 232 insertions, 308 deletions
@@ -12,334 +12,258 @@ // Forward decl for LSP int lsp_main(int argc, char **argv); -void print_search_paths() -{ - printf("Search paths:\n"); - printf(" ./\n"); - printf(" ./std/\n"); - printf(" /usr/local/share/zenc\n"); - printf(" /usr/share/zenc\n"); +void print_search_paths() { + printf("Search paths:\n"); + printf(" ./\n"); + printf(" ./std/\n"); + printf(" /usr/local/share/zenc\n"); + printf(" /usr/share/zenc\n"); } -void print_version() -{ - printf("Zen C version %s\n", ZEN_VERSION); +void print_version() { printf("Zen C version %s\n", ZEN_VERSION); } + +void print_usage() { + printf("Usage: zc [command] [options] <file.zc>\n"); + printf("Commands:\n"); + printf(" run Compile and run the program\n"); + printf(" build Compile to executable\n"); + printf(" check Check for errors only\n"); + printf(" repl Start Interactive REPL\n"); + printf(" transpile Transpile to C code only (no compilation)\n"); + printf(" lsp Start Language Server\n"); + printf("Options:\n"); + printf(" --version Print version information"); + printf(" -o <file> Output executable name\n"); + printf(" --emit-c Keep generated C file (out.c)\n"); + printf(" --freestanding Freestanding mode (no stdlib)\n"); + printf(" --cc <compiler> C compiler to use (gcc, clang, tcc, zig)\n"); + printf(" -O<level> Optimization level\n"); + printf(" -g Debug info\n"); + printf(" -v, --verbose Verbose output\n"); + printf(" -q, --quiet Quiet output\n"); + printf(" -c Compile only (produce .o)\n"); } -void print_usage() -{ - printf("Usage: zc [command] [options] <file.zc>\n"); - printf("Commands:\n"); - printf(" run Compile and run the program\n"); - printf(" build Compile to executable\n"); - printf(" check Check for errors only\n"); - printf(" repl Start Interactive REPL\n"); - printf(" transpile Transpile to C code only (no compilation)\n"); - printf(" lsp Start Language Server\n"); - printf("Options:\n"); - printf(" --version Print version information"); - printf(" -o <file> Output executable name\n"); - printf(" --emit-c Keep generated C file (out.c)\n"); - printf(" --freestanding Freestanding mode (no stdlib)\n"); - printf(" --cc <compiler> C compiler to use (gcc, clang, tcc, zig)\n"); - printf(" -O<level> Optimization level\n"); - printf(" -g Debug info\n"); - printf(" -v, --verbose Verbose output\n"); - printf(" -q, --quiet Quiet output\n"); - printf(" -c Compile only (produce .o)\n"); -} - -int main(int argc, char **argv) -{ - // Defaults - memset(&g_config, 0, sizeof(g_config)); - strcpy(g_config.cc, "gcc"); +int main(int argc, char **argv) { + // Defaults + memset(&g_config, 0, sizeof(g_config)); + strcpy(g_config.cc, "gcc"); - if (argc < 2) - { - print_usage(); - return 1; - } + if (argc < 2) { + print_usage(); + return 1; + } - // Parse command - char *command = argv[1]; - int arg_start = 2; + // Parse command + char *command = argv[1]; + int arg_start = 2; - if (strcmp(command, "lsp") == 0) - { - return lsp_main(argc, argv); - } - else if (strcmp(command, "repl") == 0) - { - run_repl(argv[0]); // Pass self path for recursive calls - return 0; - } - else if (strcmp(command, "transpile") == 0) - { - g_config.mode_transpile = 1; - g_config.emit_c = 1; // Transpile implies emitting C - } - else if (strcmp(command, "run") == 0) - { - g_config.mode_run = 1; - } - else if (strcmp(command, "check") == 0) - { - g_config.mode_check = 1; - } - else if (strcmp(command, "build") == 0) - { - // default mode - } - else if (command[0] == '-') - { - // implicit build or run? assume build if starts with flag, but usually - // command first If file provided directly: "zc file.zc" -> build - if (strchr(command, '.')) - { - // treat as filename - g_config.input_file = command; - arg_start = 2; // already consumed - } - else - { - // Flags - arg_start = 1; - } + if (strcmp(command, "lsp") == 0) { + return lsp_main(argc, argv); + } else if (strcmp(command, "repl") == 0) { + run_repl(argv[0]); // Pass self path for recursive calls + return 0; + } else if (strcmp(command, "transpile") == 0) { + g_config.mode_transpile = 1; + g_config.emit_c = 1; // Transpile implies emitting C + } else if (strcmp(command, "run") == 0) { + g_config.mode_run = 1; + } else if (strcmp(command, "check") == 0) { + g_config.mode_check = 1; + } else if (strcmp(command, "build") == 0) { + // default mode + } else if (command[0] == '-') { + // implicit build or run? assume build if starts with flag, but usually + // command first If file provided directly: "zc file.zc" -> build + if (strchr(command, '.')) { + // treat as filename + g_config.input_file = command; + arg_start = 2; // already consumed + } else { + // Flags + arg_start = 1; } - else - { - // Check if file - if (strchr(command, '.')) - { - g_config.input_file = command; - arg_start = 2; - } + } else { + // Check if file + if (strchr(command, '.')) { + g_config.input_file = command; + arg_start = 2; } - - // Parse args - for (int i = arg_start; i < argc; i++) - { - char *arg = argv[i]; - if (strcmp(arg, "--emit-c") == 0) - { - g_config.emit_c = 1; - } - else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-V") == 0) - { - print_version(); - return 0; + } + + // Parse args + for (int i = arg_start; i < argc; i++) { + char *arg = argv[i]; + if (strcmp(arg, "--emit-c") == 0) { + g_config.emit_c = 1; + } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-V") == 0) { + print_version(); + return 0; + } else if (strcmp(arg, "--verbose") == 0 || strcmp(arg, "-v") == 0) { + g_config.verbose = 1; + } else if (strcmp(arg, "--quiet") == 0 || strcmp(arg, "-q") == 0) { + g_config.quiet = 1; + } else if (strcmp(arg, "--freestanding") == 0) { + g_config.is_freestanding = 1; + } else if (strcmp(arg, "--check") == 0) { + g_config.mode_check = 1; + } else if (strcmp(arg, "--cc") == 0) { + if (i + 1 < argc) { + char *cc_arg = argv[++i]; + // Handle "zig" shorthand for "zig cc" + if (strcmp(cc_arg, "zig") == 0) { + strcpy(g_config.cc, "zig cc"); + } else { + strcpy(g_config.cc, cc_arg); } - else if (strcmp(arg, "--verbose") == 0 || strcmp(arg, "-v") == 0) - { - g_config.verbose = 1; - } - else if (strcmp(arg, "--quiet") == 0 || strcmp(arg, "-q") == 0) - { - g_config.quiet = 1; - } - else if (strcmp(arg, "--freestanding") == 0) - { - g_config.is_freestanding = 1; - } - else if (strcmp(arg, "--check") == 0) - { - g_config.mode_check = 1; - } - else if (strcmp(arg, "--cc") == 0) - { - if (i + 1 < argc) - { - char *cc_arg = argv[++i]; - // Handle "zig" shorthand for "zig cc" - if (strcmp(cc_arg, "zig") == 0) - { - strcpy(g_config.cc, "zig cc"); - } - else - { - strcpy(g_config.cc, cc_arg); - } - } - } - else if (strcmp(arg, "-o") == 0) - { - if (i + 1 < argc) - { - g_config.output_file = argv[++i]; - } - } - else if (strncmp(arg, "-O", 2) == 0) - { - // Add to CFLAGS - strcat(g_config.gcc_flags, " "); - strcat(g_config.gcc_flags, arg); - } - else if (strcmp(arg, "-g") == 0) - { - strcat(g_config.gcc_flags, " -g"); - } - else if (arg[0] == '-') - { - // Unknown flag or C flag - strcat(g_config.gcc_flags, " "); - strcat(g_config.gcc_flags, arg); - } - else - { - if (!g_config.input_file) - { - g_config.input_file = arg; - } - else - { - printf("Multiple input files not supported yet.\n"); - return 1; - } - } - } - - if (!g_config.input_file) - { - printf("Error: No input file specified.\n"); - return 1; - } - - g_current_filename = g_config.input_file; - - // Load file - char *src = load_file(g_config.input_file); - if (!src) - { - printf("Error: Could not read file %s\n", g_config.input_file); + } + } else if (strcmp(arg, "-o") == 0) { + if (i + 1 < argc) { + g_config.output_file = argv[++i]; + } + } else if (strncmp(arg, "-O", 2) == 0) { + // Add to CFLAGS + strcat(g_config.gcc_flags, " "); + strcat(g_config.gcc_flags, arg); + } else if (strcmp(arg, "-g") == 0) { + strcat(g_config.gcc_flags, " -g"); + } else if (arg[0] == '-') { + // Unknown flag or C flag + strcat(g_config.gcc_flags, " "); + strcat(g_config.gcc_flags, arg); + } else { + if (!g_config.input_file) { + g_config.input_file = arg; + } else { + printf("Multiple input files not supported yet.\n"); return 1; + } } - - init_builtins(); - zen_init(); - - // Initialize Plugin Manager - zptr_plugin_mgr_init(); - - // Parse context init - ParserContext ctx; - memset(&ctx, 0, sizeof(ctx)); - - // Scan for build directives (e.g. //> link: -lm) - scan_build_directives(&ctx, src); - - Lexer l; - lexer_init(&l, src); - - ctx.hoist_out = tmpfile(); // Temp file for plugin hoisting - if (!ctx.hoist_out) - { - perror("tmpfile for hoisting"); - return 1; - } - g_parser_ctx = &ctx; - - if (!g_config.quiet) - { - printf("[zc] Compiling %s...\n", g_config.input_file); - } - - ASTNode *root = parse_program(&ctx, &l); - if (!root) - { - // Parse failed - return 1; - } - - if (g_config.mode_check) - { - // Just verify - printf("Check passed.\n"); - return 0; - } - - // Codegen to C - FILE *out = fopen("out.c", "w"); - if (!out) - { - perror("fopen out.c"); + } + + if (!g_config.input_file) { + printf("Error: No input file specified.\n"); + return 1; + } + + g_current_filename = g_config.input_file; + + // Load file + char *src = load_file(g_config.input_file); + if (!src) { + printf("Error: Could not read file %s\n", g_config.input_file); + return 1; + } + + init_builtins(); + zen_init(); + + // Initialize Plugin Manager + zptr_plugin_mgr_init(); + + // Parse context init + ParserContext ctx; + memset(&ctx, 0, sizeof(ctx)); + + // Scan for build directives (e.g. //> link: -lm) + scan_build_directives(&ctx, src); + + Lexer l; + lexer_init(&l, src); + + ctx.hoist_out = tmpfile(); // Temp file for plugin hoisting + if (!ctx.hoist_out) { + perror("tmpfile for hoisting"); + return 1; + } + g_parser_ctx = &ctx; + + if (!g_config.quiet) { + printf("[zc] Compiling %s...\n", g_config.input_file); + } + + ASTNode *root = parse_program(&ctx, &l); + if (!root) { + // Parse failed + return 1; + } + + if (g_config.mode_check) { + // Just verify + printf("Check passed.\n"); + return 0; + } + + // Codegen to C + FILE *out = fopen("out.c", "w"); + if (!out) { + perror("fopen out.c"); + return 1; + } + + codegen_node(&ctx, root, out); + fclose(out); + + if (g_config.mode_transpile) { + if (g_config.output_file) { + // If user specified -o, rename out.c to that + if (rename("out.c", g_config.output_file) != 0) { + perror("rename out.c"); return 1; + } + if (!g_config.quiet) { + printf("[zc] Transpiled to %s\n", g_config.output_file); + } + } else { + if (!g_config.quiet) { + printf("[zc] Transpiled to out.c\n"); + } } + // Done, no C compilation + return 0; + } - codegen_node(&ctx, root, out); - fclose(out); - - if (g_config.mode_transpile) - { - if (g_config.output_file) - { - // If user specified -o, rename out.c to that - if (rename("out.c", g_config.output_file) != 0) - { - perror("rename out.c"); - return 1; - } - if (!g_config.quiet) - { - printf("[zc] Transpiled to %s\n", g_config.output_file); - } - } - else - { - if (!g_config.quiet) - { - printf("[zc] Transpiled to out.c\n"); - } - } - // Done, no C compilation - return 0; - } - - // Compile C - char cmd[8192]; - char *outfile = g_config.output_file ? g_config.output_file : "a.out"; - - // TCC-specific adjustments? - // Already handled by user passing --cc tcc - - snprintf(cmd, sizeof(cmd), "%s %s %s %s %s -o %s out.c -lm %s -I./src %s", g_config.cc, - g_config.gcc_flags, g_cflags, g_config.is_freestanding ? "-ffreestanding" : "", "", - outfile, g_parser_ctx->has_async ? "-lpthread" : "", g_link_flags); + // Compile C + char cmd[8192]; + char *outfile = g_config.output_file ? g_config.output_file : "a.out"; - if (g_config.verbose) - { - printf("[CMD] %s\n", cmd); - } + // TCC-specific adjustments? + // Already handled by user passing --cc tcc - int ret = system(cmd); - if (ret != 0) - { - printf("C compilation failed.\n"); - if (!g_config.emit_c) - { - remove("out.c"); - } - return 1; - } + snprintf(cmd, sizeof(cmd), "%s %s %s %s %s -o %s out.c -lm %s -I./src %s", + g_config.cc, g_config.gcc_flags, g_cflags, + g_config.is_freestanding ? "-ffreestanding" : "", "", outfile, + g_parser_ctx->has_async ? "-lpthread" : "", g_link_flags); - if (!g_config.emit_c) - { - // remove("out.c"); // Keep it for debugging for now or follow flag - remove("out.c"); - } + if (g_config.verbose) { + printf("[CMD] %s\n", cmd); + } - if (g_config.mode_run) - { - char run_cmd[2048]; - sprintf(run_cmd, "./%s", outfile); - ret = system(run_cmd); - remove(outfile); - zptr_plugin_mgr_cleanup(); - zen_trigger_global(); - return ret; + int ret = system(cmd); + if (ret != 0) { + printf("C compilation failed.\n"); + if (!g_config.emit_c) { + remove("out.c"); } - + return 1; + } + + if (!g_config.emit_c) { + // remove("out.c"); // Keep it for debugging for now or follow flag + remove("out.c"); + } + + if (g_config.mode_run) { + char run_cmd[2048]; + sprintf(run_cmd, "./%s", outfile); + ret = system(run_cmd); + remove(outfile); zptr_plugin_mgr_cleanup(); zen_trigger_global(); - return 0; + return ret; + } + + zptr_plugin_mgr_cleanup(); + zen_trigger_global(); + return 0; } |
