Home | History | Annotate | Line # | Download | only in lint1
err.c revision 1.246.2.1
      1  1.246.2.1  perseant /*	$NetBSD: err.c,v 1.246.2.1 2025/08/02 05:58:45 perseant 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.212    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.27       jmc #if HAVE_NBTOOL_CONFIG_H
     35       1.27       jmc #include "nbtool_config.h"
     36       1.27       jmc #endif
     37       1.27       jmc 
     38       1.10  christos #include <sys/cdefs.h>
     39      1.166    rillig #if defined(__RCSID)
     40  1.246.2.1  perseant __RCSID("$NetBSD: err.c,v 1.246.2.1 2025/08/02 05:58:45 perseant Exp $");
     41        1.1       cgd #endif
     42        1.1       cgd 
     43      1.178    rillig #include <limits.h>
     44       1.55    rillig #include <stdarg.h>
     45        1.1       cgd #include <stdlib.h>
     46      1.178    rillig #include <string.h>
     47        1.1       cgd 
     48        1.1       cgd #include "lint1.h"
     49        1.1       cgd 
     50      1.220    rillig bool seen_error;
     51      1.220    rillig bool seen_warning;
     52       1.12  christos 
     53       1.12  christos /* number of syntax errors */
     54      1.220    rillig int sytxerr;
     55       1.12  christos 
     56       1.12  christos 
     57      1.170    rillig static const char *const msgs[] = {
     58      1.225    rillig 	"empty declaration",						// 0
     59      1.225    rillig 	"old-style declaration; add 'int'",				// 1
     60      1.225    rillig 	"empty declaration",						// 2
     61      1.225    rillig 	"'%s' declared in parameter declaration list",			// 3
     62  1.246.2.1  perseant 	"invalid type combination",					// 4
     63      1.225    rillig 	"modifying typedef with '%s'; only qualifiers allowed",		// 5
     64      1.225    rillig 	"use 'double' instead of 'long float'",				// 6
     65      1.225    rillig 	"only one storage class allowed",				// 7
     66  1.246.2.1  perseant 	"invalid storage class",					// 8
     67      1.225    rillig 	"only 'register' is valid as storage class in parameter",	// 9
     68      1.225    rillig 	"duplicate '%s'",						// 10
     69      1.225    rillig 	"bit-field initializer out of range",				// 11
     70      1.225    rillig 	"compiler takes size of function",				// 12
     71      1.225    rillig 	"incomplete enum type '%s'",					// 13
     72      1.225    rillig 	"",								// 14
     73  1.246.2.1  perseant 	"function returns invalid type '%s'",				// 15
     74  1.246.2.1  perseant 	"array of function is invalid",					// 16
     75      1.225    rillig 	"null dimension",						// 17
     76  1.246.2.1  perseant 	"invalid use of 'void'",					// 18
     77      1.225    rillig 	"void type for '%s'",						// 19
     78      1.225    rillig 	"negative array dimension (%d)",				// 20
     79      1.225    rillig 	"redeclaration of formal parameter '%s'",			// 21
     80      1.225    rillig 	"incomplete or misplaced function definition",			// 22
     81      1.225    rillig 	"undefined label '%s'",						// 23
     82      1.225    rillig 	"cannot initialize function '%s'",				// 24
     83      1.225    rillig 	"cannot initialize typedef '%s'",				// 25
     84      1.225    rillig 	"cannot initialize extern declaration '%s'",			// 26
     85      1.225    rillig 	"redeclaration of '%s'",					// 27
     86      1.225    rillig 	"redefinition of '%s'",						// 28
     87      1.225    rillig 	"'%s' was previously declared extern, becomes static",		// 29
     88      1.225    rillig 	"redeclaration of '%s'; C90 or later require static",		// 30
     89      1.225    rillig 	"'%s' has incomplete type '%s'",				// 31
     90      1.225    rillig 	"type of parameter '%s' defaults to 'int'",			// 32
     91      1.225    rillig 	"duplicate member name '%s'",					// 33
     92      1.225    rillig 	"nonportable bit-field type '%s'",				// 34
     93  1.246.2.1  perseant 	"invalid bit-field type '%s'",					// 35
     94  1.246.2.1  perseant 	"invalid bit-field size: %d",					// 36
     95      1.225    rillig 	"zero size bit-field",						// 37
     96  1.246.2.1  perseant 	"function invalid in structure or union",			// 38
     97      1.225    rillig 	"zero-sized array '%s' in struct requires C99 or later",	// 39
     98      1.225    rillig 	"",			/* never used */			// 40
     99      1.225    rillig 	"bit-field in union is very unusual",				// 41
    100      1.225    rillig 	"forward reference to enum type",				// 42
    101      1.225    rillig 	"redefinition of '%s' hides earlier one",			// 43
    102      1.225    rillig 	"declaration of '%s %s' introduces new type in C90 or later",	// 44
    103      1.225    rillig 	"base type is really '%s %s'",					// 45
    104      1.225    rillig 	"%s tag '%s' redeclared as %s",					// 46
    105      1.225    rillig 	"zero sized %s is a C99 feature",				// 47
    106      1.225    rillig 	"enumeration value '%s' overflows",				// 48
    107      1.225    rillig 	"anonymous struct/union members is a C11 feature",		// 49
    108      1.225    rillig 	"parameter '%s' has function type, should be pointer",		// 50
    109      1.225    rillig 	"parameter mismatch: %d declared, %d defined",			// 51
    110      1.225    rillig 	"cannot initialize parameter '%s'",				// 52
    111      1.225    rillig 	"declared parameter '%s' is missing",				// 53
    112      1.225    rillig 	"trailing ',' in enum declaration requires C99 or later",	// 54
    113      1.225    rillig 	"integral constant expression expected",			// 55
    114  1.246.2.1  perseant 	"constant %s too large for 'int'",				// 56
    115      1.225    rillig 	"enumeration constant '%s' hides parameter",			// 57
    116      1.225    rillig 	"type of '%s' does not match prototype",			// 58
    117      1.225    rillig 	"formal parameter #%d lacks name",				// 59
    118      1.225    rillig 	"void must be sole parameter",					// 60
    119      1.225    rillig 	"void parameter '%s' cannot have name",				// 61
    120      1.225    rillig 	"function prototype parameters must have types",		// 62
    121      1.225    rillig 	"prototype does not match old-style definition",		// 63
    122      1.225    rillig 	"()-less function definition",					// 64
    123      1.225    rillig 	"'%s' has no named members",					// 65
    124      1.225    rillig 	"",								// 66
    125      1.225    rillig 	"cannot return incomplete type",				// 67
    126      1.225    rillig 	"typedef already qualified with '%s'",				// 68
    127      1.225    rillig 	"inappropriate qualifiers with 'void'",				// 69
    128      1.225    rillig 	"",			/* unused */				// 70
    129      1.225    rillig 	"too many characters in character constant",			// 71
    130      1.225    rillig 	"typedef declares no type name",				// 72
    131      1.225    rillig 	"empty character constant",					// 73
    132      1.225    rillig 	"no hex digits follow \\x",					// 74
    133      1.225    rillig 	"overflow in hex escape",					// 75
    134      1.225    rillig 	"character escape does not fit in character",			// 76
    135      1.225    rillig 	"bad octal digit '%c'",						// 77
    136      1.225    rillig 	"",			/* unused */				// 78
    137      1.225    rillig 	"dubious escape \\%c",						// 79
    138      1.225    rillig 	"dubious escape \\%o",						// 80
    139  1.246.2.1  perseant 	"\\a requires C90 or later",					// 81
    140  1.246.2.1  perseant 	"\\x requires C90 or later",					// 82
    141      1.225    rillig 	"storage class after type is obsolescent",			// 83
    142      1.225    rillig 	"C90 to C17 require formal parameter before '...'",		// 84
    143      1.225    rillig 	"dubious tag declaration '%s %s'",				// 85
    144  1.246.2.1  perseant 	"automatic '%s' hides external declaration with type '%s'",	// 86
    145  1.246.2.1  perseant 	"static '%s' hides external declaration with type '%s'",	// 87
    146  1.246.2.1  perseant 	"typedef '%s' hides external declaration with type '%s'",	// 88
    147      1.225    rillig 	"typedef '%s' redeclared",					// 89
    148      1.225    rillig 	"inconsistent redeclaration of extern '%s'",			// 90
    149      1.225    rillig 	"declaration of '%s' hides parameter",				// 91
    150      1.225    rillig 	"inconsistent redeclaration of static '%s'",			// 92
    151      1.225    rillig 	"dubious static function '%s' at block level",			// 93
    152  1.246.2.1  perseant 	"function '%s' has invalid storage class",			// 94
    153      1.225    rillig 	"declaration of '%s' hides earlier one",			// 95
    154      1.225    rillig 	"cannot dereference non-pointer type '%s'",			// 96
    155  1.246.2.1  perseant 	"suffix 'U' requires C90 or later",				// 97
    156  1.246.2.1  perseant 	"suffixes 'F' or 'L' require C90 or later",			// 98
    157      1.225    rillig 	"'%s' undefined",						// 99
    158  1.246.2.1  perseant 	"unary '+' requires C90 or later",				// 100
    159      1.225    rillig 	"type '%s' does not have member '%s'",				// 101
    160  1.246.2.1  perseant 	"invalid use of member '%s'",					// 102
    161      1.225    rillig 	"left operand of '.' must be struct or union, not '%s'",	// 103
    162      1.225    rillig 	"left operand of '->' must be pointer to struct or union, not '%s'", // 104
    163      1.225    rillig 	"non-unique member requires struct/union %s",			// 105
    164      1.225    rillig 	"left operand of '->' must be pointer",				// 106
    165      1.225    rillig 	"operands of '%s' have incompatible types '%s' and '%s'",	// 107
    166      1.225    rillig 	"operand of '%s' has invalid type '%s'",			// 108
    167  1.246.2.1  perseant 	"void type invalid in expression",				// 109
    168      1.225    rillig 	"pointer to function is not allowed here",			// 110
    169      1.225    rillig 	"unacceptable operand of '%s'",					// 111
    170      1.225    rillig 	"cannot take address of bit-field",				// 112
    171      1.225    rillig 	"cannot take address of register '%s'",				// 113
    172      1.225    rillig 	"%soperand of '%s' must be lvalue",				// 114
    173      1.225    rillig 	"%soperand of '%s' must be modifiable lvalue",			// 115
    174  1.246.2.1  perseant 	"invalid pointer subtraction",					// 116
    175      1.225    rillig 	"bitwise '%s' on signed value possibly nonportable",		// 117
    176      1.225    rillig 	"semantics of '%s' change in C90; use explicit cast",		// 118
    177      1.225    rillig 	"conversion of '%s' to '%s' is out of range",			// 119
    178      1.225    rillig 	"bitwise '%s' on signed value nonportable",			// 120
    179      1.225    rillig 	"negative shift",						// 121
    180      1.225    rillig 	"shift amount %llu is greater than bit-size %llu of '%s'",	// 122
    181  1.246.2.1  perseant 	"invalid combination of %s '%s' and %s '%s', op '%s'",		// 123
    182  1.246.2.1  perseant 	"invalid combination of '%s' and '%s', op '%s'",		// 124
    183      1.225    rillig 	"pointers to functions can only be compared for equality",	// 125
    184      1.225    rillig 	"incompatible types '%s' and '%s' in conditional",		// 126
    185  1.246.2.1  perseant 	"",			/* no longer used */			// 127
    186  1.246.2.1  perseant 	"operator '%s' discards '%s' from '%s'",			// 128
    187      1.225    rillig 	"expression has null effect",					// 129
    188      1.225    rillig 	"enum type mismatch: '%s' '%s' '%s'",				// 130
    189      1.225    rillig 	"conversion to '%s' may sign-extend incorrectly",		// 131
    190      1.225    rillig 	"conversion from '%s' to '%s' may lose accuracy",		// 132
    191      1.225    rillig 	"conversion of pointer to '%s' loses bits",			// 133
    192      1.225    rillig 	"conversion of pointer to '%s' may lose bits",			// 134
    193      1.225    rillig 	"converting '%s' to '%s' increases alignment from %u to %u",	// 135
    194      1.225    rillig 	"cannot do pointer arithmetic on operand of unknown size",	// 136
    195      1.225    rillig 	"",			/* unused */				// 137
    196      1.225    rillig 	"unknown operand size, op '%s'",				// 138
    197      1.225    rillig 	"division by 0",						// 139
    198      1.225    rillig 	"modulus by 0",							// 140
    199      1.232    rillig 	"'%s' overflows '%s'",						// 141
    200      1.225    rillig 	"operator '%s' produces floating point overflow",		// 142
    201      1.225    rillig 	"cannot take size/alignment of incomplete type",		// 143
    202      1.225    rillig 	"cannot take size/alignment of function type '%s'",		// 144
    203      1.225    rillig 	"cannot take size/alignment of bit-field",			// 145
    204      1.225    rillig 	"cannot take size/alignment of void",				// 146
    205      1.225    rillig 	"invalid cast from '%s' to '%s'",				// 147
    206      1.225    rillig 	"improper cast of void expression",				// 148
    207      1.225    rillig 	"cannot call '%s', must be a function",				// 149
    208      1.225    rillig 	"argument mismatch: %d %s passed, %d expected",			// 150
    209      1.225    rillig 	"void expressions may not be arguments, arg #%d",		// 151
    210      1.225    rillig 	"argument cannot have unknown size, arg #%d",			// 152
    211      1.225    rillig 	"converting '%s' to incompatible '%s' for argument %d",		// 153
    212  1.246.2.1  perseant 	"invalid combination of %s '%s' and %s '%s', arg #%d",		// 154
    213      1.225    rillig 	"passing '%s' to incompatible '%s', arg #%d",			// 155
    214      1.225    rillig 	"function expects '%s', passing '%s' for arg #%d",		// 156
    215      1.225    rillig 	"C90 treats constant as unsigned",				// 157
    216      1.225    rillig 	"'%s' may be used before set",					// 158
    217      1.225    rillig 	"assignment in conditional context",				// 159
    218      1.225    rillig 	"operator '==' found where '=' was expected",			// 160
    219  1.246.2.1  perseant 	"",			/* no longer used */			// 161
    220      1.225    rillig 	"operator '%s' compares '%s' with '%s'",			// 162
    221      1.225    rillig 	"a cast does not yield an lvalue",				// 163
    222      1.245    rillig 	"assignment of negative constant %lld to unsigned type '%s'",	// 164
    223      1.225    rillig 	"constant truncated by assignment",				// 165
    224      1.225    rillig 	"precision lost in bit-field assignment",			// 166
    225      1.237    rillig 	"array subscript %jd cannot be negative",			// 167
    226      1.238    rillig 	"array subscript %ju cannot be > %d",				// 168
    227  1.246.2.1  perseant 	"possible precedence confusion between '%s' and '%s'",		// 169
    228      1.225    rillig 	"first operand of '?' must have scalar type",			// 170
    229      1.225    rillig 	"cannot assign to '%s' from '%s'",				// 171
    230      1.225    rillig 	"too many struct/union initializers",				// 172
    231      1.225    rillig 	"too many array initializers, expected %d",			// 173
    232      1.242    rillig 	"too many initializers for '%s'",				// 174
    233      1.225    rillig 	"initialization of incomplete type '%s'",			// 175
    234      1.225    rillig 	"",			/* no longer used */			// 176
    235      1.225    rillig 	"non-constant initializer",					// 177
    236      1.225    rillig 	"initializer does not fit",					// 178
    237      1.225    rillig 	"cannot initialize struct/union with no named member",		// 179
    238      1.225    rillig 	"bit-field initializer does not fit",				// 180
    239      1.225    rillig 	"{}-enclosed or constant initializer of type '%s' required",	// 181
    240  1.246.2.1  perseant 	"'%s' discards '%s' from '%s'",					// 182
    241  1.246.2.1  perseant 	"invalid combination of %s '%s' and %s '%s' for '%s'",		// 183
    242  1.246.2.1  perseant 	"invalid combination of '%s' and '%s'",				// 184
    243      1.225    rillig 	"cannot initialize '%s' from '%s'",				// 185
    244      1.236    rillig 	"bit-field initializer must be an integer in traditional C",	// 186
    245      1.234    rillig 	"string literal too long (%ju) for target array (%ju)",		// 187
    246  1.246.2.1  perseant 	"automatic aggregate initialization requires C90 or later",	// 188
    247      1.225    rillig 	"",			/* no longer used */			// 189
    248      1.225    rillig 	"empty array declaration for '%s'",				// 190
    249      1.225    rillig 	"'%s' set but not used in function '%s'",			// 191
    250      1.225    rillig 	"'%s' unused in function '%s'",					// 192
    251  1.246.2.1  perseant 	"'%s' statement not reached",					// 193
    252      1.225    rillig 	"label '%s' redefined",						// 194
    253      1.225    rillig 	"case not in switch",						// 195
    254  1.246.2.1  perseant 	"case label is converted from '%s' to '%s'",			// 196
    255      1.225    rillig 	"non-constant case expression",					// 197
    256      1.225    rillig 	"non-integral case expression",					// 198
    257      1.234    rillig 	"duplicate case '%jd' in switch",				// 199
    258      1.234    rillig 	"duplicate case '%ju' in switch",				// 200
    259      1.225    rillig 	"default outside switch",					// 201
    260      1.225    rillig 	"duplicate default in switch",					// 202
    261      1.225    rillig 	"case label must be of type 'int' in traditional C",		// 203
    262      1.225    rillig 	"controlling expressions must have scalar type",		// 204
    263      1.225    rillig 	"switch expression must have integral type",			// 205
    264      1.225    rillig 	"enumeration value(s) not handled in switch",			// 206
    265  1.246.2.1  perseant 	"",			/* no longer used */			// 207
    266      1.225    rillig 	"break outside loop or switch",					// 208
    267      1.225    rillig 	"continue outside loop",					// 209
    268      1.225    rillig 	"enum type mismatch between '%s' and '%s' in initialization",	// 210
    269      1.225    rillig 	"function has return type '%s' but returns '%s'",		// 211
    270      1.225    rillig 	"cannot return incomplete type",				// 212
    271      1.225    rillig 	"void function '%s' cannot return value",			// 213
    272      1.225    rillig 	"function '%s' expects to return value",			// 214
    273      1.225    rillig 	"function '%s' implicitly declared to return int",		// 215
    274      1.225    rillig 	"function '%s' has 'return expr' and 'return'",			// 216
    275      1.225    rillig 	"function '%s' falls off bottom without returning value",	// 217
    276      1.225    rillig 	"C90 treats constant as unsigned, op '%s'",			// 218
    277  1.246.2.1  perseant 	"concatenated strings require C90 or later",			// 219
    278      1.225    rillig 	"fallthrough on case statement",				// 220
    279      1.245    rillig 	"initialization of unsigned type '%s' with negative constant %lld", // 221
    280      1.245    rillig 	"conversion of negative constant %lld to unsigned type '%s'",	// 222
    281      1.225    rillig 	"end-of-loop code not reached",					// 223
    282      1.225    rillig 	"cannot recover from previous errors",				// 224
    283      1.225    rillig 	"static function '%s' called but not defined",			// 225
    284      1.225    rillig 	"static variable '%s' unused",					// 226
    285      1.225    rillig 	"const object '%s' should have initializer",			// 227
    286      1.225    rillig 	"function cannot return const or volatile object",		// 228
    287      1.225    rillig 	"converting '%s' to '%s' is questionable",			// 229
    288      1.225    rillig 	"nonportable character comparison '%s'",			// 230
    289      1.225    rillig 	"parameter '%s' unused in function '%s'",			// 231
    290      1.225    rillig 	"label '%s' unused in function '%s'",				// 232
    291      1.225    rillig 	"struct '%s' never defined",					// 233
    292      1.225    rillig 	"union '%s' never defined",					// 234
    293      1.225    rillig 	"enum '%s' never defined",					// 235
    294      1.225    rillig 	"static function '%s' unused",					// 236
    295      1.225    rillig 	"redeclaration of formal parameter '%s'",			// 237
    296  1.246.2.1  perseant 	"initialization of union requires C90 or later",		// 238
    297  1.246.2.1  perseant 	"",			/* no longer used */			// 239
    298      1.225    rillig 	"",			/* unused */				// 240
    299      1.225    rillig 	"dubious operation '%s' on enum",				// 241
    300      1.225    rillig 	"combination of '%s' and '%s', op '%s'",			// 242
    301      1.225    rillig 	"operator '%s' assumes that '%s' is ordered",			// 243
    302  1.246.2.1  perseant 	"invalid structure pointer combination",			// 244
    303      1.225    rillig 	"incompatible structure pointers: '%s' '%s' '%s'",		// 245
    304      1.225    rillig 	"dubious conversion of enum to '%s'",				// 246
    305  1.246.2.1  perseant 	"pointer cast from '%s' to unrelated '%s'",			// 247
    306      1.225    rillig 	"floating-point constant out of range",				// 248
    307      1.225    rillig 	"syntax error '%s'",						// 249
    308      1.225    rillig 	"unknown character \\%o",					// 250
    309      1.225    rillig 	"malformed integer constant",					// 251
    310      1.225    rillig 	"integer constant out of range",				// 252
    311      1.225    rillig 	"unterminated character constant",				// 253
    312      1.225    rillig 	"newline in string or char constant",				// 254
    313      1.225    rillig 	"undefined or invalid '#' directive",				// 255
    314      1.225    rillig 	"unterminated comment",						// 256
    315      1.225    rillig 	"extra characters in lint comment",				// 257
    316      1.225    rillig 	"unterminated string constant",					// 258
    317      1.225    rillig 	"argument %d is converted from '%s' to '%s' due to prototype",	// 259
    318      1.225    rillig 	"previous declaration of '%s'",					// 260
    319      1.225    rillig 	"previous definition of '%s'",					// 261
    320  1.246.2.1  perseant 	"\\\" inside a character constant requires C90 or later",	// 262
    321  1.246.2.1  perseant 	"\\? requires C90 or later",					// 263
    322  1.246.2.1  perseant 	"\\v requires C90 or later",					// 264
    323      1.225    rillig 	"%s does not support 'long long'",				// 265
    324  1.246.2.1  perseant 	"'long double' requires C90 or later",				// 266
    325      1.225    rillig 	"shift amount %u equals bit-size of '%s'",			// 267
    326      1.225    rillig 	"variable '%s' declared inline",				// 268
    327      1.225    rillig 	"parameter '%s' declared inline",				// 269
    328  1.246.2.1  perseant 	"function prototypes require C90 or later",			// 270
    329      1.225    rillig 	"switch expression must be of type 'int' in traditional C",	// 271
    330      1.225    rillig 	"empty translation unit",					// 272
    331      1.225    rillig 	"bit-field type '%s' invalid in C90 or later",			// 273
    332      1.225    rillig 	"C90 or later forbid comparison of %s with %s",			// 274
    333      1.225    rillig 	"cast discards 'const' from type '%s'",				// 275
    334  1.246.2.1  perseant 	"'__%s__' is invalid for type '%s'",				// 276
    335      1.225    rillig 	"initialization of '%s' with '%s'",				// 277
    336      1.225    rillig 	"combination of '%s' and '%s', arg #%d",			// 278
    337      1.225    rillig 	"combination of '%s' and '%s' in return",			// 279
    338      1.225    rillig 	"comment /* %s */ must be outside function",			// 280
    339      1.225    rillig 	"duplicate comment /* %s */",					// 281
    340      1.225    rillig 	"comment /* %s */ must precede function definition",		// 282
    341      1.225    rillig 	"parameter number mismatch in comment /* %s */",		// 283
    342      1.225    rillig 	"fallthrough on default statement",				// 284
    343      1.225    rillig 	"prototype declaration",					// 285
    344      1.225    rillig 	"function definition is not a prototype",			// 286
    345      1.225    rillig 	"function declaration is not a prototype",			// 287
    346      1.225    rillig 	"dubious use of /* VARARGS */ with /* %s */",			// 288
    347      1.225    rillig 	"/* PRINTFLIKE */ and /* SCANFLIKE */ cannot be combined",	// 289
    348      1.225    rillig 	"static function '%s' declared but not defined",		// 290
    349      1.225    rillig 	"invalid multibyte character",					// 291
    350      1.225    rillig 	"cannot concatenate wide and regular string literals",		// 292
    351      1.225    rillig 	"parameter %d must be 'char *' for PRINTFLIKE/SCANFLIKE",	// 293
    352      1.225    rillig 	"multi-character character constant",				// 294
    353      1.225    rillig 	"conversion of '%s' to '%s' is out of range, arg #%d",		// 295
    354      1.245    rillig 	"conversion of negative constant %lld to unsigned type '%s', arg #%d", // 296
    355      1.225    rillig 	"conversion to '%s' may sign-extend incorrectly, arg #%d",	// 297
    356      1.225    rillig 	"conversion from '%s' to '%s' may lose accuracy, arg #%d",	// 298
    357      1.225    rillig 	"prototype does not match old-style definition, arg #%d",	// 299
    358      1.225    rillig 	"old-style definition",						// 300
    359      1.225    rillig 	"array of incomplete type",					// 301
    360      1.225    rillig 	"'%s' returns pointer to automatic object",			// 302
    361      1.225    rillig 	"conversion of %s to %s requires a cast",			// 303
    362      1.225    rillig 	"conversion of %s to %s requires a cast, arg #%d",		// 304
    363      1.225    rillig 	"conversion of %s to %s requires a cast, op %s",		// 305
    364  1.246.2.1  perseant 	"constant %s truncated by conversion, op '%s'",			// 306
    365      1.225    rillig 	"static variable '%s' set but not used",			// 307
    366      1.225    rillig 	"invalid type for _Complex",					// 308
    367  1.246.2.1  perseant 	"'%s' converts '%s' with its most significant bit being set to '%s'", // 309
    368      1.225    rillig 	"symbol renaming can't be used on function parameters",		// 310
    369      1.225    rillig 	"symbol renaming can't be used on automatic variables",		// 311
    370      1.225    rillig 	"%s does not support '//' comments",				// 312
    371      1.225    rillig 	"struct or union member name in initializer is a C99 feature",	// 313
    372      1.225    rillig 	"",		/* never used */				// 314
    373      1.225    rillig 	"GCC style struct or union member name in initializer",		// 315
    374      1.225    rillig 	"__FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension",		// 316
    375      1.225    rillig 	"__func__ is a C99 feature",					// 317
    376      1.225    rillig 	"variable array dimension is a C99/GCC extension",		// 318
    377      1.225    rillig 	"compound literals are a C99/GCC extension",			// 319
    378      1.225    rillig 	"'({ ... })' is a GCC extension",				// 320
    379      1.225    rillig 	"array initializer with designators is a C99 feature",		// 321
    380      1.225    rillig 	"zero sized array requires C99 or later",			// 322
    381      1.225    rillig 	"continue in 'do ... while (0)' loop",				// 323
    382      1.225    rillig 	"suggest cast from '%s' to '%s' on op '%s' to avoid overflow",	// 324
    383      1.225    rillig 	"variable declaration in for loop",				// 325
    384      1.225    rillig 	"attribute '%s' ignored for '%s'",				// 326
    385      1.225    rillig 	"declarations after statements is a C99 feature",		// 327
    386      1.225    rillig 	"union cast is a GCC extension",				// 328
    387      1.225    rillig 	"type '%s' is not a member of '%s'",				// 329
    388      1.225    rillig 	"operand of '%s' must be bool, not '%s'",			// 330
    389      1.225    rillig 	"left operand of '%s' must be bool, not '%s'",			// 331
    390      1.225    rillig 	"right operand of '%s' must be bool, not '%s'",			// 332
    391      1.225    rillig 	"controlling expression must be bool, not '%s'",		// 333
    392      1.225    rillig 	"parameter %d expects '%s', gets passed '%s'",			// 334
    393      1.225    rillig 	"operand of '%s' must not be bool",				// 335
    394      1.225    rillig 	"left operand of '%s' must not be bool",			// 336
    395      1.225    rillig 	"right operand of '%s' must not be bool",			// 337
    396      1.225    rillig 	"option '%c' should be handled in the switch",			// 338
    397      1.225    rillig 	"option '%c' should be listed in the options string",		// 339
    398      1.225    rillig 	"initialization with '[a...b]' is a GCC extension",		// 340
    399      1.225    rillig 	"argument to '%s' must be 'unsigned char' or EOF, not '%s'",	// 341
    400      1.225    rillig 	"argument to '%s' must be cast to 'unsigned char', not to '%s'", // 342
    401      1.225    rillig 	"static array size requires C11 or later",			// 343
    402      1.225    rillig 	"bit-field of type plain 'int' has implementation-defined signedness", // 344
    403      1.225    rillig 	"generic selection requires C11 or later",			// 345
    404      1.225    rillig 	"call to '%s' effectively discards 'const' from argument",	// 346
    405      1.225    rillig 	"redeclaration of '%s' with type '%s', expected '%s'",		// 347
    406  1.246.2.1  perseant 	"maximum value %d for '%s' of type '%s' does not match maximum array index %d", // 348
    407      1.225    rillig 	"non type argument to alignof is a GCC extension",		// 349
    408      1.225    rillig 	"'_Atomic' requires C11 or later",				// 350
    409      1.225    rillig 	"missing%s header declaration for '%s'",			// 351
    410      1.225    rillig 	"nested 'extern' declaration of '%s'",				// 352
    411      1.225    rillig 	"empty initializer braces require C23 or later",		// 353
    412      1.225    rillig 	"'_Static_assert' requires C11 or later",			// 354
    413      1.225    rillig 	"'_Static_assert' without message requires C23 or later",	// 355
    414      1.225    rillig 	"short octal escape '%.*s' followed by digit '%c'",		// 356
    415      1.226    rillig 	"hex escape '%.*s' mixes uppercase and lowercase digits",	// 357
    416      1.226    rillig 	"hex escape '%.*s' has more than 2 digits",			// 358
    417      1.226    rillig 	"missing new-style '\\177' or old-style number base",		// 359
    418      1.226    rillig 	"missing new-style number base after '\\177'",			// 360
    419      1.229    rillig 	"number base '%.*s' is %ju, must be 8, 10 or 16",		// 361
    420      1.233    rillig 	"conversion '%.*s' should not be escaped",			// 362
    421      1.240    rillig 	"escaped character '%.*s' in description of conversion '%.*s'", // 363
    422      1.226    rillig 	"missing bit position after '%.*s'",				// 364
    423      1.226    rillig 	"missing field width after '%.*s'",				// 365
    424      1.226    rillig 	"missing '\\0' at the end of '%.*s'",				// 366
    425      1.226    rillig 	"empty description in '%.*s'",					// 367
    426      1.233    rillig 	"missing comparison value after conversion '%.*s'",		// 368
    427      1.226    rillig 	"bit position '%.*s' in '%.*s' should be escaped as octal or hex", // 369
    428      1.226    rillig 	"field width '%.*s' in '%.*s' should be escaped as octal or hex", // 370
    429      1.226    rillig 	"bit position '%.*s' (%ju) in '%.*s' out of range %u..%u",	// 371
    430      1.231    rillig 	"field width '%.*s' (%ju) in '%.*s' out of range 0..64",	// 372
    431      1.226    rillig 	"bit field end %ju in '%.*s' out of range 0..64",		// 373
    432      1.233    rillig 	"unknown conversion '%.*s', must be one of 'bfF=:*'",		// 374
    433      1.229    rillig 	"comparison value '%.*s' (%ju) exceeds maximum field value %ju", // 375
    434      1.228    rillig 	"'%.*s' overlaps earlier '%.*s' on bit %u",			// 376
    435      1.230    rillig 	"redundant '\\0' at the end of the format",			// 377
    436      1.233    rillig 	"conversion '%.*s' is unreachable by input value",		// 378
    437      1.243    rillig 	"comparing integer '%s' to floating point constant %Lg",	// 379
    438      1.246    rillig 	"lossy conversion of %Lg to '%s', arg #%d",			// 380
    439      1.246    rillig 	"lossy conversion of %Lg to '%s'",				// 381
    440  1.246.2.1  perseant 	"constant assignment of type '%s' in operand of '%s' always evaluates to '%s'", // 382
    441  1.246.2.1  perseant 	"passing '%s' as argument %d to '%s' discards '%s'",		// 383
    442  1.246.2.1  perseant 	"function definition for '%s' with identifier list is obsolete in C23", // 384
    443  1.246.2.1  perseant 	"do-while macro '%.*s' ends with semicolon",			// 385
    444        1.1       cgd };
    445        1.1       cgd 
    446      1.220    rillig static bool is_suppressed[sizeof(msgs) / sizeof(msgs[0])];
    447      1.178    rillig 
    448      1.104    rillig static struct include_level {
    449      1.104    rillig 	const char *filename;
    450      1.104    rillig 	int lineno;
    451      1.104    rillig 	struct include_level *by;
    452      1.104    rillig } *includes;
    453      1.104    rillig 
    454      1.178    rillig void
    455      1.194    rillig suppress_messages(const char *p)
    456      1.178    rillig {
    457      1.194    rillig 	char *end;
    458      1.194    rillig 
    459      1.244    rillig 	for (; ch_isdigit(*p); p = end + 1) {
    460      1.194    rillig 		unsigned long id = strtoul(p, &end, 10);
    461      1.194    rillig 		if ((*end != '\0' && *end != ',') ||
    462      1.194    rillig 		    id >= sizeof(msgs) / sizeof(msgs[0]) ||
    463      1.194    rillig 		    msgs[id][0] == '\0')
    464      1.194    rillig 			break;
    465      1.178    rillig 
    466      1.179    rillig 		is_suppressed[id] = true;
    467      1.194    rillig 
    468      1.194    rillig 		if (*end == '\0')
    469      1.194    rillig 			return;
    470      1.178    rillig 	}
    471      1.199    rillig 	errx(1, "invalid message ID '%.*s'", (int)strcspn(p, ","), p);
    472      1.178    rillig }
    473      1.104    rillig 
    474      1.104    rillig void
    475      1.105    rillig update_location(const char *filename, int lineno, bool is_begin, bool is_end)
    476      1.104    rillig {
    477      1.104    rillig 	struct include_level *top;
    478      1.104    rillig 
    479      1.104    rillig 	top = includes;
    480      1.104    rillig 	if (is_begin && top != NULL)
    481      1.104    rillig 		top->lineno = curr_pos.p_line;
    482      1.104    rillig 
    483      1.104    rillig 	if (top == NULL || is_begin) {
    484      1.104    rillig 		top = xmalloc(sizeof(*top));
    485      1.104    rillig 		top->filename = filename;
    486      1.104    rillig 		top->lineno = lineno;
    487      1.104    rillig 		top->by = includes;
    488      1.104    rillig 		includes = top;
    489      1.104    rillig 	} else {
    490      1.109    rillig 		if (is_end) {
    491      1.104    rillig 			includes = top->by;
    492      1.104    rillig 			free(top);
    493      1.104    rillig 			top = includes;
    494      1.104    rillig 		}
    495      1.123    rillig 		if (top != NULL) {
    496      1.123    rillig 			top->filename = filename;
    497      1.123    rillig 			top->lineno = lineno;
    498      1.123    rillig 		}
    499      1.104    rillig 	}
    500      1.104    rillig }
    501      1.104    rillig 
    502      1.104    rillig static void
    503      1.104    rillig print_stack_trace(void)
    504      1.104    rillig {
    505      1.105    rillig 	const struct include_level *top;
    506      1.104    rillig 
    507      1.104    rillig 	if ((top = includes) == NULL)
    508      1.104    rillig 		return;
    509      1.105    rillig 	/*
    510      1.105    rillig 	 * Skip the innermost include level since it is already listed in the
    511      1.105    rillig 	 * diagnostic itself.  Furthermore, its lineno is the line number of
    512      1.105    rillig 	 * the last '#' line, not the current line.
    513      1.105    rillig 	 */
    514      1.104    rillig 	for (top = top->by; top != NULL; top = top->by)
    515      1.104    rillig 		printf("\tincluded from %s(%d)\n", top->filename, top->lineno);
    516      1.104    rillig }
    517      1.104    rillig 
    518        1.1       cgd /*
    519       1.56    rillig  * If Fflag is not set, lbasename() returns a pointer to the last
    520        1.1       cgd  * component of the path, otherwise it returns the argument.
    521        1.1       cgd  */
    522        1.1       cgd static const char *
    523       1.18        tv lbasename(const char *path)
    524        1.1       cgd {
    525        1.1       cgd 
    526        1.1       cgd 	if (Fflag)
    527       1.57    rillig 		return path;
    528        1.1       cgd 
    529      1.188    rillig 	const char *base = path;
    530      1.188    rillig 	for (const char *p = path; *p != '\0'; p++)
    531      1.188    rillig 		if (*p == '/')
    532      1.188    rillig 			base = p + 1;
    533      1.188    rillig 	return base;
    534        1.1       cgd }
    535        1.1       cgd 
    536      1.210    rillig static FILE *
    537      1.210    rillig output_channel(void)
    538      1.210    rillig {
    539      1.210    rillig 	return yflag ? stderr : stdout;
    540      1.210    rillig }
    541      1.210    rillig 
    542        1.3       jpo static void
    543      1.116    rillig verror_at(int msgid, const pos_t *pos, va_list ap)
    544        1.3       jpo {
    545        1.3       jpo 
    546      1.179    rillig 	if (is_suppressed[msgid])
    547       1.12  christos 		return;
    548       1.12  christos 
    549      1.210    rillig 	FILE *out = output_channel();
    550      1.210    rillig 	(void)fprintf(out, "%s(%d): error: ",
    551      1.210    rillig 	    lbasename(pos->p_file), pos->p_line);
    552      1.210    rillig 	(void)vfprintf(out, msgs[msgid], ap);
    553      1.210    rillig 	(void)fprintf(out, " [%d]\n", msgid);
    554      1.205    rillig 	seen_error = true;
    555      1.104    rillig 	print_stack_trace();
    556        1.3       jpo }
    557        1.3       jpo 
    558        1.3       jpo static void
    559      1.116    rillig vwarning_at(int msgid, const pos_t *pos, va_list ap)
    560        1.3       jpo {
    561        1.3       jpo 
    562      1.179    rillig 	if (is_suppressed[msgid])
    563       1.12  christos 		return;
    564       1.12  christos 
    565      1.132    rillig 	debug_step("%s: lwarn=%d msgid=%d", __func__, lwarn, msgid);
    566      1.115    rillig 	if (lwarn == LWARN_NONE || lwarn == msgid)
    567        1.3       jpo 		/* this warning is suppressed by a LINTED comment */
    568        1.3       jpo 		return;
    569        1.3       jpo 
    570      1.210    rillig 	FILE *out = output_channel();
    571      1.210    rillig 	(void)fprintf(out, "%s(%d): warning: ",
    572      1.210    rillig 	    lbasename(pos->p_file), pos->p_line);
    573      1.210    rillig 	(void)vfprintf(out, msgs[msgid], ap);
    574      1.210    rillig 	(void)fprintf(out, " [%d]\n", msgid);
    575      1.205    rillig 	seen_warning = true;
    576      1.104    rillig 	print_stack_trace();
    577        1.3       jpo }
    578        1.3       jpo 
    579      1.113    rillig static void
    580      1.116    rillig vmessage_at(int msgid, const pos_t *pos, va_list ap)
    581      1.113    rillig {
    582      1.113    rillig 
    583      1.179    rillig 	if (is_suppressed[msgid])
    584      1.113    rillig 		return;
    585      1.113    rillig 
    586      1.210    rillig 	FILE *out = output_channel();
    587      1.210    rillig 	(void)fprintf(out, "%s(%d): ",
    588      1.210    rillig 	    lbasename(pos->p_file), pos->p_line);
    589      1.210    rillig 	(void)vfprintf(out, msgs[msgid], ap);
    590      1.210    rillig 	(void)fprintf(out, " [%d]\n", msgid);
    591      1.113    rillig 	print_stack_trace();
    592      1.113    rillig }
    593      1.113    rillig 
    594      1.113    rillig void
    595      1.116    rillig (error_at)(int msgid, const pos_t *pos, ...)
    596      1.113    rillig {
    597      1.198    rillig 	va_list ap;
    598      1.113    rillig 
    599      1.113    rillig 	va_start(ap, pos);
    600      1.115    rillig 	verror_at(msgid, pos, ap);
    601      1.113    rillig 	va_end(ap);
    602      1.113    rillig }
    603      1.113    rillig 
    604        1.3       jpo void
    605      1.115    rillig (error)(int msgid, ...)
    606        1.1       cgd {
    607      1.198    rillig 	va_list ap;
    608        1.1       cgd 
    609      1.115    rillig 	va_start(ap, msgid);
    610      1.116    rillig 	verror_at(msgid, &curr_pos, ap);
    611        1.1       cgd 	va_end(ap);
    612        1.1       cgd }
    613        1.1       cgd 
    614        1.3       jpo void
    615       1.59    rillig assert_failed(const char *file, int line, const char *func, const char *cond)
    616       1.59    rillig {
    617       1.59    rillig 
    618  1.246.2.1  perseant #if LINT_FUZZING
    619      1.167    rillig 	/*
    620      1.219    rillig 	 * After encountering a parse error in the grammar, lint often does not
    621      1.219    rillig 	 * properly clean up its data structures, especially in 'dcs', the
    622      1.219    rillig 	 * stack of declaration levels.  This often leads to assertion
    623      1.219    rillig 	 * failures.  These cases are not interesting though, as the purpose of
    624      1.219    rillig 	 * lint is to check syntactically valid code.  In such a case, exit
    625      1.219    rillig 	 * gracefully.  This allows a fuzzer like afl to focus on more
    626      1.167    rillig 	 * interesting cases instead of reporting nonsense translation units
    627      1.167    rillig 	 * like 'f=({e:;}' or 'v(const(char););e(v){'.
    628      1.167    rillig 	 */
    629      1.167    rillig 	if (sytxerr > 0)
    630      1.167    rillig 		norecover();
    631  1.246.2.1  perseant #endif
    632      1.167    rillig 
    633      1.144    rillig 	(void)fflush(stdout);
    634       1.59    rillig 	(void)fprintf(stderr,
    635       1.59    rillig 	    "lint: assertion \"%s\" failed in %s at %s:%d near %s:%d\n",
    636      1.210    rillig 	    cond, func, file, line,
    637      1.210    rillig 	    lbasename(curr_pos.p_file), curr_pos.p_line);
    638      1.104    rillig 	print_stack_trace();
    639      1.156    rillig 	(void)fflush(stdout);
    640       1.59    rillig 	abort();
    641       1.59    rillig }
    642       1.59    rillig 
    643       1.59    rillig void
    644      1.116    rillig (warning_at)(int msgid, const pos_t *pos, ...)
    645      1.113    rillig {
    646      1.198    rillig 	va_list ap;
    647      1.113    rillig 
    648      1.113    rillig 	va_start(ap, pos);
    649      1.115    rillig 	vwarning_at(msgid, pos, ap);
    650      1.113    rillig 	va_end(ap);
    651      1.113    rillig }
    652      1.113    rillig 
    653      1.113    rillig void
    654      1.115    rillig (warning)(int msgid, ...)
    655        1.1       cgd {
    656      1.198    rillig 	va_list ap;
    657        1.3       jpo 
    658      1.115    rillig 	va_start(ap, msgid);
    659      1.116    rillig 	vwarning_at(msgid, &curr_pos, ap);
    660      1.113    rillig 	va_end(ap);
    661      1.113    rillig }
    662      1.113    rillig 
    663      1.113    rillig void
    664      1.116    rillig (message_at)(int msgid, const pos_t *pos, ...)
    665      1.113    rillig {
    666      1.113    rillig 	va_list ap;
    667      1.113    rillig 
    668      1.113    rillig 	va_start(ap, pos);
    669      1.115    rillig 	vmessage_at(msgid, pos, ap);
    670        1.3       jpo 	va_end(ap);
    671        1.3       jpo }
    672        1.3       jpo 
    673       1.63    rillig void
    674      1.115    rillig (c99ism)(int msgid, ...)
    675       1.25     perry {
    676      1.198    rillig 	va_list ap;
    677      1.164    rillig 
    678      1.164    rillig 	if (allow_c99)
    679      1.164    rillig 		return;
    680       1.25     perry 
    681      1.115    rillig 	va_start(ap, msgid);
    682      1.164    rillig 	int severity = (!allow_gcc ? 1 : 0) + (!allow_trad ? 1 : 0);
    683      1.161    rillig 	if (severity == 2)
    684      1.116    rillig 		verror_at(msgid, &curr_pos, ap);
    685      1.161    rillig 	if (severity == 1)
    686      1.116    rillig 		vwarning_at(msgid, &curr_pos, ap);
    687       1.25     perry 	va_end(ap);
    688        1.1       cgd }
    689        1.1       cgd 
    690      1.108    rillig void
    691      1.115    rillig (c11ism)(int msgid, ...)
    692      1.108    rillig {
    693      1.198    rillig 	va_list ap;
    694      1.108    rillig 
    695      1.162    rillig 	/* FIXME: C11 mode has nothing to do with GCC mode. */
    696      1.163    rillig 	if (allow_c11 || allow_gcc)
    697      1.110    rillig 		return;
    698      1.115    rillig 	va_start(ap, msgid);
    699      1.116    rillig 	verror_at(msgid, &curr_pos, ap);
    700      1.108    rillig 	va_end(ap);
    701      1.108    rillig }
    702      1.108    rillig 
    703      1.204    rillig void
    704      1.204    rillig (c23ism)(int msgid, ...)
    705      1.204    rillig {
    706      1.204    rillig 	va_list ap;
    707      1.204    rillig 
    708      1.204    rillig 	if (allow_c23)
    709      1.204    rillig 		return;
    710      1.204    rillig 	va_start(ap, msgid);
    711      1.204    rillig 	verror_at(msgid, &curr_pos, ap);
    712      1.204    rillig 	va_end(ap);
    713      1.204    rillig }
    714      1.204    rillig 
    715      1.162    rillig bool
    716      1.115    rillig (gnuism)(int msgid, ...)
    717        1.1       cgd {
    718      1.198    rillig 	va_list ap;
    719      1.164    rillig 	int severity = (!allow_gcc ? 1 : 0) +
    720      1.164    rillig 	    (!allow_trad && !allow_c99 ? 1 : 0);
    721        1.1       cgd 
    722      1.115    rillig 	va_start(ap, msgid);
    723      1.161    rillig 	if (severity == 2)
    724      1.116    rillig 		verror_at(msgid, &curr_pos, ap);
    725      1.161    rillig 	if (severity == 1)
    726      1.116    rillig 		vwarning_at(msgid, &curr_pos, ap);
    727        1.1       cgd 	va_end(ap);
    728      1.162    rillig 	return severity > 0;
    729        1.1       cgd }
    730      1.181    rillig 
    731      1.181    rillig 
    732      1.181    rillig static const char *queries[] = {
    733      1.181    rillig 	"",			/* unused, to make queries 1-based */
    734      1.225    rillig 	"implicit conversion from floating point '%s' to integer '%s'",	// Q1
    735      1.225    rillig 	"cast from floating point '%s' to integer '%s'",		// Q2
    736      1.225    rillig 	"implicit conversion changes sign from '%s' to '%s'",		// Q3
    737      1.225    rillig 	"usual arithmetic conversion for '%s' from '%s' to '%s'",	// Q4
    738      1.225    rillig 	"pointer addition has integer on the left-hand side",		// Q5
    739      1.225    rillig 	"no-op cast from '%s' to '%s'",					// Q6
    740      1.225    rillig 	"redundant cast from '%s' to '%s' before assignment",		// Q7
    741      1.225    rillig 	"octal number '%.*s'",						// Q8
    742      1.225    rillig 	"parenthesized return value",					// Q9
    743      1.225    rillig 	"chained assignment with '%s' and '%s'",			// Q10
    744      1.225    rillig 	"static variable '%s' in function",				// Q11
    745      1.225    rillig 	"comma operator with types '%s' and '%s'",			// Q12
    746      1.225    rillig 	"redundant 'extern' in function declaration of '%s'",		// Q13
    747      1.225    rillig 	"comparison '%s' of 'char' with plain integer %d",		// Q14
    748      1.225    rillig 	"implicit conversion from integer 0 to pointer '%s'",		// Q15
    749      1.225    rillig 	"'%s' was declared 'static', now non-'static'",			// Q16
    750      1.225    rillig 	"invisible character U+%04X in %s",				// Q17
    751      1.235    rillig 	"const automatic variable '%s'",				// Q18
    752      1.239    rillig 	"implicit conversion from integer '%s' to floating point '%s'",	// Q19
    753      1.241    rillig 	"implicit narrowing conversion from void pointer to '%s'",	// Q20
    754  1.246.2.1  perseant 	"typedef '%s' of struct type '%s'",				// Q21
    755  1.246.2.1  perseant 	"typedef '%s' of union type '%s'",				// Q22
    756  1.246.2.1  perseant 	"typedef '%s' of pointer to struct type '%s'",			// Q23
    757  1.246.2.1  perseant 	"typedef '%s' of pointer to union type '%s'",			// Q24
    758      1.181    rillig };
    759      1.181    rillig 
    760  1.246.2.1  perseant // Omit any expensive computations in the default mode where none of the
    761  1.246.2.1  perseant // queries are enabled.  Function calls in message details don't need to be
    762  1.246.2.1  perseant // guarded by this flag, as that happens in the query_message macro already.
    763  1.246.2.1  perseant bool any_query_enabled;
    764      1.221    rillig bool is_query_enabled[sizeof(queries) / sizeof(queries[0])];
    765      1.181    rillig 
    766      1.181    rillig void
    767      1.181    rillig (query_message)(int query_id, ...)
    768      1.181    rillig {
    769      1.181    rillig 
    770      1.181    rillig 	if (!is_query_enabled[query_id])
    771      1.181    rillig 		return;
    772      1.181    rillig 
    773      1.210    rillig 	va_list ap;
    774      1.210    rillig 	FILE *out = output_channel();
    775      1.210    rillig 	(void)fprintf(out, "%s(%d): ",
    776      1.210    rillig 	    lbasename(curr_pos.p_file), curr_pos.p_line);
    777      1.181    rillig 	va_start(ap, query_id);
    778      1.210    rillig 	(void)vfprintf(out, queries[query_id], ap);
    779      1.181    rillig 	va_end(ap);
    780      1.210    rillig 	(void)fprintf(out, " [Q%d]\n", query_id);
    781      1.181    rillig 	print_stack_trace();
    782      1.181    rillig }
    783      1.181    rillig 
    784      1.181    rillig void
    785      1.194    rillig enable_queries(const char *p)
    786      1.181    rillig {
    787      1.194    rillig 	char *end;
    788      1.181    rillig 
    789      1.244    rillig 	for (; ch_isdigit(*p); p = end + 1) {
    790      1.194    rillig 		unsigned long id = strtoul(p, &end, 10);
    791      1.194    rillig 		if ((*end != '\0' && *end != ',') ||
    792      1.194    rillig 		    id >= sizeof(queries) / sizeof(queries[0]) ||
    793      1.194    rillig 		    queries[id][0] == '\0')
    794      1.194    rillig 			break;
    795      1.181    rillig 
    796      1.181    rillig 		any_query_enabled = true;
    797      1.181    rillig 		is_query_enabled[id] = true;
    798      1.181    rillig 
    799      1.194    rillig 		if (*end == '\0')
    800      1.194    rillig 			return;
    801      1.181    rillig 	}
    802      1.199    rillig 	errx(1, "invalid query ID '%.*s'", (int)strcspn(p, ","), p);
    803      1.181    rillig }
    804