1 1.84 rillig /* $NetBSD: main1.c,v 1.84 2024/09/24 19:58:06 rillig Exp $ */ 2 1.2 cgd 3 1.1 cgd /* 4 1.1 cgd * Copyright (c) 1994, 1995 Jochen Pohl 5 1.1 cgd * All Rights Reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.1 cgd * 3. All advertising materials mentioning features or use of this software 16 1.1 cgd * must display the following acknowledgement: 17 1.74 rillig * This product includes software developed by Jochen Pohl for 18 1.1 cgd * The NetBSD Project. 19 1.1 cgd * 4. The name of the author may not be used to endorse or promote products 20 1.1 cgd * derived from this software without specific prior written permission. 21 1.1 cgd * 22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 1.1 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 1.1 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 1.1 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 1.1 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 1.1 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 1.1 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 1.1 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 cgd */ 33 1.1 cgd 34 1.15 jmc #if HAVE_NBTOOL_CONFIG_H 35 1.15 jmc #include "nbtool_config.h" 36 1.15 jmc #endif 37 1.15 jmc 38 1.4 christos #include <sys/cdefs.h> 39 1.62 rillig #if defined(__RCSID) 40 1.84 rillig __RCSID("$NetBSD: main1.c,v 1.84 2024/09/24 19:58:06 rillig Exp $"); 41 1.1 cgd #endif 42 1.1 cgd 43 1.5 christos #include <sys/types.h> 44 1.80 rillig #include <locale.h> 45 1.29 rillig #include <signal.h> 46 1.1 cgd #include <stdio.h> 47 1.29 rillig #include <stdlib.h> 48 1.5 christos #include <string.h> 49 1.1 cgd #include <unistd.h> 50 1.1 cgd 51 1.1 cgd #include "lint1.h" 52 1.1 cgd 53 1.78 rillig int aflag; 54 1.78 rillig bool bflag; 55 1.78 rillig bool cflag; 56 1.78 rillig bool eflag; 57 1.78 rillig bool Fflag; 58 1.78 rillig bool hflag; 59 1.78 rillig bool Pflag; 60 1.78 rillig bool pflag; 61 1.78 rillig bool rflag; 62 1.78 rillig bool Tflag; 63 1.78 rillig bool vflag; 64 1.78 rillig bool wflag; 65 1.78 rillig bool yflag; 66 1.78 rillig bool zflag; 67 1.1 cgd 68 1.60 rillig /* 69 1.60 rillig * The default language level is the one that checks for compatibility 70 1.60 rillig * between traditional C and C90. As of 2022, this default is no longer 71 1.60 rillig * useful since most traditional C code has already been migrated. 72 1.60 rillig */ 73 1.78 rillig bool allow_trad = true; 74 1.78 rillig bool allow_c90 = true; 75 1.78 rillig bool allow_c99; 76 1.78 rillig bool allow_c11; 77 1.78 rillig bool allow_c23; 78 1.78 rillig bool allow_gcc; 79 1.60 rillig 80 1.18 christos sig_atomic_t fpe; 81 1.18 christos 82 1.78 rillig static void usage(void); 83 1.4 christos 84 1.25 christos static FILE * 85 1.41 rillig gcc_builtins(void) 86 1.25 christos { 87 1.58 rillig /* https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ 88 1.54 rillig static const char builtins[] = 89 1.58 rillig "typedef typeof(sizeof(0)) __lint_size_t;\n" 90 1.58 rillig 91 1.58 rillig "void *alloca(__lint_size_t);\n" 92 1.58 rillig "void *__builtin_alloca(__lint_size_t);\n" 93 1.58 rillig "void *__builtin_alloca_with_align" 94 1.58 rillig "(__lint_size_t, __lint_size_t);\n" 95 1.58 rillig "void *__builtin_alloca_with_align_and_max" 96 1.58 rillig "(__lint_size_t, __lint_size_t, __lint_size_t);\n" 97 1.58 rillig 98 1.54 rillig "int __builtin_isinf(long double);\n" 99 1.54 rillig "int __builtin_isnan(long double);\n" 100 1.54 rillig "int __builtin_copysign(long double, long double);\n"; 101 1.54 rillig size_t builtins_len = sizeof(builtins) - 1; 102 1.54 rillig 103 1.25 christos #if HAVE_NBTOOL_CONFIG_H 104 1.25 christos char template[] = "/tmp/lint.XXXXXX"; 105 1.25 christos int fd; 106 1.25 christos FILE *fp; 107 1.25 christos if ((fd = mkstemp(template)) == -1) 108 1.25 christos return NULL; 109 1.25 christos (void)unlink(template); 110 1.25 christos if ((fp = fdopen(fd, "r+")) == NULL) { 111 1.57 rillig (void)close(fd); 112 1.25 christos return NULL; 113 1.25 christos } 114 1.54 rillig if (fwrite(builtins, 1, builtins_len, fp) != builtins_len) { 115 1.57 rillig (void)fclose(fp); 116 1.25 christos return NULL; 117 1.25 christos } 118 1.25 christos rewind(fp); 119 1.25 christos return fp; 120 1.25 christos #else 121 1.54 rillig return fmemopen(__UNCONST(builtins), builtins_len, "r"); 122 1.23 christos #endif 123 1.25 christos } 124 1.1 cgd 125 1.18 christos /*ARGSUSED*/ 126 1.18 christos static void 127 1.18 christos sigfpe(int s) 128 1.18 christos { 129 1.37 rillig fpe = 1; 130 1.18 christos } 131 1.18 christos 132 1.1 cgd int 133 1.8 lukem main(int argc, char *argv[]) 134 1.1 cgd { 135 1.56 rillig int c; 136 1.1 cgd 137 1.80 rillig setlocale(LC_ALL, ""); 138 1.12 tv setprogname(argv[0]); 139 1.12 tv 140 1.83 rillig while ((c = getopt(argc, argv, "abceghpq:rstvwyzA:FPR:STX:")) != -1) { 141 1.1 cgd switch (c) { 142 1.1 cgd case 'a': aflag++; break; 143 1.36 rillig case 'b': bflag = true; break; 144 1.36 rillig case 'c': cflag = true; break; 145 1.36 rillig case 'e': eflag = true; break; 146 1.36 rillig case 'F': Fflag = true; break; 147 1.60 rillig case 'g': allow_gcc = true; break; 148 1.36 rillig case 'h': hflag = true; break; 149 1.36 rillig case 'p': pflag = true; break; 150 1.36 rillig case 'P': Pflag = true; break; 151 1.65 rillig case 'q': enable_queries(optarg); break; 152 1.36 rillig case 'r': rflag = true; break; 153 1.60 rillig case 's': 154 1.60 rillig allow_trad = false; 155 1.60 rillig allow_c90 = true; 156 1.60 rillig allow_c99 = false; 157 1.60 rillig allow_c11 = false; 158 1.67 rillig allow_c23 = false; 159 1.60 rillig break; 160 1.60 rillig case 'S': 161 1.60 rillig allow_trad = false; 162 1.60 rillig allow_c90 = true; 163 1.60 rillig allow_c99 = true; 164 1.60 rillig allow_c11 = false; 165 1.67 rillig allow_c23 = false; 166 1.60 rillig break; 167 1.34 rillig case 'T': Tflag = true; break; 168 1.60 rillig case 't': 169 1.60 rillig allow_trad = true; 170 1.60 rillig allow_c90 = false; 171 1.60 rillig allow_c99 = false; 172 1.60 rillig allow_c11 = false; 173 1.67 rillig allow_c23 = false; 174 1.60 rillig break; 175 1.36 rillig case 'w': wflag = true; break; 176 1.70 rillig case 'v': vflag = true; break; 177 1.36 rillig case 'y': yflag = true; break; 178 1.70 rillig case 'z': zflag = true; break; 179 1.5 christos 180 1.43 rillig case 'A': 181 1.67 rillig if (strcmp(optarg, "c23") == 0) { 182 1.60 rillig allow_trad = false; 183 1.60 rillig allow_c90 = true; 184 1.60 rillig allow_c99 = true; 185 1.60 rillig allow_c11 = true; 186 1.67 rillig allow_c23 = true; 187 1.67 rillig } else if (strcmp(optarg, "c11") == 0) { 188 1.67 rillig allow_trad = false; 189 1.67 rillig allow_c90 = true; 190 1.67 rillig allow_c99 = true; 191 1.67 rillig allow_c11 = true; 192 1.68 rillig allow_c23 = false; 193 1.43 rillig } else 194 1.43 rillig usage(); 195 1.43 rillig break; 196 1.43 rillig 197 1.28 rillig case 'R': 198 1.40 rillig add_directory_replacement(optarg); 199 1.26 christos break; 200 1.26 christos 201 1.5 christos case 'X': 202 1.56 rillig suppress_messages(optarg); 203 1.5 christos break; 204 1.5 christos default: 205 1.5 christos usage(); 206 1.1 cgd } 207 1.1 cgd } 208 1.1 cgd argc -= optind; 209 1.1 cgd argv += optind; 210 1.1 cgd 211 1.1 cgd if (argc != 2) 212 1.1 cgd usage(); 213 1.1 cgd 214 1.1 cgd /* initialize output */ 215 1.79 rillig outopen(argv[1]); 216 1.1 cgd 217 1.18 christos (void)signal(SIGFPE, sigfpe); 218 1.81 rillig init_decl(); 219 1.81 rillig init_lex(); 220 1.1 cgd 221 1.61 rillig if (allow_gcc && allow_c90) { 222 1.41 rillig if ((yyin = gcc_builtins()) == NULL) 223 1.41 rillig err(1, "cannot open builtins"); 224 1.63 rillig curr_pos.p_file = "<gcc-builtins>"; 225 1.63 rillig curr_pos.p_line = 0; 226 1.63 rillig lex_next_line(); 227 1.41 rillig yyparse(); 228 1.57 rillig (void)fclose(yyin); 229 1.41 rillig } 230 1.25 christos 231 1.84 rillig #ifdef DEBUG 232 1.84 rillig debug_enabled = true; 233 1.84 rillig setvbuf(stdout, NULL, _IONBF, 0); 234 1.84 rillig #endif 235 1.84 rillig #if YYDEBUG 236 1.84 rillig if (yflag) 237 1.84 rillig yydebug = 1; 238 1.84 rillig #endif 239 1.84 rillig 240 1.22 christos /* open the input file */ 241 1.22 christos if ((yyin = fopen(argv[0], "r")) == NULL) 242 1.22 christos err(1, "cannot open '%s'", argv[0]); 243 1.63 rillig curr_pos.p_file = argv[0]; 244 1.63 rillig curr_pos.p_line = 0; 245 1.63 rillig lex_next_line(); 246 1.1 cgd yyparse(); 247 1.57 rillig (void)fclose(yyin); 248 1.1 cgd 249 1.1 cgd /* Following warnings cannot be suppressed by LINTED */ 250 1.21 christos lwarn = LWARN_ALL; 251 1.51 rillig debug_step("main lwarn = %d", lwarn); 252 1.1 cgd 253 1.76 rillig end_translation_unit(); 254 1.1 cgd 255 1.1 cgd outclose(); 256 1.1 cgd 257 1.72 rillig return seen_error || (wflag && seen_warning) ? 1 : 0; 258 1.1 cgd } 259 1.1 cgd 260 1.75 rillig static void __dead 261 1.8 lukem usage(void) 262 1.1 cgd { 263 1.5 christos (void)fprintf(stderr, 264 1.83 rillig "usage: %s [-abceghmprstvwyzFPST] [-Alevel] [-d directory] " 265 1.71 rillig "[-R old=new]\n" 266 1.71 rillig " %*s [-X id,...] [-q id,...] src dest\n", 267 1.55 rillig getprogname(), (int)strlen(getprogname()), ""); 268 1.1 cgd exit(1); 269 1.1 cgd } 270 1.8 lukem 271 1.75 rillig void __dead 272 1.8 lukem norecover(void) 273 1.1 cgd { 274 1.1 cgd /* cannot recover from previous errors */ 275 1.1 cgd error(224); 276 1.1 cgd exit(1); 277 1.1 cgd } 278