1 /* $NetBSD: main1.c,v 1.66 2023/01/13 19:41:50 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995 Jochen Pohl 5 * All Rights Reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jochen Pohl for 18 * The NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 #if defined(__RCSID) 40 __RCSID("$NetBSD: main1.c,v 1.66 2023/01/13 19:41:50 rillig Exp $"); 41 #endif 42 43 #include <sys/types.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "lint1.h" 51 52 /* set yydebug to 1*/ 53 bool yflag; 54 55 /* 56 * Print warnings if an assignment of an integer type to another integer type 57 * causes an implicit narrowing conversion. If aflag is 1, these warnings 58 * are printed only if the source type is at least as wide as long. If aflag 59 * is greater than 1, they are always printed. 60 */ 61 int aflag; 62 63 /* Print a warning if a break statement cannot be reached. */ 64 bool bflag; 65 66 /* Print warnings for pointer casts. */ 67 bool cflag; 68 69 /* Perform stricter checking of enum types and operations on enum types. */ 70 bool eflag; 71 72 /* Print complete pathnames, not only the basename. */ 73 bool Fflag; 74 75 /* Treat warnings as errors */ 76 bool wflag; 77 78 /* 79 * Apply a number of heuristic tests to attempt to intuit bugs, improve 80 * style, and reduce waste. 81 */ 82 bool hflag; 83 84 /* Attempt to check portability to other dialects of C. */ 85 bool pflag; 86 87 /* 88 * In case of redeclarations/redefinitions print the location of the 89 * previous declaration/definition. 90 */ 91 bool rflag; 92 93 bool Tflag; 94 95 /* Picky flag */ 96 bool Pflag; 97 98 /* 99 * Complain about functions and external variables used and not defined, 100 * or defined and not used. 101 */ 102 bool uflag = true; 103 104 /* Complain about unused function arguments. */ 105 bool vflag = true; 106 107 /* Complain about structures which are never defined. */ 108 bool zflag = true; 109 110 /* 111 * The default language level is the one that checks for compatibility 112 * between traditional C and C90. As of 2022, this default is no longer 113 * useful since most traditional C code has already been migrated. 114 */ 115 bool allow_trad = true; 116 bool allow_c90 = true; 117 bool allow_c99; 118 bool allow_c11; 119 bool allow_gcc; 120 121 sig_atomic_t fpe; 122 123 static void usage(void); 124 125 static FILE * 126 gcc_builtins(void) 127 { 128 /* https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ 129 static const char builtins[] = 130 "typedef typeof(sizeof(0)) __lint_size_t;\n" 131 132 "void *alloca(__lint_size_t);\n" 133 "void *__builtin_alloca(__lint_size_t);\n" 134 "void *__builtin_alloca_with_align" 135 "(__lint_size_t, __lint_size_t);\n" 136 "void *__builtin_alloca_with_align_and_max" 137 "(__lint_size_t, __lint_size_t, __lint_size_t);\n" 138 139 "int __builtin_isinf(long double);\n" 140 "int __builtin_isnan(long double);\n" 141 "int __builtin_copysign(long double, long double);\n"; 142 size_t builtins_len = sizeof(builtins) - 1; 143 144 #if HAVE_NBTOOL_CONFIG_H 145 char template[] = "/tmp/lint.XXXXXX"; 146 int fd; 147 FILE *fp; 148 if ((fd = mkstemp(template)) == -1) 149 return NULL; 150 (void)unlink(template); 151 if ((fp = fdopen(fd, "r+")) == NULL) { 152 (void)close(fd); 153 return NULL; 154 } 155 if (fwrite(builtins, 1, builtins_len, fp) != builtins_len) { 156 (void)fclose(fp); 157 return NULL; 158 } 159 rewind(fp); 160 return fp; 161 #else 162 return fmemopen(__UNCONST(builtins), builtins_len, "r"); 163 #endif 164 } 165 166 /*ARGSUSED*/ 167 static void 168 sigfpe(int s) 169 { 170 fpe = 1; 171 } 172 173 int 174 main(int argc, char *argv[]) 175 { 176 int c; 177 178 setprogname(argv[0]); 179 180 while ((c = getopt(argc, argv, "abceghmpq:rstuvwyzA:FPR:STX:")) != -1) { 181 switch (c) { 182 case 'a': aflag++; break; 183 case 'b': bflag = true; break; 184 case 'c': cflag = true; break; 185 case 'e': eflag = true; break; 186 case 'F': Fflag = true; break; 187 case 'g': allow_gcc = true; break; 188 case 'h': hflag = true; break; 189 case 'p': pflag = true; break; 190 case 'P': Pflag = true; break; 191 case 'q': enable_queries(optarg); break; 192 case 'r': rflag = true; break; 193 case 's': 194 allow_trad = false; 195 allow_c90 = true; 196 allow_c99 = false; 197 allow_c11 = false; 198 break; 199 case 'S': 200 allow_trad = false; 201 allow_c90 = true; 202 allow_c99 = true; 203 allow_c11 = false; 204 break; 205 case 'T': Tflag = true; break; 206 case 't': 207 allow_trad = true; 208 allow_c90 = false; 209 allow_c99 = false; 210 allow_c11 = false; 211 break; 212 case 'u': uflag = false; break; 213 case 'w': wflag = true; break; 214 case 'v': vflag = false; break; 215 case 'y': yflag = true; break; 216 case 'z': zflag = false; break; 217 218 case 'A': 219 if (strcmp(optarg, "c11") == 0) { 220 allow_trad = false; 221 allow_c90 = true; 222 allow_c99 = true; 223 allow_c11 = true; 224 } else 225 usage(); 226 break; 227 228 case 'm': 229 msglist(); 230 return 0; 231 232 case 'R': 233 add_directory_replacement(optarg); 234 break; 235 236 case 'X': 237 suppress_messages(optarg); 238 break; 239 default: 240 usage(); 241 } 242 } 243 argc -= optind; 244 argv += optind; 245 246 if (argc != 2) 247 usage(); 248 249 250 /* initialize output */ 251 outopen(any_query_enabled ? "/dev/null" : argv[1]); 252 253 #ifdef DEBUG 254 setvbuf(stdout, NULL, _IONBF, 0); 255 #endif 256 #ifdef YYDEBUG 257 if (yflag) 258 yydebug = 1; 259 #endif 260 261 (void)signal(SIGFPE, sigfpe); 262 initdecl(); 263 initscan(); 264 265 if (allow_gcc && allow_c90) { 266 if ((yyin = gcc_builtins()) == NULL) 267 err(1, "cannot open builtins"); 268 curr_pos.p_file = "<gcc-builtins>"; 269 curr_pos.p_line = 0; 270 lex_next_line(); 271 yyparse(); 272 (void)fclose(yyin); 273 } 274 275 /* open the input file */ 276 if ((yyin = fopen(argv[0], "r")) == NULL) 277 err(1, "cannot open '%s'", argv[0]); 278 curr_pos.p_file = argv[0]; 279 curr_pos.p_line = 0; 280 lex_next_line(); 281 yyparse(); 282 (void)fclose(yyin); 283 284 /* Following warnings cannot be suppressed by LINTED */ 285 lwarn = LWARN_ALL; 286 debug_step("main lwarn = %d", lwarn); 287 288 check_global_symbols(); 289 290 outclose(); 291 292 return nerr != 0 ? 1 : 0; 293 } 294 295 static void __attribute__((noreturn)) 296 usage(void) 297 { 298 (void)fprintf(stderr, 299 "usage: %s [-abceghmprstuvwyzFPST] [-Ac11] [-R old=new]\n" 300 " %*s [-X <id>[,<id>]...] src dest\n", 301 getprogname(), (int)strlen(getprogname()), ""); 302 exit(1); 303 } 304 305 void __attribute__((noreturn)) 306 norecover(void) 307 { 308 /* cannot recover from previous errors */ 309 error(224); 310 exit(1); 311 } 312