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 0000000..27108a6 Binary files /dev/null and b/yait differ