--- hatari/src/debug/debugui.c 2019/04/09 08:56:50 1.1.1.9 +++ hatari/src/debug/debugui.c 2019/04/09 08:59:20 1.1.1.11 @@ -13,6 +13,7 @@ const char DebugUI_fileid[] = "Hatari de #include #include #include +#include #include "config.h" @@ -57,6 +58,9 @@ static char lastResult[10]; /* parse debugger commands from here on init */ static const char *parseFileName; +/* to which directory to change after (potentially recursed) scripts parsing finishes */ +static char *finalDir; + /** * Save/Restore snapshot of debugging session variables @@ -148,7 +152,7 @@ static void DebugUI_PrintValue(Uint32 va ones = false; for (bit = 31; bit >= 0; bit--) { - one = value & (1<= ARRAY_SIZE(psArgs)) + { + fprintf(stderr, "Error: too many arguments (currently up to %d supported)\n", + ARRAY_SIZE(psArgs)); + retval = DEBUGGER_CMDCONT; + } + else + { + /* ... and execute the function */ + retval = debugCommand[i].pFunction(nArgc, psArgs); + } /* Save commando string if it can be repeated */ if (retval == DEBUGGER_CMDCONT) { @@ -798,8 +820,12 @@ static void DebugUI_FreeCommand(char *in */ static char *DebugUI_GetCommand(char *input) { + /* We need this indirection for libedit's rl_readline_name which is + * not declared as "const char *" (i.e. this is necessary for macOS) */ + static char hatari_readline_name[] = "Hatari"; + /* Allow conditional parsing of the ~/.inputrc file. */ - rl_readline_name = "Hatari"; + rl_readline_name = hatari_readline_name; /* Tell the completer that we want a crack first. */ rl_attempted_completion_function = DebugUI_Completion; @@ -807,6 +833,14 @@ static char *DebugUI_GetCommand(char *in return Str_Trim(readline("> ")); } +/** + * Get readlines idea of the terminal size + */ +static void DebugUI_GetScreenSize(int *rows, int *cols) +{ + rl_get_screen_size(rows, cols); +} + #else /* !HAVE_LIBREADLINE */ /** @@ -818,6 +852,21 @@ static void DebugUI_FreeCommand(char *in } /** + * Get number of lines/columns for terminal output + */ +static void DebugUI_GetScreenSize(int *rows, int *cols) +{ + const char *p; + + *rows = 24; + *cols = 80; + if ((p = getenv("LINES")) != NULL) + *rows = (int)strtol(p, NULL, 0); + if ((p = getenv("COLUMS")) != NULL) + *cols = (int)strtol(p, NULL, 0); +} + +/** * Read a command line from the keyboard and return a pointer to the string. * Only string returned by this function can be given for it as argument! * @return Pointer to the string which should be given back to this @@ -843,6 +892,29 @@ static char *DebugUI_GetCommand(char *in #endif /* !HAVE_LIBREADLINE */ +/** + * How many lines to "page" when user invokes calling command. + * + * If config value is >=0, use that. If it's negative, get number of lines + * from screensize. If even that's not defined, fall back to default value. + * + * @return Number of lines to output at the time. + */ +int DebugUI_GetPageLines(int config, int defvalue) +{ + int rows, cols; + + if (config >= 0) { + return config; + } + DebugUI_GetScreenSize(&rows, &cols); + /* leave 1 line for pager prompt */ + if (--rows > 0) { + return rows; + } + return defvalue; +} + static const dbgcommand_t uicommand[] = { @@ -851,8 +923,9 @@ static const dbgcommand_t uicommand[] = { DebugUI_ChangeDir, NULL, "cd", "", "change directory", - "\n" - "\tChange Hatari work directory.", + " [-f]\n" + "\tChange Hatari work directory. With '-f', directory is\n" + "\tchanged only after all script files have been parsed.", false }, { DebugUI_Evaluate, Vars_MatchCpuVariable, "evaluate", "e", @@ -912,7 +985,10 @@ static const dbgcommand_t uicommand[] = "parse", "p", "get debugger commands from file", "[filename]\n" - "\tRead debugger commands from given file and do them.", + "\tRead debugger commands from given file and do them.\n" + "\tCurrent directory is script directory during this.\n" + "\tTo specify directory to be used also for breakpoint\n" + "\tscripts execution, use '-f' option for 'cd' command.", false }, { DebugUI_Rename, NULL, "rename", "", @@ -1115,6 +1191,8 @@ void DebugUI(debug_reason_t reason) */ bool DebugUI_ParseFile(const char *path, bool reinit) { + int recurse; + static int recursing; char *olddir, *dir, *cmd, *input, *expanded, *slash; FILE *fp; @@ -1150,6 +1228,9 @@ bool DebugUI_ParseFile(const char *path, } free(dir); + recurse = recursing; + recursing = true; + input = NULL; for (;;) { @@ -1176,6 +1257,7 @@ bool DebugUI_ParseFile(const char *path, DebugUI_ParseCommand(cmd); free(expanded); } + recursing = false; free(input); fclose(fp); @@ -1189,10 +1271,27 @@ bool DebugUI_ParseFile(const char *path, free(olddir); } - if (reinit) + if (!recurse) { - DebugCpu_SetDebugging(); - DebugDsp_SetDebugging(); + /* current script (or something called by it) specified final dir */ + if (finalDir) + { + if (chdir(finalDir) != 0) + perror("ERROR"); + else + fprintf(stderr, "Delayed change to '%s' dir.\n", finalDir); + free(finalDir); + finalDir = NULL; + } + /* only top-level (non-recursed) call has valid re-init info, + * as that's the only one that can get directly called from + * breakpoints + */ + if (reinit) + { + DebugCpu_SetDebugging(); + DebugDsp_SetDebugging(); + } } return true; }