1 /* $NetBSD: main1.c,v 1.84 2024/09/24 19:58:06 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.84 2024/09/24 19:58:06 rillig Exp $"); 41 #endif 42 43 #include <sys/types.h> 44 #include <locale.h> 45 #include <signal.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 51 #include "lint1.h" 52 53 int aflag; 54 bool bflag; 55 bool cflag; 56 bool eflag; 57 bool Fflag; 58 bool hflag; 59 bool Pflag; 60 bool pflag; 61 bool rflag; 62 bool Tflag; 63 bool vflag; 64 bool wflag; 65 bool yflag; 66 bool zflag; 67 68 /* 69 * The default language level is the one that checks for compatibility 70 * between traditional C and C90. As of 2022, this default is no longer 71 * useful since most traditional C code has already been migrated. 72 */ 73 bool allow_trad = true; 74 bool allow_c90 = true; 75 bool allow_c99; 76 bool allow_c11; 77 bool allow_c23; 78 bool allow_gcc; 79 80 sig_atomic_t fpe; 81 82 static void usage(void); 83 84 static FILE * 85 gcc_builtins(void) 86 { 87 /* https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ 88 static const char builtins[] = 89 "typedef typeof(sizeof(0)) __lint_size_t;\n" 90 91 "void *alloca(__lint_size_t);\n" 92 "void *__builtin_alloca(__lint_size_t);\n" 93 "void *__builtin_alloca_with_align" 94 "(__lint_size_t, __lint_size_t);\n" 95 "void *__builtin_alloca_with_align_and_max" 96 "(__lint_size_t, __lint_size_t, __lint_size_t);\n" 97 98 "int __builtin_isinf(long double);\n" 99 "int __builtin_isnan(long double);\n" 100 "int __builtin_copysign(long double, long double);\n"; 101 size_t builtins_len = sizeof(builtins) - 1; 102 103 #if HAVE_NBTOOL_CONFIG_H 104 char template[] = "/tmp/lint.XXXXXX"; 105 int fd; 106 FILE *fp; 107 if ((fd = mkstemp(template)) == -1) 108 return NULL; 109 (void)unlink(template); 110 if ((fp = fdopen(fd, "r+")) == NULL) { 111 (void)close(fd); 112 return NULL; 113 } 114 if (fwrite(builtins, 1, builtins_len, fp) != builtins_len) { 115 (void)fclose(fp); 116 return NULL; 117 } 118 rewind(fp); 119 return fp; 120 #else 121 return fmemopen(__UNCONST(builtins), builtins_len, "r"); 122 #endif 123 } 124 125 /*ARGSUSED*/ 126 static void 127 sigfpe(int s) 128 { 129 fpe = 1; 130 } 131 132 int 133 main(int argc, char *argv[]) 134 { 135 int c; 136 137 setlocale(LC_ALL, ""); 138 setprogname(argv[0]); 139 140 while ((c = getopt(argc, argv, "abceghpq:rstvwyzA:FPR:STX:")) != -1) { 141 switch (c) { 142 case 'a': aflag++; break; 143 case 'b': bflag = true; break; 144 case 'c': cflag = true; break; 145 case 'e': eflag = true; break; 146 case 'F': Fflag = true; break; 147 case 'g': allow_gcc = true; break; 148 case 'h': hflag = true; break; 149 case 'p': pflag = true; break; 150 case 'P': Pflag = true; break; 151 case 'q': enable_queries(optarg); break; 152 case 'r': rflag = true; break; 153 case 's': 154 allow_trad = false; 155 allow_c90 = true; 156 allow_c99 = false; 157 allow_c11 = false; 158 allow_c23 = false; 159 break; 160 case 'S': 161 allow_trad = false; 162 allow_c90 = true; 163 allow_c99 = true; 164 allow_c11 = false; 165 allow_c23 = false; 166 break; 167 case 'T': Tflag = true; break; 168 case 't': 169 allow_trad = true; 170 allow_c90 = false; 171 allow_c99 = false; 172 allow_c11 = false; 173 allow_c23 = false; 174 break; 175 case 'w': wflag = true; break; 176 case 'v': vflag = true; break; 177 case 'y': yflag = true; break; 178 case 'z': zflag = true; break; 179 180 case 'A': 181 if (strcmp(optarg, "c23") == 0) { 182 allow_trad = false; 183 allow_c90 = true; 184 allow_c99 = true; 185 allow_c11 = true; 186 allow_c23 = true; 187 } else if (strcmp(optarg, "c11") == 0) { 188 allow_trad = false; 189 allow_c90 = true; 190 allow_c99 = true; 191 allow_c11 = true; 192 allow_c23 = false; 193 } else 194 usage(); 195 break; 196 197 case 'R': 198 add_directory_replacement(optarg); 199 break; 200 201 case 'X': 202 suppress_messages(optarg); 203 break; 204 default: 205 usage(); 206 } 207 } 208 argc -= optind; 209 argv += optind; 210 211 if (argc != 2) 212 usage(); 213 214 /* initialize output */ 215 outopen(argv[1]); 216 217 (void)signal(SIGFPE, sigfpe); 218 init_decl(); 219 init_lex(); 220 221 if (allow_gcc && allow_c90) { 222 if ((yyin = gcc_builtins()) == NULL) 223 err(1, "cannot open builtins"); 224 curr_pos.p_file = "<gcc-builtins>"; 225 curr_pos.p_line = 0; 226 lex_next_line(); 227 yyparse(); 228 (void)fclose(yyin); 229 } 230 231 #ifdef DEBUG 232 debug_enabled = true; 233 setvbuf(stdout, NULL, _IONBF, 0); 234 #endif 235 #if YYDEBUG 236 if (yflag) 237 yydebug = 1; 238 #endif 239 240 /* open the input file */ 241 if ((yyin = fopen(argv[0], "r")) == NULL) 242 err(1, "cannot open '%s'", argv[0]); 243 curr_pos.p_file = argv[0]; 244 curr_pos.p_line = 0; 245 lex_next_line(); 246 yyparse(); 247 (void)fclose(yyin); 248 249 /* Following warnings cannot be suppressed by LINTED */ 250 lwarn = LWARN_ALL; 251 debug_step("main lwarn = %d", lwarn); 252 253 end_translation_unit(); 254 255 outclose(); 256 257 return seen_error || (wflag && seen_warning) ? 1 : 0; 258 } 259 260 static void __dead 261 usage(void) 262 { 263 (void)fprintf(stderr, 264 "usage: %s [-abceghmprstvwyzFPST] [-Alevel] [-d directory] " 265 "[-R old=new]\n" 266 " %*s [-X id,...] [-q id,...] src dest\n", 267 getprogname(), (int)strlen(getprogname()), ""); 268 exit(1); 269 } 270 271 void __dead 272 norecover(void) 273 { 274 /* cannot recover from previous errors */ 275 error(224); 276 exit(1); 277 } 278