This commit is contained in:
2025-07-20 15:50:48 -04:00
parent 5ea2f16ba9
commit 41cfafbaf0
10 changed files with 221 additions and 66 deletions

View File

@@ -22,10 +22,9 @@ build:
c-out/obj/%.o: yait/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(YAIT): $(YAIT_OBJS)
$(YAIT): $(YAIT_OBJS) $(EMBED_HEADER)
$(CC) $(CFLAGS) -DCOMMIT=$(shell git rev-list --count --all) $^ -o $@
endif
install:
@@ -38,8 +37,10 @@ uninstall:
clean:
rm -rf c-out
rm -f $(EMBED_HEADER)
rm -f $(EMBED_HEADERS)
dist-clean: clean
rm -f config.mak
.PHONY: all clean dist-clean install uninstall build format
.PHONY: all clean dist-clean install uninstall build format gen-file-embeds

6
README
View File

@@ -6,8 +6,4 @@ project files needed for your new C ( maybe C++ ) project. It provides you with
a build system and some basic source files to give you a kick start on your new
project--with optional libraries!
The future of this project may be uncertain--however there are a few features I
for sure want to have.
A --GNU flag that will add basic flag parsing into the project for the
--version and --help flags.
For more detailed documentation vist: <https://vx-clutch.github.io/vxserver.dev/docs/yait.html>

4
config.mak Normal file
View File

@@ -0,0 +1,4 @@
PREFIX=/usr/bin/
CFLAGS=-Wall -Wextra -O2
LDFLAGS=
CC=gcc

3
configure vendored
View File

@@ -37,6 +37,9 @@ trycc cc
trycc clang
printf "%s\n" "$CC"
printf "checking for xxd... "
trycc xxd
printf "checking weather C compiler works... "
status="fail"
tmpc="$(mktemp -d)/test.c"

58
embed/Makefile Normal file
View File

