save point

This commit is contained in:
2025-10-04 19:28:26 -04:00
parent 744aaf2bf8
commit c12dbce62c
21 changed files with 546 additions and 489 deletions

View File

@@ -1,5 +1,5 @@
CompileFlags: CompileFlags:
Add: [-x, c, -std=c23] Add: [-x, c, -std=c23, -Ilib, -I.]
Diagnostics: Diagnostics:
ClangTidy: ClangTidy:

2
gcklib

Submodule gcklib updated: 432788eb5f...b88978b6df

View File

@@ -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.
* <https://opensource.org/license/bsd-3-clause>
*/
#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

View File

@@ -1,46 +1,17 @@
/* Copyright (C) GCK /* 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.
* <https://opensource.org/licence/bsd-3-clause> * <https://opensource.org/licence/bsd-3-clause>
*/ */
#include <ctype.h>
#include <stdio.h>
#include <getopt.h> #include <getopt.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "util.h" #include "flag.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;
}
static char *nextchar; static char *nextchar;

15
lib/flag.h Normal file
View File

@@ -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.
* <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef FLAG_H
#define FLAG_H
int getopt_long(int argc, char *const argv[], const char *optstring,
const struct option *longopts, int *longindex);
#endif

157
lib/fs.c Normal file
View File

@@ -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.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#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;
}

26
lib/fs.h Normal file
View File

@@ -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.
* <https://opensource.org/licence/bsd-3-clause>
*/
#ifndef fs_H
#define fs_H
#include <stdio.h>
#include <sys/types.h>
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

View File

