[PATCH 2/2] regedit: Overhaul multibyte line processing
Hugh McMaster
hugh.mcmaster at outlook.com
Sun Nov 20 05:33:44 CST 2016
Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
programs/regedit/regproc.c | 160 +++++++++++++++------------------------------
1 file changed, 51 insertions(+), 109 deletions(-)
diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index a690a10..938881e 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -607,127 +607,69 @@ static void processRegEntry(WCHAR* stdInput, BOOL isUnicode)
return; /* skip comment lines */
}
-/******************************************************************************
- * Processes a registry file.
- * Correctly processes comments (in # and ; form), line continuation.
- *
- * Parameters:
- * in - input stream to read from
- * first_chars - beginning of stream, read due to Unicode check
- */
-static void processRegLinesA(FILE *in, char* first_chars)
+static char *get_lineA(FILE *fp, char *first_chars)
{
- char *buf = NULL; /* the line read from the input stream */
- unsigned long line_size = REG_VAL_BUF_SIZE;
- size_t chars_in_buf = -1;
- char *s; /* A pointer to buf for fread */
- char *line; /* The start of the current line */
- WCHAR *lineW;
-
- buf = HeapAlloc(GetProcessHeap(), 0, line_size);
- CHECK_ENOUGH_MEMORY(buf);
- s = buf;
- line = buf;
-
- memcpy(line, first_chars, 2);
+ static size_t size, count, size_remaining, offset = 0;
+ static char *buf, *s, *line, *p, *next;
- if (first_chars)
+ if (!size)
+ {
+ size = REG_VAL_BUF_SIZE;
+ s = buf = HeapAlloc(GetProcessHeap(), 0, size);
+ CHECK_ENOUGH_MEMORY(buf);
+ memcpy(s, first_chars, 2);
s += 2;
-
- while (!feof(in)) {
- size_t size_remaining;
- int size_to_get;
- char *s_eol = NULL; /* various local uses */
-
- /* Do we need to expand the buffer? */
- assert(s >= buf && s <= buf + line_size);
- size_remaining = line_size - (s - buf);
- if (size_remaining < 3) /* we need at least 3 bytes of room for \r\n\0 */
+ }
+ while (1)
+ {
+ size_remaining = size - (s - buf);
+ if (size_remaining < 3)
{
- char *new_buffer;
- size_t new_size = line_size + REG_VAL_BUF_SIZE;
- if (new_size > line_size) /* no arithmetic overflow */
- new_buffer = HeapReAlloc(GetProcessHeap(), 0, buf, new_size);
- else
- new_buffer = NULL;
- CHECK_ENOUGH_MEMORY(new_buffer);
- buf = new_buffer;
- line = buf;
- s = buf + line_size - size_remaining;
- line_size = new_size;
- size_remaining = line_size - (s - buf);
+ char *new_buf = HeapReAlloc(GetProcessHeap(), 0, buf, size * 2);
+ CHECK_ENOUGH_MEMORY(new_buf);
+ buf = new_buf;
+ s = buf + size - size_remaining;
+ size *= 2;
+ size_remaining = size - (s - buf);
}
+ line = s - offset;
+ count = fread(s, 1, size_remaining - 1, fp);
+ s[count] = 0;
+ s += count;
- /* Get as much as possible into the buffer, terminating on EOF,
- * error or once we have read the maximum amount. Abort on error.
- */
- size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
-
- chars_in_buf = fread(s, 1, size_to_get - 1, in);
- s[chars_in_buf] = 0;
-
- if (chars_in_buf == 0) {
- if (ferror(in)) {
- perror("While reading input");
- exit(IO_ERROR);
- } else {
- assert(feof(in));
- *s = '\0';
- }
+ p = strpbrk(line, "\r\n");
+ if (!p)
+ {
+ HeapFree(GetProcessHeap(), 0, buf);
+ return NULL;
}
-
- /* If we didn't read the end-of-line sequence or EOF, go around again */
- while (1)
+ next = p + 1;
+ if (*p == '\r' && *(p + 1) == '\n') next++;
+ *p = 0;
+ if (*(p - 1) == '\\')
{
- s_eol = strpbrk(line, "\r\n");
- if (!s_eol) {
- /* Move the stub of the line to the start of the buffer so
- * we get the maximum space to read into, and so we don't
- * have to recalculate 'line' if the buffer expands */
- MoveMemory(buf, line, strlen(line) + 1);
- line = buf;
- s = strchr(line, '\0');
- break;
- }
-
- /* If we find a comment line, discard it and go around again */
- if (line [0] == '#' || line [0] == ';') {
- if (*s_eol == '\r' && *(s_eol + 1) == '\n')
- line = s_eol + 2;
- else
- line = s_eol + 1;
- continue;
- }
-
- /* If there is a concatenating '\\', go around again */
- if (*(s_eol - 1) == '\\') {
- char *next_line = s_eol + 1;
-
- if (*s_eol == '\r' && *(s_eol + 1) == '\n')
- next_line++;
-
- while (*(next_line + 1) == ' ' || *(next_line + 1) == '\t')
- next_line++;
-
- MoveMemory(s_eol - 1, next_line, chars_in_buf - (next_line - s) + 1);
- chars_in_buf -= next_line - s_eol + 1;
- continue;
- }
+ *(--p) = 0;
+ while (*next && isspace(*next)) next++;
+ MoveMemory(p, next, strlen(next) + 1);
+ continue;
+ }
+ offset = s - next;
+ return line;
+ }
+}
- /* Remove any line feed. Leave s_eol on the last \0 */
- if (*s_eol == '\r' && *(s_eol + 1) == '\n')
- *s_eol++ = '\0';
- *s_eol = '\0';
+static void processRegLinesA(FILE *fp, char *first_chars)
+{
+ char *line;
+ WCHAR *lineW;
- lineW = GetWideString(line);
- processRegEntry(lineW, FALSE);
- HeapFree(GetProcessHeap(), 0, lineW);
- line = s_eol + 1;
- }
+ while ((line = get_lineA(fp, first_chars)))
+ {
+ lineW = GetWideString(line);
+ processRegEntry(lineW, FALSE);
+ HeapFree(GetProcessHeap(), 0, lineW);
}
closeKey();
-
- HeapFree(GetProcessHeap(), 0, buf);
}
static WCHAR *get_lineW(FILE *fp)
--
2.7.4
More information about the wine-patches
mailing list