libbb: split bb_get_chunk_from_file and bb_get_chunk_with_continuation
No binary (build failed)
—
(log yok)
| @@ -730,8 +730,12 @@ extern void xclose(int fd) FAST_FUNC; | |
| /* Reads and prints to stdout till eof, then closes FILE. Exits on error: */ | |
| extern void xprint_and_close_file(FILE *file) FAST_FUNC; | |
| + | /* Reads a line from a text file, up to a newline or NUL byte, inclusive. |
| + | * Returns malloc'ed char*. If end is NULL '\n' isn't considered |
| + | * end of line. If end isn't NULL, length of the chunk is stored in it. |
| + | * Returns NULL if EOF/error. |
| + | */ |
| extern char *bb_get_chunk_from_file(FILE *file, int *end) FAST_FUNC; | |
| - | extern char *bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno) FAST_FUNC; |
| /* Reads up to (and including) TERMINATING_STRING: */ | |
| extern char *xmalloc_fgets_str(FILE *file, const char *terminating_string) FAST_FUNC RETURNS_MALLOC; | |
| /* Same, with limited max size, and returns the length (excluding NUL): */ | |
| @@ -11,45 +11,24 @@ | |
| #include "libbb.h" | |
| - | /* This function reads an entire line from a text file, up to a newline |
| - | * or NUL byte, inclusive. It returns a malloc'ed char * which |
| - | * must be free'ed by the caller. If end is NULL '\n' isn't considered |
| - | * end of line. If end isn't NULL, length of the chunk is stored in it. |
| - | * If lineno is not NULL, *lineno is incremented for each line, |
| - | * and also trailing '\' is recognized as line continuation. |
| - | * |
| - | * Returns NULL if EOF/error. */ |
| - | char* FAST_FUNC bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno) |
| + | char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end) |
| { | |
| int ch; | |
| - | int idx = 0; |
| + | unsigned idx = 0; |
| char *linebuf = NULL; | |
| - | int linebufsz = 0; |
| while ((ch = getc(file)) != EOF) { | |
| /* grow the line buffer as necessary */ | |
| - | if (idx >= linebufsz) { |
| - | linebufsz += 256; |
| - | linebuf = xrealloc(linebuf, linebufsz); |
| - | } |
| + | if (!(idx & 0xff)) |
| + | linebuf = xrealloc(linebuf, idx + 0x100); |
| linebuf[idx++] = (char) ch; | |
| - | if (!ch) |
| + | if (ch == '\0') |
| + | break; |
| + | if (end && ch == '\n') |
| break; | |
| - | if (end && ch == '\n') { |
| - | if (lineno == NULL) |
| - | break; |
| - | (*lineno)++; |
| - | if (idx < 2 || linebuf[idx-2] != '\\') |
| - | break; |
| - | idx -= 2; |
| - | } |
| } | |
| - | if (end) { |
| + | if (end) |
| *end = idx; | |
| - | /* handle corner case when the file is not ended with '\n' */ |
| - | if (ch == EOF && lineno != NULL) |
| - | (*lineno)++; |
| - | } |
| if (linebuf) { | |
| // huh, does fgets discard prior data on error like this? | |
| // I don't think so.... | |
| @@ -63,11 +42,6 @@ char* FAST_FUNC bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno | |
| return linebuf; | |
| } | |
| - | char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end) |
| - | { |
| - | return bb_get_chunk_with_continuation(file, end, NULL); |
| - | } |
| - | |
| /* Get line, including trailing \n if any */ | |
| char* FAST_FUNC xmalloc_fgets(FILE *file) | |
| { | |
| @@ -104,6 +104,44 @@ void FAST_FUNC config_close(parser_t *parser) | |
| } | |
| } | |
| + | /* This function reads an entire line from a text file, up to a newline |
| + | * or NUL byte, exclusive. It returns a malloc'ed char*. |
| + | * *lineno is incremented for each line. |
| + | * Trailing '\' is recognized as line continuation. |
| + | * Returns NULL if EOF/error. |
| + | */ |
| + | static char* get_line_with_continuation(FILE *file, int *lineno) |
| + | { |
| + | int ch; |
| + | unsigned idx = 0; |
| + | char *linebuf = NULL; |
| + | |
| + | while ((ch = getc(file)) != EOF) { |
| + | /* grow the line buffer as necessary */ |
| + | if (!(idx & 0xff)) |
| + | linebuf = xrealloc(linebuf, idx + 0x101); |
| + | if (ch == '\n') |
| + | ch = '\0'; |
| + | linebuf[idx] = (char) ch; |
| + | if (ch == '\0') { |
| + | (*lineno)++; |
| + | if (idx == 0 || linebuf[idx-1] != '\\') |
| + | break; |
| + | idx--; /* go back to '/' */ |
| + | continue; |
| + | } |
| + | idx++; |
| + | } |
| + | if (ch == EOF) { |
| + | /* handle corner case when the file is not ended with '\n' */ |
| + | (*lineno)++; |
| + | if (linebuf) |
| + | linebuf[idx] = '\0'; |
| + | } |
| + | return linebuf; |
| + | } |
| + | |
| + | |
| /* | |
| 0. If parser is NULL return 0. | |
| 1. Read a line from config file. If nothing to read then return 0. | |
| @@ -132,28 +170,24 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const | |
| { | |
| char *line; | |
| int ntokens, mintokens; | |
| - | int t, len; |
| + | int t; |
| + | |
| + | if (!parser) |
| + | return 0; |
| ntokens = (uint8_t)flags; | |
| mintokens = (uint8_t)(flags >> 8); | |
| - | if (parser == NULL) |
| - | return 0; |
| - | |
| again: | |
| memset(tokens, 0, sizeof(tokens[0]) * ntokens); | |
| config_free_data(parser); | |
| /* Read one line (handling continuations with backslash) */ | |
| - | line = bb_get_chunk_with_continuation(parser->fp, &len, &parser->lineno); |
| + | line = get_line_with_continuation(parser->fp, &parser->lineno); |
| if (line == NULL) | |
| return 0; | |
| parser->line = line; | |
| - | /* Strip trailing line-feed if any */ |
| - | if (len && line[len-1] == '\n') |
| - | line[len-1] = '\0'; |
| - | |
| /* Skip token in the start of line? */ | |
| if (flags & PARSE_TRIM) | |
| line += strspn(line, delims + 1); | |