Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: warn about mismatch in getopt hand...



details:   https://anonhg.NetBSD.org/src/rev/f543450d7d1c
branches:  trunk
changeset: 952828:f543450d7d1c
user:      rillig <rillig%NetBSD.org@localhost>
date:      Fri Feb 19 12:28:56 2021 +0000

description:
lint: warn about mismatch in getopt handling

diffstat:

 distrib/sets/lists/tests/mi                |    6 +-
 tests/usr.bin/xlint/lint1/Makefile         |    4 +-
 tests/usr.bin/xlint/lint1/msg_338.c        |   45 +++++++
 tests/usr.bin/xlint/lint1/msg_338.exp      |    4 +
 tests/usr.bin/xlint/lint1/msg_339.c        |   45 +++++++
 tests/usr.bin/xlint/lint1/msg_339.exp      |    4 +
 tests/usr.bin/xlint/lint1/t_integration.sh |    4 +-
 usr.bin/xlint/lint1/Makefile               |    6 +-
 usr.bin/xlint/lint1/ckgetopt.c             |  178 +++++++++++++++++++++++++++++
 usr.bin/xlint/lint1/err.c                  |    6 +-
 usr.bin/xlint/lint1/externs1.h             |   11 +-
 usr.bin/xlint/lint1/func.c                 |   13 +-
 12 files changed, 312 insertions(+), 14 deletions(-)

diffs (truncated from 482 to 300 lines):

diff -r 295b18d2e1fb -r f543450d7d1c distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Fri Feb 19 11:39:11 2021 +0000
+++ b/distrib/sets/lists/tests/mi       Fri Feb 19 12:28:56 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1019 2021/02/16 09:46:24 kre Exp $
+# $NetBSD: mi,v 1.1020 2021/02/19 12:28:56 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -6511,6 +6511,10 @@
 ./usr/tests/usr.bin/xlint/lint1/msg_336.exp                    tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_337.c                      tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_337.exp                    tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_338.c                      tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_338.exp                    tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_339.c                      tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_339.exp                    tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/t_integration                  tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/ztest                              tests-usr.bin-tests     compattestfile,atf
 ./usr/tests/usr.bin/ztest/Atffile                      tests-usr.bin-tests     compattestfile,atf
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/Makefile
--- a/tests/usr.bin/xlint/lint1/Makefile        Fri Feb 19 11:39:11 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/Makefile        Fri Feb 19 12:28:56 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.30 2021/01/17 23:00:41 rillig Exp $
+# $NetBSD: Makefile,v 1.31 2021/02/19 12:28:56 rillig Exp $
 
 NOMAN=         # defined
 
@@ -91,7 +91,7 @@
 FILES+=                d_typefun.c
 FILES+=                d_typename_as_var.c
 FILES+=                d_zero_sized_arrays.c
