1 /* $NetBSD: main1.c,v 1.77 2023/07/29 10:45:00 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.77 2023/07/29 10:45:00 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 int aflag; 53 bool bflag; 54 bool cflag; 55 bool eflag; 56 bool Fflag; 57 bool hflag; 58 bool Pflag; 59 bool pflag; 60 bool rflag; 61 bool Tflag; 62 bool uflag; 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 setprogname(argv[0]); 138 139 while ((c = getopt(argc, argv, "abceghpq:rstuvwyzA:FPR:STX:")) != -1) { 140 switch (c) { 141 case 'a': aflag++; break; 142 case 'b': bflag = true; break; 143 case 'c': cflag = true; break; 144 case 'e': eflag = true; break; 145 case 'F': Fflag = true; break; 146 case 'g': allow_gcc = true; break; 147 case 'h': hflag = true; break; 148 case 'p': pflag = true; break; 149 case 'P': Pflag = true; break; 150 case 'q': enable_queries(optarg); break; 151 case 'r': rflag = true; break; 152 case 's': 153 allow_trad = false; 154 allow_c90 = true; 155 allow_c99 = false; 156 allow_c11 = false; 157 allow_c23 = false; 158 break; 159 case 'S': 160 allow_trad = false; 161 allow_c90 = true; 162 allow_c99 = true; 163 allow_c11 = false; 164 allow_c23 = false; 165 break; 166 case 'T': Tflag = true; break; 167 case 't': 168 allow_trad = true; 169 allow_c90 = false; 170 allow_c99 = false; 171 allow_c11 = false; 172 allow_c23 = false; 173 break; 174 case 'u': uflag = true; 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 215 /* initialize output */ 216 outopen(any_query_enabled ? "/dev/null" : argv[1]); 217 218 #ifdef DEBUG 219 setvbuf(stdout, NULL, _IONBF, 0); 220 #endif 221 #if YYDEBUG 222 if (yflag) 223 yydebug = 1; 224 #endif 225 226 (void)signal(SIGFPE, sigfpe); 227 initdecl(); 228 initscan(); 229 230 if (allow_gcc && allow_c90) { 231 if ((yyin = gcc_builtins()) == NULL) 232 err(1, "cannot open builtins"); 233 curr_pos.p_file = "<gcc-builtins>"; 234 curr_pos.p_line = 0; 235 lex_next_line(); 236 yyparse(); 237 (void)fclose(yyin); 238 } 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 [-abceghmprstuvwyzFPST] [-Alevel] [-ddirectory] " 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