diff options
| -rw-r--r-- | regress/lib/libc/Makefile | 4 | ||||
| -rw-r--r-- | regress/lib/libc/getopt/Makefile | 10 | ||||
| -rw-r--r-- | regress/lib/libc/getopt/getopt-test.c | 59 | ||||
| -rw-r--r-- | regress/lib/libc/getopt/getopt.sh | 103 |
4 files changed, 174 insertions, 2 deletions
diff --git a/regress/lib/libc/Makefile b/regress/lib/libc/Makefile index b1a55f1c1f2..3d0712f951e 100644 --- a/regress/lib/libc/Makefile +++ b/regress/lib/libc/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.54 2020/01/13 15:35:57 bluhm Exp $ +# $OpenBSD: Makefile,v 1.55 2020/03/23 03:01:21 schwarze Exp $ SUBDIR+= _setjmp SUBDIR+= alloca arc4random-fork atexit @@ -7,7 +7,7 @@ SUBDIR+= cephes cxa-atexit SUBDIR+= db dirname SUBDIR+= env explicit_bzero SUBDIR+= fmemopen fnmatch fpclassify fread -SUBDIR+= gcvt getaddrinfo getcap getopt_long glob +SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob SUBDIR+= hsearch SUBDIR+= ieeefp ifnameindex SUBDIR+= ldexp locale longjmp diff --git a/regress/lib/libc/getopt/Makefile b/regress/lib/libc/getopt/Makefile new file mode 100644 index 00000000000..bdafc965fe5 --- /dev/null +++ b/regress/lib/libc/getopt/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1 2020/03/23 03:01:21 schwarze Exp $ + +REGRESS_TARGETS = getopt +PROG = getopt-test +MAN = + +getopt: ${PROG} + sh ${.CURDIR}/getopt.sh + +.include <bsd.regress.mk> diff --git a/regress/lib/libc/getopt/getopt-test.c b/regress/lib/libc/getopt/getopt-test.c new file mode 100644 index 00000000000..40901dcfcfc --- /dev/null +++ b/regress/lib/libc/getopt/getopt-test.c @@ -0,0 +1,59 @@ +/* $OpenBSD: getopt-test.c,v 1.1 2020/03/23 03:01:21 schwarze Exp $ */ +/* + * Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +/* + * Process command line options and arguments according to the + * optstring in the environment variable OPTS. Write: + * OPT(c) for an option "-c" without an option argument + * OPT(carg) for an option "-c" with an option argument "arg" + * ARG(arg) for a non-option argument "arg" + * NONE(arg) for a non-option argument "arg" processed with OPTS =~ ^- + * ERR(?c) for an invalid option "-c", or one lacking an argument + * ERR(:c) for an option "-c" lacking an argument while OPTS =~ ^: + */ +int +main(int argc, char *argv[]) +{ + char *optstring; + int ch; + + if ((optstring = getenv("OPTS")) == NULL) + optstring = ""; + + opterr = 0; + while ((ch = getopt(argc, argv, optstring)) != -1) { + switch (ch) { + case '\1': + printf("NONE(%s)", optarg); + break; + case ':': + case '?': + printf("ERR(%c%c)", ch, optopt); + break; + default: + printf("OPT(%c%s)", ch, optarg == NULL ? "" : optarg); + break; + } + } + while (optind < argc) + printf("ARG(%s)", argv[optind++]); + putchar('\n'); + return 0; +} diff --git a/regress/lib/libc/getopt/getopt.sh b/regress/lib/libc/getopt/getopt.sh new file mode 100644 index 00000000000..97668fc262c --- /dev/null +++ b/regress/lib/libc/getopt/getopt.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# +# $OpenBSD: getopt.sh,v 1.1 2020/03/23 03:01:21 schwarze Exp $ +# +# Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# Run ./getopt-test once. +# Function arguments: +# 1. optstring argument for getopt(3) +# 2. space-separated command line arguments +# 3. expected output from ./getopt-test +test1_getopt() +{ + result=$(OPTS=$1 ./getopt-test $2) + test "$result" == "$3" && return + echo "OPTS=$1 ./getopt-test $2" + echo "expected: $3" + echo "result: $result" + irc=1 +} + +# Test both without and with the optstring modifier "+", +# verifying that it makes no difference. +test2_getopt() +{ + test1_getopt "$1" "$2" "$3" + test1_getopt "+$1" "$2" "$3" +} + +# Also test with the GNU "-" optstring modifier, +# veryfying that it only changes ARG() to NONE(). +# This test function is inadequate in two situations: +# a) options follow non-option arguments that terminate option processing +# b) or any arguments follow explicit "--". +# In these cases, use test2_getopt() plus a separate test1_getopt(-...). +test3_getopt() +{ + test2_getopt "$1" "$2" "$3" + test1_getopt "-$1" "$2" $(echo $3 | sed s/ARG/NONE/g) +} + +irc=0 + +# isolated options without arguments +test3_getopt ax '-a -x arg' 'OPT(a)OPT(x)ARG(arg)' +test3_getopt ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)' +test1_getopt :ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)' + +# grouped options without arguments +test3_getopt ax '-ax arg' 'OPT(a)OPT(x)ARG(arg)' +test3_getopt ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)' +test1_getopt :ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)' + +# non-option arguments terminating option processing +test2_getopt ax '-a arg -x' 'OPT(a)ARG(arg)ARG(-x)' +test1_getopt -ax '-a arg1 -x arg2' 'OPT(a)NONE(arg1)OPT(x)NONE(arg2)' +test2_getopt ax '-a -- -x' 'OPT(a)ARG(-x)' +test1_getopt -ax '-a -- -x' 'OPT(a)ARG(-x)' +test2_getopt ax '-a - -x' 'OPT(a)ARG(-)ARG(-x)' +test1_getopt -ax '-a - -x arg' 'OPT(a)NONE(-)OPT(x)NONE(arg)' + +# the '-' option only works when isolated +test3_getopt a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)' +test1_getopt :a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)' +test1_getopt --a '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)NONE(arg)' +test3_getopt ax '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)' +test3_getopt a-x '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)' + +# the ':' option never works +test1_getopt ::a '-:a arg' 'ERR(?:)OPT(a)ARG(arg)' +test1_getopt :::a '-: arg -a' 'ERR(?:)ARG(arg)ARG(-a)' + +# isolated options with arguments +test3_getopt o: '-o' 'ERR(?o)' +test1_getopt :o: '-o' 'ERR(:o)' +test3_getopt o:x '-o arg -x arg' 'OPT(oarg)OPT(x)ARG(arg)' +test3_getopt o::x '-oarg -x arg' 'OPT(oarg)OPT(x)ARG(arg)' +test2_getopt o::x '-o arg -x' 'OPT(o)ARG(arg)ARG(-x)' +test1_getopt -o::x '-o arg1 -x arg2' 'OPT(o)NONE(arg1)OPT(x)NONE(arg2)' +test3_getopt o:x '-o -- -x arg' 'OPT(o--)OPT(x)ARG(arg)' + +# grouped options with arguments +test3_getopt ao: '-ao' 'OPT(a)ERR(?o)' +test1_getopt :ao: '-ao' 'OPT(a)ERR(:o)' +test3_getopt ao:x '-ao arg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)' +test3_getopt ao::x '-aoarg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)' +test2_getopt ao::x '-ao arg -x' 'OPT(a)OPT(o)ARG(arg)ARG(-x)' +test1_getopt -ao::x '-ao arg1 -x arg2' 'OPT(a)OPT(o)NONE(arg1)OPT(x)NONE(arg2)' +test3_getopt ao:x '-ao -- -x arg' 'OPT(a)OPT(o--)OPT(x)ARG(arg)' + +exit $irc |
