1/* $NetBSD: main1.c,v 1.83 2024/05/12 18:00:58 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.83 2024/05/12 18:00:58 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 53int aflag; 54bool bflag; 55bool cflag; 56bool eflag; 57bool Fflag; 58bool hflag; 59bool Pflag; 60bool pflag; 61bool rflag; 62bool Tflag; 63bool vflag; 64bool wflag; 65bool yflag; 66bool 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 */ 73bool allow_trad = true; 74bool allow_c90 = true; 75bool allow_c99; 76bool allow_c11; 77bool allow_c23; 78bool allow_gcc; 79 80sig_atomic_t fpe; 81 82static void usage(void); 83 84static FILE * 85gcc_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*/ 126static void 127sigfpe(int s) 128{ 129 fpe = 1; 130} 131 132int 133main(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#ifdef DEBUG 218 setvbuf(stdout, NULL, _IONBF, 0); 219#endif 220#if YYDEBUG 221 if (yflag) 222 yydebug = 1; 223#endif 224 225 (void)signal(SIGFPE, sigfpe); 226 init_decl(); 227 init_lex(); 228 229 if (allow_gcc && allow_c90) { 230 if ((yyin = gcc_builtins()) == NULL) 231 err(1, "cannot open builtins"); 232 curr_pos.p_file = "<gcc-builtins>"; 233 curr_pos.p_line = 0; 234 lex_next_line(); 235 yyparse(); 236 (void)fclose(yyin); 237 } 238 239 /* open the input file */ 240 if ((yyin = fopen(argv[0], "r")) == NULL) 241 err(1, "cannot open '%s'", argv[0]); 242 curr_pos.p_file = argv[0]; 243 curr_pos.p_line = 0; 244 lex_next_line(); 245 yyparse(); 246 (void)fclose(yyin); 247 248 /* Following warnings cannot be suppressed by LINTED */ 249 lwarn = LWARN_ALL; 250 debug_step("main lwarn = %d", lwarn); 251 252 end_translation_unit(); 253 254 outclose(); 255 256 return seen_error || (wflag && seen_warning) ? 1 : 0; 257} 258 259static void __dead 260usage(void) 261{ 262 (void)fprintf(stderr, 263 "usage: %s [-abceghmprstvwyzFPST] [-Alevel] [-d directory] " 264 "[-R old=new]\n" 265 " %*s [-X id,...] [-q id,...] src dest\n", 266 getprogname(), (int)strlen(getprogname()), ""); 267 exit(1); 268} 269 270void __dead 271norecover(void) 272{ 273 /* cannot recover from previous errors */ 274 error(224); 275 exit(1); 276} 277