diff options
author | Einhard Leichtfuß <alguien@respiranto.de> | 2018-04-30 01:01:25 +0200 |
---|---|---|
committer | Einhard Leichtfuß <alguien@respiranto.de> | 2018-04-30 01:01:25 +0200 |
commit | 9ff096d2523060e1cc594389e0098dc77ed830a6 (patch) | |
tree | 0b064acd05d497e6895c74fdc97317f317633619 | |
parent | 56177d4c37ec9ebaa386b7c80b55b12a4b534818 (diff) |
Fix parse.c for non terminal output
Before, this case was treated very badly. In particular, words were
stored in an array of undefined size.
Also, the code for parsing the description (causing the problem) was
split off the main() method.
-rw-r--r-- | parse.c | 211 |
1 files changed, 147 insertions, 64 deletions
@@ -48,6 +48,9 @@ unsigned short width; /* terminal width, not relevant if ! break_lines */ unsigned short n; /* actual broken line maximum length; excl. offsets */ _Bool passthrough_word(); +int getchar_mergews(_Bool); +int passthrough_line(); +int breaklines(int, int); int main(int argc, char **argv) @@ -112,70 +115,16 @@ int main(int argc, char **argv) putchar('\n'); - /* Read description - delimited by newline - and print it broken into - * lines of max. n chars with an offset of k chars, iff break_lines - * is set to 1 */ - int i = 0; - int wi = 0; - char word[n]; - _Bool first = 1; - - c = getchar(); - while (1) + if (break_lines) { - if (c == '\t' || c == '\v') - c = ' '; - - if (c == '\n' || c == EOF) - { - if (wi != 0) - { - print_word_offset(k); - printf("%.*s\n", wi, word); - } - else if (! first) - putchar('\n'); - - if (c == '\n') - break; - else /* c == EOF */ - return 0; - } - else if (c == ' ') - { - if (wi != 0) - { - i++; - print_word_offset(k); - printf("%.*s", wi, word); - first = 0; - wi = 0; - } - c = getchar(); - } - else if (break_lines && i >= n) - { - if (first) - { - print_line_offset(k); - printf("%.*s\n", wi, word); - wi = 0; - i = 0; - } - else - { - putchar('\n'); - first = 1; - i = wi; - } - } - else - { - word[wi] = c; - wi++; - i++; - c = getchar(); - } + if (breaklines(n, k) == EOF) + return 0; + } + else + { + print_line_offset(k); + if (passthrough_line() == EOF) + return 0; } } @@ -184,9 +133,10 @@ int main(int argc, char **argv) } +/* Returns 0 on end of line or end of file and 1 otherwise. */ _Bool passthrough_word() { - char c; + int c; while (1) { @@ -198,3 +148,136 @@ _Bool passthrough_word() putchar(c); } } + + +/* Like getchar(), but merge [ \t\v]* into a single space. + * Iff trim_ws, ignore any whitespace. */ +int getchar_mergews(_Bool trim_ws) +{ + int c = getchar(); + + if (c == ' ' || c == '\t' || c == '\v') + { + do + { + c = getchar(); + } + while (c == ' ' || c == '\t' || c == '\v'); + + if (trim_ws) + { + return c; + } + else + { + ungetc(c, stdin); + return ' '; + } + } + else + { + return c; + } +} + + +/* Passes through everything from stdin to stdout until a newline character + * or EOF is read. + * Converts [ \t\v]* to ' '. + * Returns 0 on end of line and EOF on end of file. */ +int passthrough_line() +{ + int c; + + c = getchar_mergews(1); + if (c == EOF) + return EOF; + else if (c == '\n') + return 0; + + while (1) + { + if (c == EOF) + { + putchar('\n'); + return EOF; + } + else if (c == '\n') + { + putchar('\n'); + return 0; + } + + putchar(c); + c = getchar_mergews(0); + } +} + + +/* Read description - delimited by newline - and print it broken into + * lines of max. n chars with an offset of k chars. + * Returns 0 on end of line and EOF on end of file. */ +int breaklines(int n, int k) +{ + int c; + int i = 0; + int wi = 0; + char word[n]; + _Bool first = 1; + + c = getchar_mergews(1); + while (1) + { + if (c == '\n' || c == EOF) + { + if (wi != 0) + { + print_word_offset(k); + printf("%.*s\n", wi, word); + } + else if (! first) + putchar('\n'); + + if (c == '\n') + return 0; + else /* c == EOF */ + return EOF; + } + + if (c == ' ') + { + if (wi != 0) + { + i++; + print_word_offset(k); + printf("%.*s", wi, word); + first = 0; + wi = 0; + } + c = getchar_mergews(0); + } + else if (break_lines && i >= n) + { + if (first) + { + print_line_offset(k); + printf("%.*s\n", wi, word); + wi = 0; + i = 0; + } + else + { + putchar('\n'); + first = 1; + i = wi; + } + } + else + { + word[wi] = c; + wi++; + i++; + c = getchar_mergews(0); + } + } +} |