-FILES+=                ${:U0 ${:U:range=337}:C,^.$,0&,:C,^..$,0&,:@msg@msg_${msg}.c msg_${msg}.exp@}
+FILES+=                ${:U0 ${:U:range=339}:C,^.$,0&,:C,^..$,0&,:@msg@msg_${msg}.c msg_${msg}.exp@}
 
 # Note: only works for adding tests.
 # To remove a test, the $$mi file must be edited manually.
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/msg_338.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_338.c       Fri Feb 19 12:28:56 2021 +0000
@@ -0,0 +1,45 @@
+/*     $NetBSD: msg_338.c,v 1.1 2021/02/19 12:28:56 rillig Exp $       */
+# 3 "msg_338.c"
+
+// Test for message: option '%c' should be handled in the switch [338]
+
+int getopt(int, char *const *, const char *);
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       int o;
+
+       while ((o = getopt(argc, argv, "a:bc:d")) != -1) { /* expect: 338, 338 */
+               switch (o) {
+               case 'a':
+                       break;
+               case 'b':
+                       /*
+                        * The following while loop must not finish the check
+                        * for the getopt options.
+                        */
+                       while (optarg[0] != '\0')
+                               optarg++;
+                       break;
+               case 'e':       /* expect: option 'e' should be listed */
+                       break;
+               case 'f':       /* expect: option 'f' should be listed */
+                       /*
+                        * The case labels in nested switch statements are
+                        * ignored by the check for getopt options.
+                        */
+                       switch (optarg[0]) {
+                       case 'X':
+                               break;
+                       }
+                       break;
+               case '?':
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+}
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/msg_338.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_338.exp     Fri Feb 19 12:28:56 2021 +0000
@@ -0,0 +1,4 @@
+msg_338.c(26): warning: option 'e' should be listed in the options string [339]
+msg_338.c(28): warning: option 'f' should be listed in the options string [339]
+msg_338.c(14): warning: option 'c' should be handled in the switch [338]
+msg_338.c(14): warning: option 'd' should be handled in the switch [338]
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/msg_339.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_339.c       Fri Feb 19 12:28:56 2021 +0000
@@ -0,0 +1,45 @@
+/*     $NetBSD: msg_339.c,v 1.1 2021/02/19 12:28:56 rillig Exp $       */
+# 3 "msg_339.c"
+
+// Test for message: option '%c' should be listed in the options string [339]
+
+int getopt(int, char *const *, const char *);
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       int o;
+
+       while ((o = getopt(argc, argv, "a:bc:d")) != -1) { /* expect: 338, 338 */
+               switch (o) {
+               case 'a':
+                       break;
+               case 'b':
+                       /*
+                        * The following while loop must not finish the check
+                        * for the getopt options.
+                        */
+                       while (optarg[0] != '\0')
+                               optarg++;
+                       break;
+               case 'e':       /* expect: option 'e' should be listed */
+                       break;
+               case 'f':       /* expect: option 'f' should be listed */
+                       /*
+                        * The case labels in nested switch statements are
+                        * ignored by the check for getopt options.
+                        */
+                       switch (optarg[0]) {
+                       case 'X':
+                               break;
+                       }
+                       break;
+               case '?':
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+}
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/msg_339.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_339.exp     Fri Feb 19 12:28:56 2021 +0000
@@ -0,0 +1,4 @@
+msg_339.c(26): warning: option 'e' should be listed in the options string [339]
+msg_339.c(28): warning: option 'f' should be listed in the options string [339]
+msg_339.c(14): warning: option 'c' should be handled in the switch [338]
+msg_339.c(14): warning: option 'd' should be handled in the switch [338]
diff -r 295b18d2e1fb -r f543450d7d1c tests/usr.bin/xlint/lint1/t_integration.sh
--- a/tests/usr.bin/xlint/lint1/t_integration.sh        Fri Feb 19 11:39:11 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/t_integration.sh        Fri Feb 19 12:28:56 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: t_integration.sh,v 1.28 2021/01/18 20:02:34 rillig Exp $
+# $NetBSD: t_integration.sh,v 1.29 2021/02/19 12:28:56 rillig Exp $
 #
 # Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -184,7 +184,7 @@
        srcdir="$(atf_get_srcdir)"
        ok="true"
 
-       for msg in $(seq 0 337); do
+       for msg in $(seq 0 339); do
                base="$(printf '%s/msg_%03d' "${srcdir}" "${msg}")"
                flags="$(extract_flags "${base}.c")"
 
diff -r 295b18d2e1fb -r f543450d7d1c usr.bin/xlint/lint1/Makefile
--- a/usr.bin/xlint/lint1/Makefile      Fri Feb 19 11:39:11 2021 +0000
+++ b/usr.bin/xlint/lint1/Makefile      Fri Feb 19 12:28:56 2021 +0000
@@ -1,10 +1,10 @@
-#      $NetBSD: Makefile,v 1.59 2021/01/23 17:58:03 rillig Exp $
+#      $NetBSD: Makefile,v 1.60 2021/02/19 12:28:56 rillig Exp $
 
 .include <bsd.own.mk>
 
 PROG=          lint1
-SRCS=          cgram.y decl.c emit.c emit1.c err.c func.c init.c inittyp.c \
-               lex.c \
+SRCS=          cgram.y ckgetopt.c decl.c emit.c emit1.c err.c \
+               func.c init.c inittyp.c lex.c \
                main1.c mem.c mem1.c oper.c print.c scan.l tree.c tyname.c
 
 MAN=           lint.7
diff -r 295b18d2e1fb -r f543450d7d1c usr.bin/xlint/lint1/ckgetopt.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/xlint/lint1/ckgetopt.c    Fri Feb 19 12:28:56 2021 +0000
@@ -0,0 +1,178 @@
+/* $NetBSD: ckgetopt.c,v 1.1 2021/02/19 12:28:56 rillig Exp $ */
+
+/*-
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roland Illig <rillig%NetBSD.org@localhost>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: ckgetopt.c,v 1.1 2021/02/19 12:28:56 rillig Exp $");
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lint1.h"
+
+/*
+ * In a typical while loop for parsing getopt options, ensure that each
+ * option from the options string is handled, and that each handled option
+ * is listed in the options string.
+ */
+
+struct {
+       pos_t options_pos;
+       char *options;
+       char *unhandled_options;
+       int while_level;
+       int switch_level;
+} ck;
+
+
+static bool
+is_getopt_call(const tnode_t *tn, char **out_options)
+{
+       if (tn == NULL)
+               return false;
+       if (tn->tn_op != NE)
+               return false;
+       if (tn->tn_left->tn_op != ASSIGN)
+               return false;
+
+       const tnode_t *call = tn->tn_left->tn_right;
+       if (call->tn_op != CALL)
+               return false;
+       if (call->tn_left->tn_op != ADDR)
+               return false;
+       if (call->tn_left->tn_left->tn_op != NAME)
+               return false;
+       if (strcmp(call->tn_left->tn_left->tn_sym->s_name, "getopt") != 0)
+               return false;
+
+       if (call->tn_right->tn_op != PUSH)
+               return false;
+
+       const tnode_t *last_arg = call->tn_right->tn_left;
+       if (last_arg->tn_op != CVT)
+               return false;
+       if (last_arg->tn_left->tn_op != ADDR)
+               return false;
+       if (last_arg->tn_left->tn_left->tn_op != STRING)
+               return false;
+       if (last_arg->tn_left->tn_left->tn_string->st_tspec != CHAR)
+               return false;
+
+       *out_options = xstrdup(
+           (const char *)last_arg->tn_left->tn_left->tn_string->st_cp);
+       return true;
+}
+
+static void
+check_unlisted_option(char opt)
+{
+       if (opt == '?')
+               return;
+
+       const char *optptr = strchr(ck.options, opt);
+       if (optptr != NULL)
+               ck.unhandled_options[optptr - ck.options] = ' ';
+       else {
+               /* option '%c' should be listed in the options string */
+               warning(339, opt);
+               return;
+       }



Home | Main Index | Thread Index | Old Index