dnl Copyright © 2021 Nick Bowler dnl dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2. dnl This is free software: you are free to do what the fuck you want to. dnl There is NO WARRANTY, to the extent permitted by law. AT_BANNER([Script tests]) AT_SETUP([gen-options.awk]) AT_DATA([options.def], [[--option-only --option-with-val (5) --option-with-flagval (&x, 5) --option-with-arg=ARG some "text" goes here --option-with-optional-arg[=OPTIONAL] hello -a, --option-with-sopt -b, --option-with-sopt-and-arg=SOPTARG -c, --option-with-sopt-and-optional-arg[=SOPTOPTIONAL] --option-with-arg-and-val=ARGVAL (42) --option-with-arg-and-flagval=ARGFLAGVAL (&a[1], 'x') --option-with-optional-arg-and-val[=OPTIONALARGVAL] (54) --option-with-optional-arg-and-flagval[=OPTIONALFLAGVAL] (0, 0) --with-sopt Here is a help string that has a line randomly indented # with a comment @&t@ and a blank line --with-arg=ARG do stuff with ARG --flagval ]]) AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" options.h]) AT_DATA([context.h], [[struct option { const char *name; int has_arg; int *flag; int val; }; int x, a[5]; ]]) # test 0: sanity test AT_DATA([test0.c], [[#include "context.h" #include "options.h" static const char sopts[] = SOPT_STRING; static const struct option opts[] = { LOPTS_INITIALIZER, {0} }; int main(void) { return 0; } ]]) AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [], [ignore]) # test 1: long option names and help text AT_DATA([test1.c], [[#include #include #include "context.h" #include "options.h" static const struct option opts[] = { LOPTS_INITIALIZER }; int main(void) { unsigned i; for (i = 0; i < sizeof opts / sizeof opts[0]; i++) { struct lopt_help help = { "INVALID", "INVALID" }; if (!lopt_get_help(&opts[i], &help)) return EXIT_FAILURE; printf("--%s", opts[i].name); if (opts[i].has_arg) printf("=%s", help.arg); printf("\n%s", help.desc); if (help.desc[0]) putchar('\n'); } return 0; } ]]) # pick out interesting bits from the definitions file sed -n '/^-/s/^.*--\([[^\= @<:@]]*\).*$/\1/p' options.def >options sed -n '/^-/{ s/[[^=]]*\(=[[^@:>@ ]]*\).*$/\1/ s/^[[^=]].*// s/^=// p }' options.def >argnames AS_ECHO(["-"]) | sed -n '1s/^-.*//p 1,/^-/d t clear :clear s/^-.*//p t s/^#.*// s/^ *// t next :next N s/\n-.*// t done s/\n#.*// s/\n */\n/g t next :done s/"/\\\\"/g s/[[^\n]][[^\n]]*/\\"&\\"/g s/^\n*// s/\n*$// s/\n\n*/ /g p ' options.def - >helptext exec 3expout while read opt <&3 && read arg <&4 && read help <&5; do if test ${arg:+y}; then AS_ECHO(["--$opt=$arg"]) >&6 else AS_ECHO(["--$opt"]) >&6 fi eval "set x $help"; shift for arg do AS_ECHO(["$arg"]) >&6 done done exec 3<&- 4<&- 5<&- 6>&- AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0], [expout], [ignore]) # test 2: short option string AT_DATA([test2.c], [[#include #include #include "context.h" #include "options.h" int main(void) { struct option lopts[] = {LOPTS_INITIALIZER}; unsigned i, j; for (i = 0; i < sizeof SOPT_STRING - 1; i++) { if (SOPT_STRING[i] != ':') { for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) { if (lopts[j].val == SOPT_STRING[i]) { printf("--%s ", lopts[j].name); break; } } } putchar(SOPT_STRING[i]); if (SOPT_STRING[i+1] != ':') putchar('\n'); } } ]]) sed -n '/^-/{ s/=.*/:/ s/[[@<:@]]/:/ s/^-\([[^-]]\)[[^:]]*/\1/p s/^-.*//p }' options.def >sopts exec 3expout while read lopt <&3 && read sopt <&4; do if test ${sopt:+y}; then AS_ECHO(["--$lopt $sopt"]) >&5 fi done exec 3<&- 4<&- 5>&- AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT], [0], [expout], [ignore]) # Check that all help strings are translatable sed 's/\([[^\\]]\\\)" /\1\\n\\" /g' helptext >help-po exec 3expected.po while read opt <&3 && read arg <&4 && read help <&5; do if test ${arg:+y}; then AS_ECHO(["msgctxt \"$opt\" msgid \"$arg\""]) >&6 fi AS_ECHO(["msgctxt \"$opt\" msgid${help:+ }$help"]) >&6 done exec 3<&- 4<&- 5<&- 6>&- AT_CHECK([xgettext --keyword=PN_:1c,2 options.h test -f messages.po || exit 77]) LC_ALL=C sort expected.po >expout AT_CHECK([sed -n '/^msgctxt/{ t next :next N s/\nmsgstr.*// t done s/\s*""// s/\n/ / t next :done p }' messages.po | LC_ALL=C sort], [0], [expout]) AT_CLEANUP AT_SETUP([gen-strtab.awk]) AT_DATA([test.def], [[ &a world &b hello world &c hello world &d world\n &e \\not a newline &f \not a newline &g inline continued &h no\ newline\ &i \ leading whitespace &j oneline # with a comment ]]) AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" test.h]) sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers # test 0: sanity test AT_DATA([test0.c], [[#include "test.h" #include int main(void) { printf("---\n"); ]]) exec 3>test0.c while read ident <&3; do AS_ECHO([' printf("%s\n---\n", '"strtab+$ident);"]) >&4 done AS_ECHO([' return 0;']) >&4 AS_ECHO(['}']) >&4 exec 3<&- 4>&- AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [--- world --- hello world --- hello world --- world --- \not a newline --- ot a newline --- inline continued --- nonewline --- leading whitespace --- oneline --- ], [ignore]) AT_CLEANUP