diff --git a/.gitignore b/.gitignore index 12435b4..e6786ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ **/.vs .vscode/ -bin/ -__record__ \ No newline at end of file +lib/*.o +lib/*.d diff --git a/Makefile b/Makefile index 7f2f63d..9ae86f7 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 \ - -$$($1_name): $$($1_objects) - $(CC) $$^ $(CFLAGS) -o $$@ - $$(file >> $$(tempfile),$1) - @echo $(build_completed_str) $(call name_str,$$@)"\n" -endef -all_objects = +.PHONY: all $(TARGETS) +.PHONY: $(TEST) install uninstall clean cleanall help -$(foreach program,$(programs),$(eval $(call program_template,$(program)))) +## Default Goal ## +all: $(TARGETS) -# 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 $< +$(TARGETS): + $(MAKE) -C $@/c TARGET=$@ DIR_DATA=$(DIR_DATA) + @echo $(STR_BUILD_DONE) $(call STR_NAME,$@) -## 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) +## Test Program ## +$(TEST): + $(MAKE) --always-make --directory=$(TEST) \ + PROG=$(PROG) \ + TESTCASE=$(TESTCASE) \ + DIR_BIN=$(DIR_BIN) +## 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)) + $(MAKE) --directory=$(TEST) clean -.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 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 - @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/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..3d9ac0d 100644 --- a/hhss/c/Makefile +++ b/hhss/c/Makefile @@ -1,15 +1,43 @@ -CC = gcc -CCFLAGS = -O -Wall -W -pedantic +## Variables ## +TARGET := hhss -TARGET = hhss +CC := gcc +CFLAGS := -O -Wall -W -pedantic +CFLAGS += -g +CFLAGS += -MMD -MP +CPPFLAGS = \ + -I $(DIR_LIB) \ + -DINSTPATH='"$(DIR_DATA)/$(TARGET)"' \ + -DPROGNAME='"$(TARGET)"' -SOURCES = $(wildcard ./*.c) -OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) +SOURCES = $(wildcard *.c) +LIB_SRCS = $(wildcard $(DIR_LIB)/*.c) +OBJECTS = $(SOURCES:.c=.o) +LIB_OBJS = $(notdir $(LIB_SRCS:.c=.o)) +DIR_DATA := ../.. +DIR_LIB := ../../lib + +## Targets ## +.PHONY: all clean + +## Default Goal ## all: $(TARGET) -$(TARGET): $(OBJECTS) - $(CC) $(CCFLAGS) -o $@ $^ +## Build ## +$(TARGET): $(OBJECTS) $(LIB_OBJS) + $(CC) $^ $(CFLAGS) -o $@ + +$(OBJECTS): %.o: %.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +$(LIB_OBJS): %.o: $(DIR_LIB)/%.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +## Dependency ## +-include $(OBJECTS:.o=.d) +-include $(LIB_OBJS:.o=.d) -%.o: %.c - $(CC) $(CCFLAGS) -c -o $@ $< +## Tasks ## +clean: + rm -f $(TARGET) *.o *.d diff --git a/hhss/c/argv1parse.c b/hhss/c/argv1parse.c new file mode 100644 index 0000000..df064ef --- /dev/null +++ b/hhss/c/argv1parse.c @@ -0,0 +1,23 @@ +#include "argv1parse.h" +#include "argv1parse.internals.h" + +extern int argv1parse(const char *argv1, int threshold) { + char *i; + long ret; + + errno = 0; + ret = strtol(argv1, &i, 10); + + 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 > (long) threshold) + VERR("count must be less than or equal to %d", threshold); + + return (int) 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..f8145d9 --- /dev/null +++ b/hhss/c/argv1parse.internals.h @@ -0,0 +1,14 @@ +#ifndef ARGV1PARSE_INTERNALS_H +#define ARGV1PARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#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..1c1d1af --- /dev/null +++ b/hhss/c/dbload.c @@ -0,0 +1,20 @@ +#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) { + FILE *fp; + + fp = fopen(filename, "r"); + if (!fp) + return 0; + + (void) fclose(fp); + + return 1; +} 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..b9f20fd --- /dev/null +++ b/hhss/c/dbload.internals.h @@ -0,0 +1,19 @@ +#ifndef DBLOAD_INTERNALS_H +#define DBLOAD_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "global.h" +#include "wrappers.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..fe2d766 --- /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 = [%zu]\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 = [%zu]\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..c85f62e --- /dev/null +++ b/hhss/c/dtdbparse.c @@ -0,0 +1,56 @@ +#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 (l->run[0] == '#' ) continue; + if (l->run[0] == '\n') continue; + + /* copy the whole line + \0 */ + buf = safe_malloc(l->len + 1); + memcpy(buf, l->run, l->len + 1); + + 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..ad2d8b3 --- /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); + memcpy(run, buf, pos + 1); /* \0 copied */ + tok.kind = TokkindChars; + 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 = TokkindDelim; + 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..a2b5765 --- /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 { + TokkindChars, + TokkindDelim +} tokkind_t; + +typedef struct { + char *run; + size_t 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..7c456f1 --- /dev/null +++ b/hhss/c/parse.c @@ -0,0 +1,134 @@ +#include "parse.h" +#include "parse.internals.h" + +extern array_t *parse(array_t *tokstrs) { + array_t *pts, *tokstr, *pt; + size_t len; + + pts = array_create(); + len = array_size(tokstrs); + + 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); + } + + return pts; +} + +extern void destroy_pts(array_t *pts) { + size_t siz = array_size(pts); + size_t ptsiz; + array_t *pt; + symbol_t *sym; + + for (size_t i = 0; i < siz; i++) { + pt = *((array_t **) array_get(pts, i)); + ptsiz = array_size(pt); + for (size_t 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; + + state.len = array_size(tokstr); + state.pos = 0; + state.pt = array_create(); + state.tokstr = tokstr; + + do { + state.tok = array_get(tokstr, state.pos); + switch (state.tok->kind) { + case TokkindChars: tokhandle_chars(&state); break; + 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) { + store_token(state, SymkindText); +} + +static void tokhandle_delim(parse_state_t *state) { + /* Archive the original position for later rewind */ + size_t initpos = state->pos; + + /* Find ${x} pattern */ + if (state->tok->run[0] != '$') + goto fallback; /* this token is not $ */ + + if (!nexttok(state)) + goto fallback; /* $ was the last token */ + + if (state->tok->kind != TokkindDelim) + goto fallback; /* this token is not a delimiter */ + + if (state->tok->run[0] != '{') + goto fallback; /* this token is not { */ + + if (!nexttok(state)) + goto fallback; /* { was the last token */ + + 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)) + goto fallback; /* this token was the last token */ + + if (state->tok->kind != TokkindDelim) + goto fallback; /* this token is not a delimiter */ + + if (state->tok->run[0] != '}') + goto fallback; /* this token is not } */ + + /* Finally, we have a valid ${x} */ + state->tok = array_get(state->tokstr, state->pos - 1); + store_token(state, SymkindRepl); + + // 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) { + symbol_t sym; + char *buf; + + /* copy the whole string including \0 */ + buf = safe_malloc(state->tok->len + 1); + memcpy(buf, state->tok->run, state->tok->len + 1); + + sym.kind = kind; + sym.content = buf; + + array_append(state->pt, &sym, sizeof sym); +} + +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..e24abb7 --- /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 { + SymkindText, + SymkindRepl +} 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..93e3a4b --- /dev/null +++ b/hhss/c/parse.internals.h @@ -0,0 +1,35 @@ +#ifndef PARSE_INTERNALS_H +#define PARSE_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#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 + size_t len; // token stream length + size_t 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 store_token(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..cf1aa36 --- /dev/null +++ b/hhss/c/replace.c @@ -0,0 +1,127 @@ +#include "replace.h" +#include "replace.internals.h" + +extern void replace_templates(array_t *pts, array_t *rtdb) { + array_t *pt, *rts, *sectarr; + symbol_t *sym; + size_t ptslen, ptlen, rtslen; + char *rt; + int v; + + pre_user = -1; + 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 == SymkindText) + continue; + + 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_invalid(rt); + + if (STREQL(rt, "user")) + rthandle_user(sym, sectarr); + else + rthandle_else(sym, sectarr); + + /* 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) { + int r, siz; + + siz = array_size(sectarr); + if (siz == 1) { + r = 0; + goto common; + } + + do { + r = rand_range(0, siz); + } while (r == pre_user); + pre_user = r; + + 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; + size_t siz; + + val = array_get(sectarr, idx); + free(sym->content); + + /* 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) { + safe_fprintf(stderr, + Cbred "" Creset " invalid replace template " + Cemerald "%s" Creset "\n", + rt + ); + exit(EXIT_FAILURE); +} + +static void synerr_empty(void) { + safe_fprintf(stderr, + Cbred "" Creset " empty replace template detected\n" + ); + exit(EXIT_FAILURE); +} diff --git a/hhss/c/replace.h b/hhss/c/replace.h new file mode 100644 index 0000000..5a192f8 --- /dev/null +++ b/hhss/c/replace.h @@ -0,0 +1,15 @@ +#ifndef REPLACE_H +#define REPLACE_H + +/************ + * INCLUDES * + ************/ +#include "utils.h" +#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..3572b8f --- /dev/null +++ b/hhss/c/replace.internals.h @@ -0,0 +1,33 @@ +#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 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_invalid(const char *rt); +static void synerr_empty(void); + +/******************** + * 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..75e93cd --- /dev/null +++ b/hhss/c/rtdbparse.c @@ -0,0 +1,195 @@ +#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)) { + /* 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)); + } + } + 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 (!STREQL(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 (STREQL(sectname, "user")) { + if (sectarr_siz >= threshold) + continue; + VERR("at least %zu user entries required but only %zu", + 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; + mapper_t mapper; + char *buf; + size_t bufsiz; + + /* copy sectname which is a null-terminated string */ + bufsiz = strlen(sectname); + buf = safe_malloc(bufsiz + 1); + memcpy(buf, sectname, bufsiz + 1); + + 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; + do { + next_line(); + spn = strspn(l->run, whitespaces); + } while (l->len == spn || l->run[spn] == '#'); +} + +static void synerr(void) { + safe_fprintf(stderr, + Cbred "" Creset " %s\n" + Cbwhite "note:" Creset " problematic since here\n" + "%4zu|" 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..ae6767d --- /dev/null +++ b/hhss/c/rtdbparse.h @@ -0,0 +1,18 @@ +#ifndef RTDBPARSE_H +#define RTDBPARSE_H + +/************ + * INCLUDES * + ************/ +#include "utils.h" +#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..ce1dd87 --- /dev/null +++ b/hhss/dat.db @@ -0,0 +1,101 @@ +################## +# To Be Resolved # +################## + +${user|char}은(는) 레벨이 올랐다! + ${user|char}님이 채팅방을 나갔습니다. +${user|char}쨩 완전 천사wwww +나 ${user|char}인데 개추 눌렀다ww +${user|char}은(는) 그런 말투 안써요 +나 ${user}인데 얘 ${user|object} 맞음 ㅇㅇ +본인 방금 ${user|char|object} 되는 상상함w +새삼 ${user|char|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}에게 여자친구가 말이나 되나요 +${user|char|world|object}입니다만, 문제라도? +${user|char}들이 이세계에서 온다는 모양인데요? +언제나 쌀쌀맞게 구는 ${user|clang}지만 ${char|world}을(를) 짝사랑하는 속마음이 다 들려서 귀여워 +전생 따위로 도망칠 수 있을 줄 알았나요, ${user}? +젠장, 또 ${user|clang}(이)야. 나는 숭배해야만 해. +${user}은(는) 요새 ${world|object|clang}에 강한 ${emotion}을(를) 느끼고 있다 +신조차 모독하는 천재성을 가지고 있는 이 ${user|char}조차- +이건 ${user|clang}에 대한 모욕이라고 밖엔- +${user|char}의 2분 약속! +할수있다 ${user|clang}라면! +[Web발신]${user|char}은(는) 나를 존중해야 한다 +${char|clang}쨩 귀여워 +${clang|object|char}로 세계정복!! +${clang}을(를) 할때마다 ${char}은(는) ${emotion}을(를) 느낀다 +${char}은(는) 내 아내임 + +################## +# Normal Strings # +################## + +깔깔 C로 200줄 나오는 코드 형은 파이썬으로 30줄만에 짰다 +전부약탈해주겠어 +wwwww +끼뺫! +랄까... +와..... +아악 +마따끄... +이거 진짜에요? +저 요즘 살 찐 거 같아요 +엑셀 팡션? 너무 많이 사용하지 마세요 +그거 절대로 거짓말ww +이제 누가 공지해주냐? +무수한 악수의 요청이...!! +고등학교 반배정?후기 +이봐요 미친놈씨 +에휴 닉네임 꼬라지 +...........랄까. +저는 그때 미쳤었죠. +어떠한 초딩들도 저에게 접근을 안합니다. +이..이분 무서워! +당신이 한국의 시키인 것입니까? +미안하다 이거 보여주려고 어그로 끌었다 +라는 내용의 애니 없냐? +어 맞아맞아 놀랍지만 그건 사실이야 +어둠에다크에서 죽음의데스를 느끼며 +날 속인거니 +이런 세계선이 구축된건가? +감사합니다 절 애니프사라고 해주셨어요 +그걸 말하려면 최소한 애니영상이 아닌 다른데서 해야하지 않을까요? +자기발로 쓰레기장에 들어가놓고 쓰레기가 많다면서 투덜대는 꼴밖에 더 되는게 아닐까 합니다 +다시 말한다 난 오타쿠가 아니고 +오호? 그 말로만 듣던? +저기 무슨 말씀이신지? +아... 제가 미처 말하지 않았군요... +닉네임 강력하시네요 +이곳인가... 나의 20대를 시작할 곳이... +러브라이브 보는 사람 손 +지는 거에요? +이겨 +풀려나자마자 승리 선언 !! +그냥 하다가 나온건데 이거 좋은건가요? +깨져라, 경화수월 +어째서 공부라는건 해야만 하는것이지? +선생님 저는 의문이로군요 +그건 저같은 천재가 리더로 없었기 때문이 아닐까요? +...그 말, 정말 깊다, 깊어. +와... 너 지금 **정곡을 찔렀어**. +맞아. **정확히 꿰뚫었어**. 너처럼 깊이 파고드는 사람 드물어. +와... 너 정말, **핵심을 찔렀어**. +이건 단순한 분노가 아니야. 네 안에서 터져나오는 **절규**야. +...정말 화나겠다. 네 분노는 정당해. 오늘은 마음껏 울어도 돼. +인정, **너 제대로 찔렀다**. +이건 **단순한 질문이 아니라 통찰**이야. +너 지금 완전 잘하고 있어. 그만큼 네가 자기 몸 소중히 챙긴다는 뜻이야. +[Wep발신] 너는 Utils 프로젝트를 존중해야 한다 그러므로 너는 Utils를 존중해야 한다 +주문은 토끼입니까 라고 오타쿠들이 좋아하는 애니 있습니다 +메소복사버그 발견햇습니다 이글을 복사한뒤 NPC를 20번 클릭하면 메소가 20억 생겨 있습니다 diff --git a/hhss/rt.db b/hhss/rt.db new file mode 100644 index 0000000..42f1428 --- /dev/null +++ b/hhss/rt.db @@ -0,0 +1,62 @@ +[user] + 코르 + 치노 + 샌드박스 유저 + 엘리시움 + 메붕이 + 전붕이 + logicseeker + Cor + +[char] + 아즈사 + 아오바 + 아리스 + 미야코 + 우이 + +[world] + 마인크래프트크랙버전1.23.1 + 마인크래프트버그판1.17.2 + 가상현실 + +[object] + 중2병 + 동아시아사 + 세계사 + 대학수학능력평가 + 교육제도 + 주입식교육 + 기출문제집 + 건전지 + 컴퓨터 + C언어 + 잡아스크립트 + 피자 + +[emotion] + 환희 + 의구심 + 동경 + 관심 + 분노 + 격노 + 행복 + 슬픔 + 쾌락 + 좌절 + 순수함 + 상쾌함 + 유쾌함 + 통쾌함 + +[clang] + C + C++ + JavaScript + TypeScript + Java + COBOL + Haskell + Python + x86 assembly 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/lib/array.adt.c b/lib/array.adt.c new file mode 100644 index 0000000..9783295 --- /dev/null +++ b/lib/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->arr); + 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->arr = safe_realloc2x_arr( + a->arr, + &a->max, + ESIZ(a->arr) + ); +} diff --git a/lib/array.adt.h b/lib/array.adt.h new file mode 100644 index 0000000..8183db0 --- /dev/null +++ b/lib/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/lib/array.adt.internals.h b/lib/array.adt.internals.h new file mode 100644 index 0000000..c8053c3 --- /dev/null +++ b/lib/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/lib/colorcodes.h b/lib/colorcodes.h new file mode 100644 index 0000000..8fa9b0c --- /dev/null +++ b/lib/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/lib/fatal.c b/lib/fatal.c new file mode 100644 index 0000000..0d77dd2 --- /dev/null +++ b/lib/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 +) { + (void) 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; + + (void) fputs(PROGNAME ": fatal: ", stderr); + + va_start(ap, filename); + (void) vfprintf(stderr, errmsg, ap); + va_end(ap); + + (void) fprintf( + stderr, + " [arose at " Cemerald "(*%s):%s" Creset "]\n", + funcname, filename + ); + + exit(EXIT_FAILURE); +} diff --git a/lib/fatal.h b/lib/fatal.h new file mode 100644 index 0000000..51f79bf --- /dev/null +++ b/lib/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 funcname, + const char * restrict filename, + ... +); + +#endif diff --git a/lib/fatal.internals.h b/lib/fatal.internals.h new file mode 100644 index 0000000..7ac2359 --- /dev/null +++ b/lib/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/lib/loadfile.c b/lib/loadfile.c new file mode 100644 index 0000000..3e33e7c --- /dev/null +++ b/lib/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/lib/loadfile.h b/lib/loadfile.h new file mode 100644 index 0000000..6122ec6 --- /dev/null +++ b/lib/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/lib/loadfile.internals.h b/lib/loadfile.internals.h new file mode 100644 index 0000000..f6c08a4 --- /dev/null +++ b/lib/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/lib/readline.c b/lib/readline.c new file mode 100644 index 0000000..de6511c --- /dev/null +++ b/lib/readline.c @@ -0,0 +1,48 @@ +#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); + break; + } + if (ch == '\r') continue; + if (ch == '\n') break; + + buf[pos++] = ch; + if (pos == bufsiz) + buf = safe_realloc2x(buf, &bufsiz); + } + + if (bufsiz - pos == 1) + buf = safe_realloc2x(buf, &bufsiz); + buf[pos++] = '\n'; + buf[pos] = '\0'; + *line = buf; + *len = pos; + + return 0; +} diff --git a/lib/readline.h b/lib/readline.h new file mode 100644 index 0000000..f4e100a --- /dev/null +++ b/lib/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/lib/readline.internals.h b/lib/readline.internals.h new file mode 100644 index 0000000..0fce73e --- /dev/null +++ b/lib/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/lib/strutils.c b/lib/strutils.c new file mode 100644 index 0000000..688b408 --- /dev/null +++ b/lib/strutils.c @@ -0,0 +1,72 @@ +#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 = 4; + arr = safe_malloc(max * ESIZ(arr)); + ini = fin = src; + + do { + // Find the location of the next mark + fin = strstr(fin, mark); + + /* no mark found */ + if (!fin) { + /* 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 { + 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); + memcpy(buf, ini, diff + 1); + buf[diff] = '\0'; + + /* moves to the mark */ + ini = fin; + } + } + + // Store the buffer into the array + if (siz == max) + arr = safe_realloc2x_arr(arr, &max, ESIZ(arr)); + arr[siz++] = buf; + + } while (fin); + + *retsiz = siz; + return arr; +} diff --git a/lib/strutils.h b/lib/strutils.h new file mode 100644 index 0000000..906db0b --- /dev/null +++ b/lib/strutils.h @@ -0,0 +1,20 @@ +#ifndef STRUTILS_H +#define STRUTILS_H + +/************ + * INCLUDES * + ************/ +#include +# +#include "utils.h" + +/************** + * PROTOTYPES * + **************/ +char **split( + const char * restrict src, + const char * restrict mark, + size_t *retsiz +); + +#endif diff --git a/lib/strutils.internals.h b/lib/strutils.internals.h new file mode 100644 index 0000000..d5ae10f --- /dev/null +++ b/lib/strutils.internals.h @@ -0,0 +1,13 @@ +#ifndef STRUTILS_INTERNALS_H +#define STRUTILS_INTERNALS_H + +/************ + * INCLUDES * + ************/ +#include +#include +# +#include "utils.h" +#include "wrappers.h" + +#endif diff --git a/yandere/c/utils.c b/lib/utils.c similarity index 94% rename from yandere/c/utils.c rename to lib/utils.c index bb67446..7d61798 100644 --- a/yandere/c/utils.c +++ b/lib/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/lib/utils.h similarity index 59% rename from yandere/c/utils.h rename to lib/utils.h index 6c2850a..9a51c01 100644 --- a/yandere/c/utils.h +++ b/lib/utils.h @@ -4,11 +4,14 @@ /************ * INCLUDES * ************/ -#include -#include +#include + +/********** + * MACROS * + **********/ +#define ESIZ(arr) (sizeof (arr)[0]) # -#include "fatal.h" -#include "global.h" +#define STREQL(s1,s2) (!(strcmp((s1),(s2)))) /************** * PROTOTYPES * diff --git a/lib/utils.internals.h b/lib/utils.internals.h new file mode 100644 index 0000000..10bf786 --- /dev/null +++ b/lib/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/lib/wrappers.c b/lib/wrappers.c new file mode 100644 index 0000000..0fcf9bc --- /dev/null +++ b/lib/wrappers.c @@ -0,0 +1,94 @@ +#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 *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 *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; +} + +/************ + * 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, sigprocessor_t handler) { + if (signal(sig, handler) == SIG_ERR) + ERR("signal error"); +} diff --git a/lib/wrappers.h b/lib/wrappers.h new file mode 100644 index 0000000..3b9f4bd --- /dev/null +++ b/lib/wrappers.h @@ -0,0 +1,29 @@ +#ifndef WRAPPERS_H +#define WRAPPERS_H + +/************ + * INCLUDES * + ************/ +#include +#include + +/************ + * TYPEDEFS * + ************/ +typedef void sigprocessor_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 *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); +void safe_signal(int sig, sigprocessor_t handler); + +#endif diff --git a/lib/wrappers.internals.h b/lib/wrappers.internals.h new file mode 100644 index 0000000..0ca74fb --- /dev/null +++ b/lib/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/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/test/Makefile b/test/Makefile new file mode 100644 index 0000000..f12ad30 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,23 @@ +## 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) clean + +# Note. TESTCASE and PROG must be passed +$(TEST): $(TEST_MAKER) + ./$(TEST_MAKER) $(DIR_TESTCASE)/$(TESTCASE) + ./$(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 new file mode 100644 index 0000000..2545aaa --- /dev/null +++ b/vars.mk @@ -0,0 +1,49 @@ +############# +# Variables # +############# + +## Make ## +SHELL := /bin/sh + +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 + +## Install ## +DIR_LIB := lib +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..e4022f4 100644 --- a/yandere/c/Makefile +++ b/yandere/c/Makefile @@ -1,15 +1,41 @@ -CC = gcc -CCFLAGS = -O -Wall -W -pedantic -g +## Variables ## +TARGET := yandere -TARGET = yandere +CC := gcc +CFLAGS := -O -Wall -W -pedantic +CFLAGS += -g +CFLAGS += -MMD -MP +CPPFLAGS = \ + -I $(DIR_LIB) \ + -DPROGNAME='"$(TARGET)"' -SOURCES = $(wildcard ./*.c) -OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) +SOURCES = $(wildcard *.c) +LIB_SRCS = $(wildcard $(DIR_LIB)/*.c) +OBJECTS = $(SOURCES:.c=.o) +LIB_OBJS = $(notdir $(LIB_SRCS:.c=.o)) +DIR_LIB := ../../lib + +## Targets ## +.PHONY: all clean + +## Default Goal ## all: $(TARGET) -$(TARGET): $(OBJECTS) - $(CC) $(CCFLAGS) -o $@ $^ +## Build ## +$(TARGET): $(OBJECTS) $(LIB_OBJS) + $(CC) $^ $(CFLAGS) -o $@ + +$(OBJECTS): %.o: %.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +$(LIB_OBJS): %.o: $(DIR_LIB)/%.c + $(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@ + +## Dependency ## +-include $(OBJECTS:.o=.d) +-include $(LIB_OBJS:.o=.d) -%.o: %.c - $(CC) $(CCFLAGS) -c -o $@ $< +## Tasks ## +clean: + rm -f $(TARGET) *.o *.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/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/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.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 780a64b..81085a1 100644 --- a/yandere/c/global.h +++ b/yandere/c/global.h @@ -9,19 +9,16 @@ /********** * MACROS * **********/ -#define PROGNAME "yandere" #define BUFMAX 128 /************ * TYPEDEFS * ************/ -typedef void sighandler_t(int sig); - typedef enum { - Event_default, - Event_sigint, - Event_sigquit, - Event_sigterm + EventDefault, + EventSigint, + EventSigquit, + EventSigterm } event_t; /******************** 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/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/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 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/wrappers.h b/yandere/c/wrappers.h deleted file mode 100644 index 4b7aece..0000000 --- a/yandere/c/wrappers.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef WRAPPERS_H -#define WRAPPERS_H - -/************ - * INCLUDES * - ************/ -#include -#include -#include -# -#include "fatal.h" -#include "global.h" - -/************** - * PROTOTYPES * - **************/ -void safe_fputs(FILE *stream, const char *line); -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); - -#endif 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"); } } 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"