From dd0abb8a0cac75a5161af427e06c2ed335f2b8fd Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Mon, 22 Jul 2002 20:33:25 +0000 Subject: [PATCH] Fixed very long line reading (and some buffering bugs). Removed the static limit in array for symbols parsing. --- debugger/debug.l | 166 ++++++++++++++++++++++++++------------------ debugger/debugger.h | 2 +- debugger/hash.c | 2 +- debugger/source.c | 2 +- 4 files changed, 100 insertions(+), 72 deletions(-) diff --git a/debugger/debug.l b/debugger/debug.l index f79ad9c2c04..d1c4f78211a 100644 --- a/debugger/debug.l +++ b/debugger/debug.l @@ -28,8 +28,11 @@ #include "y.tab.h" #undef YY_INPUT + +static int DEBUG_FetchFromLine(const char* pfx, char* buf, int size); + #define YY_INPUT(buf,result,max_size) \ - if ( (result = DEBUG_ReadLine("Wine-dbg>", buf, max_size, TRUE, TRUE)) <= 0 ) \ + if ( (result = DEBUG_FetchFromLine("Wine-dbg>", buf, max_size)) <= 0 ) \ YY_FATAL_ERROR( "ReadLine() in flex scanner failed" ); @@ -188,95 +191,120 @@ int yywrap(void) { return 1; } /* Strip whitespace from the start and end of STRING. */ -static void stripwhite (char *string) +static void stripwhite(char *string) { - register int i = 0; + int i, last; - while (whitespace (string[i])) - i++; + for (i = 0; whitespace(string[i]); i++); + if (i) strcpy(string, string + i); - if (i) - strcpy (string, string + i); + last = i = strlen(string) - 1; + if (string[last] == '\n') i--; - i = strlen (string) - 1; - - while (i > 0 && whitespace (string[i])) - i--; - - string[++i] = '\0'; + while (i > 0 && whitespace(string[i])) i--; + if (string[last] == '\n') + string[++i] = '\n'; + string[++i] = '\0'; } -int DEBUG_ReadLine(const char* pfx, char * buf, int size, int flush_sym, int keep_hist) +static int DEBUG_FetchEntireLine(const char* pfx, char** line, size_t* alloc, BOOL check_nl) { char buf_line[256]; - char* ptr; - int len; DWORD nread; + size_t len; - for (;;) + /* as of today, console handles can be file handles... so better use file APIs rather than + * consoles + */ + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pfx, strlen(pfx), NULL, NULL); + + len = 0; + do { - if (flush_sym) DEBUG_FlushSymbols(); - /* as of today, console handles can be file handles... so better use file APIs rather than - * consoles - */ - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pfx, strlen(pfx), &nread, NULL); - - if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf_line, sizeof(buf_line), &nread, NULL)) + if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf_line, sizeof(buf_line) - 1, &nread, NULL)) break; - /* FIXME: should be rewritten not to remove and then add the trailing '\n' */ - if (nread > 0 && buf_line[nread - 1] == '\n') nread--; - buf_line[nread] = 0; + buf_line[nread] = '\0'; - /* Remove leading and trailing whitespace from the line */ - stripwhite (buf_line); + if (check_nl && len == 0 && nread == 1 && buf_line[0] == '\n') + return 0; - if (keep_hist) - { - static char last_line[256] = ""; - /* If there is anything left, add it to the history list - and execute it. Otherwise, re-execute last command. */ - - if (*buf_line) - { - strncpy( last_line, buf_line, sizeof(last_line) - 1 ); - last_line[sizeof(last_line) - 1] = '\0'; - } - ptr = last_line; - } - else - { - /* I should also tweak with the undoc functions to remove this line from the console - * history... */ - ptr = buf_line; - } - - if ((len = strlen(ptr)) > 0) + /* store stuff at the end of last_line */ + if (len + nread + 1 > *alloc) { - if (size < len + 1) - { - DEBUG_Printf(DBG_CHN_MESG, "Fatal readline goof.\n"); - DEBUG_Exit(0); - } - strcpy(buf, ptr); - buf[len] = '\n'; - buf[len+1] = 0; - return len + 1; + *line = HeapReAlloc(GetProcessHeap(), 0, *line, *alloc += nread + 1); } - } - return 0; + strcpy(*line + len, buf_line); + len += nread; + } while (nread == 0 || buf_line[nread - 1] != '\n'); + + /* Remove leading and trailing whitespace from the line */ + stripwhite(*line); + return 1; } -static char *local_symbols[30]; -static int next_symbol; - -char * DEBUG_MakeSymbol(const char * symbol) +static int DEBUG_FetchFromLine(const char* pfx, char* buf, int size) { - assert(0 <= next_symbol && next_symbol < (sizeof(local_symbols) / sizeof(local_symbols[0]))); - return local_symbols[next_symbol++] = DBG_strdup(symbol); + size_t len; +static char* last_line = NULL; +static size_t last_line_size = 0; +static size_t last_line_idx = 0; + + /* first alloc of our current buffer */ + if (!last_line) + { + last_line = HeapAlloc(GetProcessHeap(), 0, last_line_size = 2); + assert(last_line); + last_line[0] = '\n'; + last_line[1] = '\0'; + } + + /* try first to fetch the remaining of an existing line */ + if (last_line_idx == 0) + { + /* no remaining chars to be read from last line, grab a brand new line up to '\n' */ + DEBUG_FlushSymbols(); + + DEBUG_FetchEntireLine(pfx, &last_line, &last_line_size, TRUE); + } + + len = min(strlen(last_line + last_line_idx), size - 1); + memcpy(buf, last_line + last_line_idx, len); + buf[len] = '\0'; + if ((last_line_idx += len) >= strlen(last_line)) + last_line_idx = 0; + return len; +} + +int DEBUG_ReadLine(const char* pfx, char* buf, int size) +{ + char* line = NULL; + size_t len = 0; + + DEBUG_FetchEntireLine(pfx, &line, &len, FALSE); + len = min(size, len); + memcpy(buf, line, len - 1); + buf[len] = '\0'; + return len - 1; +} + +static char** local_symbols /* = NULL */; +static int next_symbol /* = 0 */; +static int alloc_symbol /* = 0 */; + +char* DEBUG_MakeSymbol(const char* symbol) +{ + assert(0 <= next_symbol && next_symbol < alloc_symbol + 1); + if (next_symbol >= alloc_symbol) + { + local_symbols = HeapReAlloc(GetProcessHeap(), 0, local_symbols, + (alloc_symbol += 32) * sizeof(local_symbols[0])); + assert(local_symbols); + } + return local_symbols[next_symbol++] = DBG_strdup(symbol); } void DEBUG_FlushSymbols(void) { - while(--next_symbol >= 0) DBG_free(local_symbols[next_symbol]); - next_symbol = 0; + while(--next_symbol >= 0) DBG_free(local_symbols[next_symbol]); + next_symbol = 0; } diff --git a/debugger/debugger.h b/debugger/debugger.h index 44ba4fa1136..87e8ec8afd3 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -312,7 +312,7 @@ extern void DEBUG_Exit( DWORD ); /* debugger/debug.l */ extern void DEBUG_FlushSymbols(void); extern char*DEBUG_MakeSymbol(const char*); -extern int DEBUG_ReadLine(const char* pfx, char* buffer, int size, int flush_sym, int keep_hist); +extern int DEBUG_ReadLine(const char* pfx, char* buffer, int size); /* debugger/display.c */ extern int DEBUG_DoDisplay(void); diff --git a/debugger/hash.c b/debugger/hash.c index c5a2cb5678f..489d58b509f 100644 --- a/debugger/hash.c +++ b/debugger/hash.c @@ -427,7 +427,7 @@ BOOL DEBUG_GetSymbolValue( const char * name, const int lineno, } do { i = 0; - if (DEBUG_ReadLine("=> ", buffer, sizeof(buffer), FALSE, FALSE)) + if (DEBUG_ReadLine("=> ", buffer, sizeof(buffer))) { i = atoi(buffer); if (i < 1 || i > num) diff --git a/debugger/source.c b/debugger/source.c index 686a30cc204..75ff042ce0f 100644 --- a/debugger/source.c +++ b/debugger/source.c @@ -203,7 +203,7 @@ DEBUG_DisplaySource(char * sourcefile, int start, int end) * Still couldn't find it. Ask user for path to add. */ sprintf(zbuf, "Enter path to file '%s': ", sourcefile); - DEBUG_ReadLine(zbuf, tmppath, sizeof(tmppath), FALSE, FALSE); + DEBUG_ReadLine(zbuf, tmppath, sizeof(tmppath)); if( tmppath[strlen(tmppath)-1] == '\n' ) {