From 0809dcd7725e2c277ea55b20cac728fd6d7e4dfa Mon Sep 17 00:00:00 2001 From: Laurent MAZET Date: Fri, 11 Oct 2024 17:33:50 +0200 Subject: [PATCH 1/1] initial commit --- a-orig.pac | 31 +++++++ a.pac | 3 + block.c | 187 +++++++++++++++++++++++++++++++++++++++ block.h | 45 ++++++++++ color.c | 121 +++++++++++++++++++++++++ color.h | 39 +++++++++ debug.c | 5 ++ debug.h | 21 +++++ display.c | 208 +++++++++++++++++++++++++++++++++++++++++++ display.h | 19 ++++ function.c | 185 +++++++++++++++++++++++++++++++++++++++ function.h | 44 ++++++++++ makefile | 190 ++++++++++++++++++++++++++++++++++++++++ pacman.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++ type.h | 14 +++ 15 files changed, 1364 insertions(+) create mode 100644 a-orig.pac create mode 100644 a.pac create mode 100644 block.c create mode 100644 block.h create mode 100644 color.c create mode 100644 color.h 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 pacman.c create mode 100644 type.h diff --git a/a-orig.pac b/a-orig.pac new file mode 100644 index 0000000..43e1eed --- /dev/null +++ b/a-orig.pac @@ -0,0 +1,31 @@ +width: 28 +height: 29 +tab: "F------------TT------------7" + "| || |" + "| F--7 F---7 || F---7 F--7 |" + "| | | | | || | | | | |" + "| L--J L---J LJ L---J L--J |" + "| |" + "| F--7 F7 F------7 F7 F--7 |" + "| L--J || L--7F--J || L--J |" + "| || || || |" + "L----7 |L--7 || F--J| F----J" + " | |F--J LJ L--7| | " + " | || || | " + " | || F------7 || | " + "-----J LJ | | LJ L-----" + " | | " + "-----7 F7 | | F7 F-----" + " | || L------J || | " + " | || || | " + " | |L--7 F7 F--J| | " + "F----J |F--J || L--7| L----7" + "| || || || |" + "| F--7 || F--JL--7 || F--7 |" + "| L--J LJ L------J LJ L--J |" + "| |" + "| F--7 F---7 F7 F---7 F--7 |" + "| | | | | || | | | | |" + "| L--J L---J || L---J L--J |" + "| || |" + "L------------##------------J" diff --git a/a.pac b/a.pac new file mode 100644 index 0000000..2f57869 --- /dev/null +++ b/a.pac @@ -0,0 +1,3 @@ +width: 28 +height: 29 +tab: "F------------TT------------7| || || F--7 F---7 || F---7 F--7 || | | | | || | | | | || L--J L---J LJ L---J L--J || || F--7 F7 F------7 F7 F--7 || L--J || L--7F--J || L--J || || || || |L----7 |L--7 || F--J| F----J | |F--J LJ L--7| | | || || | | || F------7 || | -----J LJ | | LJ L----- | | -----7 F7 | | F7 F----- | || L------J || | | || || | | |L--7 F7 F--J| | F----J |F--J || L--7| L----7| || || || || F--7 || F--JL--7 || F--7 || L--J LJ L------J LJ L--J || || F--7 F---7 F7 F---7 F--7 || | | | | || | | | | || L--J L---J || L---J L--J || || |L------------##------------J" diff --git a/block.c b/block.c new file mode 100644 index 0000000..9c9fca8 --- /dev/null +++ b/block.c @@ -0,0 +1,187 @@ +#include + +#include "block.h" + +typedef enum { + _black = 0, + _blue, + _green, + _cyan, + _red, + _magenta, + _yellow, + _white +} _color_t; + +static int _color_num (int fg, int bg) +{ + return (1 << 6) | ((7 & bg) << 3) | (7 & fg); +} +static int _color_trans (_color_t c) +{ + int color; + switch (7 & c) { + case _black: + color = COLOR_BLACK; + break; + case _blue: + color = COLOR_BLUE; + break; + case _green: + color = COLOR_GREEN; + break; + case _cyan: + color = COLOR_CYAN; + break; + case _red: + color = COLOR_RED; + break; + case _magenta: + color = COLOR_MAGENTA; + break; + case _yellow: + color = COLOR_YELLOW; + break; + case _white: + color = COLOR_WHITE; + break; + } + return color; +} + +static void _init_color_pairs () { + int fg, bg; + for (bg = 0; bg < 8; bg++) { + for (fg = 0; fg < 8; fg ++) { + init_pair (_color_num (fg, bg), _color_trans (fg), _color_trans (bg)); + } + } +} + +void mvaddcb (int y, int x, cblock_t color) +{ + int init = 1; + if (init) { + _init_color_pairs (); + init = 0; + } + + int symb = ACS_CKBOARD; + switch (color) { + case black: + case gray: + case blue: + case green: + case cyan: + case red: + case magenta: + case brown: + symb = ' '; + break; + default: + symb = ACS_CKBOARD; + } + + int num; + switch (color) { + case black: + case darkgray: + num = _color_num (_white, _black); + break; + case gray: + case white: + num = _color_num (_white, _white); + break; + case darkerblue: + case darkblue: + num = _color_num (_blue, _black); + break; + case darkergreen: + case darkgreen: + num = _color_num (_green, _black); + break; + case darkercyan: + case darkcyan: + num = _color_num (_cyan, _black); + break; + case darkerred: + case darkred: + num = _color_num (_red, _black); + break; + case darkermagenta: + case darkmagenta: + num = _color_num (_magenta, _black); + break; + case darkbrown: + case darkeryellow: + num = _color_num (_yellow, _black); + break; + case blue: + case lightblue: + case lighterblue: + num = _color_num (_blue, _white); + break; + case green: + case lightgreen: + case lightergreen: + num = _color_num (_green, _white); + break; + case cyan: + case lightcyan: + case lightercyan: + num = _color_num (_cyan, _white); + break; + case red: + case lightred: + case lighterred: + num = _color_num (_red, _white); + break; + case magenta: + case lightmagenta: + case lightermagenta: + num = _color_num (_magenta, _white); + break; + case brown: + case darkyellow: + case yellow: + num = _color_num (_yellow, _white); + break; + //default: + // num = _color_num (_white, _black); + } + + int state; + switch (color) { + case blue: + case green: + case cyan: + case red: + case magenta: + case brown: + state = A_REVERSE; + break; + case white: + case darkblue: + case darkgreen: + case darkcyan: + case darkred: + case darkmagenta: + case darkeryellow: + case lighterblue: + case lightergreen: + case lightercyan: + case lighterred: + case lightermagenta: + case yellow: + state = A_BOLD; + break; + default: + state = A_NORMAL; + } + + attron (COLOR_PAIR (num) | state); + mvaddch (y, x, symb); + attroff (COLOR_PAIR (num) | state); +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/block.h b/block.h new file mode 100644 index 0000000..481bcc5 --- /dev/null +++ b/block.h @@ -0,0 +1,45 @@ +#ifndef __BLOCK_H__ +#define __BLOCK_H__ + +typedef enum { + black, + darkgray, + gray, + white, + darkerblue, + darkblue, + blue, + lightblue, + lighterblue, + darkergreen, + darkgreen, + green, + lightgreen, + lightergreen, + darkercyan, + darkcyan, + cyan, + lightcyan, + lightercyan, + darkerred, + darkred, + red, + lightred, + lighterred, + darkermagenta, + darkmagenta, + magenta, + lightmagenta, + lightermagenta, + darkbrown, + brown, + darkeryellow, + darkyellow, + yellow, +} cblock_t; + +void mvaddcb (int y, int x, cblock_t color); + +#endif /* __BLOCK_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/color.c b/color.c new file mode 100644 index 0000000..05e28fb --- /dev/null +++ b/color.c @@ -0,0 +1,121 @@ +#include + +#include "color.h" + +static void _init_color_pairs () { + init_pair (1, COLOR_WHITE, COLOR_BLACK); + init_pair (2, COLOR_BLUE, COLOR_BLACK); + init_pair (3, COLOR_GREEN, COLOR_BLACK); + init_pair (4, COLOR_CYAN, COLOR_BLACK); + init_pair (5, COLOR_RED, COLOR_BLACK); + init_pair (6, COLOR_MAGENTA, COLOR_BLACK); + init_pair (7, COLOR_YELLOW, COLOR_BLACK); + init_pair (8, COLOR_WHITE, COLOR_WHITE); + init_pair (9, COLOR_BLUE, COLOR_WHITE); + init_pair (10, COLOR_GREEN, COLOR_WHITE); + init_pair (11, COLOR_CYAN, COLOR_WHITE); + init_pair (12, COLOR_RED, COLOR_WHITE); + init_pair (13, COLOR_MAGENTA, COLOR_WHITE); + init_pair (14, COLOR_YELLOW, COLOR_WHITE); + init_pair (15, COLOR_BLACK, COLOR_WHITE); +} + +void setcolor (ctext_t color) +{ + static int init = 1; + if (init) { + _init_color_pairs (); + init = 0; + } + + attroff (A_BOLD); + + int num; + switch (color) { + case gray_black: + case white_black: + num = 1; + break; + case blue_black: + case lightblue_black: + num = 2; + break; + case green_black: + case lightgreen_black: + num = 3; + break; + case cyan_black: + case lightcyan_black: + num = 4; + break; + case red_black: + case lightred_black: + num = 5; + break; + case magenta_black: + case lightmagenta_black: + num = 6; + break; + case brown_black: + case yellow_black: + num = 7; + break; + case white_gray: + num = 8; + break; + case blue_gray: + case lightblue_gray: + num = 9; + break; + case green_gray: + case lightgreen_gray: + num = 10; + break; + case cyan_gray: + case lightcyan_gray: + num = 11; + break; + case red_gray: + case lightred_gray: + num = 12; + break; + case magenta_gray: + case lightmagenta_gray: + num = 13; + break; + case brown_gray: + case yellow_gray: + num = 14; + break; + case black_gray: + num = 15; + break; + } + + int state; + switch (color) { + case white_black: + case lightblue_black: + case lightgreen_black: + case lightcyan_black: + case lightred_black: + case lightmagenta_black: + case yellow_black: + case white_gray: + case lightblue_gray: + case lightgreen_gray: + case lightcyan_gray: + case lightred_gray: + case lightmagenta_gray: + case yellow_gray: + state = A_BOLD; + break; + default: + state = A_NORMAL; + } + + attron (COLOR_PAIR (num) | state); + +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/color.h b/color.h new file mode 100644 index 0000000..0b2d25a --- /dev/null +++ b/color.h @@ -0,0 +1,39 @@ +#ifndef __COLOR_H__ +#define __COLOR_H__ + +typedef enum { + gray_black = 0, + blue_black, + green_black, + cyan_black, + red_black, + magenta_black, + brown_black, + white_black, + lightblue_black, + lightgreen_black, + lightcyan_black, + lightred_black, + lightmagenta_black, + yellow_black, + blue_gray, + green_gray, + cyan_gray, + red_gray, + magenta_gray, + brown_gray, + white_gray, + lightblue_gray, + lightgreen_gray, + lightcyan_gray, + lightred_gray, + lightmagenta_gray, + yellow_gray, + black_gray +} ctext_t; + +void setcolor (ctext_t color); + +#endif /* __COLOR_H__ */ + +/* vim: set ts=4 sw=4 et: */ 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..eaddbf3 --- /dev/null +++ b/display.c @@ -0,0 +1,208 @@ +#include +#include +#include +#include + +#include "block.h" +#include "color.h" +#include "debug.h" +#include "function.h" +#include "type.h" + +#include "display.h" + +int _helpwindow (char *msg, int xoffset, int yoffset, int length) +{ + int i = 0; + int j = 0; + while ((msg) && (*msg != '\0')) { + if ((*msg == '\n') || (i == length)) { + 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 i; + for (i = 0; title[i] != '\0'; i++) { + mvaddch (yoffset, xoffset + i, title[i]); + mvaddch (yoffset + 1, xoffset + i, ACS_HLINE); + } +} + +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) +{ + _displaytitle ("Help message", xoffset, yoffset); + int length = strmaxlen (msg, '\n'); + int j = 2; + j += _helpwindow (msg, xoffset, yoffset + j, length); + + return j; +} + +void boardwindow (board_t *board, int mode) +{ + int i, j; + + //setcolor (mode ? gray_black : black_gray); + if (mode) { + _dobound (board->width, board->height, board->xoffset, board->yoffset); + } + //setcolor (gray_black); + + for (i = 0; i < board->width; i++) { + for (j = 0; j < board->height; j++) { + int element = ' '; + switch (*getcell (board, i, j)) { + case '-': + element = ACS_HLINE; + break; + case '|': + element = ACS_VLINE; + break; + case 'L': + element = ACS_LLCORNER; + break; + case 'J': + element = ACS_LRCORNER; + break; + case '7': + element = ACS_URCORNER; + break; + case 'F': + element = ACS_ULCORNER; + break; + case 'T': + element = ACS_TTEE; + break; + case 'E': + element = ACS_LTEE; + break; + case '#': + element = ACS_BTEE; + break; + case '3': + element = ACS_RTEE; + break; + case '+': + element = ACS_PLUS; + break; + } + mvaddch (board->yoffset + j, board->xoffset + i, element); + } + } +} + +char *savewindow (int length, int xoffset, int yoffset) +{ + char *name = (char *) calloc (1, length + 1); + CHECKALLOC (name); + memset (name, ' ', length); + + setcolor (black_gray); + _dobound (length, 1, xoffset, yoffset); + setcolor (gray_black); + + int i = 0, j; + int stop = 0; + while (!stop) { + for (j = 0; j < length; j++) { + setcolor ((j == i) ? yellow_black : black_gray); + mvaddch (yoffset, xoffset + j, name[j]); + setcolor (gray_black); + } + int ch = getch (); + switch (ch) { + case '\n': + case '\r': + stop = 1; + break; + case KEY_BACKSPACE: + case KEY_DELETE: + case 127: + case '\b': + name[i] = ' '; + i--; + break; + case KEY_LEFT: + i--; + break; + case KEY_RIGHT: + i++; + break; + case KEY_ESC: + free (name); + name = NULL; + stop = 1; + break; + default: + if ((ch >= 32) && ( ch < 128)) { + name[i] = ch; + i++; + } + } + + if (i < 0) { + i = 0; + } + if (i >= length) { + i = length - 1; + } + } + + if (name) { + for (j = length - 1; j >= 0; j--) { + if (name[j] == ' ') { + name[j] = '\0'; + } + } + if (*name == '\0') { + free (name); + name = NULL; + } + } + + return name; +} + +void msgwindow (char *msg, int xoffset, int yoffset, int length) +{ + setcolor (gray_black); + _dobound ((length > 0) ? length : (int)strlen (msg), 1, xoffset, yoffset); + if (length > 0) { + int i; + for (i = 0; i < length; i++) { + mvaddch (yoffset, xoffset + i, ' '); + } + } + mvaddstr (yoffset, xoffset + ((length > 0) ? (length - (int)strlen (msg)) / 2 : 0), msg); + setcolor (black_gray); +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.h b/display.h new file mode 100644 index 0000000..b800d35 --- /dev/null +++ b/display.h @@ -0,0 +1,19 @@ +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include "type.h" + +#define KEY_ESC 0x1b +#define KEY_DELETE 0x014a + +int helpwindow (char *msg, int xoffset, int yoffset); + +void boardwindow (board_t *board, int mode); + +char *savewindow (int length, int xoffset, int yoffset); + +void msgwindow (char *msg, int xoffset, int yoffset, int length); + +#endif /* __DISPLAY_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.c b/function.c new file mode 100644 index 0000000..235f8bf --- /dev/null +++ b/function.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "type.h" + +#include "function.h" + +#define MAXNBBLOCKS 15 + +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 width, int height) +{ + board_t *board = (board_t *) malloc (sizeof (board_t)); + CHECKALLOC (board); + board->tab = (char *) calloc (1, width * height + 1); + CHECKALLOC (board->tab); + memset (board->tab, ' ', width * height); + board->width = width; + board->height = height; + board->xoffset = 0; + board->yoffset = 0; + 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->height; j++) { + l += sprintf (buffer + l, "rem: \""); + for (i = 0; i < board->width; i++) { + l += sprintf (buffer + l, "%c", *getcell (board, i, j)); + } + l += sprintf (buffer + l, "\"\n"); + } + return l; +} + +char _itoz (int x) +{ + return (x < 10) ? '0' + x : 'A' + x - 10; +} + +int _ztoi (char x) +{ + return (x > '9') ? x - 'A' + 10 : x - '0'; +} + +char *saveboard (board_t *board) +{ + int i; + int size = 2 * (8 + 2) + 7 + board->width * board->height; + VERBOSE (INFO, size += board->height * (8 + board->width)); + + char *buffer = (char *) calloc (size + 1, 1); + CHECKALLOC (buffer); + + int l = sprintf (buffer, "width: %d\n", board->width); + l += sprintf (buffer + l, "height: %d\n", board->height); + l += sprintf (buffer + l, "tab: \"%s\"\n", board->tab); + + 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 i; + int width = 0; + int height = 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, "width") == 0) { + width = atoi (value); + } else if (strcmp (keyword, "height") == 0) { + height = atoi (value); + } else if (strcmp (keyword, "tab") == 0) { + tab = atos (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) && (strlen (tab) == (size_t)(width * height))) { + board = initboard (width, height); + memcpy (board->tab, tab, width * height); + } +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.h b/function.h new file mode 100644 index 0000000..0483576 --- /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; }) + +#define getcell(b, x, y) ({ __typeof__ (b) _b = (b); int _x = (x), _y = (y);_b->tab + _x + _b->width * _y; }) + +int strmaxlen (char *str, char ch); + +board_t *initboard (int width, int height); + +board_t *setscale (board_t *board, int scale); + +void freeboard (board_t *board); + +int _makecomments (char *buffer, 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); + +#endif /* __FUNCTION_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/makefile b/makefile new file mode 100644 index 0000000..01777bf --- /dev/null +++ b/makefile @@ -0,0 +1,190 @@ +# 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 +#LDLIBS += -lws2_32 +LDOPT = winlnk +else ifneq (, $(findstring cygwin, $(MAKE_HOST))) +# Windows CygWin +LDOPT = winlnk +else ifneq (, $(findstring msdos, $(MAKE_HOST))) +# MSDOS +LDOPT = doslnk +MV = move +endif + +# Targets + +ALLEXE = +ALLEXE += pacman + +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; }; \ + 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/pacman.c b/pacman.c new file mode 100644 index 0000000..bba8515 --- /dev/null +++ b/pacman.c @@ -0,0 +1,252 @@ +/* depend: */ +/* cflags: */ +/* linker: color.o debug.o display.o function.o -lcurses */ +/* doslnk: color.o debug.o display.o function.o -lpdc~1 */ +/* winlnk: color.o debug.o display.o function.o -lpdcurses */ + +#include +#include +#include + +#include "debug.h" +#include "display.h" +#include "function.h" + +/* static variables */ +char *progname = NULL; +char *version = "0.1"; + +char *filename = NULL; +int maxnbrecords = 0; +int savelen = 12; + +int height = 20; +int width = 40; +int xoffset = 1; +int yoffset = 1; + +char *help = + " Move up cursor\n" + " Move left cursor\n" + " Move down cursor\n" + " Move right cursor\n" + " Quit\n" + " Save file\n" + ; + +int usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s [-f file] [-h] [-r int] [-v int]\n", progname); + fprintf (fd, " -f: file name (%s)\n", (filename) ? filename : "none"); + fprintf (fd, " -h: help message\n"); + fprintf (fd, " -r: max nb records (%d)\n", maxnbrecords); + 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[]) +{ + int i; + + /* 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 'f': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: no file specified\n", progname)); + return usage (1); + } + filename = arg; + break; + case 'r': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: missing max number of records\n", progname)); + return usage (1); + } + maxnbrecords = 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'); + } + } + + /* load playground or define it */ + board_t *board = NULL; + if (filename) { + char *buffer = readdata (filename); + if (buffer == NULL) { + VERBOSE (ERROR, fprintf (stderr, "can't read file (%s)\n", filename)); + return 1; + } + board = loadboard (buffer); + free (buffer); + if (board == NULL) { + VERBOSE (ERROR, fprintf (stderr, "incorrect file (%s)\n", filename)); + return 1; + } + } else { + board = initboard (width, height); + } + + /* init recorder */ + int *rec = NULL; + if (maxnbrecords) { + rec = (int *) calloc (maxnbrecords, sizeof (int)); + CHECKALLOC (rec); + } + int nbrecords = 0; + + /* init curses window */ + initscr (); + noecho (); + cbreak (); + nonl (); + keypad (stdscr, TRUE); + curs_set (0); + start_color (); + + /* window positions (board) */ + int xboard = board->xoffset = xoffset; + int yboard = board->yoffset = yoffset; + int xsave = max (xboard + (board->width - savelen) / 2, 1); + int ysave = yboard + (board->height - 1) / 2; + char *savename = NULL; + + /* cursor definition */ + int cursor = 0; + int xcursor = board->width / 2; + int ycursor = board->height / 2; + + /* event loop */ + int stop = 0; + int mode = 0; + while (!stop) { + + boardwindow (board, 0); + + int ch = getch (); + + /* record key pressed */ + if (maxnbrecords) { + if (nbrecords < maxnbrecords) { + rec[nbrecords++] = ch; + } else { + int i; + for (i = 0; i < nbrecords - 1; i++) { + rec[i] = rec[i + 1]; + } + //memmove (rec, rec + 1, nbrecords - 1); + rec[nbrecords - 1] = ch; + } + } + + /* general controls */ + switch (ch) { + case KEY_ESC: + case 'q': + stop = 1; + break; + case 's': + savename = savewindow (savelen, xsave, ysave); + if (savename != NULL) { + char *ptr = saveboard (board); + if (writedata (savename, ptr)) { + VERBOSE (WARNING, printf ("issue writing Board\n")); + } + free (ptr); + free (savename); + } + break; + } + + /* game controls */ + switch (ch) { + case KEY_UP: + case 'i': + if (ycursor > 0) { + ycursor--; + } + break; + case KEY_LEFT: + case 'j': + if (xcursor > 0) { + xcursor--; + } + break; + case KEY_DOWN: + case 'k': + if (ycursor < board->height) { + ycursor++; + } + break; + case KEY_RIGHT: + case 'l': + if (xcursor < board->width) { + xcursor++; + } + break; + } + } + + /* cleaning before quiting */ + endwin (); + + if (nbrecords) { + int i; + printf ("records: "); + for (i = 0; i < nbrecords; i++) { + if ((rec[i] > 31) && (rec[i] < 128)) { + printf ("%c", rec[i]); + } else { + printf ("0x%x", rec[i]); + } + } + printf ("\n"); + } + + free (rec); + freeboard (board); + + return 0; +} + +/* test: pacman.exe -f 2>&1 | grep 'no file' */ +/* test: pacman.exe -f nofile.pen 2>&1 | grep "can't read file" */ +/* test: pacman.exe -f bogus.pen 2>&1 | grep 'incorrect file' */ +/* test: pacman.exe -h | grep usage */ +/* test: pacman.exe -r 2>&1 | grep 'missing max' */ +/* test: pacman.exe -v 2>&1 | grep missing */ +/* test: pacman.exe _ 2>&1 | grep invalid */ +/* test: { sleep 1; echo -n ijklq; sleep 1; echo q; } | pacman.exe -s 3 -b 6x10 */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/type.h b/type.h new file mode 100644 index 0000000..fd1f69a --- /dev/null +++ b/type.h @@ -0,0 +1,14 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +typedef struct { + int width; + int height; + char *tab; + int xoffset; + int yoffset; +} board_t; + +#endif /* __TYPE_H__ */ + +/* vim: set ts=4 sw=4 et: */ -- 2.30.2