Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47a30e426a | |||
| 129932eecf | |||
| 680ad15b25 | |||
| d80bdc6f51 | |||
| f4a8a340a6 | |||
| 8a0dd6f7f8 |
97
c_projects/tiktaktoe/Makefile
Normal file
97
c_projects/tiktaktoe/Makefile
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# MakeFile for tiktaktoe
|
||||||
|
# Created 12/23/2025
|
||||||
|
# Authored by: xavi
|
||||||
|
.POSIX:
|
||||||
|
|
||||||
|
# DIRECTORIES
|
||||||
|
SRC_DIR := src
|
||||||
|
INCLUDE_DIR := include
|
||||||
|
OBJ_DIR := obj
|
||||||
|
TESTS_DIR := tests
|
||||||
|
TESTS_INCL_DIR := $(TESTS_DIR)/include
|
||||||
|
SUBMODULES_DIR := submodules
|
||||||
|
|
||||||
|
# Final Binary Name
|
||||||
|
PROJECT_NAME := tiktaktoe
|
||||||
|
PROJECT_OBJ := $(OBJ_DIR)/$(PROJECT_NAME).o
|
||||||
|
|
||||||
|
# SUBMODULE VARS FOR GENERATING STATIC LIBS
|
||||||
|
SUBMODULES := $(wildcard $(SUBMODULES_DIR)/*)
|
||||||
|
SUBBARE := $(SUBMODULES:$(SUBMODULES_DIR)/%=%)
|
||||||
|
SUBMODULE_SLIB := $(foreach m,$(SUBBARE),$(SUBMODULES_DIR)/$(m)/$(m).a)
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_LIBS = $(shell find ./ -name "*.a")
|
||||||
|
|
||||||
|
# C compiler settings
|
||||||
|
CC := gcc
|
||||||
|
INCLUDE_LIST := $(foreach m,$(SUBMODULES),$(m)/$(INCLUDE_DIR)) $(INCLUDE_DIR) $(TESTS_INCL_DIR)
|
||||||
|
INCLUDES := $(addprefix -I,$(INCLUDE_LIST))
|
||||||
|
CFLAGS := -std=c99 -ggdb -Wall -Wextra -MMD -MP -lncurses -fsanitize=address
|
||||||
|
DFLAGS := -D_DEBUG
|
||||||
|
|
||||||
|
# Main Executable Filename
|
||||||
|
MAIN := main.c
|
||||||
|
|
||||||
|
# Files
|
||||||
|
SRC := $(filter-out $(SRC_DIR)/$(MAIN), $(wildcard $(SRC_DIR)/*.c))
|
||||||
|
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
|
||||||
|
TESTS := $(wildcard $(TESTS_DIR)/*.c)
|
||||||
|
|
||||||
|
# Get Dependencies from gcc using -MMD and -MP
|
||||||
|
DEPENDENCIES := $(OBJ:%.o=%.d)
|
||||||
|
|
||||||
|
all: $(PROJECT_NAME)
|
||||||
|
|
||||||
|
# CREATE STATIC LIBRARY OF MODULE
|
||||||
|
$(PROJECT_NAME).a: $(PROJECT_OBJ) check_submods
|
||||||
|
ar rcs $(@) $(<)
|
||||||
|
|
||||||
|
# CREATE TEST EXECUTABLES
|
||||||
|
$(TESTS:$(TESTS_DIR)/%.c=%): %: $(OBJ_DIR)/%.o $(OBJ) check_submods
|
||||||
|
$(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(<) $(OBJ) $(STATIC_LIBS)
|
||||||
|
|
||||||
|
# CREATE TEST OBJS
|
||||||
|
$(OBJ_DIR)/%.o: $(TESTS_DIR)/%.c $(OBJ)
|
||||||
|
$(CC) $(CFLAGS) $(DFLAGS) $(INCLUDES) -c -o $(@) $(^)
|
||||||
|
|
||||||
|
# CREATE MAIN OBJ
|
||||||
|
$(PROJECT_NAME): $(MAIN:%.c=$(OBJ_DIR)/%.o) $(OBJ) check_submods
|
||||||
|
$(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(<) $(OBJ) $(STATIC_LIBS)
|
||||||
|
|
||||||
|
# CREATE OBJS
|
||||||
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) $(DFLAGS) $(INCLUDES) -c -o $(@) $(<)
|
||||||
|
|
||||||
|
# RECURSE THROUGH SUBMODULES AND RUN MAKE *.a
|
||||||
|
$(SUBMODULE_SLIB):
|
||||||
|
$(MAKE) -C $(dir $(@)) $(notdir $(@))
|
||||||
|
|
||||||
|
check_submods: $(SUBMODULE_SLIB)
|
||||||
|
|
||||||
|
|
||||||
|
# RECURSE AND CLEAN ALL FILES
|
||||||
|
clean:
|
||||||
|
@for sm in $(SUBMODULES) ; do \
|
||||||
|
$(MAKE) -C $$sm clean ; \
|
||||||
|
done
|
||||||
|
rm -f $(PROJECT_NAME) $(OBJ_DIR)/* $(TESTS:$(TESTS_DIR)/%.c=%) ./*.a
|
||||||
|
|
||||||
|
-include $(DEPENDENCIES)
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "SUBMODULES: $(SUBMODULES)"
|
||||||
|
@echo "SUBMODULE_SLIB: $(SUBMODULE_SLIB)"
|
||||||
|
@echo "STATIC_LIBS: $(STATIC_LIBS)"
|
||||||
|
|
||||||
|
.PHONY: clean all check_submods help
|
||||||
|
|
||||||
|
# Create Project Hierarchy
|
||||||
|
|
||||||
|
dirs: $(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR) $(SRC_DIR)/$(MAIN)
|
||||||
|
|
||||||
|
$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):
|
||||||
|
mkdir -p $(@)
|
||||||
|
|
||||||
|
$(SRC_DIR)/$(MAIN):
|
||||||
|
touch $(SRC_DIR)/$(MAIN)
|
||||||
30
c_projects/tiktaktoe/include/gamelogic.h
Normal file
30
c_projects/tiktaktoe/include/gamelogic.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef GAMELOGIC_H
|
||||||
|
#define GAMELOGIC_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
|
||||||
|
#define N 3
|
||||||
|
#define ROWS N
|
||||||
|
#define COLS N
|
||||||
|
#define DIAGS 2
|
||||||
|
#define TOTAL_SQUARES ROWS*COLS
|
||||||
|
#define DOF 2
|
||||||
|
|
||||||
|
typedef enum{OPEN, X, O} squarestate;
|
||||||
|
enum turn {X_TURN, O_TURN};
|
||||||
|
typedef struct position_t{
|
||||||
|
uint8_t row;
|
||||||
|
uint8_t col;
|
||||||
|
}position_t;
|
||||||
|
|
||||||
|
void print_boardstate();
|
||||||
|
void init_gamestate();
|
||||||
|
int is_game_over();
|
||||||
|
void add_point();
|
||||||
|
void update_boardstate();
|
||||||
|
void update_gamestate(char input);
|
||||||
|
void main_loop();
|
||||||
|
|
||||||
|
#endif
|
||||||
4
c_projects/tiktaktoe/include/tiktaktoe.h
Normal file
4
c_projects/tiktaktoe/include/tiktaktoe.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef TIKTAKTOE_H
|
||||||
|
#define TIKTAKTOE_H
|
||||||
|
|
||||||
|
#endif
|
||||||
120
c_projects/tiktaktoe/src/gamelogic.c
Normal file
120
c_projects/tiktaktoe/src/gamelogic.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "gamelogic.h"
|
||||||
|
|
||||||
|
|
||||||
|
static enum turn currturn;
|
||||||
|
// point tracker. make any of these = N and win
|
||||||
|
static int8_t pts[ROWS+COLS+DIAGS];
|
||||||
|
static int round_counter;
|
||||||
|
static position_t cpos;
|
||||||
|
static squarestate boardstate[ROWS * COLS];
|
||||||
|
|
||||||
|
|
||||||
|
void print_boardstate(){
|
||||||
|
for( int y = 0; y < ROWS; y++ ){
|
||||||
|
for( int x = 0; x < COLS; x++ ){
|
||||||
|
printf("|%c|",
|
||||||
|
(boardstate[COLS*y + x] == X) ? 'X' :
|
||||||
|
(boardstate[COLS*y + x] == O) ? 'O' : '_');
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_gamestate(){
|
||||||
|
// init cursor pos to 0,0
|
||||||
|
cpos = (position_t){0,0};
|
||||||
|
currturn = X_TURN;
|
||||||
|
round_counter = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < TOTAL_SQUARES; i++ ){
|
||||||
|
boardstate[i] = OPEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_game_over(){
|
||||||
|
for (int i = 0; i < ROWS + COLS + DIAGS; i++){
|
||||||
|
if ( pts[i] == N ){
|
||||||
|
printf("X won\n");
|
||||||
|
return 1;
|
||||||
|
}else if ( pts[i] == -N ){
|
||||||
|
printf("O won\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (round_counter == TOTAL_SQUARES){
|
||||||
|
printf("Stalemate\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_point(){
|
||||||
|
int val = (currturn == X_TURN) ? 1 : -1;
|
||||||
|
pts[cpos.row] += val;
|
||||||
|
pts[ROWS + cpos.col] += val;
|
||||||
|
if ( cpos.row == cpos.col){
|
||||||
|
pts[ROWS + COLS + 0] += val;
|
||||||
|
}
|
||||||
|
if( (cpos.row + cpos.col) == (N - 1)){
|
||||||
|
pts[ROWS + COLS + 1] += val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_boardstate(){
|
||||||
|
int idx = COLS * cpos.row + cpos.col;
|
||||||
|
if(boardstate[idx] == OPEN){
|
||||||
|
if(currturn == X_TURN){
|
||||||
|
boardstate[idx] = X;
|
||||||
|
}
|
||||||
|
else if(currturn == O_TURN){
|
||||||
|
boardstate[idx] = O;
|
||||||
|
}
|
||||||
|
add_point();
|
||||||
|
round_counter++;
|
||||||
|
currturn = !currturn;
|
||||||
|
}
|
||||||
|
print_boardstate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_gamestate(char input){
|
||||||
|
|
||||||
|
switch(input){
|
||||||
|
case('w'):
|
||||||
|
if(cpos.row > 0){
|
||||||
|
cpos.row--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case('s'):
|
||||||
|
if(cpos.row < (ROWS - 1)){
|
||||||
|
cpos.row++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case('a'):
|
||||||
|
if(cpos.col > 0){
|
||||||
|
cpos.col--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case('d'):
|
||||||
|
if(cpos.col < (COLS - 1)){
|
||||||
|
cpos.col++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case('e'):
|
||||||
|
update_boardstate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("cpos.row = %d, cpos.col = %d,", cpos.row, cpos.col);
|
||||||
|
printf(" Turn: %d\n", currturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_loop(){
|
||||||
|
int input = 0;
|
||||||
|
while(1){
|
||||||
|
while((input = getchar()) == '\n');
|
||||||
|
update_gamestate(input);
|
||||||
|
if (is_game_over()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
c_projects/tiktaktoe/src/main.c
Normal file
8
c_projects/tiktaktoe/src/main.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "gamelogic.h"
|
||||||
|
#include "tiktaktoe.h"
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
init_gamestate();
|
||||||
|
main_loop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
c_projects/tiktaktoe/src/tiktaktoe.c
Normal file
1
c_projects/tiktaktoe/src/tiktaktoe.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "tiktaktoe.h"
|
||||||
203
c_projects/tiktaktoe/tags
Normal file
203
c_projects/tiktaktoe/tags
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/
|
||||||
|
!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/
|
||||||
|
!_TAG_EXTRA_DESCRIPTION inputFile /Include an entry for the base file name of every input file/
|
||||||
|
!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/
|
||||||
|
!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/
|
||||||
|
!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/
|
||||||
|
!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/
|
||||||
|
!_TAG_FIELD_DESCRIPTION input /input file/
|
||||||
|
!_TAG_FIELD_DESCRIPTION name /tag name/
|
||||||
|
!_TAG_FIELD_DESCRIPTION pattern /pattern/
|
||||||
|
!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/
|
||||||
|
!_TAG_FIELD_DESCRIPTION!C++ name /aliased names/
|
||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C L,label /goto labels/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C d,macro /macro definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C e,enumerator /enumerators (values inside an enumeration)/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C f,function /function definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C g,enum /enumeration names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C h,header /included header files/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C l,local /local variables/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C m,member /struct, and union members/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C p,prototype /function prototypes/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C s,struct /structure names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C t,typedef /typedefs/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C u,union /union names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C v,variable /variable definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ L,label /goto labels/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ M,module /modules/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ P,partition /partitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ c,class /classes/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ d,macro /macro definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ e,enumerator /enumerators (values inside an enumeration)/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ f,function /function definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ g,enum /enumeration names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ h,header /included header files/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ l,local /local variables/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ m,member /class, struct, and union members/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ n,namespace /namespaces/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ p,prototype /function prototypes/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ s,struct /structure names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ t,typedef /typedefs/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ u,union /union names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!C++ v,variable /variable definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D M,module /modules/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D T,template /templates/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D V,version /version statements/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D X,mixin /mixins/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D a,alias /aliases/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D c,class /classes/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D e,enumerator /enumerators (values inside an enumeration)/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D f,function /function definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D g,enum /enumeration names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D i,interface /interfaces/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D m,member /class, struct, and union members/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D n,namespace /namespaces/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D s,struct /structure names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D u,union /union names/
|
||||||
|
!_TAG_KIND_DESCRIPTION!D v,variable /variable definitions/
|
||||||
|
!_TAG_KIND_DESCRIPTION!Make I,makefile /makefiles/
|
||||||
|
!_TAG_KIND_DESCRIPTION!Make m,macro /macros/
|
||||||
|
!_TAG_KIND_DESCRIPTION!Make t,target /targets/
|
||||||
|
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
||||||
|
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
||||||
|
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
||||||
|
!_TAG_OUTPUT_VERSION 1.1 /current.age/
|
||||||
|
!_TAG_PARSER_VERSION!C 1.1 /current.age/
|
||||||
|
!_TAG_PARSER_VERSION!C++ 2.2 /current.age/
|
||||||
|
!_TAG_PARSER_VERSION!D 0.0 /current.age/
|
||||||
|
!_TAG_PARSER_VERSION!Make 1.1 /current.age/
|
||||||
|
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
||||||
|
!_TAG_PROC_CWD /home/xtro/current_projects/code/c/tiktaktoe/c_projects/tiktaktoe/ //
|
||||||
|
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
||||||
|
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
||||||
|
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 6.2.1 /v6.2.1/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C!function foreigndecl /declared in foreign languages/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C!header local /local header/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C!header system /system header/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C!macro undef /undefined/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C!struct foreigndecl /declared in foreign languages/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!header exported /exported with "exported imported ..."/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!header imported /imported with "imported ..."/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!header local /local header/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!header system /system header/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!macro undef /undefined/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!module imported /imported with "imported ..."/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!module partOwner /used for specifying a partition/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!C++!partition imported /imported with "imported ..."/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!Make!makefile included /included/
|
||||||
|
!_TAG_ROLE_DESCRIPTION!Make!makefile optional /optionally included/
|
||||||
|
$(INCLUDE_DIR) Makefile /^$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):$/;" t
|
||||||
|
$(OBJ_DIR) Makefile /^$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):$/;" t
|
||||||
|
$(OBJ_DIR)/%.o Makefile /^$(OBJ_DIR)\/%.o: $(SRC_DIR)\/%.c$/;" t
|
||||||
|
$(OBJ_DIR)/%.o Makefile /^$(OBJ_DIR)\/%.o: $(TESTS_DIR)\/%.c $(OBJ)$/;" t
|
||||||
|
$(PROJECT_NAME) Makefile /^$(PROJECT_NAME): $(MAIN:%.c=$(OBJ_DIR)\/%.o) $(OBJ) check_submods$/;" t
|
||||||
|
$(PROJECT_NAME).a Makefile /^$(PROJECT_NAME).a: $(PROJECT_OBJ) check_submods$/;" t
|
||||||
|
$(SRC_DIR) Makefile /^$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):$/;" t
|
||||||
|
$(SRC_DIR)/$(MAIN) Makefile /^$(SRC_DIR)\/$(MAIN):$/;" t
|
||||||
|
$(SUBMODULES_DIR) Makefile /^$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):$/;" t
|
||||||
|
$(SUBMODULE_SLIB) Makefile /^$(SUBMODULE_SLIB): $/;" t
|
||||||
|
$(TESTS:$(TESTS_DIR)/%.c=%) Makefile /^$(TESTS:$(TESTS_DIR)\/%.c=%): %: $(OBJ_DIR)\/%.o $(OBJ) check_submods$/;" t
|
||||||
|
$(TESTS_DIR) Makefile /^$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR):$/;" t
|
||||||
|
% Makefile /^$(TESTS:$(TESTS_DIR)\/%.c=%): %: $(OBJ_DIR)\/%.o $(OBJ) check_submods$/;" t
|
||||||
|
CC Makefile /^CC := gcc$/;" m
|
||||||
|
CFLAGS Makefile /^CFLAGS := -std=c99 -ggdb -Wall -Wextra -MMD -MP -lncurses -fsanitize=address$/;" m
|
||||||
|
DEPENDENCIES Makefile /^DEPENDENCIES := $(OBJ:%.o=%.d)$/;" m
|
||||||
|
DFLAGS Makefile /^DFLAGS := -D_DEBUG$/;" m
|
||||||
|
END tests/include/test.h /^typedef enum {START, END} header_opt;$/;" e enum:__anon431ebd300103
|
||||||
|
FAIL tests/include/test.h /^typedef enum {PASS, FAIL}rc_opt;$/;" e enum:__anon431ebd300203
|
||||||
|
FOOTERSIZE include/tiktaktoe.h /^#define FOOTERSIZE /;" d
|
||||||
|
GRIDSIZE include/tiktaktoe.h /^#define GRIDSIZE /;" d
|
||||||
|
HEADERSIZE include/tiktaktoe.h /^#define HEADERSIZE /;" d
|
||||||
|
INCLUDES Makefile /^INCLUDES := $(addprefix -I,$(INCLUDE_LIST))$/;" m
|
||||||
|
INCLUDE_DIR Makefile /^INCLUDE_DIR := include$/;" m
|
||||||
|
INCLUDE_LIST Makefile /^INCLUDE_LIST := $(foreach m,$(SUBMODULES),$(m)\/$(INCLUDE_DIR)) $(INCLUDE_DIR) $(TESTS_INCL_DIR)$/;" m
|
||||||
|
MAIN Makefile /^MAIN := main.c$/;" m
|
||||||
|
Makefile Makefile 1;" F epoch:1767240744
|
||||||
|
OBJ Makefile /^OBJ := $(SRC:$(SRC_DIR)\/%.c=$(OBJ_DIR)\/%.o)$/;" m
|
||||||
|
OBJ_DIR Makefile /^OBJ_DIR := obj$/;" m
|
||||||
|
PASS tests/include/test.h /^typedef enum {PASS, FAIL}rc_opt;$/;" e enum:__anon431ebd300203
|
||||||
|
PROJECT_NAME Makefile /^PROJECT_NAME := tiktaktoe$/;" m
|
||||||
|
PROJECT_OBJ Makefile /^PROJECT_OBJ := $(OBJ_DIR)\/$(PROJECT_NAME).o$/;" m
|
||||||
|
SRC Makefile /^SRC := $(filter-out $(SRC_DIR)\/$(MAIN), $(wildcard $(SRC_DIR)\/*.c))$/;" m
|
||||||
|
SRC_DIR Makefile /^SRC_DIR := src$/;" m
|
||||||
|
START tests/include/test.h /^typedef enum {START, END} header_opt;$/;" e enum:__anon431ebd300103
|
||||||
|
STATIC_LIBS Makefile /^STATIC_LIBS = $(shell find .\/ -name "*.a")$/;" m
|
||||||
|
SUBBARE Makefile /^SUBBARE := $(SUBMODULES:$(SUBMODULES_DIR)\/%=%)$/;" m
|
||||||
|
SUBMODULES Makefile /^SUBMODULES := $(wildcard $(SUBMODULES_DIR)\/*)$/;" m
|
||||||
|
SUBMODULES_DIR Makefile /^SUBMODULES_DIR := submodules$/;" m
|
||||||
|
SUBMODULE_SLIB Makefile /^SUBMODULE_SLIB := $(foreach m,$(SUBBARE),$(SUBMODULES_DIR)\/$(m)\/$(m).a)$/;" m
|
||||||
|
TEST tests/include/test.h /^#define TEST(/;" d
|
||||||
|
TEST tests/test.c /^TEST(fail){$/;" f
|
||||||
|
TEST tests/test.c /^TEST(segfault){$/;" f
|
||||||
|
TEST tests/test.c /^TEST(success){$/;" f
|
||||||
|
TESTS Makefile /^TESTS := $(wildcard $(TESTS_DIR)\/*.c)$/;" m
|
||||||
|
TESTS_DIR Makefile /^TESTS_DIR := tests$/;" m
|
||||||
|
TESTS_INCL_DIR Makefile /^TESTS_INCL_DIR := $(TESTS_DIR)\/include$/;" m
|
||||||
|
TIKTAKTOE_H include/tiktaktoe.h /^#define TIKTAKTOE_H$/;" d
|
||||||
|
X_GREEN tests/include/test.h /^#define X_GREEN /;" d
|
||||||
|
X_RED tests/include/test.h /^#define X_RED /;" d
|
||||||
|
X_RST tests/include/test.h /^#define X_RST /;" d
|
||||||
|
X_YELLOW tests/include/test.h /^#define X_YELLOW /;" d
|
||||||
|
__anon431ebd300103 tests/include/test.h /^typedef enum {START, END} header_opt;$/;" g
|
||||||
|
__anon431ebd300203 tests/include/test.h /^typedef enum {PASS, FAIL}rc_opt;$/;" g
|
||||||
|
all Makefile /^all: $(PROJECT_NAME)$/;" t
|
||||||
|
bmaxx include/tiktaktoe.h /^ int bmaxx;$/;" m struct:w_data_t typeref:typename:int
|
||||||
|
bmaxx src/tiktaktoe.c /^ int bmaxx = 0;$/;" l function:draw_board typeref:typename:int file:
|
||||||
|
bmaxy include/tiktaktoe.h /^ int bmaxy;$/;" m struct:w_data_t typeref:typename:int
|
||||||
|
bmaxy src/tiktaktoe.c /^ int bmaxy = 0;$/;" l function:draw_board typeref:typename:int file:
|
||||||
|
board src/tiktaktoe.c /^ w_data_t* board = NULL;$/;" l function:start_tiktaktoe typeref:typename:w_data_t * file:
|
||||||
|
board_size src/tiktaktoe.c /^ const int board_size = LINES - HEADERSIZE - FOOTERSIZE;$/;" l function:init_windows typeref:typename:const int file:
|
||||||
|
buffer src/tiktaktoe.c /^ int buffer = 10;$/;" l function:draw_board typeref:typename:int file:
|
||||||
|
check_submods Makefile /^check_submods: $(SUBMODULE_SLIB)$/;" t
|
||||||
|
clean Makefile /^clean:$/;" t
|
||||||
|
cpid tests/include/test.h /^ pid_t cpid = fork();$/;" l function:run_child typeref:typename:pid_t file:
|
||||||
|
dirs Makefile /^dirs: $(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR) $(SRC_DIR)\/$(MAIN)$/;" t
|
||||||
|
draw_board include/tiktaktoe.h /^void draw_board(w_data_t *board, w_data_t *header, w_data_t *footer);$/;" p typeref:typename:void
|
||||||
|
draw_board src/tiktaktoe.c /^void draw_board(w_data_t *board, w_data_t *header, w_data_t *footer){$/;" f typeref:typename:void
|
||||||
|
errors tests/include/test.h /^ int errors = 0;$/;" l function:run_tests typeref:typename:int file:
|
||||||
|
footer src/tiktaktoe.c /^ w_data_t* footer = NULL;$/;" l function:start_tiktaktoe typeref:typename:w_data_t * file:
|
||||||
|
head tests/include/test.h /^static testnode* head = NULL;$/;" v typeref:typename:testnode *
|
||||||
|
header src/tiktaktoe.c /^ w_data_t* header = NULL;$/;" l function:start_tiktaktoe typeref:typename:w_data_t * file:
|
||||||
|
header_opt tests/include/test.h /^typedef enum {START, END} header_opt;$/;" t typeref:enum:__anon431ebd300103
|
||||||
|
help Makefile /^help:$/;" t
|
||||||
|
hline_pos src/tiktaktoe.c /^ int hline_pos = 0;$/;" l function:draw_board typeref:typename:int file:
|
||||||
|
i tests/test.c /^ int i = 1;$/;" l function:TEST typeref:typename:int file:
|
||||||
|
init_windows src/tiktaktoe.c /^void init_windows(w_data_t *board, w_data_t *header, w_data_t *footer){$/;" f typeref:typename:void
|
||||||
|
main src/main.c /^int main(){$/;" f typeref:typename:int
|
||||||
|
main tests/test.c /^int main(void){$/;" f typeref:typename:int
|
||||||
|
main.c src/main.c 1;" F epoch:1766803538
|
||||||
|
main.d obj/main.d 1;" F epoch:1766865434
|
||||||
|
name tests/include/test.h /^ char* name;$/;" m struct:testnode typeref:typename:char *
|
||||||
|
next tests/include/test.h /^ struct testnode* next;$/;" m struct:testnode typeref:struct:testnode *
|
||||||
|
op tests/include/test.h /^ int (*op)(void);$/;" m struct:testnode typeref:typename:int (*)(void)
|
||||||
|
part src/tiktaktoe.c /^const char part = '-';$/;" v typeref:typename:const char
|
||||||
|
ppass_fail tests/include/test.h /^static void ppass_fail(rc_opt rc){$/;" f typeref:typename:void
|
||||||
|
presult tests/include/test.h /^static int presult(int status){$/;" f typeref:typename:int
|
||||||
|
ptest_headers tests/include/test.h /^static void ptest_headers(header_opt option){$/;" f typeref:typename:void
|
||||||
|
ptr tests/include/test.h /^static testnode* ptr = NULL;$/;" v typeref:typename:testnode *
|
||||||
|
rc tests/include/test.h /^ int rc = WEXITSTATUS(status);$/;" l function:presult typeref:typename:int file:
|
||||||
|
rc tests/include/test.h /^ int rc = ptr->op();$/;" l function:run_child typeref:typename:int file:
|
||||||
|
rc_opt tests/include/test.h /^typedef enum {PASS, FAIL}rc_opt;$/;" t typeref:enum:__anon431ebd300203
|
||||||
|
run_child tests/include/test.h /^static int run_child(){$/;" f typeref:typename:int
|
||||||
|
run_tests tests/include/test.h /^static int run_tests(){$/;" f typeref:typename:int
|
||||||
|
start_tiktaktoe include/tiktaktoe.h /^int start_tiktaktoe(void);$/;" p typeref:typename:int
|
||||||
|
start_tiktaktoe src/tiktaktoe.c /^int start_tiktaktoe(void){$/;" f typeref:typename:int
|
||||||
|
status tests/include/test.h /^ int status;$/;" l function:run_child typeref:typename:int file:
|
||||||
|
tail tests/include/test.h /^static testnode* tail = NULL;$/;" v typeref:typename:testnode *
|
||||||
|
test.c tests/test.c 1;" F epoch:1766557221
|
||||||
|
test.h tests/include/test.h 1;" F epoch:1766556714
|
||||||
|
testnode tests/include/test.h /^typedef struct testnode{$/;" s
|
||||||
|
testnode tests/include/test.h /^}testnode;$/;" t typeref:struct:testnode
|
||||||
|
tiktaktoe.c src/tiktaktoe.c 1;" F epoch:1767390945
|
||||||
|
tiktaktoe.d obj/tiktaktoe.d 1;" F epoch:1767390946
|
||||||
|
tiktaktoe.h include/tiktaktoe.h 1;" F epoch:1767390908
|
||||||
|
total_tests tests/include/test.h /^ int total_tests = 0;$/;" l function:run_tests typeref:typename:int file:
|
||||||
|
vline_pos src/tiktaktoe.c /^ int vline_pos = 0;$/;" l function:draw_board typeref:typename:int file:
|
||||||
|
w_data_t include/tiktaktoe.h /^typedef struct w_data_t{$/;" s
|
||||||
|
w_data_t include/tiktaktoe.h /^}w_data_t;$/;" t typeref:struct:w_data_t
|
||||||
|
w_ptr include/tiktaktoe.h /^ WINDOW *w_ptr;$/;" m struct:w_data_t typeref:typename:WINDOW *
|
||||||
|
x tests/test.c /^ int* x = NULL;$/;" l function:TEST typeref:typename:int * file:
|
||||||
|
y tests/test.c /^ int y = *x;$/;" l function:TEST typeref:typename:int file:
|
||||||
162
c_projects/tiktaktoe/tests/include/test.h
Normal file
162
c_projects/tiktaktoe/tests/include/test.h
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
// printf Formating
|
||||||
|
#define X_RED "\x1B[31m"
|
||||||
|
#define X_GREEN "\x1B[32m"
|
||||||
|
#define X_YELLOW "\x1B[33m"
|
||||||
|
#define X_RST "\x1B[0m"
|
||||||
|
|
||||||
|
|
||||||
|
// TEST FRAMEWORK STRUCT
|
||||||
|
typedef struct testnode{
|
||||||
|
char* name;
|
||||||
|
int (*op)(void);
|
||||||
|
struct testnode* next;
|
||||||
|
}testnode;
|
||||||
|
|
||||||
|
// LL nodes
|
||||||
|
static testnode* head = NULL;
|
||||||
|
static testnode* tail = NULL;
|
||||||
|
static testnode* ptr = NULL;
|
||||||
|
|
||||||
|
// TEST FRAMEWORK MACRO
|
||||||
|
// create a new node and pass in the name of the test. Then make a new function
|
||||||
|
// that adds the test to the LL. __attribute__((constructor)) has the function
|
||||||
|
// run before main
|
||||||
|
#define TEST(UNIT)\
|
||||||
|
static int UNIT(void);\
|
||||||
|
static testnode UNIT##node = {#UNIT, UNIT, NULL};\
|
||||||
|
__attribute__((constructor)) \
|
||||||
|
static void add##UNIT(void){ \
|
||||||
|
if (head == NULL){\
|
||||||
|
head = &UNIT##node;\
|
||||||
|
tail = head;\
|
||||||
|
return; \
|
||||||
|
}\
|
||||||
|
ptr = tail;\
|
||||||
|
tail = &UNIT##node;\
|
||||||
|
ptr->next = tail;\
|
||||||
|
}\
|
||||||
|
static int UNIT(void)
|
||||||
|
|
||||||
|
// TEST HELPER FUNCTIONS and STRUCTS
|
||||||
|
typedef enum {START, END} header_opt;
|
||||||
|
static void ptest_headers(header_opt option){
|
||||||
|
switch (option){
|
||||||
|
case START:
|
||||||
|
printf("\n-------------------\n");
|
||||||
|
printf(" Starting Tests\n");
|
||||||
|
printf("-------------------\n");
|
||||||
|
break;
|
||||||
|
case END:
|
||||||
|
printf("-------------------\n");
|
||||||
|
printf(" ENDING TESTS\n");
|
||||||
|
printf("-------------------\n\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("error: Wrong option in ptest_headers()\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {PASS, FAIL}rc_opt;
|
||||||
|
static void ppass_fail(rc_opt rc){
|
||||||
|
switch (rc){
|
||||||
|
case PASS:
|
||||||
|
printf("%s[PASS]%s ", X_GREEN, X_RST);
|
||||||
|
printf("%s", ptr->name);
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
printf("%s[FAIL]%s ", X_RED, X_RST);
|
||||||
|
printf("%s ", ptr->name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("error: Unknown return code");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int presult(int status){
|
||||||
|
if (WIFEXITED(status)){
|
||||||
|
int rc = WEXITSTATUS(status);
|
||||||
|
if (rc == 0) {
|
||||||
|
ppass_fail(PASS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ppass_fail(FAIL);
|
||||||
|
printf("- Exit Code %s(%d)%s",
|
||||||
|
X_YELLOW, rc, X_RST);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (WIFSIGNALED(status)){
|
||||||
|
ppass_fail(FAIL);
|
||||||
|
printf("- Termination Signal %s(%d)%s",
|
||||||
|
X_YELLOW, WTERMSIG(status), X_RST);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
printf("%s[FAIL]%s ", X_RED, X_RST);
|
||||||
|
printf("%s ", ptr->name);
|
||||||
|
printf("- Unknown Error ");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_child(){
|
||||||
|
int status;
|
||||||
|
pid_t cpid = fork();
|
||||||
|
if (cpid < 0){
|
||||||
|
perror("fork");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpid == 0){
|
||||||
|
int rc = ptr->op();
|
||||||
|
_exit(rc);
|
||||||
|
}else{
|
||||||
|
if (waitpid(cpid, &status, 0) < 0){
|
||||||
|
perror("waitpid");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_tests(){
|
||||||
|
int total_tests = 0;
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
ptest_headers(START);
|
||||||
|
|
||||||
|
ptr = head;
|
||||||
|
while (ptr != NULL){
|
||||||
|
total_tests++;
|
||||||
|
|
||||||
|
|
||||||
|
if(presult(run_child())){
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("\nTests completed with %s%d PASS%s", X_GREEN, total_tests - errors, X_RST);
|
||||||
|
printf(" and %s%d FAIL%s\n", X_RED, errors, X_RST);
|
||||||
|
|
||||||
|
ptest_headers(END);
|
||||||
|
|
||||||
|
if (errors > 0){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
28
c_projects/tiktaktoe/tests/test.c
Normal file
28
c_projects/tiktaktoe/tests/test.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// INCLUDE PROJECT HEADERS
|
||||||
|
|
||||||
|
|
||||||
|
// DEFINE TESTS
|
||||||
|
TEST(success){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(fail){
|
||||||
|
int i = 1;
|
||||||
|
assert(i == 0);
|
||||||
|
printf("after assert\n");
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(segfault){
|
||||||
|
int* x = NULL;
|
||||||
|
int y = *x;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// END OF TEST DEFINITIONS
|
||||||
|
|
||||||
|
int main(void){
|
||||||
|
return run_tests();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user