@@ -0,0 +1,58 @@
prefix = /usr/bin
YAIT_SRCS := $(wildcard yait/*.c) $(wildcard core/*.c)
YAIT_OBJS := $(patsubst yait/%.c,c-out/obj/%.o,$(YAIT_SRCS))
YAIT := c-out/bin/yait
-include config.mak
ifeq ($(wildcard config.mak),)
all:
@echo "File config.mak not found, run configure"
@exit 1
else
all: build $(YAIT) $(YAIT_DOC)
build:
mkdir -p c-out/bin
mkdir -p c-out/obj
EMBED_FILES := $(wildcard embed/*)
gen-file-embeds:
@echo "// Generated header with embedded files" > $(EMBED_HEADER)
@echo "#ifndef EMBEDDED_FILES_H" >> $(EMBED_HEADER)
@echo "#define EMBEDDED_FILES_H" >> $(EMBED_HEADER)
@echo "" >> $(EMBED_HEADER)
@for f in $(EMBED_FILES); do \
var=$$(echo $$f | tr './-' '__' | tr '[:lower:]' '[:upper:]'); \
xxd -i $$f | sed "s/^unsigned char/${var}_data/" | sed "s/^unsigned int/${var}_len/" >> $(EMBED_HEADER); \
echo "" >> $(EMBED_HEADER); \
done
@echo "#endif // EMBEDDED_FILES_H" >> $(EMBED_HEADER)
c-out/obj/%.o: yait/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(YAIT): $(YAIT_OBJS)
$(CC) $(CFLAGS) -DCOMMIT=$(shell git rev-list --count --all) $^ -o $@
endif
install:
@echo "NOT IMPL"
exit 1
uninstall:
@echo "NOT IMPL"
exit 1
clean:
rm -rf c-out
dist-clean: clean
rm -f config.mak
.PHONY: all clean dist-clean install uninstall build format gen-file-embeds

56
embed/configure vendored Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
usage() {
cat <<EOF
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.
CC C compiler command [detected]
CFLAGS C compiler flags [-g, ...]
EOF
exit 0
}
echo () { printf "%s\n" "$*" ; }
cmdexists () { type "$1" >/dev/null 2>&1 ; }
trycc () { test -z "$CC" && cmdexists "$1" && CC=$1 ; }
prefix=/usr/bin/
CFLAGS="-Wall -Wextra -O2"
LDFLAGS=
CC=
for arg ; do
case "$arg" in
--help|h) usage ;;
CFLAGS=*) CFLAGS=${arg#*=} ;;
LDFLAGS=*) LDFLAGS=${arg#*=} ;;
esac
done
printf "checking for C compiler... "
trycc gcc
trycc cc
trycc clang
printf "%s\n" "$CC"
printf "checking weather C compiler works... "
status="fail"
tmpc="$(mktemp -d)/test.c"
echo "typedef int x;" > "$tmpc"
if output=$($CC $CFLAGS -c -o /dev/null "$tmpc" 2>&1) ; then
printf "yes\n"
else
printf "no; %s\n" "$output"
exit 1
fi
printf "creating config.mak... "
printf "PREFIX=%s\n" "$prefix" > config.mak
printf "CFLAGS=%s\n" "$CFLAGS" >> config.mak
printf "LDFLAGS=%s\n" "$LDFLAGS" >> config.mak
printf "CC=%s\n" "$CC" >> config.mak
printf "done\n"

View File

@@ -1,42 +0,0 @@
#!/usr/bin/env python3
import argparse
def c_escape_byte(b):
if b == 0x09:
return r'\t'
elif b == 0x0A:
return r'\n'
elif b == 0x0D:
return r'\r'
elif b == 0x5C: # \
return r'\\'
elif b == 0x22: # "
return r'\"'
elif 0x20 <= b <= 0x7E:
return chr(b)
elif b == 0x25: # %
return '%%'
else:
return f'\\x{b:02x}'
def file_to_c_string(filepath):
with open(filepath, 'rb') as f:
content = f.read()
escaped = ''.join(c_escape_byte(b) for b in content)
return f'"{escaped}"'
def main():
parser = argparse.ArgumentParser(
description='Convert file contents to a valid C string literal.')
parser.add_argument('input', help='Path to input file')
args = parser.parse_args()
c_string = file_to_c_string(args.input)
print(c_string)
if __name__ == '__main__':
main()

10
tools/gen-embed-header Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/env bash
files=./embed/*
touch embed_header.h
echo "" > embed_header.h
for f in $files; do
xxd -i >> embed_header.h
done

View File

@@ -25,14 +25,20 @@ typedef enum {
*/
} lib_flags_t;
/* Flag option type struct */
typedef struct {
bool GNU;
bool git;
bool clang_format;
} flags_t;
/* Project configuration structure */
typedef struct {
bool git; /* Whether to initialize git repository */
bool clang_format; /* Whether to create .clang-format file */
licence_t licence; /* License type for the project */
char *project; /* Project name */
char *name; /* Author/creator name */
lib_flags_t libraries; /* Selected libraries (bit field) */
flags_t flag; /* Flags */
} format_t;
/* Default values */

View File

