1 /* $NetBSD: main1.c,v 1.45 2021/04/18 22:51:24 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) && !defined(lint) 40 __RCSID("$NetBSD: main1.c,v 1.45 2021/04/18 22:51:24 rillig Exp $"); 41 #endif 42 43 #include <sys/types.h> 44 #include <errno.h> 45 #include <limits.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "lint1.h" 53 54 /* set yydebug to 1*/ 55 bool yflag; 56 57 /* 58 * Print warnings if an assignment of an integer type to another integer type 59 * causes an implicit narrowing conversion. If aflag is 1, these warnings 60 * are printed only if the source type is at least as wide as long. If aflag 61 * is greater than 1, they are always printed. 62 */ 63 int aflag; 64 65 /* Print a warning if a break statement cannot be reached. */ 66 bool bflag; 67 68 /* Print warnings for pointer casts. */ 69 bool cflag; 70 71 /* Allow features from C11, C99 and C90. */ 72 bool c11flag; 73 74 /* Print various debug information. */ 75 bool dflag; 76 77 /* Perform stricter checking of enum types and operations on enum types. */ 78 bool eflag; 79 80 /* Print complete pathnames, not only the basename. */ 81 bool Fflag; 82 83 /* Enable some extensions of gcc */ 84 bool gflag; 85 86 /* Treat warnings as errors */ 87 bool wflag; 88 89 /* 90 * Apply a number of heuristic tests to attempt to intuit bugs, improve 91 * style, and reduce waste. 92 */ 93 bool hflag; 94 95 /* Attempt to check portability to other dialects of C. */ 96 bool pflag; 97 98 /* 99 * In case of redeclarations/redefinitions print the location of the 100 * previous declaration/definition. 101 */ 102 bool rflag; 103 104 /* Strict ANSI C mode. */ 105 bool sflag; 106 107 bool Tflag; 108 109 /* Traditional C mode. */ 110 bool tflag; 111 112 /* Enable C9X extensions */ 113 bool Sflag; 114 115 /* Picky flag */ 116 bool Pflag; 117 118 /* 119 * Complain about functions and external variables used and not defined, 120 * or defined and not used. 121 */ 122 bool uflag = true; 123 124 /* Complain about unused function arguments. */ 125 bool vflag = true; 126 127 /* Complain about structures which are never defined. */ 128 bool zflag = true; 129 130 err_set msgset; 131 132 sig_atomic_t fpe; 133 134 static void usage(void); 135 136 static const char builtins[] = 137 "int __builtin_isinf(long double);\n" 138 "int __builtin_isnan(long double);\n" 139 "int __builtin_copysign(long double, long double);\n" 140 ; 141 static const size_t builtinlen = sizeof(builtins) - 1; 142 143 static FILE * 144 gcc_builtins(void) 145 { 146 #if HAVE_NBTOOL_CONFIG_H 147 char template[] = "/tmp/lint.XXXXXX"; 148 int fd; 149 FILE *fp; 150 if ((fd = mkstemp(template)) == -1) 151 return NULL; 152 (void)unlink(template); 153 if ((fp = fdopen(fd, "r+")) == NULL) { 154 close(fd); 155 return NULL; 156 } 157 if (fwrite(builtins, 1, builtinlen, fp) != builtinlen) { 158 fclose(fp); 159 return NULL; 160 } 161 rewind(fp); 162 return fp; 163 #else 164 return fmemopen(__UNCONST(builtins), builtinlen, "r"); 165 #endif 166 } 167 168 /*ARGSUSED*/ 169 static void 170 sigfpe(int s) 171 { 172 fpe = 1; 173 } 174 175 int 176 main(int argc, char *argv[]) 177 { 178 int c; 179 char *ptr; 180 181 setprogname(argv[0]); 182 183 ERR_ZERO(&msgset); 184 while ((c = getopt(argc, argv, "abcdeghmprstuvwyzA:FPR:STX:")) != -1) { 185 switch (c) { 186 case 'a': aflag++; break; 187 case 'b': bflag = true; break; 188 case 'c': cflag = true; break; 189 case 'd': dflag = true; break; 190 case 'e': eflag = true; break; 191 case 'F': Fflag = true; break; 192 case 'g': gflag = true; break; 193 case 'h': hflag = true; break; 194 case 'p': pflag = true; break; 195 case 'P': Pflag = true; break; 196 case 'r': rflag = true; break; 197 case 's': sflag = true; break; 198 case 'S': Sflag = true; break; 199 case 'T': Tflag = true; break; 200 case 't': tflag = true; break; 201 case 'u': uflag = false; break; 202 case 'w': wflag = true; break; 203 case 'v': vflag = false; break; 204 case 'y': yflag = true; break; 205 case 'z': zflag = false; break; 206 207 case 'A': 208 if (strcmp(optarg, "c11") == 0) { 209 c11flag = true; 210 Sflag = true; 211 sflag = true; 212 } else 213 usage(); 214 break; 215 216 case 'm': 217 msglist(); 218 return 0; 219 220 case 'R': 221 add_directory_replacement(optarg); 222 break; 223 224 case 'X': 225 for (ptr = strtok(optarg, ","); ptr != NULL; 226 ptr = strtok(NULL, ",")) { 227 char *eptr; 228 long msg; 229 230 errno = 0; 231 msg = strtol(ptr, &eptr, 0); 232 if ((msg == TARG_LONG_MIN || msg == TARG_LONG_MAX) && 233 errno == ERANGE) 234 err(1, "invalid error message id '%s'", 235 ptr); 236 if (*eptr != '\0' || ptr == eptr || msg < 0 || 237 msg >= ERR_SETSIZE) 238 errx(1, "invalid error message id '%s'", 239 ptr); 240 ERR_SET(msg, &msgset); 241 } 242 break; 243 default: 244 usage(); 245 } 246 } 247 argc -= optind; 248 argv += optind; 249 250 if (argc != 2) 251 usage(); 252 253 254 /* initialize output */ 255 outopen(argv[1]); 256 257 #ifdef YYDEBUG 258 if (yflag) 259 yydebug = 1; 260 #endif 261 262 (void)signal(SIGFPE, sigfpe); 263 initmem(); 264 initdecl(); 265 initscan(); 266 267 if (gflag) { 268 if ((yyin = gcc_builtins()) == NULL) 269 err(1, "cannot open builtins"); 270 yyparse(); 271 fclose(yyin); 272 } 273 274 /* open the input file */ 275 if ((yyin = fopen(argv[0], "r")) == NULL) 276 err(1, "cannot open '%s'", argv[0]); 277 yyparse(); 278 fclose(yyin); 279 280 /* Following warnings cannot be suppressed by LINTED */ 281 lwarn = LWARN_ALL; 282 #ifdef DEBUG 283 printf("%s, %d: lwarn = %d\n", curr_pos.p_file, curr_pos.p_line, lwarn); 284 #endif 285 286 check_global_symbols(); 287 288 outclose(); 289 290 return nerr != 0 ? 1 : 0; 291 } 292 293 static void __attribute__((noreturn)) 294 usage(void) 295 { 296 (void)fprintf(stderr, 297 "usage: %s [-abcdeghmprstuvwyzFST] [-Ac11] [-X <id>[,<id>]... " 298 "src dest\n", 299 getprogname()); 300 exit(1); 301 } 302 303 void __attribute__((noreturn)) 304 norecover(void) 305 { 306 /* cannot recover from previous errors */ 307 error(224); 308 exit(1); 309 } 310