diff options
-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); + } + } +} |