@@ -9,15 +9,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../config.h" #include <libgen.h>
#include <config.h>
#include "proginfo.h" #include "proginfo.h"
const char *prog_name = ""; 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() void emit_try_help()
@@ -36,12 +37,12 @@ There is NO WARRNTY, to the extent permitted by law.\n\
prog_name, VERSION, COMMIT, YEAR); prog_name, VERSION, COMMIT, YEAR);
} }
int parse_standard_options(int argc, char **argv, void (*usage)(int), int parse_standard_options(int argc, char **argv, void (*print_help)(),
void (*version)()) void (*print_version)())
{ {
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if (!strcmp(argv[i], "--help")) { if (!strcmp(argv[i], "--help")) {
usage(0); print_help();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (!strcmp(argv[i], "--version")) { } else if (!strcmp(argv[i], "--version")) {
emit_version(); emit_version();

View File

@@ -11,12 +11,12 @@
extern const char *prog_name; extern const char *prog_name;
void set_prog_name(const char *name); void set_prog_name(char *name);
void emit_try_help(); void emit_try_help();
void emit_version(); void emit_version();
int parse_standard_options(int argc, char **argv, void (*usage)(int), int parse_standard_options(int argc, char **argv, void (*print_help)(),
void (*version)()); void (*print_version)());
#endif #endif

View File

@@ -1,12 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "xmem.h"
#include "str_dup.h"
char *str_dup(char *s)
{
char *new = xmalloc(strlen(s) + 1);
strcpy(new, s);
return new;
}

View File

@@ -1,6 +0,0 @@
#ifndef STR_DUP_H
#define STR_DUP_H
char *str_dup(char *s);
#endif

28
lib/textc.c Normal file
View File

@@ -0,0 +1,28 @@
#include <string.h>
#include <ctype.h>
#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;
}

8
lib/textc.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef TEXTC_H
#define TEXTC_H
char *str_dup(char *s);
char *tostrupr(char *s);
char *tostrlwr(char *s);
#endif

View File

@@ -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.
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#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 <stdio.h>\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;
// }

View File

@@ -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.
* <https://opensource.org/license/bsd-3-clause>
*/
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#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;
}

View File

@@ -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

View File

@@ -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.
* <https://opensource.org/licence/bsd-3-clause>
*/
#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

View File

@@ -8,31 +8,33 @@
// Usage: yait [OPTION]... <PROJECT> // Usage: yait [OPTION]... <PROJECT>
#include <errno.h>
#include <getopt.h> #include <getopt.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h>
#include <proginfo.h> #include "../config.h"
#include <err.h> #include "../lib/err.h"
#include <str_dup.h> #include "../lib/fs.h"
#include <yait.h> #include "../lib/xmem.h"
#include <config.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[] = { static const struct option longopts[] = {
{ "author", required_argument, 0, 'a' }, { "author", required_argument, 0, 'a' },
{ "licence", required_argument, 0, 'l' }, { "licence", required_argument, 0, 'l' },
{ "quiet", no_argument, 0, 'q' }, { "quiet", no_argument, 0, 'q' },
{ "force", no_argument, 0, 'f' }, { "force", no_argument, 0, 'f' },
{ 0, 0, 0, 0 } }; { 0, 0, 0, 0 }
};
static int exit_status; static int exit_status;
@@ -88,39 +90,41 @@ int main(int argc, char **argv)
{ {
int optc; int optc;
int lose = 0; int lose = 0;
char *package;
set_prog_name(argv[0]); set_prog_name(argv[0]);
exit_status = EXIT_SUCCESS; exit_status = EXIT_SUCCESS;
bool quiet = false; bool quiet = false;
bool force = false; bool force = false;
bool editor = false;
manifest_t manifest = { const char *author = get_name();
.author = get_name(), licence_t licence;
.editor = NULL,
.licence = BSD,
.project = "Project",
};
parse_standard_options(argc, argv, print_help, print_version); 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) { switch (optc) {
case 'l': case 'l':
if (!strcmp(optarg, "list")) { if (!strcmp(optarg, "list")) {
puts("BSD\nGPL\nMIT"); puts("BSD\nGPL\nMIT\nUNL");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (!strcmp(optarg, "GPL")) if (!strcmp(optarg, "GPL"))
manifest.licence = GPL; licence = GPL;
else if (!strcmp(optarg, "MIT")) 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 { else {
puts("BSD\nGPL\nMIT"); puts("BSD\nGPL\nMIT\nUNL");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break; break;
case 'E': case 'E':
manifest.editor = getenv("EDITOR"); editor = true;
break; break;
case 'q': case 'q':
quiet = true; quiet = true;
@@ -131,16 +135,266 @@ int main(int argc, char **argv)
default: default:
lose = 1; lose = 1;
} }
if (lose || optind < argc) { if (lose) {
errorf("extra operand: %s", argv[optind]); emit_try_help();
usage();
} }
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 <<EOF\n\
Usage: $0 [OPTION]... [VAR=VALUE]...\n\
\n\
To assign environment variables (e.g., CC, CFLAGS...), specify them as\n\
VAR=VALUE.\n\
\n\
CC C compiler command [detected]\n\
CFLAGS C compiler flags [-g, ...]\n\
LDFLAGS C linker flags\n\
\n\
--prefix=<path> 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); char *cwd = getcwd(NULL, 0);
if (!cwd) { if (cwd == NULL) {
fatalfa(errno); 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); free(cwd);
return exit_status; return exit_status;
@@ -168,15 +422,13 @@ Generates an optionated C project.\n",
exit(exit_status); exit(exit_status);
} }
/* Print version and copyright information. */
static void print_version() static void print_version()
{ {
printf("%s %s %d\n", prog_name, VERSION, COMMIT); printf("%s %s %d\n", prog_name, VERSION, COMMIT);
printf("Copyright (C) %d GCK.\n", YEAR);
puts("This is free software: you are free to change and redistribute it."); printf("Copyright (C) %d GCK.\n", YEAR);
puts("There is NO WARRNTY, to the extent permitted by law.");
exit(exit_status); 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);
} }

View File

@@ -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
}
'

3
tools/update-gcklib Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
git submodule update --remote --rebase

BIN
yait Executable file

Binary file not shown.