# retoor <retoor@molodetz.nl>

CC = gcc
CFLAGS = -Wall -Wextra -Werror -pedantic -std=c11 -O3 -march=native -flto
CFLAGS_DEBUG = -Wall -Wextra -pedantic -std=c11 -g -O0 -DDEBUG
CFLAGS_COV = -Wall -Wextra -pedantic -std=c11 -g -O0 --coverage -fprofile-arcs -ftest-coverage
CFLAGS_PROF = -Wall -Wextra -pedantic -std=c11 -O2 -pg

INCLUDES = -Iinclude
LDFLAGS = -flto
LDFLAGS_COV = --coverage

SRC_DIR = src
INC_DIR = include
BUILD_DIR = build
TEST_DIR = tests
COV_DIR = coverage

SRCS = $(SRC_DIR)/lexer.c $(SRC_DIR)/ast.c $(SRC_DIR)/parser.c \
       $(SRC_DIR)/nfa.c $(SRC_DIR)/matcher.c $(SRC_DIR)/lorex.c \
       $(SRC_DIR)/repl.c $(SRC_DIR)/main.c

LIB_SRCS = $(SRC_DIR)/lexer.c $(SRC_DIR)/ast.c $(SRC_DIR)/parser.c \
           $(SRC_DIR)/nfa.c $(SRC_DIR)/matcher.c $(SRC_DIR)/lorex.c

OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))
LIB_OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(LIB_SRCS))

TARGET = lorex
LIB_TARGET = liblorex.a

TEST_SRCS = $(TEST_DIR)/test_lexer.c $(TEST_DIR)/test_parser.c \
            $(TEST_DIR)/test_nfa.c $(TEST_DIR)/test_matcher.c \
            $(TEST_DIR)/test_all.c $(TEST_DIR)/test_integration.c

TEST_BINS = $(BUILD_DIR)/test_lexer $(BUILD_DIR)/test_parser \
            $(BUILD_DIR)/test_nfa $(BUILD_DIR)/test_matcher \
            $(BUILD_DIR)/test_all $(BUILD_DIR)/test_integration

.PHONY: all clean test debug coverage lcov profile valgrind help install

all: $(BUILD_DIR) $(TARGET)

$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(TARGET): $(OBJS)
	$(CC) $(OBJS) -o $@ $(LDFLAGS)

$(LIB_TARGET): $(LIB_OBJS)
	ar rcs $@ $(LIB_OBJS)

debug: CFLAGS = $(CFLAGS_DEBUG)
debug: clean $(TARGET)

$(BUILD_DIR)/test_lexer: $(TEST_DIR)/test_lexer.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/test_parser: $(TEST_DIR)/test_parser.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/test_nfa: $(TEST_DIR)/test_nfa.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/test_matcher: $(TEST_DIR)/test_matcher.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/test_all: $(TEST_DIR)/test_all.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/test_integration: $(TEST_DIR)/test_integration.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) $(CFLAGS_DEBUG) $(INCLUDES) $< $(LIB_SRCS) -o $@

$(BUILD_DIR)/benchmark: $(TEST_DIR)/benchmark.c $(LIB_SRCS) | $(BUILD_DIR)
	$(CC) -O3 -march=native $(INCLUDES) $< $(LIB_SRCS) -o $@

test: $(TEST_BINS)
	@echo "running lexer tests..."
	@$(BUILD_DIR)/test_lexer
	@echo ""
	@echo "running parser tests..."
	@$(BUILD_DIR)/test_parser
	@echo ""
	@echo "running nfa tests..."
	@$(BUILD_DIR)/test_nfa
	@echo ""
	@echo "running matcher tests..."
	@$(BUILD_DIR)/test_matcher
	@echo ""
	@echo "running comprehensive tests..."
	@$(BUILD_DIR)/test_all
	@echo ""
	@echo "running integration tests..."
	@$(BUILD_DIR)/test_integration

