This commit is contained in:
2025-08-10 18:04:30 -04:00
parent f33dedeeff
commit e441dec020
10 changed files with 126 additions and 142 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,3 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,21 +16,14 @@
#define DEFAULT_GIT_INIT true
#define DEFAULT_CLANG_FORMAT true
/* This is to keep track of how deep we are within
the project tree. This is used in reset_path_ () */
int depth;
/* This macro exist purely because I like how it looks. This should be called
in every function that creates file to ensure they are being created in
right place. */
#define reset_path reset_path_()
int reset_path_()
static int reset_path(void)
{
while (depth != 0) {
while (depth > 0) {
if (chdir("..") != 0)
return errno;
else
--depth;
depth--;
}
return 0;
}
@@ -40,11 +32,11 @@ int program_exists(const char *prog)
{
char *path = getenv("PATH");
if (!path)
return 1;
return -1;
char *copy = strdup(path);
if (!copy)
return 1;
return -1;
char *dir = strtok(copy, ":");
while (dir) {
@@ -61,26 +53,30 @@ int program_exists(const char *prog)
return 1;
}
// TODO(vx-clutch): sanitize the alpha-numeric range
// clang-format off
int sanitize(manifest_t *m)
int sanitize(manifest_t *m)
{
if (!m->project) m->project = DEFAULT_PROJECT_NAME;
if (!m->name) m->name = DEFAULT_USER_NAME;
if (!(m->licence == UNLICENCE)) m->licence = DEFAULT_LICENCE;
m->flag.git = m->flag.git ? true : DEFAULT_GIT_INIT;
m->flag.clang_format = m->flag.clang_format ? true : DEFAULT_CLANG_FORMAT;
m->flag.GNU = m->flag.GNU ? true : DEFAULT_GNU;
if (!m->project)
m->project = DEFAULT_PROJECT_NAME;
if (!m->name) {
struct passwd *pw = getpwuid(getuid());
m->name = (pw && pw->pw_name) ? pw->pw_name : DEFAULT_USER_NAME;
}
if (m->licence == UNLICENCE)
m->licence = DEFAULT_LICENCE;
if (!m->flag.git)
m->flag.git = DEFAULT_GIT_INIT;
if (!m->flag.clang_format)
m->flag.clang_format = DEFAULT_CLANG_FORMAT;
if (!m->flag.GNU)
m->flag.GNU = DEFAULT_GNU;
return 0;
}
// clang-format on
int create_libraries(manifest_t manifest)
{
@@ -90,29 +86,31 @@ int create_libraries(manifest_t manifest)
return status;
}
/* reset_path; */
while (depth != 0) {
if (chdir("..") != 0)
return errno;
else
--depth;
}
int ret = reset_path();
if (ret != 0)
return ret;
for (int i = 0; i < LIB_COUNT_; ++i) {
if (HAS_LIBRARY(manifest.libraries, LIB_RAYLIB)) {
REMOVE_LIBRARY(manifest.libraries, LIB_RAYLIB);
status = system(
"git submodule add -q https://github.com/raysan5/raylib");
} else if (HAS_LIBRARY(manifest.libraries, LIB_NCURSES)) {
status = system("git submodule add -q https://github.com/raysan5/raylib");
if (status != 0)
return status;
}
if (HAS_LIBRARY(manifest.libraries, LIB_NCURSES)) {
REMOVE_LIBRARY(manifest.libraries, LIB_NCURSES);
status = system(
"git submodule add -q https://github.com/mirror/ncurses");
} else if (HAS_LIBRARY(manifest.libraries, LIB_CURL)) {
status = system("git submodule add -q https://github.com/mirror/ncurses");
if (status != 0)
return status;
}
if (HAS_LIBRARY(manifest.libraries, LIB_CURL)) {
REMOVE_LIBRARY(manifest.libraries, LIB_CURL);
status = system(
"git submodule add -q https://github.com/raysan5/raylib");
}
status = system("git submodule add -q https://github.com/curl/curl");
if (status != 0)
return status;
}
return status;
}
@@ -121,76 +119,55 @@ int create_licence(manifest_t manifest, char **licence_line_buffer)
if (manifest.licence == UNLICENCE)
return 0;
/* reset_path; */
while (depth != 0) {
if (chdir("..") != 0)
return errno;
else
--depth;
}
int ret = reset_path();
if (ret != 0)
return ret;
assert(licence_line_buffer != NULL);
if (!licence_line_buffer)
return EINVAL;
switch (manifest.licence) {
case BSD3:
*licence_line_buffer = "Bsd";
printfn("Not impl");
assert(1 == 2);
break;
fprintf(stderr, "create_licence: BSD3 license generation not implemented\n");
return ENOSYS;
case GPLv3:
printfn("Not impl");
assert(1 == 2);
break;
fprintf(stderr, "create_licence: GPLv3 license generation not implemented\n");
return ENOSYS;
case MIT:
printfn("Not impl");
assert(1 == 2);
break;
case UNLICENCE:
fprintf(stderr, "create_licence: MIT license generation not implemented\n");
return ENOSYS;
default:
printfn("bad logic in create_licence ()");
return 1;
fprintf(stderr, "create_licence: unknown license type\n");
return EINVAL;
}
return 0;
}
int maybe_create_clang_format(manifest_t manifest)
{
int status;
int ret = reset_path();
if (ret != 0)
return ret;
if (!manifest.flag.clang_format)
return 0;
/* reset_path; */
while (depth != 0) {
if (chdir("..") != 0)
return errno;
else
--depth;
}
status = create_file_with_content(".clang-format",
clang_format_template);
int status = create_file_with_content(".clang-format", clang_format_template);
return status;
}
int setup_git(manifest_t manifest)
{
if (!manifest.flag.git) {
if (!manifest.flag.git)
return 0;
}
/* reset_path; */
while (depth != 0) {
if (chdir("..") != 0)
return errno;
else
--depth;
}
int ret = reset_path();
if (ret != 0)
return ret;
int status = system("git init --quiet");
if (status) {
printfn("failed on git initialize: %s", strerror(status));
}
if (status != 0)
fprintf(stderr, "setup_git: failed to initialize git: %s\n", strerror(status));
return status;
}
@@ -199,66 +176,74 @@ int create_makefile(manifest_t manifest)
{
char *makefile_name = strdup(manifest.project);
if (!makefile_name) {
printfn("fatal: out of memory");
return 1;
fprintf(stderr, "create_makefile: fatal: out of memory\n");
return ENOMEM;
}
for (char *p = makefile_name; *p; ++p)
if (*p >= 'a' && *p <= 'z')
*p -= 32;
*p -= 'a' - 'A';
reset_path;
int ret = reset_path();
if (ret != 0) {
free(makefile_name);
return ret;
}
create_file_with_content("Makefile", makefile_template, makefile_name,
int status = create_file_with_content("Makefile", makefile_template, makefile_name,
makefile_name, makefile_name, makefile_name,
makefile_name, makefile_name, manifest.project,
makefile_name, makefile_name);
free(makefile_name);
return 0;
return status;
}
int create_configure(manifest_t manifest)
{
int status = 0;
reset_path;
int ret = reset_path();
if (ret != 0)
return ret;
char *cc;
const char *cc;
if (manifest.flag.use_cpp) {
cc = "trycc g++\ntrycc CC\ntrycc clang++\n";
} else {
cc = "trycc gcc\ntrycc cc\ntrycc clang\n";
}
create_file_with_content("configure", configure_template, cc);
int status = create_file_with_content("configure", configure_template, cc);
if (status != 0)
return status;
status = system("chmod +x configure");
if (status)
printfn("error: %s", strerror(status));
if (status != 0)
fprintf(stderr, "create_configure: chmod failed: %s\n", strerror(status));
return status;
}
int generate_source_code(manifest_t manifest, char *licence_line)
{
int status, year = 0;
int status = 0;
time_t t = time(NULL);
struct tm tm = *localtime(&t);
year = tm.tm_year + 1900;
int year = tm.tm_year + 1900;
// XXX(vx-clutch): this segfaults, but why?
// Uncomment or fix when create_file_with_content supports this
// status = create_file_with_content("config.h", manifest.project, licence_line, year);
if (status) {
printfn("failed to create config.h: %s", strerror(status));
return status;
}
// if (status != 0) {
// fprintf(stderr, "generate_source_code: failed to create config.h: %s\n", strerror(status));
// return status;
// }
status = create_and_enter_directory(manifest.project);
++depth;
if (status) {
printfn("failed to create or enter directory: %s",
strerror(status));
if (status != 0) {
fprintf(stderr, "generate_source_code: failed to create or enter directory: %s\n", strerror(status));
return status;
}
depth++;
if (manifest.flag.GNU) {
status = create_file_with_content("main.c", main_c_gnu_template,
@@ -269,6 +254,7 @@ int generate_source_code(manifest_t manifest, char *licence_line)
manifest.project,
manifest.name);
}
return status;
}
@@ -276,70 +262,68 @@ int create_project(manifest_t manifest)
{
int status;
status = sanitize(&manifest);
if (status) {
printfn("failed to sanitize format: %s", strerror(status));
return status;
}
sanitize(&manifest);
depth = 0;
if (strcmp(manifest.path, ".") != 0) {
status = create_and_enter_directory(manifest.project);
if (status) {
printfn("failed to create or enter directory: %s",
if (status != 0) {
fprintf(stderr, "create_project: failed to create or enter directory: %s\n",
strerror(status));
return status;
}
depth++;
}
status = create_makefile(manifest);
if (status) {
printfn("failed to create Makefile: %s", strerror(status));
if (status != 0) {
fprintf(stderr, "create_project: failed to create Makefile: %s\n", strerror(status));
return status;
}
status = create_configure(manifest);
if (status) {
printfn("failed to create configure: %s", strerror(status));
if (status != 0) {
fprintf(stderr, "create_project: failed to create configure: %s\n", strerror(status));
return status;
}
status = setup_git(manifest);
if (status) {
printfn("warning: git initialization failed: %s",
if (status != 0) {
fprintf(stderr, "create_project: warning: git initialization failed: %s\n",
strerror(status));
}
status = maybe_create_clang_format(manifest);
if (status) {
printfn("warning: clang-format setup failed: %s",
if (status != 0) {
fprintf(stderr, "create_project: warning: clang-format setup failed: %s\n",
strerror(status));
}
// TODO(vx-clutch): make this smarter--or not ( macro ).
char *licence_line = malloc(sizeof(char) * 1024);
char *licence_line = malloc(1024);
if (!licence_line) {
printfn("failed to create memory for licence line: %s",
strerror(status));
return status;
fprintf(stderr, "create_project: failed to allocate memory for licence line\n");
return ENOMEM;
}
status = create_licence(manifest, &licence_line);
if (status) {
printfn("failed to get libraries: %s", strerror(status));
if (status != 0) {
fprintf(stderr, "create_project: failed to create licence: %s\n", strerror(status));
free(licence_line);
return status;
}
// TODO(vx-clutch): Take in licence line and put it into standard.c
status = generate_source_code(manifest, licence_line);
if (status) {
printfn("failed to generate source code: %s", strerror(status));
if (status != 0) {
fprintf(stderr, "create_project: failed to generate source code: %s\n", strerror(status));
free(licence_line);
return status;
}
free(licence_line);
status = create_libraries(manifest);
if (status) {
printfn("failed to get libraries: %s", strerror(status));
if (status != 0) {
fprintf(stderr, "create_project: failed to get libraries: %s\n", strerror(status));
return status;
}