From 9ff096d2523060e1cc594389e0098dc77ed830a6 Mon Sep 17 00:00:00 2001 From: Einhard Leichtfuß Date: Mon, 30 Apr 2018 01:01:25 +0200 Subject: 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. --- parse.c | 211 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 64 deletions(-) diff --git a/parse.c b/parse.c index bfe43fa..cac117b 100644 --- a/parse.c +++ b/parse.c @@ -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); + } + } +} -- cgit v1.2.3