1 /* $NetBSD: main1.c,v 1.85 2026/01/20 23:46:36 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.85 2026/01/20 23:46:36 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 "typedef long double __float128;\n" 91 92 "void *alloca(__lint_size_t);\n" 93 "void *__builtin_alloca(__lint_size_t);\n" 94 "void *__builtin_alloca_with_align" 95 "(__lint_size_t, __lint_size_t);\n" 96 "void *__builtin_alloca_with_align_and_max" 97 "(__lint_size_t, __lint_size_t, __lint_size_t);\n" 98 99 "int __builtin_isinf(long double);\n" 100 "int __builtin_isnan(long double);\n" 101 "int __builtin_copysign(long double, long double);\n"; 102 size_t builtins_len = sizeof(builtins) - 1; 103 104 #if HAVE_NBTOOL_CONFIG_H 105 char template[] = "/tmp/lint.XXXXXX"; 106 int fd; 107 FILE *fp; 108 if ((fd = mkstemp(template)) == -1) 109 return NULL; 110 (void)unlink(template); 111 if ((fp = fdopen(fd, "r+")) == NULL) { 112 (void)close(fd); 113 return NULL; 114 } 115 if (fwrite(builtins, 1, builtins_len, fp) != builtins_len) { 116 (void)fclose(fp); 117 return NULL; 118 } 119 rewind(fp); 120 return fp; 121 #else 122 return fmemopen(__UNCONST(builtins), builtins_len, "r"); 123 #endif 124 } 125 126 /*ARGSUSED*/ 127 static void 128 sigfpe(int s) 129 { 130 fpe = 1; 131 } 132 133 int 134 main(int argc, char *argv[]) 135 { 136 int c; 137 138 setlocale(LC_ALL, ""); 139 setprogname(argv[0]); 140 141 while ((c = getopt(argc, argv, "abceghpq:rstvwyzA:FPR:STX:")) != -1) { 142 switch (c) { 143 case 'a': aflag++; break; 144 case 'b': bflag = true; break; 145 case 'c': cflag = true; break; 146 case 'e': eflag = true; break; 147 case 'F': Fflag = true; break; 148 case 'g': allow_gcc = true; break; 149 case 'h': hflag = true; break; 150 case 'p': pflag = true; break; 151 case 'P': Pflag = true; break; 152 case 'q': enable_queries(optarg); break; 153 case 'r': rflag = true; break; 154 case 's': 155 allow_trad = false; 156 allow_c90 = true; 157 allow_c99 = false; 158 allow_c11 = false; 159 allow_c23 = false; 160 break; 161 case 'S': 162 allow_trad = false; 163 allow_c90 = true; 164 allow_c99 = true; 165 allow_c11 = false; 166 allow_c23 = false; 167 break; 168 case 'T': Tflag = true; break; 169 case 't': 170 allow_trad = true; 171 allow_c90 = false; 172 allow_c99 = false; 173 allow_c11 = false; 174 allow_c23 = false; 175 break; 176 case 'w': wflag = true; break; 177 case 'v': vflag = true; break; 178 case 'y': yflag = true; break; 179 case 'z': zflag = true; break; 180 181 case 'A': 182 if (strcmp(optarg, "c23") == 0) { 183 allow_trad = false; 184 allow_c90 = true; 185 allow_c99 = true; 186 allow_c11 = true; 187 allow_c23 = true; 188 } else if (strcmp(optarg, "c11") == 0) { 189 allow_trad = false; 190 allow_c90 = true; 191 allow_c99 = true; 192 allow_c11 = true; 193 allow_c23 = false; 194 } else 195 usage(); 196 break; 197 198 case 'R': 199 add_directory_replacement(optarg); 200 break; 201 202 case 'X': 203 suppress_messages(optarg); 204 break; 205 default: 206 usage(); 207 } 208 } 209 argc -= optind; 210 argv += optind; 211 212 if (argc != 2) 213 usage(); 214 215 /* initialize output */ 216 outopen(argv[1]); 217 218 (void)signal(SIGFPE, sigfpe); 219 init_decl(); 220 init_lex(); 221 222 if (allow_gcc && allow_c90) { 223 if ((yyin = gcc_builtins()) == NULL) 224 err(1, "cannot open builtins"); 225 curr_pos.p_file = "<gcc-builtins>"; 226 curr_pos.p_line = 0; 227 lex_next_line(); 228 yyparse(); 229 (void)fclose(yyin); 230 } 231 232 #ifdef DEBUG 233 debug_enabled = true; 234 setvbuf(stdout, NULL, _IONBF, 0); 235 #endif 236 #if YYDEBUG 237 if (yflag) 238 yydebug = 1; 239 #endif 240 241 /* open the input file */ 242 if ((yyin = fopen(argv[0], "r")) == NULL) 243 err(1, "cannot open '%s'", argv[0]); 244 curr_pos.p_file = argv[0]; 245 curr_pos.p_line = 0; 246 lex_next_line(); 247 yyparse(); 248 (void)fclose(yyin); 249 250 /* Following warnings cannot be suppressed by LINTED */ 251 lwarn = LWARN_ALL; 252 debug_step("main lwarn = %d", lwarn); 253 254 end_translation_unit(); 255 256 outclose(); 257 258 return seen_error || (wflag && seen_warning) ? 1 : 0; 259 } 260 261 static void __dead 262 usage(void) 263 { 264 (void)fprintf(stderr, 265 "usage: %s [-abceghmprstvwyzFPST] [-Alevel] [-d directory] " 266 "[-R old=new]\n" 267 " %*s [-X id,...] [-q id,...] src dest\n", 268 getprogname(), (int)strlen(getprogname()), ""); 269 exit(1); 270 } 271 272 void __dead 273 norecover(void) 274 { 275 /* cannot recover from previous errors */ 276 error(224); 277 exit(1); 278 } 279