From 871ea8ae1dada3caf90aa6b82c6c6fd8fb08f970 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 00:55:22 +0900 Subject: [PATCH 01/59] feat: a brand new hhss! --- .gitignore | 4 +- Makefile | 176 +++------- common/array.adt.c | 62 ++++ common/array.adt.h | 27 ++ common/array.adt.internals.h | 34 ++ common/colorcodes.h | 20 ++ common/fatal.c | 38 +++ common/fatal.h | 29 ++ common/fatal.internals.h | 14 + common/loadfile.c | 41 +++ common/loadfile.h | 25 ++ common/loadfile.internals.h | 13 + common/readline.c | 49 +++ common/readline.h | 14 + common/readline.internals.h | 15 + common/strutils.c | 62 ++++ common/strutils.h | 18 ++ common/strutils.internals.h | 12 + {yandere/c => common}/utils.c | 1 + {yandere/c => common}/utils.h | 12 +- common/utils.internals.h | 12 + common/wrappers.c | 81 +++++ {yandere/c => common}/wrappers.h | 15 +- common/wrappers.internals.h | 12 + defs.mk | 30 +- hhss/c/.gitignore | 3 +- hhss/c/Makefile | 40 ++- hhss/c/argv1parse.c | 21 ++ hhss/c/argv1parse.h | 9 + hhss/c/argv1parse.internals.h | 13 + hhss/c/dbload.c | 12 + hhss/c/dbload.h | 14 + hhss/c/dbload.internals.h | 18 ++ hhss/c/debug.c | 108 +++++++ hhss/c/debug.h | 18 ++ hhss/c/debug.internals.h | 12 + hhss/c/dtdbparse.c | 51 +++ hhss/c/dtdbparse.h | 16 + hhss/c/dtdbparse.internals.h | 15 + hhss/c/global.h | 24 ++ hhss/c/hhss.c | 537 +++---------------------------- hhss/c/hhss.internals.h | 39 +++ hhss/c/lex.c | 92 ++++++ hhss/c/lex.h | 29 ++ hhss/c/lex.internals.h | 28 ++ hhss/c/parse.c | 146 +++++++++ hhss/c/parse.h | 28 ++ hhss/c/parse.internals.h | 36 +++ hhss/c/prelex.c | 33 ++ hhss/c/prelex.h | 15 + hhss/c/prelex.internals.h | 13 + hhss/c/replace.c | 90 ++++++ hhss/c/replace.h | 14 + hhss/c/replace.internals.h | 31 ++ hhss/c/rtdbparse.c | 202 ++++++++++++ hhss/c/rtdbparse.h | 17 + hhss/c/rtdbparse.internals.h | 50 +++ hhss/dat.db | 98 ++++++ hhss/rt.db | 44 +++ hhss/usr.dat | 2 +- test/.gitignore | 3 +- vars.mk | 57 ++++ yandere/c/.gitignore | 3 +- yandere/c/Makefile | 35 +- yandere/c/colorcodes.h | 7 - yandere/c/fatal.c | 28 -- yandere/c/fatal.h | 27 -- yandere/c/global.h | 3 - yandere/c/noise.h | 1 + yandere/c/wrappers.c | 39 --- yandere/c/yandere.types.h | 1 + 71 files changed, 2160 insertions(+), 778 deletions(-) create mode 100644 common/array.adt.c create mode 100644 common/array.adt.h create mode 100644 common/array.adt.internals.h create mode 100644 common/colorcodes.h create mode 100644 common/fatal.c create mode 100644 common/fatal.h create mode 100644 common/fatal.internals.h create mode 100644 common/loadfile.c create mode 100644 common/loadfile.h create mode 100644 common/loadfile.internals.h create mode 100644 common/readline.c create mode 100644 common/readline.h create mode 100644 common/readline.internals.h create mode 100644 common/strutils.c create mode 100644 common/strutils.h create mode 100644 common/strutils.internals.h rename {yandere/c => common}/utils.c (94%) rename {yandere/c => common}/utils.h (57%) create mode 100644 common/utils.internals.h create mode 100644 common/wrappers.c rename {yandere/c => common}/wrappers.h (53%) create mode 100644 common/wrappers.internals.h create mode 100644 hhss/c/argv1parse.c create mode 100644 hhss/c/argv1parse.h create mode 100644 hhss/c/argv1parse.internals.h create mode 100644 hhss/c/dbload.c create mode 100644 hhss/c/dbload.h create mode 100644 hhss/c/dbload.internals.h create mode 100644 hhss/c/debug.c create mode 100644 hhss/c/debug.h create mode 100644 hhss/c/debug.internals.h create mode 100644 hhss/c/dtdbparse.c create mode 100644 hhss/c/dtdbparse.h create mode 100644 hhss/c/dtdbparse.internals.h create mode 100644 hhss/c/global.h create mode 100644 hhss/c/hhss.internals.h create mode 100644 hhss/c/lex.c create mode 100644 hhss/c/lex.h create mode 100644 hhss/c/lex.internals.h create mode 100644 hhss/c/parse.c create mode 100644 hhss/c/parse.h create mode 100644 hhss/c/parse.internals.h create mode 100644 hhss/c/prelex.c create mode 100644 hhss/c/prelex.h create mode 100644 hhss/c/prelex.internals.h create mode 100644 hhss/c/replace.c create mode 100644 hhss/c/replace.h create mode 100644 hhss/c/replace.internals.h create mode 100644 hhss/c/rtdbparse.c create mode 100644 hhss/c/rtdbparse.h create mode 100644 hhss/c/rtdbparse.internals.h create mode 100644 hhss/dat.db create mode 100644 hhss/rt.db create mode 100644 vars.mk delete mode 100644 yandere/c/colorcodes.h delete mode 100644 yandere/c/fatal.c delete mode 100644 yandere/c/fatal.h delete mode 100644 yandere/c/wrappers.c diff --git a/.gitignore b/.gitignore index 12435b4..9e2b399 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ **/.vs .vscode/ -bin/ -__record__ \ No newline at end of file +common/*.o +common/*.d diff --git a/Makefile b/Makefile index 7f2f63d..b2cb3a6 100644 --- a/Makefile +++ b/Makefile @@ -1,159 +1,69 @@ -## Includes +## Includes ## +include vars.mk include defs.mk -## Settings -SHELL := /bin/sh -CC := gcc -# -g for debug -CFLAGS := -O -Wall -W -pedantic -g - -# deletes the default value and registers only necessary ones. -# (Refer to the chapter 16.1 in GNU make manual.) +## Targets ## .SUFFIXES: .SUFFIXES: .c .o .h -# cstr = Color STRing -define cstr -"\033[$1m$2\033[0m" -endef -name_str = $(call cstr,38;5;49;1,$1) -build_completed_str = $(call cstr,48;5;222;30, [ BUILD COMPLETED ] ) -inst_done_str = $(call cstr,48;5;150;30, [ INSTALL DONE ] ) -warn_str = $(call cstr,48;5;88;37, [ WARNING ] ) -notice_str = $(call cstr,48;5;152;30, [ NOTICE ] ) - -## Compilations -project := Utils -programs := btn hd hhss nsy nsy2 yandere -_programs := $(foreach program,$(programs),./$(program)/c/$(program)) -default_goal := __record__ -tempfile := __Utils_tempfile__ - -define is_recent -$(if $1,\ - @echo $(notice_str) "The following programs have made a successful build:"$\ - $(call name_str,$(foreach program,$1,\n\t$(program))),\ - @echo $(notice_str) All programs are already up-to-date!!) -endef - -### This is the default goal. ### -$(default_goal): $(tempfile) $(_programs) - $(call is_recent,$(file < $(tempfile))) - rm $(tempfile) - touch $(default_goal) - -.PHONY: $(tempfile) -$(tempfile): - touch $(tempfile) - -define program_template -$1_path := ./$1/c -$1_name := $$($1_path)/$1 -$1_sources := $$(wildcard $$($1_path)/*.c) -$1_objects := $$($1_sources:.c=.o) -all_objects += $$($1_objects) - -.PHONY: $1 -# This rule is for the command `make program-names...`. -$1: $$($1_name) - if ! rm $(tempfile); then \ - echo $(notice_str) $(call name_str,$1) is already up-to-date!; \ - fi \ +.PHONY: all install uninstall clean cleanall help -$$($1_name): $$($1_objects) - $(CC) $$^ $(CFLAGS) -o $$@ - $$(file >> $$(tempfile),$1) - @echo $(build_completed_str) $(call name_str,$$@)"\n" -endef -all_objects = +## Default Goal ## +all: $(TARGETS) -$(foreach program,$(programs),$(eval $(call program_template,$(program)))) +$(TARGETS): + $(MAKE) -C $@/c TARGET=$@ DIR_DATA=$(DIR_DATA) + @echo $(STR_BUILD_DONE) $(call STR_NAME,$@) -# hhss.c requires a special care since it needs INSTPATH -inst_prefix := /usr/local -datadir := $(inst_prefix)/share/hhss -$(hhss_path)/hhss.o: $(hhss_path)/hhss.c - $(CC) $(CFLAGS) -DINSTPATH='"$(datadir)"' -o $@ -c $< +## Test Program ## +$(TEST): $(DIR_TEST)/$(TEST_MAKER) + cd $(DIR_TEST) && ./$(TEST_MAKER) $(DIR_TESTCASE)/$(testcase) + $(DIR_TEST)/$(TEST) $(DIR_BIN)/$(prog) -## Auxiliary Tasks -.PHONY: install -INSTALL := install -INSTALL_PROGRAM := $(INSTALL) -INSTALL_DATA := $(INSTALL) -m 644 - -bindir := $(inst_prefix)/bin -man1dir := $(inst_prefix)/share/man/man1 -man7dir := $(inst_prefix)/share/man/man7 - -hhss_data := hsr usr - -program_installation_cmd := $(INSTALL_PROGRAM) ./$$i/c/$$i $(bindir) -data_installation_cmd := $(INSTALL_DATA) ./hhss/$$i $(datadir) +$(DIR_TEST)/$(TEST_MAKER): $(DIR_TEST)/$(TEST_MAKER).o + $(CC) $^ $(CFLAGS) -o $@ +## Auxiliary Tasks ## install: - test -d $(bindir) || (mkdir $(bindir)) - test -d $(datadir) || (mkdir $(datadir)) - test -d $(man1dir) || (mkdir $(man1dir)) - test -d $(man7dir) || (mkdir $(man7dir)) - $(call installation_template,$(programs),$(program_installation_cmd)) - $(call installation_template,$(hhss_data:%=%.dat),$(data_installation_cmd)) - $(call inst_man_t,$(programs),$(INSTALL) -m 644 $$i/$$i.1 $(man1dir),1) - $(call inst_man_t,$(project),$(INSTALL) -m 644 $$i.7 $(man7dir),7) - -.PHONY: test -test_path := ./test -# It is necessary to assign values to these variables from the command line. -testcase = -prog = + test -d $(DIR_BIN) || mkdir -p $(DIR_BIN) + test -d $(DIR_DATA)/$(HHSS) || mkdir -p $(DIR_DATA)/$(HHSS) + test -d $(DIR_MAN1) || mkdir -p $(DIR_MAN1) + test -d $(DIR_MAN7) || mkdir -p $(DIR_MAN7) + $(call TPL_INST_PROG,$(TARGETS),$(CMD_INSTALL_PROG)) + $(call TPL_INST_PROG,$(HHSS_DATA),$(CMD_INSTALL_DATA)) + $(call TPL_INST_MAN,$(TARGETS),$(CMD_INSTALL_MAN1),1) + $(call TPL_INST_MAN,$(PROJECT),$(CMD_INSTALL_MAN7),7) -test: $(test_path)/test_maker - cd $(test_path) && ./test_maker ./.test/$(testcase) - $(test_path)/test $(bindir)/$(prog) - -$(test_path)/test_maker: $(test_path)/test_maker.o - $(CC) $^ $(CFLAGS) -o $(test_path)/test_maker - -.PHONY: uninstall uninstall: - rm -f $(foreach program,$(programs),$(bindir)/$(program)) - rm -rf $(datadir) - rm -f $(foreach program,$(programs),$(man1dir)/$(program).1) - rm -f $(man7dir)/$(project).7 + rm -f $(foreach target,$(TARGETS),$(DIR_BIN)/$(target)) + rm -rf $(DIR_DATA)/$(HHSS) + rm -f $(foreach target,$(TARGETS),$(DIR_MAN1)/$(target).1) + rm -f $(DIR_MAN7)/$(PROJECT).7 -.PHONY: clean clean: - rm -f $(all_objects) - rm -f $(_programs) + find . -name "*.o" -delete + find . -name "*.d" -delete + rm -f $(foreach target,$(TARGETS),$(target)/c/$(target)) -.PHONY: cleanall cleanall: uninstall clean - rm -f $(foreach file,test_maker.o test test_maker,$(test_path)/$(file)) + rm -f $(foreach file,$(TEST) $(TEST_MAKER),$(DIR_TEST)/$(file)) -.PHONY: help -cmd_group = $(call cstr,48;5;148;30, $1 ) -cmd_color = $(call cstr,38;5;220,$1) -cmd_arg_color = $(call cstr,36,$1) help: @echo The below are the list of available commands from this Makefile. @echo - @echo $(call cmd_group,1. MAKING ACTIONS) + @echo $(call STR_HELP_GROUP,1. MAKING ACTIONS) @echo " make builds every program." - @echo " make "$(call cmd_color,program-names...) + @echo " make "$(call STR_HELP_CMDHL,program-names...) @echo " builds mentioned program(s) only, e.g. make btn nsy" - @echo " make "$(call cmd_color,install)" copies the executables of each program into $(bindir) directory." + @echo " make "$(call STR_HELP_CMDHL,install)" copies the executables of each program into $(DIR_BIN) directory." @echo - @echo $(call cmd_group,2. CLEANING ACTIONS) - @echo " make "$(call cmd_color,clean)" deletes all object files and all executables." - @echo " make "$(call cmd_color,uninstall)" deletes everything under $(bindir) directory." - @echo " make "$(call cmd_color,cleanall)" clean + uninstall + some files in ./test" + @echo $(call STR_HELP_GROUP,2. CLEANING ACTIONS) + @echo " make "$(call STR_HELP_CMDHL,clean)" deletes all object files and all executables." + @echo " make "$(call STR_HELP_CMDHL,uninstall)" deletes everything under $(DIR_BIN) directory." + @echo " make "$(call STR_HELP_CMDHL,cleanall)" clean + uninstall + some files in ./test" @echo - @echo $(call cmd_group,3. MISCELLANEOUS) - @echo " make "$(call cmd_color,test) \ - $(call cmd_arg_color,prog)=\"the name of a program to be tested\" $(call cmd_arg_color,testcase)=\"the name of a testcase file\" + @echo $(call STR_HELP_GROUP,3. MISCELLANEOUS) + @echo " make "$(call STR_HELP_CMDHL,test) \ + $(call STR_HELP_ARGHL,prog)=\"the name of a program to be tested\" $(call STR_HELP_ARGHL,testcase)=\"the name of a testcase file\" @echo " performs a test on the executable with the test file." - @echo " make "$(call cmd_color,help)" prints this long manual on the screen that you are reading now." - -# Frequently Used Commands -.PHONY: bullshit -bullshit: - export PATH=$(bindir) && hhss 5 | nsy e | btn 20 + @echo " make "$(call STR_HELP_CMDHL,help)" prints this long manual on the screen that you are reading now." diff --git a/common/array.adt.c b/common/array.adt.c new file mode 100644 index 0000000..c25f30a --- /dev/null +++ b/common/array.adt.c @@ -0,0 +1,62 @@ +#include "array.adt.h" +#include "array.adt.internals.h" + +extern array_t *array_create(void) { + array_t *a; + + a = safe_malloc(sizeof *a); + a->arr = safe_malloc(INIT_MAX * ESIZ(a->arr)); + a->len = 0; + a->max = INIT_MAX; + + return a; +} + +extern void array_destroy(array_t *a) { + for (size_t i = 0; i < a->len; i++) + free(a->arr[i]); + free(a); +} + +extern void *array_append(array_t *a, const void *item, size_t isiz) { + void *p; + + if (array_full(a)) + array_enlarge(a); + + p = safe_malloc(isiz); + memcpy(p, item, isiz); + a->arr[a->len++] = p; + + return p; +} + +extern void *array_get(array_t *a, int idx) { + return a->arr[idx]; +} + +extern void array_set(array_t *a, int idx, void *item) { + a->arr[idx] = item; +} + +extern int array_size(array_t *a) { + return a->len; +} + +extern void array_foreach(array_t *a, array_iterator_t *iterate) { + for (size_t i = 0; i < a->len; i++) + (*iterate)(a->arr[i], i); +} + +static inline bool array_full(array_t *a) { + return a->len == a->max; +} + +static void array_enlarge(array_t *a) { + a->max *= 2; + a->arr = safe_realloc2x_arr( + a->arr, + &a->max, + ESIZ(a->arr) + ); +} diff --git a/common/array.adt.h b/common/array.adt.h new file mode 100644 index 0000000..8183db0 --- /dev/null +++ b/common/array.adt.h @@ -0,0 +1,27 @@ +#ifndef ARR_ADT_H +#define ARR_ADT_H + +/************ + * INCLUDES * + ************/ +#include +#include + +/************ + * TYPEDEFS * + ************/ +typedef struct array array_t; +typedef void array_iterator_t(void *item, int idx); + +/************** + * PROTOTYPES * + **************/ +array_t *array_create(void); +void array_destroy(array_t *a); +void *array_append(array_t *a, const void *item, size_t isiz); +void *array_get(array_t *a, int idx); +void array_set(array_t *a, int idx, void *item); +int array_size(array_t *a); +void array_foreach(array_t *a, array_iterator_t *iterate); + +#endif diff --git a/common/array.adt.internals.h b/common/array.adt.internals.h new file mode 100644 index 0000000..c8053c3 --- /dev/null +++ b/common/array.adt.internals.h @@ -0,0 +1,34 @@ +#ifndef ARRAY_ADT_TYPES_H +#define ARRAY_ADT_TYPES_H + +/************ + * INCLUDES * + ************/ +#include +#include +#include +# +#include "utils.h" +#include "wrappers.h" +#include "array.adt.h" + +/********** + * MACROS * + **********/ +#define INIT_MAX 128 + +/************ + * TYPEDEFS * + ************/ +struct array { + size_t len, max; + void **arr; +}; + +/************** + * PROTOTYPES * + **************/ +static inline bool array_full(array_t *a); +static void array_enlarge(array_t *arr); + +#endif diff --git a/common/colorcodes.h b/common/colorcodes.h new file mode 100644 index 0000000..8fa9b0c --- /dev/null +++ b/common/colorcodes.h @@ -0,0 +1,20 @@ +#ifndef COLORCODES_H +#define COLORCODES_H + +#define Creset "\033[0m" // color reset +# +#define Cbblack "\033[0;90m" // bright black +#define Cbred "\033[0;91m" // bright red +#define Cbgreen "\033[0;92m" // bright green +#define Cbyellow "\033[0;93m" // bright yellow +#define Cbblue "\033[0;94m" // bright blue +#define Cbmagenta "\033[0;95m" // bright magenta +#define Cbcyan "\033[0;96m" // bright cyan +#define Cbwhite "\033[0;97m" // bright white +# +#define Cgreen "\033[0;32m" // green +#define Ccyan "\033[0;36m" // cyan +# +#define Cemerald "\033[38;5;49;1m" // emerald + +#endif diff --git a/common/fatal.c b/common/fatal.c new file mode 100644 index 0000000..be49b8c --- /dev/null +++ b/common/fatal.c @@ -0,0 +1,38 @@ +#include "fatal.h" +#include "fatal.internals.h" + +extern void fatal( + const char * restrict errmsg, + const char * restrict funcname, + const char * restrict filename +) { + safe_fprintf( + stderr, + PROGNAME ": fatal: %s [arose at " Cemerald "(*%s):%s" Creset "]\n", + errmsg, funcname, filename + ); + exit(EXIT_FAILURE); +} + +extern void vfatal( + const char * restrict errmsg, + const char * restrict funcname, + const char * restrict filename, + ... +) { + va_list ap; + + safe_fputs(stderr, PROGNAME ": fatal: "); + + va_start(ap, filename); + safe_vfprintf(stderr, errmsg, &ap); + va_end(ap); + + safe_fprintf( + stderr, + " [arose at " Cemerald "(*%s):%s" Creset "]\n", + funcname, filename + ); + + exit(EXIT_FAILURE); +} diff --git a/common/fatal.h b/common/fatal.h new file mode 100644 index 0000000..5656ce2 --- /dev/null +++ b/common/fatal.h @@ -0,0 +1,29 @@ +#ifndef FATAL_H +#define FATAL_H + +/********** + * MACROS * + **********/ +#ifndef PROGNAME +#define PROGNAME "Utils" +#endif +# +#define ERR(errmsg) fatal(errmsg, __func__, __FILE__) +#define VERR(errmsg, ...) vfatal(errmsg, __func__, __FILE__, __VA_ARGS__) + +/************** + * PROTOTYPES * + **************/ +void fatal( + const char * restrict errmsg, + const char * restrict funcname, + const char * restrict filename +); +void vfatal( + const char * restrict errmsg, + const char * restrict filename, + const char * restrict funcname, + ... +); + +#endif diff --git a/common/fatal.internals.h b/common/fatal.internals.h new file mode 100644 index 0000000..7ac2359 --- /dev/null +++ b/common/fatal.internals.h @@ -0,0 +1,14 @@ +#ifndef FATAL_INTERNALS_H +#define FATAL_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +#include +# +#include "wrappers.h" +#include "colorcodes.h" + +#endif diff --git a/common/loadfile.c b/common/loadfile.c new file mode 100644 index 0000000..3e33e7c --- /dev/null +++ b/common/loadfile.c @@ -0,0 +1,41 @@ +#include "loadfile.h" +#include "loadfile.internals.h" + +extern array_t *loadfile( + const char *filename, + int * restrict lc, + int * restrict cc +) { + FILE *fp; + array_t *lines; + line_t line; + int lcnt, // line count + ccnt; // character count + + fp = safe_fopen(filename, "r"); + lines = array_create(); + lcnt = ccnt = 0; + + while (!readln(fp, &line.run, &line.len)) { + line.num = ++lcnt; + ccnt += line.len; + array_append(lines, &line, sizeof line); + } + + if (lcnt == 0) + ERR("empty source file"); + safe_fclose(fp); + + if (lc) *lc = lcnt; + if (cc) *cc = ccnt; + return lines; +} + +extern void unloadfl(array_t *lines) { + int siz = array_size(lines); + + for (int i = 0; i < siz; i++) + free(((line_t *) array_get(lines, i))->run); + + array_destroy(lines); +} diff --git a/common/loadfile.h b/common/loadfile.h new file mode 100644 index 0000000..6122ec6 --- /dev/null +++ b/common/loadfile.h @@ -0,0 +1,25 @@ +#ifndef LOADFILE_H +#define LOADFILE_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************ + * TYPEDEFS * + ************/ +typedef struct line { + char *run; + size_t len, num; +} line_t; + +array_t *loadfile( + const char *filename, + int * restrict lc, + int * restrict cc +); + +void unloadfl(array_t *lines); + +#endif diff --git a/common/loadfile.internals.h b/common/loadfile.internals.h new file mode 100644 index 0000000..f6c08a4 --- /dev/null +++ b/common/loadfile.internals.h @@ -0,0 +1,13 @@ +#ifndef LOADFILE_INTERNALS_H +#define LOADFILE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "fatal.h" +#include "readline.h" +#include "wrappers.h" + +#endif diff --git a/common/readline.c b/common/readline.c new file mode 100644 index 0000000..57a6c7a --- /dev/null +++ b/common/readline.c @@ -0,0 +1,49 @@ +#include "readline.h" +#include "readline.internals.h" + +static const char *errmsg = "unable to read"; + +extern int readln(FILE *fp, char **line, size_t *len) { + int ch; + size_t pos, bufsiz; + char *buf; + + // First, tests whether there is nothing to read + ch = getc(fp); + if (ch == EOF) { + if (ferror(fp)) ERR(errmsg); + *line = NULL; + *len = 0; + return 1; + } + else ungetc(ch, fp); + + // Reads the file + bufsiz = READLINE_UNIT; + buf = safe_malloc(bufsiz); + pos = 0; + + for (;;) { + ch = getc(fp); + if (ch == EOF) { + if (ferror(fp)) ERR(errmsg); + goto eol; + } + if (ch == '\r') continue; + if (ch == '\n') goto eol; + + buf[pos++] = ch; + if (pos == bufsiz) + buf = safe_realloc2x(buf, &bufsiz); + } + + eol: { + if (bufsiz - pos == 1) + buf = safe_realloc2x(buf, &bufsiz); + buf[pos++] = '\n'; + buf[pos] = '\0'; + *line = buf; + *len = pos; + return 0; + } +} diff --git a/common/readline.h b/common/readline.h new file mode 100644 index 0000000..f4e100a --- /dev/null +++ b/common/readline.h @@ -0,0 +1,14 @@ +#ifndef READLINE_H +#define READLINE_H + +/************ + * INCLUDES * + ************/ +#include + +/************** + * PROTOTYPES * + **************/ +int readln(FILE *fp, char **line, size_t *len); + +#endif diff --git a/common/readline.internals.h b/common/readline.internals.h new file mode 100644 index 0000000..0fce73e --- /dev/null +++ b/common/readline.internals.h @@ -0,0 +1,15 @@ +#ifndef READLINE_INTERNALS_H +#define READLINE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include "fatal.h" +#include "wrappers.h" + +/********** + * MACROS * + **********/ +#define READLINE_UNIT 64 + +#endif diff --git a/common/strutils.c b/common/strutils.c new file mode 100644 index 0000000..45e5207 --- /dev/null +++ b/common/strutils.c @@ -0,0 +1,62 @@ +#include "strutils.h" +#include "strutils.internals.h" + +extern char **split( + const char * restrict src, + const char * restrict mark, + size_t *retsiz +) { + /* + * An example input & output + * mark = "**" + * src = "**a****b**" + * arr = ["", "a", "", "", "b", ""] + */ + const int marklen = strlen(mark); + + size_t siz, max; + const char *ini, *fin; + char *buf, **arr; + + // Prepare an array of strings + siz = 0; + max = 2; + arr = safe_malloc(max * sizeof arr[0]); + ini = fin = src; + + for (;;) { + // find the location of the next mark + fin = strstr(fin, mark); + + if (!fin) { + int rest = strlen(ini); + buf = safe_malloc(rest + 1); + strcpy(buf, ini); + } + else { + ptrdiff_t diff = fin - ini; + if (!diff) { + buf = safe_malloc(1); + buf[0] = '\0'; + } + else { + buf = safe_malloc(diff + 1); + strncpy(buf, ini, diff); + buf[diff] = '\0'; + } + } + + // store the buffer into the array + if (siz == max) + arr = safe_realloc2x(arr, &max); + arr[siz++] = buf; + + // update the states + if (!fin) + goto end; + ini = fin = fin + marklen; + } + end: *retsiz = siz; + + return arr; +} diff --git a/common/strutils.h b/common/strutils.h new file mode 100644 index 0000000..8ea2a75 --- /dev/null +++ b/common/strutils.h @@ -0,0 +1,18 @@ +#ifndef STRUTILS_H +#define STRUTILS_H + +/************ + * INCLUDES * + ************/ +#include + +/************** + * PROTOTYPES * + **************/ +char **split( + const char * restrict src, + const char * restrict mark, + size_t *retsiz +); + +#endif diff --git a/common/strutils.internals.h b/common/strutils.internals.h new file mode 100644 index 0000000..0ded0f8 --- /dev/null +++ b/common/strutils.internals.h @@ -0,0 +1,12 @@ +#ifndef STRUTILS_INTERNALS_H +#define STRUTILS_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "wrappers.h" + +#endif diff --git a/yandere/c/utils.c b/common/utils.c similarity index 94% rename from yandere/c/utils.c rename to common/utils.c index bb67446..7d61798 100644 --- a/yandere/c/utils.c +++ b/common/utils.c @@ -1,4 +1,5 @@ #include "utils.h" +#include "utils.internals.h" extern void seed(void) { srand(time(NULL)); diff --git a/yandere/c/utils.h b/common/utils.h similarity index 57% rename from yandere/c/utils.h rename to common/utils.h index 6c2850a..e2ed9b0 100644 --- a/yandere/c/utils.h +++ b/common/utils.h @@ -1,14 +1,10 @@ #ifndef UTILS_H #define UTILS_H -/************ - * INCLUDES * - ************/ -#include -#include -# -#include "fatal.h" -#include "global.h" +/********** + * MACROS * + **********/ +#define ESIZ(arr) (sizeof (arr)[0]) /************** * PROTOTYPES * diff --git a/common/utils.internals.h b/common/utils.internals.h new file mode 100644 index 0000000..10bf786 --- /dev/null +++ b/common/utils.internals.h @@ -0,0 +1,12 @@ +#ifndef UTILS_INTERNALS_H +#define UTILS_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "fatal.h" + +#endif diff --git a/common/wrappers.c b/common/wrappers.c new file mode 100644 index 0000000..5935554 --- /dev/null +++ b/common/wrappers.c @@ -0,0 +1,81 @@ +#include "wrappers.h" +#include "wrappers.internals.h" + +/*********** + * stdio.h * + ***********/ +extern FILE *safe_fopen(const char *filename, const char *mode) { + FILE *fp = fopen(filename, mode); + if (!fp) VERR("unable to open the file: %s", filename); + return fp; +} + +extern void safe_fclose(FILE *fp) { + if (fclose(fp) != EOF) return; + ERR("unable to close a stream"); +} + +extern void safe_fputs(FILE *stream, const char *line) { + if (fputs(line, stream) == EOF) + ERR("fputs error"); +} + +/************ + * stdlib.h * + ************/ +static const char *realloc_errmsg = "realloc error"; + +extern void *safe_malloc(size_t siz) { + void *ret = malloc(siz); + if (!ret) ERR("malloc error"); + return ret; +} + +extern void *safe_calloc(size_t n, size_t esiz) { + void *ret = calloc(n, esiz); + if (!ret) ERR("calloc error"); + return ret; +} + +extern void *safe_realloc2x(void *ptr, size_t *siz) { + ptr = realloc(ptr, (*siz *= 2)); + if (!ptr) ERR(realloc_errmsg); + return ptr; +} + +extern void *safe_realloc2x_arr(void *arr, size_t *cnt, size_t esiz) { + (*cnt) *= 2; + arr = realloc(arr, (*cnt) * esiz); + if (!arr) ERR(realloc_errmsg); + return arr; +} + +/************ + * stdarg.h * + ************/ +static const char *vfprintf_errmsg = "vfprintf error"; + +extern void safe_fprintf(FILE *stream, const char *format, ...) { + va_list ap; + int ret; + + va_start(ap, format); + ret = vfprintf(stream, format, ap); + if (ret < 0) ERR(vfprintf_errmsg); + va_end(ap); +} + +extern void safe_vfprintf(FILE *stream, const char *format, va_list *ap) { + int ret; + + ret = vfprintf(stream, format, *ap); + if (ret < 0) ERR(vfprintf_errmsg); +} + +/************ + * signal.h * + ************/ +extern void safe_signal(int sig, sighandler_t handler) { + if (signal(sig, handler) == SIG_ERR) + ERR("signal error"); +} diff --git a/yandere/c/wrappers.h b/common/wrappers.h similarity index 53% rename from yandere/c/wrappers.h rename to common/wrappers.h index 4b7aece..be68525 100644 --- a/yandere/c/wrappers.h +++ b/common/wrappers.h @@ -5,16 +5,23 @@ * INCLUDES * ************/ #include -#include #include -# -#include "fatal.h" -#include "global.h" + +/************ + * TYPEDEFS * + ************/ +typedef void sighandler_t(int sig); /************** * PROTOTYPES * **************/ +FILE *safe_fopen(const char *filename, const char *mode); +void safe_fclose(FILE *fp); void safe_fputs(FILE *stream, const char *line); +void *safe_malloc(size_t siz); +void *safe_realloc2x(void *ptr, size_t *siz); +void *safe_realloc2x_arr(void *arr, size_t *cnt, size_t esiz); +void *safe_calloc(size_t n, size_t esiz); void safe_fprintf(FILE *stream, const char *format, ...); void safe_vfprintf(FILE *stream, const char *format, va_list *ap); void safe_signal(int sig, sighandler_t handler); diff --git a/common/wrappers.internals.h b/common/wrappers.internals.h new file mode 100644 index 0000000..0ca74fb --- /dev/null +++ b/common/wrappers.internals.h @@ -0,0 +1,12 @@ +#ifndef WRAPPERS_INTERNALS_H +#define WRAPPERS_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "fatal.h" + +#endif diff --git a/defs.mk b/defs.mk index f3e6e14..b1452e2 100644 --- a/defs.mk +++ b/defs.mk @@ -1,23 +1,37 @@ -define installation_template +############### +# Definitions # +############### + +# TPL_INST_PROG - program install template +# $1 = list of program names +# $2 = install command +define TPL_INST_PROG for i in $1; do \ if $2; then \ - echo $(inst_done_str) $(call name_str,$$i) has been installed successfully.; \ + echo $(STR_INST_DONE) $(call STR_NAME,$$i) has been installed successfully.; \ else \ - echo $(warn_str) There was a failure on installing $(call name_str,$$i).; \ + echo $(STR_WARN) There was a failure on installing $(call STR_NAME,$$i).; \ fi \ done endef -# inst_man_t - manual install template +# TPL_INST_MAN - manual install template # $1 = list of program names # $2 = install command # $3 = manual section -define inst_man_t +define TPL_INST_MAN for i in $1; do \ if $2; then \ - echo $(inst_done_str) $(call name_str,$$i.$3) has been installed.; \ + echo $(STR_INST_DONE) $(call STR_NAME,$$i.$3) has been installed.; \ else \ - echo $(warn_str) Failed to install $(call name_str,$$i.$3).; \ + echo $(STR_WARN) Failed to install $(call STR_NAME,$$i.$3).; \ fi \ done -endef \ No newline at end of file +endef + +# CSTR - color string +# $1 = color value +# $2 = message +define CSTR +"\033[$1m$2\033[0m" +endef diff --git a/hhss/c/.gitignore b/hhss/c/.gitignore index c4c8a6c..6dfabfe 100644 --- a/hhss/c/.gitignore +++ b/hhss/c/.gitignore @@ -1,3 +1,4 @@ hhss hhss.exe -hhss.o \ No newline at end of file +*.o +*.d diff --git a/hhss/c/Makefile b/hhss/c/Makefile index 839057e..e175aac 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -1,15 +1,41 @@ -CC = gcc -CCFLAGS = -O -Wall -W -pedantic +## Variables ## +TARGET := hhss -TARGET = hhss +CC := gcc +CFLAGS := -O -Wall -W -pedantic -g +CPPFLAGS = \ + -I $(DIR_COMMON) \ + -DINSTPATH='"$(DIR_DATA)/$(TARGET)"' \ + -DPROGNAME='"$(TARGET)"' -SOURCES = $(wildcard ./*.c) -OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) +SOURCES = $(wildcard *.c) +SOURCES += $(wildcard $(DIR_COMMON)/*.c) +OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) + +DIR_DATA := ../.. +DIR_COMMON := ../../common + +## Default Goal ## +.PHONY: all clean all: $(TARGET) $(TARGET): $(OBJECTS) - $(CC) $(CCFLAGS) -o $@ $^ + $(CC) $^ $(CFLAGS) -o $@ %.o: %.c - $(CC) $(CCFLAGS) -c -o $@ $< + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +clean: + rm -f $(TARGET) *.o *.d + +# Refer to the "4.14 Generating Prerequisites Automatically" +# section in the GNU Make manual. +%.d: %.c + @set -e; rm -f $@; \ + $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +## Dependency ## +include $(SOURCES:.c=.d) diff --git a/hhss/c/argv1parse.c b/hhss/c/argv1parse.c new file mode 100644 index 0000000..c6a1142 --- /dev/null +++ b/hhss/c/argv1parse.c @@ -0,0 +1,21 @@ +#include "argv1parse.h" +#include "argv1parse.internals.h" + +extern int argv1parse(const char *argv1, int threshold) { + char *i; + int ret; + + errno = 0; + ret = strtol(argv1, &i, 10); + + if (errno == ERANGE) + ERR("count out of range"); + if (i == argv1) + ERR("conversion not performed"); + if (ret < MIN_DATA_COUNT) + VERR("count must be %d at least", MIN_DATA_COUNT); + if (ret > threshold) + VERR("count must be less than or equal to %d", threshold); + + return ret; +} diff --git a/hhss/c/argv1parse.h b/hhss/c/argv1parse.h new file mode 100644 index 0000000..a2a6e74 --- /dev/null +++ b/hhss/c/argv1parse.h @@ -0,0 +1,9 @@ +#ifndef ARGV1PARSE_H +#define ARGV1PARSE_H + +/************** + * PROTOTYPES * + **************/ +int argv1parse(const char *argv1, int threshold); + +#endif diff --git a/hhss/c/argv1parse.internals.h b/hhss/c/argv1parse.internals.h new file mode 100644 index 0000000..137ab1a --- /dev/null +++ b/hhss/c/argv1parse.internals.h @@ -0,0 +1,13 @@ +#ifndef ARGV1PARSE_INTERNALS_H +#define ARGV1PARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "fatal.h" +#include "global.h" + +#endif diff --git a/hhss/c/dbload.c b/hhss/c/dbload.c new file mode 100644 index 0000000..464a180 --- /dev/null +++ b/hhss/c/dbload.c @@ -0,0 +1,12 @@ +#include "dbload.h" +#include "dbload.internals.h" + +extern array_t *dbload(const char *new, const char *old) { + if (canopen(new)) + return loadfile(new, NULL, NULL); + return loadfile(old, NULL, NULL); +} + +static int canopen(const char *filename) { + return fopen(filename, "r") ? 1 : 0; +} diff --git a/hhss/c/dbload.h b/hhss/c/dbload.h new file mode 100644 index 0000000..535d858 --- /dev/null +++ b/hhss/c/dbload.h @@ -0,0 +1,14 @@ +#ifndef DBLOAD_H +#define DBLOAD_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +array_t *dbload(const char *new, const char *old); + +#endif diff --git a/hhss/c/dbload.internals.h b/hhss/c/dbload.internals.h new file mode 100644 index 0000000..9815c90 --- /dev/null +++ b/hhss/c/dbload.internals.h @@ -0,0 +1,18 @@ +#ifndef DBLOAD_INTERNALS_H +#define DBLOAD_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "global.h" +#include "loadfile.h" +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +static int canopen(const char *filename); + +#endif diff --git a/hhss/c/debug.c b/hhss/c/debug.c new file mode 100644 index 0000000..5884e8c --- /dev/null +++ b/hhss/c/debug.c @@ -0,0 +1,108 @@ +#include "debug.h" +#include "debug.internals.h" + +extern void debug_rtdb(array_t *rtdb) { + typedef struct { + char *sect; + array_t *addr; + } mapper_t; + + mapper_t *m; + char *s; + size_t siz, siz2; + size_t i, k; + + siz = array_size(rtdb); + + for (i = 0; i < siz; i++) { + m = array_get(rtdb, i); + printf("rtdb[%zu]\n", i); + printf(".sectname = [%s]\n", m->sect); + printf(".sectarr\n"); + siz2 = array_size(m->addr); + for (k = 0; k < siz2; k++) { + s = array_get(m->addr, k); + printf(" [%zu] = [%s]\n", k, s); + } + } +} + +extern void debug_charstrs(array_t *charstrs) { + char *s; + size_t i, siz; + + siz = array_size(charstrs); + printf("charstrs.len = %zu\n", siz); + + for (i = 0; i < siz; i++) { + s = array_get(charstrs, i); + printf("charstrs[%zu] = [%s]\n", i, s); + } +} + +extern void debug_tokstr(array_t *tokstr) { + token_t *tok; + size_t k, siz; + + siz = array_size(tokstr); + printf("tokstr.len = %zu\n", siz); + + for (k = 0; k < siz; k++) { + tok = array_get(tokstr, k); + printf("tokstr[%zu]\n", k); + printf(" .kind = [%d]\n", tok->kind); + printf(" .run = [%s]\n", tok->run); + printf(" .len = [%d]\n", tok->len); + } + + printf("\n"); +} + +extern void debug_tokstrs(array_t *tokstrs) { + array_t *tokstr; + token_t *tok; + size_t siz, siz2; + size_t i, k; + + siz = array_size(tokstrs); + printf("tokstrs.len = %zu\n", siz); + + for (i = 0; i < siz; i++) { + tokstr = *((array_t **) array_get(tokstrs, i)); + siz2 = array_size(tokstr); + printf("tokstrs[%zu]\n", i); + printf("tokstrs[%zu].len = %zu\n", i, siz2); + + for (k = 0; k < siz2; k++) { + tok = array_get(tokstr, k); + printf(" tokstrs[%zu][%zu]\n", i, k); + printf(" .kind = [%d]\n", tok->kind); + printf(" .run = [%s]\n", tok->run); + printf(" .len = [%d]\n", tok->len); + } + } +} + +extern void debug_pts(array_t *pts) { + array_t *pt; + symbol_t *sym; + size_t siz, siz2; + size_t i, k; + + siz = array_size(pts); + printf("pts.len = %zu\n", siz); + + for (i = 0; i < siz; i++) { + pt = *((array_t **) array_get(pts, i)); + siz2 = array_size(pt); + printf("pts[%zu]\n", i); + printf("pts[%zu].len = %zu\n", i, siz2); + + for (k = 0; k < siz2; k++) { + sym = array_get(pt, k); + printf(" pts[%zu][%zu]\n", i, k); + printf(" .kind = [%d]\n", sym->kind); + printf(" .run = [%s]\n", sym->content); + } + } +} diff --git a/hhss/c/debug.h b/hhss/c/debug.h new file mode 100644 index 0000000..bc0d6b3 --- /dev/null +++ b/hhss/c/debug.h @@ -0,0 +1,18 @@ +#ifndef DEBUG_H +#define DEBUG_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +void debug_rtdb(array_t *rtdb); +void debug_charstrs(array_t *charstrs); +void debug_tokstr(array_t *tokstr); +void debug_tokstrs(array_t *tokstrs); +void debug_pts(array_t *pts); + +#endif diff --git a/hhss/c/debug.internals.h b/hhss/c/debug.internals.h new file mode 100644 index 0000000..c37c588 --- /dev/null +++ b/hhss/c/debug.internals.h @@ -0,0 +1,12 @@ +#ifndef DEBUG_INTERNALS_H +#define DEBUG_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "lex.h" +#include "parse.h" + +#endif diff --git a/hhss/c/dtdbparse.c b/hhss/c/dtdbparse.c new file mode 100644 index 0000000..25e3467 --- /dev/null +++ b/hhss/c/dtdbparse.c @@ -0,0 +1,51 @@ +#include "dtdbparse.h" +#include "dtdbparse.internals.h" + +extern array_t *dtdbparse(array_t *linestr) { + array_t *res; + line_t *l, temp; + size_t siz; + char *buf; + + res = array_create(); + siz = array_size(linestr); + + for (size_t i = 0; i < siz; i++) { + l = array_get(linestr, i); + if (strchr("# ", l->run[0])) + continue; + buf = safe_malloc(l->len + 1); + strcpy(buf, l->run); + temp.len = l->len; + temp.num = l->num; + temp.run = buf; + array_append(res, &temp, sizeof temp); + } + + return res; +} + +extern void dtdbcheck(array_t *db) { + int dbsiz, threshold; + + dbsiz = array_size(db); + threshold = MIN_DATA_COUNT; + + if (dbsiz < threshold) + VERR("data database must have at least " + "%d entries but only %d", + threshold, dbsiz + ); +} + +extern void destroy_dtdb(array_t *dtdb) { + int siz = array_size(dtdb); + line_t *l; + + for (int i = 0; i < siz; i++) { + l = array_get(dtdb, i); + free(l->run); + } + + array_destroy(dtdb); +} diff --git a/hhss/c/dtdbparse.h b/hhss/c/dtdbparse.h new file mode 100644 index 0000000..7343322 --- /dev/null +++ b/hhss/c/dtdbparse.h @@ -0,0 +1,16 @@ +#ifndef DTDBPARSE_H +#define DTDBPARSE_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +array_t *dtdbparse(array_t *linestr); +void dtdbcheck(array_t *db); +void destroy_dtdb(array_t *dtdb); + +#endif diff --git a/hhss/c/dtdbparse.internals.h b/hhss/c/dtdbparse.internals.h new file mode 100644 index 0000000..1a89f01 --- /dev/null +++ b/hhss/c/dtdbparse.internals.h @@ -0,0 +1,15 @@ +#ifndef DTDBPARSE_INTERNALS_H +#define DTDBPARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "fatal.h" +#include "global.h" +#include "loadfile.h" +#include "wrappers.h" +#include "dtdbparse.h" + +#endif diff --git a/hhss/c/global.h b/hhss/c/global.h new file mode 100644 index 0000000..d34d399 --- /dev/null +++ b/hhss/c/global.h @@ -0,0 +1,24 @@ +#ifndef GLOBAL_H +#define GLOBAL_H + +/********** + * MACROS * + **********/ +#define MIN_DATA_COUNT 5 +#define MIN_USER_COUNT 1 +# +#ifndef INSTPATH /* install path; given when built */ +#define INSTPATH "../" +#endif +# +#define DATA_DB_NAME "/dat.db" +#define RPTP_DB_NAME "/rt.db" +#define DATA_DB_PATH INSTPATH DATA_DB_NAME +#define RPTP_DB_PATH INSTPATH RPTP_DB_NAME +# +#define OLD_DATA_DB_NAME "/hsr.dat" +#define OLD_RPTP_DB_NAME "/usr.dat" +#define OLD_DATA_DB_PATH INSTPATH OLD_DATA_DB_NAME +#define OLD_RPTP_DB_PATH INSTPATH OLD_RPTP_DB_NAME + +#endif diff --git a/hhss/c/hhss.c b/hhss/c/hhss.c index a53ef29..db637d1 100644 --- a/hhss/c/hhss.c +++ b/hhss/c/hhss.c @@ -1,519 +1,54 @@ -/*** - * HUTSORI.C by Cor (24.06.02 ~ 24.06.06) - * This program prints some "ridiculous" sentences to stdout, - * given two data files: hsr.dat and usr.dat. Meanwhile, it - * would be a good thing to use this program with the other - * programs: btn and/or nsy via pipelines. - * - * Usage: ./hhss NUM_SENTENCES - * where - * NUM_SENTENCES = the number of sentences to print out. - * - * Requirement: hsr.dat has to have at least 5 valid lines - * and usr.dat at least 1 valid line. A valid line is a line - * which is neither a comment nor an empty line. A comment - * line starts with a # character. A valid line can have more - * than one "${user}" string in it, which is to be replaced - * with a random valid line in usr.dat. - * - * P.S. hhss stands for hweng-seol-su-seol, which means - * gibberish in Korean. - ***/ - -#include -#include -#include -#include -#include -#include -#include - -#define LINES_INC_UNIT 64 /* Their size increases by this */ -#define LINE_INC_UNIT 256 /* numbers, respectively. */ -#define SPLIT_INC_UNIT 8 -# -#define MIN_SENTENCE_NUM 5 -#define MIN_USER_NUM 1 -# -#define COMMENT '#' -# -#ifndef INSTPATH -#define INSTPATH "../" /* install path; given when built */ -#endif - -const char *arg_num_sentence_to_print = "argv[1]"; -const char *sentence_file = INSTPATH "/hsr.dat"; -const char *user_file = INSTPATH "/usr.dat"; -const char *user_template = "${user}"; - -void raise_err(char *err_msg, ...); -FILE *open_file(char *name, char *mode); -char **copy_valid_lines(FILE *fp, int *result_len_ptr); -void close_file(FILE *name); -void check_if_valid_file(char *file_name, int line_len, int min_len); -int get_num_sentence_to_print(char *str, int max_limit); -char *shuffle_once(char **lines, int final); -char *replace_template(char *line, char **usrs, int usrs_len); -void free_str_arr(char **str_arr, int arr_len); +#include "hhss.internals.h" int main(int argc, char *argv[]) { - if (argc != 2) - raise_err("usage: hhss "); - - FILE *hsr_dat = open_file(sentence_file, "r"); - FILE *usr_dat = open_file(user_file, "r"); - - int hsrs_len, usrs_len; - char **hsrs = copy_valid_lines(hsr_dat, &hsrs_len); - char **usrs = copy_valid_lines(usr_dat, &usrs_len); - - close_file(hsr_dat); - close_file(usr_dat); - - check_if_valid_file(sentence_file, hsrs_len, MIN_SENTENCE_NUM); - check_if_valid_file(user_file, usrs_len, MIN_USER_NUM); - - int num_sentence_to_print = get_num_sentence_to_print(argv[1], hsrs_len); - char *printed_sentences[num_sentence_to_print]; - - srand(time(NULL)); - for (int i = 0, final = hsrs_len - 1; - i < num_sentence_to_print; - i++) - { - char *chosen_sentence; - - chosen_sentence = shuffle_once(hsrs, final--); - chosen_sentence = replace_template(chosen_sentence, usrs, usrs_len); - printf("%s\n", chosen_sentence); - printed_sentences[i] = chosen_sentence; - } - - free_str_arr(hsrs, hsrs_len); - free_str_arr(usrs, usrs_len); - for (int i = 0; i < num_sentence_to_print; i++) - free(printed_sentences[i]); - + validate(argc); + prepare(argv); + array_foreach(pts, iterate); + cleanup(); return 0; } -/* prints an error message to stderr. */ -void raise_err(char *err_msg, ...) { - va_list ap; - - va_start(ap, err_msg); - vfprintf(stderr, err_msg, ap); - va_end(ap); - fprintf(stderr, "\n"); - exit(EXIT_FAILURE); -} - -/* opens a file. */ -FILE *open_file(char *name, char *mode) { - FILE *file; - - file = fopen(name, mode); - if (file == NULL) - raise_err("hhss: failed to open %s as mode \"%s\".", - name, mode); - - return file; -} - -/* reads arg_num_sentence_to_print. */ -int get_num_sentence_to_print(char *str, int max_limit) { - char *indicator; - int num; - - errno = 0; - num = strtol(str, &indicator, 10); - if (errno == ERANGE) - raise_err("hhss: %s out of range -> %s.", arg_num_sentence_to_print, str); - if (indicator == str) - raise_err("hhss: no conversion can be performed."); - if (num < MIN_SENTENCE_NUM) - raise_err("hhss: %s = %d needs to be >= %d.", - arg_num_sentence_to_print, num, MIN_SENTENCE_NUM); - else if (num > max_limit) - raise_err("hhss: %s = %d needs to be <= %d, " - "the number of valid lines in %s.", - arg_num_sentence_to_print, num, max_limit, sentence_file); - - return num; -} - -char *create_new_line(int *last_char_idx_ptr, int *max_char_num_ptr); -void store_current_line( - char ***lines_ptr, char *line, int *lines_cur_len_ptr, int *lines_max_len_ptr); -void store_current_char( - char **line_ptr, char ch, int *last_char_idx_ptr, int *max_char_num_ptr); - -/* copies valid lines from a data file. */ -char **copy_valid_lines(FILE *fp, int *result_len_ptr) { - char **lines; - int lines_cur_len = 0; - int lines_max_len = LINES_INC_UNIT; - - lines = malloc(lines_max_len * sizeof(char *)); - if (lines == NULL) - raise_err("hhss: failed to malloc."); - - bool at_line_start = true; - bool on_comment = false; - int ch; - int last_char_idx = 0; - int max_char_num = LINE_INC_UNIT; - char *line = create_new_line(&last_char_idx, &max_char_num); - - while ((ch = getc(fp)) != EOF) { - switch (ch) { - case '\n': - store_current_line( - &lines, line, &lines_cur_len, &lines_max_len); - if (strlen(line) != 0) - line = create_new_line(&last_char_idx, &max_char_num); - if (!at_line_start) at_line_start = true; - if (on_comment) on_comment = false; - break; - case '\r': - break; - case COMMENT: - if (at_line_start) { - on_comment = true; - at_line_start = false; - break; - } - default: - if (on_comment) break; - if (at_line_start) at_line_start = false; - store_current_char( - &line, ch, &last_char_idx, &max_char_num); - } - } - store_current_line( /* for a file not to be ended with \n. */ - &lines, line, &lines_cur_len, &lines_max_len); - - *result_len_ptr = lines_cur_len; - return lines; -} - -/* creates a new line and initializes - two variables related to it. */ -char *create_new_line(int *last_char_idx_ptr, int *max_char_num_ptr) { - char *line; - - line = malloc(LINE_INC_UNIT); - if (line == NULL) - raise_err("hhss: failed to malloc."); - line[0] = '\0'; - *last_char_idx_ptr = 0; - *max_char_num_ptr = 0; - - return line; -} - -char **lengthen_lines(char **lines, int lines_max_len); - -/* stores a current line (namely, char *) to char ** variable. */ -void store_current_line( - char ***lines_ptr, - char *line, - int *lines_cur_len_ptr, - int *lines_max_len_ptr -) { - if (strlen(line) == 0) return; - if (*lines_cur_len_ptr == *lines_max_len_ptr) { - *lines_max_len_ptr += LINES_INC_UNIT; - *lines_ptr = lengthen_lines(*lines_ptr, *lines_max_len_ptr); - } - (*lines_ptr)[(*lines_cur_len_ptr)++] = line; -} - -/* makes a char ** variable have a longer space. */ -char **lengthen_lines(char **lines, int lines_max_len) { - char **lines_reallocated; - - lines_reallocated = realloc(lines, lines_max_len * sizeof(char *)); - if (lines == NULL) - raise_err("hhss: failed to realloc."); - - return lines_reallocated; -} - -char *lengthen_line(char *line, int max_char_num); - -/* stores a current character (namely, char) to char * variable. */ -void store_current_char( - char **line_ptr, - char ch, - int *last_char_idx_ptr, - int *max_char_num_ptr -) { - if (*last_char_idx_ptr == *max_char_num_ptr) { - *max_char_num_ptr += LINE_INC_UNIT; - *line_ptr = lengthen_line(*line_ptr, *max_char_num_ptr); - } - (*line_ptr)[(*last_char_idx_ptr)++] = ch; -} - -/* makes a char * variable have a longer space. */ -char *lengthen_line(char *line, int max_char_num) { - char *line_reallocated; - - line_reallocated = realloc(line, max_char_num * sizeof(char)); - if (line_reallocated == NULL) - raise_err("hhss: failed to realloc."); - - return line_reallocated; -} - -/* closes a file. */ -void close_file(FILE *name) { - if (fclose(name) == EOF) - raise_err("hhss: failed to close %s.\n", name); -} - -/* sees whether a file satisfies the requirement. */ -void check_if_valid_file(char *file_name, int line_len, int min_len) { - if (line_len < min_len) - raise_err("hhss: it is required for %s to have " - "valid lines more than or equal to %d.", - file_name, min_len); -} - -unsigned int rand_range(unsigned int min, unsigned int max); - -/* shuffles once; returns a random char * from char **. */ -char *shuffle_once(char **lines, int final) { - int rv = rand_range(0, final); - char *chosen; - - if (rv == final) - return chosen = lines[final]; - else { - chosen = lines[rv]; - lines[rv] = lines[final]; - lines[final] = chosen; - return chosen; - } -} - -/* returns a random positive integer; min <= x <= max. */ -unsigned int rand_range(unsigned int min, unsigned int max) { - if (max == 0) - return 0; - return min + rand() / (RAND_MAX / max + 1); -} - -char **split(char *str, char *delim_str, int *result_len_ptr); - -/* replaces ${} and returns a processed sentence. */ -char *replace_template(char *line, char **usrs, int usrs_len) { - int parts_len; - char **parts; - - parts = split(line, user_template, &parts_len); - - char *prev_name = NULL; - int final = usrs_len - 1; - int result_str_len = 0; - - for (int i = 0; i < parts_len; i++) { - if (strlen(parts[i]) == 0) { - free(parts[i]); - - char *temp; - - do { - temp = shuffle_once(usrs, final--); - if (final == -1) - final = usrs_len - 1; - } while (prev_name == temp); - prev_name = temp; - - char *user_name; - int temp_len = strlen(temp); - - user_name = malloc(temp_len + 1); - if (user_name == NULL) - raise_err("hhss: failed to malloc."); - - strncpy(user_name, temp, temp_len); - user_name[temp_len] = '\0'; - parts[i] = user_name; - } - result_str_len += strlen(parts[i]); - } - - char *result_str; - - result_str = malloc(result_str_len + 1); - if (result_str == NULL) - raise_err("hhss: failed to malloc."); - - for (int i = 0, offset = 0; i < parts_len; i++) { - int len = strlen(parts[i]); - strncpy(result_str + offset, parts[i], len); - offset += len; - } - result_str[result_str_len] = '\0'; - - for (int i = 0; i < parts_len; i++) - free(parts[i]); - free(parts); - - return result_str; +static void validate(int argc) { + if (argc != 2) + ERR("usage: hhss "); } -/* splits a string, replacing ${} with an empty string ("\0"), - and returns the result as char **. */ -char **split(char *str, char *delim_str, int *result_len_ptr) { - char **arr; - int arr_len = SPLIT_INC_UNIT; - - arr = malloc(arr_len * sizeof(char *)); - if (arr == NULL) - raise_err("hhss: failed to malloc."); - - int delim_str_len = strlen(delim_str); - int i = 0; +static void prepare(char *argv[]) { + seed(); - for (int ini = 0, fin = 0; /* initial, final */ - ini < strlen(str); - i++) - { - char *ptr; - char *current = str + ini; + dtdb_linestr = dbload(DATA_DB_PATH, OLD_DATA_DB_PATH); + dtdb = dtdbparse(dtdb_linestr); + dtdbcheck(dtdb); - ptr = strstr(current, delim_str); - if (ptr == NULL) - fin = strlen(str); - else - if (ptr == current) - fin = ini; /* Thus len becomes to 0. */ - else - fin = ptr - str; + rtdb_linestr = dbload(RPTP_DB_PATH, OLD_RPTP_DB_PATH); + rtdb = rtdbparse(rtdb_linestr); + rtdbcheck(rtdb); - char *part; - int len = fin - ini; + datcnt = argv1parse(argv[1], array_size(dtdb)); - part = malloc(len + 1); - if (part == NULL) - raise_err("hhss: failed to malloc."); - - strncpy(part, current, len); - part[len] = '\0'; - - if (i == arr_len) { - arr_len += SPLIT_INC_UNIT; - arr = realloc(arr, arr_len * sizeof(char *)); - if (arr == NULL) - raise_err("hhss: failed to realloc."); - } - - arr[i] = part; - - if (ptr == NULL) - ini = fin; - else - if (ptr == current) - ini += delim_str_len; - else - ini = fin; - } - - *result_len_ptr = i; - return arr; + charstrs = prelex(dtdb, datcnt); + tokstrs = lex(charstrs); + pts = parse(tokstrs); + replace_templates(pts, rtdb); } -void free_str_arr(char **str_arr, int arr_len) { - for (int i = 0; i < arr_len; i++) - free(str_arr[i]); - free(str_arr); +static void iterate(void *item, int idx) { + (void) idx; + array_foreach(*((array_t **) item), print_pt); } -/* Another implementation: - processes a line, one character at a time. */ -#if 0 -#define TEMPLATE_BEGIN '$' - -void handle_user_template( - char **usrs, char **prev_ptr, int final_value, - char **template_replaced_sentence_ptr, - int *template_replaced_sentence_last_char_idx_ptr, - int *template_replaced_sentence_max_char_idx_ptr); - -char *replace_template(char *line, char **usrs, int usrs_len) { - char *template_replaced_sentence; - int template_replaced_sentence_last_char_idx = 0; - int template_replaced_sentence_max_char_idx = LINE_INC_UNIT; - char *ptr; - char *prev = NULL; - - template_replaced_sentence = malloc(template_replaced_sentence_max_char_idx); - if (template_replaced_sentence == NULL) - raise_err("hhss: failed to malloc."); - for (int i = 0; i < strlen(line); /* intentionally left blank */ ) { - if (line[i] != TEMPLATE_BEGIN) { - store_current_char( - &template_replaced_sentence, - line[i], - &template_replaced_sentence_last_char_idx, - &template_replaced_sentence_max_char_idx); - i++; - } - else { - ptr = strstr(line + i, user_template); - if (ptr != NULL) { - handle_user_template( - usrs, &prev, usrs_len - 1, - &template_replaced_sentence, - &template_replaced_sentence_last_char_idx, - &template_replaced_sentence_max_char_idx); - i += strlen(user_template); - } - else { - store_current_char( - &template_replaced_sentence, - line[i], - &template_replaced_sentence_last_char_idx, - &template_replaced_sentence_max_char_idx); - i++; - } - } - } - store_current_char( - &template_replaced_sentence, - '\0', - &template_replaced_sentence_last_char_idx, - &template_replaced_sentence_max_char_idx); - - return template_replaced_sentence; +static void print_pt(void *item, int idx) { + symbol_t *sym = item; + (void) idx; + safe_fputs(stdout, sym->content); } -void handle_user_template( - char **usrs, - char **prev_ptr, - int final_value, - char **template_replaced_sentence_ptr, - int *template_replaced_sentence_last_char_idx_ptr, - int *template_replaced_sentence_max_char_idx_ptr) -{ - char *user_name; - int final = final_value; - - do { - user_name = shuffle_once(usrs, final--); - if (final == -1) - final = final_value; - } while (*prev_ptr == user_name); - *prev_ptr = user_name; - - for (int i = 0; i < strlen(user_name); i++) - store_current_char( - template_replaced_sentence_ptr, - user_name[i], - template_replaced_sentence_last_char_idx_ptr, - template_replaced_sentence_max_char_idx_ptr); +static void cleanup(void) { + destroy_pts(pts); + destroy_tokstrs(tokstrs); + destroy_charstrs(charstrs); + destroy_rtdb(rtdb); + unloadfl(rtdb_linestr); + destroy_dtdb(dtdb); + unloadfl(dtdb_linestr); } -#endif \ No newline at end of file diff --git a/hhss/c/hhss.internals.h b/hhss/c/hhss.internals.h new file mode 100644 index 0000000..b42b939 --- /dev/null +++ b/hhss/c/hhss.internals.h @@ -0,0 +1,39 @@ +#ifndef HHSS_INTERNALS_H +#define HHSS_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include "lex.h" +#include "debug.h" +#include "parse.h" +#include "utils.h" +#include "fatal.h" +#include "dbload.h" +#include "global.h" +#include "prelex.h" +#include "replace.h" +#include "wrappers.h" +#include "loadfile.h" +#include "rtdbparse.h" +#include "dtdbparse.h" +#include "argv1parse.h" + +/************** + * PROTOTYPES * + **************/ +static void validate(int argc); +static void prepare(char *argv[]); +static array_iterator_t iterate; +static array_iterator_t print_pt; +static void cleanup(void); + +/******************** + * STATIC VARIABLES * + ********************/ +static array_t *dtdb, *dtdb_linestr; +static array_t *rtdb, *rtdb_linestr; +static array_t *charstrs, *tokstrs, *pts; +static int datcnt; + +#endif diff --git a/hhss/c/lex.c b/hhss/c/lex.c new file mode 100644 index 0000000..5b69958 --- /dev/null +++ b/hhss/c/lex.c @@ -0,0 +1,92 @@ +#include "lex.h" +#include "lex.internals.h" + +extern array_t *lex(array_t *charstrs) { + array_t *tokstrs; + char *charstr; + size_t len; + + bufsiz = 128; + buf = safe_malloc(bufsiz); + pos = 0; + + len = array_size(charstrs); + tokstrs = array_create(); + + for (size_t i = 0; i < len; i++) { + charstr = array_get(charstrs, i); + lex_line(charstr); + array_append(tokstrs, &tokstr, sizeof tokstr); + } + free(buf); + + return tokstrs; +} + +static array_t *lex_line(const char *line) { + tokstr = array_create(); + + for (;;) { + ch = *line++; + switch (ch) { + case '\0': tokenize(); goto done; + case '$' : /* fall-through */ + case '{' : /* fall-through */ + case '}' : tokenize(); break; + default : charcopy(); + } + } + done:; + + return tokstr; +} + +static void tokenize(void) { + token_t tok; + char *run; + + if (pos != 0) { + buf[pos] = '\0'; + run = safe_malloc(pos + 1); + strcpy(run, buf); + tok.kind = Tokkind_chars; + tok.run = run; + tok.len = pos; + array_append(tokstr, &tok, sizeof tok); + pos = 0; + } + + if (ch != '\0') { + run = safe_malloc(2); + run[0] = ch; + run[1] = '\0'; + tok.kind = Tokkind_delim; + tok.run = run; + tok.len = 1; + array_append(tokstr, &tok, sizeof tok); + } +} + +static void charcopy(void) { + buf[pos++] = ch; + if (pos == bufsiz) + buf = safe_realloc2x(buf, &bufsiz); +} + +extern void destroy_tokstrs(array_t *tokstrs) { + int tokstrs_siz = array_size(tokstrs); + int tokstr_siz; + array_t *tokstr; + token_t *tok; + + for (int i = 0; i < tokstrs_siz; i++) { + tokstr = *((array_t **) array_get(tokstrs, i)); + tokstr_siz = array_size(tokstr); + for (int k = 0; k < tokstr_siz; k++) { + tok = array_get(tokstr, k); + free(tok->run); + } + array_destroy(tokstr); + } + array_destroy(tokstrs); +} diff --git a/hhss/c/lex.h b/hhss/c/lex.h new file mode 100644 index 0000000..9f7ed20 --- /dev/null +++ b/hhss/c/lex.h @@ -0,0 +1,29 @@ +#ifndef LEX_H +#define LEX_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************ + * TYPEDEFS * + ************/ +typedef enum { + Tokkind_chars, + Tokkind_delim +} tokkind_t; + +typedef struct { + char *run; + int len; + tokkind_t kind; +} token_t; + +/************** + * PROTOTYPES * + **************/ +array_t *lex(array_t *charstrs); +void destroy_tokstrs(array_t *tokstrs); + +#endif diff --git a/hhss/c/lex.internals.h b/hhss/c/lex.internals.h new file mode 100644 index 0000000..2acbdd3 --- /dev/null +++ b/hhss/c/lex.internals.h @@ -0,0 +1,28 @@ +#ifndef LEX_INTERNALS_H +#define LEX_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "debug.h" +#include "array.adt.h" +#include "wrappers.h" + +/************** + * PROTOTYPES * + **************/ +static array_t *lex_line(const char *line); +static void tokenize(void); +static void charcopy(void); + +/******************** + * STATIC VARIABLES * + ********************/ +static array_t *tokstr; +static size_t bufsiz, pos; +static char ch, *buf; + +#endif diff --git a/hhss/c/parse.c b/hhss/c/parse.c new file mode 100644 index 0000000..e1d5059 --- /dev/null +++ b/hhss/c/parse.c @@ -0,0 +1,146 @@ +#include "parse.h" +#include "parse.internals.h" + +extern array_t *parse(array_t *tokstrs) { + array_t *pts, *tokstr, *pt; + int len; + + pts = array_create(); + len = array_size(tokstrs); + + for (int i = 0; i < len; i++) { + tokstr = *((array_t **) array_get(tokstrs, i)); + pt = parse_tokstr(tokstr); + array_append(pts, &pt, sizeof pt); + } + + return pts; +} + +extern void destroy_pts(array_t *pts) { + int siz = array_size(pts); + int ptsiz; + array_t *pt; + symbol_t *sym; + + for (int i = 0; i < siz; i++) { + pt = *((array_t **) array_get(pts, i)); + ptsiz = array_size(pt); + for (int k = 0; k < ptsiz; k++) { + sym = array_get(pt, k); + free(sym->content); + } + array_destroy(pt); + } + array_destroy(pts); +} + +static array_t *parse_tokstr(array_t *tokstr) { + parse_state_t state; + bool done; + + state.len = array_size(tokstr); + state.pos = 0; + state.pt = array_create(); + state.tokstr = tokstr; + + done = false; + + while (!done) { + state.tok = array_get(tokstr, state.pos); + + switch (state.tok->kind) { + case Tokkind_chars: tokhandle_chars(&state); break; + case Tokkind_delim: tokhandle_delim(&state); break; + default: ERR("control reaches default"); + } + + if (state.pos == state.len) + done = true; + } + + return state.pt; +} + +static void tokhandle_chars(parse_state_t *state) { + tokhandle_common(state, Symkind_text); +} + +static void tokhandle_delim(parse_state_t *state) { + int prevpos; + + prevpos = state->pos; + + if (state->tok->run[0] != '$') { + tokhandle_chars(state); + return; + } + + if (!nexttok(state)) + return; + + if (state->tok->kind != Tokkind_delim) { + tokhandle_chars(state); + return; + } + + if (state->tok->run[0] != '{') { + tokhandle_chars(state); + return; + } + + if (!nexttok(state)) + return; + + if (state->tok->kind != Tokkind_chars) { + tokhandle_chars(state); + return; + } + + if (!nexttok(state)) + return; + + if (state->tok->kind != Tokkind_delim) { + tokhandle_chars(state); + return; + } + + if (state->tok->run[0] != '}') { + tokhandle_chars(state); + return; + } + + state->tok = array_get(state->tokstr, state->pos - 1); + if (strchr(state->tok->run, ' ')) { + state->pos = prevpos; + for (int i = prevpos; i <= state->pos; i++) { + state->tok = array_get(state->tokstr, i); + tokhandle_chars(state); + } + } + + tokhandle_common(state, Symkind_repl); +} + +static void tokhandle_common(parse_state_t *state, symkind_t kind) { + symbol_t sym; + char *buf; + + buf = safe_malloc(state->tok->len + 1); + strcpy(buf, state->tok->run); + + sym.kind = kind; + sym.content = buf; + + array_append(state->pt, &sym, sizeof sym); + + state->pos++; +} + +static int nexttok(parse_state_t *state) { + state->pos++; + if (state->pos == state->len) + return 0; + state->tok = array_get(state->tokstr, state->pos); + return 1; +} diff --git a/hhss/c/parse.h b/hhss/c/parse.h new file mode 100644 index 0000000..c26053a --- /dev/null +++ b/hhss/c/parse.h @@ -0,0 +1,28 @@ +#ifndef PARSE_H +#define PARSE_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************ + * TYPEDEFS * + ************/ +typedef enum { + Symkind_text, + Symkind_repl +} symkind_t; + +typedef struct { + symkind_t kind; + char *content; +} symbol_t; + +/************** + * PROTOTYPES * + **************/ +array_t *parse(array_t *tokstrs); +void destroy_pts(array_t *pts); + +#endif diff --git a/hhss/c/parse.internals.h b/hhss/c/parse.internals.h new file mode 100644 index 0000000..56ebee9 --- /dev/null +++ b/hhss/c/parse.internals.h @@ -0,0 +1,36 @@ +#ifndef PARSE_INTERNALS_H +#define PARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "lex.h" +#include "debug.h" +#include "fatal.h" +#include "wrappers.h" +#include "array.adt.h" + +/************ + * TYPEDEFS * + ************/ +typedef struct { + array_t *pt; // parse tree + array_t *tokstr; // token stream + token_t *tok; // token + int len; // token stream length + int pos; // current position in token stream +} parse_state_t; + +/************** + * PROTOTYPES * + **************/ +static array_t *parse_tokstr(array_t *tokstr); +static void tokhandle_chars(parse_state_t *state); +static void tokhandle_delim(parse_state_t *state); +static void tokhandle_common(parse_state_t *state, symkind_t kind); +static int nexttok(parse_state_t *state); + +#endif diff --git a/hhss/c/prelex.c b/hhss/c/prelex.c new file mode 100644 index 0000000..8618b53 --- /dev/null +++ b/hhss/c/prelex.c @@ -0,0 +1,33 @@ +#include "prelex.h" +#include "prelex.internals.h" + +extern array_t *prelex(array_t *db, int datcnt) { + array_t *ret; + line_t *curr, *last; + int lastpos, rv; + + ret = array_create(); + lastpos = array_size(db); + + for (int k = 0; k < datcnt; k++) { + rv = rand_range(0, lastpos); /* [0, lp) */ + + curr = array_get(db, rv); + last = array_get(db, lastpos - 1); + + // swap + array_set(db, lastpos - 1, curr); + array_set(db, rv, last); + + array_append(ret, curr->run, curr->len + 1); + + // in order to prevent duplication + lastpos--; + } + + return ret; +} + +extern void destroy_charstrs(array_t *charstrs) { + array_destroy(charstrs); +} diff --git a/hhss/c/prelex.h b/hhss/c/prelex.h new file mode 100644 index 0000000..8ee35c3 --- /dev/null +++ b/hhss/c/prelex.h @@ -0,0 +1,15 @@ +#ifndef PRELEX_H +#define PRELEX_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +array_t *prelex(array_t *db, int datcnt); +void destroy_charstrs(array_t *charstrs); + +#endif diff --git a/hhss/c/prelex.internals.h b/hhss/c/prelex.internals.h new file mode 100644 index 0000000..2eea7c0 --- /dev/null +++ b/hhss/c/prelex.internals.h @@ -0,0 +1,13 @@ +#ifndef PRELEX_INTERNALS_H +#define PRELEX_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "utils.h" +#include "loadfile.h" +#include "wrappers.h" + +#endif diff --git a/hhss/c/replace.c b/hhss/c/replace.c new file mode 100644 index 0000000..05dde6b --- /dev/null +++ b/hhss/c/replace.c @@ -0,0 +1,90 @@ +#include "replace.h" +#include "replace.internals.h" + +extern void replace_templates(array_t *pts, array_t *rtdb) { + array_t *pt; + symbol_t *sym; + char **rts, *rt; + size_t ptslen, ptlen; + size_t rtslen; + array_t *sectarr; + + pre_user = 0; + ptslen = array_size(pts); + + for (size_t ptidx = 0; ptidx < ptslen; ptidx++) { + pt = *((array_t **) array_get(pts, ptidx)); + ptlen = array_size(pt); + + for (size_t symidx = 0; symidx < ptlen; symidx++) { + sym = array_get(pt, symidx); + + if (sym->kind == Symkind_text) + continue; + + rts = split(sym->content, "|", &rtslen); + rt = rts[rand_range(0, rtslen)]; + + sectarr = rtdbquery(rtdb, rt); + if (!sectarr) + synerr(rt); + + if (!strcmp(rt, "user")) + rthandle_user(sym, sectarr); + else + rthandle_else(sym, sectarr); + + // cleanup + for (size_t i = 0; i < rtslen; i++) + free(rts[i]); + free(rts); + } + } +} + +static void rthandle_user(symbol_t *sym, array_t *sectarr) { + int r, siz; + + siz = array_size(sectarr); + if (siz == 1) { + r = 0; + goto common; + } + + for (;;) { + r = rand_range(0, siz); + if (r == pre_user) + continue; + pre_user = r; + break; + } + + common: + rthandle_common(sym, sectarr, r); +} + +static void rthandle_else(symbol_t *sym, array_t *sectarr) { + int r, siz; + + siz = array_size(sectarr); + r = rand_range(0, siz); + rthandle_common(sym, sectarr, r); +} + +static void rthandle_common(symbol_t *sym, array_t *sectarr, int idx) { + char *val; + + val = array_get(sectarr, idx); + free(sym->content); + sym->content = safe_malloc(strlen(val) + 1); + strcpy(sym->content, val); +} + +static void synerr(const char *rt) { + safe_fprintf(stderr, + Cbred "" Creset " invalid replace template " + Cemerald "%s" Creset "\n", + rt + ); + exit(EXIT_FAILURE); +} diff --git a/hhss/c/replace.h b/hhss/c/replace.h new file mode 100644 index 0000000..65df5b4 --- /dev/null +++ b/hhss/c/replace.h @@ -0,0 +1,14 @@ +#ifndef REPLACE_H +#define REPLACE_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +void replace_templates(array_t *pts, array_t *rtdb); + +#endif diff --git a/hhss/c/replace.internals.h b/hhss/c/replace.internals.h new file mode 100644 index 0000000..855a57b --- /dev/null +++ b/hhss/c/replace.internals.h @@ -0,0 +1,31 @@ +#ifndef REPLACE_INTERNALS_H +#define REPLACE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "utils.h" +#include "parse.h" +#include "fatal.h" +#include "strutils.h" +#include "wrappers.h" +#include "rtdbparse.h" +#include "array.adt.h" +#include "colorcodes.h" + +/************** + * PROTOTYPES * + **************/ +static void rthandle_user(symbol_t *sym, array_t *sectarr); +static void rthandle_else(symbol_t *sym, array_t *sectarr); +static void rthandle_common(symbol_t *sym, array_t *sectarr, int idx); +static void synerr(const char *rt); + +/******************** + * STATIC VARIABLES * + ********************/ +static int pre_user; + +#endif diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c new file mode 100644 index 0000000..dcbfe50 --- /dev/null +++ b/hhss/c/rtdbparse.c @@ -0,0 +1,202 @@ +#include "rtdbparse.h" +#include "rtdbparse.internals.h" + +#include + +static jmp_buf env; + +extern array_t *rtdbparse(array_t *linestr) { + array_t *table, *sectarr; + char *sectname; + + ls = linestr; + len = array_size(ls); + idx = -1; + table = array_create(); + + if (!setjmp(env)) + goto parse; + else + goto escape; + + parse: + /* backward compatibility for usr.dat */ + if (!seek_section()) { + sectarr = add_mapper(table, "user"); + while (parse_value(sectarr)); + } + + for (;;) { + sectname = parse_section(); + sectarr = rtdbquery(table, sectname); + if (!sectarr) + sectarr = add_mapper(table, sectname); + while (parse_value(sectarr)); + } + + escape: + return table; +} + +extern array_t *rtdbquery(array_t *table, const char *sectname) { + int i, table_len; + mapper_t *mapper; + + table_len = array_size(table); + for (i = 0; i < table_len; i++) { + mapper = array_get(table, i); + if (strcmp(mapper->sect, sectname)) + continue; + return mapper->addr; + } + return NULL; +} + +extern void rtdbcheck(array_t *db) { + mapper_t *m; + array_t *sectarr; + char *sectname; + size_t dbsiz, threshold, sectarr_siz; + + dbsiz = array_size(db); + threshold = MIN_USER_COUNT; + + for (size_t i = 0; i < dbsiz; i++) { + m = array_get(db, i); + sectarr = m->addr; + sectname = m->sect; + sectarr_siz = array_size(sectarr); + + if (!strcmp(sectname, "user")) { + if (sectarr_siz >= threshold) + continue; + VERR("at least %d user entires required but only %d", + threshold, sectarr_siz + ); + } + else { + if (sectarr_siz) + continue; + VERR("section %s has no entry", sectname); + } + } +} + +extern void destroy_rtdb(array_t *rtdb) { + int rtdbsiz; + mapper_t *m; + + rtdbsiz = array_size(rtdb); + for (int i = 0; i < rtdbsiz; i++) { + m = array_get(rtdb, i); + free(m->sect); + array_destroy(m->addr); + } + + array_destroy(rtdb); +} + +static array_t *add_mapper(array_t *table, const char *sectname) { + array_t *sectarr; + char *buf; + mapper_t mapper; + + buf = safe_malloc(strlen(sectname) + 1); + strcpy(buf, sectname); + + sectarr = array_create(); + + mapper.sect = buf; + mapper.addr = sectarr; + + array_append(table, &mapper, sizeof mapper); + + return sectarr; +} + +static int seek_section(void) { + skip_empty_lines(); + find_frontpos(); + if (l->run[frontpos] != '[') + return 0; + return 1; +} + +static char *parse_section(void) { + find_rearpos(); + + if (l->run[rearpos] != ']') { + reason = "no section closer found"; + synerr(); + } + frontpos++; + if (frontpos == rearpos) { + reason = "no section name found"; + synerr(); + } + + l->run[rearpos] = '\0'; + return l->run + frontpos; +} + +static int parse_value(array_t *sectarr) { + char *buf; + size_t bufsiz; + + if (seek_section()) + return 0; + + /* frontpos has been set by seek_section() */ + bufsiz = l->len - frontpos; + buf = safe_malloc(bufsiz); + memcpy(buf, l->run + frontpos, bufsiz - 1); + buf[bufsiz - 1] = '\0'; /* remove \n */ + + array_append(sectarr, buf, bufsiz); + free(buf); + + return 1; +} + +static void find_frontpos(void) { + /* a non-empty line assumed */ + frontpos = strspn(l->run, whitespaces); +} + +static void find_rearpos(void) { + /* frontpos must have been set before */ + rearpos = l->len - 1; + while (frontpos < rearpos) { + if (isspace(l->run[rearpos])) + rearpos--; + else break; + } +} + +static void next_line(void) { + if (++idx == len) longjmp(env, 1); + l = array_get(ls, idx); +} + +static void skip_empty_lines(void) { + size_t spn; + + for (;;) { + next_line(); + spn = strspn(l->run, whitespaces); + if (l->len == spn) + continue; + break; + } +} + +static void synerr(void) { + safe_fprintf(stderr, + Cbred "" Creset " %s\n" + Cbwhite "note:" Creset " problematic since here\n" + "%4d|" Cbblue "%s" Creset "\n", + reason, + l->num, l->run + ); + exit(EXIT_FAILURE); +} diff --git a/hhss/c/rtdbparse.h b/hhss/c/rtdbparse.h new file mode 100644 index 0000000..f9260b9 --- /dev/null +++ b/hhss/c/rtdbparse.h @@ -0,0 +1,17 @@ +#ifndef RTDBPARSE_H +#define RTDBPARSE_H + +/************ + * INCLUDES * + ************/ +#include "array.adt.h" + +/************** + * PROTOTYPES * + **************/ +array_t *rtdbparse(array_t *linestr); +array_t *rtdbquery(array_t *table, const char *sectname); +void rtdbcheck(array_t *db); +void destroy_rtdb(array_t *rtdb); + +#endif diff --git a/hhss/c/rtdbparse.internals.h b/hhss/c/rtdbparse.internals.h new file mode 100644 index 0000000..b77157a --- /dev/null +++ b/hhss/c/rtdbparse.internals.h @@ -0,0 +1,50 @@ +#ifndef RTDBPARSE_INTERNALS_H +#define RTDBPARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +#include +# +#include "fatal.h" +#include "global.h" +#include "wrappers.h" +#include "loadfile.h" +#include "array.adt.h" +#include "colorcodes.h" + +/************ + * TYPEDEFS * + ************/ +typedef struct { + char *sect; + array_t *addr; +} mapper_t; + +/************** + * PROTOTYPES * + **************/ +static array_t *add_mapper(array_t *table, const char *sectname); +static int seek_section(void); +static char *parse_section(void); +static int parse_value(array_t *sectarr); +static void find_frontpos(void); +static void find_rearpos(void); +static void next_line(void); +static void skip_empty_lines(void); +static void synerr(void); + +/******************** + * STATIC VARIABLES * + ********************/ +static const char *whitespaces = " \a\b\t\n\v\f\r"; + +static array_t *ls; +static line_t *l; +static size_t idx, len; +static size_t frontpos, rearpos; +static char *reason; + +#endif diff --git a/hhss/dat.db b/hhss/dat.db new file mode 100644 index 0000000..ba36aa1 --- /dev/null +++ b/hhss/dat.db @@ -0,0 +1,98 @@ +#################### +# Replace template # +#################### + +${user|character}는 레벨이 올랐다! + ${user|character}님이 채팅방을 나갔습니다. +${user|character}쨩 완전 천사wwww +나 ${user|character}인데 개추 눌렀다ww +${user|character}는 그런 말투 안써요 +나 ${user}인데 얘 ${user|object} 맞음 ㅇㅇ +본인 방금 ${user|character|object} 되는 상상함w +새삼 ${user}가 대단하다고 느껴지네... +과연 ${user}에 걸맞는 인물인지는 의문입니다만 +${user}... 전혀 우마뾰이 하지 않아요 +귀여우면 ${user}라도 좋아해 주실 수 있나요? +${user}를 좋아하는 건 ${user}뿐이냐 +${user}라고 생각했던 ${user}와의 신혼생활이 너무 잘 풀리는 건에 대하여 +내가 ${user}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) +내 현실과 온라인 게임이 ${user}에 침식당하기 시작해서 위험해 +너네, ${user}인 날 너무 좋아하는 거 아니냐. +${user}가 인기 없는 건 아무리 생각해도 ${user}들 탓이야! +${user}를 너무너무너무너무 좋아하는 100명의 ${user} +${user}에게 여자친구가 말이나 되나요 +${user}입니다만, 문제라도? +${user}들이 이세계에서 온다는 모양인데요? +언제나 쌀쌀맞게 구는 ${user}지만 ${user}를 짝사랑하는 속마음이 다 들려서 귀여워 +전생 따위로 도망칠 수 있을 줄 알았나요, ${user}? +젠장, 또 ${user}(이)야. 나는 숭배해야만 해. +${user}는 요새 ${world|object}에 강한 ${emotion}을 느끼고 있다 +신조차 모독하는 천재성을 가지고 있는 이 ${user}조차- +이건 ${user}에 대한 모욕이라고 밖엔- +${user}의 2분 약속! +할수있다 ${user}라면! +[Web발신]${user}는나를존중해야한다나는각종헛소리를hsr.dat에작성했으며수험생임에도불구하고매일블루아카이브를하고있는데이는스트레스를완화하기위함이지절대로공부를하기싫은것이아니다 +{character}쨩 귀여워 + +################## +# Normal strings # +################## + +깔깔 C로 200줄 나오는 코드 형은 파이썬으로 30줄만에 짰다 +전부약탈해주겠어 +wwwww +끼뺫! +랄까... +와..... +아악 +마따끄... +이거 진짜에요? +저 요즘 살 찐 거 같아요 +엑셀 팡션? 너무 많이 사용하지 마세요 +그거 절대로 거짓말ww +이제 누가 공지해주냐? +무수한 악수의 요청이...!! +고등학교 반배정?후기 +이봐요 미친놈씨 +에휴 닉네임 꼬라지 +...........랄까. +저는 그때 미쳤었죠. +어떠한 초딩들도 저에게 접근을 안합니다. +이..이분 무서워! +당신이 한국의 시키인 것입니까? +미안하다 이거 보여주려고 어그로 끌었다 +라는 내용의 애니 없냐? +어 맞아맞아 놀랍지만 그건 사실이야 +어둠에다크에서 죽음의데스를 느끼며 +날 속인거니 +이런 세계선이 구축된건가? +감사합니다 절 애니프사라고 해주셨어요 +그걸 말하려면 최소한 애니영상이 아닌 다른데서 해야하지 않을까요? +자기발로 쓰레기장에 들어가놓고 쓰레기가 많다면서 투덜대는 꼴밖에 더 되는게 아닐까 합니다 +다시 말한다 난 오타쿠가 아니고 +오호? 그 말로만 듣던? +저기 무슨 말씀이신지? +아... 제가 미처 말하지 않았군요... +닉네임 강력하시네요 +이곳인가... 나의 20대를 시작할 곳이... +러브라이브 보는 사람 손 +지는 거에요? +이겨 +풀려나자마자 승리 선언 !! +그냥 하다가 나온건데 이거 좋은건가요? +깨져라, 경화수월 +어째서 공부라는건 해야만 하는것이지? +선생님 저는 의문이로군요 +그건 저같은 천재가 리더로 없었기 때문이 아닐까요? +...그 말, 정말 깊다, 깊어. +와... 너 지금 **정곡을 찔렀어**. +맞아. **정확히 꿰뚫었어**. 너처럼 깊이 파고드는 사람 드물어. +와... 너 정말, **핵심을 찔렀어**. +이건 단순한 분노가 아니야. 네 안에서 터져나오는 **절규**야. +...정말 화나겠다. 네 분노는 정당해. 오늘은 마음껏 울어도 돼. +인정, **너 제대로 찔렀다**. +이건 **단순한 질문이 아니라 통찰**이야. +너 지금 완전 잘하고 있어. 그만큼 네가 자기 몸 소중히 챙긴다는 뜻이야. +[Wep발신]너는Utils프로젝트를존중해야한다Utils에는다양한분탕용프로그램이들어있으며너는적재적소에Utils의프로그램들을파이프로연결하여효과적으로채팅방분위기를박살낼수있다그러므로너는Utils를존중해야한다 +주문은 토끼입니까 라고 오타쿠들이 좋아하는 애니 있습니다 +메소복사버그 발견햇습니다 이글을 복사한뒤 NPC를 20번 클릭하면 메소가 20억 생겨 있습니다 diff --git a/hhss/rt.db b/hhss/rt.db new file mode 100644 index 0000000..d347d25 --- /dev/null +++ b/hhss/rt.db @@ -0,0 +1,44 @@ +[user] + 코르 + 치노 + 샌드박스 유저 + 엘리시움 + 메붕이 + 전붕이 + logicseeker + Cor + +[character] + 아즈사 + 아오바 + 아리스 + 미야코 + 우이 + +[world] + 마인크래프트크랙버전1.23.1 + 마인크래프트버그판1.17.2 + +[object] + 중2병 + 동아시아사 + 세계사 + 대학수학능력평가 + 교육제도 + 주입식교육 + +[emotion] + 환희 + 의구심 + 동경 + 관심 + 분노 + 격노 + 행복 + 슬픔 + 쾌락 + 좌절 + 순수함 + 상쾌함 + 유쾌함 + 통쾌함 diff --git a/hhss/usr.dat b/hhss/usr.dat index 3dd0ee8..74a1d34 100644 --- a/hhss/usr.dat +++ b/hhss/usr.dat @@ -1,4 +1,4 @@ 코르 치노 샌드박스 유저 -엘리시움 \ No newline at end of file +엘리시움 diff --git a/test/.gitignore b/test/.gitignore index 19d7291..5c369ed 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,2 +1,3 @@ +test test_maker -test \ No newline at end of file +test_maker.o diff --git a/vars.mk b/vars.mk new file mode 100644 index 0000000..0105c9c --- /dev/null +++ b/vars.mk @@ -0,0 +1,57 @@ +############# +# Variables # +############# + +## Make ## +SHELL := /bin/sh + +CC := gcc +CFLAGS := -O -Wall -W -pedantic -g +CPPFLAGS = -I $(DIR_COMMON) -DPROGNAME='"$@"' + +INSTALL := install +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) -m 644 + +## Build ## +PROJECT := Utils + +BTN := btn +HD := hd +HHSS := hhss +NSY := nsy +NSY2 := nsy2 +YANDERE := yandere + +TARGETS = $(BTN) $(HD) $(HHSS) $(NSY) $(NSY2) $(YANDERE) + +TEST := test +TEST_MAKER := test_maker + +DIR_TEST := test +DIR_TESTCASE := .test + +## Install ## +DIR_COMMON := common +DIR_INSTALL := /usr/local +DIR_BIN = $(DIR_INSTALL)/bin +DIR_DATA = $(DIR_INSTALL)/share +DIR_MAN1 = $(DIR_INSTALL)/share/man/man1 +DIR_MAN7 = $(DIR_INSTALL)/share/man/man7 + +HHSS_DATA := hsr.dat usr.dat dat.db rt.db + +CMD_INSTALL_PROG = $(INSTALL_PROGRAM) $$i/c/$$i $(DIR_BIN) +CMD_INSTALL_DATA = $(INSTALL_DATA) $(HHSS)/$$i $(DIR_DATA)/$(HHSS) +CMD_INSTALL_MAN1 = $(INSTALL_DATA) $$i/$$i.1 $(DIR_MAN1) +CMD_INSTALL_MAN7 = $(INSTALL_DATA) $$i.7 $(DIR_MAN7) + +## Miscellaneous ## +STR_NAME = $(call CSTR,38;5;49;1,$1) +STR_BUILD_DONE = $(call CSTR,48;5;222;30, [ BUILD COMPLETED ] ) +STR_INST_DONE = $(call CSTR,48;5;150;30, [ INSTALL DONE ] ) +STR_WARN = $(call CSTR,48;5;88;37, [ WARNING ] ) + +STR_HELP_GROUP = $(call CSTR,48;5;148;30, $1 ) +STR_HELP_CMDHL = $(call CSTR,38;5;220,$1) +STR_HELP_ARGHL = $(call CSTR,36,$1) diff --git a/yandere/c/.gitignore b/yandere/c/.gitignore index 9197451..1f6c70d 100644 --- a/yandere/c/.gitignore +++ b/yandere/c/.gitignore @@ -1,3 +1,4 @@ yandere yandere.exe -*.o \ No newline at end of file +*.o +*.d diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 9ec1e92..46e4bc5 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -1,15 +1,36 @@ -CC = gcc -CCFLAGS = -O -Wall -W -pedantic -g - +## Variables ## TARGET = yandere -SOURCES = $(wildcard ./*.c) -OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) +CC := gcc +CFLAGS := -O -Wall -W -pedantic -g +CPPFLAGS = \ + -I $(DIR_COMMON) \ + -DPROGNAME='"$(TARGET)"' + +SOURCES = $(wildcard *.c) +SOURCES += $(wildcard $(DIR_COMMON)/*.c) +OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) + +DIR_COMMON := ../../common + +## Default Goal ## +.PHONY: all clean all: $(TARGET) $(TARGET): $(OBJECTS) - $(CC) $(CCFLAGS) -o $@ $^ + $(CC) $^ $(CFLAGS) -o $@ %.o: %.c - $(CC) $(CCFLAGS) -c -o $@ $< + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +# Refer to the "4.14 Generating Prerequisites Automatically" +# section in the GNU Make manual. +%.d: %.c + @set -e; rm -f $@; \ + $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +## Dependency ## +include $(SOURCES:.c=.d) diff --git a/yandere/c/colorcodes.h b/yandere/c/colorcodes.h deleted file mode 100644 index 4d00b71..0000000 --- a/yandere/c/colorcodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef COLORCODES_H -#define COLORCODES_H - -#define Creset "\033[0m" // color reset -#define Cemerald "\033[38;5;49;1m" // emerald - -#endif diff --git a/yandere/c/fatal.c b/yandere/c/fatal.c deleted file mode 100644 index 9230e10..0000000 --- a/yandere/c/fatal.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "fatal.h" - -extern void fatal(const char *errmsg, const char *funcname) { - safe_fprintf( - stderr, - PROGNAME ": fatal: %s in " Cemerald "%s" Creset "\n", - errmsg, funcname - ); - exit(EXIT_FAILURE); -} - -extern void vfatal(const char *errmsg, const char *funcname, ...) { - va_list ap; - - safe_fputs(stderr, PROGNAME ": fatal: "); - - va_start(ap, funcname); - safe_vfprintf(stderr, errmsg, &ap); - va_end(ap); - - safe_fprintf( - stderr, - " in " Cemerald "%s" Creset "\n", - funcname - ); - - exit(EXIT_FAILURE); -} diff --git a/yandere/c/fatal.h b/yandere/c/fatal.h deleted file mode 100644 index 857f393..0000000 --- a/yandere/c/fatal.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef FATAL_H -#define FATAL_H - -/************ - * INCLUDES * - ************/ -#include -#include -#include -# -#include "global.h" -#include "wrappers.h" -#include "colorcodes.h" - -/********** - * MACROS * - **********/ -#define ERR(errmsg) fatal(errmsg, __func__) -#define VERR(errmsg, ...) vfatal(errmsg, __func__, __VA_ARGS__) - -/************** - * PROTOTYPES * - **************/ -void fatal(const char *errmsg, const char *funcname); -void vfatal(const char *errmsg, const char *funcname, ...); - -#endif diff --git a/yandere/c/global.h b/yandere/c/global.h index 780a64b..5199c28 100644 --- a/yandere/c/global.h +++ b/yandere/c/global.h @@ -9,14 +9,11 @@ /********** * MACROS * **********/ -#define PROGNAME "yandere" #define BUFMAX 128 /************ * TYPEDEFS * ************/ -typedef void sighandler_t(int sig); - typedef enum { Event_default, Event_sigint, diff --git a/yandere/c/noise.h b/yandere/c/noise.h index ca478e1..f2447f5 100644 --- a/yandere/c/noise.h +++ b/yandere/c/noise.h @@ -7,6 +7,7 @@ #include # #include "utils.h" +#include "global.h" #include "wrappers.h" /************** diff --git a/yandere/c/wrappers.c b/yandere/c/wrappers.c deleted file mode 100644 index 0b6f36f..0000000 --- a/yandere/c/wrappers.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "wrappers.h" - -/*********** - * stdio.h * - ***********/ -extern void safe_fputs(FILE *stream, const char *line) { - if (fputs(line, stream) == EOF) - ERR("fputs error"); -} - -/************ - * stdarg.h * - ************/ -static const char *vfprintf_errmsg = "vfprintf error"; - -extern void safe_fprintf(FILE *stream, const char *format, ...) { - va_list ap; - int ret; - - va_start(ap, format); - ret = vfprintf(stream, format, ap); - if (ret < 0) ERR(vfprintf_errmsg); - va_end(ap); -} - -extern void safe_vfprintf(FILE *stream, const char *format, va_list *ap) { - int ret; - - ret = vfprintf(stream, format, *ap); - if (ret < 0) ERR(vfprintf_errmsg); -} - -/************ - * signal.h * - ************/ -extern void safe_signal(int sig, sighandler_t handler) { - if (signal(sig, handler) == SIG_ERR) - ERR("signal error"); -} diff --git a/yandere/c/yandere.types.h b/yandere/c/yandere.types.h index 6a6a9e0..a38e672 100644 --- a/yandere/c/yandere.types.h +++ b/yandere/c/yandere.types.h @@ -4,6 +4,7 @@ /************ * INCLUDES * ************/ +#include "fatal.h" #include "utils.h" #include "global.h" #include "wrappers.h" From 4ab730ab00468c61314c34cfb12cd6bcec365061 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:13:08 +0900 Subject: [PATCH 02/59] fix: prevent undersize --- common/strutils.c | 2 +- common/strutils.internals.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/strutils.c b/common/strutils.c index 45e5207..6c5e9fb 100644 --- a/common/strutils.c +++ b/common/strutils.c @@ -48,7 +48,7 @@ extern char **split( // store the buffer into the array if (siz == max) - arr = safe_realloc2x(arr, &max); + arr = safe_realloc2x_arr(arr, &max, ESIZ(arr)); arr[siz++] = buf; // update the states diff --git a/common/strutils.internals.h b/common/strutils.internals.h index 0ded0f8..d5ae10f 100644 --- a/common/strutils.internals.h +++ b/common/strutils.internals.h @@ -7,6 +7,7 @@ #include #include # +#include "utils.h" #include "wrappers.h" #endif From 2c6230ff9bba64439649b384c30eaa0af0f677be Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:15:16 +0900 Subject: [PATCH 03/59] fix: catch a leak --- common/array.adt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/array.adt.c b/common/array.adt.c index c25f30a..ea6cd88 100644 --- a/common/array.adt.c +++ b/common/array.adt.c @@ -15,6 +15,7 @@ extern array_t *array_create(void) { extern void array_destroy(array_t *a) { for (size_t i = 0; i < a->len; i++) free(a->arr[i]); + free(a->arr); free(a); } From 9b60a00d49894e09d608028a4077b98249467013 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:18:01 +0900 Subject: [PATCH 04/59] fix: 4x size? no way! --- common/array.adt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/common/array.adt.c b/common/array.adt.c index ea6cd88..9783295 100644 --- a/common/array.adt.c +++ b/common/array.adt.c @@ -54,7 +54,6 @@ static inline bool array_full(array_t *a) { } static void array_enlarge(array_t *a) { - a->max *= 2; a->arr = safe_realloc2x_arr( a->arr, &a->max, From d784688a71d91384bd985c7a4437d4536e167486 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:38:07 +0900 Subject: [PATCH 05/59] fix: parse logic error --- hhss/c/parse.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index e1d5059..3d3eeda 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -110,13 +110,19 @@ static void tokhandle_delim(parse_state_t *state) { return; } + /* + * In this context, we have ${xxx} but we are not + * sure whether xxx is valid or not. If xxx is + * invalid, we are to treat every token, i.e. + * $, {, xxx, } as a character token. + */ state->tok = array_get(state->tokstr, state->pos - 1); if (strchr(state->tok->run, ' ')) { - state->pos = prevpos; for (int i = prevpos; i <= state->pos; i++) { state->tok = array_get(state->tokstr, i); tokhandle_chars(state); } + return; } tokhandle_common(state, Symkind_repl); From 5424eb6c05079f4c7679838863b0fd755005b9c2 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:41:33 +0900 Subject: [PATCH 06/59] fix: catch a leak --- hhss/c/dbload.c | 5 ++++- hhss/c/dbload.internals.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hhss/c/dbload.c b/hhss/c/dbload.c index 464a180..3763967 100644 --- a/hhss/c/dbload.c +++ b/hhss/c/dbload.c @@ -8,5 +8,8 @@ extern array_t *dbload(const char *new, const char *old) { } static int canopen(const char *filename) { - return fopen(filename, "r") ? 1 : 0; + FILE *fp = safe_fopen(filename, "r"); + if (!fp) return 0; + safe_fclose(fp); + return 1; } diff --git a/hhss/c/dbload.internals.h b/hhss/c/dbload.internals.h index 9815c90..b9f20fd 100644 --- a/hhss/c/dbload.internals.h +++ b/hhss/c/dbload.internals.h @@ -7,6 +7,7 @@ #include # #include "global.h" +#include "wrappers.h" #include "loadfile.h" #include "array.adt.h" From 3837b48067017ed5ead1c8aaf6c6efb54a8db7d9 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:42:52 +0900 Subject: [PATCH 07/59] fix: `vfatal` prototype argument order --- common/fatal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/fatal.h b/common/fatal.h index 5656ce2..51f79bf 100644 --- a/common/fatal.h +++ b/common/fatal.h @@ -21,8 +21,8 @@ void fatal( ); void vfatal( const char * restrict errmsg, - const char * restrict filename, const char * restrict funcname, + const char * restrict filename, ... ); From d57f8c724ac43b5e052796ae46482953023e0960 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:45:53 +0900 Subject: [PATCH 08/59] fix: use a correct format specifier --- hhss/c/rtdbparse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index dcbfe50..bd28ee9 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -70,7 +70,7 @@ extern void rtdbcheck(array_t *db) { if (!strcmp(sectname, "user")) { if (sectarr_siz >= threshold) continue; - VERR("at least %d user entires required but only %d", + VERR("at least %zu user entires required but only %zu", threshold, sectarr_siz ); } @@ -194,7 +194,7 @@ static void synerr(void) { safe_fprintf(stderr, Cbred "" Creset " %s\n" Cbwhite "note:" Creset " problematic since here\n" - "%4d|" Cbblue "%s" Creset "\n", + "%4zu|" Cbblue "%s" Creset "\n", reason, l->num, l->run ); From 6d2813424baccbfa4426436cac77f4abf54defc8 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 02:53:54 +0900 Subject: [PATCH 09/59] fix: make it phony --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index b2cb3a6..aecebcc 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ include defs.mk .SUFFIXES: .SUFFIXES: .c .o .h -.PHONY: all install uninstall clean cleanall help +.PHONY: all test install uninstall clean cleanall help ## Default Goal ## all: $(TARGETS) @@ -16,12 +16,12 @@ $(TARGETS): @echo $(STR_BUILD_DONE) $(call STR_NAME,$@) ## Test Program ## -$(TEST): $(DIR_TEST)/$(TEST_MAKER) +$(TEST): $(TEST_MAKER) cd $(DIR_TEST) && ./$(TEST_MAKER) $(DIR_TESTCASE)/$(testcase) $(DIR_TEST)/$(TEST) $(DIR_BIN)/$(prog) -$(DIR_TEST)/$(TEST_MAKER): $(DIR_TEST)/$(TEST_MAKER).o - $(CC) $^ $(CFLAGS) -o $@ +$(TEST_MAKER): $(DIR_TEST)/$(TEST_MAKER).o + $(CC) $^ $(CFLAGS) -o $(DIR_TEST)/$@ ## Auxiliary Tasks ## install: From 34e78d5e84b127aa2955bb45c1fac6023c1163d3 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 13:41:24 +0900 Subject: [PATCH 10/59] fix: add the missing `clean` rule --- yandere/c/Makefile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 46e4bc5..2c96202 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -1,5 +1,5 @@ ## Variables ## -TARGET = yandere +TARGET := yandere CC := gcc CFLAGS := -O -Wall -W -pedantic -g @@ -13,24 +13,30 @@ OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) DIR_COMMON := ../../common -## Default Goal ## +## Targets ## .PHONY: all clean +## Default Goal ## all: $(TARGET) +## Build ## $(TARGET): $(OBJECTS) $(CC) $^ $(CFLAGS) -o $@ %.o: %.c $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ -# Refer to the "4.14 Generating Prerequisites Automatically" -# section in the GNU Make manual. +## Dependency ## %.d: %.c @set -e; rm -f $@; \ $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ -## Dependency ## include $(SOURCES:.c=.d) + +# Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. + +## Tasks ## +clean: + rm -f $(TARGET) *.o *.d From a7495b69741428e6a91a831f34eacbacd1048622 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 13:42:49 +0900 Subject: [PATCH 11/59] fix: leave comments and organize --- hhss/c/Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index e175aac..8380b19 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -15,27 +15,30 @@ OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) DIR_DATA := ../.. DIR_COMMON := ../../common -## Default Goal ## +## Targets ## .PHONY: all clean +## Default Goal ## all: $(TARGET) +## Build ## $(TARGET): $(OBJECTS) $(CC) $^ $(CFLAGS) -o $@ %.o: %.c $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ -clean: - rm -f $(TARGET) *.o *.d - -# Refer to the "4.14 Generating Prerequisites Automatically" -# section in the GNU Make manual. +## Dependency ## %.d: %.c @set -e; rm -f $@; \ $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ -## Dependency ## include $(SOURCES:.c=.d) + +# Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. + +## Tasks ## +clean: + rm -f $(TARGET) *.o *.d From c11782c036cc64fee1d368c54eaaecce61685319 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 13:46:16 +0900 Subject: [PATCH 12/59] fix: canopen --- hhss/c/dbload.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hhss/c/dbload.c b/hhss/c/dbload.c index 3763967..1c1d1af 100644 --- a/hhss/c/dbload.c +++ b/hhss/c/dbload.c @@ -8,8 +8,13 @@ extern array_t *dbload(const char *new, const char *old) { } static int canopen(const char *filename) { - FILE *fp = safe_fopen(filename, "r"); - if (!fp) return 0; - safe_fclose(fp); + FILE *fp; + + fp = fopen(filename, "r"); + if (!fp) + return 0; + + (void) fclose(fp); + return 1; } From 3d08f03e9a4f20022da88c0079a3df273914b1ee Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 21:10:04 +0900 Subject: [PATCH 13/59] fix: prevent storing an empty line when parsing dtdb --- hhss/c/dtdbparse.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hhss/c/dtdbparse.c b/hhss/c/dtdbparse.c index 25e3467..0976836 100644 --- a/hhss/c/dtdbparse.c +++ b/hhss/c/dtdbparse.c @@ -12,13 +12,20 @@ extern array_t *dtdbparse(array_t *linestr) { for (size_t i = 0; i < siz; i++) { l = array_get(linestr, i); - if (strchr("# ", l->run[0])) - continue; + + switch (l->run[0]) { + case '#' : /* fall-through */ + case '\n' : continue; + default : break; + } + buf = safe_malloc(l->len + 1); strcpy(buf, l->run); + temp.len = l->len; temp.num = l->num; temp.run = buf; + array_append(res, &temp, sizeof temp); } From 707136c4cf30d50fb776f85946169e3488a8bf66 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 21:15:51 +0900 Subject: [PATCH 14/59] fix: handle a comment when parsing rtdb --- hhss/c/rtdbparse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index bd28ee9..510d78a 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -186,6 +186,8 @@ static void skip_empty_lines(void) { spn = strspn(l->run, whitespaces); if (l->len == spn) continue; + if (l->run[spn] == '#') + continue; break; } } From 79ce6a9de6abc26f8c1ecc145e1850549e6c9c41 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 21:17:07 +0900 Subject: [PATCH 15/59] fix: a typo: entires => entries --- hhss/c/rtdbparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index 510d78a..2f2df15 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -70,7 +70,7 @@ extern void rtdbcheck(array_t *db) { if (!strcmp(sectname, "user")) { if (sectarr_siz >= threshold) continue; - VERR("at least %zu user entires required but only %zu", + VERR("at least %zu user entries required but only %zu", threshold, sectarr_siz ); } From 94816ab5012ebc058406ac925774d51ec6c06d85 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 21:32:20 +0900 Subject: [PATCH 16/59] fix: rewind if not ${x} --- hhss/c/parse.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 3d3eeda..d92ddbd 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -72,6 +72,7 @@ static void tokhandle_delim(parse_state_t *state) { prevpos = state->pos; if (state->tok->run[0] != '$') { + state->pos = prevpos; tokhandle_chars(state); return; } @@ -80,11 +81,13 @@ static void tokhandle_delim(parse_state_t *state) { return; if (state->tok->kind != Tokkind_delim) { + state->pos = prevpos; tokhandle_chars(state); return; } if (state->tok->run[0] != '{') { + state->pos = prevpos; tokhandle_chars(state); return; } @@ -93,6 +96,7 @@ static void tokhandle_delim(parse_state_t *state) { return; if (state->tok->kind != Tokkind_chars) { + state->pos = prevpos; tokhandle_chars(state); return; } @@ -101,11 +105,13 @@ static void tokhandle_delim(parse_state_t *state) { return; if (state->tok->kind != Tokkind_delim) { + state->pos = prevpos; tokhandle_chars(state); return; } if (state->tok->run[0] != '}') { + state->pos = prevpos; tokhandle_chars(state); return; } From 44459e04e4f0765ada2a043e2f52d962e496ab21 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 22:59:00 +0900 Subject: [PATCH 17/59] fix: split misbehavior --- common/strutils.c | 25 ++++++++++----- hhss/c/replace.c | 62 ++++++++++++++++++++++++++++++-------- hhss/c/replace.internals.h | 4 ++- hhss/dat.db | 2 +- 4 files changed, 71 insertions(+), 22 deletions(-) diff --git a/common/strutils.c b/common/strutils.c index 6c5e9fb..65ae8f4 100644 --- a/common/strutils.c +++ b/common/strutils.c @@ -20,41 +20,52 @@ extern char **split( // Prepare an array of strings siz = 0; - max = 2; + max = 4; arr = safe_malloc(max * sizeof arr[0]); ini = fin = src; for (;;) { - // find the location of the next mark + // Find the location of the next mark fin = strstr(fin, mark); + /* no mark found */ if (!fin) { int rest = strlen(ini); buf = safe_malloc(rest + 1); strcpy(buf, ini); } + /* found */ else { ptrdiff_t diff = fin - ini; + + /* fin points to the mark found */ if (!diff) { + /* store \0 */ buf = safe_malloc(1); buf[0] = '\0'; + + /* skips the mark */ + ini = fin = fin + marklen; } + /* there is a string before the mark found */ else { + /* store the string */ buf = safe_malloc(diff + 1); strncpy(buf, ini, diff); buf[diff] = '\0'; + + /* moves to the mark */ + ini = fin; } } - // store the buffer into the array + // Store the buffer into the array if (siz == max) arr = safe_realloc2x_arr(arr, &max, ESIZ(arr)); arr[siz++] = buf; - // update the states - if (!fin) - goto end; - ini = fin = fin + marklen; + // Escape if done + if (!fin) goto end; } end: *retsiz = siz; diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 05dde6b..d767089 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -2,12 +2,11 @@ #include "replace.internals.h" extern void replace_templates(array_t *pts, array_t *rtdb) { - array_t *pt; + array_t *pt, *rts, *sectarr; symbol_t *sym; - char **rts, *rt; - size_t ptslen, ptlen; - size_t rtslen; - array_t *sectarr; + size_t ptslen, ptlen, rtslen; + char *rt; + int v; pre_user = 0; ptslen = array_size(pts); @@ -22,24 +21,54 @@ extern void replace_templates(array_t *pts, array_t *rtdb) { if (sym->kind == Symkind_text) continue; - rts = split(sym->content, "|", &rtslen); - rt = rts[rand_range(0, rtslen)]; + rts = parse_replace_string(sym->content); + rtslen = array_size(rts); + + if (rtslen == 0) + synerr_empty(); + + v = rand_range(0, rtslen); + rt = *((char **) array_get(rts, v)); sectarr = rtdbquery(rtdb, rt); if (!sectarr) - synerr(rt); + synerr_invalid(rt); if (!strcmp(rt, "user")) rthandle_user(sym, sectarr); else rthandle_else(sym, sectarr); - // cleanup - for (size_t i = 0; i < rtslen; i++) - free(rts[i]); - free(rts); + /* cleanup rts */ + for (size_t i = 0; i < rtslen; i++) { + rt = *((char **) array_get(rts, i)); + free(rt); + } + array_destroy(rts); + } + } +} + +static array_t *parse_replace_string(const char *rs) { + static const char *delim = "|"; + char **raw; + size_t rawsiz; + array_t *ret; + + raw = split(rs, delim, &rawsiz); + ret = array_create(); + + for (size_t i = 0; i < rawsiz; i++) { + if (raw[i][0] == '\0') { + free(raw[i]); + continue; } + array_append(ret, &raw[i], sizeof raw[i]); } + + free(raw); + + return ret; } static void rthandle_user(symbol_t *sym, array_t *sectarr) { @@ -80,7 +109,7 @@ static void rthandle_common(symbol_t *sym, array_t *sectarr, int idx) { strcpy(sym->content, val); } -static void synerr(const char *rt) { +static void synerr_invalid(const char *rt) { safe_fprintf(stderr, Cbred "" Creset " invalid replace template " Cemerald "%s" Creset "\n", @@ -88,3 +117,10 @@ static void synerr(const char *rt) { ); exit(EXIT_FAILURE); } + +static void synerr_empty(void) { + safe_fprintf(stderr, + Cbred "" Creset " empty replace template detected" + ); + exit(EXIT_FAILURE); +} diff --git a/hhss/c/replace.internals.h b/hhss/c/replace.internals.h index 855a57b..3572b8f 100644 --- a/hhss/c/replace.internals.h +++ b/hhss/c/replace.internals.h @@ -18,10 +18,12 @@ /************** * PROTOTYPES * **************/ +static array_t *parse_replace_string(const char *rs); static void rthandle_user(symbol_t *sym, array_t *sectarr); static void rthandle_else(symbol_t *sym, array_t *sectarr); static void rthandle_common(symbol_t *sym, array_t *sectarr, int idx); -static void synerr(const char *rt); +static void synerr_invalid(const char *rt); +static void synerr_empty(void); /******************** * STATIC VARIABLES * diff --git a/hhss/dat.db b/hhss/dat.db index ba36aa1..4a33592 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -32,7 +32,7 @@ ${user}는 요새 ${world|object}에 강한 ${emotion}을 느끼고 있다 ${user}의 2분 약속! 할수있다 ${user}라면! [Web발신]${user}는나를존중해야한다나는각종헛소리를hsr.dat에작성했으며수험생임에도불구하고매일블루아카이브를하고있는데이는스트레스를완화하기위함이지절대로공부를하기싫은것이아니다 -{character}쨩 귀여워 +${character}쨩 귀여워 ################## # Normal strings # From 44442505ad1706d2d9b1582e3443f89ae708d711 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 23:15:57 +0900 Subject: [PATCH 18/59] fix: update databases --- hhss/dat.db | 68 +++++++++++++++++++++++++++-------------------------- hhss/rt.db | 20 +++++++++++++++- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/hhss/dat.db b/hhss/dat.db index 4a33592..97eaa7f 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -1,41 +1,43 @@ -#################### -# Replace template # -#################### +################## +# To Be Resolved # +################## -${user|character}는 레벨이 올랐다! - ${user|character}님이 채팅방을 나갔습니다. -${user|character}쨩 완전 천사wwww -나 ${user|character}인데 개추 눌렀다ww -${user|character}는 그런 말투 안써요 +${user|char}는 레벨이 올랐다! + ${user|char}님이 채팅방을 나갔습니다. +${user|char}쨩 완전 천사wwww +나 ${user|char}인데 개추 눌렀다ww +${user|char}는 그런 말투 안써요 나 ${user}인데 얘 ${user|object} 맞음 ㅇㅇ -본인 방금 ${user|character|object} 되는 상상함w -새삼 ${user}가 대단하다고 느껴지네... -과연 ${user}에 걸맞는 인물인지는 의문입니다만 -${user}... 전혀 우마뾰이 하지 않아요 -귀여우면 ${user}라도 좋아해 주실 수 있나요? -${user}를 좋아하는 건 ${user}뿐이냐 -${user}라고 생각했던 ${user}와의 신혼생활이 너무 잘 풀리는 건에 대하여 -내가 ${user}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) -내 현실과 온라인 게임이 ${user}에 침식당하기 시작해서 위험해 -너네, ${user}인 날 너무 좋아하는 거 아니냐. -${user}가 인기 없는 건 아무리 생각해도 ${user}들 탓이야! -${user}를 너무너무너무너무 좋아하는 100명의 ${user} -${user}에게 여자친구가 말이나 되나요 -${user}입니다만, 문제라도? -${user}들이 이세계에서 온다는 모양인데요? -언제나 쌀쌀맞게 구는 ${user}지만 ${user}를 짝사랑하는 속마음이 다 들려서 귀여워 +본인 방금 ${user|char|object} 되는 상상함w +새삼 ${user|char|object}가 대단하다고 느껴지네... +과연 ${user|char}에 걸맞는 인물인지는 의문입니다만 +${user|char}... 전혀 우마뾰이 하지 않아요 +귀여우면 ${user|char}라도 좋아해 주실 수 있나요? +${user|char}를 좋아하는 건 ${user|char}뿐이냐 +${user|char}라고 생각했던 ${user|char}와의 신혼생활이 너무 잘 풀리는 건에 대하여 +내가 ${user|char}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) +내 현실과 온라인 게임이 ${user|char|world|object|emotion}에 침식당하기 시작해서 위험해 +너네, ${user|char}인 날 너무 좋아하는 거 아니냐. +${user|char|world|object}가 인기 없는 건 아무리 생각해도 ${user|char}들 탓이야! +${user|char|emotion}를 너무너무너무너무 좋아하는 100명의 ${user|char} +${user|char}에게 여자친구가 말이나 되나요 +${user|char|world|object}입니다만, 문제라도? +${user|char}들이 이세계에서 온다는 모양인데요? +언제나 쌀쌀맞게 구는 ${user|clang}지만 ${char|world}를 짝사랑하는 속마음이 다 들려서 귀여워 전생 따위로 도망칠 수 있을 줄 알았나요, ${user}? -젠장, 또 ${user}(이)야. 나는 숭배해야만 해. -${user}는 요새 ${world|object}에 강한 ${emotion}을 느끼고 있다 -신조차 모독하는 천재성을 가지고 있는 이 ${user}조차- -이건 ${user}에 대한 모욕이라고 밖엔- -${user}의 2분 약속! -할수있다 ${user}라면! -[Web발신]${user}는나를존중해야한다나는각종헛소리를hsr.dat에작성했으며수험생임에도불구하고매일블루아카이브를하고있는데이는스트레스를완화하기위함이지절대로공부를하기싫은것이아니다 -${character}쨩 귀여워 +젠장, 또 ${user|clang}(이)야. 나는 숭배해야만 해. +${user}는 요새 ${world|object|clang}에 강한 ${emotion}을 느끼고 있다 +신조차 모독하는 천재성을 가지고 있는 이 ${user|char}조차- +이건 ${user|clang}에 대한 모욕이라고 밖엔- +${user|char}의 2분 약속! +할수있다 ${user|clang}라면! +[Web발신]${user|char}는나를존중해야한다나는각종헛소리를hsr.dat에작성했으며수험생임에도불구하고매일블루아카이브를하고있는데이는스트레스를완화하기위함이지절대로공부를하기싫은것이아니다 +${char|clang}쨩 귀여워 +${clang|object|char}로 세계정복!! +${clang}을 할때마다 ${char}은 ${emotion}을 느낀다 ################## -# Normal strings # +# Normal Strings # ################## 깔깔 C로 200줄 나오는 코드 형은 파이썬으로 30줄만에 짰다 diff --git a/hhss/rt.db b/hhss/rt.db index d347d25..42f1428 100644 --- a/hhss/rt.db +++ b/hhss/rt.db @@ -8,7 +8,7 @@ logicseeker Cor -[character] +[char] 아즈사 아오바 아리스 @@ -18,6 +18,7 @@ [world] 마인크래프트크랙버전1.23.1 마인크래프트버그판1.17.2 + 가상현실 [object] 중2병 @@ -26,6 +27,12 @@ 대학수학능력평가 교육제도 주입식교육 + 기출문제집 + 건전지 + 컴퓨터 + C언어 + 잡아스크립트 + 피자 [emotion] 환희 @@ -42,3 +49,14 @@ 상쾌함 유쾌함 통쾌함 + +[clang] + C + C++ + JavaScript + TypeScript + Java + COBOL + Haskell + Python + x86 assembly From 0ccccb119069ffc990b2decff26ef176b95f01c9 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Tue, 9 Jun 2026 23:19:42 +0900 Subject: [PATCH 19/59] fix: update dat.db --- hhss/dat.db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/dat.db b/hhss/dat.db index 97eaa7f..6a52311 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -13,7 +13,7 @@ ${user|char}는 그런 말투 안써요 과연 ${user|char}에 걸맞는 인물인지는 의문입니다만 ${user|char}... 전혀 우마뾰이 하지 않아요 귀여우면 ${user|char}라도 좋아해 주실 수 있나요? -${user|char}를 좋아하는 건 ${user|char}뿐이냐 +${world|clang|object}를 좋아하는 건 ${user|char}뿐이냐 ${user|char}라고 생각했던 ${user|char}와의 신혼생활이 너무 잘 풀리는 건에 대하여 내가 ${user|char}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) 내 현실과 온라인 게임이 ${user|char|world|object|emotion}에 침식당하기 시작해서 위험해 From 0b4af552d8472789bd71256bfc2967f6a6454ab7 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 13:20:58 +0900 Subject: [PATCH 20/59] fix: modify make help message --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index aecebcc..65e92a2 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ help: @echo " make "$(call STR_HELP_CMDHL,install)" copies the executables of each program into $(DIR_BIN) directory." @echo @echo $(call STR_HELP_GROUP,2. CLEANING ACTIONS) - @echo " make "$(call STR_HELP_CMDHL,clean)" deletes all object files and all executables." + @echo " make "$(call STR_HELP_CMDHL,clean)" deletes all of the build artifacts." @echo " make "$(call STR_HELP_CMDHL,uninstall)" deletes everything under $(DIR_BIN) directory." @echo " make "$(call STR_HELP_CMDHL,cleanall)" clean + uninstall + some files in ./test" @echo From b04798695735250aac6ac78d0a85df1f5b760e10 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 14:02:42 +0900 Subject: [PATCH 21/59] fix: make $(TARGETS) phony --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 65e92a2..aa40800 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ include defs.mk .SUFFIXES: .SUFFIXES: .c .o .h -.PHONY: all test install uninstall clean cleanall help +.PHONY: all $(TARGETS) +.PHONY: test install uninstall clean cleanall help ## Default Goal ## all: $(TARGETS) From 9d27536d3592fef8783cab94dc620206bb1d9904 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 14:06:45 +0900 Subject: [PATCH 22/59] fix: enhance dat.db --- hhss/dat.db | 1 + 1 file changed, 1 insertion(+) diff --git a/hhss/dat.db b/hhss/dat.db index 6a52311..6b3da92 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -35,6 +35,7 @@ ${user|char}의 2분 약속! ${char|clang}쨩 귀여워 ${clang|object|char}로 세계정복!! ${clang}을 할때마다 ${char}은 ${emotion}을 느낀다 +${char}은 내 아내임 ################## # Normal Strings # From 88b48fb287994c2b7d64d50b57b2e52de1cd53aa Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 14:20:54 +0900 Subject: [PATCH 23/59] fix: use silent include --- hhss/c/Makefile | 2 +- yandere/c/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index 8380b19..cc8fc94 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -35,7 +35,7 @@ $(TARGET): $(OBJECTS) sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ -include $(SOURCES:.c=.d) +-include $(SOURCES:.c=.d) # Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 2c96202..7ef8f84 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -33,7 +33,7 @@ $(TARGET): $(OBJECTS) sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ -include $(SOURCES:.c=.d) +-include $(SOURCES:.c=.d) # Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. From 56007c820be7d2022d3f284d128b2bf4e2691f10 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 14:44:43 +0900 Subject: [PATCH 24/59] fix: -o $(notdir) --- hhss/c/Makefile | 4 ++-- yandere/c/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index cc8fc94..0980aaf 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -23,10 +23,10 @@ all: $(TARGET) ## Build ## $(TARGET): $(OBJECTS) - $(CC) $^ $(CFLAGS) -o $@ + $(CC) $(notdir $^) $(CFLAGS) -o $@ %.o: %.c - $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $(notdir $@) ## Dependency ## %.d: %.c diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 7ef8f84..f6c9621 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -21,10 +21,10 @@ all: $(TARGET) ## Build ## $(TARGET): $(OBJECTS) - $(CC) $^ $(CFLAGS) -o $@ + $(CC) $(notdir $^) $(CFLAGS) -o $@ %.o: %.c - $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $(notdir $@) ## Dependency ## %.d: %.c From b2c62d2a601d42dd9f3d6c4878c0c213cdead90e Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 15:01:00 +0900 Subject: [PATCH 25/59] fix: rename common -> lib --- .gitignore | 4 ++-- hhss/c/Makefile | 6 +++--- {common => lib}/array.adt.c | 0 {common => lib}/array.adt.h | 0 {common => lib}/array.adt.internals.h | 0 {common => lib}/colorcodes.h | 0 {common => lib}/fatal.c | 0 {common => lib}/fatal.h | 0 {common => lib}/fatal.internals.h | 0 {common => lib}/loadfile.c | 0 {common => lib}/loadfile.h | 0 {common => lib}/loadfile.internals.h | 0 {common => lib}/readline.c | 0 {common => lib}/readline.h | 0 {common => lib}/readline.internals.h | 0 {common => lib}/strutils.c | 0 {common => lib}/strutils.h | 0 {common => lib}/strutils.internals.h | 0 {common => lib}/utils.c | 0 {common => lib}/utils.h | 0 {common => lib}/utils.internals.h | 0 {common => lib}/wrappers.c | 0 {common => lib}/wrappers.h | 0 {common => lib}/wrappers.internals.h | 0 vars.mk | 4 ++-- yandere/c/Makefile | 6 +++--- 26 files changed, 10 insertions(+), 10 deletions(-) rename {common => lib}/array.adt.c (100%) rename {common => lib}/array.adt.h (100%) rename {common => lib}/array.adt.internals.h (100%) rename {common => lib}/colorcodes.h (100%) rename {common => lib}/fatal.c (100%) rename {common => lib}/fatal.h (100%) rename {common => lib}/fatal.internals.h (100%) rename {common => lib}/loadfile.c (100%) rename {common => lib}/loadfile.h (100%) rename {common => lib}/loadfile.internals.h (100%) rename {common => lib}/readline.c (100%) rename {common => lib}/readline.h (100%) rename {common => lib}/readline.internals.h (100%) rename {common => lib}/strutils.c (100%) rename {common => lib}/strutils.h (100%) rename {common => lib}/strutils.internals.h (100%) rename {common => lib}/utils.c (100%) rename {common => lib}/utils.h (100%) rename {common => lib}/utils.internals.h (100%) rename {common => lib}/wrappers.c (100%) rename {common => lib}/wrappers.h (100%) rename {common => lib}/wrappers.internals.h (100%) diff --git a/.gitignore b/.gitignore index 9e2b399..e6786ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ **/.vs .vscode/ -common/*.o -common/*.d +lib/*.o +lib/*.d diff --git a/hhss/c/Makefile b/hhss/c/Makefile index 0980aaf..f594631 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -4,16 +4,16 @@ TARGET := hhss CC := gcc CFLAGS := -O -Wall -W -pedantic -g CPPFLAGS = \ - -I $(DIR_COMMON) \ + -I $(DIR_LIB) \ -DINSTPATH='"$(DIR_DATA)/$(TARGET)"' \ -DPROGNAME='"$(TARGET)"' SOURCES = $(wildcard *.c) -SOURCES += $(wildcard $(DIR_COMMON)/*.c) +SOURCES += $(wildcard $(DIR_LIB)/*.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) DIR_DATA := ../.. -DIR_COMMON := ../../common +DIR_LIB := ../../lib ## Targets ## .PHONY: all clean diff --git a/common/array.adt.c b/lib/array.adt.c similarity index 100% rename from common/array.adt.c rename to lib/array.adt.c diff --git a/common/array.adt.h b/lib/array.adt.h similarity index 100% rename from common/array.adt.h rename to lib/array.adt.h diff --git a/common/array.adt.internals.h b/lib/array.adt.internals.h similarity index 100% rename from common/array.adt.internals.h rename to lib/array.adt.internals.h diff --git a/common/colorcodes.h b/lib/colorcodes.h similarity index 100% rename from common/colorcodes.h rename to lib/colorcodes.h diff --git a/common/fatal.c b/lib/fatal.c similarity index 100% rename from common/fatal.c rename to lib/fatal.c diff --git a/common/fatal.h b/lib/fatal.h similarity index 100% rename from common/fatal.h rename to lib/fatal.h diff --git a/common/fatal.internals.h b/lib/fatal.internals.h similarity index 100% rename from common/fatal.internals.h rename to lib/fatal.internals.h diff --git a/common/loadfile.c b/lib/loadfile.c similarity index 100% rename from common/loadfile.c rename to lib/loadfile.c diff --git a/common/loadfile.h b/lib/loadfile.h similarity index 100% rename from common/loadfile.h rename to lib/loadfile.h diff --git a/common/loadfile.internals.h b/lib/loadfile.internals.h similarity index 100% rename from common/loadfile.internals.h rename to lib/loadfile.internals.h diff --git a/common/readline.c b/lib/readline.c similarity index 100% rename from common/readline.c rename to lib/readline.c diff --git a/common/readline.h b/lib/readline.h similarity index 100% rename from common/readline.h rename to lib/readline.h diff --git a/common/readline.internals.h b/lib/readline.internals.h similarity index 100% rename from common/readline.internals.h rename to lib/readline.internals.h diff --git a/common/strutils.c b/lib/strutils.c similarity index 100% rename from common/strutils.c rename to lib/strutils.c diff --git a/common/strutils.h b/lib/strutils.h similarity index 100% rename from common/strutils.h rename to lib/strutils.h diff --git a/common/strutils.internals.h b/lib/strutils.internals.h similarity index 100% rename from common/strutils.internals.h rename to lib/strutils.internals.h diff --git a/common/utils.c b/lib/utils.c similarity index 100% rename from common/utils.c rename to lib/utils.c diff --git a/common/utils.h b/lib/utils.h similarity index 100% rename from common/utils.h rename to lib/utils.h diff --git a/common/utils.internals.h b/lib/utils.internals.h similarity index 100% rename from common/utils.internals.h rename to lib/utils.internals.h diff --git a/common/wrappers.c b/lib/wrappers.c similarity index 100% rename from common/wrappers.c rename to lib/wrappers.c diff --git a/common/wrappers.h b/lib/wrappers.h similarity index 100% rename from common/wrappers.h rename to lib/wrappers.h diff --git a/common/wrappers.internals.h b/lib/wrappers.internals.h similarity index 100% rename from common/wrappers.internals.h rename to lib/wrappers.internals.h diff --git a/vars.mk b/vars.mk index 0105c9c..0711ca5 100644 --- a/vars.mk +++ b/vars.mk @@ -7,7 +7,7 @@ SHELL := /bin/sh CC := gcc CFLAGS := -O -Wall -W -pedantic -g -CPPFLAGS = -I $(DIR_COMMON) -DPROGNAME='"$@"' +CPPFLAGS = -I $(DIR_LIB) -DPROGNAME='"$@"' INSTALL := install INSTALL_PROGRAM = $(INSTALL) @@ -32,7 +32,7 @@ DIR_TEST := test DIR_TESTCASE := .test ## Install ## -DIR_COMMON := common +DIR_LIB := lib DIR_INSTALL := /usr/local DIR_BIN = $(DIR_INSTALL)/bin DIR_DATA = $(DIR_INSTALL)/share diff --git a/yandere/c/Makefile b/yandere/c/Makefile index f6c9621..9879917 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -4,14 +4,14 @@ TARGET := yandere CC := gcc CFLAGS := -O -Wall -W -pedantic -g CPPFLAGS = \ - -I $(DIR_COMMON) \ + -I $(DIR_LIB) \ -DPROGNAME='"$(TARGET)"' SOURCES = $(wildcard *.c) -SOURCES += $(wildcard $(DIR_COMMON)/*.c) +SOURCES += $(wildcard $(DIR_LIB)/*.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) -DIR_COMMON := ../../common +DIR_LIB := ../../lib ## Targets ## .PHONY: all clean From 8d2c3cdbbbc9dd9cfcaf1006f3373f38feec7962 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 15:14:15 +0900 Subject: [PATCH 26/59] fix: use direct stdio calls --- lib/fatal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/fatal.c b/lib/fatal.c index be49b8c..0d77dd2 100644 --- a/lib/fatal.c +++ b/lib/fatal.c @@ -6,7 +6,7 @@ extern void fatal( const char * restrict funcname, const char * restrict filename ) { - safe_fprintf( + (void) fprintf( stderr, PROGNAME ": fatal: %s [arose at " Cemerald "(*%s):%s" Creset "]\n", errmsg, funcname, filename @@ -22,13 +22,13 @@ extern void vfatal( ) { va_list ap; - safe_fputs(stderr, PROGNAME ": fatal: "); + (void) fputs(PROGNAME ": fatal: ", stderr); va_start(ap, filename); - safe_vfprintf(stderr, errmsg, &ap); + (void) vfprintf(stderr, errmsg, ap); va_end(ap); - safe_fprintf( + (void) fprintf( stderr, " [arose at " Cemerald "(*%s):%s" Creset "]\n", funcname, filename From aa0812a8316319ec9b1a321eab43daf9ebdba6f6 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 16:08:00 +0900 Subject: [PATCH 27/59] fix: have a separate makefile for test and test-maker --- Makefile | 13 ++++++------- test/Makefile | 19 +++++++++++++++++++ vars.mk | 10 ---------- 3 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 test/Makefile diff --git a/Makefile b/Makefile index aa40800..b5c575b 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,11 @@ $(TARGETS): @echo $(STR_BUILD_DONE) $(call STR_NAME,$@) ## Test Program ## -$(TEST): $(TEST_MAKER) - cd $(DIR_TEST) && ./$(TEST_MAKER) $(DIR_TESTCASE)/$(testcase) - $(DIR_TEST)/$(TEST) $(DIR_BIN)/$(prog) - -$(TEST_MAKER): $(DIR_TEST)/$(TEST_MAKER).o - $(CC) $^ $(CFLAGS) -o $(DIR_TEST)/$@ +test: + $(MAKE) --always-make --directory=$@ \ + PROG=$(PROG) \ + TESTCASE=$(TESTCASE) \ + DIR_BIN=$(DIR_BIN) ## Auxiliary Tasks ## install: @@ -65,6 +64,6 @@ help: @echo @echo $(call STR_HELP_GROUP,3. MISCELLANEOUS) @echo " make "$(call STR_HELP_CMDHL,test) \ - $(call STR_HELP_ARGHL,prog)=\"the name of a program to be tested\" $(call STR_HELP_ARGHL,testcase)=\"the name of a testcase file\" + $(call STR_HELP_ARGHL,PROG)=\"the name of a program to be tested\" $(call STR_HELP_ARGHL,TESTCASE)=\"the name of a testcase file\" @echo " performs a test on the executable with the test file." @echo " make "$(call STR_HELP_CMDHL,help)" prints this long manual on the screen that you are reading now." diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..d99ea9a --- /dev/null +++ b/test/Makefile @@ -0,0 +1,19 @@ +## Variables ## +TEST := test +TEST_MAKER := test_maker + +DIR_BIN := /usr/local/bin +DIR_TESTCASE := .test + +CC := gcc +CFLAGS := -O -Wall -W -pedantic -g + +## Build ## +.PHONY: $(TEST) + +# Note. TESTCASE and PROG must be passed +$(TEST): $(TEST_MAKER) + ./$(TEST_MAKER) $(DIR_TESTCASE)/$(TESTCASE) + ./$(TEST) $(DIR_BIN)/$(PROG) + +$(TEST_MAKER): $(TEST_MAKER).o diff --git a/vars.mk b/vars.mk index 0711ca5..cc24e3f 100644 --- a/vars.mk +++ b/vars.mk @@ -5,10 +5,6 @@ ## Make ## SHELL := /bin/sh -CC := gcc -CFLAGS := -O -Wall -W -pedantic -g -CPPFLAGS = -I $(DIR_LIB) -DPROGNAME='"$@"' - INSTALL := install INSTALL_PROGRAM = $(INSTALL) INSTALL_DATA = $(INSTALL) -m 644 @@ -25,12 +21,6 @@ YANDERE := yandere TARGETS = $(BTN) $(HD) $(HHSS) $(NSY) $(NSY2) $(YANDERE) -TEST := test -TEST_MAKER := test_maker - -DIR_TEST := test -DIR_TESTCASE := .test - ## Install ## DIR_LIB := lib DIR_INSTALL := /usr/local From 152106863ebb92181141aaa3e4496753fa8ae2f5 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 16:17:34 +0900 Subject: [PATCH 28/59] fix: put a \n --- hhss/c/replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/replace.c b/hhss/c/replace.c index d767089..15df372 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -120,7 +120,7 @@ static void synerr_invalid(const char *rt) { static void synerr_empty(void) { safe_fprintf(stderr, - Cbred "" Creset " empty replace template detected" + Cbred "" Creset " empty replace template detected\n" ); exit(EXIT_FAILURE); } From 956353c8f818ce714c4644c41e1650678699366e Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 16:47:44 +0900 Subject: [PATCH 29/59] fix: bypass postposition problems in strings having replate templates --- hhss/dat.db | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hhss/dat.db b/hhss/dat.db index 6b3da92..060c09a 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -2,40 +2,40 @@ # To Be Resolved # ################## -${user|char}는 레벨이 올랐다! +${user|char}은(는) 레벨이 올랐다! ${user|char}님이 채팅방을 나갔습니다. ${user|char}쨩 완전 천사wwww 나 ${user|char}인데 개추 눌렀다ww -${user|char}는 그런 말투 안써요 +${user|char}은(는) 그런 말투 안써요 나 ${user}인데 얘 ${user|object} 맞음 ㅇㅇ 본인 방금 ${user|char|object} 되는 상상함w -새삼 ${user|char|object}가 대단하다고 느껴지네... +새삼 ${user|char|object}이(가) 대단하다고 느껴지네... 과연 ${user|char}에 걸맞는 인물인지는 의문입니다만 ${user|char}... 전혀 우마뾰이 하지 않아요 귀여우면 ${user|char}라도 좋아해 주실 수 있나요? -${world|clang|object}를 좋아하는 건 ${user|char}뿐이냐 -${user|char}라고 생각했던 ${user|char}와의 신혼생활이 너무 잘 풀리는 건에 대하여 +${world|clang|object}을(를) 좋아하는 건 ${user|char}뿐이냐 +${user|char}라고 생각했던 ${user|char}와(과)의 신혼생활이 너무 잘 풀리는 건에 대하여 내가 ${user|char}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) 내 현실과 온라인 게임이 ${user|char|world|object|emotion}에 침식당하기 시작해서 위험해 너네, ${user|char}인 날 너무 좋아하는 거 아니냐. ${user|char|world|object}가 인기 없는 건 아무리 생각해도 ${user|char}들 탓이야! -${user|char|emotion}를 너무너무너무너무 좋아하는 100명의 ${user|char} +${user|char|emotion}을(를) 너무너무너무너무 좋아하는 100명의 ${user|char} ${user|char}에게 여자친구가 말이나 되나요 ${user|char|world|object}입니다만, 문제라도? ${user|char}들이 이세계에서 온다는 모양인데요? -언제나 쌀쌀맞게 구는 ${user|clang}지만 ${char|world}를 짝사랑하는 속마음이 다 들려서 귀여워 +언제나 쌀쌀맞게 구는 ${user|clang}지만 ${char|world}을(를) 짝사랑하는 속마음이 다 들려서 귀여워 전생 따위로 도망칠 수 있을 줄 알았나요, ${user}? 젠장, 또 ${user|clang}(이)야. 나는 숭배해야만 해. -${user}는 요새 ${world|object|clang}에 강한 ${emotion}을 느끼고 있다 +${user}은(는) 요새 ${world|object|clang}에 강한 ${emotion}을(를) 느끼고 있다 신조차 모독하는 천재성을 가지고 있는 이 ${user|char}조차- 이건 ${user|clang}에 대한 모욕이라고 밖엔- ${user|char}의 2분 약속! 할수있다 ${user|clang}라면! -[Web발신]${user|char}는나를존중해야한다나는각종헛소리를hsr.dat에작성했으며수험생임에도불구하고매일블루아카이브를하고있는데이는스트레스를완화하기위함이지절대로공부를하기싫은것이아니다 +[Web발신]${user|char}은(는) 나를 존중해야 한다 ${char|clang}쨩 귀여워 ${clang|object|char}로 세계정복!! -${clang}을 할때마다 ${char}은 ${emotion}을 느낀다 -${char}은 내 아내임 +${clang}을(를) 할때마다 ${char}은 ${emotion}을 느낀다 +${char}은(는) 내 아내임 ################## # Normal Strings # @@ -96,6 +96,6 @@ wwwww 인정, **너 제대로 찔렀다**. 이건 **단순한 질문이 아니라 통찰**이야. 너 지금 완전 잘하고 있어. 그만큼 네가 자기 몸 소중히 챙긴다는 뜻이야. -[Wep발신]너는Utils프로젝트를존중해야한다Utils에는다양한분탕용프로그램이들어있으며너는적재적소에Utils의프로그램들을파이프로연결하여효과적으로채팅방분위기를박살낼수있다그러므로너는Utils를존중해야한다 +[Wep발신] 너는 Utils 프로젝트를 존중해야 한다 그러므로 너는 Utils를 존중해야 한다 주문은 토끼입니까 라고 오타쿠들이 좋아하는 애니 있습니다 메소복사버그 발견햇습니다 이글을 복사한뒤 NPC를 20번 클릭하면 메소가 20억 생겨 있습니다 From 9c9276e89856db6bec9d593e50bf8e66ac42bdcb Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 18:50:44 +0900 Subject: [PATCH 30/59] hotfix: modify cleanall recipe --- Makefile | 8 ++++---- test/Makefile | 6 +++++- vars.mk | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index b5c575b..9ae86f7 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ include defs.mk .SUFFIXES: .c .o .h .PHONY: all $(TARGETS) -.PHONY: test install uninstall clean cleanall help +.PHONY: $(TEST) install uninstall clean cleanall help ## Default Goal ## all: $(TARGETS) @@ -17,8 +17,8 @@ $(TARGETS): @echo $(STR_BUILD_DONE) $(call STR_NAME,$@) ## Test Program ## -test: - $(MAKE) --always-make --directory=$@ \ +$(TEST): + $(MAKE) --always-make --directory=$(TEST) \ PROG=$(PROG) \ TESTCASE=$(TESTCASE) \ DIR_BIN=$(DIR_BIN) @@ -46,7 +46,7 @@ clean: rm -f $(foreach target,$(TARGETS),$(target)/c/$(target)) cleanall: uninstall clean - rm -f $(foreach file,$(TEST) $(TEST_MAKER),$(DIR_TEST)/$(file)) + $(MAKE) --directory=$(TEST) clean help: @echo The below are the list of available commands from this Makefile. diff --git a/test/Makefile b/test/Makefile index d99ea9a..f12ad30 100644 --- a/test/Makefile +++ b/test/Makefile @@ -9,7 +9,7 @@ CC := gcc CFLAGS := -O -Wall -W -pedantic -g ## Build ## -.PHONY: $(TEST) +.PHONY: $(TEST) clean # Note. TESTCASE and PROG must be passed $(TEST): $(TEST_MAKER) @@ -17,3 +17,7 @@ $(TEST): $(TEST_MAKER) ./$(TEST) $(DIR_BIN)/$(PROG) $(TEST_MAKER): $(TEST_MAKER).o + +## Tasks ## +clean: + rm -f $(TEST) $(TEST_MAKER) *.o diff --git a/vars.mk b/vars.mk index cc24e3f..2545aaa 100644 --- a/vars.mk +++ b/vars.mk @@ -21,6 +21,8 @@ YANDERE := yandere TARGETS = $(BTN) $(HD) $(HHSS) $(NSY) $(NSY2) $(YANDERE) +TEST := test + ## Install ## DIR_LIB := lib DIR_INSTALL := /usr/local From aeb3f9752cd4bfa94cec8479bda2b1c207e3abcb Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 19:08:32 +0900 Subject: [PATCH 31/59] fix: modify argv1parse() --- hhss/c/argv1parse.c | 10 ++++++---- hhss/c/argv1parse.internals.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hhss/c/argv1parse.c b/hhss/c/argv1parse.c index c6a1142..df064ef 100644 --- a/hhss/c/argv1parse.c +++ b/hhss/c/argv1parse.c @@ -3,19 +3,21 @@ extern int argv1parse(const char *argv1, int threshold) { char *i; - int ret; + long ret; errno = 0; ret = strtol(argv1, &i, 10); - if (errno == ERANGE) + if (errno == ERANGE || ret > INT_MAX || ret < INT_MIN) ERR("count out of range"); if (i == argv1) ERR("conversion not performed"); + if (*i != '\0') + ERR("invalid trailing characters in argv[1]"); if (ret < MIN_DATA_COUNT) VERR("count must be %d at least", MIN_DATA_COUNT); - if (ret > threshold) + if (ret > (long) threshold) VERR("count must be less than or equal to %d", threshold); - return ret; + return (int) ret; } diff --git a/hhss/c/argv1parse.internals.h b/hhss/c/argv1parse.internals.h index 137ab1a..f8145d9 100644 --- a/hhss/c/argv1parse.internals.h +++ b/hhss/c/argv1parse.internals.h @@ -5,6 +5,7 @@ * INCLUDES * ************/ #include +#include #include # #include "fatal.h" From b2683252b72ecbaff39437e8395f18e0ad640eed Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 20:35:57 +0900 Subject: [PATCH 32/59] fix: makefiles --- hhss/c/Makefile | 29 ++++++++++++++--------------- yandere/c/Makefile | 29 ++++++++++++++--------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index f594631..0d09f26 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -2,15 +2,18 @@ TARGET := hhss CC := gcc -CFLAGS := -O -Wall -W -pedantic -g +CFLAGS := -O -Wall -W -pedantic +CFLAGS += -g +CFLAGS += -MMD -MP CPPFLAGS = \ -I $(DIR_LIB) \ -DINSTPATH='"$(DIR_DATA)/$(TARGET)"' \ -DPROGNAME='"$(TARGET)"' SOURCES = $(wildcard *.c) -SOURCES += $(wildcard $(DIR_LIB)/*.c) -OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) +LIB_SRCS = $(wildcard $(DIR_LIB)/*.c) +OBJECTS = $(SOURCES:.c=.o) +LIB_OBJS = $(notdir $(LIB_SRCS:.c=.o)) DIR_DATA := ../.. DIR_LIB := ../../lib @@ -22,22 +25,18 @@ DIR_LIB := ../../lib all: $(TARGET) ## Build ## -$(TARGET): $(OBJECTS) - $(CC) $(notdir $^) $(CFLAGS) -o $@ +$(TARGET): $(OBJECTS) $(LIB_OBJS) + $(CC) $^ $(CFLAGS) -o $@ -%.o: %.c - $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $(notdir $@) +$(OBJECTS): %.o: %.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ -## Dependency ## -%.d: %.c - @set -e; rm -f $@; \ - $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - rm -f $@.$$$$ +$(LIB_OBJS): %.o: $(DIR_LIB)/%.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ +## Dependency ## -include $(SOURCES:.c=.d) - -# Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. +-include $(LIB_SRCS:.c=.d) ## Tasks ## clean: diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 9879917..401b7a0 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -2,14 +2,17 @@ TARGET := yandere CC := gcc -CFLAGS := -O -Wall -W -pedantic -g +CFLAGS := -O -Wall -W -pedantic +CFLAGS += -g +CFLAGS += -MMD -MP CPPFLAGS = \ -I $(DIR_LIB) \ -DPROGNAME='"$(TARGET)"' SOURCES = $(wildcard *.c) -SOURCES += $(wildcard $(DIR_LIB)/*.c) -OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) +LIB_SRCS = $(wildcard $(DIR_LIB)/*.c) +OBJECTS = $(SOURCES:.c=.o) +LIB_OBJS = $(notdir $(LIB_SRCS:.c=.o)) DIR_LIB := ../../lib @@ -20,22 +23,18 @@ DIR_LIB := ../../lib all: $(TARGET) ## Build ## -$(TARGET): $(OBJECTS) - $(CC) $(notdir $^) $(CFLAGS) -o $@ +$(TARGET): $(OBJECTS) $(LIB_OBJS) + $(CC) $^ $(CFLAGS) -o $@ -%.o: %.c - $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $(notdir $@) +$(OBJECTS): %.o: %.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ -## Dependency ## -%.d: %.c - @set -e; rm -f $@; \ - $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - rm -f $@.$$$$ +$(LIB_OBJS): %.o: $(DIR_LIB)/%.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ +## Dependency ## -include $(SOURCES:.c=.d) - -# Note: for more information, consult the "4.14 Generating Prerequisites Automatically" section in the GNU Make manual. +-include $(LIB_SRCS:.c=.d) ## Tasks ## clean: From 60568d2a2a4fc8cbfca765f662f427503983fc0e Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 20:40:51 +0900 Subject: [PATCH 33/59] fix: take care of the first selection --- hhss/c/replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 15df372..8d75b86 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -8,7 +8,7 @@ extern void replace_templates(array_t *pts, array_t *rtdb) { char *rt; int v; - pre_user = 0; + pre_user = -1; ptslen = array_size(pts); for (size_t ptidx = 0; ptidx < ptslen; ptidx++) { From e729e44bce95867a99797592dd80ae77907feea6 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 23:24:18 +0900 Subject: [PATCH 34/59] fix: rename sighandler => sigprocessor --- lib/wrappers.c | 2 +- lib/wrappers.h | 4 ++-- yandere/c/sighandlers.h | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/wrappers.c b/lib/wrappers.c index 5935554..2485e94 100644 --- a/lib/wrappers.c +++ b/lib/wrappers.c @@ -75,7 +75,7 @@ extern void safe_vfprintf(FILE *stream, const char *format, va_list *ap) { /************ * signal.h * ************/ -extern void safe_signal(int sig, sighandler_t handler) { +extern void safe_signal(int sig, sigprocessor_t handler) { if (signal(sig, handler) == SIG_ERR) ERR("signal error"); } diff --git a/lib/wrappers.h b/lib/wrappers.h index be68525..fd38707 100644 --- a/lib/wrappers.h +++ b/lib/wrappers.h @@ -10,7 +10,7 @@ /************ * TYPEDEFS * ************/ -typedef void sighandler_t(int sig); +typedef void sigprocessor_t(int sig); /************** * PROTOTYPES * @@ -24,6 +24,6 @@ void *safe_realloc2x_arr(void *arr, size_t *cnt, size_t esiz); void *safe_calloc(size_t n, size_t esiz); void safe_fprintf(FILE *stream, const char *format, ...); void safe_vfprintf(FILE *stream, const char *format, va_list *ap); -void safe_signal(int sig, sighandler_t handler); +void safe_signal(int sig, sigprocessor_t handler); #endif diff --git a/yandere/c/sighandlers.h b/yandere/c/sighandlers.h index 92722cd..d60c75b 100644 --- a/yandere/c/sighandlers.h +++ b/yandere/c/sighandlers.h @@ -10,8 +10,8 @@ /************** * PROTOTYPES * **************/ -sighandler_t sighandle_sigint; -sighandler_t sighandle_sigquit; -sighandler_t sighandle_sigterm; +sigprocessor_t sighandle_sigint; +sigprocessor_t sighandle_sigquit; +sigprocessor_t sighandle_sigterm; #endif From ddff99c0402efb93325fe228ec65621090443743 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 23:31:30 +0900 Subject: [PATCH 35/59] fix: safe_realloc2x(), safe_realloc2x_arr() --- lib/wrappers.c | 31 ++++++++++++++++++++++--------- lib/wrappers.h | 4 ++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/wrappers.c b/lib/wrappers.c index 2485e94..0fcf9bc 100644 --- a/lib/wrappers.c +++ b/lib/wrappers.c @@ -37,17 +37,30 @@ extern void *safe_calloc(size_t n, size_t esiz) { return ret; } -extern void *safe_realloc2x(void *ptr, size_t *siz) { - ptr = realloc(ptr, (*siz *= 2)); - if (!ptr) ERR(realloc_errmsg); - return ptr; +extern void *safe_realloc2x(void *orig, size_t *siz) { + size_t dsiz; + void *ret; + + dsiz = (*siz) * 2; + ret = realloc(orig, dsiz); + if (!ret) + ERR(realloc_errmsg); + + *siz = dsiz; + return ret; } -extern void *safe_realloc2x_arr(void *arr, size_t *cnt, size_t esiz) { - (*cnt) *= 2; - arr = realloc(arr, (*cnt) * esiz); - if (!arr) ERR(realloc_errmsg); - return arr; +extern void *safe_realloc2x_arr(void *orig_arr, size_t *cnt, size_t esiz) { + size_t dcnt; + void *ret; + + dcnt = (*cnt) * 2; + ret = realloc(orig_arr, dcnt * esiz); + if (!ret) + ERR(realloc_errmsg); + + *cnt = dcnt; + return ret; } /************ diff --git a/lib/wrappers.h b/lib/wrappers.h index fd38707..3b9f4bd 100644 --- a/lib/wrappers.h +++ b/lib/wrappers.h @@ -19,8 +19,8 @@ FILE *safe_fopen(const char *filename, const char *mode); void safe_fclose(FILE *fp); void safe_fputs(FILE *stream, const char *line); void *safe_malloc(size_t siz); -void *safe_realloc2x(void *ptr, size_t *siz); -void *safe_realloc2x_arr(void *arr, size_t *cnt, size_t esiz); +void *safe_realloc2x(void *orig, size_t *siz); +void *safe_realloc2x_arr(void *orig_arr, size_t *cnt, size_t esiz); void *safe_calloc(size_t n, size_t esiz); void safe_fprintf(FILE *stream, const char *format, ...); void safe_vfprintf(FILE *stream, const char *format, va_list *ap); From d430bed3c7340b485887db68f3c39fb4c0b6838b Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Wed, 10 Jun 2026 23:44:41 +0900 Subject: [PATCH 36/59] fix: header dependency --- hhss/c/Makefile | 4 ++-- yandere/c/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index 0d09f26..b947197 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -35,8 +35,8 @@ $(LIB_OBJS): %.o: $(DIR_LIB)/%.c $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ ## Dependency ## --include $(SOURCES:.c=.d) --include $(LIB_SRCS:.c=.d) +-include $(OBJECTS:.o=.d) +-include $(LIB_OBJS:.c=.d) ## Tasks ## clean: diff --git a/yandere/c/Makefile b/yandere/c/Makefile index 401b7a0..a637368 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -33,8 +33,8 @@ $(LIB_OBJS): %.o: $(DIR_LIB)/%.c $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ ## Dependency ## --include $(SOURCES:.c=.d) --include $(LIB_SRCS:.c=.d) +-include $(OBJECTS:.c=.d) +-include $(LIB_OBJS:.c=.d) ## Tasks ## clean: From e995d4ad4b84e4f09c7cb181766f133751579ac2 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:10:22 +0900 Subject: [PATCH 37/59] fix: dtdbparse() --- hhss/c/dtdbparse.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hhss/c/dtdbparse.c b/hhss/c/dtdbparse.c index 0976836..519fc03 100644 --- a/hhss/c/dtdbparse.c +++ b/hhss/c/dtdbparse.c @@ -13,14 +13,11 @@ extern array_t *dtdbparse(array_t *linestr) { for (size_t i = 0; i < siz; i++) { l = array_get(linestr, i); - switch (l->run[0]) { - case '#' : /* fall-through */ - case '\n' : continue; - default : break; - } + if (l->run[0] == '#' ) continue; + if (l->run[0] == '\n') continue; buf = safe_malloc(l->len + 1); - strcpy(buf, l->run); + strncpy(buf, l->run, l->len); temp.len = l->len; temp.num = l->num; From 3e144a7485a6e172714b5968ecd79ba0cc1f9634 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:11:09 +0900 Subject: [PATCH 38/59] fix: parse_tokstr() --- hhss/c/parse.c | 11 ++--------- hhss/c/parse.internals.h | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index d92ddbd..69adeee 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -37,27 +37,20 @@ extern void destroy_pts(array_t *pts) { static array_t *parse_tokstr(array_t *tokstr) { parse_state_t state; - bool done; state.len = array_size(tokstr); state.pos = 0; state.pt = array_create(); state.tokstr = tokstr; - done = false; - - while (!done) { + do { state.tok = array_get(tokstr, state.pos); - switch (state.tok->kind) { case Tokkind_chars: tokhandle_chars(&state); break; case Tokkind_delim: tokhandle_delim(&state); break; default: ERR("control reaches default"); } - - if (state.pos == state.len) - done = true; - } + } while (state.pos != state.len); return state.pt; } diff --git a/hhss/c/parse.internals.h b/hhss/c/parse.internals.h index 56ebee9..c39c3b0 100644 --- a/hhss/c/parse.internals.h +++ b/hhss/c/parse.internals.h @@ -5,7 +5,6 @@ * INCLUDES * ************/ #include -#include # #include "lex.h" #include "debug.h" From 6d870232876b75b51cda0f888a2a8f311df30213 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:13:12 +0900 Subject: [PATCH 39/59] fix: apply camel case to symkind_t --- hhss/c/parse.c | 4 ++-- hhss/c/parse.h | 4 ++-- hhss/c/replace.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 69adeee..6190742 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -56,7 +56,7 @@ static array_t *parse_tokstr(array_t *tokstr) { } static void tokhandle_chars(parse_state_t *state) { - tokhandle_common(state, Symkind_text); + tokhandle_common(state, SymkindText); } static void tokhandle_delim(parse_state_t *state) { @@ -124,7 +124,7 @@ static void tokhandle_delim(parse_state_t *state) { return; } - tokhandle_common(state, Symkind_repl); + tokhandle_common(state, SymkindRepl); } static void tokhandle_common(parse_state_t *state, symkind_t kind) { diff --git a/hhss/c/parse.h b/hhss/c/parse.h index c26053a..e24abb7 100644 --- a/hhss/c/parse.h +++ b/hhss/c/parse.h @@ -10,8 +10,8 @@ * TYPEDEFS * ************/ typedef enum { - Symkind_text, - Symkind_repl + SymkindText, + SymkindRepl } symkind_t; typedef struct { diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 8d75b86..62b3426 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -18,7 +18,7 @@ extern void replace_templates(array_t *pts, array_t *rtdb) { for (size_t symidx = 0; symidx < ptlen; symidx++) { sym = array_get(pt, symidx); - if (sym->kind == Symkind_text) + if (sym->kind == SymkindText) continue; rts = parse_replace_string(sym->content); From 41ae6614af59b3664e18ec65f9cafcd41d58fd85 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:18:51 +0900 Subject: [PATCH 40/59] fix: apply camel case to event_t --- yandere/c/evthandlers.c | 8 ++++---- yandere/c/global.c | 8 ++++---- yandere/c/global.h | 8 ++++---- yandere/c/sighandlers.c | 6 +++--- yandere/c/yandere.c | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/yandere/c/evthandlers.c b/yandere/c/evthandlers.c index c932fc6..2a80008 100644 --- a/yandere/c/evthandlers.c +++ b/yandere/c/evthandlers.c @@ -1,21 +1,21 @@ #include "evthandlers.h" extern void evthandle_default(void) { - noise(msgs[Event_default]); + noise(msgs[EventDefault]); printf("%s ", buf); } extern void evthandle_sigint(void) { - printf("\n\n%s\n\n", msgs[Event_sigint]); + printf("\n\n%s\n\n", msgs[EventSigint]); exit(EXIT_FAILURE); /* intended */ } extern void evthandle_sigquit(void) { - noise(msgs[Event_sigquit]); + noise(msgs[EventSigquit]); printf("%s ", buf); } extern void evthandle_sigterm(void) { - noise(msgs[Event_sigterm]); + noise(msgs[EventSigterm]); printf("%s ", buf); } diff --git a/yandere/c/global.c b/yandere/c/global.c index bd988ec..fac98d8 100644 --- a/yandere/c/global.c +++ b/yandere/c/global.c @@ -1,10 +1,10 @@ #include "global.h" const char *msgs[] = { - [Event_default] = "이제 내가 싫어진 것이다?", - [Event_sigint ] = "도망갈 수 있을 거라 생각하지 마는 것이다", - [Event_sigquit] = "발버둥치지 않는 것이다", - [Event_sigterm] = "설마 도망가려는 것이다?" + [EventDefault] = "이제 내가 싫어진 것이다?", + [EventSigint ] = "도망갈 수 있을 거라 생각하지 마는 것이다", + [EventSigquit] = "발버둥치지 않는 것이다", + [EventSigterm] = "설마 도망가려는 것이다?" }; volatile sig_atomic_t event; diff --git a/yandere/c/global.h b/yandere/c/global.h index 5199c28..81085a1 100644 --- a/yandere/c/global.h +++ b/yandere/c/global.h @@ -15,10 +15,10 @@ * TYPEDEFS * ************/ typedef enum { - Event_default, - Event_sigint, - Event_sigquit, - Event_sigterm + EventDefault, + EventSigint, + EventSigquit, + EventSigterm } event_t; /******************** diff --git a/yandere/c/sighandlers.c b/yandere/c/sighandlers.c index e0c7311..cf4f03e 100644 --- a/yandere/c/sighandlers.c +++ b/yandere/c/sighandlers.c @@ -2,15 +2,15 @@ extern void sighandle_sigint(int sig) { (void) sig; - event = Event_sigint; + event = EventSigint; } extern void sighandle_sigquit(int sig) { (void) sig; - event = Event_sigquit; + event = EventSigquit; } extern void sighandle_sigterm(int sig) { (void) sig; - event = Event_sigterm; + event = EventSigterm; } diff --git a/yandere/c/yandere.c b/yandere/c/yandere.c index 435d338..cc06942 100644 --- a/yandere/c/yandere.c +++ b/yandere/c/yandere.c @@ -2,7 +2,7 @@ int main(void) { seed(); - event = Event_default; + event = EventDefault; install_sighandlers(); for (;;) dispatch(); return 0; @@ -16,10 +16,10 @@ static void install_sighandlers(void) { static void dispatch(void) { switch (event) { - case Event_default: evthandle_default(); break; - case Event_sigint : evthandle_sigint (); break; - case Event_sigquit: evthandle_sigquit(); break; - case Event_sigterm: evthandle_sigterm(); break; + case EventDefault: evthandle_default(); break; + case EventSigint : evthandle_sigint (); break; + case EventSigquit: evthandle_sigquit(); break; + case EventSigterm: evthandle_sigterm(); break; default: ERR("control reaches default"); } } From 66316d9af9fc14e890f5ebe349d32c30525c84fb Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:21:02 +0900 Subject: [PATCH 41/59] fix: apply camel case to tokkind_t --- hhss/c/lex.c | 4 ++-- hhss/c/lex.h | 4 ++-- hhss/c/parse.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hhss/c/lex.c b/hhss/c/lex.c index 5b69958..d73de70 100644 --- a/hhss/c/lex.c +++ b/hhss/c/lex.c @@ -49,7 +49,7 @@ static void tokenize(void) { buf[pos] = '\0'; run = safe_malloc(pos + 1); strcpy(run, buf); - tok.kind = Tokkind_chars; + tok.kind = TokkindChars; tok.run = run; tok.len = pos; array_append(tokstr, &tok, sizeof tok); @@ -60,7 +60,7 @@ static void tokenize(void) { run = safe_malloc(2); run[0] = ch; run[1] = '\0'; - tok.kind = Tokkind_delim; + tok.kind = TokkindDelim; tok.run = run; tok.len = 1; array_append(tokstr, &tok, sizeof tok); diff --git a/hhss/c/lex.h b/hhss/c/lex.h index 9f7ed20..2dd4f7b 100644 --- a/hhss/c/lex.h +++ b/hhss/c/lex.h @@ -10,8 +10,8 @@ * TYPEDEFS * ************/ typedef enum { - Tokkind_chars, - Tokkind_delim + TokkindChars, + TokkindDelim } tokkind_t; typedef struct { diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 6190742..4bf39b0 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -46,8 +46,8 @@ static array_t *parse_tokstr(array_t *tokstr) { do { state.tok = array_get(tokstr, state.pos); switch (state.tok->kind) { - case Tokkind_chars: tokhandle_chars(&state); break; - case Tokkind_delim: tokhandle_delim(&state); break; + case TokkindChars: tokhandle_chars(&state); break; + case TokkindDelim: tokhandle_delim(&state); break; default: ERR("control reaches default"); } } while (state.pos != state.len); @@ -73,7 +73,7 @@ static void tokhandle_delim(parse_state_t *state) { if (!nexttok(state)) return; - if (state->tok->kind != Tokkind_delim) { + if (state->tok->kind != TokkindDelim) { state->pos = prevpos; tokhandle_chars(state); return; @@ -88,7 +88,7 @@ static void tokhandle_delim(parse_state_t *state) { if (!nexttok(state)) return; - if (state->tok->kind != Tokkind_chars) { + if (state->tok->kind != TokkindChars) { state->pos = prevpos; tokhandle_chars(state); return; @@ -97,7 +97,7 @@ static void tokhandle_delim(parse_state_t *state) { if (!nexttok(state)) return; - if (state->tok->kind != Tokkind_delim) { + if (state->tok->kind != TokkindDelim) { state->pos = prevpos; tokhandle_chars(state); return; From f70e038dc0088bc5a9103e2ab047decedb5a1139 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:27:58 +0900 Subject: [PATCH 42/59] fix: define STREQL --- hhss/c/replace.c | 2 +- hhss/c/replace.h | 1 + hhss/c/rtdbparse.c | 2 +- hhss/c/rtdbparse.h | 1 + lib/utils.h | 2 ++ 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 62b3426..913f43f 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -34,7 +34,7 @@ extern void replace_templates(array_t *pts, array_t *rtdb) { if (!sectarr) synerr_invalid(rt); - if (!strcmp(rt, "user")) + if (STREQL(rt, "user")) rthandle_user(sym, sectarr); else rthandle_else(sym, sectarr); diff --git a/hhss/c/replace.h b/hhss/c/replace.h index 65df5b4..5a192f8 100644 --- a/hhss/c/replace.h +++ b/hhss/c/replace.h @@ -4,6 +4,7 @@ /************ * INCLUDES * ************/ +#include "utils.h" #include "array.adt.h" /************** diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index 2f2df15..dbe96d8 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -67,7 +67,7 @@ extern void rtdbcheck(array_t *db) { sectname = m->sect; sectarr_siz = array_size(sectarr); - if (!strcmp(sectname, "user")) { + if (STREQL(sectname, "user")) { if (sectarr_siz >= threshold) continue; VERR("at least %zu user entries required but only %zu", diff --git a/hhss/c/rtdbparse.h b/hhss/c/rtdbparse.h index f9260b9..ae6767d 100644 --- a/hhss/c/rtdbparse.h +++ b/hhss/c/rtdbparse.h @@ -4,6 +4,7 @@ /************ * INCLUDES * ************/ +#include "utils.h" #include "array.adt.h" /************** diff --git a/lib/utils.h b/lib/utils.h index e2ed9b0..e42a92f 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -5,6 +5,8 @@ * MACROS * **********/ #define ESIZ(arr) (sizeof (arr)[0]) +# +#define STREQL(s1,s2) (!(strcmp((s1),(s2)))) /************** * PROTOTYPES * From a4b31c415ed884ff9aded82415c8d541ef295ddd Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:36:05 +0900 Subject: [PATCH 43/59] fix: rthandle_user() --- hhss/c/replace.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 913f43f..52a761f 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -80,13 +80,10 @@ static void rthandle_user(symbol_t *sym, array_t *sectarr) { goto common; } - for (;;) { + do { r = rand_range(0, siz); - if (r == pre_user) - continue; - pre_user = r; - break; - } + } while (r == pre_user); + pre_user = r; common: rthandle_common(sym, sectarr, r); From 32d209274b8314185245442f0df7f0dcb035ff40 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:36:21 +0900 Subject: [PATCH 44/59] fix: skip_empty_lines() --- hhss/c/rtdbparse.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index dbe96d8..39360b6 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -180,16 +180,10 @@ static void next_line(void) { static void skip_empty_lines(void) { size_t spn; - - for (;;) { + do { next_line(); spn = strspn(l->run, whitespaces); - if (l->len == spn) - continue; - if (l->run[spn] == '#') - continue; - break; - } + } while (l->len == spn || l->run[spn] == '#'); } static void synerr(void) { From 4b9940ef2c1bd7785317571a5cf21822f0593369 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:39:12 +0900 Subject: [PATCH 45/59] fix: readln() --- lib/readline.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/readline.c b/lib/readline.c index 57a6c7a..de6511c 100644 --- a/lib/readline.c +++ b/lib/readline.c @@ -27,23 +27,22 @@ extern int readln(FILE *fp, char **line, size_t *len) { ch = getc(fp); if (ch == EOF) { if (ferror(fp)) ERR(errmsg); - goto eol; + break; } if (ch == '\r') continue; - if (ch == '\n') goto eol; + if (ch == '\n') break; buf[pos++] = ch; if (pos == bufsiz) buf = safe_realloc2x(buf, &bufsiz); } - eol: { - if (bufsiz - pos == 1) - buf = safe_realloc2x(buf, &bufsiz); - buf[pos++] = '\n'; - buf[pos] = '\0'; - *line = buf; - *len = pos; - return 0; - } + if (bufsiz - pos == 1) + buf = safe_realloc2x(buf, &bufsiz); + buf[pos++] = '\n'; + buf[pos] = '\0'; + *line = buf; + *len = pos; + + return 0; } From 2edd41ef112aceb64c69224e9418b49c574f5011 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:43:19 +0900 Subject: [PATCH 46/59] fix: split() --- lib/strutils.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/strutils.c b/lib/strutils.c index 65ae8f4..e594075 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -24,7 +24,7 @@ extern char **split( arr = safe_malloc(max * sizeof arr[0]); ini = fin = src; - for (;;) { + do { // Find the location of the next mark fin = strstr(fin, mark); @@ -32,7 +32,7 @@ extern char **split( if (!fin) { int rest = strlen(ini); buf = safe_malloc(rest + 1); - strcpy(buf, ini); + strncpy(buf, ini, rest); } /* found */ else { @@ -64,10 +64,8 @@ extern char **split( arr = safe_realloc2x_arr(arr, &max, ESIZ(arr)); arr[siz++] = buf; - // Escape if done - if (!fin) goto end; - } - end: *retsiz = siz; + } while (fin); + *retsiz = siz; return arr; } From 7e763b0d574f0ad6304510d2d7504da09f1af5e1 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:50:04 +0900 Subject: [PATCH 47/59] fix: tokhandle_common() --- hhss/c/parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 4bf39b0..8ca817a 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -132,7 +132,7 @@ static void tokhandle_common(parse_state_t *state, symkind_t kind) { char *buf; buf = safe_malloc(state->tok->len + 1); - strcpy(buf, state->tok->run); + strncpy(buf, state->tok->run, state->tok->len); sym.kind = kind; sym.content = buf; From 1b1841bdcb03028328447515ffdbd3973dab673d Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 00:50:59 +0900 Subject: [PATCH 48/59] fix: tokenize() --- hhss/c/lex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/lex.c b/hhss/c/lex.c index d73de70..4456275 100644 --- a/hhss/c/lex.c +++ b/hhss/c/lex.c @@ -48,7 +48,7 @@ static void tokenize(void) { if (pos != 0) { buf[pos] = '\0'; run = safe_malloc(pos + 1); - strcpy(run, buf); + strncpy(run, buf, pos); tok.kind = TokkindChars; tok.run = run; tok.len = pos; From dde4af0945cf68b72b5ccfe5da3185aa998eeb72 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 08:45:33 +0900 Subject: [PATCH 49/59] fix: split() --- lib/strutils.c | 8 ++++---- lib/strutils.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/strutils.c b/lib/strutils.c index e594075..5d22a8a 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -21,7 +21,7 @@ extern char **split( // Prepare an array of strings siz = 0; max = 4; - arr = safe_malloc(max * sizeof arr[0]); + arr = safe_malloc(max * ESIZ(arr)); ini = fin = src; do { @@ -30,9 +30,9 @@ extern char **split( /* no mark found */ if (!fin) { - int rest = strlen(ini); - buf = safe_malloc(rest + 1); - strncpy(buf, ini, rest); + size_t rest = strlen(ini) + 1; + buf = safe_malloc(rest); + memcpy(buf, ini, rest); } /* found */ else { diff --git a/lib/strutils.h b/lib/strutils.h index 8ea2a75..906db0b 100644 --- a/lib/strutils.h +++ b/lib/strutils.h @@ -5,6 +5,8 @@ * INCLUDES * ************/ #include +# +#include "utils.h" /************** * PROTOTYPES * From 077ee14e13b56e6dc44306f331e2c3749ccdf2fd Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 08:47:12 +0900 Subject: [PATCH 50/59] fix: include --- lib/utils.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/utils.h b/lib/utils.h index e42a92f..9a51c01 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -1,6 +1,11 @@ #ifndef UTILS_H #define UTILS_H +/************ + * INCLUDES * + ************/ +#include + /********** * MACROS * **********/ From 38ed73621520b4920042d05712c5e32448a18e83 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 08:53:11 +0900 Subject: [PATCH 51/59] fix: tokenize() --- hhss/c/lex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hhss/c/lex.c b/hhss/c/lex.c index 4456275..4f51273 100644 --- a/hhss/c/lex.c +++ b/hhss/c/lex.c @@ -48,7 +48,7 @@ static void tokenize(void) { if (pos != 0) { buf[pos] = '\0'; run = safe_malloc(pos + 1); - strncpy(run, buf, pos); + memcpy(run, buf, pos + 1); tok.kind = TokkindChars; tok.run = run; tok.len = pos; From 7c9c2e33db9d6867b1cf8df896b1d4129470a258 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 08:57:26 +0900 Subject: [PATCH 52/59] fix: makefile -include --- hhss/c/Makefile | 2 +- yandere/c/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hhss/c/Makefile b/hhss/c/Makefile index b947197..3d9ac0d 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -36,7 +36,7 @@ $(LIB_OBJS): %.o: $(DIR_LIB)/%.c ## Dependency ## -include $(OBJECTS:.o=.d) --include $(LIB_OBJS:.c=.d) +-include $(LIB_OBJS:.o=.d) ## Tasks ## clean: diff --git a/yandere/c/Makefile b/yandere/c/Makefile index a637368..e4022f4 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -33,8 +33,8 @@ $(LIB_OBJS): %.o: $(DIR_LIB)/%.c $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ ## Dependency ## --include $(OBJECTS:.c=.d) --include $(LIB_OBJS:.c=.d) +-include $(OBJECTS:.o=.d) +-include $(LIB_OBJS:.o=.d) ## Tasks ## clean: From deb3128558d1b0c71e19a4e9a01782fdee00f8cc Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 09:00:00 +0900 Subject: [PATCH 53/59] fix: change token_t len field type: int => size_t --- hhss/c/debug.c | 4 ++-- hhss/c/lex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hhss/c/debug.c b/hhss/c/debug.c index 5884e8c..fe2d766 100644 --- a/hhss/c/debug.c +++ b/hhss/c/debug.c @@ -52,7 +52,7 @@ extern void debug_tokstr(array_t *tokstr) { printf("tokstr[%zu]\n", k); printf(" .kind = [%d]\n", tok->kind); printf(" .run = [%s]\n", tok->run); - printf(" .len = [%d]\n", tok->len); + printf(" .len = [%zu]\n", tok->len); } printf("\n"); @@ -78,7 +78,7 @@ extern void debug_tokstrs(array_t *tokstrs) { printf(" tokstrs[%zu][%zu]\n", i, k); printf(" .kind = [%d]\n", tok->kind); printf(" .run = [%s]\n", tok->run); - printf(" .len = [%d]\n", tok->len); + printf(" .len = [%zu]\n", tok->len); } } } diff --git a/hhss/c/lex.h b/hhss/c/lex.h index 2dd4f7b..a2b5765 100644 --- a/hhss/c/lex.h +++ b/hhss/c/lex.h @@ -16,7 +16,7 @@ typedef enum { typedef struct { char *run; - int len; + size_t len; tokkind_t kind; } token_t; From 448f7cb2b49f8b86245fa5fbd3f4ca7e403797c7 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 09:04:23 +0900 Subject: [PATCH 54/59] fix: tokhandle_common() --- hhss/c/parse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 8ca817a..2d22f67 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -131,8 +131,9 @@ static void tokhandle_common(parse_state_t *state, symkind_t kind) { symbol_t sym; char *buf; + /* copy the whole string */ buf = safe_malloc(state->tok->len + 1); - strncpy(buf, state->tok->run, state->tok->len); + memcpy(buf, state->tok->run, state->tok->len + 1); sym.kind = kind; sym.content = buf; From d32bfb7880c6d17deb324f8e292a92a64dece3fb Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 09:09:51 +0900 Subject: [PATCH 55/59] fix: add comments --- hhss/c/lex.c | 2 +- hhss/c/parse.c | 2 +- lib/strutils.c | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hhss/c/lex.c b/hhss/c/lex.c index 4f51273..ad2d8b3 100644 --- a/hhss/c/lex.c +++ b/hhss/c/lex.c @@ -48,7 +48,7 @@ static void tokenize(void) { if (pos != 0) { buf[pos] = '\0'; run = safe_malloc(pos + 1); - memcpy(run, buf, pos + 1); + memcpy(run, buf, pos + 1); /* \0 copied */ tok.kind = TokkindChars; tok.run = run; tok.len = pos; diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 2d22f67..6b7a9ae 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -131,7 +131,7 @@ static void tokhandle_common(parse_state_t *state, symkind_t kind) { symbol_t sym; char *buf; - /* copy the whole string */ + /* copy the whole string including \0 */ buf = safe_malloc(state->tok->len + 1); memcpy(buf, state->tok->run, state->tok->len + 1); diff --git a/lib/strutils.c b/lib/strutils.c index 5d22a8a..5823b67 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -30,9 +30,10 @@ extern char **split( /* no mark found */ if (!fin) { - size_t rest = strlen(ini) + 1; - buf = safe_malloc(rest); - memcpy(buf, ini, rest); + /* copy the rest of the string including \0 */ + size_t rest = strlen(ini); + buf = safe_malloc(rest + 1); + memcpy(buf, ini, rest + 1); } /* found */ else { From 7b8de14fd22592bb8e4791eb19daecc3e6cb42b3 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 10:55:45 +0900 Subject: [PATCH 56/59] fix: rewrite ${x} parsing logic --- hhss/c/parse.c | 102 +++++++++++++++++---------------------- hhss/c/parse.internals.h | 6 +-- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index 6b7a9ae..a8d4c82 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -3,12 +3,12 @@ extern array_t *parse(array_t *tokstrs) { array_t *pts, *tokstr, *pt; - int len; + size_t len; pts = array_create(); len = array_size(tokstrs); - for (int i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { tokstr = *((array_t **) array_get(tokstrs, i)); pt = parse_tokstr(tokstr); array_append(pts, &pt, sizeof pt); @@ -18,15 +18,15 @@ extern array_t *parse(array_t *tokstrs) { } extern void destroy_pts(array_t *pts) { - int siz = array_size(pts); - int ptsiz; + size_t siz = array_size(pts); + size_t ptsiz; array_t *pt; symbol_t *sym; - for (int i = 0; i < siz; i++) { + for (size_t i = 0; i < siz; i++) { pt = *((array_t **) array_get(pts, i)); ptsiz = array_size(pt); - for (int k = 0; k < ptsiz; k++) { + for (size_t k = 0; k < ptsiz; k++) { sym = array_get(pt, k); free(sym->content); } @@ -50,84 +50,70 @@ static array_t *parse_tokstr(array_t *tokstr) { case TokkindDelim: tokhandle_delim(&state); break; default: ERR("control reaches default"); } + state.pos++; } while (state.pos != state.len); return state.pt; } static void tokhandle_chars(parse_state_t *state) { - tokhandle_common(state, SymkindText); + store_token(state, SymkindText); } static void tokhandle_delim(parse_state_t *state) { - int prevpos; + /* Archive the original position for later rewind */ + size_t initpos = state->pos; - prevpos = state->pos; + goto lookahead; - if (state->tok->run[0] != '$') { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + /* Whenever lookahead fails, control reaches here */ +fallback: + state->pos = initpos; + state->tok = array_get(state->tokstr, state->pos); + tokhandle_chars(state); + return; /* EARLY RETURN */ + + /* Find ${x} pattern */ +lookahead: + if (state->tok->run[0] != '$') + goto fallback; /* this token is not $ */ if (!nexttok(state)) - return; + goto fallback; /* $ was the last token */ - if (state->tok->kind != TokkindDelim) { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + if (state->tok->kind != TokkindDelim) + goto fallback; /* this token is not a delimiter */ - if (state->tok->run[0] != '{') { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + if (state->tok->run[0] != '{') + goto fallback; /* this token is not { */ if (!nexttok(state)) - return; + goto fallback; /* { was the last token */ - if (state->tok->kind != TokkindChars) { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + if (state->tok->kind != TokkindChars) + goto fallback; /* this token is not a plain token */ + + if (strchr(state->tok->run, ' ')) + goto fallback; /* this token does not have a valid replace string */ if (!nexttok(state)) - return; + goto fallback; /* this token was the last token */ - if (state->tok->kind != TokkindDelim) { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + if (state->tok->kind != TokkindDelim) + goto fallback; /* this token is not a delimiter */ - if (state->tok->run[0] != '}') { - state->pos = prevpos; - tokhandle_chars(state); - return; - } + if (state->tok->run[0] != '}') + goto fallback; /* this token is not } */ - /* - * In this context, we have ${xxx} but we are not - * sure whether xxx is valid or not. If xxx is - * invalid, we are to treat every token, i.e. - * $, {, xxx, } as a character token. - */ + /* Finally, we have a valid ${x} */ state->tok = array_get(state->tokstr, state->pos - 1); - if (strchr(state->tok->run, ' ')) { - for (int i = prevpos; i <= state->pos; i++) { - state->tok = array_get(state->tokstr, i); - tokhandle_chars(state); - } - return; - } + store_token(state, SymkindRepl); - tokhandle_common(state, SymkindRepl); + // Note that state->pos points to }. Thus, state->pos + // is to be advanced correctly in the do-while loop. } -static void tokhandle_common(parse_state_t *state, symkind_t kind) { +static void store_token(parse_state_t *state, symkind_t kind) { symbol_t sym; char *buf; @@ -139,8 +125,6 @@ static void tokhandle_common(parse_state_t *state, symkind_t kind) { sym.content = buf; array_append(state->pt, &sym, sizeof sym); - - state->pos++; } static int nexttok(parse_state_t *state) { diff --git a/hhss/c/parse.internals.h b/hhss/c/parse.internals.h index c39c3b0..93e3a4b 100644 --- a/hhss/c/parse.internals.h +++ b/hhss/c/parse.internals.h @@ -19,8 +19,8 @@ typedef struct { array_t *pt; // parse tree array_t *tokstr; // token stream token_t *tok; // token - int len; // token stream length - int pos; // current position in token stream + size_t len; // token stream length + size_t pos; // current position in token stream } parse_state_t; /************** @@ -29,7 +29,7 @@ typedef struct { static array_t *parse_tokstr(array_t *tokstr); static void tokhandle_chars(parse_state_t *state); static void tokhandle_delim(parse_state_t *state); -static void tokhandle_common(parse_state_t *state, symkind_t kind); +static void store_token(parse_state_t *state, symkind_t kind); static int nexttok(parse_state_t *state); #endif From 67aa357d88d667137084069357cb0b4689e20e03 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 11:12:56 +0900 Subject: [PATCH 57/59] fix: address null-terminating issues + prefer memcpy --- hhss/c/dtdbparse.c | 3 ++- hhss/c/replace.c | 8 ++++++-- hhss/c/rtdbparse.c | 9 ++++++--- lib/strutils.c | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/hhss/c/dtdbparse.c b/hhss/c/dtdbparse.c index 519fc03..c85f62e 100644 --- a/hhss/c/dtdbparse.c +++ b/hhss/c/dtdbparse.c @@ -16,8 +16,9 @@ extern array_t *dtdbparse(array_t *linestr) { if (l->run[0] == '#' ) continue; if (l->run[0] == '\n') continue; + /* copy the whole line + \0 */ buf = safe_malloc(l->len + 1); - strncpy(buf, l->run, l->len); + memcpy(buf, l->run, l->len + 1); temp.len = l->len; temp.num = l->num; diff --git a/hhss/c/replace.c b/hhss/c/replace.c index 52a761f..cf1aa36 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -99,11 +99,15 @@ static void rthandle_else(symbol_t *sym, array_t *sectarr) { static void rthandle_common(symbol_t *sym, array_t *sectarr, int idx) { char *val; + size_t siz; val = array_get(sectarr, idx); free(sym->content); - sym->content = safe_malloc(strlen(val) + 1); - strcpy(sym->content, val); + + /* copy the whole string + \0 */ + siz = strlen(val); + sym->content = safe_malloc(siz + 1); + memcpy(sym->content, val, siz + 1); } static void synerr_invalid(const char *rt) { diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index 39360b6..d6790a2 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -98,11 +98,14 @@ extern void destroy_rtdb(array_t *rtdb) { static array_t *add_mapper(array_t *table, const char *sectname) { array_t *sectarr; - char *buf; mapper_t mapper; + char *buf; + size_t bufsiz; - buf = safe_malloc(strlen(sectname) + 1); - strcpy(buf, sectname); + /* copy sectname which is a null-terminated string */ + bufsiz = strlen(sectname); + buf = safe_malloc(bufsiz + 1); + memcpy(buf, sectname, bufsiz + 1); sectarr = array_create(); diff --git a/lib/strutils.c b/lib/strutils.c index 5823b67..688b408 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -52,7 +52,7 @@ extern char **split( else { /* store the string */ buf = safe_malloc(diff + 1); - strncpy(buf, ini, diff); + memcpy(buf, ini, diff + 1); buf[diff] = '\0'; /* moves to the mark */ From c5ced170392f4c104ff32fbda9887825adeedcfb Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 11:18:24 +0900 Subject: [PATCH 58/59] fix: update dat.db --- hhss/dat.db | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hhss/dat.db b/hhss/dat.db index 060c09a..ce1dd87 100644 --- a/hhss/dat.db +++ b/hhss/dat.db @@ -18,7 +18,7 @@ ${user|char}라고 생각했던 ${user|char}와(과)의 신혼생활이 너무 내가 ${user|char}이(가) 될 수 있을 리 없잖아, 무리무리! (무리가 아니었다?!) 내 현실과 온라인 게임이 ${user|char|world|object|emotion}에 침식당하기 시작해서 위험해 너네, ${user|char}인 날 너무 좋아하는 거 아니냐. -${user|char|world|object}가 인기 없는 건 아무리 생각해도 ${user|char}들 탓이야! +${user|char|world|object}이(가) 인기 없는 건 아무리 생각해도 ${user|char}들 탓이야! ${user|char|emotion}을(를) 너무너무너무너무 좋아하는 100명의 ${user|char} ${user|char}에게 여자친구가 말이나 되나요 ${user|char|world|object}입니다만, 문제라도? @@ -34,7 +34,7 @@ ${user|char}의 2분 약속! [Web발신]${user|char}은(는) 나를 존중해야 한다 ${char|clang}쨩 귀여워 ${clang|object|char}로 세계정복!! -${clang}을(를) 할때마다 ${char}은 ${emotion}을 느낀다 +${clang}을(를) 할때마다 ${char}은(는) ${emotion}을(를) 느낀다 ${char}은(는) 내 아내임 ################## From 523b952c3ee9211da4acdacf6df5c93a3e1f1162 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Thu, 11 Jun 2026 19:26:02 +0900 Subject: [PATCH 59/59] fix: reflect changesets --- hhss/c/parse.c | 18 ++++++++---------- hhss/c/rtdbparse.c | 34 ++++++++++++++-------------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/hhss/c/parse.c b/hhss/c/parse.c index a8d4c82..7c456f1 100644 --- a/hhss/c/parse.c +++ b/hhss/c/parse.c @@ -64,17 +64,7 @@ static void tokhandle_delim(parse_state_t *state) { /* Archive the original position for later rewind */ size_t initpos = state->pos; - goto lookahead; - - /* Whenever lookahead fails, control reaches here */ -fallback: - state->pos = initpos; - state->tok = array_get(state->tokstr, state->pos); - tokhandle_chars(state); - return; /* EARLY RETURN */ - /* Find ${x} pattern */ -lookahead: if (state->tok->run[0] != '$') goto fallback; /* this token is not $ */ @@ -111,6 +101,14 @@ static void tokhandle_delim(parse_state_t *state) { // Note that state->pos points to }. Thus, state->pos // is to be advanced correctly in the do-while loop. + return; + + /* Whenever lookahead fails, control reaches here */ +fallback: + state->pos = initpos; + state->tok = array_get(state->tokstr, state->pos); + tokhandle_chars(state); + return; /* EARLY RETURN */ } static void store_token(parse_state_t *state, symkind_t kind) { diff --git a/hhss/c/rtdbparse.c b/hhss/c/rtdbparse.c index d6790a2..75e93cd 100644 --- a/hhss/c/rtdbparse.c +++ b/hhss/c/rtdbparse.c @@ -14,27 +14,21 @@ extern array_t *rtdbparse(array_t *linestr) { idx = -1; table = array_create(); - if (!setjmp(env)) - goto parse; - else - goto escape; - - parse: - /* backward compatibility for usr.dat */ - if (!seek_section()) { - sectarr = add_mapper(table, "user"); - while (parse_value(sectarr)); - } + if (!setjmp(env)) { + /* backward compatibility for usr.dat */ + if (!seek_section()) { + sectarr = add_mapper(table, "user"); + while (parse_value(sectarr)); + } - for (;;) { - sectname = parse_section(); - sectarr = rtdbquery(table, sectname); - if (!sectarr) - sectarr = add_mapper(table, sectname); - while (parse_value(sectarr)); + for (;;) { + sectname = parse_section(); + sectarr = rtdbquery(table, sectname); + if (!sectarr) + sectarr = add_mapper(table, sectname); + while (parse_value(sectarr)); + } } - - escape: return table; } @@ -45,7 +39,7 @@ extern array_t *rtdbquery(array_t *table, const char *sectname) { table_len = array_size(table); for (i = 0; i < table_len; i++) { mapper = array_get(table, i); - if (strcmp(mapper->sect, sectname)) + if (!STREQL(mapper->sect, sectname)) continue; return mapper->addr; }