From 41cfafbaf00e52fda1a7fc6d3b67bbb6ced20387 Mon Sep 17 00:00:00 2001 From: vx-clutch Date: Sun, 20 Jul 2025 15:50:48 -0400 Subject: [PATCH] save --- Makefile | 7 ++-- README | 6 +-- config.mak | 4 ++ configure | 3 ++ embed/Makefile | 58 ++++++++++++++++++++++++++ embed/configure | 56 +++++++++++++++++++++++++ tools/file_to_string.py | 42 ------------------- tools/gen-embed-header | 10 +++++ yait/format.h | 10 ++++- yait/main.c | 91 ++++++++++++++++++++++++++++++++++------- 10 files changed, 221 insertions(+), 66 deletions(-) create mode 100644 config.mak create mode 100644 embed/Makefile create mode 100755 embed/configure delete mode 100755 tools/file_to_string.py create mode 100755 tools/gen-embed-header diff --git a/Makefile b/Makefile index bc387a6..18346df 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README b/README index 11b9287..8a0f625 100644 --- a/README +++ b/README @@ -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: diff --git a/config.mak b/config.mak new file mode 100644 index 0000000..d6ba4f4 --- /dev/null +++ b/config.mak @@ -0,0 +1,4 @@ +PREFIX=/usr/bin/ +CFLAGS=-Wall -Wextra -O2 +LDFLAGS= +CC=gcc diff --git a/configure b/configure index b75b922..6222641 100755 --- a/configure +++ b/configure @@ -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" diff --git a/embed/Makefile b/embed/Makefile new file mode 100644 index 0000000..f925712 --- /dev/null +++ b/embed/Makefile @@ -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 diff --git a/embed/configure b/embed/configure new file mode 100755 index 0000000..b75b922 --- /dev/null +++ b/embed/configure @@ -0,0 +1,56 @@ +#!/bin/sh + +usage() { +cat </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" diff --git a/tools/file_to_string.py b/tools/file_to_string.py deleted file mode 100755 index c293bb8..0000000 --- a/tools/file_to_string.py +++ /dev/null @@ -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() diff --git a/tools/gen-embed-header b/tools/gen-embed-header new file mode 100755 index 0000000..b001ece --- /dev/null +++ b/tools/gen-embed-header @@ -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 diff --git a/yait/format.h b/yait/format.h index c6bc4f3..f07a6a0 100644 --- a/yait/format.h +++ b/yait/format.h @@ -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 */ diff --git a/yait/main.c b/yait/main.c index 137ade5..b22bc7e 100644 --- a/yait/main.c +++ b/yait/main.c @@ -3,7 +3,6 @@ #include "../core/print.h" #include "../core/standard.h" #include "format.h" -#include #include #include #include @@ -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 " + ""; 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); - create_file_with_content ( - "main.c", - "#include \n\nint main(void) {\n printf(\"%s: Hello " - "%s!\\n\");\nreturn 0;\n}", - fmt.project ? fmt.project : DEFAULT_PROJECT_NAME, - fmt.name ? fmt.name : "World"); + if (!fmt.flag.GNU) + { + create_file_with_content ( + "main.c", + "#include \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 \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 " + "\n#include \n#include " + "\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; }