This commit is contained in:
2025-08-21 15:51:05 -04:00
parent 4e4d867895
commit 592301d1f8
28 changed files with 201 additions and 161 deletions

View File

@@ -1,2 +1,2 @@
CompileFlags: CompileFlags:
Add: ["-std=c2x"] Add: ["--std=c2x", "-xc"]

View File

@@ -12,7 +12,7 @@ all:
@exit 1 @exit 1
else else
all: build $(YAIT) $(YAIT_DOC) all: build $(YAIT)
build: build:
mkdir -p bin mkdir -p bin

7
TODO Normal file
View File

@@ -0,0 +1,7 @@
VX yait --- TODO
Todo:
* Argument Parsing
end of file TODO

BIN
bin/yait Executable file

Binary file not shown.

View File

@@ -9,9 +9,4 @@
#define VERSION "alpha" #define VERSION "alpha"
#define YEAR 2025 #define YEAR 2025
/* Custom error codes */
#define HELP_REQUESTED 2
#define ERROR_MEMORY_ALLOCATION 3
#define ERROR_DIRECTORY_CREATION 4
#endif #endif

4
config.mak Normal file
View File

@@ -0,0 +1,4 @@
PREFIX=/usr/bin/
CFLAGS=-ggdb -std=c23
LDFLAGS=
CC=gcc

2
configure vendored
View File

@@ -19,7 +19,7 @@ cmdexists () { type "$1" >/dev/null 2>&1 ; }
trycc () { test -z "$CC" && cmdexists "$1" && CC=$1 ; } trycc () { test -z "$CC" && cmdexists "$1" && CC=$1 ; }
prefix=/usr/bin/ prefix=/usr/bin/
CFLAGS="-Wall -Wextra -O2 --std=c23" CFLAGS="-Wall -Wextra -O2 --std=c23 -Wpedantic"
LDFLAGS= LDFLAGS=
CC= CC=

View File

@@ -0,0 +1,8 @@
.POSIX:
CC ::= gcc
CFLAGS ::= -Wall -Wpedenatic -O2
all: simple
clean:
$(RM) simple

View File

@@ -0,0 +1,3 @@
simple.c vx-clutch
A simple program that does simple things.

View File

View File

@@ -9,47 +9,43 @@
#ifndef YAIT_H #ifndef YAIT_H
#define YAIT_H #define YAIT_H
typedef struct {
bool posix;
bool git;
bool clang;
bool lib;
bool cc;
bool gnu;
/* If this flag is set it will ignore: GNU, and enforce POSIX. */
bool simple;
} flag_t;
typedef struct {
bool ncurses;
bool raylib;
bool stb;
bool uthash;
bool linenoise;
} libmap_t;
typedef enum { typedef enum {
BSD3,
GPLv3,
MIT, MIT,
UNLICENCE, GPL,
LICENCE_HELP, BSD,
UNL,
} licence_t; } licence_t;
/* A bit field is used so that we can accomplish two things. (a) store lots of
libraries without taxing memory; and (b) a dynamic array is not neccescary.
*/
typedef enum {
LIB_NONE = 0,
LIB_RAYLIB = 1 << 0,
LIB_NCURSES = 1 << 1,
LIB_CURL = 1 << 2,
LIB_COUNT_,
LIB_HELP,
} lib_flags_t;
typedef struct {
bool GNU;
bool git;
bool clang_format;
bool use_cpp;
} flags_t;
typedef struct { typedef struct {
libmap_t libraries;
licence_t licence; licence_t licence;
flag_t flags;
char *project; char *project;
char *name; char *name;
lib_flags_t libraries;
flags_t flag;
} manifest_t; } manifest_t;
#define HAS_LIBRARY(libs, lib) ((libs) & (lib))
#define ADD_LIBRARY(libs, lib) ((libs) |= (lib))
#define REMOVE_LIBRARY(libs, lib) ((libs) &= ~(lib))
int create_project(manifest_t manifest); int create_project(manifest_t manifest);
int mkdir_p(const char *path); int mkdir_p(const char *path);
int create_file_with_content(const char *path, const char *format, ...); int cfprintf(const char *path, const char *format, ...);
#endif // YAIT_H #endif // YAIT_H

