xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_338.c (revision b2baa50111d645353fa30b4deab0f79d93650c8c)
1 /*	$NetBSD: msg_338.c,v 1.9 2023/03/28 14:44:35 rillig Exp $	*/
2 # 3 "msg_338.c"
3 
4 // Test for message: option '%c' should be handled in the switch [338]
5 
6 /* lint1-extra-flags: -X 351 */
7 
8 int getopt(int, char *const *, const char *);
9 extern char *optarg;
10 
11 int
main(int argc,char ** argv)12 main(int argc, char **argv)
13 {
14 	int o;
15 
16 	/* expect+2: warning: option 'c' should be handled in the switch [338] */
17 	/* expect+1: warning: option 'd' should be handled in the switch [338] */
18 	while ((o = getopt(argc, argv, "a:bc:d")) != -1) {
19 		switch (o) {
20 		case 'a':
21 			break;
22 		case 'b':
23 			/*
24 			 * The following while loop must not finish the check
25 			 * for the getopt options.
26 			 */
27 			while (optarg[0] != '\0')
28 				optarg++;
29 			break;
30 		case 'e':
31 			/* expect-1: warning: option 'e' should be listed in the options string [339] */
32 			break;
33 		case 'f':
34 			/* expect-1: warning: option 'f' should be listed in the options string [339] */
35 			/*
36 			 * The case labels in nested switch statements are
37 			 * ignored by the check for getopt options.
38 			 */
39 			switch (optarg[0]) {
40 			case 'X':
41 				break;
42 			}
43 			break;
44 		case '?':
45 		default:
46 			break;
47 		}
48 	}
49 
50 	/* A while loop that is not related to getopt is simply skipped. */
51 	while (o != 0) {
52 		switch (o) {
53 		case '?':
54 			o = ':';
55 		}
56 	}
57 
58 	return 0;
59 }
60 
61 void usage(void);
62 
63 /*
64  * Before ckgetopt.c 1.11 from 2021-08-23, lint wrongly warned about a
65  * missing '?' in the switch statement, even though it was there.
66  *
67  * Seen in usr.bin/ftp/main.c 1.127 from 2020-07-18.
68  */
69 int
question_option(int argc,char ** argv)70 question_option(int argc, char **argv)
71 {
72 	int c;
73 
74 	while ((c = getopt(argc, argv, "?x")) != -1) {
75 		switch (c) {
76 		case 'x':
77 			break;
78 		case '?':
79 			usage();
80 			return 0;
81 		default:
82 			usage();
83 			return 1;
84 		}
85 	}
86 	return 0;
87 }
88 
89 /*
90  * If the first character of the options string is ':', getopt does not print
91  * its own error messages. Getopt returns ':' if an option is missing its
92  * argument; that is handled by the 'default:' already.
93  */
94 int
suppress_errors(int argc,char ** argv)95 suppress_errors(int argc, char **argv)
96 {
97 	int c;
98 
99 	/* expect+1: warning: option 'o' should be handled in the switch [338] */
100 	while ((c = getopt(argc, argv, ":b:o")) != -1) {
101 		switch (c) {
102 		case 'b':
103 			return 'b';
104 		default:
105 			usage();
106 		}
107 	}
108 	return 0;
109 }
110 
111 /*
112  * If the first character of the options string is ':', getopt returns ':'
113  * if an option is missing its argument. This condition can be handled
114  * separately from '?', which getopt returns for unknown options.
115  */
116 int
missing_argument(int argc,char ** argv)117 missing_argument(int argc, char **argv)
118 {
119 	int c;
120 
121 	/* expect+1: warning: option 'o' should be handled in the switch [338] */
122 	while ((c = getopt(argc, argv, ":b:o")) != -1) {
123 		switch (c) {
124 		case 'b':
125 			return 'b';
126 		case ':':
127 			return 'm';
128 		default:
129 			usage();
130 		}
131 	}
132 	return 0;
133 }
134 
135 /*
136  * Getopt only returns ':' if ':' is the first character in the options
137  * string. Everywhere else, a ':' marks the preceding option as having a
138  * required argument. In theory, if the options string contained "a::x",
139  * that could be interpreted as '-a argument', followed by '-:' and '-x',
140  * but nobody does that.
141  */
142 int
unreachable_colon(int argc,char ** argv)143 unreachable_colon(int argc, char **argv)
144 {
145 	int c;
146 
147 	/* expect+1: warning: option 'b' should be handled in the switch [338] */
148 	while ((c = getopt(argc, argv, "b:")) != -1) {
149 		switch (c) {
150 		/* expect+1: warning: option ':' should be listed in the options string [339] */
151 		case ':':
152 			return 'm';
153 		default:
154 			usage();
155 		}
156 	}
157 	return 0;
158 }
159