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:
Add: ["-std=c2x"]
Add: ["--std=c2x", "-xc"]

View File

@@ -12,7 +12,7 @@ all:
@exit 1
else
all: build $(YAIT) $(YAIT_DOC)
all: build $(YAIT)
build:
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 YEAR 2025
/* Custom error codes */
#define HELP_REQUESTED 2
#define ERROR_MEMORY_ALLOCATION 3
#define ERROR_DIRECTORY_CREATION 4
#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 ; }
prefix=/usr/bin/
CFLAGS="-Wall -Wextra -O2 --std=c23"
CFLAGS="-Wall -Wextra -O2 --std=c23 -Wpedantic"
LDFLAGS=
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
#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 {
BSD3,
GPLv3,
MIT,
UNLICENCE,
LICENCE_HELP,
GPL,
BSD,
UNL,
} 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 {
libmap_t libraries;
licence_t licence;
flag_t flags;
char *project;
char *name;
lib_flags_t libraries;
flags_t flag;
} 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 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

View File

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

View File

@@ -6,9 +6,44 @@
* <https://opensource.org/licence/bsd-3-clause>
*/
#include <unistd.h>
#include <stdio.h>
#include "../include/yait.h"
#include "contents.h"
char buffer[BUFSIZ];
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;
}

View File

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

View File

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

View File

@@ -10,11 +10,13 @@
#define COMMIT 0
#endif
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../config.h"
#include "standard.h"
int parse_standard_options(void (*usage)(int), int argc, char **argv)
{
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