View File

@@ -10,10 +10,9 @@
#ifndef CONTENTS_H #ifndef CONTENTS_H
#define CONTENTS_H #define CONTENTS_H
#define line(l) l "\n" #define line(ln) ln "\n"
/* README template */ char *readme =
char *readme_template =
line ("%s ( concise description )") line ("%s ( concise description )")
line () line ()
line ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor") line ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor")
@@ -23,8 +22,7 @@ char *readme_template =
line ("fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in") line ("fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in")
line ("culpa qui officia deserunt mollit anim id est laborum."); line ("culpa qui officia deserunt mollit anim id est laborum.");
/* configure script template */ char *configure =
char *configure_template =
line ("#!/bin/sh") line ("#!/bin/sh")
line () line ()
line ("usage() {") line ("usage() {")
@@ -41,7 +39,7 @@ char *configure_template =
line ("exit 0") line ("exit 0")
line ("}") line ("}")
line () line ()
line ("echo () { printf \"%s\\n\" \"$*\" ; }") line ("echo () { printf \"%%s\\n\" \"$*\" ; }")
line ("cmdexists () { type \"$1\" >/dev/null 2>&1 ; }") line ("cmdexists () { type \"$1\" >/dev/null 2>&1 ; }")
line ("trycc () { test -z \"$CC\" && cmdexists \"$1\" && CC=$1 ; }") line ("trycc () { test -z \"$CC\" && cmdexists \"$1\" && CC=$1 ; }")
line () line ()
@@ -59,8 +57,8 @@ char *configure_template =
line ("done") line ("done")
line () line ()
line ("printf \"checking for C compiler... \"") line ("printf \"checking for C compiler... \"")
line ("%s") line ("%%s")
line ("printf \"%s\\n\" \"$CC\"") line ("printf \"%%s\\n\" \"$CC\"")
line () line ()
line ("printf \"checking weather C compiler works... \"") line ("printf \"checking weather C compiler works... \"")
line ("status=\"fail\"") line ("status=\"fail\"")
@@ -69,19 +67,18 @@ char *configure_template =
line ("if output=$($CC $CFLAGS -c -o /dev/null \"$tmpc\" 2>&1) ; then") line ("if output=$($CC $CFLAGS -c -o /dev/null \"$tmpc\" 2>&1) ; then")
line ("printf \"yes\\n\"") line ("printf \"yes\\n\"")
line ("else") line ("else")
line ("printf \"no; %s\\n\" \"$output\"") line ("printf \"no; %%s\\n\" \"$output\"")
line ("exit 1") line ("exit 1")
line ("fi") line ("fi")
line () line ()
line ("printf \"creating config.mak... \"") line ("printf \"creating config.mak... \"")
line ("printf \"PREFIX=%s\\n\" \"$prefix\" > config.mak") line ("printf \"PREFIX=%%s\\n\" \"$prefix\" > config.mak")
line ("printf \"CFLAGS=%s\\n\" \"$CFLAGS\" >> config.mak") line ("printf \"CFLAGS=%%s\\n\" \"$CFLAGS\" >> config.mak")
line ("printf \"LDFLAGS=%s\\n\" \"$LDFLAGS\" >> config.mak") line ("printf \"LDFLAGS=%%s\\n\" \"$LDFLAGS\" >> config.mak")
line ("printf \"CC=%s\\n\" \"$CC\" >> config.mak") line ("printf \"CC=%%s\\n\" \"$CC\" >> config.mak")
line ("printf \"done\\n\""); line ("printf \"done\\n\"");
/* Makefile template */ char *makefile =
char *makefile_template =
line ("prefix = /usr/bin") line ("prefix = /usr/bin")
line () line ()
line ("%s_SRCS := $(wildcard %s/*.c)") line ("%s_SRCS := $(wildcard %s/*.c)")
@@ -127,12 +124,10 @@ char *makefile_template =
line () line ()
line (".PHONY: all clean dist-clean install uninstall"); line (".PHONY: all clean dist-clean install uninstall");
/* .clang-format template */ char *clang_format =
char *clang_format_template =
line ("BasedOnStyle: GNU"); line ("BasedOnStyle: GNU");
/* BSD 3-Clause License template */ char *bsd3_license =
char *bsd3_license_template =
line ("BSD 3-Clause License") line ("BSD 3-Clause License")
line () line ()
line ("Copyright (c) %d, %s") line ("Copyright (c) %d, %s")
@@ -162,16 +157,13 @@ char *bsd3_license_template =
line ("OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE") line ("OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE")
line ("OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."); line ("OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.");
/* MIT License template */ char *mit_license =
char *mit_license_template =
line ("THIS IS THE MIT LICENSE"); line ("THIS IS THE MIT LICENSE");
/* GPLv3 License template */ char *gplv3_license =
char *gplv3_license_template =
line ("THIS IS THE GPLv3 LICENSE"); line ("THIS IS THE GPLv3 LICENSE");
/* config.h template */ char *config_h =
char *config_h_template =
line ("#ifndef CONFIG_H") line ("#ifndef CONFIG_H")
line ("#define CONFIG_H") line ("#define CONFIG_H")
line () line ()
@@ -188,8 +180,7 @@ char *config_h_template =
line () line ()
line ("#endif"); line ("#endif");
/* main.c (non-GNU) template */ char *main_c =
char *main_c_template =
line ("#include <stdio.h>") line ("#include <stdio.h>")
line () line ()
line ("int main(void) {") line ("int main(void) {")
@@ -197,8 +188,7 @@ char *main_c_template =
line (" return 0;") line (" return 0;")
line ("}"); line ("}");
/* main.c (GNU) template */ char *main_c_gnu =
char *main_c_gnu_template =
line ("#include <stdio.h>") line ("#include <stdio.h>")
line ("#include \"standard.h\"") line ("#include \"standard.h\"")
line () line ()
@@ -214,8 +204,7 @@ char *main_c_gnu_template =
line (" return 0;") line (" return 0;")
line ("}"); line ("}");
/* standard.c template */ char *standard_c =
char *standard_c_template =
line ("#include \"standard.h\"") line ("#include \"standard.h\"")
line ("#include \"../config.h\"") line ("#include \"../config.h\"")
line ("#include <stdio.h>") line ("#include <stdio.h>")
@@ -241,8 +230,7 @@ char *standard_c_template =
line (" return HELP_REQUESTED;") line (" return HELP_REQUESTED;")
line ("}"); line ("}");
/* standard.h template */ char *standard_h =
char *standard_h_template =
line ("#ifndef STANDARD_H") line ("#ifndef STANDARD_H")
line ("#define STANDARD_H") line ("#define STANDARD_H")
line () line ()
@@ -250,8 +238,7 @@ char *standard_h_template =
line () line ()
line ("#endif"); line ("#endif");
/* WHATNEXT.md template */ char *what_next =
char *what_next_template =
line ("# What next?") line ("# What next?")
line ("") line ("")
line ("## Steps") line ("## Steps")

