aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEinhard Leichtfuß <alguien@respiranto.de>2018-04-30 01:01:25 +0200
committerEinhard Leichtfuß <alguien@respiranto.de>2018-04-30 01:01:25 +0200
commit9ff096d2523060e1cc594389e0098dc77ed830a6 (patch)
tree0b064acd05d497e6895c74fdc97317f317633619
parent56177d4c37ec9ebaa386b7c80b55b12a4b534818 (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.c211
1 files 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);
+ }
+ }
+}