save
This commit is contained in:
BIN
c-out/bin/yait
Executable file
BIN
c-out/bin/yait
Executable file
Binary file not shown.
BIN
c-out/obj/main.o
BIN
c-out/obj/main.o
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
PREFIX=/usr/bin/
|
PREFIX=/usr/bin/
|
||||||
CFLAGS=-Wall -Wextra -O2
|
CFLAGS=-Wall -Wextra -g
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
CC=gcc
|
CC=clang
|
||||||
|
|||||||
@@ -4,32 +4,9 @@
|
|||||||
|
|
||||||
make dist-clean
|
make dist-clean
|
||||||
|
|
||||||
lint_file() {
|
|
||||||
local output
|
|
||||||
output=$(clang-tidy "$1" 2>&1 | grep -v -E 'Error while trying to load a compilation database|No compilation database found|fixed-compilation-database:|json-compilation-database:|Running without flags.')
|
|
||||||
if [[ -n "$output" ]]; then
|
|
||||||
echo "[LINT] $1:"
|
|
||||||
echo "$output"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
whitespace_cleanup() {
|
|
||||||
sed -i 's/[ \t]*$//' "$1"
|
|
||||||
awk 'BEGIN{ORS=""} {print $0 "\n"} END{}' "$1" > "$1.tmp" && mv "$1.tmp" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
comment_check() {
|
|
||||||
if grep -n -E 'TODO|FIXME' "$1"; then
|
|
||||||
echo "[WARN] $1 contains TODO/FIXME comments."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
process_file() {
|
process_file() {
|
||||||
clang-format -i "$1"
|
clang-format -i "$1"
|
||||||
tools/check_header_footer "$1"
|
tools/check_header_footer "$1"
|
||||||
lint_file "$1"
|
|
||||||
whitespace_cleanup "$1"
|
|
||||||
comment_check "$1"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $# -gt 0 ]]; then
|
if [[ $# -gt 0 ]]; then
|
||||||
|
|||||||
44
tools/check_header
Executable file
44
tools/check_header
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/env bash
|
||||||
|
|
||||||
|
# Usage: ./check_header
|
||||||
|
|
||||||
|
if pwd | grep -q tools; then
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
|
||||||
|
files=$(find yait \( -name '*.c' -o -name '*.h' \))
|
||||||
|
files+=" "
|
||||||
|
files+=$(find core \( -name '*.c' -o -name '*.h' \))
|
||||||
|
files+=" $(find . -maxdepth 1 -type f)"
|
||||||
|
|
||||||
|
ignore="README COPYING .clang-format config.mak"
|
||||||
|
|
||||||
|
if [ -z "$files" ]; then
|
||||||
|
echo "No files found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
missing=""
|
||||||
|
|
||||||
|
for file in $files; do
|
||||||
|
if echo "$ignore" | grep -qw "$(basename "$file")"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo -ne "$file... "
|
||||||
|
if grep -q "Copyright (C)" "$file"; then
|
||||||
|
echo -e "\033[1;32mOK\033[0m"
|
||||||
|
else
|
||||||
|
echo -e "\033[0;31mFAIL\033[0m"
|
||||||
|
missing+="$file "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$missing" = "" ]; then
|
||||||
|
echo -e "\033[1;32mAll checks pass.\033[0m"
|
||||||
|
else
|
||||||
|
echo -e "\033[0;31mThe follwing files are missing copyright information.\033[0m"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in $missing; do
|
||||||
|
echo " - $file"
|
||||||
|
done
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Usage: ./ensure_header_footer.sh filename
|
|
||||||
|
|
||||||
FILE="$1"
|
|
||||||
HEADER=$(cat <<'EOF'
|
|
||||||
// Copyright (C) 2025 vx_clutch ( owestness@gmail.com )
|
|
||||||
// See end of file for extended copyright information.
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
HEADER+=$'\n'
|
|
||||||
FOOTER=$(cat <<'EOF'
|
|
||||||
|
|
||||||
/* yait is yet another init tool.
|
|
||||||
* Copyright (C) 2025 vx-clutch
|
|
||||||
*
|
|
||||||
* This file is part of yait.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions, and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions, and the following disclaimer in the documentation or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of vx-clutch nor the names of its contributors may be
|
|
||||||
* used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ -z "$FILE" ]]; then
|
|
||||||
echo "Usage: $0 <filename>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f "$FILE" ]]; then
|
|
||||||
echo "Error: File '$FILE' does not exist."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
TMP_FILE="$(mktemp)"
|
|
||||||
|
|
||||||
read -r FIRST_LINE < "$FILE"
|
|
||||||
if [[ "$FIRST_LINE" != "$HEADER" ]]; then
|
|
||||||
echo "$HEADER" > "$TMP_FILE"
|
|
||||||
cat "$FILE" >> "$TMP_FILE"
|
|
||||||
mv "$TMP_FILE" "$FILE"
|
|
||||||
else
|
|
||||||
rm "$TMP_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$(tail -n 1 "$FILE")" != "$FOOTER" ]]; then
|
|
||||||
echo "$FOOTER" >> "$FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Checked '$FILE' for header/footer."
|
|
||||||
237
yait/main.c
237
yait/main.c
@@ -1,9 +1,12 @@
|
|||||||
|
// Usage: yait [OPTION]... [PROJECT] (NAME)
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../core/file.h"
|
#include "../core/file.h"
|
||||||
#include "../core/print.h"
|
#include "../core/print.h"
|
||||||
#include "../core/standard.h"
|
#include "../core/standard.h"
|
||||||
#include "contents.h"
|
#include "contents.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
#include <errno.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -21,14 +24,39 @@
|
|||||||
#define print_option(option, description) \
|
#define print_option(option, description) \
|
||||||
printf (" %-20s %-20s\n", option, description)
|
printf (" %-20s %-20s\n", option, description)
|
||||||
|
|
||||||
|
#define on_error(msg, code) \
|
||||||
|
if (err) \
|
||||||
|
{ \
|
||||||
|
printfn (msg ": %s", strerror (err)); \
|
||||||
|
return code; \
|
||||||
|
}
|
||||||
|
|
||||||
int create_license_if_needed(format_t);
|
#ifdef DEBUG
|
||||||
|
#define debug(fmt, ...) \
|
||||||
|
fprintf (stderr, "\e[0;32m[%8d]\e[0;33m " fmt "\e[0m\n", __LINE__, \
|
||||||
|
##__VA_ARGS__)
|
||||||
|
#define debugc(fmt, ...) \
|
||||||
|
fprintf (stderr, "\e[0;32m[%8d]\e[0;33m " fmt "...\e[0m", __LINE__, \
|
||||||
|
##__VA_ARGS__)
|
||||||
|
#define done fprintf(stderr, "done.\n")
|
||||||
|
#else
|
||||||
|
#define debug(fmt, ...)
|
||||||
|
#define debugc(fmt, ...)
|
||||||
|
#define done
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// int create_license_if_needed (format_t);
|
||||||
|
// int get_license_line_and_create_license (format_t, char **);
|
||||||
|
int create_configure ();
|
||||||
int create_makefile (format_t);
|
int create_makefile (format_t);
|
||||||
int create_project (format_t);
|
int create_project (format_t);
|
||||||
int get_license_line_and_create_license(format_t, char**);
|
int generate_source_files (format_t);
|
||||||
int maybe_apply_clang_format (format_t);
|
int maybe_apply_clang_format (format_t);
|
||||||
|
int reset_path_ ();
|
||||||
int sanitize (format_t *);
|
int sanitize (format_t *);
|
||||||
int setup_git_and_permissions(format_t);
|
int setup_git (format_t);
|
||||||
|
|
||||||
|
int depth;
|
||||||
|
|
||||||
void
|
void
|
||||||
usage (int status)
|
usage (int status)
|
||||||
@@ -42,8 +70,10 @@ usage(int status)
|
|||||||
printf ("Usage: yait [OPTION]... [PROJECT] (NAME)\n");
|
printf ("Usage: yait [OPTION]... [PROJECT] (NAME)\n");
|
||||||
printf ("Creates a C project with opinionated defaults.\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 ("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");
|
printf ("Mandatory arguments to long options are mandatory for short "
|
||||||
print_option("-l, --license=NAME", "Set license (gpl, mit, bsd) [default: gpl]");
|
"options too\n");
|
||||||
|
print_option ("-l, --license=NAME",
|
||||||
|
"Set license (gpl, mit, bsd) [default: bsd]");
|
||||||
print_option ("--use-cpp", "Uses the CPP language instead of C");
|
print_option ("--use-cpp", "Uses the CPP language instead of C");
|
||||||
print_option ("--git", "Initialize git repository");
|
print_option ("--git", "Initialize git repository");
|
||||||
print_option ("--GNU", "Adds standard GNU argument parsing to your project");
|
print_option ("--GNU", "Adds standard GNU argument parsing to your project");
|
||||||
@@ -69,9 +99,10 @@ main(int argc, char **argv)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
format_t conf;
|
format_t conf = { 0 };
|
||||||
conf.project = argv[0];
|
|
||||||
conf.name = (argc > 2) ? argv[1] : NULL;
|
conf.project = argv[0]; // fix: project name is argv[1]
|
||||||
|
conf.name = (argc > 1) ? argv[1] : NULL; // fix: name is optional, at argv[2]
|
||||||
|
|
||||||
if (!conf.name)
|
if (!conf.name)
|
||||||
{
|
{
|
||||||
@@ -82,9 +113,7 @@ main(int argc, char **argv)
|
|||||||
conf.flag.git = DEFAULT_GIT_INIT;
|
conf.flag.git = DEFAULT_GIT_INIT;
|
||||||
conf.flag.clang_format = DEFAULT_CLANG_FORMAT;
|
conf.flag.clang_format = DEFAULT_CLANG_FORMAT;
|
||||||
conf.licence = DEFAULT_LICENSE;
|
conf.licence = DEFAULT_LICENSE;
|
||||||
#ifdef DEBUG
|
|
||||||
system(strcat("rm -rf ", conf.project));
|
|
||||||
#endif
|
|
||||||
return create_project (conf);
|
return create_project (conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,47 +122,50 @@ create_project(format_t fmt)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = create_and_enter_directory(fmt.project);
|
debugc ("sanitize... ");
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
printfn("failed to create or enter directory: %s", strerror(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sanitize (&fmt);
|
err = sanitize (&fmt);
|
||||||
if (err)
|
on_error ("failed to sanitize format", err);
|
||||||
{
|
done;
|
||||||
printfn("failed to sanitize format: %s", strerror(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = create_license_if_needed(fmt);
|
debugc ("take %s", fmt.project);
|
||||||
if (err)
|
err = create_and_enter_directory (fmt.project);
|
||||||
{
|
on_error ("failed to create or enter directory", err);
|
||||||
printfn("failed to create license: %s", strerror(err));
|
done;
|
||||||
return err;
|
depth = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
// debug ("create licenseing");
|
||||||
|
// err = create_license_if_needed (fmt);
|
||||||
|
// on_error ("failed to create license", err);
|
||||||
|
|
||||||
|
debugc ("create makefile");
|
||||||
err = create_makefile (fmt);
|
err = create_makefile (fmt);
|
||||||
if (err)
|
on_error ("failed to create Makefile", err);
|
||||||
{
|
done;
|
||||||
printfn("failed to create Makefile: %s", strerror(err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = setup_git_and_permissions(fmt);
|
debug ("setup git");
|
||||||
|
err = setup_git (fmt);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
printfn ("warning: git initialization failed: %s", strerror (err));
|
printfn ("warning: git initialization failed: %s", strerror (err));
|
||||||
// continue even if git fails
|
|
||||||
}
|
|
||||||
|
|
||||||
|
debug ("create .clang-format");
|
||||||
err = maybe_apply_clang_format (fmt);
|
err = maybe_apply_clang_format (fmt);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
printfn ("warning: clang-format setup failed: %s", strerror (err));
|
printfn ("warning: clang-format setup failed: %s", strerror (err));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define reset_path reset_path_ ()
|
||||||
|
int
|
||||||
|
reset_path_ ()
|
||||||
|
{
|
||||||
|
while (depth != 0)
|
||||||
|
{
|
||||||
|
if (chdir ("..") != 0)
|
||||||
|
return errno;
|
||||||
|
else
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,33 +174,38 @@ sanitize(format_t *fmt)
|
|||||||
{
|
{
|
||||||
if (!fmt->name)
|
if (!fmt->name)
|
||||||
fmt->name = DEFAULT_USER_NAME;
|
fmt->name = DEFAULT_USER_NAME;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
// int
|
||||||
create_license_if_needed(format_t fmt)
|
// create_license_if_needed (format_t fmt)
|
||||||
{
|
// {
|
||||||
char *license_line = NULL;
|
// char *license_line = NULL;
|
||||||
return get_license_line_and_create_license(fmt, &license_line);
|
// return get_license_line_and_create_license (fmt, &license_line);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
int
|
// int
|
||||||
get_license_line_and_create_license(format_t fmt, char **license_line_buffer)
|
// get_license_line_and_create_license (format_t fmt, char
|
||||||
{
|
// **license_line_buffer)
|
||||||
switch (fmt.licence)
|
// {
|
||||||
{
|
// switch (fmt.licence)
|
||||||
case BSD3:
|
// {
|
||||||
*license_line_buffer =
|
// case BSD3:
|
||||||
"License BSD-3-Clause: BSD-3-Clause <https://opensource.org/licence/bsd-3-clause>";
|
// *license_line_buffer = "License BSD-3-Clause: BSD-3-Clause "
|
||||||
return create_file_with_content("COPYING", bsd3_license_template, YEAR, fmt.name);
|
// "<https://opensource.org/license/bsd-3-clause/>";
|
||||||
|
// return create_file_with_content ("COPYING", bsd3_license_template,
|
||||||
case GPLv3:
|
// YEAR,
|
||||||
default:
|
// fmt.name);
|
||||||
*license_line_buffer = "License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>";
|
//
|
||||||
return create_file_with_content("COPYING", gplv3_license_template, YEAR, fmt.name);
|
// case GPLv3:
|
||||||
}
|
// default:
|
||||||
}
|
// *license_line_buffer = "License GPLv3: GNU GPL version 3 "
|
||||||
|
// "<https://www.gnu.org/licenses/gpl-3.0.html>";
|
||||||
|
// return create_file_with_content ("COPYING", gplv3_license_template,
|
||||||
|
// YEAR,
|
||||||
|
// fmt.name);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
int
|
int
|
||||||
maybe_apply_clang_format (format_t fmt)
|
maybe_apply_clang_format (format_t fmt)
|
||||||
@@ -176,20 +213,86 @@ maybe_apply_clang_format(format_t fmt)
|
|||||||
if (!fmt.flag.clang_format)
|
if (!fmt.flag.clang_format)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const char *clang_fmt = "BasedOnStyle: LLVM\nIndentWidth: 2\nUseTab: Never\n";
|
reset_path;
|
||||||
|
|
||||||
|
char *clang_fmt = "BasedOnStyle: LLVM\nIndentWidth: 2\nUseTab: Never\n";
|
||||||
return create_file_with_content (".clang-format", clang_fmt, 0, NULL);
|
return create_file_with_content (".clang-format", clang_fmt, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
setup_git_and_permissions(format_t fmt)
|
setup_git (format_t fmt)
|
||||||
{
|
{
|
||||||
if (!fmt.flag.git)
|
if (!fmt.flag.git)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
reset_path;
|
||||||
|
|
||||||
int err = system ("git init --quiet");
|
int err = system ("git init --quiet");
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
printfn ("failed on git initialize: %s", strerror (err));
|
printfn ("failed on git initialize: %s", strerror (err));
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
create_makefile (format_t fmt)
|
||||||
|
{
|
||||||
|
char *makefile_name = strdup (fmt.project);
|
||||||
|
if (!makefile_name)
|
||||||
|
{
|
||||||
|
printfn ("fatal: out of memory");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char *p = makefile_name; *p; ++p)
|
||||||
|
if (*p >= 'a' && *p <= 'z')
|
||||||
|
*p -= 32;
|
||||||
|
|
||||||
|
reset_path;
|
||||||
|
|
||||||
|
create_file_with_content ("Makefile", makefile_template, makefile_name,
|
||||||
|
makefile_name, makefile_name, makefile_name,
|
||||||
|
makefile_name, makefile_name, fmt.project,
|
||||||
|
makefile_name);
|
||||||
|
|
||||||
|
free (makefile_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
create_configure ()
|
||||||
|
{
|
||||||
|
reset_path;
|
||||||
|
|
||||||
|
create_file_with_content ("configure", configure_template);
|
||||||
|
int err = system ("chmod +x configure");
|
||||||
|
if (err)
|
||||||
|
printfn ("error: %s", strerror (err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
generate_source_files (format_t fmt)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
debug ("take %s/%s", fmt.project, fmt.project);
|
||||||
|
err = create_and_enter_directory (fmt.project);
|
||||||
|
on_error ("failed to create or enter directory", err);
|
||||||
|
|
||||||
|
if (fmt.flag.GNU)
|
||||||
|
{
|
||||||
|
debug ("GNU flag source branch");
|
||||||
|
|
||||||
|
create_file_with_content ("main.c", main_c_gnu_template);
|
||||||
|
|
||||||
|
goto atexit_clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug ("default sourcebranch");
|
||||||
|
create_file_with_content ("main.c", main_c_template);
|
||||||
|
|
||||||
|
atexit_clean:
|
||||||
|
reset_path;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user