@@ -3,7 +3,6 @@
#include "../core/print.h"
#include "../core/standard.h"
#include "format.h"
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -81,8 +80,11 @@ main (int argc, char **argv)
else
conf.name = DEFAULT_USER_NAME;
}
conf.git = DEFAULT_GIT_INIT;
conf.clang_format = DEFAULT_CLANG_FORMAT;
conf.flag.git = DEFAULT_GIT_INIT;
conf.flag.clang_format = DEFAULT_CLANG_FORMAT;
conf.flag.GNU = true; // debug
conf.licence = DEFAULT_LICENSE;
int result = create_project (conf);
@@ -103,7 +105,7 @@ create_project (format_t fmt)
printfn ("failed to create or enter directory: %s", strerror (err));
return 1;
}
if (fmt.git)
if (fmt.flag.git)
err = system ("git init --quiet");
if (err)
{
@@ -202,7 +204,7 @@ create_project (format_t fmt)
create_file_with_content (
"Makefile",
"prefix = /usr/bin\n\n"
"%s_SRCS := $(wildcard *.c)\n"
"%s_SRCS := $(wildcard %s*.c)\n"
"%s_OBJS := $(patsubst %%.c,c-out/obj/%%.o,$(%s_SRCS))\n\n"
"%s := c-out/bin/%s\n\n"
"-include config.mak\n\n"
@@ -232,15 +234,18 @@ create_project (format_t fmt)
"dist-clean: clean\n"
"\trm -f config.mak\n\n"
".PHONY: all clean dist-clean install uninstall build format\n",
mkfile_name, mkfile_name, mkfile_name, mkfile_name, fmt.project,
mkfile_name, mkfile_name, mkfile_name);
mkfile_name, mkfile_name, mkfile_name, mkfile_name, mkfile_name,
fmt.project, mkfile_name, mkfile_name, mkfile_name);
free (mkfile_name);
if (fmt.clang_format)
if (fmt.flag.clang_format)
create_file_with_content (".clang-format",
"Language: Cpp\nBasedOnStyle: GNU\n");
char *license_line = "";
switch (fmt.licence)
{
case BSD3:
license_line = "License BSD-3-Clause: BSD-3-Clause "
"<https://opensource.org/licence/bsd-3-clause>";
create_file_with_content (
"COPYING",
"BSD 3-Clause License\n\nCopyright (c) %d, "
@@ -274,12 +279,70 @@ create_project (format_t fmt)
default:
break;
}
create_file_with_content ("config.h",
"#ifndef CONFIG_H\n"
"#define CONFIG_H\n\n"
"/* Program information */\n"
"#define PROGRAM \"%s\"\n"
"#define LICENSE_LINE \"%s\"\n"
"#define AUTHORS \"%s\"\n"
"#define VERSION \"pre-alpha\"\n"
"#define YEAR 2025\n\n"
"#endif",
fmt.project, license_line, fmt.name, YEAR);
create_and_enter_directory (fmt.project);
if (!fmt.flag.GNU)
{
create_file_with_content (
"main.c",
"#include <stdio.h>\n\nint main(void) {\n printf(\"%s: Hello "
"%s!\\n\");\n return 0;\n}",
fmt.project ? fmt.project : DEFAULT_PROJECT_NAME,
fmt.name ? fmt.name : "World");
}
else
{
create_file_with_content (
"main.c",
"#include <stdio.h>\n"
"#include \"standard.h\"\n"
"\n"
"void usage(int status) {\nprintf(\"Usage: %s [OPTION...]\\n\")\n}\n"
"\n"
"int main(void) {\n"
"parse_standard_options(NULL, argc, argv);\n"
"printf(\"%s: Hello "
"%s!\\n\");\n return 0;\n}",
fmt.project, fmt.project ? fmt.project : DEFAULT_PROJECT_NAME,
fmt.name ? fmt.name : "World");
}
if (fmt.flag.GNU)
{
create_file_with_content (
"standard.c",
"#include \"standard.h\"\n#include \"../config.h\"\n#include "
"<stdio.h>\n#include <stdlib.h>\n#include "
"<string.h>\n\nint\nparse_standard_options (void (*usage) (int), "
"int argc, char **argv)\n{\n for (int i = 1; i < argc; ++i)\n "
"{\n if (strcmp (argv[i], \"--help\") == 0)\n {\n "
" usage (0);\n exit (EXIT_SUCCESS);\n }\n "
"else if (strcmp (argv[i], \"--version\") == 0)\n {\n "
" printf (\"%%s %%s %%d\\nCopyright (C) %%d %%s.\\n%%s\\nThis is "
"free "
"software: \"\n \"you are free to change and "
"redistribute it.\\nThere is NO \"\n \"WARRNTY, to "
"the extent permitted by law.\\n\",\n PROGRAM, "
"VERSION, COMMIT, YEAR, AUTHORS, LICENSE_LINE);\n exit "
"(EXIT_SUCCESS);\n }\n }\n return HELP_REQUESTED;\n}\n");
create_file_with_content (
"standard.h",
"#ifndef STANDARD_H\n#define STANDARD_H\n\n/**\n * Parse standard "
"command line options (--help, --version)\n * @param usage_func "
"Function pointer to usage display function\n * @param argc "
"Argument count\n * @param argv Argument vector\n * @return 0 on "
"success, 1 if help/version requested, errno on error\n */\nint "
"parse_standard_options(void (*usage_func)(), int argc, char "
"**argv);\n\n#endif\n");
}
return 0;
}