diff --git a/src/dusk/console/cmd/cmdecho.h b/src/dusk/console/cmd/cmdecho.h index 6bcd1593..f370146a 100644 --- a/src/dusk/console/cmd/cmdecho.h +++ b/src/dusk/console/cmd/cmdecho.h @@ -14,5 +14,5 @@ void cmdEcho(const consolecmdexec_t *exec) { return; } - consolePrint("%s", exec->argv[0]); + consolePrint("%s\n", exec->argv[0]); } \ No newline at end of file diff --git a/src/dusk/console/cmd/cmdlist.h b/src/dusk/console/cmd/cmdlist.h deleted file mode 100644 index a87d7afe..00000000 --- a/src/dusk/console/cmd/cmdlist.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -// #include "console/cmd/cmdquit.h" -#include "console/cmd/cmdecho.h" -#include "console/cmd/cmdset.h" -#include "console/cmd/cmdget.h" -// #include "console/cmd/cmdbind.h" -// #include "console/cmd/cmdtoggleconsole.h" -// #include "console/cmd/cmdalias.h" - -X(ECHO, "echo", cmdEcho) -X(SET, "set", cmdSet) -X(GET, "get", cmdGet) \ No newline at end of file diff --git a/src/dusk/console/console.c b/src/dusk/console/console.c index dc5d20a2..fd24ad8a 100644 --- a/src/dusk/console/console.c +++ b/src/dusk/console/console.c @@ -12,8 +12,14 @@ #include "input/input.h" #include "log/log.h" #include "engine/engine.h" + +#include "console/cmd/cmdecho.h" #include "console/cmd/cmdset.h" #include "console/cmd/cmdget.h" +#include "console/cmd/cmdquit.h" +// #include "console/cmd/cmdbind.h" +// #include "console/cmd/cmdtoggleconsole.h" +// #include "console/cmd/cmdalias.h" #include "display/shader/shaderunlit.h" #include "display/text/text.h" @@ -30,15 +36,13 @@ void consoleInit() { // Register cmds CONSOLE.cmdGet = consoleRegCmd("get", cmdGet); CONSOLE.cmdSet = consoleRegCmd("set", cmdSet); - - #define X(unused, command, function) \ - consoleRegCmd(command, function); - #include "console/cmd/cmdlist.h" - #undef X + consoleRegCmd("echo", cmdEcho); + consoleRegCmd("quit", cmdQuit); #ifdef DUSK_CONSOLE_POSIX threadInit(&CONSOLE.thread, consoleInputThread); threadMutexInit(&CONSOLE.execMutex); + threadMutexInit(&CONSOLE.printMutex); threadStartRequest(&CONSOLE.thread); #endif } @@ -88,6 +92,10 @@ void consolePrint(const char_t *message, ...) { int32_t len = stringFormatVA(buffer, CONSOLE_LINE_MAX, message, args); va_end(args); + #ifdef DUSK_CONSOLE_POSIX + threadMutexLock(&CONSOLE.printMutex); + #endif + // Move all lines back memoryMove( CONSOLE.line[0], @@ -101,6 +109,11 @@ void consolePrint(const char_t *message, ...) { buffer, len + 1 ); + + #ifdef DUSK_CONSOLE_POSIX + threadMutexUnlock(&CONSOLE.printMutex); + #endif + logDebug("%s", buffer); } @@ -116,11 +129,14 @@ void consoleExec(const char_t *line) { ); char_t buffer[CONSOLE_LINE_MAX]; + char_t pendingPrint[CONSOLE_LINE_MAX]; size_t i = 0, j = 0; char_t c; consoleexecstate_t state = CONSOLE_EXEC_STATE_INITIAL; consolecmdexec_t *exec = NULL; + pendingPrint[0] = '\0'; + while(state != CONSOLE_EXEC_STATE_FULLY_PARSED) { c = line[i]; @@ -149,16 +165,16 @@ void consoleExec(const char_t *line) { if(c == '"') { // Can't handle quotes within the command. - consolePrint("Invalid command"); + stringCopy(pendingPrint, "Invalid command", CONSOLE_LINE_MAX); while(c != '\0' && c != ';') c = line[++i]; continue; } - + buffer[j++] = c; i++; if(j >= CONSOLE_LINE_MAX) { - consolePrint("Command too long"); + stringCopy(pendingPrint, "Command too long", CONSOLE_LINE_MAX); state = CONSOLE_EXEC_STATE_FULLY_PARSED; continue; } @@ -212,7 +228,7 @@ void consoleExec(const char_t *line) { i++; if(j >= CONSOLE_LINE_MAX) { - consolePrint("Arg too long"); + stringCopy(pendingPrint, "Arg too long", CONSOLE_LINE_MAX); state = CONSOLE_EXEC_STATE_FULLY_PARSED; continue; } @@ -226,7 +242,7 @@ void consoleExec(const char_t *line) { } if(c == '\0' || c == ';') { - consolePrint("Unterminated quote"); + stringCopy(pendingPrint, "Unterminated quote", CONSOLE_LINE_MAX); state = CONSOLE_EXEC_STATE_FULLY_PARSED; continue; } @@ -235,7 +251,7 @@ void consoleExec(const char_t *line) { c = line[++i]; if(c == '\0' || c == ';') { - consolePrint("Unterminated quote"); + stringCopy(pendingPrint, "Unterminated quote", CONSOLE_LINE_MAX); state = CONSOLE_EXEC_STATE_FULLY_PARSED; continue; } @@ -245,7 +261,7 @@ void consoleExec(const char_t *line) { i++; if(j >= CONSOLE_LINE_MAX) { - consolePrint("Arg too long"); + stringCopy(pendingPrint, "Arg too long", CONSOLE_LINE_MAX); state = CONSOLE_EXEC_STATE_FULLY_PARSED; continue; } @@ -288,33 +304,44 @@ void consoleExec(const char_t *line) { } break; } + } + if(exec->cmd == NULL) { // Variable not found, is there an alias that matches? bool_t aliasFound = false; for(uint32_t k = 0; k < CONSOLE.aliasCount; k++) { consolealias_t *alias = &CONSOLE.aliases[k]; if(stringCompare(alias->alias, exec->command) != 0) continue; - // Matching alias found, we unlock the mutex and recursively call - // consoleExec to handle the alias command. + char_t aliasCmd[CONSOLE_LINE_MAX]; + stringCopy(aliasCmd, alias->command, CONSOLE_LINE_MAX); + + // Null exec before unlocking so the unclaimed slot cannot be + // raced by another thread calling consoleExec concurrently. + exec = NULL; + state = CONSOLE_EXEC_STATE_INITIAL; + aliasFound = true; + #ifdef DUSK_CONSOLE_POSIX threadMutexUnlock(&CONSOLE.execMutex); #endif - consoleExec(alias->command); + consoleExec(aliasCmd); #ifdef DUSK_CONSOLE_POSIX threadMutexLock(&CONSOLE.execMutex); #endif - aliasFound = true; break; } - if(!aliasFound && exec->cmd == NULL) { - consolePrint("Command \"%s\" not found", exec->command); + if(!aliasFound) { + stringFormat( + pendingPrint, CONSOLE_LINE_MAX, + "Command \"%s\" not found", exec->command + ); exec = NULL; state = CONSOLE_EXEC_STATE_INITIAL; - break; } + break; } // Prep for next command. @@ -332,6 +359,8 @@ void consoleExec(const char_t *line) { #ifdef DUSK_CONSOLE_POSIX threadMutexUnlock(&CONSOLE.execMutex); #endif + + if(pendingPrint[0] != '\0') consolePrint("%s", pendingPrint); } void consoleUpdate() { @@ -400,6 +429,7 @@ void consoleDispose(void) { #ifdef DUSK_CONSOLE_POSIX threadStop(&CONSOLE.thread); threadMutexDispose(&CONSOLE.execMutex); + threadMutexDispose(&CONSOLE.printMutex); #endif } @@ -408,7 +438,6 @@ void consoleDispose(void) { assertNotNull(thread, "Thread cannot be NULL."); char_t line[CONSOLE_LINE_MAX]; - size_t cap = 0; struct pollfd pfd = { .fd = STDIN_FILENO, diff --git a/src/dusk/console/console.h b/src/dusk/console/console.h index c6cc6538..4a713d61 100644 --- a/src/dusk/console/console.h +++ b/src/dusk/console/console.h @@ -56,6 +56,7 @@ typedef struct { char_t inputBuffer[CONSOLE_LINE_MAX]; thread_t thread; threadmutex_t execMutex; + threadmutex_t printMutex; #endif } console_t; diff --git a/src/dusklinux/log/log.c b/src/dusklinux/log/log.c index b0d808a5..1dd2d2d6 100644 --- a/src/dusklinux/log/log.c +++ b/src/dusklinux/log/log.c @@ -12,6 +12,7 @@ void logDebug(const char_t *message, ...) { va_start(args, message); vprintf(message, args); va_end(args); + fflush(stdout); } void logError(const char_t *message, ...) {