From 5239c8525bb1b570fa0a5ee6c71288c20d613f96 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 3 Feb 2025 10:03:24 -0500 Subject: [PATCH 1/5] More generalized keyboard commands and their respective tests --- tests/expected/test_kb_cmd.expect | 9 ++ tests/src/kb_cmd.h | 224 ++++++++++++++++++++++++++++++ tests/src/test_kb_cmd.c | 172 +++++++++++++++++++++++ 3 files changed, 405 insertions(+) create mode 100644 tests/expected/test_kb_cmd.expect create mode 100644 tests/src/kb_cmd.h create mode 100644 tests/src/test_kb_cmd.c diff --git a/tests/expected/test_kb_cmd.expect b/tests/expected/test_kb_cmd.expect new file mode 100644 index 0000000..923942d --- /dev/null +++ b/tests/expected/test_kb_cmd.expect @@ -0,0 +1,9 @@ +loop test starting +loop test completed +nesting test starting +nesting test completed +char table test starting +char table test completed +word test starting +word test completed +test_kb_cmd done diff --git a/tests/src/kb_cmd.h b/tests/src/kb_cmd.h new file mode 100644 index 0000000..0a5e47b --- /dev/null +++ b/tests/src/kb_cmd.h @@ -0,0 +1,224 @@ +#ifndef KB_CMD_H +#define KB_CMD_H + +#include "device/keyboard.h" +#include "device/ps2.h" +#include "test_helper.h" + +// Returns 0 if executed successfully, non-zero otherwise +typedef int (*CmdFunc)(void); + +struct LoopNode { + int idx; + int remaining; +}; + +// if you have more than 8 nested loops then what the fuck +struct LoopNode loopStack[8]; +int current = -1; + +typedef enum { + // A singular key press + CMD_KEY_PRESS, + + // Types the entire provided word + CMD_TYPE_WORD, + + // Signifies the start of a command loop + CMD_LOOP_START, + + // Signifies the end of the most recent loop command + CMD_LOOP_END, + + // Runs a function + CMD_FUNC, + + // End of command list + CMD_END +} CMD; + +struct KbCmd { + CMD cmd; + union { + // key to press + struct PS2Buf_t kb; + + // null terminated string + char *w; + + // loop count + int loops; + + // function to execute + CmdFunc func; + } data; +}; + +struct KeyData { + enum KeyCode c; + uint8_t mods; +}; + +#define keyDataStruct(code, modifiers) \ + (struct KeyData) {code, modifiers} + +#define keyAndShifted(unshiftedChar, shiftedChar, key) \ + [unshiftedChar] = keyDataStruct(key, 0), \ + [shiftedChar] = keyDataStruct(key, KEY_MOD_SHIFT), + +#define keyAndCapital(char, key) \ + [char] = keyDataStruct(key, 0), \ + [char - 32] = keyDataStruct(key, KEY_MOD_SHIFT), + +struct KeyData charToPressCMD[] = { + // Row 1 + keyAndShifted('`', '~', Key_grave) + keyAndShifted('1', '!', Key_1) + keyAndShifted('2', '@', Key_2) + keyAndShifted('3', '#', Key_3) + keyAndShifted('4', '$', Key_4) + keyAndShifted('5', '%', Key_5) + keyAndShifted('6', '^', Key_6) + keyAndShifted('7', '&', Key_7) + keyAndShifted('8', '*', Key_8) + keyAndShifted('9', '(', Key_9) + keyAndShifted('0', ')', Key_0) + keyAndShifted('-', '_', Key_minus) + keyAndShifted('=', '+', Key_equal) + + // Row 2 + keyAndCapital('q', Key_q) + keyAndCapital('w', Key_w) + keyAndCapital('e', Key_e) + keyAndCapital('r', Key_r) + keyAndCapital('t', Key_t) + keyAndCapital('y', Key_y) + keyAndCapital('u', Key_u) + keyAndCapital('i', Key_i) + keyAndCapital('o', Key_o) + keyAndCapital('p', Key_p) + keyAndShifted('[', '{', Key_openSquare) + keyAndShifted(']', '}', Key_closeSquare) + keyAndShifted('\\', '|', Key_backSlash) + + // Row 3 + keyAndCapital('a', Key_a) + keyAndCapital('s', Key_s) + keyAndCapital('d', Key_d) + keyAndCapital('f', Key_f) + keyAndCapital('g', Key_g) + keyAndCapital('h', Key_h) + keyAndCapital('j', Key_j) + keyAndCapital('k', Key_k) + keyAndCapital('l', Key_l) + keyAndShifted(';', ':', Key_semicolon) + keyAndShifted('\'', '"', Key_apostrophe) + + // Row 4 + keyAndCapital('z', Key_z) + keyAndCapital('x', Key_x) + keyAndCapital('c', Key_c) + keyAndCapital('v', Key_v) + keyAndCapital('b', Key_b) + keyAndCapital('n', Key_n) + keyAndCapital('m', Key_m) + keyAndShifted(',', '<', Key_comma) + keyAndShifted('.', '>', Key_period) + keyAndShifted('/', '?', Key_slash) +}; + +#undef keyPressStruct +#undef keyAndShifted +#undef keyAndCapital + +struct KbCmd keyPressCMD(enum KeyCode code, enum KeyState event, + uint8_t modifiers) { + KeyPress kp = (KeyPress){0, code, event, modifiers}; + struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; + return (struct KbCmd){CMD_KEY_PRESS, {.kb = b}}; +} + +struct KbCmd keyPressCMDFromData(struct KeyData data) { + KeyPress kp = (KeyPress){0, data.c, KeyPressed, data.mods}; + struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; + return (struct KbCmd){CMD_KEY_PRESS, {.kb = b}}; +} + +struct KbCmd typeWordCMD(char *word) { + return (struct KbCmd){CMD_TYPE_WORD, {.w = word}}; +} + +// `loops` must be greater than 0 +struct KbCmd loopStartCMD(int loops) { + return (struct KbCmd){CMD_LOOP_START, {.loops = loops}}; +} + +struct KbCmd loopEndCMD() { + return (struct KbCmd){CMD_LOOP_END, {}}; +} + +struct KbCmd funcCMD(CmdFunc func) { + return (struct KbCmd){CMD_FUNC, {.func = func}}; +} + +struct KbCmd endCMD() { + return (struct KbCmd){CMD_END, {}}; +} + +// Returns 0 when exiting normally, and anything else when shit went fuck +typedef int (*ExecFunc)(struct KbCmd, int *); + +int baseExec(struct KbCmd cmd, int *idx) { + switch (cmd.cmd) { + case CMD_KEY_PRESS: + vgaEditor(cmd.data.kb); + break; + case CMD_TYPE_WORD: + for(char *c = cmd.data.w; c != 0; c++) { + vgaEditor(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb); + } + break; + case CMD_LOOP_START: + if (cmd.data.loops < 1) { + FAIL_M("Loop count must be greater than 0, got %i", cmd.data.loops); + return 1; + } + if (current == -1 || loopStack[current].idx != *idx) { + current++; + loopStack[current] = (struct LoopNode){*idx, cmd.data.loops}; + } + loopStack[current].remaining--; + break; + case CMD_LOOP_END: + if (loopStack[current].remaining) { + // subtract 1 because idx is incremented after command completes + // this was a surprisingly annoying issue to track down + *idx = loopStack[current].idx - 1; + } else { + current--; + } + break; + case CMD_FUNC: + return cmd.data.func(); + case CMD_END: + break; + default: + FAIL_M("Unexpected command type: %i", cmd.cmd); + return 1; + } + return 0; +} + +int execList(struct KbCmd *cmds, ExecFunc f) { + for (int i = 0; cmds[i].cmd != CMD_END; i++) { + if (f(cmds[i], &i)) { + char buff[32]; + int len = snprintf(buff, 32, "Command %i failed", i); + serialWrite(COM1, (uint8_t *)buff, len); + return 1; + } + } + return 0; +} + +#endif diff --git a/tests/src/test_kb_cmd.c b/tests/src/test_kb_cmd.c new file mode 100644 index 0000000..e22a3ba --- /dev/null +++ b/tests/src/test_kb_cmd.c @@ -0,0 +1,172 @@ +#include "kb_cmd.h" +#include "string.h" + +#define testStart(name, print) \ + int name##Start() { \ + char text[] = print " starting\n"; \ + serialWrite(COM1, (uint8_t *)(text), sizeof(text) - 1); \ + return 0; \ + } + +#define testEnd(name, print) \ + int name##End() { \ + char text[] = print " completed\n"; \ + serialWrite(COM1, (uint8_t *)(text), sizeof(text) - 1); \ + return 0; \ + } + +char buff[64]; +int buffIdx = 0; + +int resetBuff() { + memset(buff, 0, 64); + buffIdx = 0; + return 0; +} + +int testExec(struct KbCmd cmd, int *idx) { + switch (cmd.cmd) { + case CMD_KEY_PRESS: + buff[buffIdx++] = keyPressToASCII(cmd.data.kb.keyEvent); + break; + case CMD_TYPE_WORD: + for(char *c = cmd.data.w; *c != 0; c++) { + buff[buffIdx++] = keyPressToASCII(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb.keyEvent); + } + break; + case CMD_LOOP_START: + if (cmd.data.loops < 1) { + FAIL_M("Loop count must be greater than 0, got %i", cmd.data.loops); + return 1; + } + if (current == -1 || loopStack[current].idx != *idx) { + current++; + loopStack[current] = (struct LoopNode){*idx, cmd.data.loops}; + } + loopStack[current].remaining--; + break; + case CMD_LOOP_END: + if (loopStack[current].remaining) { + // subtract 1 because idx is incremented after command completes + // this was a surprisingly annoying issue to track down + *idx = loopStack[current].idx - 1; + } else { + current--; + } + break; + case CMD_FUNC: + return cmd.data.func(); + case CMD_END: + break; + default: + FAIL_M("Unexpected command type: %i", cmd.cmd); + return 1; + } + return 0; +} + +// clang-format off + +// Loop prints +testStart(loopTest, "loop test") +testEnd(loopTest, "loop test") + +// Nesting prints +testStart(nestingTest, "nesting test") +testEnd(nestingTest, "nesting test") + +// Char table prints +testStart(charTableTest, "char table test") +testEnd(charTableTest, "char table test") + +// Word prints +testStart(wordTest, "word test") +testEnd(wordTest, "word test") + +// Loop testing +int v = 0; + +// clang-format on +// stop fucking this up + +int vReset() { + v = 0; + return 0; +} + +int vInc() { + v++; + return 0; +} + +int testSingleLoop() { + ASSERT_M(v == 4, "Expected to loop 4 times, looped %i time(s) instead", v); + return 0; +} + +int testNestedLoop() { + ASSERT_M(v == 6, "Expected to loop 6 times, looped %i time(s) instead", v); + return 0; +} + +// Char table testing +int capitalShiftTest() { + ASSERT(Key_a == charToPressCMD['a'].c); + ASSERT(0 == charToPressCMD['a'].mods); + ASSERT(Key_a == charToPressCMD['A'].c); + ASSERT(KEY_MOD_SHIFT == charToPressCMD['A'].mods) + return 0; +} + +int shiftTest() { + ASSERT(Key_grave == charToPressCMD['`'].c) + ASSERT(0 == charToPressCMD['`'].mods) + ASSERT(Key_grave == charToPressCMD['~'].c) + ASSERT(KEY_MOD_SHIFT == charToPressCMD['~'].mods) + return 0; +} + +// Word type testing +int wordTest() { + ASSERT(strncmp("test", buff, 5)) + return 0; +} + +void test_main() { + struct KbCmd list[] = { + // Single loop test + funcCMD(loopTestStart), + loopStartCMD(4), + funcCMD(vInc), + loopEndCMD(), + funcCMD(testSingleLoop), + funcCMD(loopTestEnd), + + funcCMD(vReset), + // Nested loop test + funcCMD(nestingTestStart), + loopStartCMD(2), + loopStartCMD(3), + funcCMD(vInc), + loopEndCMD(), + loopEndCMD(), + funcCMD(testNestedLoop), + funcCMD(nestingTestEnd), + + // Char table values test + funcCMD(charTableTestStart), + funcCMD(capitalShiftTest), + funcCMD(shiftTest), + funcCMD(charTableTestEnd), + + // Word type test + funcCMD(wordTestStart), + typeWordCMD("test"), + funcCMD(wordTestEnd), + + endCMD(), + }; + execList(list, testExec); + char done[] = "test_kb_cmd done\n"; + serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); +} \ No newline at end of file From 37b81639cd1bcae57e63d2cfe7ff6ef0ec137330 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 3 Feb 2025 10:07:53 -0500 Subject: [PATCH 2/5] Formatting... you'd think I'd remember to do this by now --- tests/src/kb_cmd.h | 2 +- tests/src/test_kb_cmd.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/src/kb_cmd.h b/tests/src/kb_cmd.h index 0a5e47b..3fe6f40 100644 --- a/tests/src/kb_cmd.h +++ b/tests/src/kb_cmd.h @@ -165,7 +165,7 @@ struct KbCmd endCMD() { return (struct KbCmd){CMD_END, {}}; } -// Returns 0 when exiting normally, and anything else when shit went fuck +// Returns 0 when exiting normally, and anything else when shit went fuck typedef int (*ExecFunc)(struct KbCmd, int *); int baseExec(struct KbCmd cmd, int *idx) { diff --git a/tests/src/test_kb_cmd.c b/tests/src/test_kb_cmd.c index e22a3ba..f663804 100644 --- a/tests/src/test_kb_cmd.c +++ b/tests/src/test_kb_cmd.c @@ -30,8 +30,9 @@ int testExec(struct KbCmd cmd, int *idx) { buff[buffIdx++] = keyPressToASCII(cmd.data.kb.keyEvent); break; case CMD_TYPE_WORD: - for(char *c = cmd.data.w; *c != 0; c++) { - buff[buffIdx++] = keyPressToASCII(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb.keyEvent); + for (char *c = cmd.data.w; *c != 0; c++) { + buff[buffIdx++] = keyPressToASCII( + keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb.keyEvent); } break; case CMD_LOOP_START: From 846543adeaf291fbe4d6bd474df10bbc85b652f6 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 10 Feb 2025 12:39:07 -0500 Subject: [PATCH 3/5] Remove macro and move all previous usages to use to get clang-format to shut up --- tests/src/kb_cmd.h | 112 ++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/tests/src/kb_cmd.h b/tests/src/kb_cmd.h index 3fe6f40..72329ab 100644 --- a/tests/src/kb_cmd.h +++ b/tests/src/kb_cmd.h @@ -59,72 +59,70 @@ struct KeyData { uint8_t mods; }; -#define keyDataStruct(code, modifiers) \ - (struct KeyData) {code, modifiers} - -#define keyAndShifted(unshiftedChar, shiftedChar, key) \ - [unshiftedChar] = keyDataStruct(key, 0), \ - [shiftedChar] = keyDataStruct(key, KEY_MOD_SHIFT), +#define keyDataStruct(code, modifiers) \ + (struct KeyData) { \ + code, modifiers \ + } -#define keyAndCapital(char, key) \ - [char] = keyDataStruct(key, 0), \ - [char - 32] = keyDataStruct(key, KEY_MOD_SHIFT), +#define keyAndShifted(unshiftedChar, shiftedChar, key) \ + [unshiftedChar] = keyDataStruct(key, 0), [shiftedChar] = keyDataStruct( \ + key, KEY_MOD_SHIFT) struct KeyData charToPressCMD[] = { // Row 1 - keyAndShifted('`', '~', Key_grave) - keyAndShifted('1', '!', Key_1) - keyAndShifted('2', '@', Key_2) - keyAndShifted('3', '#', Key_3) - keyAndShifted('4', '$', Key_4) - keyAndShifted('5', '%', Key_5) - keyAndShifted('6', '^', Key_6) - keyAndShifted('7', '&', Key_7) - keyAndShifted('8', '*', Key_8) - keyAndShifted('9', '(', Key_9) - keyAndShifted('0', ')', Key_0) - keyAndShifted('-', '_', Key_minus) - keyAndShifted('=', '+', Key_equal) + keyAndShifted('`', '~', Key_grave), + keyAndShifted('1', '!', Key_1), + keyAndShifted('2', '@', Key_2), + keyAndShifted('3', '#', Key_3), + keyAndShifted('4', '$', Key_4), + keyAndShifted('5', '%', Key_5), + keyAndShifted('6', '^', Key_6), + keyAndShifted('7', '&', Key_7), + keyAndShifted('8', '*', Key_8), + keyAndShifted('9', '(', Key_9), + keyAndShifted('0', ')', Key_0), + keyAndShifted('-', '_', Key_minus), + keyAndShifted('=', '+', Key_equal), // Row 2 - keyAndCapital('q', Key_q) - keyAndCapital('w', Key_w) - keyAndCapital('e', Key_e) - keyAndCapital('r', Key_r) - keyAndCapital('t', Key_t) - keyAndCapital('y', Key_y) - keyAndCapital('u', Key_u) - keyAndCapital('i', Key_i) - keyAndCapital('o', Key_o) - keyAndCapital('p', Key_p) - keyAndShifted('[', '{', Key_openSquare) - keyAndShifted(']', '}', Key_closeSquare) - keyAndShifted('\\', '|', Key_backSlash) + keyAndShifted('q', 'Q', Key_q), + keyAndShifted('w', 'W', Key_w), + keyAndShifted('e', 'E', Key_e), + keyAndShifted('r', 'R', Key_r), + keyAndShifted('t', 'T', Key_t), + keyAndShifted('y', 'Y', Key_y), + keyAndShifted('u', 'U', Key_u), + keyAndShifted('i', 'I', Key_i), + keyAndShifted('o', 'O', Key_o), + keyAndShifted('p', 'P', Key_p), + keyAndShifted('[', '{', Key_openSquare), + keyAndShifted(']', '}', Key_closeSquare), + keyAndShifted('\\', '|', Key_backSlash), // Row 3 - keyAndCapital('a', Key_a) - keyAndCapital('s', Key_s) - keyAndCapital('d', Key_d) - keyAndCapital('f', Key_f) - keyAndCapital('g', Key_g) - keyAndCapital('h', Key_h) - keyAndCapital('j', Key_j) - keyAndCapital('k', Key_k) - keyAndCapital('l', Key_l) - keyAndShifted(';', ':', Key_semicolon) - keyAndShifted('\'', '"', Key_apostrophe) + keyAndShifted('a', 'A', Key_a), + keyAndShifted('s', 'S', Key_s), + keyAndShifted('d', 'D', Key_d), + keyAndShifted('f', 'F', Key_f), + keyAndShifted('g', 'G', Key_g), + keyAndShifted('h', 'H', Key_h), + keyAndShifted('j', 'J', Key_j), + keyAndShifted('k', 'K', Key_k), + keyAndShifted('l', 'L', Key_l), + keyAndShifted(';', ':', Key_semicolon), + keyAndShifted('\'', '"', Key_apostrophe), // Row 4 - keyAndCapital('z', Key_z) - keyAndCapital('x', Key_x) - keyAndCapital('c', Key_c) - keyAndCapital('v', Key_v) - keyAndCapital('b', Key_b) - keyAndCapital('n', Key_n) - keyAndCapital('m', Key_m) - keyAndShifted(',', '<', Key_comma) - keyAndShifted('.', '>', Key_period) - keyAndShifted('/', '?', Key_slash) + keyAndShifted('z', 'Z', Key_z), + keyAndShifted('x', 'X', Key_x), + keyAndShifted('c', 'C', Key_c), + keyAndShifted('v', 'V', Key_v), + keyAndShifted('b', 'B', Key_b), + keyAndShifted('n', 'N', Key_n), + keyAndShifted('m', 'M', Key_m), + keyAndShifted(',', '<', Key_comma), + keyAndShifted('.', '>', Key_period), + keyAndShifted('/', '?', Key_slash), }; #undef keyPressStruct @@ -174,7 +172,7 @@ int baseExec(struct KbCmd cmd, int *idx) { vgaEditor(cmd.data.kb); break; case CMD_TYPE_WORD: - for(char *c = cmd.data.w; c != 0; c++) { + for (char *c = cmd.data.w; c != 0; c++) { vgaEditor(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb); } break; From 0c4d5730ba9d5f41a3f94de97408ced8d97cb94a Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 10 Feb 2025 13:28:13 -0500 Subject: [PATCH 4/5] Implement changes suggested by Trevor --- tests/expected/test_kb_cmd.expect | 2 ++ tests/src/kb_cmd.h | 55 ++++++++++++++++------------ tests/src/test_kb_cmd.c | 60 +++++++++---------------------- 3 files changed, 51 insertions(+), 66 deletions(-) diff --git a/tests/expected/test_kb_cmd.expect b/tests/expected/test_kb_cmd.expect index 923942d..520f230 100644 --- a/tests/expected/test_kb_cmd.expect +++ b/tests/expected/test_kb_cmd.expect @@ -6,4 +6,6 @@ char table test starting char table test completed word test starting word test completed +complex word test starting +complex word test completed test_kb_cmd done diff --git a/tests/src/kb_cmd.h b/tests/src/kb_cmd.h index 72329ab..e50ead1 100644 --- a/tests/src/kb_cmd.h +++ b/tests/src/kb_cmd.h @@ -14,8 +14,8 @@ struct LoopNode { }; // if you have more than 8 nested loops then what the fuck -struct LoopNode loopStack[8]; -int current = -1; +static struct LoopNode loopStack[8]; +static int current = -1; typedef enum { // A singular key press @@ -68,7 +68,8 @@ struct KeyData { [unshiftedChar] = keyDataStruct(key, 0), [shiftedChar] = keyDataStruct( \ key, KEY_MOD_SHIFT) -struct KeyData charToPressCMD[] = { +// clang-format off +static const struct KeyData charToPressCMD[] = { // Row 1 keyAndShifted('`', '~', Key_grave), keyAndShifted('1', '!', Key_1), @@ -123,57 +124,65 @@ struct KeyData charToPressCMD[] = { keyAndShifted(',', '<', Key_comma), keyAndShifted('.', '>', Key_period), keyAndShifted('/', '?', Key_slash), + + // Row 5 + [' '] = keyDataStruct(Key_space, 0) }; +// clang-format on +// clang-format can you please not butcher the readability of the code? #undef keyPressStruct #undef keyAndShifted #undef keyAndCapital -struct KbCmd keyPressCMD(enum KeyCode code, enum KeyState event, - uint8_t modifiers) { +static struct KbCmd keyPressCMD(enum KeyCode code, enum KeyState event, + uint8_t modifiers) { KeyPress kp = (KeyPress){0, code, event, modifiers}; struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; return (struct KbCmd){CMD_KEY_PRESS, {.kb = b}}; } -struct KbCmd keyPressCMDFromData(struct KeyData data) { - KeyPress kp = (KeyPress){0, data.c, KeyPressed, data.mods}; - struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; - return (struct KbCmd){CMD_KEY_PRESS, {.kb = b}}; +static struct KbCmd keyPressCMDFromData(struct KeyData data) { + return (keyPressCMD(data.c, KeyPressed, data.mods)); } -struct KbCmd typeWordCMD(char *word) { +static struct KbCmd typeWordCMD(char *word) { return (struct KbCmd){CMD_TYPE_WORD, {.w = word}}; } // `loops` must be greater than 0 -struct KbCmd loopStartCMD(int loops) { +static struct KbCmd loopStartCMD(int loops) { return (struct KbCmd){CMD_LOOP_START, {.loops = loops}}; } -struct KbCmd loopEndCMD() { +static struct KbCmd loopEndCMD() { return (struct KbCmd){CMD_LOOP_END, {}}; } -struct KbCmd funcCMD(CmdFunc func) { +static struct KbCmd funcCMD(CmdFunc func) { return (struct KbCmd){CMD_FUNC, {.func = func}}; } -struct KbCmd endCMD() { +static struct KbCmd endCMD() { return (struct KbCmd){CMD_END, {}}; } -// Returns 0 when exiting normally, and anything else when shit went fuck -typedef int (*ExecFunc)(struct KbCmd, int *); +// Returns 0 when exiting normally, and anything else when things go wrong +typedef void (*KeyPressHandler)(struct PS2Buf_t); +typedef int (*ExecFunc)(struct KbCmd, int *, KeyPressHandler); + +void baseKeyHandler(struct PS2Buf_t kb) { + vgaEditor(kb); +} -int baseExec(struct KbCmd cmd, int *idx) { +static int baseExec(struct KbCmd cmd, int *idx, KeyPressHandler kp) { switch (cmd.cmd) { case CMD_KEY_PRESS: - vgaEditor(cmd.data.kb); + kp(cmd.data.kb); break; case CMD_TYPE_WORD: - for (char *c = cmd.data.w; c != 0; c++) { - vgaEditor(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb); + for (char *c = cmd.data.w; *c != 0; c++) { + kp(keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb); } break; case CMD_LOOP_START: @@ -207,11 +216,11 @@ int baseExec(struct KbCmd cmd, int *idx) { return 0; } -int execList(struct KbCmd *cmds, ExecFunc f) { +static int execList(struct KbCmd *cmds, ExecFunc f, KeyPressHandler kp) { for (int i = 0; cmds[i].cmd != CMD_END; i++) { - if (f(cmds[i], &i)) { + if (f(cmds[i], &i, kp)) { char buff[32]; - int len = snprintf(buff, 32, "Command %i failed", i); + int len = snprintf(buff, sizeof(buff), "Command %i failed", i); serialWrite(COM1, (uint8_t *)buff, len); return 1; } diff --git a/tests/src/test_kb_cmd.c b/tests/src/test_kb_cmd.c index f663804..1a666fc 100644 --- a/tests/src/test_kb_cmd.c +++ b/tests/src/test_kb_cmd.c @@ -19,51 +19,13 @@ char buff[64]; int buffIdx = 0; int resetBuff() { - memset(buff, 0, 64); + memset(buff, 0, sizeof(buff)); buffIdx = 0; return 0; } -int testExec(struct KbCmd cmd, int *idx) { - switch (cmd.cmd) { - case CMD_KEY_PRESS: - buff[buffIdx++] = keyPressToASCII(cmd.data.kb.keyEvent); - break; - case CMD_TYPE_WORD: - for (char *c = cmd.data.w; *c != 0; c++) { - buff[buffIdx++] = keyPressToASCII( - keyPressCMDFromData(charToPressCMD[(int)*c]).data.kb.keyEvent); - } - break; - case CMD_LOOP_START: - if (cmd.data.loops < 1) { - FAIL_M("Loop count must be greater than 0, got %i", cmd.data.loops); - return 1; - } - if (current == -1 || loopStack[current].idx != *idx) { - current++; - loopStack[current] = (struct LoopNode){*idx, cmd.data.loops}; - } - loopStack[current].remaining--; - break; - case CMD_LOOP_END: - if (loopStack[current].remaining) { - // subtract 1 because idx is incremented after command completes - // this was a surprisingly annoying issue to track down - *idx = loopStack[current].idx - 1; - } else { - current--; - } - break; - case CMD_FUNC: - return cmd.data.func(); - case CMD_END: - break; - default: - FAIL_M("Unexpected command type: %i", cmd.cmd); - return 1; - } - return 0; +void testKeyHandler(struct PS2Buf_t buf) { + buff[buffIdx++] = keyPressToASCII(buf.keyEvent); } // clang-format off @@ -84,11 +46,14 @@ testEnd(charTableTest, "char table test") testStart(wordTest, "word test") testEnd(wordTest, "word test") +// Complex word prints +testStart(complexWordTest, "complex word test") +testEnd(complexWordTest, "complex word test") + // Loop testing int v = 0; // clang-format on -// stop fucking this up int vReset() { v = 0; @@ -133,6 +98,11 @@ int wordTest() { return 0; } +int complexWordTest() { + ASSERT(strncmp("This is a very Loong word$%@^@\\", buff, 32)) + return 0; +} + void test_main() { struct KbCmd list[] = { // Single loop test @@ -165,9 +135,13 @@ void test_main() { typeWordCMD("test"), funcCMD(wordTestEnd), + funcCMD(complexWordTestStart), + typeWordCMD("This is a very Loong word$%@^@\\"), + funcCMD(complexWordTestEnd), + endCMD(), }; - execList(list, testExec); + execList(list, baseExec, testKeyHandler); char done[] = "test_kb_cmd done\n"; serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); } \ No newline at end of file From f3415ef3260db949106817c90778c767fd737e28 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 10 Feb 2025 18:48:41 -0500 Subject: [PATCH 5/5] Added missing static --- tests/src/kb_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/kb_cmd.h b/tests/src/kb_cmd.h index e50ead1..37c7ea1 100644 --- a/tests/src/kb_cmd.h +++ b/tests/src/kb_cmd.h @@ -171,7 +171,7 @@ static struct KbCmd endCMD() { typedef void (*KeyPressHandler)(struct PS2Buf_t); typedef int (*ExecFunc)(struct KbCmd, int *, KeyPressHandler); -void baseKeyHandler(struct PS2Buf_t kb) { +static void baseKeyHandler(struct PS2Buf_t kb) { vgaEditor(kb); }