View File

@@ -6,9 +6,44 @@
* <https://opensource.org/licence/bsd-3-clause> * <https://opensource.org/licence/bsd-3-clause>
*/ */
#include <unistd.h>
#include <stdio.h>
#include "../include/yait.h" #include "../include/yait.h"
#include "contents.h"
char buffer[BUFSIZ];
int create_project(manifest_t manifest) int create_project(manifest_t manifest)
{ {
mkdir_p(manifest.project);
chdir(manifest.project);
if (manifest.flags.simple) {
cfprintf(
"Makefile",
".POSIX:\nCC ::= gcc\nCFLAGS ::= -Wall --std=c23 -Wpedantic\n\nall: %s",
manifest.project);
cfprintf("README", "%s", manifest.project);
snprintf(buffer, BUFSIZ, "%s.c", manifest.project);
cfprintf(buffer, "");
return 0;
}
cfprintf("Makefile", "");
cfprintf("configure", configure);
cfprintf(".clang-format", "");
cfprintf("README", readme, manifest.name);
cfprintf("src/main.c", "");
snprintf(buffer, BUFSIZ, "include/%s.h", manifest.project);
cfprintf(buffer, "");
snprintf(buffer, BUFSIZ, "man/%s.1", manifest.project);
cfprintf(buffer, "");
cfprintf("doc/WHATNEXT", what_next);
return 0; return 0;
} }

