From c12dbce62c9a6ea86d9a994caff9e8fdd3bbefe1 Mon Sep 17 00:00:00 2001 From: vx-clutch Date: Sat, 4 Oct 2025 19:28:26 -0400 Subject: [PATCH] save point --- .clangd | 2 +- gcklib | 2 +- include/yait.h | 23 --- src/util.c => lib/flag.c | 37 +--- lib/flag.h | 15 ++ lib/fs.c | 157 +++++++++++++++++ lib/fs.h | 26 +++ lib/proginfo.c | 13 +- lib/proginfo.h | 6 +- lib/str_dup.c | 12 -- lib/str_dup.h | 6 - lib/textc.c | 28 +++ lib/textc.h | 8 + src/create_project.c | 182 -------------------- src/file.c | 91 ---------- src/tests/run_unit_tests.sh | 20 --- src/util.h | 27 --- src/yait.c | 334 +++++++++++++++++++++++++++++++----- tools/tostr | 43 ----- tools/update-gcklib | 3 + yait | Bin 0 -> 60152 bytes 21 files changed, 546 insertions(+), 489 deletions(-) delete mode 100644 include/yait.h rename src/util.c => lib/flag.c (76%) create mode 100644 lib/flag.h create mode 100644 lib/fs.c create mode 100644 lib/fs.h delete mode 100644 lib/str_dup.c delete mode 100644 lib/str_dup.h create mode 100644 lib/textc.c create mode 100644 lib/textc.h delete mode 100644 src/create_project.c delete mode 100644 src/file.c delete mode 100755 src/tests/run_unit_tests.sh delete mode 100644 src/util.h delete mode 100755 tools/tostr create mode 100755 tools/update-gcklib create mode 100755 yait diff --git a/.clangd b/.clangd index 5b95111..589b320 100644 --- a/.clangd +++ b/.clangd @@ -1,5 +1,5 @@ CompileFlags: - Add: [-x, c, -std=c23] + Add: [-x, c, -std=c23, -Ilib, -I.] Diagnostics: ClangTidy: diff --git a/gcklib b/gcklib index 432788e..b88978b 160000 --- a/gcklib +++ b/gcklib @@ -1 +1 @@ -Subproject commit 432788eb5f78afb08b7c011b81118c7f9bc520d9 +Subproject commit b88978b6dffa344752f98c842ac0417d15b6309f diff --git a/include/yait.h b/include/yait.h deleted file mode 100644 index ef2a3ac..0000000 --- a/include/yait.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) GCK - * - * This file is part of yait - * - * This project and file is licenced under the BSD-3-Clause licence. - * - */ - -#ifndef YAIT_H -#define YAIT_H - -typedef enum { MIT, GPL, BSD } licence_t; - -typedef struct { - licence_t licence; - char *project; - char *author; - char *editor; -} manifest_t; - -int create_project(manifest_t manifest); - -#endif // YAIT_H diff --git a/src/util.c b/lib/flag.c similarity index 76% rename from src/util.c rename to lib/flag.c index 5f11ad6..bd4fc09 100644 --- a/src/util.c +++ b/lib/flag.c @@ -1,46 +1,17 @@ /* Copyright (C) GCK * - * This file is part of yait + * This file is part of gcklib * - * This project and file is licenced under the BSD-3-Clause licence. + * This project and file is licensed under the BSD-3-Clause licence. * */ -#include -#include #include +#include #include #include -#include "util.h" -#include "../include/yait.h" - -int fno = 1; -bool flast = false; - -char *tostrupr(const char *s) -{ - char *new = malloc(strlen(s) + 1); - if (!new) - return NULL; - strcpy(new, s); - for (int i = 0; new[i] != '\0'; ++i) - new[i] = toupper((unsigned char)new[i]); - return new; -} - -licence_t TOlicence(char *src) -{ - char *s = tostrupr(src); - if (!strcmp(s, "MIT")) - return MIT; - if (!strcmp(s, "GPL")) - return GPL; - if (!strcmp(s, "BSD")) - return BSD; - free(s); - return BSD; -} +#include "flag.h" static char *nextchar; diff --git a/lib/flag.h b/lib/flag.h new file mode 100644 index 0000000..74b45f1 --- /dev/null +++ b/lib/flag.h @@ -0,0 +1,15 @@ +/* Copyright (C) GCK + * + * This file is part of gcklib + * + * This project and file is licensed under the BSD-3-Clause licence. + * + */ + +#ifndef FLAG_H +#define FLAG_H + +int getopt_long(int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex); + +#endif diff --git a/lib/fs.c b/lib/fs.c new file mode 100644 index 0000000..c01b602 --- /dev/null +++ b/lib/fs.c @@ -0,0 +1,157 @@ +/* Copyright (C) GCK + * + * This file is part of gcklib + * + * This project and file is licensed under the BSD-3-Clause licence. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "err.h" + +#include "fs.h" + +char *fs_read(const char *path) +{ + FILE *fptr = fopen(path, "r"); + if (!fptr) + return NULL; + + size_t cap = 1024; + size_t len = 0; + char *buf = malloc(cap); + if (!buf) { + fclose(fptr); + return NULL; + } + + int c; + while ((c = fgetc(fptr)) != EOF) { + if (len + 1 >= cap) { + cap *= 2; + char *tmp = realloc(buf, cap); + if (!tmp) { + free(buf); + fclose(fptr); + return NULL; + } + buf = tmp; + } + buf[len++] = (char)c; + } + buf[len] = '\0'; + + fclose(fptr); + return buf; +} + +bool fs_exists(const char *path) +{ + FILE *fptr; + bool exists; + + fptr = fopen(path, "r"); + if (fptr) { + exists = true; + } else { + exists = false; + } + + return exists; +} + +int fs_append(const char *path, const char *format, ...) +{ + FILE *fp = fopen(path, "a"); + if (!fp) + return -1; + + va_list ap; + va_start(ap, format); + int ret = vfprintf(fp, format, ap); + va_end(ap); + + if (ret < 0) { + fclose(fp); + return -1; + } + + if (fclose(fp) != 0) + return -1; + + return ret; +} + +int fs_del(const char *path) +{ + return remove(path); +} + +int fs_new(const char *path) +{ + size_t len; + int fd; + + if (path == NULL) { + errno = EINVAL; + return -1; + } + + len = strlen(path); + if (len == 0) { + errno = EINVAL; + return -1; + } + + if (path[len - 1] == '/') { + if (mkdir(path, 0777) == -1) + return -1; + } else { + fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666); + if (fd == -1) + return -1; + close(fd); + } + + return 0; +} + +int fs_write(const char *path, const char *format, ...) +{ + FILE *fptr = fopen(path, "w"); + if (!fptr) + return -1; + + va_list ap; + va_start(ap, format); + int ret = vfprintf(fptr, format, ap); + va_end(ap); + + if (ret < 0) { + fclose(fptr); + return -1; + } + + if (fclose(fptr) != 0) + return -1; + + return ret; +} + +FILE *fs_temp() +{ + FILE *fptr = tmpfile(); + + if (!fptr) { + errorf("tmpfile failed"); + return NULL; + } + + return fptr; +} diff --git a/lib/fs.h b/lib/fs.h new file mode 100644 index 0000000..35019e5 --- /dev/null +++ b/lib/fs.h @@ -0,0 +1,26 @@ +/* Copyright (C) GCK + * + * This file is part of gcklib + * + * This project and file is licensed under the BSD-3-Clause licence. + * + */ + +#ifndef fs_H +#define fs_H + +#include +#include + +char *fs_read(const char *path); + +bool fs_exists(const char *path); + +int fs_append(const char *path, const char *format, ...); +int fs_del(const char *path); +int fs_new(const char *path); +int fs_write(const char *path, const char *format, ...); + +FILE *fs_temp(); + +#endif diff --git a/lib/proginfo.c b/lib/proginfo.c index 410408f..dca283c 100644 --- a/lib/proginfo.c +++ b/lib/proginfo.c @@ -9,15 +9,16 @@ #include #include #include -#include "../config.h" +#include +#include #include "proginfo.h" const char *prog_name = ""; -void set_prog_name(const char *name) +void set_prog_name(char *name) { - prog_name = prog_name ? name : ""; + prog_name = prog_name ? basename(name) : ""; } void emit_try_help() @@ -36,12 +37,12 @@ There is NO WARRNTY, to the extent permitted by law.\n\ prog_name, VERSION, COMMIT, YEAR); } -int parse_standard_options(int argc, char **argv, void (*usage)(int), - void (*version)()) +int parse_standard_options(int argc, char **argv, void (*print_help)(), + void (*print_version)()) { for (int i = 0; i < argc; ++i) { if (!strcmp(argv[i], "--help")) { - usage(0); + print_help(); exit(EXIT_SUCCESS); } else if (!strcmp(argv[i], "--version")) { emit_version(); diff --git a/lib/proginfo.h b/lib/proginfo.h index 2a426c6..d2a79f4 100644 --- a/lib/proginfo.h +++ b/lib/proginfo.h @@ -11,12 +11,12 @@ extern const char *prog_name; -void set_prog_name(const char *name); +void set_prog_name(char *name); void emit_try_help(); void emit_version(); -int parse_standard_options(int argc, char **argv, void (*usage)(int), - void (*version)()); +int parse_standard_options(int argc, char **argv, void (*print_help)(), + void (*print_version)()); #endif diff --git a/lib/str_dup.c b/lib/str_dup.c deleted file mode 100644 index 3c4f1c2..0000000 --- a/lib/str_dup.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include "xmem.h" - -#include "str_dup.h" - -char *str_dup(char *s) -{ - char *new = xmalloc(strlen(s) + 1); - strcpy(new, s); - return new; -} diff --git a/lib/str_dup.h b/lib/str_dup.h deleted file mode 100644 index 7ab6a61..0000000 --- a/lib/str_dup.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef STR_DUP_H -#define STR_DUP_H - -char *str_dup(char *s); - -#endif diff --git a/lib/textc.c b/lib/textc.c new file mode 100644 index 0000000..575ae97 --- /dev/null +++ b/lib/textc.c @@ -0,0 +1,28 @@ +#include +#include +#include "xmem.h" + +#include "textc.h" + +char *str_dup(char *s) +{ + char *new = xmalloc(strlen(s) + 1); + strcpy(new, s); + return new; +} + +char *tostrupr(char *s) +{ + char *new = str_dup(s); + for (int i = 0; new[i] != '\0'; ++i) + new[i] = toupper((unsigned char)new[i]); + return new; +} + +char *tostrlwr(char *s) +{ + char *new = str_dup(s); + for (int i = 0; new[i] != '\0'; ++i) + new[i] = tolower((unsigned char)new[i]); + return new; +} diff --git a/lib/textc.h b/lib/textc.h new file mode 100644 index 0000000..b9bc131 --- /dev/null +++ b/lib/textc.h @@ -0,0 +1,8 @@ +#ifndef TEXTC_H +#define TEXTC_H + +char *str_dup(char *s); +char *tostrupr(char *s); +char *tostrlwr(char *s); + +#endif diff --git a/src/create_project.c b/src/create_project.c deleted file mode 100644 index 24fe92d..0000000 --- a/src/create_project.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright (C) GCK - * - * This file is part of yait - * - * This project and file is licensed under the BSD-3-Clause licence. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "../include/yait.h" -#include "licences/licences.h" -#include "util.h" - -// int create_project(manifest_t manifest) -// { -// int status; -// char buffer[BUFSIZ], *main_source; -// -// status = mkdir_p(manifest.project); -// if (status) -// return 1; -// -// status = chdir(manifest.project); -// if (status) -// return 1; -// -// cfprintf( -// "README", -// "%s ( short description )\n\nThis cool project actions adverbly.\n", -// manifest.project); -// -// if (manifest.build != BARE) { -// main_source = manifest.flat ? "main.c" : "src/main.c"; -// cfprintf(main_source, "#include \n" -// "\n" -// "int main()\n" -// "{\n" -// "\tputs(\"Hello, World!\");\n" -// "\treturn 0;\n" -// "}\n"); -// } -// char *upr_name = tostrupr(manifest.project); -// switch (manifest.build) { -// case MAKE: -// cfprintf( -// "Makefile", -// "PREFIX = /usr/bin\n" -// "\n" -// "%s_SRCS := $(wildcard src/*.c)\n" -// "%s_OBJS := $(patsubst src/%.c,build/obj/%.o,$(%s_SRCS))" -// "\n" -// "%s := bin/%s" -// "\n" -// "-include config.mak\n" -// "\n" -// "ifeq ($(wildcard config.mak),)\n", -// upr_name, upr_name, upr_name, upr_name, -// manifest.project); -// break; -// case CMAKE: -// cfprintf("CMakeLists.txt", -// "cmake_minimum_required(VERSION 3.16)\n" -// "\n" -// "project(%s\n" -// " VERSION 0.1.0\n" -// " LANGUAGES C)\n" -// "\n" -// "set(CMAKE_C_STANDARD 23)\n" -// "set(CMAKE_C_STANDARD_REQUIRED ON)\n" -// "set(CMAKE_C_EXTENSIONS OFF)\n" -// "\n" -// "include(GNUInstallDirs)\n" -// "\n" -// "add_executable(%s\n" -// " src/main.c\n" -// ")\n" -// "\n" -// "install(TARGETS %s\n" -// " RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n" -// ")\n", -// manifest.project, manifest.project, manifest.project); -// break; -// case AUTOTOOLS: -// cfprintf("configure.ac", -// "AC_PREREQ([2.69])\n" -// "AC_INIT([%s], [0.1], [bug-report@exmaple.com])\n" -// "AM_INIT_AUTOMAKE([foreign -Wall])\n" -// "AC_CONFIG_SRCDIR([src/main.c])\n" -// "AC_CONFIG_HEADERS([config.h])" -// "AC_PROG_CC\n" -// "AC_CONFIG_FILES([Makefile src/Makefile])\n" -// "AC_OUTPUT\n", -// manifest.project); -// cfprintf("Makefile.am", "SUBDIRS = src\n"); -// cfprintf("src/Makefile.am", -// "bin_PROGRAMS = %s\n" -// "%s_SOURCES = main.c\n", -// manifest.project, manifest.project); -// cfprintf("bootstrap", -// "#!/bin/sh\n" -// "set -e\n" -// "\n" -// "autoreconf --install --verbose --force\n"); -// break; -// case BARE: -// snprintf(buffer, BUFSIZ, "%s.c", manifest.project); -// cfprintf(buffer, ""); -// main_source = str_dup(buffer); -// cfprintf("Makefile", -// ".POSIX:\n" -// "CC ::= gcc\n" -// "CFLAGS ::= -std=c23 -Wall -Wextra -Wpedantic\n" -// "\n" -// "all: %s\n" -// "\n" -// "clean:\n" -// "\t$(RM) %s", -// manifest.project, manifest.project); -// break; -// case BCOUNT: -// default: -// abort(); -// } -// -// flast = true; -// switch (manifest.licence) { -// case MIT: -// cfprintf("COPYING", "%s", MIT_txt); -// break; -// case GPL: -// cfprintf("COPYING", "%s", GPL_3_0_txt); -// break; -// case BSD: -// cfprintf("COPYING", "%s", BSD_3_Clause_txt); -// break; -// case UNL: -// cfprintf("COPYING", "%s", UNLICENSE_txt); -// break; -// case LCOUNT: -// default: -// abort(); -// } -// -// if (!manifest.git) { -// fprintf(stderr, "Initializing git reposity"); -// status = system("git init --quiet"); -// if (status) -// fprintf(stderr, ", failed.\n"); -// else -// fprintf(stderr, ", done.\n"); -// } -// -// if (manifest.build == AUTOTOOLS) { -// fprintf(stderr, "Changing files permissions 1"); -// struct stat st; -// if (stat("bootstrap", &st) == -1) { -// perror("stat failed"); -// return 1; -// } -// mode_t new_mode = st.st_mode | S_IXUSR; -// if (chmod("bootstrap", new_mode) == -1) { -// perror("chmod failed"); -// return 1; -// } -// fprintf(stderr, ", done.\n"); -// } -// -// if (manifest.open_editor) { -// snprintf(buffer, BUFSIZ, "$EDITOR %s", main_source); -// status = system(buffer); -// if (status) -// fprintf(stderr, "Could not open editor"); -// } -// -// return 0; -// } diff --git a/src/file.c b/src/file.c deleted file mode 100644 index 25e7f08..0000000 --- a/src/file.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) GCK - * - * This file is part of yait - * - * This project and file is licensed under the BSD-3-Clause licence. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" - -int mkdir_p(const char *path) -{ - char *copypath = strdup(path); - char *p = copypath; - int status = 0; - - if (!copypath) - return -1; - - if (copypath[0] == '/') - p++; - - for (; *p; p++) { - if (*p == '/') { - *p = '\0'; - if (mkdir(copypath, 0777) && errno != EEXIST) { - status = -1; - break; - } - *p = '/'; - } - } - - if (!status && mkdir(copypath, 0777) && errno != EEXIST) - status = -1; - - free(copypath); - return status; -} - -int cfprintf(const char *path, const char *format, ...) -{ - // int lines = atoi(getenv("LINES")); - char *dirpath; - const char *slash = strrchr(path, '/'); - if (slash) { - size_t len = slash - path; - dirpath = malloc(len + 1); - if (!dirpath) - return -1; - memcpy(dirpath, path, len); - dirpath[len] = '\0'; - if (mkdir_p(dirpath)) { - free(dirpath); - return -1; - } - free(dirpath); - } - - FILE *fp = fopen(path, "w"); - if (!fp) - return -1; - - va_list args; - va_start(args, format); - if (vfprintf(fp, format, args) < 0) { - va_end(args); - fclose(fp); - return -1; - } - va_end(args); - - fclose(fp); - - if (flast) - fprintf(stderr, "Created files %d, done.\n", fno); - else - fprintf(stderr, "Created files %d\r", fno); - fno++; - - return 0; -} diff --git a/src/tests/run_unit_tests.sh b/src/tests/run_unit_tests.sh deleted file mode 100755 index da96bb3..0000000 --- a/src/tests/run_unit_tests.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -yait="$(pwd)/bin/yait" - -fatal() { - echo "fatal: $*" >&2 - exit 1 -} - -[ -d "./yait" ] && fatal "must be run from parent directory" - -{ -$yait --help || fatal "failed on --help" -$yait --version || fatal "failed on --version" - -tmpd=$(mktemp -d) -cd $tmpd - -$yait foo || fatal "failed to create `foo` at ${tmpd}" -} > build/test.log 2>&1 diff --git a/src/util.h b/src/util.h deleted file mode 100644 index 7d2f865..0000000 --- a/src/util.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) GCK - * - * This file is part of yait - * - * This project and file is licenced under the BSD-3-Clause licence. - * - */ - -#ifndef UTIL_H -#define UTIL_H - -#include "../include/yait.h" - -licence_t TOlicence(char *s); - -int getopt_long(int argc, char *const argv[], const char *optstring, - const struct option *longopts, int *longindex); - -char *tostrupr(const char *s); - -extern int fno; -extern bool flast; - -int mkdir_p(const char *path); -int cfprintf(const char *path, const char *format, ...); - -#endif diff --git a/src/yait.c b/src/yait.c index 55fe31f..22a30e0 100644 --- a/src/yait.c +++ b/src/yait.c @@ -8,31 +8,33 @@ // Usage: yait [OPTION]... +#include #include +#include #include +#include #include #include -#include -#include -#include -#include #include #include +#include -#include -#include -#include -#include -#include +#include "../config.h" +#include "../lib/err.h" +#include "../lib/fs.h" +#include "../lib/xmem.h" +#include "../lib/proginfo.h" +#include "../lib/textc.h" -#include "name.h" +typedef enum { MIT, GPL, BSD, UNL } licence_t; static const struct option longopts[] = { - { "author", required_argument, 0, 'a' }, - { "licence", required_argument, 0, 'l' }, - { "quiet", no_argument, 0, 'q' }, - { "force", no_argument, 0, 'f' }, - { 0, 0, 0, 0 } }; + { "author", required_argument, 0, 'a' }, + { "licence", required_argument, 0, 'l' }, + { "quiet", no_argument, 0, 'q' }, + { "force", no_argument, 0, 'f' }, + { 0, 0, 0, 0 } +}; static int exit_status; @@ -88,39 +90,41 @@ int main(int argc, char **argv) { int optc; int lose = 0; + char *package; set_prog_name(argv[0]); exit_status = EXIT_SUCCESS; bool quiet = false; bool force = false; - - manifest_t manifest = { - .author = get_name(), - .editor = NULL, - .licence = BSD, - .project = "Project", - }; + bool editor = false; + const char *author = get_name(); + licence_t licence; parse_standard_options(argc, argv, print_help, print_version); - while ((optc = getopt_long(argc, argv, "a:l:Eqf", longopts, NULL)) != -1) + while ((optc = getopt_long(argc, argv, "a:l:Eqf", longopts, NULL)) != + -1) switch (optc) { case 'l': if (!strcmp(optarg, "list")) { - puts("BSD\nGPL\nMIT"); + puts("BSD\nGPL\nMIT\nUNL"); exit(EXIT_SUCCESS); } if (!strcmp(optarg, "GPL")) - manifest.licence = GPL; + licence = GPL; else if (!strcmp(optarg, "MIT")) - manifest.licence = MIT; + licence = MIT; + else if (!strcmp(optarg, "BSD")) + licence = BSD; + else if (!strcmp(optarg, "UNL")) + licence = UNL; else { - puts("BSD\nGPL\nMIT"); + puts("BSD\nGPL\nMIT\nUNL"); exit(EXIT_FAILURE); } break; case 'E': - manifest.editor = getenv("EDITOR"); + editor = true; break; case 'q': quiet = true; @@ -131,16 +135,266 @@ int main(int argc, char **argv) default: lose = 1; } - if (lose || optind < argc) { - errorf("extra operand: %s", argv[optind]); - usage(); + if (lose) { + emit_try_help(); } + if (optind >= argc) { + fatalf("no project name provided"); + } + + if (optind + 1 < argc) { + errorf("extra operand: %s", argv[optind + 1]); + emit_try_help(); + } + + package = str_dup(argv[optind]); + + size_t len = strlen(package); + char *pdir = xmalloc(len + 2); + memcpy(pdir, package, len); + pdir[len] = '/'; + pdir[len + 1] = '\0'; + + fs_write("README", "\ +This is the README for the GCK %s distribution.\n\ +%s does a thing.\n\ +\n\ + Copyright (C) %d GCK.\n\ +\n\ + Copying and distribution of this file, with or without modifications\n\ + are permitted in any medium without royalty provided the copyright\n\ + notice and this notice are preserved.\n\ +\n\ +See the files ./INSTALL* for building and installation instructions.\n\ +\n\ +Bug reports:\n\ + Please include enough information for the maintainers to reproduce the\n\ + problem. Generally speaking, that means:\n\ +- the contents of any input files necessary to reproduce the bug\n\ + and command line invocations of the program(s) involved (crucial!).\n\ +- a description of the problem and any samples of the erroneous output.\n\ +- the version number of the program(s) involved (use --version).\n\ +- hardware, operating system, and compiler versions (uname -a).\n\ +- unusual options you gave to configure, if any (see config.mak).\n\ +- anything else that you think would be helpful.\n\ +\n\ +See README-dev for information on the development environment -- any\n\ +interested parties are welcome. If you're a programmer and wish to\n\ +contribute, this should get you started. If you're not a programmer,\n\ +your help in writing test cases, checking documentation against the\n\ +implementation, etc., would still be very much appreciated.\n\ +\n\ +GCK %s is free software. See the file COPYING for copying conditions.\n\ +\n", + package, package, YEAR, package); + + fs_write("INSTALL", "\ +Installation Instructions\n\ +*************************\n\ +\n\ +Copyright (C) %d GCK.\n\ +\n\ + Copying and distribution of this file, with or without modification,\n\ +are permitted in any medium without royalty provided the copyright\n\ +notice and this notice are preserved. This file is offered as-is,\n\ +without warranty of any kind.\n\ +\n\ +Basic Installation\n\ +==================\n\ +\n\ + Briefly, the shell command `./configure && make && make install` should\n\ +configure, build, and install this package. The following more-detailed\n\ +instruction are generic; see the `README` file for instructions specific to\n\ +this package.\n\ +\n\ + The `configure` shell script attempts to guess correct values for\n\ +various system-dependent variables used during compilation. It uses\n\ +those values within a `Makefile` to build for that POSIX system as\n\ +defined by `config.mak` which was generated by `configure`.\n\ +\n\ +Compilers and Options\n\ +=====================\n\ +\n\ + Some systems require unusal options for compilation or linking that\n\ +the `configure` script does not know about. If you run into an issue\n\ +run `./configure --help` to figure out what you can do to fix the\n\ +behavoir.\n\ +\n\ +Installation Names\n\ +==================\n\ +\n\ + By default, `make install` installs the package's command under\n\ +`/usr/local/bin`. You can specify an installation prefix other than `/usr/local/`\n\ +by giving `configure` the option `--prefix=PREFIX` to `configure`, the package uses\n\ +PREFIX as the prefix for installation programs and libraries.\n\ +Documentation and other data files still use the regular prefix.\n\ +\n\ +`configure` Invokation\n\ +======================\n\ +\n\ + `configure` recongizes the following options to control its operations.\n\ +\n\ + `--help`\n\ + Prints a summary of all the options to `configure`, and exits.\n\ + `--prefix=PREFIX`\n\ + Sets the installation prefix.\n\ + `CFLAGS`\n\ + Sets the flags used during compilation.\n\ +\n\ +`configure` also accepts some other options. Run `configure --help` for more\n\ +details\n\ +", + YEAR); + + fs_write("AUTHORS", "\ +Authors of GCK yait.\n\ +\n\ + Copyright (C) 2025 GCK.\n\ +\n\ + Copying and distribution of this file, with or without modification,\n\ + are permitted in any medium without royalty provided the copyright\n\ + notice and this notice are preserved.\n\ +\n\ +Also see the THANKS files.\n\ +\n\ +%s\n\ +", + author); + + fs_write("THANKS", "\ +Additional contributors to GCK %s.\n\ +\n\ + Copyright (C) %d GCK.\n\ +\n\ + Copying and distribution of this file, with or without modification,\n\ + are permitted in any medium without royalty provided the copyright\n\ + notice and this notice are preserved.\n\ +\n\ +Thanks to:\n\ +\n\ + GCK yait for project initialization.\n\ +\n\ +See also the AUTHORS file.\n\ + ", + package, YEAR); + + fs_write("config.h", "\ +#ifndef CONFIG_H\n\ +#define CONFIG_H\n\ +\n\ +/* Program information */\n\ +#define PROGRAM \"%s\"\n\ +#define AUTHORS \"GCK\"\n\ +#define VERSION \"beta\"\n\ +#define YEAR %d\n\ +\n\ +#endif\n\ + ", + package, YEAR); + + fs_write("configure", "\ +#!/bin/sh\n\ +\n\ +usage() {\n\ +cat < Set the install path\n\ +--debug Flags for debug build, overrides CFLAGS\n\ +\n\ +EOF\n\ +exit 0\n\ +}\n\ +\n\ +cmdexists() { type \"$1\" >/dev/null 2>&1 ; }\n\ +trycc() { [ -z \"$CC\" ] && cmdexists \"$1\" && CC=$1 ; }\n\ +\n\ +prefix=/usr/local\n\ +CFLAGS=\"-std=c23\"\n\ +LDFLAGS=\n\ +CC=\n\ +\n\ +printf \"checking for C compiler... \"\n\ +trycc gcc\n\ +trycc clang\n\ +trycc cc\n\ +trycc icx\n\ +printf \"%s\n\" \"$CC\"\n\ +\n\ +DEBUG=false\n\ +for arg; do\n\ +case \"$arg\" in\n\ +--help|-h) usage ;;\n\ +--prefix=*) prefix=${arg#*=} ;;\n\ +--debug) DEBUG=true ;;\n\ +CFLAGS=*) CFLAGS=${arg#*=} ;;\n\ +LDFLAGS=*) LDFLAGS=${arg#*=} ;;\n\ +CC=*) CC=${arg#*=} ;;\n\ +*) printf \"Unrecognized option %s\n\" \"$arg\" ;;\n\ +esac\n\ +done\n\ +\n\ +printf \"checking whether C compiler works... \"\n\ +tmpc=\"$(mktemp -d)/test.c\"\n\ +echo \"typedef int x;\" > \"$tmpc\"\n\ +if output=$($CC $CFLAGS -c -o /dev/null \"$tmpc\" 2>&1); then\n\ +printf \"yes\n\"\n\ +else\n\ +printf \"no; %%s\n\" \"$output\"\n\ +exit 1\n\ +fi\n\ +\n\ +GDEBUGCFLAGS=\"-std=c23 -O0 -g3 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wdouble-promotion -Wformat=2 -Wnull-dereference -Wconversion -Wsign-conversion -Wcast-qual -Wcast-align=strict -Wpointer-arith -Wstrict-overflow=5 -Wstrict-aliasing=2 -Wundef -Wunreachable-code -Wswitch-enum -fanalyzer -fsanitize=undefined,address -fstack-protector-strong -D_FORTIFY_SOURCE=3\"\n\ +CDEBUGCFLAGS=\"-std=gnu2x -O0 -g3 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wdouble-promotion -Wformat=2 -Wnull-dereference -Wconversion -Wsign-conversion -Wcast-qual -Wcast-align=strict -Wpointer-arith -Wstrict-overflow=5 -Wstrict-aliasing=2 -Wundef -Wunreachable-code -Wswitch-enum -fanalyzer -fsanitize=undefined,address -fstack-protector-strong -D_FORTIFY_SOURCE=3\"\n\ +\n\ +if [ -z \"$DEBUG\" ]; then\n\ +case \"$CC\" in\n\ +gcc) CFLAGS=\"$GDEBUGFLAGS\";;\n\ +clang) CFLAGS=\"$CDEBUGFLAGS\";;\n\ +*) ;;\n\ +esac\n\ +else\n\ +case \"$CC\" in\n\ +gcc) ;;\n\ +clang) ;;\n\ +*) ;;\n\ +esac\n\ +fi\n\ +\n\ +case \"$OSTYPE\" in\n\ +cygwin|msys) \n\ +echo \"enabling windows specific flags\"\n\ +CFLAGS=\"-v $CFLAGS\"\n\ +;;\n\ +esac\n\ +\n\ +printf \"creating config.mak... \"\n\ +{\n\ +printf \"PREFIX=%%s\n\" \"$prefix\"\n\ +printf \"CFLAGS=%%s\n\" \"$CFLAGS\"\n\ +printf \"LDFLAGS=%%s\n\" \"$LDFLAGS\"\n\ +printf \"CC=%%s\n\" \"$CC\"\n\ +} > config.mak\n\ +printf \"done\n\"\n\ +"); + char *cwd = getcwd(NULL, 0); - if (!cwd) { + if (cwd == NULL) { fatalfa(errno); } - fprintf(stderr, "Created %s at\n %s\n", manifest.project, cwd); + + if (!quiet) { + fprintf(stderr, "Created %s at\n %s\n", package, cwd); + } + free(cwd); return exit_status; @@ -168,15 +422,13 @@ Generates an optionated C project.\n", exit(exit_status); } -/* Print version and copyright information. */ - static void print_version() { - printf("%s %s %d\n", prog_name, VERSION, COMMIT); - - printf("Copyright (C) %d GCK.\n", YEAR); + printf("%s %s %d\n", prog_name, VERSION, COMMIT); - puts("This is free software: you are free to change and redistribute it."); - puts("There is NO WARRNTY, to the extent permitted by law."); - exit(exit_status); + printf("Copyright (C) %d GCK.\n", YEAR); + + puts("This is free software: you are free to change and redistribute it."); + puts("There is NO WARRNTY, to the extent permitted by law."); + exit(exit_status); } diff --git a/tools/tostr b/tools/tostr deleted file mode 100755 index 4ae3958..0000000 --- a/tools/tostr +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh - -awk ' -{ - # Start a new string literal - printf "\"" - - for (i = 1; i <= length($0); i++) { - c = substr($0, i, 1) - if (c == "\\") { - printf "\\\\" - } else if (c == "\"") { - printf "\\\"" - } else if (c == "\t") { - printf "\\t" - } else if (c == "\r") { - printf "\\r" - } else if (c == "\n") { - printf "\\n" - } else if (c == "\f") { - printf "\\f" - } else if (c == "\b") { - printf "\\b" - } else if (c == "\a") { - printf "\\a" - } else if (c == "\v") { - printf "\\v" - } else if (c ~ /[[:cntrl:]]/) { - printf "\\x%02x", ord(c) - } else { - printf "%s", c - } - } - - # Always end each literal with \n inside, close quote, then newline - printf "\\n\"\n" -} -function ord(str, l, r) { - l = sprintf("%c", 255) - r = sprintf("%c", 0) - return index(l str r, str) - 1 -} -' diff --git a/tools/update-gcklib b/tools/update-gcklib new file mode 100755 index 0000000..1c383e6 --- /dev/null +++ b/tools/update-gcklib @@ -0,0 +1,3 @@ +#!/bin/sh + +git submodule update --remote --rebase diff --git a/yait b/yait new file mode 100755 index 0000000000000000000000000000000000000000..27108a61c08df96b9613d92d362d88ab511d5ffa GIT binary patch literal 60152 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 literal 0 HcmV?d00001