coverage: CFLAGS = $(CFLAGS_COV)
coverage: LDFLAGS = $(LDFLAGS_COV)
coverage: clean $(BUILD_DIR)
	$(CC) $(CFLAGS_COV) $(INCLUDES) $(TEST_DIR)/test_all.c $(LIB_SRCS) -o $(BUILD_DIR)/test_coverage $(LDFLAGS_COV)
	$(BUILD_DIR)/test_coverage
	gcov -b $(LIB_SRCS)
	@echo ""
	@echo "coverage report generated"
	@mkdir -p $(BUILD_DIR)/coverage
	@mv *.gcov $(BUILD_DIR)/coverage/ 2>/dev/null || true
	@mv *.gcda $(BUILD_DIR)/coverage/ 2>/dev/null || true
	@mv *.gcno $(BUILD_DIR)/coverage/ 2>/dev/null || true

lcov: clean $(BUILD_DIR)
	@mkdir -p $(COV_DIR)
	$(CC) $(CFLAGS_COV) $(INCLUDES) $(TEST_DIR)/test_integration.c $(LIB_SRCS) -o $(BUILD_DIR)/test_lcov $(LDFLAGS_COV)
	lcov --zerocounters --directory .
	$(BUILD_DIR)/test_lcov
	lcov --capture --directory . --output-file $(COV_DIR)/coverage.info
	lcov --remove $(COV_DIR)/coverage.info '*/tests/*' --ignore-errors unused --output-file $(COV_DIR)/coverage.info
	genhtml $(COV_DIR)/coverage.info --output-directory $(COV_DIR)/html
	@echo ""
	@echo "lcov html report: $(COV_DIR)/html/index.html"

profile: CFLAGS = $(CFLAGS_PROF)
profile: clean $(BUILD_DIR)
	$(CC) $(CFLAGS_PROF) $(INCLUDES) $(TEST_DIR)/test_all.c $(LIB_SRCS) -o $(BUILD_DIR)/test_profile
	$(BUILD_DIR)/test_profile
	gprof $(BUILD_DIR)/test_profile gmon.out > $(BUILD_DIR)/profile.txt
	@echo ""
	@echo "profile report: $(BUILD_DIR)/profile.txt"
	@mv gmon.out $(BUILD_DIR)/ 2>/dev/null || true

valgrind: $(BUILD_DIR)/test_all
	valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
		--error-exitcode=1 $(BUILD_DIR)/test_all

valgrind-verbose: $(BUILD_DIR)/test_all
	valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \
		--verbose --log-file=$(BUILD_DIR)/valgrind.log $(BUILD_DIR)/test_all
	@echo "valgrind log: $(BUILD_DIR)/valgrind.log"

benchmark: $(BUILD_DIR)/benchmark
	@./$(BUILD_DIR)/benchmark

benchmark-quick: $(TARGET)
	@echo "quick benchmark..."
	@echo "pattern: [a-z]+@[a-z]+\\.[a-z]+"
	@time -p sh -c 'for i in $$(seq 1 1000); do ./$(TARGET) "[a-z]+@[a-z]+\\.[a-z]+" "test@example.com" > /dev/null; done'
	@echo ""
	@echo "pattern: (a|b)*abb"
	@time -p sh -c 'for i in $$(seq 1 1000); do ./$(TARGET) "(a|b)*abb" "aabababb" > /dev/null; done'

install: $(TARGET)
	install -d $(DESTDIR)/usr/local/bin
	install -m 755 $(TARGET) $(DESTDIR)/usr/local/bin/

uninstall:
	rm -f $(DESTDIR)/usr/local/bin/$(TARGET)

clean:
	rm -rf $(BUILD_DIR) $(TARGET) $(LIB_TARGET) $(COV_DIR)
	rm -f *.gcov *.gcda *.gcno gmon.out

help:
	@echo "lorex makefile targets:"
	@echo "  all         build optimized release binary"
	@echo "  debug       build with debug symbols"
	@echo "  test        run all tests"
	@echo "  coverage    run tests with gcov coverage analysis"
	@echo "  lcov        generate html coverage report with lcov"
	@echo "  profile     run tests with profiling"
	@echo "  valgrind    run tests under valgrind"
	@echo "  benchmark   run performance benchmarks"
	@echo "  install     install to /usr/local/bin"
	@echo "  uninstall   remove from /usr/local/bin"
	@echo "  clean       remove build artifacts"
	@echo "  help        show this message"