View File

@@ -47,7 +47,7 @@ int mkdir_p(const char *path)
return status; return status;
} }
int create_file_with_content(const char *path, const char *format, ...) int cfprintf(const char *path, const char *format, ...)
{ {
char *dirpath; char *dirpath;
const char *slash = strrchr(path, '/'); const char *slash = strrchr(path, '/');

View File

@@ -10,106 +10,68 @@
#include <getopt.h> #include <getopt.h>
#include <pwd.h> #include <pwd.h>
#define _POSIX_C_SOURCE 200809L // popen extention
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "../config.h"
#include "../include/yait.h" #include "../include/yait.h"
#include "standard.c" #include "standard.h"
#include "util.h"
#define print_option(option, description) \ #define print_option(option, description) \
printf(" %-20s %-20s\n", option, description) fprintf(stderr, " %-20s %-20s\n", option, description)
// clang-format off static void usage(int status)
static void
usage (int status)
{ {
if (status != 0) if (status != 0) {
{ fputs("Try 'yait --help' for more information.\n", stderr);
fprintf (stderr, "Try 'yait --help' for more information.\n"); return;
return; }
}
printf ("Usage: yait [OPTION]... <PATH>\n"); fputs("Usage: yait [OPTION]... <PATH>", stderr);
printf ("Creates a C project with opinionated defaults.\n"); fputs("Creates a C project with opinionated defaults.", stderr);
printf ("When only given the first argument it will detect your name.\n\n"); fputs("When only given the first argument it will detect your name.\n",
printf ("Mandatory arguments to long options are mandatory for short options too\n"); stderr);
print_option ("-l, --licence=NAME", "Set licence (gpl, mit, bsd) [default: bsd]"); fputs("Mandatory arguments to long options are mandatory for short options too",
print_option ("--lib=LIB", "Add a library to the project. You can list libraries with --lib=help."); stderr);
print_option ("--use-cpp", "Uses the CPP language instead of C"); print_option("--posix", "Enable POSIX compliance");
print_option ("--git", "Initialize git repository"); print_option("--git", "Do not inititize git reposity");
print_option ("--GNU", "Adds standard GNU argument parsing to your project"); print_option("--clang", "Add clang-format files and tooling");
printf (" --help display this help text and exit\n"); print_option("-L <licence>", "Set licence");
printf (" --version output version information and exit\n"); print_option("-l <library>", "Add a library");
print_option("-C", "Use C++");
print_option("--GNU",
"Add GNU argument parsing: --version, and --help");
print_option("-S, --simple", "Enable simple mode");
fputs(" --help display this help text and exit", stderr);
fputs(" --version output version information and exit", stderr);
} }
// clang-format on
static int parse_arguments(manifest_t *conf, int argc, char **argv) static int parse_arguments(manifest_t *conf, int argc, char **argv)
{ {
static struct option long_options[] = {
{ "GNU", no_argument, 0, 'g' },
{ "use-cpp", no_argument, 0, 'c' },
{ "git", no_argument, 0, 'i' },
{ "licence", required_argument, 0, 'l' },
{ "lib", required_argument, 0, 'L' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
int opt; int opt;
while ((opt = getopt_long(argc, argv, "gcil:L:h", long_options,
NULL)) != -1) { while ((opt = getopt(argc, argv, "L:l:CS")) != -1) {
switch (opt) { switch (opt) {
case 'g': case 'L':
conf->flag.GNU = true; conf->licence = TOlicence(optarg);
break;
case 'c':
conf->flag.use_cpp = true;
break;
case 'i':
conf->flag.git = true;
break; break;
case 'l': case 'l':
if (strcmp(optarg, "bsd") == 0)
conf->licence = BSD3;
else if (strcmp(optarg, "gpl") == 0)
conf->licence = GPLv3;
else if (strcmp(optarg, "mit") == 0)
conf->licence = MIT;
else {
fprintf(stderr, "Unknown licence: %s\n",
optarg);
exit(EXIT_FAILURE);
}
break; break;
// case 'L': case 'C':
// if (strcmp(optarg, "help")) conf->flags.cc = true;
// fprintf(stderr, "raylib\nncurses\ncurl\n"); break;
// else case 'S':
// ADD_LIBRARY(conf->libraries, TOLibrary(optarg)); conf->flags.simple = true;
// break; break;
case 'h':
usage(0);
exit(0);
default: default:
usage(1); fprintf(stderr, "Usage: %s [--help]\n", argv[0]);
exit(1); return 1;
} }
} }
if (optind >= argc) {
fprintf(stderr, "Missing required path argument\n");
usage(1);
exit(EXIT_FAILURE);
}
conf->project = argv[optind++];
if (optind < argc)
conf->name = argv[optind++];
return 0; return 0;
} }
@@ -145,7 +107,24 @@ int get_name(char **output)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int status; int status;
manifest_t manifest = { 0 }; manifest_t manifest = {
.project = "Project",
.name = "author",
.licence = UNL,
.libraries.ncurses = false,
.libraries.raylib = false,
.libraries.stb = false,
.libraries.uthash = false,
.libraries.linenoise = false,
.flags.posix = false,
.flags.git = true,
.flags.clang = false,
.flags.lib = false,
.flags.cc = false,
.flags.gnu = true,
.flags.simple = false,
};
status = parse_standard_options(usage, argc, argv); status = parse_standard_options(usage, argc, argv);
if (status != 0 && status != HELP_REQUESTED) if (status != 0 && status != HELP_REQUESTED)
@@ -154,14 +133,8 @@ int main(int argc, char **argv)
parse_arguments(&manifest, argc, argv); parse_arguments(&manifest, argc, argv);
if (!manifest.name) { get_name(&manifest.name);
status = get_name(&manifest.name);
if (status != 0 || !manifest.name || manifest.name[0] == '\0') {
fprintf(stderr, "Could not determine user name\n");
return EXIT_FAILURE;
}
}
status = create_project(manifest); status = create_project(manifest);
return status == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
return EXIT_SUCCESS;
} }

View File

@@ -10,11 +10,13 @@
#define COMMIT 0 #define COMMIT 0
#endif #endif
#include "../config.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../config.h"
#include "standard.h"
int parse_standard_options(void (*usage)(int), int argc, char **argv) int parse_standard_options(void (*usage)(int), int argc, char **argv)
{ {
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {

8
src/standard.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef STANDARD_H
#define STANDARD_H
#define HELP_REQUESTED 2
int parse_standard_options(void (*usage)(int), int argc, char **argv);
#endif

14
src/util.c Normal file
View File

@@ -0,0 +1,14 @@
#include <string.h>
#include "util.h"
#include "../include/yait.h"
// clang-format off
licence_t TOlicence(const char *s)
{
if (strcmp(s, "mit")) return MIT;
if (strcmp(s, "gpl")) return GPL;
if (strcmp(s, "bsd")) return BSD;
return UNL;
}
// clang-format on

8
src/util.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef UTIL_H
#define UTIL_H
#include "../include/yait.h"
licence_t TOlicence(const char *s);
#endif