root/tests/usr.bin/xlint/lint1/msg_338.c
/*      $NetBSD: msg_338.c,v 1.10 2025/02/27 22:37:37 rillig Exp $      */
# 3 "msg_338.c"

// Test for message: option '%c' should be handled in the switch [338]

/* lint1-extra-flags: -X 351 */

int getopt(int, char *const *, const char *);
extern char *optarg;

int
main(int argc, char **argv)
{
        int o;

        /* expect+2: warning: option 'c' should be handled in the switch [338] */
        /* expect+1: warning: option 'd' should be handled in the switch [338] */
        while ((o = getopt(argc, argv, "a:bc:d")) != -1) {
                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-1: warning: option 'e' should be listed in the options string [339] */
                        break;
                case 'f':
                        /* expect-1: warning: option 'f' should be listed in the options string [339] */
                        /*
                         * 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;
                }
        }

        /* A while loop that is not related to getopt is simply skipped. */
        while (o != 0) {
                switch (o) {
                case '?':
                        o = ':';
                }
        }

        return 0;
}

void usage(void);

/*
 * Before ckgetopt.c 1.11 from 2021-08-23, lint wrongly warned about a
 * missing '?' in the switch statement, even though it was there.
 *
 * Seen in usr.bin/ftp/main.c 1.127 from 2020-07-18.
 */
int
question_option(int argc, char **argv)
{
        int c;

        while ((c = getopt(argc, argv, "?x")) != -1) {
                switch (c) {
                case 'x':
                        break;
                case '?':
                        usage();
                        return 0;
                default:
                        usage();
                        return 1;
                }
        }
        return 0;
}

/*
 * If the first character of the options string is ':', getopt does not print
 * its own error messages. Getopt returns ':' if an option is missing its
 * argument; that is handled by the 'default:' already.
 */
int
suppress_errors(int argc, char **argv)
{
        int c;

        /* expect+1: warning: option 'o' should be handled in the switch [338] */
        while ((c = getopt(argc, argv, ":b:o")) != -1) {
                switch (c) {
                case 'b':
                        return 'b';
                default:
                        usage();
                }
        }
        return 0;
}

/*
 * If the first character of the options string is ':', getopt returns ':'
 * if an option is missing its argument. This condition can be handled
 * separately from '?', which getopt returns for unknown options.
 */
int
missing_argument(int argc, char **argv)
{
        int c;

        /* expect+1: warning: option 'o' should be handled in the switch [338] */
        while ((c = getopt(argc, argv, ":b:o")) != -1) {
                switch (c) {
                case 'b':
                        return 'b';
                case ':':
                        return 'm';
                default:
                        usage();
                }
        }
        return 0;
}

/*
 * Getopt only returns ':' if ':' is the first character in the options
 * string. Everywhere else, a ':' marks the preceding option as having a
 * required argument. In theory, if the options string contained "a::x",
 * that could be interpreted as '-a argument', followed by '-:' and '-x',
 * but nobody does that.
 */
int
unreachable_colon(int argc, char **argv)
{
        int c;

        /* expect+1: warning: option 'b' should be handled in the switch [338] */
        while ((c = getopt(argc, argv, "b:")) != -1) {
                switch (c) {
                /* expect+1: warning: option ':' should be listed in the options string [339] */
                case ':':
                        return 'm';
                default:
                        usage();
                }
        }
        return 0;
}

void
suppressed_warning(int argc, char **argv)
{
        int c;

        /* expect+2: warning: option 'a' should be handled in the switch [338] */
        /* expect+1: warning: option 'b' should be handled in the switch [338] */
        while ((c = getopt(argc, argv, "ab")) != -1) {
                switch (c) {
                }
        }
        /* LINTED 338 */
        while ((c = getopt(argc, argv, "ab")) != -1) {
                switch (c) {
                }
        }
        /* expect+2: warning: option 'a' should be handled in the switch [338] */
        /* expect+1: warning: option 'b' should be handled in the switch [338] */
        while ((c = getopt(argc, argv, "ab")) != -1) {
                switch (c) {
                }
        }
}