From 1f5f4230597c41725605646cfdc67e8575a28057 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 24 Jul 2020 10:31:14 +0200 Subject: [PATCH] Support input from file in oneliner executable When no arguments are given, read input from stdin. Any line that is not indented relative to the start of the current test starts a new test. Comments start with # and "literate programming" mode is enabled with the "-l" option and causes it ignore all lines not starting with "> ". Signed-off-by: Erik Boasson --- src/core/ddsc/tests/oneliner.c | 92 +++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/tests/oneliner.c b/src/core/ddsc/tests/oneliner.c index d6e32a9..60875fd 100644 --- a/src/core/ddsc/tests/oneliner.c +++ b/src/core/ddsc/tests/oneliner.c @@ -10,16 +10,104 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include +#include #include +#include #include "test_oneliner.h" int main (int argc, char **argv) { - for (int i = 1; i < argc; i++) + bool litmode = false; + if (argc == 2 && strcmp (argv[1], "-l") == 0) { - if (test_oneliner (argv[i]) <= 0) + /* literate mode: test code lines start with "> ", everything + else is just gobbledygook to be ignored */ + argc--; + argv++; + litmode = true; + } + if (argc > 1) + { + /* treat each argument as a test to execute */ + for (int i = 1; i < argc; i++) + { + if (test_oneliner (argv[i]) <= 0) + return 1; + } + } + else + { + /* read from stdin, # starts a comment, any line with an indent no greater + than the current test's indent starts a new test, i.e., + # this is a comment + r wr w 1 + take{(1,0,0)} r + r disp w 1 # this is also a comment + take{1} r + contains two tests */ + struct oneliner_ctx ctx; + size_t test_indent = SIZE_MAX; + unsigned lineno = 0, test_begin = 0, test_end = 0; + char buf[4096]; + while (fgets (buf, (int) sizeof (buf), stdin) != NULL) + { + lineno++; + if (buf[strlen (buf) - 1] != '\n' && !feof (stdin)) + { + if (test_indent < SIZE_MAX) + (void) test_oneliner_fini (&ctx); + fprintf (stderr, "stdin:%u: line too long\n", lineno); + return 1; + } + + if (litmode) + { + if (strncmp (buf, "> ", 2) != 0) + continue; + buf[0] = ' '; + } + + char *cmt = strchr (buf, '#'); + if (cmt) + *cmt = 0; + + size_t indent = 0, idx = 0; + while (buf[idx] == ' ' || buf[idx] == '\t') + indent += (buf[idx++] == ' ' ? 1 : 8 - (indent % 8)); + while (isspace ((unsigned char) buf[idx])) + idx++; + if (buf[idx] == 0) + continue; + + if (indent <= test_indent) + { + if (test_indent < SIZE_MAX) + { + if (test_oneliner_fini (&ctx) <= 0) + { + fprintf (stderr, "stdin:%u-%u: FAIL: %s\n", test_begin, test_end, test_oneliner_message (&ctx)); + return 1; + } + printf ("\n"); + } + printf ("------ stdin:%u ------\n", lineno); + test_indent = indent; + test_begin = lineno; + test_oneliner_init (&ctx); + } + + test_oneliner_step (&ctx, buf + idx); + test_end = lineno; + } + + if (test_indent < SIZE_MAX && test_oneliner_fini (&ctx) <= 0) + fprintf (stderr, "stdin:%u-%u: FAIL: %s\n", test_begin, test_end, test_oneliner_message (&ctx)); + if (ferror (stdin)) + { + fprintf (stderr, "error reading stdin\n"); return 1; + } } return 0; }