aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
+ }
+ }
+}