From 242cae72b68930bb2a4ee3be166cbeb7e1fac51f Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Fri, 28 Feb 2025 10:07:54 +0100 Subject: [PATCH] initial commit --- .gitignore | 8 ++ debug.c | 5 ++ debug.h | 21 +++++ display.c | 164 ++++++++++++++++++++++++++++++++++++ display.h | 15 ++++ function.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++ function.h | 44 ++++++++++ makefile | 193 +++++++++++++++++++++++++++++++++++++++++++ sudoku.c | 142 ++++++++++++++++++++++++++++++++ type.h | 12 +++ 10 files changed, 842 insertions(+) create mode 100644 .gitignore create mode 100644 debug.c create mode 100644 debug.h create mode 100644 display.c create mode 100644 display.h create mode 100644 function.c create mode 100644 function.h create mode 100644 makefile create mode 100644 sudoku.c create mode 100644 type.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68f55a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.d +*.exe +*.gcda +*.gcno +*.gcov +*.ld +*.o +*.log diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..b9eba44 --- /dev/null +++ b/debug.c @@ -0,0 +1,5 @@ +#include "debug.h" + +int verbose = 0; + +/* vim: set ts=4 sw=4 et: */ diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..32dc0ca --- /dev/null +++ b/debug.h @@ -0,0 +1,21 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +/* constants */ + +#define DEBUG 3 +#define INFO 2 +#define WARNING 1 +#define ERROR 0 + +/* macros */ + +#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) + +/* gobal variables */ + +extern int verbose; + +#endif /* __DEBUG_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.c b/display.c new file mode 100644 index 0000000..39c94b5 --- /dev/null +++ b/display.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include + +#include "debug.h" +#include "function.h" + +#include "display.h" + +typedef enum { + white = 1, + red, + green, + blue, + cyan, + magenta, + yellow, + ired, + igreen, + iblue, + icyan, + imagenta, + iyellow, + bred, + bgreen, + bblue, + bcyan, + bmagenta, + byellow, + black, + wred, + wgreen, + wblue, + wcyan, + wmagenta, + wyellow, +} color_t; + +void set_color (color_t color) +{ + static int init = 1; + + if (init) { + init_pair (white, COLOR_WHITE, COLOR_BLACK); + init_pair (red, COLOR_RED, COLOR_BLACK); + init_pair (green, COLOR_GREEN, COLOR_BLACK); + init_pair (blue, COLOR_BLUE, COLOR_BLACK); + init_pair (magenta, COLOR_MAGENTA, COLOR_BLACK); + init_pair (yellow, COLOR_YELLOW, COLOR_BLACK); + init_pair (cyan, COLOR_CYAN, COLOR_BLACK); + init_pair (ired, COLOR_RED, COLOR_WHITE); + init_pair (igreen, COLOR_GREEN, COLOR_WHITE); + init_pair (iblue, COLOR_BLUE, COLOR_WHITE); + init_pair (imagenta, COLOR_MAGENTA, COLOR_WHITE); + init_pair (iyellow, COLOR_YELLOW, COLOR_WHITE); + init_pair (icyan, COLOR_CYAN, COLOR_WHITE); + init_pair (bred, COLOR_BLACK, COLOR_RED); + init_pair (bgreen, COLOR_BLACK, COLOR_GREEN); + init_pair (bblue, COLOR_BLACK, COLOR_BLUE); + init_pair (bmagenta, COLOR_BLACK, COLOR_MAGENTA); + init_pair (byellow, COLOR_BLACK, COLOR_YELLOW); + init_pair (bcyan, COLOR_BLACK, COLOR_CYAN); + init_pair (black, COLOR_BLACK, COLOR_WHITE); + init_pair (wred, COLOR_WHITE, COLOR_RED); + init_pair (wgreen, COLOR_WHITE, COLOR_GREEN); + init_pair (wblue, COLOR_WHITE, COLOR_BLUE); + init_pair (wcyan, COLOR_WHITE, COLOR_CYAN); + init_pair (wmagenta, COLOR_WHITE, COLOR_MAGENTA); + init_pair (wyellow, COLOR_WHITE, COLOR_YELLOW); + init = 0; + } + + attrset (COLOR_PAIR(color)); +} + +int _helpwindow (char *msg, int xoffset, int yoffset, int length) +{ + int i = 0; + int j = 0; + while ((msg) && (*msg != '\0')) { + if (*msg == '\n') { + if (i <= length) { + mvaddch (yoffset + j, xoffset + i, ' '); + i++; + continue; + } + i = 0; + j++; + } + if (*msg != '\n') { + mvaddch (yoffset + j, xoffset + i, *msg); + i++; + } + msg++; + } + return j; +} + +void _displaytitle (char *title, int xoffset, int yoffset, int length) +{ + int i; + for (i = 0; i < length; i++) { + mvaddch (yoffset, xoffset + i, ' '); + mvaddch (yoffset + 1, xoffset + i, ACS_HLINE); + } + for (i = 0; title[i] != '\0'; i++) { + mvaddch (yoffset, xoffset + i + (length - strlen (title)) / 2, title[i]); + } +} + +void _dobound (int xsize, int ysize, int xoffset, int yoffset) +{ + int i, j; + + for (i = 0; i < xsize; i++) { + mvaddch (yoffset - 1, xoffset + i, ACS_HLINE); + mvaddch (yoffset + ysize, xoffset + i, ACS_HLINE); + } + for (j = 0; j < ysize; j++) { + mvaddch (yoffset + j, xoffset - 1, ACS_VLINE); + mvaddch (yoffset + j, xoffset + xsize, ACS_VLINE); + } + mvaddch (yoffset - 1, xoffset - 1, ACS_ULCORNER); + mvaddch (yoffset + ysize, xoffset - 1, ACS_LLCORNER); + mvaddch (yoffset - 1, xoffset + xsize, ACS_URCORNER); + mvaddch (yoffset + ysize, xoffset + xsize, ACS_LRCORNER); +} + +int helpwindow (char *msg, int xoffset, int yoffset) +{ + char *title = "Help message"; + int length = strmaxlen (msg, '\n'); + if (length < (int)strlen (title)) { + length = strlen (title); + } + set_color (byellow); + _displaytitle (title, xoffset, yoffset, length); + int j = 2; + j += _helpwindow (msg, xoffset, yoffset + j, length); + _dobound (length, j, xoffset, yoffset); + set_color (white); + + while (getch () == ERR) { + usleep (200 * 1000); + } + + return j; +} + +void displayboard (board_t *board, int xoffset, int yoffset) +{ + int i, j; + + _dobound (board->nb + 2, board->nb + 2, xoffset - 1, yoffset - 1); + for (i = 0; i < board->nb; i++) { + for (j= 0; j < board->nb; j++) { + mvaddch (j + yoffset, i + xoffset, getvalue (board, i, j)); + } + } +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.h b/display.h new file mode 100644 index 0000000..031fa04 --- /dev/null +++ b/display.h @@ -0,0 +1,15 @@ +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include "type.h" + +int helpwindow (char *msg, int xoffset, int yoffset); + +void displayboard (board_t *board, int xoffset, int yoffset); + +#define KEY_DELETE 0x014a +#define KEY_ESC 0x1b + +#endif /* __DISPLAY_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.c b/function.c new file mode 100644 index 0000000..70b2ecf --- /dev/null +++ b/function.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "type.h" + +#include "function.h" + +int strmaxlen (char *str, char ch) +{ + int len = 0; + char *end = NULL; + while ((end = strchr (str, ch)) != NULL) { + int l = (int)(end - str); + if (l > len) { + len = l; + } + str = end + 1; + } + return len; +} + +board_t *initboard (int length) +{ + board_t *board = (board_t *) malloc (sizeof (board_t)); + CHECKALLOC (board); + board->length = length; + int nb = board->nb = length * length; + board->tab = (char *) calloc (1, nb * nb + 1); + CHECKALLOC (board->tab); + memset (board->tab, ' ', nb * nb); + return board; +} + +char _itoh (int x) +{ + char h = '0'; + if ((x > 0) && (x <= 10 + 'Z' - 'A')) { + h = x + ((x > 9) ? 'A' - 10 : '0'); + } + return h; +} + +board_t *initplay (board_t *board) +{ + int i, j, k; + + for (i = 0; i < board->nb; i++) { + for (j = 0; j < board->nb; j++) { + int draw = 1; + while (draw) { + + char tile = _itoh (1 + (rand () / board->nb) / (((RAND_MAX / board->nb) + board->nb) / board->nb)); + VERBOSE (DEBUG, printf ("tile drawn '%c'\n", tile)); + draw = 0; + + /* check line */ + VERBOSE (DEBUG, printf ("check line\n")); + for (k = 0; (k < j) && (!draw); k++) { + if (getvalue (board, i, k) == tile) { + draw = 1; + } + } + + /* check column */ + VERBOSE (DEBUG, printf ("check column\n")); + for (k = 0; (k < i) && (!draw); k++) { + if (getvalue (board, k, j) == tile) { + draw = 1; + } + } + + /* check box */ + VERBOSE (DEBUG, printf ("check box\n")); + for (k = 0; (k < board->nb) && (!draw); k++) { + int I = board->length * (i / board->length); + int J = board->length * (j / board->length); + if (getvalue (board, I + k / board->length, J + k % board->length) == tile) { + draw = 1; + } + } + + if (!draw) { + VERBOSE (INFO, printf ("(%d, %d) = %c\n", i, j, tile)); + *getcell (board, i, j) = tile; + } + } + } + } + + return board; +} + +void freeboard (board_t *board) +{ + if (board) { + free (board->tab); + } + free (board); +} + +int _makecomments (char *buffer, board_t *board) +{ + int i, j, l = 0; + for (j = 0; j < board->nb; j++) { + l += sprintf (buffer + l, "rem: \""); + for (i = 0; i < board->nb; i++) { + l += sprintf (buffer + l, "%c", getvalue (board, i, j)); + } + l += sprintf (buffer + l, "\"\n"); + } + return l; +} + +char *saveboard (board_t *board) +{ + int size = 2 * (8 + 3) + 8 + board->nb * board->nb + 1; + + char *buffer = (char *) calloc (size, 1); + CHECKALLOC (buffer); + + int l = sprintf (buffer, "length: %d\n", board->length); + l += sprintf (buffer + l, "nb: %d\n", board->nb); + + VERBOSE (INFO, _makecomments (buffer + l, board)); + + return buffer; +} + +int writedata (char *filename, char *data) +{ + int ret = 0; + + FILE *fd = fopen (filename, "w"); + if (fd) { + size_t n = fwrite (data, strlen (data), 1, fd); + fclose (fd); + ret = (n == strlen (data)); + } else { + VERBOSE (WARNING, printf ("can't write file (%s)\n", filename)); + } + + return ret; +} + +char *readdata (char *filename) +{ + char *buffer = NULL; + FILE *fd = fopen (filename, "r"); + if (fd) { + fseek (fd, 0, SEEK_END); + int size = ftell (fd); + buffer = (char *) calloc (size + 1, 1); + CHECKALLOC (buffer); + + fseek (fd, 0, SEEK_SET); + int nb = fread (buffer, 1, size, fd); + if (nb != size) { + VERBOSE (WARNING, printf ("can't fully read file (%s)\n", filename)); + } + fclose (fd); + } + + return buffer; +} + +char *atos (char *str) +{ + char *ret = NULL; + + if (*str == '"') { + char *ptr = ++str; + while ((*ptr != '"') && (*ptr != '\0')) { + ptr++; + } + if (*ptr == '"') { + *ptr = '\0'; + ret = str; + } + } + + return ret; +} + +board_t *loadboard (char *str) +{ + int length = 0; + int nb = 0; + char *tab = NULL; + + char *saveptr1, *saveptr2; + + char *line = strtok_r (str, "\n", &saveptr1); + while (line) { + + char *keyword = strtok_r (line, ":", &saveptr2); + + char *value = line + strlen (keyword) + 1; + while (*value == ' ') { + value++; + } + + if (strcmp (keyword, "length") == 0) { + length = atoi (value); + } else if (strcmp (keyword, "nb") == 0) { + nb = atoi (value); + } else if (strcmp (keyword, "rem") == 0) { + /* nothing to do with remark */ + } else { + VERBOSE (WARNING, printf ("unknown keyword: %s\n", keyword)); + } + + line = strtok_r (NULL, "\n", &saveptr1); + } + + board_t *board = NULL; + if ((tab) && (nb == length * length) && (strlen (tab) == (size_t)(nb * nb))) { + board = initboard (length); + memcpy (board->tab, tab, nb * nb); + } + + return board; +} + +char *getcell (board_t *board, int x, int y) +{ + return board->tab + x + board->nb * y; +} + +char getvalue (board_t *board, int x, int y) +{ + VERBOSE (DEBUG, printf ("(%d, %d) => '%c'\n", x, y, *getcell (board, x, y))); + return (x >= 0) && (x < board->nb) && (y >= 0) && (y < board->nb) ? *getcell (board, x, y) : 0; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.h b/function.h new file mode 100644 index 0000000..4d6b84d --- /dev/null +++ b/function.h @@ -0,0 +1,44 @@ +#ifndef __FUNCTION_H__ +#define __FUNCTION_H__ + +#include + +#include "type.h" + +#define CHECKALLOC(ptr) \ + do { \ + if ((ptr) == NULL) { \ + VERBOSE (ERROR, fprintf (stderr, "can't get enough memory for '%s'\n", #ptr)); \ + exit (1); \ + } \ + } while (0) + +#define max(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) + +#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) + +int strmaxlen (char *str, char ch); + +board_t *initboard (int length); + +board_t *initplay (board_t *board); + +void freeboard (board_t *board); + +char *saveboard (board_t *board); + +int writedata (char *filename, char *data); + +char *readdata (char *filename); + +char *atos (char *str); + +board_t *loadboard (char *str); + +char *getcell (board_t *board, int x, int y); + +char getvalue (board_t *board, int x, int y); + +#endif /* __FUNCTION_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/makefile b/makefile new file mode 100644 index 0000000..8abae4b --- /dev/null +++ b/makefile @@ -0,0 +1,193 @@ +# Default flags + +CC = gcc + +#INCLUDES = -I../debug -D__MEMORY_ALLOCATION__ +INCLUDES = +OFLAGS = -O4 -Os +#OFLAGS = -O4 -ffast-math -finline-functions +#OFLAGS = -O4 -finline-functions +#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow +#OFLAGS += -minline-all-stringops -fsingle-precision-constant +#OFLAGS += -malign-double +CFLAGS += -W -Wall -Wextra -g +#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500 +CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS) +LDFLAGS += -g $(LDOPTS) $(OPTIONS) + +LDOPT = linker +MV = mv +ifneq (, $(findstring linux, $(MAKE_HOST))) +# Linux +else ifneq (, $(findstring mingw, $(MAKE_HOST))) +# Windows MinGw +CFLAGS += -DWIN32 +#LDLIBS += -lws2_32 +LDOPT = winlnk +else ifneq (, $(findstring cygwin, $(MAKE_HOST))) +CFLAGS += -DWIN32 +# Windows CygWin +LDOPT = winlnk +else ifneq (, $(findstring msdos, $(MAKE_HOST))) +# MSDOS +LDOPT = doslnk +MV = move +endif + +# Targets + +ALLEXE = +ALLEXE += sudoku + +SHELL = bash + +#MAKE = mingw32-make +MAKEFLAGS += -s +include $(wildcard .makefile) + +# Functions + +TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t" +PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m" +WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m" +FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m" + +MKDIR = mkdir -p $(1) && chmod a+rx,go-w $(1) + +INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2) + +VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; } + +GETCOMMENTS = awk '/\/\*\s*$(1):/,/\*\// { sub(/.*\/\*\s*$(1):/, ""); sub (/\s*\*\/.*/, ""); print } /\/\/\s*$(1):/ {sub (/.*\/\/\s*$(1):/, ""); print }' $(2) +#GETCOMMENTS = perl -- getcomments.pl -p='$(1):\s' -f='%' $(2) + +## Generic rules + +all: depends + $(MAKE) $(ALLEXE:%=%.exe) + +count: + wc $(wildcard *.c *.h) $(MAKEFILE_LIST) + +clean: + $(call TITLE, "Cleaning") + touch clean + rm -f clean $(wildcard *.d *.ld *.log *.o *.test *~ .exec_* gmon.out _) + $(call PASS, SUCCESS) + +depends: $(patsubst %.c, %.d, $(wildcard *.c)) $(patsubst %, %.ld, $(ALLEXE)) + +gcovs: + $(MAKE) $(addprefix gcov_,$(ALLEXE)) + +gprofs: + $(MAKE) $(addprefix gprof_,$(ALLEXE)) + +purge: clean + $(call TITLE, "Purging") + touch purge + rm -f purge $(ALLEXE:%=%.exe) + $(call PASS, SUCCESS) + +valgrinds: + $(MAKE) all + $(MAKE) $(addprefix valgrind_,$(ALLEXE)) + +wipe: purge + $(call TITLE, "Wiping") + touch wipe + rm -f wipe $(wildcard *.gcda *.gcno *.gcov *.glog) + $(call PASS, SUCCESS) + +tests: + -rm -f $(ALLEXE) + $(MAKE) all + $(MAKE) $(addprefix test_,$(ALLEXE)) + +## Main rules + +include $(wildcard *.d) +include $(wildcard *.ld) + +gcov_%: + $(MAKE) purge + $(MAKE) depends + OPTIONS="-coverage -O0" $(MAKE) ${@:gcov_%=%}.exe + $(MAKE) test_$(@:gcov_%=%) + gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g' $(@:gcov_%=%.ld)` + touch gcov + rm -f gcov $(wildcard *.gcda *.gcno) + $(MAKE) purge + grep '^ *#####' *.c.gcov || true + +gprof_%: + $(MAKE) purge + $(MAKE) depends + OPTIONS="-pg" $(MAKE) ${@:gprof_%=%}.exe + $(MAKE) ${@:gprof_%=%}.test + IFS=$$'\n'; id=1; \ + for test in `cat ${@:gprof_%=%}.test | sed 's,${@:gprof_%=%}.exe,./${@:gprof_%=%}.exe,g'`; do \ + log=${@:gprof_%=%}.prof-$$id.glog; \ + $(call TITLE, test: $$test); \ + echo $$test > $$log; \ + eval $$test >> $$log; \ + [ $$? -eq 0 ] \ + && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || echo -e "\033[1;31mFAILED\033[0;0m"; \ + [ -f gmon.out ] && { gprof ${@:gprof_%=%}.exe gmon.out >> $$log; rm gmon.out; }; \ + let id++; \ + done; + $(MAKE) purge + +%.test: %.c + $(call TITLE, "Building $@") + $(call GETCOMMENTS,test, $<) > $@ + $(call PASS, SUCCESS) + -rm -f _ + +test_%: %.test %.exe + IFS=$$'\n'; RC=0; \ + for test in `cat $< | sed 's,${<:.test=.exe},$(VALGRIND) ./${<:.test=.exe},g'`; do \ + echo "=== $$test ==="; \ + eval $$test; \ + [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \ + test "$$RC" = 1 -a "$(STOP)" = 1 && break; \ + done; \ + test "$$RC" -ne 1 + +valgrind_%: %.exe + VALGRIND="valgrind -v --leak-check=full --log-fd=3"; \ + export VALGRIND; \ + $(MAKE) $(@:valgrind_%=test_%) 3>$@.log + +%.d: %.c + $(call TITLE, "Building $@") + $(CC) $(INCLUDES) -MM $< -o $@~ + echo ${<:.c=.o}: $(shell $(call GETCOMMENTS,depends, $<)) >> $@~ + $(MV) $@~ $@ + $(call PASS, SUCCESS) + +%.ld: %.c + $(call TITLE, "Building $@") + echo ${<:.c=.exe}: $(shell $(call GETCOMMENTS,$(LDOPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@ + $(call PASS, SUCCESS) + +%.o: %.c + $(call TITLE, "Building $@") + $(CC) $(CFLAGS) $(INCLUDES) $(shell $(call GETCOMMENTS,cflags, $<)) -c $< -o $@ + $(call PASS, SUCCESS) + + +%.exe: %.o %.d + $(call TITLE, "Building $@") + $(CC) $(LDFLAGS) $< $(shell $(call GETCOMMENTS,$(LDOPT), ${<:.o=.c})) $(LDLIBS) -o $@ + $(call PASS, SUCCESS) + +## Phony + +.PHONY: all clean count depends gcovs purge tests + +## Precious + +.PRECIOUS: %.d %.o diff --git a/sudoku.c b/sudoku.c new file mode 100644 index 0000000..3068bb6 --- /dev/null +++ b/sudoku.c @@ -0,0 +1,142 @@ +/* depend: */ +/* cflags: */ +/* linker: debug.o display.o function.o -lcurses */ +/* doslnk: debug.o display.o function.o -lpdc~1 */ +/* winlnk: debug.o display.o function.o -lpdcurses */ + +#include +#include +#include +#include + +#include "debug.h" +#include "display.h" +#include "function.h" +#include "type.h" + +/* global constants */ + +/* static variables */ +char *progname = NULL; +char *version = "0.1"; + +int length = 3; +int xoffset = 1; +int yoffset = 1; + +char *help = + " Move up\n" + " Move left\n" + " Move down\n" + " Move right\n" + " Quit\n" + ; + +int usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s [-h] [-l length] [-v level]\n", progname); + fprintf (fd, " -h: help message\n"); + fprintf (fd, " -l: box length (%d)\n", length); + fprintf (fd, " -v: verbose level (%d)\n", verbose); + fprintf (fd, "%s version %s\n", progname, version); + + return ret; +} + +/* main function */ +int main (int argc, char *argv[]) +{ + + /* get basename */ + char *pt = progname = argv[0]; + while (*pt) { + if ((*pt == '/') || (*pt == '\\')) { + progname = pt + 1; + } + pt++; + } + + /* process argument */ + while (argc-- > 1) { + char *arg = *(++argv); + if (arg[0] != '-') { + VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg)); + return usage (1); + } + char c = arg[1]; + switch (c) { + case 'l': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: no length specified\n", progname)); + return usage (1); + } + length = atoi (arg); + break; + case 'v': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname)); + return usage (1); + } + verbose = atoi (arg); + break; + case 'h': + default: + return usage (c != 'h'); + } + } + + /* init board */ + board_t *board = initboard (length); + initplay (board); + + /* init curses */ + initscr (); + noecho (); + cbreak (); + nonl (); + keypad (stdscr, TRUE); + curs_set (0); + + /* event loop */ + int stop = 0; + while (!stop) { + + displayboard (board, xoffset, yoffset); + + int ch = getch (); + switch (ch) { + case KEY_UP: + case 'i': + break; + case KEY_LEFT: + case 'j': + break; + case KEY_DOWN: + case 'k': + break; + case KEY_RIGHT: + case 'l': + break; + case 'q': + stop = 1; + break; + } + } + + endwin (); + + freeboard (board); + + return 0; +} + +/* test: sudoku.exe -h | grep usage */ +/* test: sudoku.exe -l 2>&1 | grep length */ +/* test: sudoku.exe -v 2>&1 | grep missing */ +/* test: sudoku.exe _ 2>&1 | grep invalid */ + +/* test: { sleep 10; echo q; } | sudoku.exe */ + diff --git a/type.h b/type.h new file mode 100644 index 0000000..f7731ae --- /dev/null +++ b/type.h @@ -0,0 +1,12 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +typedef struct { + int length; + int nb; + char *tab; +} board_t; + +#endif /* __TYPE_H__ */ + +/* vim: set ts=4 sw=4 et: */ -- 2.30.2