commit d244528dfb52ffea32767df307f57d86241fd3ec Author: xSlendiX Date: Mon Dec 12 20:36:48 2022 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be7f4c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +tbuild + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f033c8c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tomlc99"] + path = tomlc99 + url = https://github.com/cktan/tomlc99 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..2e61574 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,27 @@ +# DON'T BE A DICK PUBLIC LICENSE + +> Version 1.1, December 2016 + +> Copyright (C) 2022 Slendi + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document. + +> DON'T BE A DICK PUBLIC LICENSE +> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +1. Do whatever you like with the original work, just don't be a dick. + + Being a dick includes - but is not limited to - the following instances: + + 1a. Outright copyright infringement - Don't just copy this and change the name. + 1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick. + 1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick. + +2. If you become rich through modifications, related works/services, or supporting the original work, +share the love. Only a dick would make loads off this work and not buy the original work's +creator(s) a pint. + +3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes +you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back. + diff --git a/RedSeaGen b/RedSeaGen new file mode 100755 index 0000000..b6e18a8 Binary files /dev/null and b/RedSeaGen differ diff --git a/RedSeaGen.exe b/RedSeaGen.exe new file mode 100644 index 0000000..10979f2 Binary files /dev/null and b/RedSeaGen.exe differ diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..2620a2f --- /dev/null +++ b/build.sh @@ -0,0 +1,4 @@ +cd tomlc99 +make +cd .. +cc tomlc99/toml.o main.c -o tbuild diff --git a/main.c b/main.c new file mode 100644 index 0000000..6191900 --- /dev/null +++ b/main.c @@ -0,0 +1,741 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tomlc99/toml.h" + +// FIXME: This is hardcoded, fix it. +char *python_interpreter_path = "/usr/local/bin/python3"; + +bool can_run_command(const char *cmd) { + if(strchr(cmd, '/')) { + return access(cmd, X_OK)==0; + } + const char *path = getenv("PATH"); + if(!path) return false; + char *buf = malloc(strlen(path)+strlen(cmd)+3); + if(!buf) return false; + for(; *path; ++path) { + char *p = buf; + for(; *path && *path!=':'; ++path,++p) + *p = *path; + if(p==buf) *p++='.'; + if(p[-1]!='/') *p++='/'; + strcpy(p, cmd); + if(access(buf, X_OK)==0) { + free(buf); + return true; + } + if(!*path) break; + } + free(buf); + return false; +} + +#define BUFFER_SIZE 1024 +bool copy_directory(const char *src_path, const char *dest_path) { + DIR *src_dir = opendir(src_path); + if (src_dir == NULL) { + // Failed to open source directory + return false; + } + + // Create destination directory if it doesn't exist + mkdir(dest_path, 0755); + + // Copy files and directories from source to destination + struct dirent *entry; + while ((entry = readdir(src_dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + // Skip "." and ".." directories + continue; + } + + char src_file_path[BUFFER_SIZE]; + snprintf(src_file_path, BUFFER_SIZE, "%s/%s", src_path, entry->d_name); + + char dest_file_path[BUFFER_SIZE]; + snprintf(dest_file_path, BUFFER_SIZE, "%s/%s", dest_path, entry->d_name); + + struct stat src_file_stat; + stat(src_file_path, &src_file_stat); + + if (S_ISDIR(src_file_stat.st_mode)) { + // Recursively copy directories + if (!copy_directory(src_file_path, dest_file_path)) { + return false; + } + } else if (S_ISREG(src_file_stat.st_mode)) { + // Copy regular files + FILE *src_file = fopen(src_file_path, "rb"); + if (src_file == NULL) { + // Failed to open source file + return false; + } + + FILE *dest_file = fopen(dest_file_path, "wb"); + if (dest_file == NULL) { + // Failed to open destination file + fclose(src_file); + return false; + } + + // Copy file contents + char buffer[BUFFER_SIZE]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, src_file)) > 0) { + fwrite(buffer, 1, bytes_read, dest_file); + } + + fclose(src_file); + fclose(dest_file); + } else { + // Skip other file types + continue; + } + } + + closedir(src_dir); + return true; +} + +void clear_directory(char const *path) { + DIR *dir = opendir(path); + if (dir == NULL) { + // Unable to open the directory + perror("opendir"); + return; + } + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + // Skip "." and ".." entries + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // Get the full path of the entry + char entry_path[1024]; + snprintf(entry_path, sizeof(entry_path), "%s/%s", path, entry->d_name); + + // Check if the entry is a directory + struct stat entry_stat; + if (stat(entry_path, &entry_stat) != 0) { + perror("stat"); + continue; + } + if (S_ISDIR(entry_stat.st_mode)) { + // Remove the directory recursively + clear_directory(entry_path); + if (rmdir(entry_path) != 0) { + perror("rmdir"); + } + } else { + // Remove the entry + if (unlink(entry_path) != 0) { + perror("unlink"); + } + } + } + + closedir(dir); +} + +#define MANIFEST_FNAME "tos_project.toml" + +char* find_project_root(void) +{ + char* result = NULL; + + // Get the current working directory + char cwd[1024]; + if (getcwd(cwd, sizeof(cwd)) == NULL) { + return NULL; + } + + // Check if the current working directory contains the file "tos_project.toml" + size_t file_path_len = strlen(cwd) + strlen("/tos_project.toml") + 1; + char file_path[file_path_len]; + snprintf(file_path, file_path_len, "%s/tos_project.toml", cwd); + + if (access(file_path, F_OK) == 0) { + // The file exists, so we can return the path to the directory containing it + result = malloc(strlen(cwd) + 1); + strncpy(result, cwd, strlen(cwd) + 1); + return result; + } + + // The file does not exist in the current working directory, so we need to search backwards + size_t len = strlen(cwd); + for (int i = len - 1; i >= 0; i--) { + if (cwd[i] == '/') { + // We found a directory separator, so we can check if the parent directory contains the file + cwd[i] = '\0'; + snprintf(file_path, file_path_len, "%s/tos_project.toml", cwd); + + if (access(file_path, F_OK) == 0) { + // The file exists, so we can return the path to the parent directory containing it + result = malloc(strlen(cwd) + 1); + strncpy(result, cwd, strlen(cwd) + 1); + break; + } + } + } + + return result; +} + +#define SAMPLE_MANIFEST "[General]\n" \ + "Name=\"%s\"\n" \ + "Author=\"%s\"\n" \ + "Version=\"0.1\"\n" \ + "\n" \ + "[Dependencies]\n" + +typedef struct project_manifest { + char *name, *author, *version; + // FIXME: Add dependencies. +} project_manifest; + +void free_manifest(project_manifest *manifest) { + free(manifest->name); + free(manifest->author); + free(manifest->version); +} + +project_manifest* load_manifest(char const *path) { + FILE* fp; + char errbuf[200]; + + fp = fopen(path, "r"); + if (!fp) { + fputs("Error: Cannot load manifest file: Cannot open file.\n", stderr); + return NULL; + } + + project_manifest *new = calloc(1, sizeof(project_manifest)); + + toml_table_t *conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); + fclose(fp); + if (!conf) { + fprintf(stderr, "Error: Cannot load manifest file: Cannot parse file.\n", errbuf); + return NULL; + } + + toml_table_t *general = toml_table_in(conf, "General"); + if (!general) { + fprintf(stderr, "Error: Cannot load manifest file: Cannot find [General] table.\n", errbuf); + return NULL; + } + + toml_datum_t name = toml_string_in(general, "Name"); + if (!name.ok) { + fprintf(stderr, "Error: Cannot load manifest file: Cannot find Name field.\n", errbuf); + return NULL; + } + + toml_datum_t author = toml_string_in(general, "Author"); + if (!author.ok) { + fprintf(stderr, "Error: Cannot load manifest file: Cannot find Author field.\n", errbuf); + return NULL; + } + + toml_datum_t version = toml_string_in(general, "Version"); + if (!version.ok) { + fprintf(stderr, "Error: Cannot load manifest file: Cannot find Version field.\n", errbuf); + return NULL; + } + + new->name = name.u.s; + new->author = author.u.s; + new->version = version.u.s; + + // FIXME: Add dependencies. + + toml_free(conf); + + printf("%s, %s, %s\n", new->name, new->author, new->version); + + return new; +} + +char buffer_text_format[2048]; +char *text_format(char const *format, ...) { + va_list args; + va_start(args, format); + vsprintf(buffer_text_format, format, args); + va_end(args); + return buffer_text_format; +} + +char *get_username(void) { +#if defined(_WIN32) + // FIXME: This leaks memory. + + TCHAR infoBuf[105]; + DWORD bufCharCount = 105; + if( !GetUserName( infoBuf, &bufCharCount ) ) + printError( TEXT("GetUserName") ); + + char *c_szText[105]; + wcstombs(c_szText, infoBuf, wcslen(infoBuf) + 1); + return c_szText; +#else + uid_t uid = geteuid(); + struct passwd *pw = getpwuid(uid); + if (pw == NULL) + return NULL; + return pw->pw_name; +#endif +} + +bool create_manifest_file(char const *project_path) { + char *name; + char cwd[4096]; + if (strlen(project_path) == 1 && project_path[0] == '.') { + if (getcwd(cwd, sizeof(cwd)) == NULL) { + fputs("Error: Cannot create manifest: Cannot get current working directory.\n", stderr); + return false; + } else { + name = malloc((strlen(cwd)+1)*sizeof(char)); + strcpy(name, cwd); + } + } else { + name = basename((char *)project_path); + } + char *uname = get_username(); + + FILE *fd = fopen(text_format("%s/" MANIFEST_FNAME, project_path), "w+"); + if (fd == NULL) { + fputs("Error: Cannot create manifest: Cannot open manifest file.\n", stderr); + return false; + } + + fprintf(fd, SAMPLE_MANIFEST, name, uname); + + fclose(fd); + + return true; +} + +void print_help(char **argv) { + printf("Usage: %s [command]\n", argv[0]); + fputs("\nCommands:\n", stderr); + fputs(" * init|i [path=.] - Setup a new project.\n", stderr); + fputs(" * build|. - Build project in current working directory.\n", stderr); + fputs(" * clean - Clean output code in current working directory.\n", stderr); + fputs("\nTo see manifest file usage, check out man tbuild(1)\n", stderr); +} + +bool file_exists(char const *path) { + struct stat st = {0}; + return (stat(path, &st) != -1); +} + +// FIXME: Implement for Windows. +bool makedir(char const *path) { + struct stat st = {0}; + + if (stat(path, &st) == -1) { + mkdir(path, 0700); + } else { + fprintf(stderr, "Warning: File already exists. Continuing anyway."); + return false; + } + return true; +} + +bool makedir_parenting(char const *path) { + char *p; + struct stat st = {0}; + + for(p=strchr(path+1, '/'); p; p=strchr(p+1, '/')){ + *p = 0; + if(stat(path, &st) == -1 && makedir(path) == true) + return true; + *p = '/'; + } + + if(stat(path, &st) == -1) + makedir(path); + + return true; +} + +void replace_in_file(char const *file, char const *text_to_find, char const *text_to_replace) { + FILE *input = fopen(file, "r"); + FILE *output = fopen("temp.txt", "w"); + + char buffer[512]; + while (fgets(buffer, sizeof(buffer), input) != NULL) { + char *pos = strstr(buffer, text_to_find); + + if (pos == NULL) { + fputs(buffer, output); + continue; + } + + char *temp = calloc(strlen(buffer) - strlen(text_to_find) + strlen(text_to_replace) + 1, 1); + + memcpy(temp, buffer, pos - buffer); + memcpy(temp + (pos - buffer), text_to_replace, strlen(text_to_replace)); + memcpy(temp + (pos - buffer) + strlen(text_to_replace), + pos + strlen(text_to_find), + 1 + strlen(buffer) - ((pos - buffer) + strlen(text_to_find))); + + fputs(temp, output); + free(temp); + } + fclose(output); + fclose(input); + + rename("temp.txt", file); +} + +void convert_to_zealos(char const *path) { + DIR *dir; + struct dirent *entry; + struct stat s; + + if (!(dir = opendir(path))) + return; + + if (!(entry = readdir(dir))) + return; + + do { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + char fpath[1024]; + int len = snprintf(fpath, sizeof(fpath)-1, "%s/%s", path, entry->d_name); + fpath[len] = 0; + + if (lstat(fpath, &s) == 0 && S_ISDIR(s.st_mode)) { // Is directory? + convert_to_zealos(fpath); + continue; + } + + if (fpath[len-2] != 'H' || fpath[len-3] != '.') + continue; + + printf("Converting %s\n", entry->d_name); + + replace_in_file(fpath, "MemCpy", "MemCopy"); + replace_in_file(fpath, "MemCpy", "MemCopy"); + replace_in_file(fpath, "MemCmp", "MemCompare"); + replace_in_file(fpath, "StrCpy", "StrCopy"); + replace_in_file(fpath, "StrCmp", "StrCompare"); + replace_in_file(fpath, "StrICmp", "StrICompare"); + replace_in_file(fpath, "StrNCmp", "StrNCompare"); + replace_in_file(fpath, "StrNICmp", "StrNICompare"); + replace_in_file(fpath, "BEqu", "BEqual"); + replace_in_file(fpath, "LBEqu", "LBEqual"); + replace_in_file(fpath, "ms", "mouse"); + replace_in_file(fpath, "Snd", "Sound"); + replace_in_file(fpath, "SndTaskEndCB", "SoundTaskEndCB"); + replace_in_file(fpath, "mp_cnt", "mp_count"); + replace_in_file(fpath, "QueIns", "QueueInsert"); + replace_in_file(fpath, "QueInit", "QueueInit"); + replace_in_file(fpath, "QueRem", "QueueRemove"); + replace_in_file(fpath, "QueDel", "QueueDel"); + replace_in_file(fpath, "MsSet", "MouseSet"); + replace_in_file(fpath, "UnusedStk", "UnusedStack"); + replace_in_file(fpath, "word_lst", "word_list"); + replace_in_file(fpath, "FileExtRem", "FileExtRemove"); + replace_in_file(fpath, "cnts", "counts"); + replace_in_file(fpath, "PostMsg", "MessagePost"); + replace_in_file(fpath, "PostMsgWait", "MessagePostWait"); + replace_in_file(fpath, "QSort", "QuickSort"); + replace_in_file(fpath, "QSortI64", "QuickSortI64"); + replace_in_file(fpath, "ScanMsg", "MessageScan"); + replace_in_file(fpath, "cnts", "counts"); + replace_in_file(fpath, "Dsk", "Disk"); + replace_in_file(fpath, "collision_cnt", "collision_count"); + replace_in_file(fpath, "Drv", "Drive"); + replace_in_file(fpath, "DrvRep", "DriveRep"); + replace_in_file(fpath, "Drv2Let", "Drive2Letter"); + replace_in_file(fpath, "LstSub", "ListSub"); + replace_in_file(fpath, "LstMatch", "ListMatch"); + replace_in_file(fpath, "DefineLstLoad", "DefineListLoad"); + replace_in_file(fpath, "ExtDft", "ExtDefault"); + replace_in_file(fpath, "ExtChg", "ExtChange"); + replace_in_file(fpath, "RegDft", "RegDefault"); + replace_in_file(fpath, "\"HC\"", "\"CC\""); + replace_in_file(fpath, "CDrv", "CDrive"); + replace_in_file(fpath, "CDbgInfo", "CDebugInfo"); + replace_in_file(fpath, "dbg_info", "debug_info"); + replace_in_file(fpath, "StrFirstRem", "StrFirstRemove"); + replace_in_file(fpath, "StrLastRem", "StrLastRemove"); + replace_in_file(fpath, "TempleOS/Apps", "/Apps"); + replace_in_file(fpath, "adam_task", "sys_task"); + replace_in_file(fpath, "JobQue", "JobQueue"); + replace_in_file(fpath, "MSG_", "MESSAGE_"); + replace_in_file(fpath, ".HC", ".ZC"); + replace_in_file(fpath, "Msg", "Message"); + replace_in_file(fpath, "MusicSettingsRst", "MusicSettingsReset"); + replace_in_file(fpath, "hndlr", "handler"); + replace_in_file(fpath, "FifoU8Rem", "FifoU8Remove"); + replace_in_file(fpath, "GodBitsIns", "GodBitsInsert"); + replace_in_file(fpath, "fp_draw_ms", "fp_draw_mouse"); + replace_in_file(fpath, "DrawStdMs", "DrawStdMouse"); + replace_in_file(fpath, "WIG_TASK_DFT", "WIG_TASK_DEFAULT"); + replace_in_file(fpath, "DirMk", "DirMake"); + replace_in_file(fpath, "GetI64", "I64Get"); + replace_in_file(fpath, "GetF64", "F64Get"); + replace_in_file(fpath, "GetStr", "StrGet"); + replace_in_file(fpath, "GetChar", "CharGet"); + + // Added from Anfintony's Insecticide November 24 2022 + replace_in_file(fpath, "GetMsg", "MessageGet"); + replace_in_file(fpath, "DRV_SIGNATURE_VAL", "DRIVE_SIGNATURE_VAL"); + replace_in_file(fpath, "dv_signature", "drive_signature"); + replace_in_file(fpath, "DrvTextAttrGet", "DriveTextAttrGet"); + replace_in_file(fpath, "DrvIsWritable", "DriveIsWritable"); + replace_in_file(fpath, "gr_palette_std", "gr32_palette_std"); + replace_in_file(fpath, "GetKey", "KeyGet"); + replace_in_file(fpath, "STD_DISTRO_DVD_CFG", "STD_DISTRO_DVD_CONFIG"); + replace_in_file(fpath, "CBGR48", "CBGR24"); + replace_in_file(fpath, "CFreeLst", "CFreeList"); + replace_in_file(fpath, "DrvLock", "DriveLock"); + replace_in_file(fpath, "DrvUnlock", "DriveUnlock"); + replace_in_file(fpath, "DrvChk", "DriveCheck"); + replace_in_file(fpath, "AMAlloc", "SysMAlloc"); + replace_in_file(fpath, "Let2Drv", "Letter2Drive"); + replace_in_file(fpath, "Let2Let", "Letter2Letter"); + replace_in_file(fpath, "Let2BlkDev", "Letter2BlkDev"); + replace_in_file(fpath, "first_drv_let", "first_drive_let"); + + // Added by Doodguy and Anfintony November 25 2022 + replace_in_file(fpath, "ScanKey", "KeyScan"); + replace_in_file(fpath, "ScanChar", "CharScan"); + replace_in_file(fpath, "fp_final_scrn_update", "fp_final_screen_update"); + + entry->d_name[strlen(entry->d_name)-2] = 'Z'; + rename(fpath, text_format("%s/%s", path, entry->d_name)); + + } while ((entry = readdir(dir))); + closedir(dir); +} + +bool run_scripts(char const *path) { + DIR *dir; + struct dirent *entry; + struct stat s; + + if (!(dir = opendir(path))) + return false; + + if (!(entry = readdir(dir))) + return false; + + do { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + char fpath[1024]; + int len = snprintf(fpath, sizeof(fpath)-1, "%s/%s", path, entry->d_name); + fpath[len] = 0; + + if (lstat(fpath, &s) == 0 && S_ISDIR(s.st_mode)) { // Is directory? + run_scripts(fpath); + continue; + } + + if (fpath[len-3] != 'p' || fpath[len-2] != 'y' || fpath[len-3] != '.') + continue; + + printf("Running %s\n", entry->d_name); + char *argv[] = { + fpath, + NULL + }; + + execve(python_interpreter_path, argv, NULL); + + } while ((entry = readdir(dir))); + closedir(dir); + + return true; +} + +int main(int argc, char **argv) { + if (argc < 2) { + puts("No arguments provided.\n"); + print_help(argv); + return 0; + } + + char path_save[PATH_MAX]; + char abs_exe_path[PATH_MAX]; + char *p; + + if(!(p = strrchr(argv[0], '/'))) + getcwd(abs_exe_path, sizeof(abs_exe_path)); + else { + *p = '\0'; + getcwd(path_save, sizeof(path_save)); + chdir(argv[0]); + getcwd(abs_exe_path, sizeof(abs_exe_path)); + chdir(path_save); + } + + char *project_path = "."; + char cmd = tolower(argv[1][0]); + if (cmd == 'i') { + if (argc > 2) { + project_path = calloc(1, (strlen(argv[2])+1)*sizeof(char)); + strcpy(project_path, argv[2]); + } + + fprintf(stderr, "Initializing project in `%s`.\n", project_path); + + bool ret = true; + if (!(strlen(project_path) == 1 && project_path[0] == '.')) + ret = makedir_parenting(project_path); + + if (!ret) { + fputs("Error: Cannot create project: Cannot create directories.\n", stderr); + return -1; + } + + // Check if manifest file exists. + if (file_exists(text_format("%s/" MANIFEST_FNAME, project_path))) { + fputs("Error: Cannot create project: Project already exists!\n", stderr); + return -1; + } + + create_manifest_file(project_path); + + if (can_run_command("git")) + system(text_format("git init %s", project_path)); + + // Free only if alloc'ed, "." doesn't count since it is embedded in the program itself. + // Trying to free it if it's "." would cause a crash cause of this. + if (argc > 2) + free(project_path); + } else if (cmd == 'b' || cmd == '.') { + struct { + bool zeal_build; + } options = { 0 }; + + for (int i = 2; i < argc; i++) { + if (argv[i][0] != '-') + continue; + + if (argv[i][1] == '-') { + if (strcmp(argv[i], "--zeal")) + options.zeal_build = true; + + continue; + } + + for (int j = 1; j < strlen(argv[i]); j++) { + switch (argv[i][j]) { + case 'z': + case 'Z': + options.zeal_build = true; + break; + } + } + } + + // Find project root. + char cwd[4096]; + if (getcwd(cwd, sizeof(cwd)) == NULL) { + fputs("Error: Cannot build project: Cannot get current working directory.\n", stderr); + return 1; + } + + project_path = find_project_root(); + if (project_path == NULL) { + fputs("Error: Cannot build project: Not in a project directory.\n", stderr); + return 1; + } + + project_manifest* manifest = load_manifest(text_format("%s/" MANIFEST_FNAME, project_path)); + puts(buffer_text_format); + + // TODO: Validate dependencies. + + // Create build directory + text_format("%s/build", project_path); + char *build_dir = malloc((strlen(buffer_text_format)+1)*sizeof(char)); + strcpy(build_dir, buffer_text_format); + text_format("%s/src", project_path); + char *src_dir = malloc((strlen(buffer_text_format)+1)*sizeof(char)); + strcpy(src_dir, buffer_text_format); + if (!file_exists(build_dir)) { + bool status = makedir(build_dir); + if (!status) { + fputs("Error: Cannot build project: Cannot create build directory.\n", stderr); + free_manifest(manifest); + return 1; + } + } + + // Clear and populate. + puts("Populating build directory..."); + clear_directory(build_dir); + copy_directory(src_dir, build_dir); + if (file_exists(text_format("%s/libs", project_path))) + copy_directory(src_dir, buffer_text_format); + + // Run scripts (if any) + puts("Running scripts..."); + // FIXME: This is incredibly hacky. + text_format("%s/scripts", project_path); + char *scripts_dir = malloc((strlen(buffer_text_format)+1)*sizeof(char)); + strcpy(scripts_dir, buffer_text_format); + if (file_exists(scripts_dir)) { + if (!run_scripts(scripts_dir)) { + fputs("Failed running script!\b", stderr); + return -1; + } + } + + if (options.zeal_build) { + puts("Converting to ZealOS..."); + convert_to_zealos(build_dir); + } + + // TODO: Obfuscate code if enabled. + + text_format("%s/output", project_path); + char *out_dir = malloc((strlen(buffer_text_format)+1)*sizeof(char)); + strcpy(out_dir, buffer_text_format); + if (!file_exists(out_dir)) { + bool status = makedir(out_dir); + if (!status) { + fputs("Error: Cannot build project: Cannot create output directory.\n", stderr); + free_manifest(manifest); + return 1; + } + } + + if (options.zeal_build) + text_format("%s/output/%s-%s.zeal.ISO.C", project_path, manifest->name, manifest->version); + else + text_format("%s/output/%s-%s.ISO.C", project_path, manifest->name, manifest->version); + char *iso_c = malloc((strlen(buffer_text_format)+1)*sizeof(char)); + strcpy(iso_c, buffer_text_format); +#if defined(_WIN32) + system(text_format("%s/RedSeaGen.exe '%s' '%s'", abs_exe_path, build_dir, iso_c)); +#else + system(text_format("%s/RedSeaGen '%s' '%s'", abs_exe_path, build_dir, iso_c)); +#endif + + free(build_dir); + free_manifest(manifest); + } +} + diff --git a/tomlc99 b/tomlc99 new file mode 160000 index 0000000..8949028 --- /dev/null +++ b/tomlc99 @@ -0,0 +1 @@ +Subproject commit 894902820a3ea2f1ec470cd7fe338bde54045cf5