diff options
40 files changed, 0 insertions, 21874 deletions
diff --git a/usr.bin/xlint/Makefile b/usr.bin/xlint/Makefile deleted file mode 100644 index 78522e050b1..00000000000 --- a/usr.bin/xlint/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# $OpenBSD: Makefile,v 1.3 1997/09/21 11:52:12 deraadt Exp $ - -SUBDIR= lint1 lint2 xlint llib - -.include <bsd.subdir.mk> diff --git a/usr.bin/xlint/PSD.doc/Makefile b/usr.bin/xlint/PSD.doc/Makefile deleted file mode 100644 index 69fda41be1c..00000000000 --- a/usr.bin/xlint/PSD.doc/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# OpenBSD$ - -DIR= psd/09.lint -SRCS= lint.ms -MACROS= -ms -REFER= refer -e -p /usr/doc/run/Ind - -paper.${PRINTER}: ${SRCS} - ${REFER} ${SRCS} | ${ROFF} > ${.TARGET} - -.include <bsd.doc.mk> diff --git a/usr.bin/xlint/PSD.doc/lint.ms b/usr.bin/xlint/PSD.doc/lint.ms deleted file mode 100644 index 79f59bf4cff..00000000000 --- a/usr.bin/xlint/PSD.doc/lint.ms +++ /dev/null @@ -1,1101 +0,0 @@ -.\" $OpenBSD: lint.ms,v 1.1 2003/06/26 16:30:10 mickey Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed or owned by Caldera -.\" International, Inc. -.\" 4. Neither the name of Caldera International, Inc. nor the names of other -.\" contributors may be used to endorse or promote products derived from -.\" this software without specific prior written permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT, -.\" INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)lint.ms 6.2 (Berkeley) 4/17/91 -.\" -.EH 'PS1:9-%''Lint, a C Program Checker' -.OH 'Lint, a C Program Checker''PS1:9-%' -.\".RP -.ND "July 26, 1978" -.OK -.\"Program Portability -.\"Strong Type Checking -.TL -Lint, a C Program Checker -.AU "MH 2C-559" 3968 -S. C. Johnson -.AI -.MH -.AB -.PP -.I Lint -is a command which examines C source programs, -detecting -a number of bugs and obscurities. -It enforces the type rules of C more strictly than -the C compilers. -It may also be used to enforce a number of portability -restrictions involved in moving -programs between different machines and/or operating systems. -Another option detects a number of wasteful, or error prone, constructions -which nevertheless are, strictly speaking, legal. -.PP -.I Lint -accepts multiple input files and library specifications, and checks them for consistency. -.PP -The separation of function between -.I lint -and the C compilers has both historical and practical -rationale. -The compilers turn C programs into executable files rapidly -and efficiently. -This is possible in part because the -compilers do not do sophisticated -type checking, especially between -separately compiled programs. -.I Lint -takes a more global, leisurely view of the program, -looking much more carefully at the compatibilities. -.PP -This document discusses the use of -.I lint , -gives an overview of the implementation, and gives some hints on the -writing of machine independent C code. -.AE -.CS 10 2 12 0 0 5 -.SH -Introduction and Usage -.PP -Suppose there are two C -.[ -Kernighan Ritchie Programming Prentice 1978 -.] -source files, -.I file1. c -and -.I file2.c , -which are ordinarily compiled and loaded together. -Then the command -.DS -lint file1.c file2.c -.DE -produces messages describing inconsistencies and inefficiencies -in the programs. -The program enforces the typing rules of C -more strictly than the C compilers -(for both historical and practical reasons) -enforce them. -The command -.DS -lint \-p file1.c file2.c -.DE -will produce, in addition to the above messages, additional messages -which relate to the portability of the programs to other operating -systems and machines. -Replacing the -.B \-p -by -.B \-h -will produce messages about various error-prone or wasteful constructions -which, strictly speaking, are not bugs. -Saying -.B \-hp -gets the whole works. -.PP -The next several sections describe the major messages; -the document closes with sections -discussing the implementation and giving suggestions -for writing portable C. -An appendix gives a summary of the -.I lint -options. -.SH -A Word About Philosophy -.PP -Many of the facts which -.I lint -needs may be impossible to -discover. -For example, whether a given function in a program ever gets called -may depend on the input data. -Deciding whether -.I exit -is ever called is equivalent to solving the famous ``halting problem,'' known to be -recursively undecidable. -.PP -Thus, most of the -.I lint -algorithms are a compromise. -If a function is never mentioned, it can never be called. -If a function is mentioned, -.I lint -assumes it can be called; this is not necessarily so, but in practice is quite reasonable. -.PP -.I Lint -tries to give information with a high degree of relevance. -Messages of the form ``\fIxxx\fR might be a bug'' -are easy to generate, but are acceptable only in proportion -to the fraction of real bugs they uncover. -If this fraction of real bugs is too small, the messages lose their credibility -and serve merely to clutter up the output, -obscuring the more important messages. -.PP -Keeping these issues in mind, we now consider in more detail -the classes of messages which -.I lint -produces. -.SH -Unused Variables and Functions -.PP -As sets of programs evolve and develop, -previously used variables and arguments to -functions may become unused; -it is not uncommon for external variables, or even entire -functions, to become unnecessary, and yet -not be removed from the source. -These ``errors of commission'' rarely cause working programs to fail, but they are a source -of inefficiency, and make programs harder to understand -and change. -Moreover, information about such unused variables and functions can occasionally -serve to discover bugs; if a function does a necessary job, and -is never called, something is wrong! -.PP -.I Lint -complains about variables and functions which are defined but not otherwise -mentioned. -An exception is variables which are declared through explicit -.B extern -statements but are never referenced; thus the statement -.DS -extern float sin(\|); -.DE -will evoke no comment if -.I sin -is never used. -Note that this agrees with the semantics of the C compiler. -In some cases, these unused external declarations might be of some interest; they -can be discovered by adding the -.B \-x -flag to the -.I lint -invocation. -.PP -Certain styles of programming -require many functions to be written with similar interfaces; -frequently, some of the arguments may be unused -in many of the calls. -The -.B \-v -option is available to suppress the printing of -complaints about unused arguments. -When -.B \-v -is in effect, no messages are produced about unused -arguments except for those -arguments which are unused and also declared as -register arguments; this can be considered -an active (and preventable) waste of the register -resources of the machine. -.PP -There is one case where information about unused, or -undefined, variables is more distracting -than helpful. -This is when -.I lint -is applied to some, but not all, files out of a collection -which are to be loaded together. -In this case, many of the functions and variables defined -may not be used, and, conversely, -many functions and variables defined elsewhere may be used. -The -.B \-u -flag may be used to suppress the spurious messages which might otherwise appear. -.SH -Set/Used Information -.PP -.I Lint -attempts to detect cases where a variable is used before it is set. -This is very difficult to do well; -many algorithms take a good deal of time and space, -and still produce messages about perfectly valid programs. -.I Lint -detects local variables (automatic and register storage classes) -whose first use appears physically earlier in the input file than the first assignment to the variable. -It assumes that taking the address of a variable constitutes a ``use,'' since the actual use -may occur at any later time, in a data dependent fashion. -.PP -The restriction to the physical appearance of variables in the file makes the -algorithm very simple and quick to implement, -since the true flow of control need not be discovered. -It does mean that -.I lint -can complain about some programs which are legal, -but these programs would probably be considered bad on stylistic grounds (e.g. might -contain at least two \fBgoto\fR's). -Because static and external variables are initialized to 0, -no meaningful information can be discovered about their uses. -The algorithm deals correctly, however, with initialized automatic variables, and variables -which are used in the expression which first sets them. -.PP -The set/used information also permits recognition of those local variables which are set -and never used; these form a frequent source of inefficiencies, and may also be symptomatic of bugs. -.SH -Flow of Control -.PP -.I Lint -attempts to detect unreachable portions of the programs which it processes. -It will complain about unlabeled statements immediately following -\fBgoto\fR, \fBbreak\fR, \fBcontinue\fR, or \fBreturn\fR statements. -An attempt is made to detect loops which can never be left at the bottom, detecting the -special cases -\fBwhile\fR( 1 ) and \fBfor\fR(;;) as infinite loops. -.I Lint -also complains about loops which cannot be entered at the top; -some valid programs may have such loops, but at best they are bad style, -at worst bugs. -.PP -.I Lint -has an important area of blindness in the flow of control algorithm: -it has no way of detecting functions which are called and never return. -Thus, a call to -.I exit -may cause unreachable code which -.I lint -does not detect; the most serious effects of this are in the -determination of returned function values (see the next section). -.PP -One form of unreachable statement is not usually complained about by -.I lint; -a -.B break -statement that cannot be reached causes no message. -Programs generated by -.I yacc , -.[ -Johnson Yacc 1975 -.] -and especially -.I lex , -.[ -Lesk Lex -.] -may have literally hundreds of unreachable -.B break -statements. -The -.B \-O -flag in the C compiler will often eliminate the resulting object code inefficiency. -Thus, these unreached statements are of little importance, -there is typically nothing the user can do about them, and the -resulting messages would clutter up the -.I lint -output. -If these messages are desired, -.I lint -can be invoked with the -.B \-b -option. -.SH -Function Values -.PP -Sometimes functions return values which are never used; -sometimes programs incorrectly use function ``values'' -which have never been returned. -.I Lint -addresses this problem in a number of ways. -.PP -Locally, within a function definition, -the appearance of both -.DS -return( \fIexpr\fR ); -.DE -and -.DS -return ; -.DE -statements is cause for alarm; -.I lint -will give the message -.DS -function \fIname\fR contains return(e) and return -.DE -The most serious difficulty with this is detecting when a function return is implied -by flow of control reaching the end of the function. -This can be seen with a simple example: -.DS -.ta .5i 1i 1.5i -\fRf ( a ) { - if ( a ) return ( 3 ); - g (\|); - } -.DE -Notice that, if \fIa\fR tests false, \fIf\fR will call \fIg\fR and then return -with no defined return value; this will trigger a complaint from -.I lint . -If \fIg\fR, like \fIexit\fR, never returns, -the message will still be produced when in fact nothing is wrong. -.PP -In practice, some potentially serious bugs have been discovered by this feature; -it also accounts for a substantial fraction of the ``noise'' messages produced -by -.I lint . -.PP -On a global scale, -.I lint -detects cases where a function returns a value, but this value is sometimes, -or always, unused. -When the value is always unused, it may constitute an inefficiency in the function definition. -When the value is sometimes unused, it may represent bad style (e.g., not testing for -error conditions). -.PP -The dual problem, using a function value when the function does not return one, -is also detected. -This is a serious problem. -Amazingly, this bug has been observed on a couple of occasions -in ``working'' programs; the desired function value just happened to have been computed -in the function return register! -.SH -Type Checking -.PP -.I Lint -enforces the type checking rules of C more strictly than the compilers do. -The additional checking is in four major areas: -across certain binary operators and implied assignments, -at the structure selection operators, -between the definition and uses of functions, -and in the use of enumerations. -.PP -There are a number of operators which have an implied balancing between types of the operands. -The assignment, conditional ( ?\|: ), and relational operators -have this property; the argument -of a \fBreturn\fR statement, -and expressions used in initialization also suffer similar conversions. -In these operations, -\fBchar\fR, \fBshort\fR, \fBint\fR, \fBlong\fR, \fBunsigned\fR, \fBfloat\fR, and \fBdouble\fR types may be freely intermixed. -The types of pointers must agree exactly, -except that arrays of \fIx\fR's can, of course, be intermixed with pointers to \fIx\fR's. -.PP -The type checking rules also require that, in structure references, the -left operand of the \(em> be a pointer to structure, the left operand of the \fB.\fR -be a structure, and the right operand of these operators be a member -of the structure implied by the left operand. -Similar checking is done for references to unions. -.PP -Strict rules apply to function argument and return value -matching. -The types \fBfloat\fR and \fBdouble\fR may be freely matched, -as may the types \fBchar\fR, \fBshort\fR, \fBint\fR, and \fBunsigned\fR. -Also, pointers can be matched with the associated arrays. -Aside from this, all actual arguments must agree in type with their declared counterparts. -.PP -With enumerations, checks are made that enumeration variables or members are not mixed -with other types, or other enumerations, -and that the only operations applied are =, initialization, ==, !=, and function arguments and return values. -.SH -Type Casts -.PP -The type cast feature in C was introduced largely as an aid -to producing more portable programs. -Consider the assignment -.DS -p = 1 ; -.DE -where -.I p -is a character pointer. -.I Lint -will quite rightly complain. -Now, consider the assignment -.DS -p = (char \(**)1 ; -.DE -in which a cast has been used to -convert the integer to a character pointer. -The programmer obviously had a strong motivation -for doing this, and has clearly signaled his intentions. -It seems harsh for -.I lint -to continue to complain about this. -On the other hand, if this code is moved to another -machine, such code should be looked at carefully. -The -.B \-c -flag controls the printing of comments about casts. -When -.B \-c -is in effect, casts are treated as though they were assignments -subject to complaint; otherwise, all legal casts are passed without comment, -no matter how strange the type mixing seems to be. -.SH -Nonportable Character Use -.PP -On the PDP-11, characters are signed quantities, with a range -from \-128 to 127. -On most of the other C implementations, characters take on only positive -values. -Thus, -.I lint -will flag certain comparisons and assignments as being -illegal or nonportable. -For example, the fragment -.DS -char c; - ... -if( (c = getchar(\|)) < 0 ) .... -.DE -works on the PDP-11, but -will fail on machines where characters always take -on positive values. -The real solution is to declare -.I c -an integer, since -.I getchar -is actually returning -integer values. -In any case, -.I lint -will say -``nonportable character comparison''. -.PP -A similar issue arises with bitfields; when assignments -of constant values are made to bitfields, the field may -be too small to hold the value. -This is especially true because -on some machines bitfields are considered as signed -quantities. -While it may seem unintuitive to consider -that a two bit field declared of type -.B int -cannot hold the value 3, the problem disappears -if the bitfield is declared to have type -.B unsigned . -.SH -Assignments of longs to ints -.PP -Bugs may arise from the assignment of -.B long -to -an -.B int , -which loses accuracy. -This may happen in programs -which have been incompletely converted to use -.B typedefs . -When a -.B typedef -variable -is changed from \fBint\fR to \fBlong\fR, -the program can stop working because -some intermediate results may be assigned -to \fBints\fR, losing accuracy. -Since there are a number of legitimate reasons for -assigning \fBlongs\fR to \fBints\fR, the detection -of these assignments is enabled -by the -.B \-a -flag. -.SH -Strange Constructions -.PP -Several perfectly legal, but somewhat strange, constructions -are flagged by -.I lint; -the messages hopefully encourage better code quality, clearer style, and -may even point out bugs. -The -.B \-h -flag is used to enable these checks. -For example, in the statement -.DS -\(**p++ ; -.DE -the \(** does nothing; this provokes the message ``null effect'' from -.I lint . -The program fragment -.DS -unsigned x ; -if( x < 0 ) ... -.DE -is clearly somewhat strange; the -test will never succeed. -Similarly, the test -.DS -if( x > 0 ) ... -.DE -is equivalent to -.DS -if( x != 0 ) -.DE -which may not be the intended action. -.I Lint -will say ``degenerate unsigned comparison'' in these cases. -If one says -.DS -if( 1 != 0 ) .... -.DE -.I lint -will report -``constant in conditional context'', since the comparison -of 1 with 0 gives a constant result. -.PP -Another construction -detected by -.I lint -involves -operator precedence. -Bugs which arise from misunderstandings about the precedence -of operators can be accentuated by spacing and formatting, -making such bugs extremely hard to find. -For example, the statements -.DS -if( x&077 == 0 ) ... -.DE -or -.DS -x<\h'-.3m'<2 + 40 -.DE -probably do not do what was intended. -The best solution is to parenthesize such expressions, -and -.I lint -encourages this by an appropriate message. -.PP -Finally, when the -.B \-h -flag is in force -.I lint -complains about variables which are redeclared in inner blocks -in a way that conflicts with their use in outer blocks. -This is legal, but is considered by many (including the author) to -be bad style, usually unnecessary, and frequently a bug. -.SH -Ancient History -.PP -There are several forms of older syntax which are being officially -discouraged. -These fall into two classes, assignment operators and initialization. -.PP -The older forms of assignment operators (e.g., =+, =\-, . . . ) -could cause ambiguous expressions, such as -.DS -a =\-1 ; -.DE -which could be taken as either -.DS -a =\- 1 ; -.DE -or -.DS -a = \-1 ; -.DE -The situation is especially perplexing if this -kind of ambiguity arises as the result of a macro substitution. -The newer, and preferred operators (+=, \-=, etc. ) -have no such ambiguities. -To spur the abandonment of the older forms, -.I lint -complains about these old fashioned operators. -.PP -A similar issue arises with initialization. -The older language allowed -.DS -int x \fR1 ; -.DE -to initialize -.I x -to 1. -This also caused syntactic difficulties: for example, -.DS -int x ( \-1 ) ; -.DE -looks somewhat like the beginning of a function declaration: -.DS -int x ( y ) { . . . -.DE -and the compiler must read a fair ways past -.I x -in order to sure what the declaration really is.. -Again, the problem is even more perplexing when the -initializer involves a macro. -The current syntax places an equals sign between the -variable and the initializer: -.DS -int x = \-1 ; -.DE -This is free of any possible syntactic ambiguity. -.SH -Pointer Alignment -.PP -Certain pointer assignments may be reasonable on some machines, -and illegal on others, due entirely to -alignment restrictions. -For example, on the PDP-11, it is reasonable -to assign integer pointers to double pointers, since -double precision values may begin on any integer boundary. -On the Honeywell 6000, double precision values must begin -on even word boundaries; -thus, not all such assignments make sense. -.I Lint -tries to detect cases where pointers are assigned to other -pointers, and such alignment problems might arise. -The message ``possible pointer alignment problem'' -results from this situation whenever either the -.B \-p -or -.B \-h -flags are in effect. -.SH -Multiple Uses and Side Effects -.PP -In complicated expressions, the best order in which to evaluate -subexpressions may be highly machine dependent. -For example, on machines (like the PDP-11) in which the stack -runs backwards, function arguments will probably be best evaluated -from right-to-left; on machines with a stack running forward, -left-to-right seems most attractive. -Function calls embedded as arguments of other functions -may or may not be treated similarly to ordinary arguments. -Similar issues arise with other operators which have side effects, -such as the assignment operators and the increment and decrement operators. -.PP -In order that the efficiency of C on a particular machine not be -unduly compromised, the C language leaves the order -of evaluation of complicated expressions up to the -local compiler, and, in fact, the various C compilers have considerable -differences in the order in which they will evaluate complicated -expressions. -In particular, if any variable is changed by a side effect, and -also used elsewhere in the same expression, the result is explicitly undefined. -.PP -.I Lint -checks for the important special case where -a simple scalar variable is affected. -For example, the statement -.DS -\fIa\fR[\fIi\|\fR] = \fIb\fR[\fIi\fR++] ; -.DE -will draw the complaint: -.DS -warning: \fIi\fR evaluation order undefined -.DE -.SH -Implementation -.PP -.I Lint -consists of two programs and a driver. -The first program is a version of the -Portable C Compiler -.[ -Johnson Ritchie BSTJ Portability Programs System -.] -.[ -Johnson portable compiler 1978 -.] -which is the basis of the -IBM 370, Honeywell 6000, and Interdata 8/32 C compilers. -This compiler does lexical and syntax analysis on the input text, -constructs and maintains symbol tables, and builds trees for expressions. -Instead of writing an intermediate file which is passed to -a code generator, as the other compilers -do, -.I lint -produces an intermediate file which consists of lines of ascii text. -Each line contains an external variable name, -an encoding of the context in which it was seen (use, definition, declaration, etc.), -a type specifier, and a source file name and line number. -The information about variables local to a function or file -is collected -by accessing the symbol table, and examining the expression trees. -.PP -Comments about local problems are produced as detected. -The information about external names is collected -onto an intermediate file. -After all the source files and library descriptions have -been collected, the intermediate file is sorted -to bring all information collected about a given external -name together. -The second, rather small, program then reads the lines -from the intermediate file and compares all of the -definitions, declarations, and uses for consistency. -.PP -The driver controls this -process, and is also responsible for making the options available -to both passes of -.I lint . -.SH -Portability -.PP -C on the Honeywell and IBM systems is used, in part, to write system code for the host operating system. -This means that the implementation of C tends to follow local conventions rather than -adhere strictly to -.UX -system conventions. -Despite these differences, many C programs have been successfully moved to GCOS and the various IBM -installations with little effort. -This section describes some of the differences between the implementations, and -discusses the -.I lint -features which encourage portability. -.PP -Uninitialized external variables are treated differently in different -implementations of C. -Suppose two files both contain a declaration without initialization, such as -.DS -int a ; -.DE -outside of any function. -The -.UX -loader will resolve these declarations, and cause only a single word of storage -to be set aside for \fIa\fR. -Under the GCOS and IBM implementations, this is not feasible (for various stupid reasons!) -so each such declaration causes a word of storage to be set aside and called \fIa\fR. -When loading or library editing takes place, this causes fatal conflicts which prevent -the proper operation of the program. -If -.I lint -is invoked with the \fB\-p\fR flag, -it will detect such multiple definitions. -.PP -A related difficulty comes from the amount of information retained about external names during the -loading process. -On the -.UX -system, externally known names have seven significant characters, with the upper/lower -case distinction kept. -On the IBM systems, there are eight significant characters, but the case distinction -is lost. -On GCOS, there are only six characters, of a single case. -This leads to situations where programs run on the -.UX -system, but encounter loader -problems on the IBM or GCOS systems. -.I Lint -.B \-p -causes all external symbols to be mapped to one case and truncated to six characters, -providing a worst-case analysis. -.PP -A number of differences arise in the area of character handling: characters in the -.UX -system are eight bit ascii, while they are eight bit ebcdic on the IBM, and -nine bit ascii on GCOS. -Moreover, character strings go from high to low bit positions (``left to right'') -on GCOS and IBM, and low to high (``right to left'') on the PDP-11. -This means that code attempting to construct strings -out of character constants, or attempting to use characters as indices -into arrays, must be looked at with great suspicion. -.I Lint -is of little help here, except to flag multi-character character constants. -.PP -Of course, the word sizes are different! -This causes less trouble than might be expected, at least when -moving from the -.UX -system (16 bit words) to the IBM (32 bits) or GCOS (36 bits). -The main problems are likely to arise in shifting or masking. -C now supports a bit-field facility, which can be used to write much of -this code in a reasonably portable way. -Frequently, portability of such code can be enhanced by -slight rearrangements in coding style. -Many of the incompatibilities seem to have the flavor of writing -.DS -x &= 0177700 ; -.DE -to clear the low order six bits of \fIx\fR. -This suffices on the PDP-11, but fails badly on GCOS and IBM. -If the bit field feature cannot be used, the same effect can be obtained by -writing -.DS -x &= \(ap 077 ; -.DE -which will work on all these machines. -.PP -The right shift operator is arithmetic shift on the PDP-11, and logical shift on most -other machines. -To obtain a logical shift on all machines, the left operand can be -typed \fBunsigned\fR. -Characters are considered signed integers on the PDP-11, and unsigned on the other machines. -This persistence of the sign bit may be reasonably considered a bug in the PDP-11 hardware -which has infiltrated itself into the C language. -If there were a good way to discover the programs which would be affected, C could be changed; -in any case, -.I lint -is no help here. -.PP -The above discussion may have made the problem of portability seem -bigger than it in fact is. -The issues involved here are rarely subtle or mysterious, at least to the -implementor of the program, although they can involve some work to straighten out. -The most serious bar to the portability of -.UX -system utilities has been the inability to mimic -essential -.UX -system functions on the other systems. -The inability to seek to a random character position in a text file, or to establish a pipe -between processes, has involved far more rewriting -and debugging than any of the differences in C compilers. -On the other hand, -.I lint -has been very helpful -in moving the -.UX -operating system and associated -utility programs to other machines. -.SH -Shutting Lint Up -.PP -There are occasions when -the programmer is smarter than -.I lint . -There may be valid reasons for ``illegal'' type casts, -functions with a variable number of arguments, etc. -Moreover, as specified above, the flow of control information -produced by -.I lint -often has blind spots, causing occasional spurious -messages about perfectly reasonable programs. -Thus, some way of communicating with -.I lint , -typically to shut it up, is desirable. -.PP -The form which this mechanism should take is not at all clear. -New keywords would require current and old compilers to -recognize these keywords, if only to ignore them. -This has both philosophical and practical problems. -New preprocessor syntax suffers from similar problems. -.PP -What was finally done was to cause a number of words -to be recognized by -.I lint -when they were embedded in comments. -This required minimal preprocessor changes; -the preprocessor just had to agree to pass comments -through to its output, instead of deleting them -as had been previously done. -Thus, -.I lint -directives are invisible to the compilers, and -the effect on systems with the older preprocessors -is merely that the -.I lint -directives don't work. -.PP -The first directive is concerned with flow of control information; -if a particular place in the program cannot be reached, -but this is not apparent to -.I lint , -this can be asserted by the directive -.DS -/* NOTREACHED */ -.DE -at the appropriate spot in the program. -Similarly, if it is desired to turn off -strict type checking for -the next expression, the directive -.DS -/* NOSTRICT */ -.DE -can be used; the situation reverts to the -previous default after the next expression. -The -.B \-v -flag can be turned on for one function by the directive -.DS -/* ARGSUSED */ -.DE -Complaints about variable number of arguments in calls to a function -can be turned off by the directive -.DS -/* VARARGS */ -.DE -preceding the function definition. -In some cases, it is desirable to check the -first several arguments, and leave the later arguments unchecked. -This can be done by following the VARARGS keyword immediately -with a digit giving the number of arguments which should be checked; thus, -.DS -/* VARARGS2 */ -.DE -will cause the first two arguments to be checked, the others unchecked. -Finally, the directive -.DS -/* LINTLIBRARY */ -.DE -at the head of a file identifies this file as -a library declaration file; this topic is worth a -section by itself. -.SH -Library Declaration Files -.PP -.I Lint -accepts certain library directives, such as -.DS -\-ly -.DE -and tests the source files for compatibility with these libraries. -This is done by accessing library description files whose -names are constructed from the library directives. -These files all begin with the directive -.DS -/* LINTLIBRARY */ -.DE -which is followed by a series of dummy function -definitions. -The critical parts of these definitions -are the declaration of the function return type, -whether the dummy function returns a value, and -the number and types of arguments to the function. -The VARARGS and ARGSUSED directives can -be used to specify features of the library functions. -.PP -.I Lint -library files are processed almost exactly like ordinary -source files. -The only difference is that functions which are defined on a library file, -but are not used on a source file, draw no complaints. -.I Lint -does not simulate a full library search algorithm, -and complains if the source files contain a redefinition of -a library routine (this is a feature!). -.PP -By default, -.I lint -checks the programs it is given against a standard library -file, which contains descriptions of the programs which -are normally loaded when -a C program -is run. -When the -.B -p -flag is in effect, another file is checked containing -descriptions of the standard I/O library routines -which are expected to be portable across various machines. -The -.B -n -flag can be used to suppress all library checking. -.SH -Bugs, etc. -.PP -.I Lint -was a difficult program to write, partially -because it is closely connected with matters of programming style, -and partially because users usually don't notice bugs which cause -.I lint -to miss errors which it should have caught. -(By contrast, if -.I lint -incorrectly complains about something that is correct, the -programmer reports that immediately!) -.PP -A number of areas remain to be further developed. -The checking of structures and arrays is rather inadequate; -size -incompatibilities go unchecked, -and no attempt is made to match up structure and union -declarations across files. -Some stricter checking of the use of the -.B typedef -is clearly desirable, but what checking is appropriate, and how -to carry it out, is still to be determined. -.PP -.I Lint -shares the preprocessor with the C compiler. -At some point it may be appropriate for a -special version of the preprocessor to be constructed -which checks for things such as unused macro definitions, -macro arguments which have side effects which are -not expanded at all, or are expanded more than once, etc. -.PP -The central problem with -.I lint -is the packaging of the information which it collects. -There are many options which -serve only to turn off, or slightly modify, -certain features. -There are pressures to add even more of these options. -.PP -In conclusion, it appears that the general notion of having two -programs is a good one. -The compiler concentrates on quickly and accurately turning the -program text into bits which can be run; -.I lint -concentrates on issues -of portability, style, and efficiency. -.I Lint -can afford to be wrong, since incorrectness and over-conservatism -are merely annoying, not fatal. -The compiler can be fast since it knows that -.I lint -will cover its flanks. -Finally, the programmer can -concentrate at one stage -of the programming process solely on the algorithms, -data structures, and correctness of the -program, and then later retrofit, -with the aid of -.I lint , -the desirable properties of universality and portability. -.SG MH-1273-SCJ-unix -.\".bp -.[ -$LIST$ -.] -.bp -.SH -Appendix: Current Lint Options -.PP -The command currently has the form -.DS -lint\fR [\fB\-\fRoptions ] files... library-descriptors... -.DE -The options are -.IP \fBh\fR -Perform heuristic checks -.IP \fBp\fR -Perform portability checks -.IP \fBv\fR -Don't report unused arguments -.IP \fBu\fR -Don't report unused or undefined externals -.IP \fBb\fR -Report unreachable -.B break -statements. -.IP \fBx\fR -Report unused external declarations -.IP \fBa\fR -Report assignments of -.B long -to -.B int -or shorter. -.IP \fBc\fR -Complain about questionable casts -.IP \fBn\fR -No library checking is done -.IP \fBs\fR -Same as -.B h -(for historical reasons) diff --git a/usr.bin/xlint/README b/usr.bin/xlint/README deleted file mode 100644 index 0692d6f77c2..00000000000 --- a/usr.bin/xlint/README +++ /dev/null @@ -1,30 +0,0 @@ -lint is divided into 3 separate programs: lint, lint1, and -lint2 (the latter two programs reside in /usr/libexec). - -lint calls /usr/libexec/cpp to preprocess the program, then passes -the output to lint1, which does most of the work. lint1 then outputs -a .ln file, which is parsed by lint2 to do more holistic checks. all -of this is driven by /usr/bin/lint, which is like a wrapper program. - -lint1 implements its own C parser. it is incapable of parsing some -weird gcc things, such as __attribute__ and so on. OpenBSD's source -tree already does a good job of removing gcc'isms when parsers other -than gcc are detected. - -lint1 keeps a symbol table for the current context, which always -includes global symbols for the current translation unit, as well as -locals (inside a function definition). When it parses a function -definition, it pushes a symbol table context onto the stack, and -then pops it off when the function definition ends. - -lint1 does the vast majority of its checks one expression at a time. -It uses the symbol table (which contains types of symbols) and almost -nothing else when doing type conversions. All of the checks happen at -parse time. lint1 does not really build an abstract syntax tree (AST) -to represent the entire program; it only keeps track of the symbols -in the current context, and some minimal information about the types -of enclosing control blocks (loops, switch statements, etc). When lint1 -is finished parsing an expression, you will not see any more warnings -regarding that expression. - -$OpenBSD: README,v 1.2 2007/09/24 19:56:34 jmc Exp $ diff --git a/usr.bin/xlint/lint1/Makefile b/usr.bin/xlint/lint1/Makefile deleted file mode 100644 index 4bf5b7a432c..00000000000 --- a/usr.bin/xlint/lint1/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# $OpenBSD: Makefile,v 1.10 2006/11/03 16:27:52 otto Exp $ -# $NetBSD: Makefile,v 1.3 1995/07/04 01:53:05 cgd Exp $ - -PROG= lint1 -SRCS= cgram.y scan.l mem1.c mem.c err.c main1.c decl.c tree.c func.c \ - init.c emit.c emit1.c -NOMAN= -LDADD+= -ll -DPADD+= ${LIBL} -YFLAGS= -d -CFLAGS+=-I. -I${.CURDIR} -LINTFLAGS=-aehpz - -BINDIR= /usr/libexec - -.include <bsd.prog.mk> diff --git a/usr.bin/xlint/lint1/cgram.y b/usr.bin/xlint/lint1/cgram.y deleted file mode 100644 index ed83d88aba0..00000000000 --- a/usr.bin/xlint/lint1/cgram.y +++ /dev/null @@ -1,1726 +0,0 @@ -%{ -/* $OpenBSD: cgram.y,v 1.24 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: cgram.y,v 1.8 1995/10/02 17:31:35 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <limits.h> - -#include "lint1.h" - -/* - * Contains the level of current declaration. 0 is extern. - * Used for symbol table entries. - */ -int blklev; - -/* - * level for memory allocation. Normaly the same as blklev. - * An exception is the declaration of arguments in prototypes. Memory - * for these can't be freed after the declaration, but symbols must - * be removed from the symbol table after the declaration. - */ -int mblklev; - -/* - * Is the statement empty? - */ -int estmnt; - -static int toicon(tnode_t *); -static void idecl(sym_t *, int); -static void ignuptorp(void); - -%} - -%union { - int y_int; - val_t *y_val; - sbuf_t *y_sb; - sym_t *y_sym; - op_t y_op; - scl_t y_scl; - tspec_t y_tspec; - tqual_t y_tqual; - type_t *y_type; - tnode_t *y_tnode; - strg_t *y_strg; - pqinf_t *y_pqinf; -}; - -%token T_LBRACE T_RBRACE T_LBRACK T_RBRACK T_LPARN T_RPARN -%token <y_op> T_STROP -%token <y_op> T_UNOP -%token <y_op> T_INCDEC -%token T_SIZEOF -%token <y_op> T_MULT -%token <y_op> T_DIVOP -%token <y_op> T_ADDOP -%token <y_op> T_SHFTOP -%token <y_op> T_RELOP -%token <y_op> T_EQOP -%token <y_op> T_AND -%token <y_op> T_XOR -%token <y_op> T_OR -%token <y_op> T_LOGAND -%token <y_op> T_LOGOR -%token T_QUEST -%token T_COLON -%token <y_op> T_ASSIGN -%token <y_op> T_OPASS -%token T_COMMA -%token T_SEMI -%token T_ELLIPSE - -/* storage classes (extern, static, auto, register and typedef) */ -%token <y_scl> T_SCLASS - -/* types (char, int, short, long, unsigned, signed, float, double, void) */ -%token <y_tspec> T_TYPE - -/* qualifiers (const, volatile, restrict) */ -%token <y_tqual> T_QUAL - -/* struct or union */ -%token <y_tspec> T_SOU - -/* enum */ -%token T_ENUM - -/* remaining keywords */ -%token T_CASE -%token T_DEFAULT -%token T_IF -%token T_ELSE -%token T_SWITCH -%token T_DO -%token T_WHILE -%token T_FOR -%token T_GOTO -%token T_CONTINUE -%token T_BREAK -%token T_RETURN -%token T_ASM -%token T_LEQUAL -%token T_ATTRIBUTE - -%left T_COMMA -%right T_ASSIGN T_OPASS -%right T_QUEST T_COLON -%left T_LOGOR -%left T_LOGAND -%left T_OR -%left T_XOR -%left T_AND -%left T_EQOP -%left T_RELOP -%left T_SHFTOP -%left T_ADDOP -%left T_MULT T_DIVOP -%right T_UNOP T_INCDEC T_SIZEOF -%left T_LPARN T_LBRACK T_STROP - -%token <y_sb> T_NAME -%token <y_sb> T_TYPENAME -%token <y_val> T_CON -%token <y_strg> T_STRING - -%type <y_sym> func_decl -%type <y_sym> notype_decl -%type <y_sym> type_decl -%type <y_type> typespec -%type <y_type> clrtyp_typespec -%type <y_type> notype_typespec -%type <y_type> struct_spec -%type <y_type> enum_spec -%type <y_sym> struct_tag -%type <y_sym> enum_tag -%type <y_tspec> struct -%type <y_sym> struct_declaration -%type <y_sb> identifier -%type <y_sym> member_declaration_list_with_rbrace -%type <y_sym> member_declaration_list -%type <y_sym> member_declaration -%type <y_sym> notype_member_decls -%type <y_sym> type_member_decls -%type <y_sym> notype_member_decl -%type <y_sym> type_member_decl -%type <y_tnode> constant -%type <y_sym> enum_declaration -%type <y_sym> enums_with_opt_comma -%type <y_sym> enums -%type <y_sym> enumerator -%type <y_sym> ename -%type <y_sym> notype_direct_decl -%type <y_sym> type_direct_decl -%type <y_pqinf> pointer -%type <y_pqinf> asterisk -%type <y_sym> param_decl -%type <y_sym> param_list -%type <y_sym> abs_decl_param_list -%type <y_sym> direct_param_decl -%type <y_sym> notype_param_decl -%type <y_sym> direct_notype_param_decl -%type <y_pqinf> type_qualifier_list -%type <y_pqinf> type_qualifier -%type <y_sym> identifier_list -%type <y_sym> abs_decl -%type <y_sym> direct_abs_decl -%type <y_sym> vararg_parameter_type_list -%type <y_sym> parameter_type_list -%type <y_sym> parameter_declaration -%type <y_tnode> expr -%type <y_tnode> term -%type <y_tnode> func_arg_list -%type <y_op> point_or_arrow -%type <y_type> type_name -%type <y_sym> abstract_declaration -%type <y_tnode> do_while_expr -%type <y_tnode> opt_expr -%type <y_strg> string -%type <y_strg> string2 - - -%% - -program: - /* empty */ { - if (sflag) { - /* empty translation unit */ - error(272); - } else { - /* empty translation unit */ - warning(272); - } - } - | translation_unit - ; - -translation_unit: - ext_decl - | translation_unit ext_decl - ; - -ext_decl: - func_def { - glclup(0); - clrwflgs(); - } - | data_def { - glclup(0); - clrwflgs(); - } - | T_LEQUAL T_LPARN identifier T_COMMA identifier T_RPARN T_SEMI { - sym_t *new, *old; - - if ($5->sb_sym && $3->sb_sym /*== NULL*/) { - new = getsym($5); - old = $3->sb_sym; - new->s_dpos = old->s_dpos; - new->s_spos = old->s_spos; - new->s_upos = old->s_upos; - new->s_kind = old->s_kind; - new->s_keyw = old->s_keyw; - new->s_field = old->s_field; - new->s_set = old->s_set; - new->s_used = old->s_used; - new->s_arg = old->s_arg; - new->s_reg = old->s_reg; - new->s_defarg = old->s_defarg; - new->s_rimpl = old->s_rimpl; - new->s_osdef = old->s_osdef; - new->s_inline = old->s_inline; - new->s_noreturn = old->s_noreturn; - new->s_def = old->s_def; - new->s_scl = old->s_scl; - new->s_blklev = old->s_blklev; - new->s_type = old->s_type; - new->s_value = old->s_value; - new->u = old->u; - - /* XXX missing 'r' because do not know return type - of parent... */ - /* outsym(new, new->s_scl, DEF); */ - outfdef(new, &csrc_pos, - new->s_rimpl || new->s_type->t_subt->t_tspec != VOID, - 0, NULL); - } - - } - ; - -data_def: T_SEMI - | clrtyp deftyp notype_init_decls T_SEMI { - if (sflag) { - /* old style declaration; add "int" */ - error(1); - } else { - /* old style declaration; add "int" */ - warning(1); - } - } - | declmods deftyp T_SEMI { - if (dcs->d_scl == TYPEDEF) { - /* typedef declares no type name */ - warning(72); - } else { - /* empty declaration */ - warning(2); - } - } - | declmods deftyp notype_init_decls T_SEMI - | declspecs deftyp T_SEMI { - if (dcs->d_scl == TYPEDEF) { - /* typedef declares no type name */ - warning(72); - } else if (!dcs->d_nedecl) { - /* empty declaration */ - warning(2); - } - } - | declspecs deftyp type_init_decls opt_attribute_spec T_SEMI - | error T_SEMI { - globclup(); - } - | error T_RBRACE { - globclup(); - } - ; - -func_def: - func_decl { - if ($1->s_type->t_tspec != FUNC) { - /* syntax error */ - error(249); - YYERROR; - } - if ($1->s_type->t_typedef) { - /* ()-less function definition */ - error(64); - YYERROR; - } - funcdef($1); - blklev++; - pushdecl(ARG); - } opt_arg_declaration_list { - popdecl(); - blklev--; - cluparg(); - pushctrl(0); - } comp_stmnt { - funcend(); - popctrl(0); - } - ; - -opt_attribute_spec: - /* empty */ - | T_ATTRIBUTE T_LPARN T_LPARN read_until_rparn T_RPARN - ; - -func_decl: - clrtyp deftyp notype_decl { - $$ = $3; - } - | declmods deftyp notype_decl { - $$ = $3; - } - | declspecs deftyp type_decl { - $$ = $3; - } - ; - -opt_arg_declaration_list: - /* empty */ - | arg_declaration_list - ; - -arg_declaration_list: - arg_declaration - | arg_declaration_list arg_declaration - /* XXX or better "arg_declaration error" ? */ - | error - ; - -/* - * "arg_declaration" is separated from "declaration" because it - * needs other error handling. - */ - -arg_declaration: - declmods deftyp T_SEMI { - /* empty declaration */ - warning(2); - } - | declmods deftyp notype_init_decls T_SEMI - | declspecs deftyp T_SEMI { - if (!dcs->d_nedecl) { - /* empty declaration */ - warning(2); - } else { - tspec_t ts = dcs->d_type->t_tspec; - /* %s declared in argument declaration list */ - warning(3, ts == STRUCT ? "struct" : - (ts == UNION ? "union" : "enum")); - } - } - | declspecs deftyp type_init_decls T_SEMI { - if (dcs->d_nedecl) { - tspec_t ts = dcs->d_type->t_tspec; - /* %s declared in argument declaration list */ - warning(3, ts == STRUCT ? "struct" : - (ts == UNION ? "union" : "enum")); - } - } - | declmods error - | declspecs error - ; - -declaration: - declmods deftyp T_SEMI { - if (dcs->d_scl == TYPEDEF) { - /* typedef declares no type name */ - warning(72); - } else { - /* empty declaration */ - warning(2); - } - } - | declmods deftyp notype_init_decls T_SEMI - | declspecs deftyp T_SEMI { - if (dcs->d_scl == TYPEDEF) { - /* typedef declares no type name */ - warning(72); - } else if (!dcs->d_nedecl) { - /* empty declaration */ - warning(2); - } - } - | declspecs deftyp type_init_decls T_SEMI - | error T_SEMI - ; - -clrtyp: - { - clrtyp(); - } - ; - -deftyp: - /* empty */ { - deftyp(); - } - ; - -declspecs: - clrtyp_typespec { - addtype($1); - } - | declmods typespec { - addtype($2); - } - | declspecs declmod - | declspecs notype_typespec { - addtype($2); - } - ; - -declmods: - clrtyp T_QUAL { - addqual($2); - } - | clrtyp T_SCLASS { - addscl($2); - } - | declmods declmod - ; - -declmod: - T_QUAL { - addqual($1); - } - | T_SCLASS { - addscl($1); - } - ; - -clrtyp_typespec: - clrtyp notype_typespec { - $$ = $2; - } - | T_TYPENAME clrtyp { - $$ = getsym($1)->s_type; - } - ; - -typespec: - notype_typespec { - $$ = $1; - } - | T_TYPENAME { - $$ = getsym($1)->s_type; - } - ; - -notype_typespec: - T_TYPE { - $$ = gettyp($1); - } - | struct_spec { - popdecl(); - $$ = $1; - } - | enum_spec { - popdecl(); - $$ = $1; - } - ; - -struct_spec: - struct struct_tag { - /* - * STDC requires that "struct a;" always introduces - * a new tag if "a" is not declared at current level - * - * yychar is valid because otherwise the parser would - * not been able to deceide if he must shift or reduce - */ - $$ = mktag($2, $1, 0, yychar == T_SEMI); - } - | struct struct_tag { - dcs->d_tagtyp = mktag($2, $1, 1, 0); - } struct_declaration { - $$ = compltag(dcs->d_tagtyp, $4); - } - | struct { - dcs->d_tagtyp = mktag(NULL, $1, 1, 0); - } struct_declaration { - $$ = compltag(dcs->d_tagtyp, $3); - } - | struct error { - symtyp = FVFT; - $$ = gettyp(INT); - } - ; - -struct: - T_SOU { - symtyp = FTAG; - pushdecl($1 == STRUCT ? MOS : MOU); - dcs->d_offset = 0; - dcs->d_stralign = CHAR_BIT; - $$ = $1; - } - ; - -struct_tag: - identifier { - $$ = getsym($1); - } - ; - -struct_declaration: - struct_decl_lbrace member_declaration_list_with_rbrace { - $$ = $2; - } - ; - -struct_decl_lbrace: - T_LBRACE { - symtyp = FVFT; - } - ; - -member_declaration_list_with_rbrace: - member_declaration_list T_SEMI T_RBRACE { - $$ = $1; - } - | member_declaration_list T_RBRACE { - if (sflag) { - /* syntax req. ";" after last struct/union member */ - error(66); - } else { - /* syntax req. ";" after last struct/union member */ - warning(66); - } - $$ = $1; - } - | T_RBRACE { - $$ = NULL; - } - ; - -member_declaration_list: - member_declaration { - $$ = $1; - } - | member_declaration_list T_SEMI member_declaration { - $$ = lnklst($1, $3); - } - ; - -member_declaration: - noclass_declmods deftyp { - /* too late, i know, but getsym() compensates it */ - symtyp = FMOS; - } notype_member_decls { - symtyp = FVFT; - $$ = $4; - } - | noclass_declspecs deftyp { - symtyp = FMOS; - } type_member_decls { - symtyp = FVFT; - $$ = $4; - } - | noclass_declmods deftyp { - /* struct or union member must be named */ - warning(49); - $$ = NULL; - } - | noclass_declspecs deftyp { - /* struct or union member must be named */ - warning(49); - $$ = NULL; - } - | error { - symtyp = FVFT; - $$ = NULL; - } - ; - -noclass_declspecs: - clrtyp_typespec { - addtype($1); - } - | noclass_declmods typespec { - addtype($2); - } - | noclass_declspecs T_QUAL { - addqual($2); - } - | noclass_declspecs notype_typespec { - addtype($2); - } - ; - -noclass_declmods: - clrtyp T_QUAL { - addqual($2); - } - | noclass_declmods T_QUAL { - addqual($2); - } - ; - -notype_member_decls: - notype_member_decl { - $$ = decl1str($1); - } - | notype_member_decls { - symtyp = FMOS; - } T_COMMA type_member_decl { - $$ = lnklst($1, decl1str($4)); - } - ; - -type_member_decls: - type_member_decl { - $$ = decl1str($1); - } - | type_member_decls { - symtyp = FMOS; - } T_COMMA type_member_decl { - $$ = lnklst($1, decl1str($4)); - } - ; - -notype_member_decl: - notype_decl { - $$ = $1; - } - | notype_decl T_COLON constant { - $$ = bitfield($1, toicon($3)); - } - | { - symtyp = FVFT; - } T_COLON constant { - $$ = bitfield(NULL, toicon($3)); - } - ; - -type_member_decl: - type_decl { - $$ = $1; - } - | type_decl T_COLON constant { - $$ = bitfield($1, toicon($3)); - } - | { - symtyp = FVFT; - } T_COLON constant { - $$ = bitfield(NULL, toicon($3)); - } - ; - -enum_spec: - enum enum_tag { - $$ = mktag($2, ENUM, 0, 0); - } - | enum enum_tag { - dcs->d_tagtyp = mktag($2, ENUM, 1, 0); - } enum_declaration { - $$ = compltag(dcs->d_tagtyp, $4); - } - | enum { - dcs->d_tagtyp = mktag(NULL, ENUM, 1, 0); - } enum_declaration { - $$ = compltag(dcs->d_tagtyp, $3); - } - | enum error { - symtyp = FVFT; - $$ = gettyp(INT); - } - ; - -enum: - T_ENUM { - symtyp = FTAG; - pushdecl(ENUMCON); - } - ; - -enum_tag: - identifier { - $$ = getsym($1); - } - ; - -enum_declaration: - enum_decl_lbrace enums_with_opt_comma T_RBRACE { - $$ = $2; - } - ; - -enum_decl_lbrace: - T_LBRACE { - symtyp = FVFT; - enumval = 0; - } - ; - -enums_with_opt_comma: - enums { - $$ = $1; - } - | enums T_COMMA { - $$ = $1; - } - ; - -enums: - enumerator { - $$ = $1; - } - | enums T_COMMA enumerator { - $$ = lnklst($1, $3); - } - | error { - $$ = NULL; - } - ; - -enumerator: - ename { - $$ = ename($1, enumval, 1); - } - | ename T_ASSIGN constant { - $$ = ename($1, toicon($3), 0); - } - ; - -ename: - identifier { - $$ = getsym($1); - } - ; - - -notype_init_decls: - notype_init_decl - | notype_init_decls T_COMMA type_init_decl - ; - -type_init_decls: - type_init_decl - | type_init_decls T_COMMA type_init_decl - ; - -notype_init_decl: - notype_decl opt_attribute_spec opt_asm_spec { - idecl($1, 0); - chksz($1); - } - | notype_decl opt_asm_spec { - idecl($1, 1); - } T_ASSIGN initializer { - chksz($1); - } - ; - -type_init_decl: - type_decl opt_asm_spec { - idecl($1, 0); - chksz($1); - } - | type_decl opt_asm_spec { - idecl($1, 1); - } T_ASSIGN initializer { - chksz($1); - } - ; - -notype_decl: - notype_direct_decl { - $$ = $1; - } - | pointer notype_direct_decl { - $$ = addptr($2, $1); - } - ; - -notype_direct_decl: - T_NAME { - $$ = dname(getsym($1)); - } - | T_LPARN type_decl T_RPARN { - $$ = $2; - } - | notype_direct_decl T_LBRACK T_RBRACK { - $$ = addarray($1, 0, 0); - } - | notype_direct_decl T_LBRACK constant T_RBRACK { - $$ = addarray($1, 1, toicon($3)); - } - | notype_direct_decl param_list { - $$ = addfunc($1, $2); - popdecl(); - blklev--; - } - ; - -type_decl: - type_direct_decl { - $$ = $1; - } - | pointer type_direct_decl { - $$ = addptr($2, $1); - } - ; - -type_direct_decl: - identifier { - $$ = dname(getsym($1)); - } - | T_LPARN type_decl T_RPARN { - $$ = $2; - } - | type_direct_decl T_LBRACK T_RBRACK { - $$ = addarray($1, 0, 0); - } - | type_direct_decl T_LBRACK constant T_RBRACK { - $$ = addarray($1, 1, toicon($3)); - } - | type_direct_decl param_list { - $$ = addfunc($1, $2); - popdecl(); - blklev--; - } - ; - -/* - * param_decl and notype_param_decl exist to avoid a conflict in - * argument lists. A typename enclosed in parens should always be - * treated as a typename, not an argument. - * "typedef int a; f(int (a));" is "typedef int a; f(int foo(a));" - * not "typedef int a; f(int a);" - */ -param_decl: - direct_param_decl { - $$ = $1; - } - | pointer direct_param_decl { - $$ = addptr($2, $1); - } - ; - -direct_param_decl: - identifier { - $$ = dname(getsym($1)); - } - | T_LPARN notype_param_decl T_RPARN { - $$ = $2; - } - | direct_param_decl T_LBRACK T_RBRACK { - $$ = addarray($1, 0, 0); - } - | direct_param_decl T_LBRACK constant T_RBRACK { - $$ = addarray($1, 1, toicon($3)); - } - | direct_param_decl param_list { - $$ = addfunc($1, $2); - popdecl(); - blklev--; - } - ; - -notype_param_decl: - direct_notype_param_decl { - $$ = $1; - } - | pointer direct_notype_param_decl { - $$ = addptr($2, $1); - } - ; - -direct_notype_param_decl: - T_NAME { - $$ = dname(getsym($1)); - } - | T_LPARN notype_param_decl T_RPARN { - $$ = $2; - } - | direct_notype_param_decl T_LBRACK T_RBRACK { - $$ = addarray($1, 0, 0); - } - | direct_notype_param_decl T_LBRACK constant T_RBRACK { - $$ = addarray($1, 1, toicon($3)); - } - | direct_notype_param_decl param_list { - $$ = addfunc($1, $2); - popdecl(); - blklev--; - } - ; - -pointer: - asterisk { - $$ = $1; - } - | asterisk type_qualifier_list { - $$ = mergepq($1, $2); - } - | asterisk pointer { - $$ = mergepq($1, $2); - } - | asterisk type_qualifier_list pointer { - $$ = mergepq(mergepq($1, $2), $3); - } - ; - -asterisk: - T_MULT { - $$ = xcalloc(1, sizeof (pqinf_t)); - $$->p_pcnt = 1; - } - ; - -type_qualifier_list: - type_qualifier { - $$ = $1; - } - | type_qualifier_list type_qualifier { - $$ = mergepq($1, $2); - } - ; - -type_qualifier: - T_QUAL { - $$ = xcalloc(1, sizeof (pqinf_t)); - if ($1 == CONST) { - $$->p_const = 1; - } else { - $$->p_volatile = 1; - } - } - ; - -param_list: - id_list_lparn identifier_list T_RPARN { - $$ = $2; - } - | abs_decl_param_list { - $$ = $1; - } - ; - -id_list_lparn: - T_LPARN { - blklev++; - pushdecl(PARG); - } - ; - -identifier_list: - T_NAME { - $$ = iname(getsym($1)); - } - | identifier_list T_COMMA T_NAME { - $$ = lnklst($1, iname(getsym($3))); - } - | identifier_list error { - $$ = $1; - } - ; - -abs_decl_param_list: - abs_decl_lparn T_RPARN { - $$ = NULL; - } - | abs_decl_lparn vararg_parameter_type_list T_RPARN { - dcs->d_proto = 1; - $$ = $2; - } - | abs_decl_lparn error T_RPARN { - $$ = NULL; - } - ; - -abs_decl_lparn: - T_LPARN { - blklev++; - pushdecl(PARG); - } - ; - -vararg_parameter_type_list: - parameter_type_list { - $$ = $1; - } - | parameter_type_list T_COMMA T_ELLIPSE { - dcs->d_vararg = 1; - $$ = $1; - } - | T_ELLIPSE { - if (sflag) { - /* ANSI C requires formal parameter before "..." */ - error(84); - } else { - /* ANSI C requires formal parameter before "..." */ - warning(84); - } - dcs->d_vararg = 1; - $$ = NULL; - } - ; - -parameter_type_list: - parameter_declaration opt_asm_spec { - $$ = $1; - } - | parameter_type_list T_COMMA parameter_declaration opt_asm_spec { - $$ = lnklst($1, $3); - } - ; - -parameter_declaration: - declmods deftyp { - $$ = decl1arg(aname(), 0); - } - | declspecs deftyp { - $$ = decl1arg(aname(), 0); - } - | declmods deftyp notype_param_decl { - $$ = decl1arg($3, 0); - } - /* - * param_decl is needed because of following conflict: - * "typedef int a; f(int (a));" could be parsed as - * "function with argument a of type int", or - * "function with an abstract argument of type function". - * This grammar realizes the second case. - */ - | declspecs deftyp param_decl { - $$ = decl1arg($3, 0); - } - | declmods deftyp abs_decl { - $$ = decl1arg($3, 0); - } - | declspecs deftyp abs_decl { - $$ = decl1arg($3, 0); - } - ; - -opt_asm_spec: - /* empty */ - | T_ASM T_LPARN read_until_rparn - ; - -initializer: - init_expr - ; - -init_expr: - expr %prec T_COMMA { - mkinit($1); - } - | init_lbrace init_expr_list init_rbrace - | init_lbrace init_expr_list T_COMMA init_rbrace - | init_lbrace init_rbrace - | error - ; - -init_expr_list: - init_expr %prec T_COMMA - | init_expr_list T_COMMA init_expr - ; - -init_lbrace: - T_LBRACE { - initlbr(); - } - ; - -init_rbrace: - T_RBRACE { - initrbr(); - } - ; - -type_name: - { - pushdecl(ABSTRACT); - } abstract_declaration { - popdecl(); - $$ = $2->s_type; - } - ; - -abstract_declaration: - noclass_declmods deftyp { - $$ = decl1abs(aname()); - } - | noclass_declspecs deftyp { - $$ = decl1abs(aname()); - } - | noclass_declmods deftyp abs_decl { - $$ = decl1abs($3); - } - | noclass_declspecs deftyp abs_decl { - $$ = decl1abs($3); - } - ; - -abs_decl: - pointer { - $$ = addptr(aname(), $1); - } - | direct_abs_decl { - $$ = $1; - } - | pointer direct_abs_decl { - $$ = addptr($2, $1); - } - ; - -direct_abs_decl: - T_LPARN abs_decl T_RPARN { - $$ = $2; - } - | T_LBRACK T_RBRACK { - $$ = addarray(aname(), 0, 0); - } - | T_LBRACK constant T_RBRACK { - $$ = addarray(aname(), 1, toicon($2)); - } - | direct_abs_decl T_LBRACK T_RBRACK { - $$ = addarray($1, 0, 0); - } - | direct_abs_decl T_LBRACK constant T_RBRACK { - $$ = addarray($1, 1, toicon($3)); - } - | abs_decl_param_list { - $$ = addfunc(aname(), $1); - popdecl(); - blklev--; - } - | direct_abs_decl abs_decl_param_list { - $$ = addfunc($1, $2); - popdecl(); - blklev--; - } - ; - -stmnt: - labeled_stmnt { - estmnt = 0; - } - | expr_stmnt - | comp_stmnt { - estmnt = 0; - } - | selection_stmnt { - estmnt = 0; - } - | iteration_stmnt { - estmnt = 0; - } - | jump_stmnt { - estmnt = 0; - ftflg = 0; - } - | asm_stmnt { - estmnt = 0; - } - ; - -labeled_stmnt: - label stmnt - ; - -label: - identifier T_COLON { - symtyp = FLAB; - label(T_NAME, getsym($1), NULL); - } - | T_CASE constant T_COLON { - label(T_CASE, NULL, $2); - ftflg = 1; - } - | T_CASE constant T_ELLIPSE constant T_COLON { - /* XXX: only using the first value of this gcc-ism */ - label(T_CASE, NULL, $2); - ftflg = 1; - - if (!gflag) - gnuism(311); - } - | T_DEFAULT T_COLON { - label(T_DEFAULT, NULL, NULL); - ftflg = 1; - } - ; - -comp_stmnt: - compstmnt_lbrace declaration_list opt_stmnt_list compstmnt_rbrace - | compstmnt_lbrace opt_stmnt_list compstmnt_rbrace - ; - -compstmnt_lbrace: - T_LBRACE { - blklev++; - mblklev++; - pushdecl(AUTO); - } - ; - -compstmnt_rbrace: - T_RBRACE { - popdecl(); - freeblk(); - mblklev--; - blklev--; - ftflg = 0; - } - ; - -opt_stmnt_list: - /* empty */ - | stmnt_list - ; - -stmnt_list: - stmnt { - clrwflgs(); - } - | stmnt_list stmnt { - clrwflgs(); - } - | stmnt_list error T_SEMI { - clrwflgs(); - } - ; - -expr_stmnt: - expr T_SEMI { - expr($1, 0, 0); - estmnt = 0; - ftflg = 0; - } - | T_SEMI { - estmnt = 1; - ftflg = 0; - } - ; - -selection_stmnt: - if_without_else { - if2(); - if3(0); - } - | if_without_else T_ELSE { - if2(); - } stmnt { - if (estmnt) { - /* empty body of the else statement */ - warning(316); - } - - if3(1); - } - | if_without_else T_ELSE error { - if3(0); - } - | switch_expr stmnt { - switch2(); - } - | switch_expr error { - switch2(); - } - ; - -if_without_else: - if_expr stmnt { - if (estmnt) { - /* empty body of the if statement */ - warning(315); - } - } - | if_expr error - ; - -if_expr: - T_IF T_LPARN expr T_RPARN { - if1($3); - clrwflgs(); - } - ; - -switch_expr: - T_SWITCH T_LPARN expr T_RPARN { - switch1($3); - clrwflgs(); - } - ; - -iteration_stmnt: - while_expr stmnt { - while2(); - } - | while_expr error { - while2(); - } - | do stmnt do_while_expr { - do2($3); - ftflg = 0; - } - | do error { - do2(NULL); - } - | for_exprs stmnt { - for2(); - } - | for_exprs error { - for2(); - } - ; - -while_expr: - T_WHILE T_LPARN expr T_RPARN { - while1($3); - clrwflgs(); - } - ; - -do: - T_DO { - do1(); - } - ; - -do_while_expr: - T_WHILE T_LPARN expr T_RPARN T_SEMI { - $$ = $3; - } - ; - -for_exprs: - T_FOR T_LPARN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPARN { - for1($3, $5, $7); - clrwflgs(); - } - ; - -opt_expr: - /* empty */ { - $$ = NULL; - } - | expr { - $$ = $1; - } - ; - -jump_stmnt: - goto identifier T_SEMI { - dogoto(getsym($2)); - } - | goto error T_SEMI { - symtyp = FVFT; - } - | T_CONTINUE T_SEMI { - docont(); - } - | T_BREAK T_SEMI { - dobreak(); - } - | T_RETURN T_SEMI { - doreturn(NULL); - } - | T_RETURN expr T_SEMI { - doreturn($2); - } - ; - -goto: - T_GOTO { - symtyp = FLAB; - } - ; - -asm_stmnt: - T_ASM T_LPARN read_until_rparn T_SEMI { - setasm(); - } - | T_ASM T_QUAL T_LPARN read_until_rparn T_SEMI { - setasm(); - } - | T_ASM error - ; - -read_until_rparn: - /* empty */ { - ignuptorp(); - } - ; - -declaration_list: - declaration { - clrwflgs(); - } - | declaration_list declaration { - clrwflgs(); - } - ; - -constant: - expr %prec T_COMMA { - $$ = $1; - } - ; - -expr: - expr T_MULT expr { - $$ = build(MULT, $1, $3); - } - | expr T_DIVOP expr { - $$ = build($2, $1, $3); - } - | expr T_ADDOP expr { - $$ = build($2, $1, $3); - } - | expr T_SHFTOP expr { - $$ = build($2, $1, $3); - } - | expr T_RELOP expr { - $$ = build($2, $1, $3); - } - | expr T_EQOP expr { - $$ = build($2, $1, $3); - } - | expr T_AND expr { - $$ = build(AND, $1, $3); - } - | expr T_XOR expr { - $$ = build(XOR, $1, $3); - } - | expr T_OR expr { - $$ = build(OR, $1, $3); - } - | expr T_LOGAND expr { - $$ = build(LOGAND, $1, $3); - } - | expr T_LOGOR expr { - $$ = build(LOGOR, $1, $3); - } - | expr T_QUEST expr T_COLON expr { - $$ = build(QUEST, $1, build(COLON, $3, $5)); - } - | expr T_ASSIGN expr { - $$ = build(ASSIGN, $1, $3); - } - | expr T_OPASS expr { - $$ = build($2, $1, $3); - } - | expr T_COMMA expr { - $$ = build(COMMA, $1, $3); - } - | term { - $$ = $1; - } - ; - -term: - T_NAME { - /* XXX really necessary? */ - if (yychar < 0) - yychar = yylex(); - $$ = getnnode(getsym($1), yychar); - } - | string { - $$ = getsnode($1); - } - | T_CON { - $$ = getcnode(gettyp($1->v_tspec), $1); - } - | T_LPARN expr T_RPARN { - if ($2 != NULL) - $2->tn_parn = 1; - $$ = $2; - } - | term T_INCDEC { - $$ = build($2 == INC ? INCAFT : DECAFT, $1, NULL); - } - | T_INCDEC term { - $$ = build($1 == INC ? INCBEF : DECBEF, $2, NULL); - } - | T_MULT term { - $$ = build(STAR, $2, NULL); - } - | T_AND term { - $$ = build(AMPER, $2, NULL); - } - | T_UNOP term { - $$ = build($1, $2, NULL); - } - | T_ADDOP term { - $$ = build($1 == PLUS ? UPLUS : UMINUS, $2, NULL); - } - | term T_LBRACK expr T_RBRACK { - $$ = build(STAR, build(PLUS, $1, $3), NULL); - } - | term T_LPARN T_RPARN { - $$ = funccall($1, NULL); - } - | term T_LPARN func_arg_list T_RPARN { - $$ = funccall($1, $3); - } - | term point_or_arrow T_NAME { - if ($1 != NULL) { - sym_t *msym; - /* XXX strmemb should be integrated in build() */ - if ($2 == ARROW) { - /* must to this before strmemb is called */ - $1 = cconv($1); - } - msym = strmemb($1, $2, getsym($3)); - $$ = build($2, $1, getnnode(msym, 0)); - } else { - $$ = NULL; - } - } - | T_SIZEOF term %prec T_SIZEOF { - if (($$ = $2 == NULL ? NULL : bldszoftrm($2)) != NULL) - chkmisc($2, 0, 0, 0, 0, 0, 1); - } - | T_SIZEOF T_LPARN type_name T_RPARN %prec T_SIZEOF { - $$ = bldszof($3); - } - | T_LPARN type_name T_RPARN term %prec T_UNOP { - $$ = cast($4, $2); - } - ; - -string: - T_STRING { - $$ = $1; - } - | T_STRING string2 { - $$ = catstrg($1, $2); - } - ; - -string2: - T_STRING { - $$ = $1; - } - | string2 T_STRING { - $$ = catstrg($1, $2); - } - ; - -func_arg_list: - expr %prec T_COMMA { - $$ = funcarg(NULL, $1); - } - | func_arg_list T_COMMA expr { - $$ = funcarg($1, $3); - } - ; - -point_or_arrow: - T_STROP { - symtyp = FMOS; - $$ = $1; - } - ; - -identifier: - T_NAME { - $$ = $1; - } - | T_TYPENAME { - $$ = $1; - } - ; - -%% - -/* ARGSUSED */ -int -yyerror(char *msg) -{ - error(249); - if (++sytxerr >= 5) - norecover(); - return (0); -} - -/* - * Gets a node for a constant and returns the value of this constant - * as integer. - * Is the node not constant or too large for int or of type float, - * a warning will be printed. - * - * toicon() should be used only inside declarations. If it is used in - * expressions, it frees the memory used for the expression. - */ -static int -toicon(tnode_t *tn) -{ - int i; - tspec_t t; - val_t *v; - - v = constant(tn); - - /* - * Abstract declarations are used inside expression. To free - * the memory would be a fatal error. - */ - if (dcs->d_ctx != ABSTRACT) - tfreeblk(); - - if ((t = v->v_tspec) == FLOAT || t == DOUBLE || t == LDOUBLE) { - i = (int)v->v_ldbl; - /* integral constant expression expected */ - error(55); - } else { - i = (int)v->v_quad; - if (isutyp(t)) { - if ((u_quad_t)v->v_quad > UINT_MAX) { - /* integral constant too large */ - warning(56); - } - } else { - if (v->v_quad > INT_MAX || v->v_quad < INT_MIN) { - /* integral constant too large */ - warning(56); - } - } - } - free(v); - return (i); -} - -static void -idecl(sym_t *decl, int initflg) -{ - initerr = 0; - initsym = decl; - - if (usedflg) - setuflg(decl, 0, 0); - - switch (dcs->d_ctx) { - case EXTERN: - decl1ext(decl, initflg); - break; - case ARG: - (void)decl1arg(decl, initflg); - break; - case AUTO: - decl1loc(decl, initflg); - break; - default: - lerror("idecl()"); - } - - if (initflg && !initerr) - prepinit(); -} - -/* - * Discard all input tokens up to and including the next - * unmatched right paren - */ -void -ignuptorp(void) -{ - int level; - - if (yychar < 0) - yychar = yylex(); - freeyyv(&yylval, yychar); - - level = 1; - while (yychar != T_RPARN || --level > 0) { - if (yychar == T_LPARN) { - level++; - } else if (yychar <= 0) { - break; - } - freeyyv(&yylval, yychar = yylex()); - } - - yyclearin; -} diff --git a/usr.bin/xlint/lint1/decl.c b/usr.bin/xlint/lint1/decl.c deleted file mode 100644 index c40ba5b47db..00000000000 --- a/usr.bin/xlint/lint1/decl.c +++ /dev/null @@ -1,3140 +0,0 @@ -/* $OpenBSD: decl.c,v 1.30 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: decl.c,v 1.11 1995/10/02 17:34:16 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <stdbool.h> -#include <complex.h> - -#include "lint1.h" - -const char *unnamed = "<unnamed>"; - -/* contains various information and classification on types */ -ttab_t ttab[NTSPEC]; - -/* shared type structures for arithmetic types and void */ -static type_t *typetab; - -/* value of next enumerator during declaration of enum types */ -int enumval; - -/* - * pointer to top element of a stack which contains informations local - * to nested declarations - */ -dinfo_t *dcs; - -static type_t *tdeferr(type_t *, tspec_t); -static void settdsym(type_t *, sym_t *); -static tspec_t mrgtspec(tspec_t, tspec_t); -static void align(int, int); -static sym_t *newtag(sym_t *, scl_t, int, int); -static int eqargs(type_t *, type_t *, int *); -static int mnoarg(type_t *, int *); -static int chkosdef(sym_t *, sym_t *); -static int chkptdecl(sym_t *, sym_t *); -static sym_t *nsfunc(sym_t *, sym_t *); -static void osfunc(sym_t *, sym_t *); -static void ledecl(sym_t *); -static int chkinit(sym_t *); -static void chkausg(int, sym_t *); -static void chkvusg(int, sym_t *); -static void chklusg(sym_t *); -static void chktusg(sym_t *); -static void chkglvar(sym_t *); -static void glchksz(sym_t *); - -/* - * initializes all global vars used in declarations - */ -void -initdecl(void) -{ - int i; - static struct { - tspec_t it_tspec; - ttab_t it_ttab; - } ittab[] = { - { SIGNED, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "signed" } }, - { UNSIGN, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "unsigned" } }, - { BOOL, { sizeof (_Bool) * CHAR_BIT, CHAR_BIT, 1, - BOOL, BOOL, - 1, 1, 0, 1, 1, "_Bool" } }, - { CHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "char" } }, - { SCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "signed char" } }, - { UCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 1, 0, 1, 1, "unsigned char" } }, - { SHORT, { sizeof (short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 0, 0, 1, 1, "short" } }, - { USHORT, { sizeof (u_short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 1, 0, 1, 1, "unsigned short" } }, - { INT, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 0, 0, 1, 1, "int" } }, - { UINT, { sizeof (u_int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 1, 0, 1, 1, "unsigned int" } }, - { LONG, { sizeof (long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 0, 0, 1, 1, "long" } }, - { ULONG, { sizeof (u_long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 1, 0, 1, 1, "unsigned long" } }, - { QUAD, { sizeof (quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 0, 0, 1, 1, "long long" } }, - { UQUAD, { sizeof (u_quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 1, 0, 1, 1, "unsigned long long" } }, - { FLOAT, { sizeof (float) * CHAR_BIT, 4 * CHAR_BIT, -1, - FLOAT, FLOAT, - 0, 0, 1, 1, 1, "float" } }, - { DOUBLE, { sizeof (double) * CHAR_BIT, 8 * CHAR_BIT, -1, - DOUBLE, DOUBLE, - 0, 0, 1, 1, 1, "double" } }, - { LDOUBLE, { sizeof (ldbl_t) * CHAR_BIT, 16 * CHAR_BIT, -1, - LDOUBLE, LDOUBLE, - 0, 0, 1, 1, 1, "long double" } }, - { COMPLEX, { sizeof (float _Complex) * CHAR_BIT, - 8 * CHAR_BIT, -1, - COMPLEX, COMPLEX, - 0, 0, 1, 1, 3, "float _Complex" } }, - { DCOMPLEX, { sizeof (double _Complex) * CHAR_BIT, - 16 * CHAR_BIT, -1, - DCOMPLEX, DCOMPLEX, - 0, 0, 1, 1, 3, "double _Complex" } }, - { LDCOMPLEX,{ sizeof (long double _Complex) * CHAR_BIT, - 32 * CHAR_BIT, -1, - LDCOMPLEX, LDCOMPLEX, - 0, 0, 1, 1, 3, "long double _Complex" } }, -#if 0 - { IMAGINARY,{ sizeof (float _Imaginary) * CHAR_BIT, - 4 * CHAR_BIT, -1, - IMAGINARY, IMAGINARY, - 0, 0, 1, 1, 2, "float _Imaginary" } }, - { DIMAGINARY,{ sizeof (double _Imaginary) * CHAR_BIT, - 8 * CHAR_BIT, -1, - DIMAGINARY, DIMAGINARY, - 0, 0, 1, 1, 2, "double _Imaginary" } }, - { LDIMAGINARY,{ sizeof (long double _Imaginary) * CHAR_BIT, - 16 * CHAR_BIT, -1, - LDIMAGINARY, LDIMAGINARY, - 0, 0, 1, 1, 2, "long double _Imaginary" } }, -#endif - { VOID, { -1, -1, -1, - VOID, VOID, - 0, 0, 0, 0, 0, "void" } }, - { STRUCT, { -1, -1, -1, - STRUCT, STRUCT, - 0, 0, 0, 0, 0, "struct" } }, - { UNION, { -1, -1, -1, - UNION, UNION, - 0, 0, 0, 0, 0, "union" } }, - { ENUM, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - ENUM, ENUM, - 1, 0, 0, 1, 1, "enum" } }, - { PTR, { sizeof (void *) * CHAR_BIT, 4 * CHAR_BIT, -1, - PTR, PTR, - 0, 1, 0, 0, 1, "pointer" } }, - { ARRAY, { -1, -1, -1, - ARRAY, ARRAY, - 0, 0, 0, 0, 0, "array" } }, - { FUNC, { -1, -1, -1, - FUNC, FUNC, - 0, 0, 0, 0, 0, "function" } }, - }; - - /* declaration stack */ - dcs = xcalloc(1, sizeof (dinfo_t)); - dcs->d_ctx = EXTERN; - dcs->d_ldlsym = &dcs->d_dlsyms; - - /* type information and classification */ - for (i = 0; i < sizeof (ittab) / sizeof (ittab[0]); i++) - STRUCT_ASSIGN(ttab[ittab[i].it_tspec], ittab[i].it_ttab); - if (!pflag) { - for (i = 0; i < NTSPEC; i++) - ttab[i].tt_psz = ttab[i].tt_sz; - } - - /* shared type structures */ - typetab = xcalloc(NTSPEC, sizeof (type_t)); - for (i = 0; i < NTSPEC; i++) - typetab[i].t_tspec = NOTSPEC; - typetab[BOOL].t_tspec = BOOL; - typetab[CHAR].t_tspec = CHAR; - typetab[SCHAR].t_tspec = SCHAR; - typetab[UCHAR].t_tspec = UCHAR; - typetab[SHORT].t_tspec = SHORT; - typetab[USHORT].t_tspec = USHORT; - typetab[INT].t_tspec = INT; - typetab[UINT].t_tspec = UINT; - typetab[LONG].t_tspec = LONG; - typetab[ULONG].t_tspec = ULONG; - typetab[QUAD].t_tspec = QUAD; - typetab[UQUAD].t_tspec = UQUAD; - typetab[FLOAT].t_tspec = FLOAT; - typetab[DOUBLE].t_tspec = DOUBLE; - typetab[LDOUBLE].t_tspec = LDOUBLE; - typetab[COMPLEX].t_tspec = COMPLEX; - typetab[DCOMPLEX].t_tspec = DCOMPLEX; - typetab[LDCOMPLEX].t_tspec = LDCOMPLEX; - typetab[IMAGINARY].t_tspec = IMAGINARY; - typetab[DIMAGINARY].t_tspec = DIMAGINARY; - typetab[LDIMAGINARY].t_tspec = LDIMAGINARY; - typetab[VOID].t_tspec = VOID; - /* - * Next two are not real types. They are only used by the parser - * to return keywords "signed" and "unsigned" - */ - typetab[SIGNED].t_tspec = SIGNED; - typetab[UNSIGN].t_tspec = UNSIGN; -} - -/* - * Returns a shared type structure for arithmetic types and void. - * - * It's important to duplicate this structure (using duptyp() or tduptyp()) - * if it is to be modified (adding qualifiers or anything else). - */ -type_t * -gettyp(tspec_t t) -{ - return (&typetab[t]); -} - -type_t * -duptyp(const type_t *tp) -{ - type_t *ntp; - - ntp = getblk(sizeof (type_t)); - STRUCT_ASSIGN(*ntp, *tp); - return (ntp); -} - -/* - * Use tduptyp() instead of duptyp() inside expressions (if the - * allocated memory should be freed after the expr). - */ -type_t * -tduptyp(const type_t *tp) -{ - type_t *ntp; - - ntp = tgetblk(sizeof (type_t)); - STRUCT_ASSIGN(*ntp, *tp); - return (ntp); -} - -/* - * Returns 1 if the argument is void or an incomplete array, - * struct, union or enum type. - */ -int -incompl(type_t *tp) -{ - tspec_t t; - - if ((t = tp->t_tspec) == VOID) { - return (1); - } else if (t == ARRAY) { - return (tp->t_aincompl); - } else if (t == STRUCT || t == UNION) { - return (tp->t_str->sincompl); - } else if (t == ENUM) { - return (tp->t_enum->eincompl); - } - return (0); -} - -/* - * Set the flag for (in)complete array, struct, union or enum - * types. - */ -void -setcompl(type_t *tp, int ic) -{ - tspec_t t; - - if ((t = tp->t_tspec) == ARRAY) { - tp->t_aincompl = ic; - } else if (t == STRUCT || t == UNION) { - tp->t_str->sincompl = ic; - } else { - if (t != ENUM) - lerror("setcompl() 1"); - tp->t_enum->eincompl = ic; - } -} - -/* - * Remember the storage class of the current declaration in dcs->d_scl - * (the top element of the declaration stack) and detect multiple - * storage classes. - */ -void -addscl(scl_t sc) -{ - if (sc == INLINE) { - if (dcs->d_inline) - /* duplicate '%s' */ - warning(10, "inline"); - dcs->d_inline = 1; - return; - } - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_smod != NOTSPEC || dcs->d_lmod != NOTSPEC) { - /* storage class after type is obsolescent */ - warning(83); - } - if (dcs->d_scl == NOSCL) { - dcs->d_scl = sc; - } else { - /* - * multiple storage classes. An error will be reported in - * deftyp(). - */ - dcs->d_mscl = 1; - } -} - -/* - * Remember the type, modifier or typedef name returned by the parser - * in *dcs (top element of decl stack). This information is used in - * deftyp() to build the type used for all declarators in this - * declaration. - * - * Is tp->t_typedef 1, the type comes from a previously defined typename. - * Otherwise it comes from a type specifier (int, long, ...) or a - * struct/union/enum tag. - */ -void -addtype(type_t *tp) -{ - tspec_t t; - - if (tp->t_typedef) { - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC || - dcs->d_dmod != NOTSPEC) { - /* - * something like "typedef int a; int a b;" - * This should not happen with current grammar. - */ - lerror("addtype()"); - } - dcs->d_type = tp; - return; - } - - t = tp->t_tspec; - - if (t == STRUCT || t == UNION || t == ENUM) { - /* - * something like "int struct a ..." - * struct/union/enum with anything else is not allowed - */ - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC || - dcs->d_dmod != NOTSPEC) { - /* - * remember that an error must be reported in - * deftyp(). - */ - dcs->d_terr = 1; - dcs->d_atyp = dcs->d_smod = dcs->d_lmod = - dcs->d_dmod = NOTSPEC; - } - dcs->d_type = tp; - return; - } - - if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { - /* - * something like "struct a int" - * struct/union/enum with anything else is not allowed - */ - dcs->d_terr = 1; - return; - } - - if (t == LONG && dcs->d_lmod == LONG) { - /* "long long" or "long ... long" */ - t = QUAD; - dcs->d_lmod = NOTSPEC; - if (!quadflg) - /* %s C does not support 'long long' */ - (void)gnuism(265, "ANSI"); - } - - if (dcs->d_type != NULL && dcs->d_type->t_typedef) { - /* something like "typedef int a; a long ..." */ - dcs->d_type = tdeferr(dcs->d_type, t); - return; - } - - /* now it can be only a combination of arithmetic types and void */ - if (t == SIGNED || t == UNSIGN) { - /* remeber specifiers "signed" and "unsigned" in dcs->d_smod */ - if (dcs->d_smod != NOTSPEC) - /* - * more than one "signed" and/or "unsigned"; print - * an error in deftyp() - */ - dcs->d_terr = 1; - dcs->d_smod = t; - } else if (t == SHORT || t == LONG || t == QUAD) { - /* - * remember specifiers "short", "long" and "long long" in - * dcs->d_lmod - */ - if (dcs->d_lmod != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_lmod = t; - } else if (t == COMPLEX || t == IMAGINARY) { - /* - * remember specifiers "_Complex" and "_Imaginary" in - * dcs->d_dmod - */ - if (dcs->d_dmod != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_dmod = t; - } else { - /* - * remember specifiers "void", "char", "int", "float" or - * "double" int dcs->d_atyp - */ - if (dcs->d_atyp != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_atyp = t; - } -} - -/* - * called if a list of declaration specifiers contains a typedef name - * and other specifiers (except struct, union, enum, typedef name) - */ -static type_t * -tdeferr(type_t *td, tspec_t t) -{ - tspec_t t2; - - t2 = td->t_tspec; - - switch (t) { - case SIGNED: - case UNSIGN: - if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || - t2 == QUAD) { - /* modifying typedef with ... */ - warning(5, ttab[t].tt_name); - td = duptyp(gettyp(mrgtspec(t2, t))); - td->t_typedef = 1; - return (td); - } - break; - case SHORT: - if (t2 == INT || t2 == UINT) { - /* modifying typedef with ... */ - warning(5, "short"); - td = duptyp(gettyp(t2 == INT ? SHORT : USHORT)); - td->t_typedef = 1; - return (td); - } - break; - case LONG: - if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || - t2 == FLOAT || t2 == DOUBLE || t2 == COMPLEX || - t2 == IMAGINARY) { - /* modifying typedef with ... */ - warning(5, "long"); - if (t2 == INT) { - td = gettyp(LONG); - } else if (t2 == UINT) { - td = gettyp(ULONG); - } else if (t2 == LONG) { - td = gettyp(QUAD); - } else if (t2 == ULONG) { - td = gettyp(UQUAD); - } else if (t2 == FLOAT) { - td = gettyp(DOUBLE); - } else if (t2 == DOUBLE) { - td = gettyp(LDOUBLE); - } else if (t2 == COMPLEX) { - td = gettyp(DCOMPLEX); - } else if (t2 == DCOMPLEX) { - td = gettyp(LDCOMPLEX); - } else if (t2 == IMAGINARY) { - td = gettyp(DIMAGINARY); - } else if (t2 == DIMAGINARY) { - td = gettyp(LDIMAGINARY); - } - td = duptyp(td); - td->t_typedef = 1; - return (td); - } - break; - /* LINTED (enumeration values not handled in switch) */ - } - - /* Anything other is not accepted. */ - - dcs->d_terr = 1; - return (td); -} - -/* - * Remember the symbol of a typedef name (2nd arg) in a struct, union - * or enum tag if the typedef name is the first defined for this tag. - * - * If the tag is unnamed, the typdef name is used for identification - * of this tag in lint2. Although its possible that more than one typedef - * name is defined for one tag, the first name defined should be unique - * if the tag is unnamed. - */ -static void -settdsym(type_t *tp, sym_t *sym) -{ - tspec_t t; - - if ((t = tp->t_tspec) == STRUCT || t == UNION) { - if (tp->t_str->stdef == NULL) - tp->t_str->stdef = sym; - } else if (t == ENUM) { - if (tp->t_enum->etdef == NULL) - tp->t_enum->etdef = sym; - } -} - -/* - * Remember a qualifier which is part of the declaration specifiers - * (and not the declarator) in the top element of the declaration stack. - * Also detect multiple qualifiers of the same kind. - - * The remembered qualifier is used by deftyp() to construct the type - * for all declarators. - */ -void -addqual(tqual_t q) -{ - if (q == CONST) { - if (dcs->d_const) { - /* duplicate "%s" */ - warning(10, "const"); - } - dcs->d_const = 1; - } else if (q == VOLATILE) { - if (dcs->d_volatile) { - /* duplicate "%s" */ - warning(10, "volatile"); - } - dcs->d_volatile = 1; - } else if (q == RESTRICT) { - if (dcs->d_restrict) { - /* duplicate "%s" */ - warning(10, "restrict"); - } - dcs->d_restrict = 1; - } else - lerror("addqual() 1"); -} - -/* - * Go to the next declaration level (structs, nested structs, blocks, - * argument declaration lists ...) - */ -void -pushdecl(scl_t sc) -{ - dinfo_t *di; - - if (dflag) - (void)printf("pushdecl(%d)\n", (int)sc); - - /* put a new element on the declaration stack */ - di = xcalloc(1, sizeof (dinfo_t)); - di->d_nxt = dcs; - dcs = di; - di->d_ctx = sc; - di->d_ldlsym = &di->d_dlsyms; -} - -/* - * Go back to previous declaration level - */ -void -popdecl(void) -{ - dinfo_t *di; - - if (dflag) - (void)printf("popdecl(%d)\n", (int)dcs->d_ctx); - - if (dcs->d_nxt == NULL) - lerror("popdecl() 1"); - di = dcs; - dcs = di->d_nxt; - switch (di->d_ctx) { - case EXTERN: - /* there is nothing after external declarations */ - lerror("popdecl() 2"); - /* NOTREACHED */ - case MOS: - case MOU: - case ENUMCON: - /* - * Symbols declared in (nested) structs or enums are - * part of the next level (they are removed from the - * symbol table if the symbols of the outher level are - * removed) - */ - if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) - dcs->d_ldlsym = di->d_ldlsym; - break; - case ARG: - /* - * All symbols in dcs->d_dlsyms are introduced in old style - * argument declarations (it's not clean, but possible). - * They are appended to the list of symbols declared in - * an old style argument identifier list or a new style - * parameter type list. - */ - if (di->d_dlsyms != NULL) { - *di->d_ldlsym = dcs->d_fpsyms; - dcs->d_fpsyms = di->d_dlsyms; - } - break; - case ABSTRACT: - /* - * casts and sizeof - * Append all symbols declared in the abstract declaration - * to the list of symbols declared in the surounding decl. - * or block. - * XXX I'm not sure whether they should be removed from the - * symbol table now or later. - */ - if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) - dcs->d_ldlsym = di->d_ldlsym; - break; - case AUTO: - /* check usage of local vars */ - chkusage(di); - /* FALLTHROUGH */ - case PARG: - /* usage of arguments will be checked by funcend() */ - rmsyms(di->d_dlsyms); - break; - default: - lerror("popdecl() 3"); - } - free(di); -} - -/* - * Set flag d_asm in all declaration stack elements up to the - * outermost one. - * - * This is used to mark compound statements which have, possibly in - * nested compound statements, asm statements. For these compound - * statements no warnings about unused or unitialized variables are - * printed. - * - * There is no need to clear d_asm in dinfo structs with context AUTO, - * because these structs are freed at the end of the compound statement. - * But it must be cleard in the outermost dinfo struct, which has - * context EXTERN. This could be done in clrtyp() and would work for - * C, but not for C++ (due to mixed statements and declarations). Thus - * we clear it in glclup(), which is used to do some cleanup after - * global declarations/definitions. - */ -void -setasm(void) -{ - dinfo_t *di; - - for (di = dcs; di != NULL; di = di->d_nxt) - di->d_asm = 1; -} - -/* - * Clean all elements of the top element of declaration stack which - * will be used by the next declaration - */ -void -clrtyp(void) -{ - dcs->d_atyp = dcs->d_smod = dcs->d_lmod = dcs->d_dmod = NOTSPEC; - dcs->d_scl = NOSCL; - dcs->d_type = NULL; - dcs->d_const = dcs->d_volatile = 0; - dcs->d_inline = 0; - dcs->d_mscl = dcs->d_terr = 0; - dcs->d_nedecl = 0; - dcs->d_notyp = 0; -} - -/* - * Merge the domain (_Complex or _Imaginary) into a type. Returns non-zero - * if the merge doesn't make sense. e.g., no "int _Complex". - */ -int -mergedomain(tspec_t *tp, tspec_t domain) -{ - if (domain == NOTSPEC) - return (0); - if (domain != COMPLEX && domain != IMAGINARY) - lerror("mergedomain()"); - switch (*tp) { - case FLOAT: - *tp = domain; - break; - case DOUBLE: - *tp = domain == COMPLEX ? DCOMPLEX : DIMAGINARY; - break; - case LDOUBLE: - *tp = domain == COMPLEX ? LDCOMPLEX : LDIMAGINARY; - break; - default: - return (1); - } - return (0); -} - -/* - * Create a type structure from the informations gathered in - * the declaration stack. - * Complain about storage classes which are not possible in current - * context. - */ -void -deftyp(void) -{ - tspec_t t, s, l, d; - type_t *tp; - scl_t scl; - - t = dcs->d_atyp; /* BOOL, CHAR, INT, FLOAT, - DOUBLE, VOID */ - s = dcs->d_smod; /* SIGNED, UNSIGNED */ - l = dcs->d_lmod; /* SHORT, LONG, QUAD */ - d = dcs->d_dmod; /* COMPLEX, IMAGINARY */ - tp = dcs->d_type; - scl = dcs->d_scl; - - if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && tp == NULL) - dcs->d_notyp = 1; - - if (tp != NULL && (t != NOTSPEC || s != NOTSPEC || l != NOTSPEC)) { - /* should never happen */ - lerror("deftyp() 1"); - } - - if (tp == NULL) { - switch (t) { - case NOTSPEC: - t = INT; - /* FALLTHROUGH */ - case BOOL: - break; - case INT: - if (s == NOTSPEC) - s = SIGNED; - break; - case CHAR: - if (l != NOTSPEC) { - dcs->d_terr = 1; - l = NOTSPEC; - } - break; - case FLOAT: - if (l == LONG) { - l = NOTSPEC; - t = DOUBLE; - /* use 'double' instead of ... */ - warning(6); - } - break; - case DOUBLE: - if (l == LONG) { - l = NOTSPEC; - t = LDOUBLE; - } - break; - case VOID: - break; - default: - lerror("deftyp() 2"); - } - if (mergedomain(&t, d)) - dcs->d_terr = 1; - if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { - dcs->d_terr = 1; - l = s = NOTSPEC; - } - if (l != NOTSPEC) - t = l; - dcs->d_type = gettyp(mrgtspec(t, s)); - } - - if (dcs->d_mscl) { - /* only one storage class allowed */ - error(7); - } - if (dcs->d_terr) { - /* illegal type combination */ - error(4); - } - - if (dcs->d_ctx == EXTERN) { - if (scl == REG || scl == AUTO) { - /* illegal storage class */ - error(8); - scl = NOSCL; - } - } else if (dcs->d_ctx == ARG || dcs->d_ctx == PARG) { - if (scl != NOSCL && scl != REG) { - /* only "register" valid ... */ - error(9); - scl = NOSCL; - } - } - - dcs->d_scl = scl; - - if (dcs->d_const && dcs->d_type->t_const) { - if (!dcs->d_type->t_typedef) - lerror("deftyp() 3"); - /* typedef already qualified with "%s" */ - warning(68, "const"); - } - if (dcs->d_volatile && dcs->d_type->t_volatile) { - if (!dcs->d_type->t_typedef) - lerror("deftyp() 4"); - /* typedef already qualified with "%s" */ - warning(68, "volatile"); - } - - if (dcs->d_const || dcs->d_volatile) { - dcs->d_type = duptyp(dcs->d_type); - dcs->d_type->t_const |= dcs->d_const; - dcs->d_type->t_volatile |= dcs->d_volatile; - } -} - -/* - * Merge type specifiers (char, ..., long long, signed, unsigned). - */ -static tspec_t -mrgtspec(tspec_t t, tspec_t s) -{ - if (s == SIGNED || s == UNSIGN) { - if (t == CHAR) { - t = s == SIGNED ? SCHAR : UCHAR; - } else if (t == SHORT) { - t = s == SIGNED ? SHORT : USHORT; - } else if (t == INT) { - t = s == SIGNED ? INT : UINT; - } else if (t == LONG) { - t = s == SIGNED ? LONG : ULONG; - } else if (t == QUAD) { - t = s == SIGNED ? QUAD : UQUAD; - } - } - - return (t); -} - -/* - * Return the length of a type in bit. - * - * Printing a message if the outhermost dimension of an array is 0 must - * be done by the caller. All other problems are reported by length() - * if name is not NULL. - */ -int -length(type_t *tp, const char *name) -{ - int elem, elsz; - - elem = 1; - while (tp && tp->t_tspec == ARRAY) { - elem *= tp->t_dim; - tp = tp->t_subt; - } - if (tp == NULL) - return (-1); - - switch (tp->t_tspec) { - case FUNC: - /* compiler takes size of function */ - lerror(msgs[12]); - /* NOTREACHED */ - case STRUCT: - case UNION: - if (incompl(tp) && name != NULL) { - /* incomplete structure or union %s: %s */ - error(31, tp->t_str->stag->s_name, name); - } - elsz = tp->t_str->size; - break; - case ENUM: - if (incompl(tp) && name != NULL) { - /* incomplete enum type: %s */ - warning(13, name); - } - /* FALLTHROUGH */ - default: - elsz = size(tp->t_tspec); - if (elsz <= 0) - lerror("length()"); - break; - } - return (elem * elsz); -} - -/* - * Get the alignment of the given type in bits. - */ -int -getbound(type_t *tp) -{ - int a; - tspec_t t; - - while (tp && tp->t_tspec == ARRAY) - tp = tp->t_subt; - - if (tp == NULL) - return (-1); - - if ((t = tp->t_tspec) == STRUCT || t == UNION) { - a = tp->t_str->align; - } else if (t == FUNC) { - /* compiler takes alignment of function */ - error(14); - a = ALIGN(1) * CHAR_BIT; - } else { - if ((a = size(t)) == 0) { - a = CHAR_BIT; - } else if (a > ALIGN(1) * CHAR_BIT) { - a = ALIGN(1) * CHAR_BIT; - } - } - if (a < CHAR_BIT || a > ALIGN(1) * CHAR_BIT) - lerror("getbound() 1"); - return (a); -} - -/* - * Concatenate two lists of symbols by s_nxt. Used by declarations of - * struct/union/enum elements and parameters. - */ -sym_t * -lnklst(sym_t *l1, sym_t *l2) -{ - sym_t *l; - - if ((l = l1) == NULL) - return (l2); - while (l1->s_nxt != NULL) - l1 = l1->s_nxt; - l1->s_nxt = l2; - return (l); -} - -/* - * Check if the type of the given symbol is valid and print an error - * message if it is not. - * - * Invalid types are: - * - arrays of incomlete types or functions - * - functions returning arrays or functions - * - void types other than type of function or pointer - */ -void -chktyp(sym_t *sym) -{ - tspec_t to, t; - type_t **tpp, *tp; - - tpp = &sym->s_type; - to = NOTSPEC; - while ((tp = *tpp) != NULL) { - t = tp->t_tspec; - /* - * If this is the type of an old style function definition, - * a better warning is printed in funcdef(). - */ - if (t == FUNC && !tp->t_proto && - !(to == NOTSPEC && sym->s_osdef)) { - if (sflag && hflag) - /* function declaration is not a prototype */ - warning(287); - } - if (to == FUNC) { - if (t == FUNC || t == ARRAY) { - /* function returns illegal type */ - error(15); - if (t == FUNC) { - *tpp = incref(*tpp, PTR); - } else { - *tpp = incref((*tpp)->t_subt, PTR); - } - return; - } else if (tp->t_const || tp->t_volatile) { - if (sflag) { - /* function cannot return const... */ - warning(228); - } - } - } if (to == ARRAY) { - if (t == FUNC) { - /* array of function is illegal */ - error(16); - *tpp = gettyp(INT); - return; - } else if (t == ARRAY && tp->t_dim == 0) { - /* null dimension */ - error(17); - return; - } else if (t == VOID) { - /* illegal use of void */ - error(18); - *tpp = gettyp(INT); -#if 0 /* errors are produced by length() */ - } else if (incompl(tp)) { - /* array of incomplete type */ - if (sflag) { - error(301); - } else { - warning(301); - } -#endif - } - } else if (to == NOTSPEC && t == VOID) { - if (dcs->d_ctx == PARG) { - if (sym->s_scl != ABSTRACT) { - if (sym->s_name == unnamed) - lerror("chktyp()"); - /* void param cannot have name: %s */ - error(61, sym->s_name); - *tpp = gettyp(INT); - } - } else if (dcs->d_ctx == ABSTRACT) { - /* ok */ - } else if (sym->s_scl != TYPEDEF) { - /* void type for %s */ - error(19, sym->s_name); - *tpp = gettyp(INT); - } - } - if (t == VOID && to != PTR) { - if (tp->t_const || tp->t_volatile || tp->t_restrict) { - /* inappropriate qualifiers with "void" */ - warning(69); - tp->t_const = tp->t_volatile = 0; - tp->t_restrict = 0; - } - } - tpp = &tp->t_subt; - to = t; - } -} - -/* - * Process the declarator of a struct/union element. - */ -sym_t * -decl1str(sym_t *dsym) -{ - type_t *tp; - tspec_t t; - int sz, o, len; - scl_t sc; - - if ((sc = dsym->s_scl) != MOS && sc != MOU) - lerror("decl1str() 1"); - - if (dcs->d_rdcsym != NULL) { - if ((sc = dcs->d_rdcsym->s_scl) != MOS && sc != MOU) - /* should be ensured by storesym() */ - lerror("decl1str() 2"); - if (dsym->s_styp == dcs->d_rdcsym->s_styp) { - /* duplicate member name: %s */ - error(33, dsym->s_name); - rmsym(dcs->d_rdcsym); - } - } - - chktyp(dsym); - - t = (tp = dsym->s_type)->t_tspec; - - if (dsym->s_field) { - /* - * bit field - * - * only unsigned and signed int are portable bit-field types - * (at least in ANSI C, in traditional C only unsigned int) - */ - if (t == CHAR || t == UCHAR || t == SCHAR || - t == SHORT || t == USHORT || t == ENUM) { - if (sflag) { - /* bit-field type '%s' invalid in ANSI C */ - warning(273, tyname(tp)); - } else if (pflag) { - /* nonportable bit-field type */ - warning(34); - } - if (isutyp(t)) - tp->t_tspec = UINT; - else - tp->t_tspec = INT; - - tp->t_isenum = 0; - } else if (t == INT && dcs->d_smod == NOTSPEC) { - if (pflag) { - /* nonportable bit-field type */ - warning(34); - } - } else if (t != INT && t != UINT && t != LONG && - t != ULONG && t != QUAD && t != UQUAD && t != BOOL) { - /* illegal bit-field type */ - error(35); - sz = tp->t_flen; - dsym->s_type = tp = duptyp(gettyp(t = INT)); - if ((tp->t_flen = sz) > size(t)) - tp->t_flen = size(t); - } - if ((len = tp->t_flen) < 0 || len > size(t)) { - /* illegal bit-field size */ - error(36); - tp->t_flen = size(t); - } else if (len == 0 && dsym->s_name != unnamed) { - /* zero size bit-field */ - error(37); - tp->t_flen = size(t); - } - if (dsym->s_scl == MOU) { - /* illegal use of bit-field */ - error(41); - dsym->s_type->t_isfield = 0; - dsym->s_field = 0; - } - } else if (t == FUNC) { - /* function illegal in structure or union */ - error(38); - dsym->s_type = tp = incref(tp, t = PTR); - } - - /* - * bit-fields of length 0 are not warned about because length() - * does not return the length of the bit-field but the length - * of the type the bit-field is packed in (its ok) - */ - if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { - if (t == ARRAY && dsym->s_type->t_dim == 0) { - /* illegal zero sized structure member: %s */ - warning(39, dsym->s_name); - } - } - - if (dcs->d_ctx == MOU) { - o = dcs->d_offset; - dcs->d_offset = 0; - } - if (dsym->s_field) { - align(getbound(tp), tp->t_flen); - dsym->s_value.v_quad = (dcs->d_offset / size(t)) * size(t); - tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; - dcs->d_offset += tp->t_flen; - } else { - align(getbound(tp), 0); - dsym->s_value.v_quad = dcs->d_offset; - dcs->d_offset += sz; - } - if (dcs->d_ctx == MOU) { - if (o > dcs->d_offset) - dcs->d_offset = o; - } - - chkfdef(dsym, 0); - - return (dsym); -} - -/* - * Aligns next structure element as required. - * - * al contains the required alignment, len the length of a bit-field. - */ -static void -align(int al, int len) -{ - int no; - - /* - * The alignment of the current element becomes the alignment of - * the struct/union if it is larger than the current alignment - * of the struct/union. - */ - if (al > dcs->d_stralign) - dcs->d_stralign = al; - - no = (dcs->d_offset + (al - 1)) & ~(al - 1); - if (len == 0 || dcs->d_offset + len > no) - dcs->d_offset = no; -} - -/* - * Remember the width of the field in its type structure. - */ -sym_t * -bitfield(sym_t *dsym, int len) -{ - if (dsym == NULL) { - dsym = getblk(sizeof (sym_t)); - dsym->s_name = unnamed; - dsym->s_kind = FMOS; - dsym->s_scl = MOS; - dsym->s_type = gettyp(INT); - dsym->s_blklev = -1; - } - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_isfield = 1; - dsym->s_type->t_proto = 0; - dsym->s_type->t_isenum = 0; - dsym->s_type->t_flen = len; - dsym->s_field = 1; - return (dsym); -} - -/* - * Collect informations about a sequence of asterisks and qualifiers - * in a list of type pqinf_t. - * Qualifiers refer always to the left asterisk. The rightmost asterisk - * will be at the top of the list. - */ -pqinf_t * -mergepq(pqinf_t *p1, pqinf_t *p2) -{ - pqinf_t *p; - - if (p2->p_pcnt != 0) { - /* left '*' at the end of the list */ - for (p = p2; p->p_nxt != NULL; p = p->p_nxt) ; - p->p_nxt = p1; - return (p2); - } else { - if (p2->p_const) { - if (p1->p_const) { - /* duplicate %s */ - warning(10, "const"); - } - p1->p_const = 1; - } - if (p2->p_volatile) { - if (p1->p_volatile) { - /* duplicate %s */ - warning(10, "volatile"); - } - p1->p_volatile = 1; - } - free(p2); - return (p1); - } -} - -/* - * Followint 3 functions extend the type of a declarator with - * pointer, function and array types. - * - * The current type is the type built by deftyp() (dcs->d_type) and - * pointer, function and array types already added for this - * declarator. The new type extension is inserted between both. - */ -sym_t * -addptr(sym_t *decl, pqinf_t *pi) -{ - type_t **tpp, *tp; - pqinf_t *npi; - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - while (pi != NULL) { - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = PTR; - tp->t_const = pi->p_const; - tp->t_volatile = pi->p_volatile; - *(tpp = &tp->t_subt) = dcs->d_type; - npi = pi->p_nxt; - free(pi); - pi = npi; - } - return (decl); -} - -/* - * If a dimension was specified, dim is 1, otherwise 0 - * n is the specified dimension - */ -sym_t * -addarray(sym_t *decl, int dim, int n) -{ - type_t **tpp, *tp; - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = ARRAY; - tp->t_subt = dcs->d_type; - tp->t_dim = n; - - if (n < 0) { - /* zero or negative array dimension */ - error(20); - n = 0; - } else if (n == 0 && dim) { - /* zero or negative array dimension */ - warning(20); - } else if (n == 0 && !dim) { - /* is incomplete type */ - setcompl(tp, 1); - } - - return (decl); -} - -sym_t * -addfunc(sym_t *decl, sym_t *args) -{ - type_t **tpp, *tp; - - if (dcs->d_proto) { - args = nsfunc(decl, args); - } else { - osfunc(decl, args); - } - - /* - * The symbols are removed from the symbol table by popdecl() after - * addfunc(). To be able to restore them if this is a function - * definition, a pointer to the list of all symbols is stored in - * dcs->d_nxt->d_fpsyms. Also a list of the arguments (concatenated - * by s_nxt) is stored in dcs->d_nxt->d_fargs. - * (dcs->d_nxt must be used because *dcs is the declaration stack - * element created for the list of params and is removed after - * addfunc()) - */ - if (dcs->d_nxt->d_ctx == EXTERN && - decl->s_type == dcs->d_nxt->d_type) { - dcs->d_nxt->d_fpsyms = dcs->d_dlsyms; - dcs->d_nxt->d_fargs = args; - } - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_nxt->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = FUNC; - tp->t_subt = dcs->d_nxt->d_type; - if ((tp->t_proto = dcs->d_proto) != 0) - tp->t_args = args; - tp->t_vararg = dcs->d_vararg; - - return (decl); -} - -/* - * Called for new style function declarations. - */ -/* ARGSUSED */ -static sym_t * -nsfunc(sym_t *decl, sym_t *args) -{ - sym_t *arg, *sym; - scl_t sc; - int n; - - /* - * Declarations of structs/unions/enums in param lists are legal, - * but senseless. - */ - for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { - sc = sym->s_scl; - if (sc == STRTAG || sc == UNIONTAG || sc == ENUMTAG) { - /* dubious tag declaration: %s %s */ - warning(85, scltoa(sc), sym->s_name); - } - } - - n = 1; - for (arg = args; arg != NULL; arg = arg->s_nxt) { - if (arg->s_type->t_tspec == VOID) { - if (n > 1 || arg->s_nxt != NULL) { - /* "void" must be sole parameter */ - error(60); - arg->s_type = gettyp(INT); - } - } - n++; - } - - /* return NULL if first param is VOID */ - return (args != NULL && args->s_type->t_tspec != VOID ? args : NULL); -} - -/* - * Called for old style function declarations. - */ -static void -osfunc(sym_t *decl, sym_t *args) -{ - /* - * Remember list of params only if this is really seams to be - * a function definition. - */ - if (dcs->d_nxt->d_ctx == EXTERN && - decl->s_type == dcs->d_nxt->d_type) { - /* - * We assume that this becomes a function definition. If - * we are wrong, its corrected in chkfdef(). - */ - if (args != NULL) { - decl->s_osdef = 1; - decl->s_args = args; - } - } else { - if (args != NULL) - /* function prototype parameters must have types */ - warning(62); - } -} - -/* - * Lists of Identifiers in functions declarations are allowed only if - * its also a function definition. If this is not the case, print a - * error message. - */ -void -chkfdef(sym_t *sym, int msg) -{ - if (sym->s_osdef) { - if (msg) { - /* incomplete or misplaced function definition */ - error(22); - } - sym->s_osdef = 0; - sym->s_args = NULL; - } -} - -/* - * Process the name in a declarator. - * If the symbol does already exists, a new one is created. - * The symbol becomes one of the storage classes EXTERN, STATIC, AUTO or - * TYPEDEF. - * s_def and s_reg are valid after dname(). - */ -sym_t * -dname(sym_t *sym) -{ - scl_t sc = NOSCL; - - if (sym->s_scl == NOSCL) { - dcs->d_rdcsym = NULL; - } else if (sym->s_defarg) { - sym->s_defarg = 0; - dcs->d_rdcsym = NULL; - } else { - dcs->d_rdcsym = sym; - sym = pushdown(sym); - } - - switch (dcs->d_ctx) { - case MOS: - case MOU: - /* Parent setzen */ - sym->s_styp = dcs->d_tagtyp->t_str; - sym->s_def = DEF; - sym->s_value.v_tspec = INT; - sc = dcs->d_ctx; - break; - case EXTERN: - /* - * static and external symbols without "extern" are - * considered to be tentative defined, external - * symbols with "extern" are declared, and typedef names - * are defined. Tentative defined and declared symbols - * may become defined if an initializer is present or - * this is a function definition. - */ - if ((sc = dcs->d_scl) == NOSCL) { - sc = EXTERN; - sym->s_def = TDEF; - } else if (sc == STATIC) { - sym->s_def = TDEF; - } else if (sc == TYPEDEF) { - sym->s_def = DEF; - } else if (sc == EXTERN) { - sym->s_def = DECL; - } else { - lerror("dname() 1"); - } - break; - case PARG: - sym->s_arg = 1; - /* FALLTHROUGH */ - case ARG: - if ((sc = dcs->d_scl) == NOSCL) { - sc = AUTO; - } else if (sc == REG) { - sym->s_reg = 1; - sc = AUTO; - } else { - lerror("dname() 2"); - } - sym->s_def = DEF; - break; - case AUTO: - if ((sc = dcs->d_scl) == NOSCL) { - /* - * XXX somewhat ugly because we dont know whether - * this is AUTO or EXTERN (functions). If we are - * wrong it must be corrected in decl1loc(), where - * we have the necessary type information. - */ - sc = AUTO; - sym->s_def = DEF; - } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { - sym->s_def = DEF; - } else if (sc == REG) { - sym->s_reg = 1; - sc = AUTO; - sym->s_def = DEF; - } else if (sc == EXTERN) { - sym->s_def = DECL; - } else { - lerror("dname() 3"); - } - break; - default: - lerror("dname() 4"); - } - sym->s_scl = sc; - - sym->s_type = dcs->d_type; - - dcs->d_fpsyms = NULL; - - return (sym); -} - -/* - * Process a name in the list of formal params in an old style function - * definition. - */ -sym_t * -iname(sym_t *sym) -{ - if (sym->s_scl != NOSCL) { - if (blklev == sym->s_blklev) { - /* redeclaration of formal parameter %s */ - error(21, sym->s_name); - if (!sym->s_defarg) - lerror("iname()"); - } - sym = pushdown(sym); - } - sym->s_type = gettyp(INT); - sym->s_scl = AUTO; - sym->s_def = DEF; - sym->s_defarg = sym->s_arg = 1; - return (sym); -} - -/* - * Create the type of a tag. - * - * tag points to the symbol table entry of the tag - * kind is the kind of the tag (STRUCT/UNION/ENUM) - * decl is 1 if the type of the tag will be completed in this declaration - * (the following token is T_LBRACE) - * semi is 1 if the following token is T_SEMI - */ -type_t * -mktag(sym_t *tag, tspec_t kind, int decl, int semi) -{ - scl_t scl = NOSCL; - type_t *tp; - - if (kind == STRUCT) { - scl = STRTAG; - } else if (kind == UNION) { - scl = UNIONTAG; - } else if (kind == ENUM) { - scl = ENUMTAG; - } else { - lerror("mktag()"); - } - - if (tag != NULL) { - if (tag->s_scl != NOSCL) { - tag = newtag(tag, scl, decl, semi); - } else { - /* a new tag, no empty declaration */ - dcs->d_nxt->d_nedecl = 1; - if (scl == ENUMTAG && !decl) { - if (sflag || pflag) - /* forward reference to enum type */ - warning(42); - } - } - if (tag->s_scl == NOSCL) { - tag->s_scl = scl; - tag->s_type = tp = getblk(sizeof (type_t)); - } else { - tp = tag->s_type; - } - } else { - tag = getblk(sizeof (sym_t)); - tag->s_name = unnamed; - STRUCT_ASSIGN(tag->s_dpos, curr_pos); - tag->s_kind = FTAG; - tag->s_scl = scl; - tag->s_blklev = -1; - tag->s_type = tp = getblk(sizeof (type_t)); - dcs->d_nxt->d_nedecl = 1; - } - - if (tp->t_tspec == NOTSPEC) { - tp->t_tspec = kind; - if (kind != ENUM) { - tp->t_str = getblk(sizeof (str_t)); - tp->t_str->align = CHAR_BIT; - tp->t_str->stag = tag; - } else { - tp->t_isenum = 1; - tp->t_enum = getblk(sizeof (enum_t)); - tp->t_enum->etag = tag; - } - /* is incomplete type */ - setcompl(tp, 1); - } - - return (tp); -} - -/* - * Checks all possible cases of tag redeclarations. - * decl is 1 if T_LBRACE follows - * semi is 1 if T_SEMI follows - */ -static sym_t * -newtag(sym_t *tag, scl_t scl, int decl, int semi) -{ - if (tag->s_blklev < blklev) { - if (semi) { - /* "struct a;" */ - if (!sflag) - /* decl. introduces new type ... */ - warning(44, scltoa(scl), tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (decl) { - /* "struct a { ..." */ - if (hflag) - /* redefinition hides earlier one: %s */ - warning(43, tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (tag->s_scl != scl) { - /* base type is really "%s %s" */ - warning(45, scltoa(tag->s_scl), tag->s_name); - /* declaration introduces new type in ANSI C: %s %s */ - if (!sflag) - warning(44, scltoa(scl), tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } - } else { - if (tag->s_scl != scl) { - /* (%s) tag redeclared */ - error(46, scltoa(tag->s_scl)); - prevdecl(-1, tag); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (decl && !incompl(tag->s_type)) { - /* (%s) tag redeclared */ - error(46, scltoa(tag->s_scl)); - prevdecl(-1, tag); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (semi || decl) { - dcs->d_nxt->d_nedecl = 1; - } - } - return (tag); -} - -const char * -scltoa(scl_t sc) -{ - const char *s; - - switch (sc) { - case EXTERN: s = "extern"; break; - case STATIC: s = "static"; break; - case AUTO: s = "auto"; break; - case REG: s = "register"; break; - case TYPEDEF: s = "typedef"; break; - case STRTAG: s = "struct"; break; - case UNIONTAG: s = "union"; break; - case ENUMTAG: s = "enum"; break; - default: lerror("tagttoa()"); - } - return (s); -} - -/* - * Completes the type of a tag in a struct/union/enum declaration. - * tp points to the type of the, tag, fmem to the list of members/enums. - */ -type_t * -compltag(type_t *tp, sym_t *fmem) -{ - tspec_t t; - str_t *sp; - int n; - sym_t *mem; - - /* from now a complete type */ - setcompl(tp, 0); - - if ((t = tp->t_tspec) != ENUM) { - align(dcs->d_stralign, 0); - sp = tp->t_str; - sp->align = dcs->d_stralign; - sp->size = dcs->d_offset; - sp->memb = fmem; - if (sp->size == 0) { - if (sflag) { - /* zero sized %s */ - warning(47, ttab[t].tt_name); - } - } else { - n = 0; - for (mem = fmem; mem != NULL; mem = mem->s_nxt) { - if (mem->s_name != unnamed) - n++; - } - if (n == 0) { - /* %s has no named members */ - warning(65, - t == STRUCT ? "structure" : "union"); - } - } - } else { - tp->t_enum->elem = fmem; - } - return (tp); -} - -/* - * Processes the name of an enumerator in en enum declaration. - * - * sym points to the enumerator - * val is the value of the enumerator - * impl is 1 if the value of the enumerator was not explicitly specified. - */ -sym_t * -ename(sym_t *sym, int val, int impl) -{ - if (sym->s_scl) { - if (sym->s_blklev == blklev) { - /* no hflag, because this is illegal!!! */ - if (sym->s_arg) { - /* enumeration constant hides parameter: %s */ - warning(57, sym->s_name); - } else { - /* redeclaration of %s */ - error(27, sym->s_name); - /* - * inside blocks it should not too complicated - * to find the position of the previous - * declaration - */ - if (blklev == 0) - prevdecl(-1, sym); - } - } else { - if (hflag) - /* redefinition hides earlier one: %s */ - warning(43, sym->s_name); - } - sym = pushdown(sym); - } - sym->s_scl = ENUMCON; - sym->s_type = dcs->d_tagtyp; - sym->s_value.v_tspec = INT; - sym->s_value.v_quad = val; - if (impl && val - 1 == INT_MAX) { - /* overflow in enumeration values: %s */ - warning(48, sym->s_name); - } - enumval = val + 1; - return (sym); -} - -/* - * Process a single external declarator. - */ -void -decl1ext(sym_t *dsym, int initflg) -{ - int warn, rval, redec; - sym_t *rdsym; - - chkfdef(dsym, 1); - - chktyp(dsym); - - if (initflg && !(initerr = chkinit(dsym))) - dsym->s_def = DEF; - - /* - * Declarations of functions are marked as "tentative" in dname(). - * This is wrong because there are no tentative function - * definitions. - */ - if (dsym->s_type->t_tspec == FUNC && dsym->s_def == TDEF) - dsym->s_def = DECL; - - if (dcs->d_inline) { - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_inline = 1; - } else { - /* variable declared inline: %s */ - warning(268, dsym->s_name); - } - } - - if (dsym->s_type->t_tspec == FUNC) { - if (noretflg) - dsym->s_noreturn = 1; - } - noretflg = 0; - - /* Write the declaration into the output file */ - if (plibflg && llibflg && - dsym->s_type->t_tspec == FUNC && dsym->s_type->t_proto) { - /* - * With both LINTLIBRARY and PROTOLIB the prototype is - * written as a function definition to the output file. - */ - rval = dsym->s_type->t_subt->t_tspec != VOID; - outfdef(dsym, &dsym->s_dpos, rval, 0, NULL); - } else { - outsym(dsym, dsym->s_scl, dsym->s_def); - } - - if ((rdsym = dcs->d_rdcsym) != NULL) { - /* - * If the old symbol stems from a old style function definition - * we have remembered the params in rdsmy->s_args and compare - * them with the params of the prototype. - */ - if (rdsym->s_osdef && dsym->s_type->t_proto) { - redec = chkosdef(rdsym, dsym); - } else { - redec = 0; - } - - if (!redec && !isredec(dsym, (warn = 0, &warn))) { - if (warn) { - /* redeclaration of %s */ - (*(sflag ? error : warning))(27, dsym->s_name); - prevdecl(-1, rdsym); - } - - /* - * Overtake the rememberd params if the new symbol - * is not a prototype. - */ - if (rdsym->s_osdef && !dsym->s_type->t_proto) { - dsym->s_osdef = rdsym->s_osdef; - dsym->s_args = rdsym->s_args; - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } - - /* - * Remember the position of the declaration if the - * old symbol was a prototype and the new is not. - * Also remember the position if the old symbol - * was defined and the new is not. - */ - if (rdsym->s_type->t_proto && !dsym->s_type->t_proto) { - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } else if (rdsym->s_def == DEF && dsym->s_def != DEF) { - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } - - /* - * Copy informations about usage of the name into - * the new symbol. - */ - cpuinfo(dsym, rdsym); - - /* Once a name is defined, it remains defined. */ - if (rdsym->s_def == DEF) - dsym->s_def = DEF; - - /* once a function is inline, it remains inline */ - if (rdsym->s_inline) - dsym->s_inline = 1; - - compltyp(dsym, rdsym); - - } - - rmsym(rdsym); - } - - if (dsym->s_scl == TYPEDEF) { - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_typedef = 1; - settdsym(dsym->s_type, dsym); - } - -} - -/* - * Copies informations about usage into a new symbol table entry of - * the same symbol. - */ -void -cpuinfo(sym_t *sym, sym_t *rdsym) -{ - sym->s_spos = rdsym->s_spos; - sym->s_upos = rdsym->s_upos; - sym->s_set = rdsym->s_set; - sym->s_used = rdsym->s_used; -} - -/* - * Prints an error and returns 1 if a symbol is redeclared/redefined. - * Otherwise returns 0 and, in some cases of minor problems, prints - * a warning. - */ -int -isredec(sym_t *dsym, int *warn) -{ - sym_t *rsym; - - if ((rsym = dcs->d_rdcsym)->s_scl == ENUMCON) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (rsym->s_scl == TYPEDEF) { - /* typedef redeclared: %s */ - error(89, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (dsym->s_scl == TYPEDEF) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (rsym->s_def == DEF && dsym->s_def == DEF) { - /* redefinition of %s */ - error(28, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (!eqtype(rsym->s_type, dsym->s_type, 0, 0, warn)) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (rsym->s_scl == EXTERN && dsym->s_scl == EXTERN) - return(0); - if (rsym->s_scl == STATIC && dsym->s_scl == STATIC) - return(0); - if (rsym->s_scl == STATIC && dsym->s_def == DECL) - return(0); - if (rsym->s_scl == EXTERN && rsym->s_def == DEF) { - /* - * All cases except "int a = 1; static int a;" are caught - * above with or without a warning - */ - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (rsym->s_scl == EXTERN) { - /* previously declared extern, becomes static: %s */ - warning(29, dsym->s_name); - prevdecl(-1, rsym); - return(0); - } - /* - * Now its on of: - * "static a; int a;", "static a; int a = 1;", "static a = 1; int a;" - */ - /* redeclaration of %s; ANSI C requires "static" */ - if (sflag) { - warning(30, dsym->s_name); - prevdecl(-1, rsym); - } - dsym->s_scl = STATIC; - return (0); -} - -/* - * Checks if two types are compatible. Returns 0 if not, otherwise 1. - * - * ignqual ignore qualifiers of type; used for function params - * promot promote left type; used for comparison of params of - * old style function definitions with params of prototypes. - * *warn set to 1 if an old style function declaration is not - * compatible with a prototype - */ -int -eqtype(type_t *tp1, type_t *tp2, int ignqual, int promot, int *warn) -{ - tspec_t t; - - while (tp1 != NULL && tp2 != NULL) { - t = tp1->t_tspec; - if (promot) { - if (t == FLOAT) { - t = DOUBLE; - } else if (t == BOOL) { - t = INT; - } else if (t == CHAR || t == SCHAR) { - t = INT; - } else if (t == UCHAR) { - t = INT; - } else if (t == SHORT) { - t = INT; - } else if (t == USHORT) { - /* CONSTCOND */ - t = INT_MAX < USHRT_MAX ? UINT : INT; - } else if (t == COMPLEX) { - t = DCOMPLEX; - } else if (t == IMAGINARY) { - t = DIMAGINARY; - } - } - - if (t != tp2->t_tspec) - return (0); - - if (tp1->t_const != tp2->t_const && !ignqual) - return (0); - - if (tp1->t_volatile != tp2->t_volatile && !ignqual) - return (0); - - if (tp1->t_restrict != tp2->t_restrict && !ignqual) - return (0); - - if (t == STRUCT || t == UNION) - return (tp1->t_str == tp2->t_str); - - if (t == ARRAY && tp1->t_dim != tp2->t_dim) { - if (tp1->t_dim != 0 && tp2->t_dim != 0) - return (0); - } - - /* dont check prototypes for traditional */ - if (t == FUNC) { - if (tp1->t_proto && tp2->t_proto) { - if (!eqargs(tp1, tp2, warn)) - return (0); - } else if (tp1->t_proto) { - if (!mnoarg(tp1, warn)) - return (0); - } else if (tp2->t_proto) { - if (!mnoarg(tp2, warn)) - return (0); - } - } - - tp1 = tp1->t_subt; - tp2 = tp2->t_subt; - ignqual = promot = 0; - - } - - return (tp1 == tp2); -} - -/* - * Compares the parameter types of two prototypes. - */ -static int -eqargs(type_t *tp1, type_t *tp2, int *warn) -{ - sym_t *a1, *a2; - - if (tp1->t_vararg != tp2->t_vararg) - return (0); - - a1 = tp1->t_args; - a2 = tp2->t_args; - - while (a1 != NULL && a2 != NULL) { - if (eqtype(a1->s_type, a2->s_type, 1, 0, warn) == 0) - return (0); - - a1 = a1->s_nxt; - a2 = a2->s_nxt; - - } - - return (a1 == a2); -} - -/* - * mnoarg() (matches functions with no argument type information) - * returns 1 if all parameters of a prototype are compatible with - * and old style function declaration. - * This is the case if following conditions are met: - * 1. the prototype must have a fixed number of parameters - * 2. no parameter is of type float - * 3. no parameter is converted to another type if integer promotion - * is applied on it - */ -static int -mnoarg(type_t *tp, int *warn) -{ - sym_t *arg; - tspec_t t; - - if (tp->t_vararg) { - if (warn != NULL) - *warn = 1; - } - for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) { - if ((t = arg->s_type->t_tspec) == FLOAT || t == BOOL || - t == CHAR || t == SCHAR || t == UCHAR || - t == SHORT || t == USHORT || t == COMPLEX || - t == DCOMPLEX || t == LDCOMPLEX || t == IMAGINARY || - t == DIMAGINARY || t == LDIMAGINARY) { - if (warn != NULL) - *warn = 1; - } - } - return (1); -} - -/* - * Compares a prototype declaration with the remembered arguments of - * a previous old style function definition. - */ -static int -chkosdef(sym_t *rdsym, sym_t *dsym) -{ - sym_t *args, *pargs, *arg, *parg; - int narg, nparg, n; - int warn, msg; - - args = rdsym->s_args; - pargs = dsym->s_type->t_args; - - msg = 0; - - narg = nparg = 0; - for (arg = args; arg != NULL; arg = arg->s_nxt) - narg++; - for (parg = pargs; parg != NULL; parg = parg->s_nxt) - nparg++; - if (narg != nparg) { - /* prototype does not match old-style definition */ - error(63); - msg = 1; - goto end; - } - - arg = args; - parg = pargs; - n = 1; - while (narg--) { - warn = 0; - /* - * If it does not match due to promotion and sflag is - * not set we print only a warning. - */ - if (!eqtype(arg->s_type, parg->s_type, 1, 1, &warn) || warn) { - /* prototype does not match old-style def., arg #%d */ - error(299, n); - msg = 1; - } - arg = arg->s_nxt; - parg = parg->s_nxt; - n++; - } - - end: - if (msg) - /* old style definition */ - prevdecl(300, rdsym); - - return (msg); -} - -/* - * Completes a type by copying the dimension and prototype information - * from a second compatible type. - * - * Following lines are legal: - * "typedef a[]; a b; a b[10]; a c; a c[20];" - * "typedef ft(); ft f; f(int); ft g; g(long);" - * This means that, if a type is completed, the type structure must - * be duplicated. - */ -void -compltyp(sym_t *dsym, sym_t *ssym) -{ - type_t **dstp, *src; - type_t *dst; - - dstp = &dsym->s_type; - src = ssym->s_type; - - while ((dst = *dstp) != NULL) { - if (src == NULL || dst->t_tspec != src->t_tspec) - lerror("compltyp() 1"); - if (dst->t_tspec == ARRAY) { - if (dst->t_dim == 0 && src->t_dim != 0) { - *dstp = dst = duptyp(dst); - dst->t_dim = src->t_dim; - /* now a complete type */ - setcompl(dst, 0); - } - } else if (dst->t_tspec == FUNC) { - if (!dst->t_proto && src->t_proto) { - *dstp = dst = duptyp(dst); - dst->t_proto = 1; - dst->t_args = src->t_args; - } - } - dstp = &dst->t_subt; - src = src->t_subt; - } -} - -/* - * Completes the declaration of a single argument. - */ -sym_t * -decl1arg(sym_t *sym, int initflg) -{ - tspec_t t; - - chkfdef(sym, 1); - - chktyp(sym); - - if (dcs->d_rdcsym != NULL && dcs->d_rdcsym->s_blklev == blklev) { - /* redeclaration of formal parameter %s */ - error(237, sym->s_name); - rmsym(dcs->d_rdcsym); - sym->s_arg = 1; - } - - if (!sym->s_arg) { - /* declared argument %s is missing */ - error(53, sym->s_name); - sym->s_arg = 1; - } - - if (initflg) { - /* cannot initialize parameter: %s */ - error(52, sym->s_name); - initerr = 1; - } - - if ((t = sym->s_type->t_tspec) == ARRAY) { - sym->s_type = incref(sym->s_type->t_subt, PTR); - } else if (t == FUNC) { - sym->s_type = incref(sym->s_type, PTR); - } - - if (dcs->d_inline) - /* argument declared inline: %s */ - warning(269, sym->s_name); - - /* - * Arguments must have complete types. lengths() prints the needed - * error messages (null dimension is impossible because arrays are - * converted to pointers). - */ - if (sym->s_type->t_tspec != VOID) - (void)length(sym->s_type, sym->s_name); - - setsflg(sym); - - return (sym); -} - -/* - * Does some checks for lint directives which apply to functions. - * Processes arguments in old style function definitions which default - * to int. - * Checks compatibility of old style function definition with previous - * prototype. - */ -void -cluparg(void) -{ - sym_t *args, *arg, *pargs, *parg; - int narg, nparg, n, msg; - tspec_t t; - - args = funcsym->s_args; - pargs = funcsym->s_type->t_args; - - /* check for illegal combinations of lint directives */ - if (prflstrg != -1 && scflstrg != -1) { - /* can't be used together: ** PRINTFLIKE ** ** SCANFLIKE ** */ - warning(289); - prflstrg = scflstrg = -1; - } - if (nvararg != -1 && (prflstrg != -1 || scflstrg != -1)) { - /* dubious use of ** VARARGS ** with ** %s ** */ - warning(288, prflstrg != -1 ? "PRINTFLIKE" : "SCANFLIKE"); - nvararg = -1; - } - - /* - * check if the argument of a lint directive is compatible with the - * number of arguments. - */ - narg = 0; - for (arg = dcs->d_fargs; arg != NULL; arg = arg->s_nxt) - narg++; - if (nargusg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "ARGSUSED"); - nargusg = 0; - } - if (nvararg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "VARARGS"); - nvararg = 0; - } - if (prflstrg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "PRINTFLIKE"); - prflstrg = -1; - } else if (prflstrg == 0) { - prflstrg = -1; - } - if (scflstrg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "SCANFLIKE"); - scflstrg = -1; - } else if (scflstrg == 0) { - scflstrg = -1; - } - if (prflstrg != -1 || scflstrg != -1) { - narg = prflstrg != -1 ? prflstrg : scflstrg; - arg = dcs->d_fargs; - for (n = 1; n < narg; n++) - arg = arg->s_nxt; - if (arg->s_type->t_tspec != PTR || - ((t = arg->s_type->t_subt->t_tspec) != CHAR && - t != UCHAR && t != SCHAR)) { - /* arg. %d must be 'char *' for PRINTFLIKE/SCANFLIKE */ - warning(293, narg); - prflstrg = scflstrg = -1; - } - } - - /* - * print a warning for each argument of an old style function - * definition which defaults to int - */ - for (arg = args; arg != NULL; arg = arg->s_nxt) { - if (arg->s_defarg) { - /* argument type defaults to int: %s */ - warning(32, arg->s_name); - arg->s_defarg = 0; - setsflg(arg); - } - } - - /* - * If this is an old style function definition and a prototype - * exists, compare the types of arguments. - */ - if (funcsym->s_osdef && funcsym->s_type->t_proto) { - /* - * If the number of arguments does not macht, we need not - * continue. - */ - narg = nparg = 0; - msg = 0; - for (parg = pargs; parg != NULL; parg = parg->s_nxt) - nparg++; - for (arg = args; arg != NULL; arg = arg->s_nxt) - narg++; - if (narg != nparg) { - /* parameter mismatch: %d declared, %d defined */ - error(51, nparg, narg); - msg = 1; - } else { - parg = pargs; - arg = args; - while (narg--) { - msg |= chkptdecl(arg, parg); - parg = parg->s_nxt; - arg = arg->s_nxt; - } - } - if (msg) - /* prototype declaration */ - prevdecl(285, dcs->d_rdcsym); - - /* from now the prototype is valid */ - funcsym->s_osdef = 0; - funcsym->s_args = NULL; - - } - -} - -/* - * Checks compatibility of an old style function definition with a previous - * prototype declaration. - * Returns 1 if the position of the previous declaration should be reported. - */ -static int -chkptdecl(sym_t *arg, sym_t *parg) -{ - type_t *tp, *ptp; - int warn, msg; - - tp = arg->s_type; - ptp = parg->s_type; - - msg = 0; - warn = 0; - - if (!eqtype(tp, ptp, 1, 1, &warn)) { - if (eqtype(tp, ptp, 1, 0, &warn)) { - /* type does not match prototype: %s */ - msg = gnuism(58, arg->s_name); - } else { - /* type does not match prototype: %s */ - error(58, arg->s_name); - msg = 1; - } - } else if (warn) { - /* type does not match prototype: %s */ - (*(sflag ? error : warning))(58, arg->s_name); - msg = 1; - } - - return (msg); -} - -/* - * Completes a single local declaration/definition. - */ -void -decl1loc(sym_t *dsym, int initflg) -{ - /* Correct a mistake done in dname(). */ - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_def = DECL; - if (dcs->d_scl == NOSCL) - dsym->s_scl = EXTERN; - } - - if (dsym->s_type->t_tspec == FUNC) { - if (dsym->s_scl == STATIC) { - /* dubious static function at block level: %s */ - warning(93, dsym->s_name); - dsym->s_scl = EXTERN; - } else if (dsym->s_scl != EXTERN && dsym->s_scl != TYPEDEF) { - /* function has illegal storage class: %s */ - error(94, dsym->s_name); - dsym->s_scl = EXTERN; - } - } - - /* - * functions may be declared inline at local scope, although - * this has no effect for a later definition of the same - * function. - */ - if (dcs->d_inline) { - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_inline = 1; - } else { - /* variable declared inline: %s */ - warning(268, dsym->s_name); - } - } - - chkfdef(dsym, 1); - - chktyp(dsym); - - if (dcs->d_rdcsym != NULL && dsym->s_scl == EXTERN) - ledecl(dsym); - - if (dsym->s_scl == EXTERN) { - /* - * XXX wenn die statische Variable auf Ebene 0 erst - * spaeter definiert wird, haben wir die Brille auf. - */ - if (dsym->s_xsym == NULL) { - outsym(dsym, EXTERN, dsym->s_def); - } else { - outsym(dsym, dsym->s_xsym->s_scl, dsym->s_def); - } - } - - if (dcs->d_rdcsym != NULL) { - if (dcs->d_rdcsym->s_blklev == 0) { - switch (dsym->s_scl) { - case AUTO: - /* automatic hides external declaration: %s */ - if (hflag) - warning(86, dsym->s_name); - break; - case STATIC: - /* static hides external declaration: %s */ - if (hflag) - warning(87, dsym->s_name); - break; - case TYPEDEF: - /* typedef hides external declaration: %s */ - if (hflag) - warning(88, dsym->s_name); - break; - case EXTERN: - /* - * Warnings and errors are printed in ledecl() - */ - break; - default: - lerror("decl1loc() 1"); - } - } else if (dcs->d_rdcsym->s_blklev == blklev) { - /* no hflag, because its illegal! */ - if (dcs->d_rdcsym->s_arg) { - /* - * a "redeclaration of %s" error - * is produced below - */ - } - - } else if (dcs->d_rdcsym->s_blklev < blklev) { - if (hflag) - /* declaration hides earlier one: %s */ - warning(95, dsym->s_name); - } - - if (dcs->d_rdcsym->s_blklev == blklev) { - /* redeclaration of %s */ - error(27, dsym->s_name); - rmsym(dcs->d_rdcsym); - } - } - - if (initflg && !(initerr = chkinit(dsym))) { - dsym->s_def = DEF; - setsflg(dsym); - } - - if (dsym->s_scl == TYPEDEF) { - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_typedef = 1; - settdsym(dsym->s_type, dsym); - } - - /* - * Before we can check the size we must wait for a initialisation - * which may follow. - */ -} - -/* - * Processes (re)declarations of external Symbols inside blocks. - */ -static void -ledecl(sym_t *dsym) -{ - int eqt, warn; - sym_t *esym; - - /* look for a symbol with the same name */ - esym = dcs->d_rdcsym; - while (esym != NULL && esym->s_blklev != 0) { - while ((esym = esym->s_link) != NULL) { - if (esym->s_kind != FVFT) - continue; - if (strcmp(dsym->s_name, esym->s_name) == 0) - break; - } - } - if (esym == NULL) - return; - if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { - /* gcc accepts this without a warning, pcc prints an error. */ - /* redeclaration of %s */ - warning(27, dsym->s_name); - prevdecl(-1, esym); - return; - } - - warn = 0; - eqt = eqtype(esym->s_type, dsym->s_type, 0, 0, &warn); - - if (!eqt || warn) { - if (esym->s_scl == EXTERN) { - /* inconsistent redeclaration of extern: %s */ - warning(90, dsym->s_name); - prevdecl(-1, esym); - } else { - /* inconsistent redeclaration of static: %s */ - warning(92, dsym->s_name); - prevdecl(-1, esym); - } - } - - if (eqt) { - /* - * Remember the external symbol so we can update usage - * information at the end of the block. - */ - dsym->s_xsym = esym; - } -} - -/* - * Print an error or a warning if the symbol can't be initialized due - * to type/storage class. Return value is 1 if an error has been - * detected. - */ -static int -chkinit(sym_t *sym) -{ - int err; - - err = 0; - - if (sym->s_type->t_tspec == FUNC) { - /* cannot initialize function: %s */ - error(24, sym->s_name); - err = 1; - } else if (sym->s_scl == TYPEDEF) { - /* cannot initialize typedef: %s */ - error(25, sym->s_name); - err = 1; - } else if (sym->s_scl == EXTERN && sym->s_def == DECL) { - /* cannot initialize "extern" declaration: %s */ - if (dcs->d_ctx == EXTERN) { - warning(26, sym->s_name); - } else { - error(26, sym->s_name); - err = 1; - } - } - - return (err); -} - -/* - * Create a symbole for an abstract declaration. - */ -sym_t * -aname(void) -{ - sym_t *sym; - - if (dcs->d_ctx != ABSTRACT && dcs->d_ctx != PARG) - lerror("aname()"); - - sym = getblk(sizeof (sym_t)); - - sym->s_name = unnamed; - sym->s_def = DEF; - sym->s_scl = ABSTRACT; - sym->s_blklev = -1; - - if (dcs->d_ctx == PARG) - sym->s_arg = 1; - - sym->s_type = dcs->d_type; - dcs->d_rdcsym = NULL; - dcs->d_vararg = 0; - - return (sym); -} - -/* - * Removes anything which has nothing to do on global level. - */ -void -globclup(void) -{ - while (dcs->d_nxt != NULL) - popdecl(); - - cleanup(); - blklev = 0; - mblklev = 0; - - /* - * remove all information about pending lint directives without - * warnings. - */ - glclup(1); -} - -/* - * Process an abstract type declaration - */ -sym_t * -decl1abs(sym_t *sym) -{ - chkfdef(sym, 1); - chktyp(sym); - return (sym); -} - -/* - * Checks size after declarations of variables and their initialisation. - */ -void -chksz(sym_t *dsym) -{ - /* - * check size only for symbols which are defined and no function and - * not typedef name - */ - if (dsym->s_def != DEF) - return; - if (dsym->s_scl == TYPEDEF) - return; - if (dsym->s_type->t_tspec == FUNC) - return; - - if (length(dsym->s_type, dsym->s_name) == 0 && - dsym->s_type->t_tspec == ARRAY && dsym->s_type->t_dim == 0) { - /* empty array declaration: %s */ - error(190, dsym->s_name); - } -} - -/* - * Mark an object as set if it is not already - */ -void -setsflg(sym_t *sym) -{ - if (!sym->s_set) { - sym->s_set = 1; - STRUCT_ASSIGN(sym->s_spos, curr_pos); - } -} - -/* - * Mark an object as used if it is not already - */ -void -setuflg(sym_t *sym, int fcall, int szof) -{ - if (!sym->s_used) { - sym->s_used = 1; - STRUCT_ASSIGN(sym->s_upos, curr_pos); - } - /* - * for function calls another record is written - * - * XXX Should symbols used in sizeof() treated as used or not? - * Probably not, because there is no sense to declare an - * external variable only to get their size. - */ - if (!fcall && !szof && sym->s_kind == FVFT && sym->s_scl == EXTERN) - outusg(sym); -} - -/* - * Prints warnings for a list of variables and labels (concatenated - * with s_dlnxt) if these are not used or only set. - */ -void -chkusage(dinfo_t *di) -{ - sym_t *sym; - int mknowarn; - - /* for this warnings LINTED has no effect */ - mknowarn = nowarn; - nowarn = 0; - - for (sym = di->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) - chkusg1(di->d_asm, sym); - - nowarn = mknowarn; -} - -/* - * Prints a warning for a single variable or label if it is not used or - * only set. - */ -void -chkusg1(int novar, sym_t *sym) -{ - pos_t cpos; - - if (sym->s_blklev == -1) - return; - - STRUCT_ASSIGN(cpos, curr_pos); - - if (sym->s_kind == FVFT) { - if (sym->s_arg) { - chkausg(novar, sym); - } else { - chkvusg(novar, sym); - } - } else if (sym->s_kind == FLAB) { - chklusg(sym); - } else if (sym->s_kind == FTAG) { - chktusg(sym); - } - - STRUCT_ASSIGN(curr_pos, cpos); -} - -static void -chkausg(int novar, sym_t *arg) -{ - if (!arg->s_set) - lerror("chkausg() 1"); - - if (novar) - return; - - if (!arg->s_used && vflag) { - STRUCT_ASSIGN(curr_pos, arg->s_dpos); - /* argument %s unused in function %s */ - warning(231, arg->s_name, funcsym->s_name); - } -} - -static void -chkvusg(int novar, sym_t *sym) -{ - scl_t sc; - sym_t *xsym; - - if (blklev == 0 || sym->s_blklev == 0) - lerror("chkvusg() 1"); - - /* errors in expressions easily cause lots of these warnings */ - if (nerr != 0) - return; - - /* - * XXX Only variables are checkd, although types should - * probably also be checked - */ - if ((sc = sym->s_scl) != EXTERN && sc != STATIC && - sc != AUTO && sc != REG) { - return; - } - - if (novar) - return; - - if (sc == EXTERN) { - if (!sym->s_used && !sym->s_set) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* %s unused in function %s */ - warning(192, sym->s_name, funcsym->s_name); - } - } else { - if (sym->s_set && !sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_spos); - /* %s set but not used in function %s */ - warning(191, sym->s_name, funcsym->s_name); - } else if (!sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* %s unused in function %s */ - warning(192, sym->s_name, funcsym->s_name); - } - } - - if (sc == EXTERN) { - /* - * information about usage is taken over into the symbol - * tabel entry at level 0 if the symbol was locally declared - * as an external symbol. - * - * XXX This is wrong for symbols declared static at level 0 - * if the usage information stems from sizeof(). This is - * because symbols at level 0 only used in sizeof() are - * considered to not be used. - */ - if ((xsym = sym->s_xsym) != NULL) { - if (sym->s_used && !xsym->s_used) { - xsym->s_used = 1; - STRUCT_ASSIGN(xsym->s_upos, sym->s_upos); - } - if (sym->s_set && !xsym->s_set) { - xsym->s_set = 1; - STRUCT_ASSIGN(xsym->s_spos, sym->s_spos); - } - } - } -} - -static void -chklusg(sym_t *lab) -{ - if (blklev != 1 || lab->s_blklev != 1) - lerror("chklusg() 1"); - - if (lab->s_set && !lab->s_used) { - STRUCT_ASSIGN(curr_pos, lab->s_spos); - /* label %s unused in function %s */ - warning(192, lab->s_name, funcsym->s_name); - } else if (!lab->s_set) { - STRUCT_ASSIGN(curr_pos, lab->s_upos); - /* undefined label %s */ - warning(23, lab->s_name); - } -} - -static void -chktusg(sym_t *sym) -{ - if (!incompl(sym->s_type)) - return; - - /* complain always about incomplete tags declared inside blocks */ - if (!zflag || dcs->d_ctx != EXTERN) - return; - - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - switch (sym->s_type->t_tspec) { - case STRUCT: - /* struct %s never defined */ - warning(233, sym->s_name); - break; - case UNION: - /* union %s never defined */ - warning(234, sym->s_name); - break; - case ENUM: - /* enum %s never defined */ - warning(235, sym->s_name); - break; - default: - lerror("chktusg() 1"); - } -} - -/* - * Called after the entire translation unit has been parsed. - * Changes tentative definitions in definitions. - * Performs some tests on global Symbols. Detected Problems are: - * - defined variables of incomplete type - * - constant variables which are not initialized - * - static symbols which are never used - */ -void -chkglsyms(void) -{ - sym_t *sym; - pos_t cpos; - - if (blklev != 0 || dcs->d_nxt != NULL) - norecover(); - - STRUCT_ASSIGN(cpos, curr_pos); - - for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { - if (sym->s_blklev == -1) - continue; - if (sym->s_kind == FVFT) { - chkglvar(sym); - } else if (sym->s_kind == FTAG) { - chktusg(sym); - } else { - if (sym->s_kind != FMOS) - lerror("chkglsyms() 1"); - } - } - - STRUCT_ASSIGN(curr_pos, cpos); -} - -static void -chkglvar(sym_t *sym) -{ - if (sym->s_scl == TYPEDEF || sym->s_scl == ENUMCON) - return; - - if (sym->s_scl != EXTERN && sym->s_scl != STATIC) - lerror("chkglvar() 1"); - - glchksz(sym); - - if (sym->s_scl == STATIC) { - if (sym->s_type->t_tspec == FUNC) { - if (sym->s_used && sym->s_def != DEF) { - STRUCT_ASSIGN(curr_pos, sym->s_upos); - /* static func. called but not def.. */ - error(225, sym->s_name); - } - } - if (!sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - if (sym->s_type->t_tspec == FUNC) { - if (sym->s_def == DEF) { - if (!sym->s_inline) - /* static function %s unused */ - warning(236, sym->s_name); - } else { - /* static function %s decl. but ... */ - warning(290, sym->s_name); - } - } else if (!sym->s_set) { - /* static variable %s unused */ - warning(226, sym->s_name); - } else { - /* static variable %s set but not used */ - warning(307, sym->s_name); - } - } - if (sym->s_def == TDEF && sym->s_type->t_const) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* const object %s should have initializer */ - warning(227, sym->s_name); - } - } -} - -static void -glchksz(sym_t *sym) -{ - if (sym->s_def == TDEF) { - if (sym->s_type->t_tspec == FUNC) - /* - * this can happen if a syntax error occurred - * after a function declaration - */ - return; - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - if (length(sym->s_type, sym->s_name) == 0 && - sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { - /* empty array declaration: %s */ - if (sym->s_scl == EXTERN && !sflag) { - warning(190, sym->s_name); - } else { - error(190, sym->s_name); - } - } - } -} - -/* - * Prints information about location of previous definition/declaration. - */ -void -prevdecl(int msg, sym_t *psym) -{ - pos_t cpos; - - if (!rflag) - return; - - STRUCT_ASSIGN(cpos, curr_pos); - STRUCT_ASSIGN(curr_pos, psym->s_dpos); - if (msg != -1) { - message(msg, psym->s_name); - } else if (psym->s_def == DEF || psym->s_def == TDEF) { - /* previous definition of %s */ - message(261, psym->s_name); - } else { - /* previous declaration of %s */ - message(260, psym->s_name); - } - STRUCT_ASSIGN(curr_pos, cpos); -} diff --git a/usr.bin/xlint/lint1/emit.c b/usr.bin/xlint/lint1/emit.c deleted file mode 100644 index 379d344e826..00000000000 --- a/usr.bin/xlint/lint1/emit.c +++ /dev/null @@ -1,224 +0,0 @@ -/* $OpenBSD: emit.c,v 1.10 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: emit.c,v 1.2 1995/07/03 21:24:00 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <err.h> - -#include "lint.h" - -/* name and handle of output file */ -static const char *loname; -static FILE *lout; - -/* output buffer data */ -ob_t ob; - -static void outxbuf(void); - - -/* - * initialize output - */ -void -outopen(const char *name) -{ - loname = name; - - /* open output file */ - if ((lout = fopen(name, "w")) == NULL) - err(1, "cannot open '%s'", name); - - /* generate output buffer */ - ob.o_len = 1024; - ob.o_end = (ob.o_buf = ob.o_nxt = xmalloc(ob.o_len)) + ob.o_len; -} - -/* - * flush output buffer and close file - */ -void -outclose(void) -{ - outclr(); - if (fclose(lout) == EOF) - err(1, "cannot close '%s'", loname); -} - -/* - * resize output buffer - */ -static void -outxbuf(void) -{ - ptrdiff_t coffs; - - coffs = ob.o_nxt - ob.o_buf; - ob.o_len *= 2; - ob.o_end = (ob.o_buf = xrealloc(ob.o_buf, ob.o_len)) + ob.o_len; - ob.o_nxt = ob.o_buf + coffs; -} - -/* - * reset output buffer - * if it is not empty, it is flushed - */ -void -outclr(void) -{ - size_t sz; - - if (ob.o_buf != ob.o_nxt) { - outchar('\n'); - sz = ob.o_nxt - ob.o_buf; - if (sz > ob.o_len) - errx(1, "internal error: outclr() 1"); - if (fwrite(ob.o_buf, sz, 1, lout) != 1) - err(1, "cannot write to %s", loname); - ob.o_nxt = ob.o_buf; - } -} - -/* - * write a character to the output buffer - */ -void -outchar(int c) -{ - if (ob.o_nxt == ob.o_end) - outxbuf(); - *ob.o_nxt++ = (char)c; -} - -/* - * write a character to the output buffer, qouted if necessary - */ -void -outqchar(int c) -{ - if (isprint(c) && c != '\\' && c != '"' && c != '\'') { - outchar(c); - } else { - outchar('\\'); - switch (c) { - case '\\': - outchar('\\'); - break; - case '"': - outchar('"'); - break; - case '\'': - outchar('\''); - break; - case '\b': - outchar('b'); - break; - case '\t': - outchar('t'); - break; - case '\n': - outchar('n'); - break; - case '\f': - outchar('f'); - break; - case '\r': - outchar('r'); - break; - case '\v': - outchar('v'); - break; - case '\a': - outchar('a'); - break; - default: - outchar((((u_int)c >> 6) & 07) + '0'); - outchar((((u_int)c >> 3) & 07) + '0'); - outchar((c & 07) + '0'); - break; - } - } -} - -/* - * write a strint to the output buffer - * the string must not contain any characters which - * should be quoted - */ -void -outstrg(const char *s) -{ - while (*s != '\0') { - if (ob.o_nxt == ob.o_end) - outxbuf(); - *ob.o_nxt++ = *s++; - } -} - -/* - * write an integer value to toe output buffer - */ -void -outint(int i) -{ - if ((ob.o_end - ob.o_nxt) < 12) - outxbuf(); - snprintf(ob.o_nxt, ob.o_end - ob.o_nxt, "%d", i); - ob.o_nxt += strlen(ob.o_nxt); -} - -/* - * write the name of a symbol to the output buffer - * the name is preceded by its length - */ -void -outname(const char *name) -{ - if (name == NULL) - errx(1, "internal error: outname() 1"); - outint((int)strlen(name)); - outstrg(name); -} - -/* - * write the name of the .c source - */ -void -outsrc(const char *name) -{ - outclr(); - outchar('S'); - outstrg(name); -} diff --git a/usr.bin/xlint/lint1/emit1.c b/usr.bin/xlint/lint1/emit1.c deleted file mode 100644 index 28f962cd549..00000000000 --- a/usr.bin/xlint/lint1/emit1.c +++ /dev/null @@ -1,589 +0,0 @@ -/* $OpenBSD: emit1.c,v 1.9 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: emit1.c,v 1.4 1995/10/02 17:21:28 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <ctype.h> - -#include "lint1.h" - -static void outtt(sym_t *, sym_t *); -static void outfstrg(strg_t *); - -/* - * Write type into the output buffer. - * The type is written as a sequence of substrings, each of which describes a - * node of type type_t - * a node is coded as follows: - * _Bool B - * char C - * signed char s C - * unsigned char u C - * short S - * unsigned short u S - * int I - * unsigned int u I - * long L - * unsigned long u L - * long long Q - * unsigned long long u Q - * float s D - * double D - * long double l D - * float _Complex s X - * double _Complex X - * long double _Complex l X - * float _Imaginary s J - * double _Imaginary J - * long double _Imaginary l J - * void V - * * P - * [n] A n - * () F - * (void) F 0 - * (n arguments) F n arg1 arg2 ... argn - * (n arguments, ...) F n arg1 arg2 ... argn-1 E - * (a, b, c, ...) f n arg1 arg2 ... - * enum tag e T tag_or_typename - * struct tag s T tag_or_typename - * union tag u T tag_or_typename - * - * tag_or_typename 0 no tag or type name - * 1 n tag Tag - * 2 n typename only type name - * - * spaces are only for better readability - * additionaly it is possible to prepend the characters 'c' (for const) - * and 'v' (for volatile) - */ -void -outtype(type_t *tp) -{ - int t, s, na; - sym_t *arg; - tspec_t ts; - - while (tp != NULL) { - if ((ts = tp->t_tspec) == INT && tp->t_isenum) - ts = ENUM; - switch (ts) { - case BOOL: t = 'B'; s = '\0'; break; - case CHAR: t = 'C'; s = '\0'; break; - case SCHAR: t = 'C'; s = 's'; break; - case UCHAR: t = 'C'; s = 'u'; break; - case SHORT: t = 'S'; s = '\0'; break; - case USHORT: t = 'S'; s = 'u'; break; - case INT: t = 'I'; s = '\0'; break; - case UINT: t = 'I'; s = 'u'; break; - case LONG: t = 'L'; s = '\0'; break; - case ULONG: t = 'L'; s = 'u'; break; - case QUAD: t = 'Q'; s = '\0'; break; - case UQUAD: t = 'Q'; s = 'u'; break; - case FLOAT: t = 'D'; s = 's'; break; - case DOUBLE: t = 'D'; s = '\0'; break; - case LDOUBLE: t = 'D'; s = 'l'; break; - case COMPLEX: t = 'X'; s = 's'; break; - case DCOMPLEX: t = 'X'; s = '\0'; break; - case LDCOMPLEX: t = 'X'; s = 'l'; break; - case IMAGINARY: t = 'J'; s = 's'; break; - case DIMAGINARY: t = 'J'; s = '\0'; break; - case LDIMAGINARY:t = 'J'; s = 'l'; break; - case VOID: t = 'V'; s = '\0'; break; - case PTR: t = 'P'; s = '\0'; break; - case ARRAY: t = 'A'; s = '\0'; break; - case FUNC: t = 'F'; s = '\0'; break; - case ENUM: t = 'T'; s = 'e'; break; - case STRUCT: t = 'T'; s = 's'; break; - case UNION: t = 'T'; s = 'u'; break; - default: - lerror("outtyp() 1"); - } - if (tp->t_const) - outchar('c'); - if (tp->t_volatile) - outchar('v'); - if (s != '\0') - outchar(s); - outchar(t); - if (ts == ARRAY) { - outint(tp->t_dim); - } else if (ts == ENUM) { - outtt(tp->t_enum->etag, tp->t_enum->etdef); - } else if (ts == STRUCT || ts == UNION) { - outtt(tp->t_str->stag, tp->t_str->stdef); - } else if (ts == FUNC && tp->t_proto) { - na = 0; - for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) - na++; - if (tp->t_vararg) - na++; - outint(na); - for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) - outtype(arg->s_type); - if (tp->t_vararg) - outchar('E'); - } - tp = tp->t_subt; - } -} - -/* - * type to string - * used for debugging output - * - * it uses its own output buffer for conversion - */ -const char * -ttos(type_t *tp) -{ - static ob_t tob; - ob_t tmp; - - if (tob.o_buf == NULL) { - tob.o_len = 64; - tob.o_buf = tob.o_nxt = xmalloc(tob.o_len); - tob.o_end = tob.o_buf + tob.o_len; - } - - tmp = ob; - ob = tob; - ob.o_nxt = ob.o_buf; - outtype(tp); - outchar('\0'); - tob = ob; - ob = tmp; - - return (tob.o_buf); -} - -/* - * write the name of a tag or typename - * - * if the tag is named, the name of the - * tag is written, otherwise, if a typename exists which - * refers to this tag, this typename is written - */ -static void -outtt(sym_t *tag, sym_t *tdef) -{ - if (tag->s_name != unnamed) { - outint(1); - outname(tag->s_name); - } else if (tdef != NULL) { - outint(2); - outname(tdef->s_name); - } else { - outint(0); - } -} - -/* - * write information about an global declared/defined symbol - * with storage class extern - * - * informations about function definitions are written in outfdef(), - * not here - */ -void -outsym(sym_t *sym, scl_t sc, def_t def) -{ - /* - * Static function declarations must also be written to the output - * file. Compatibility of function declarations (for both static - * and extern functions) must be checked in lint2. Lint1 can't do - * this, especially not, if functions are declared at block level - * before their first declaration at level 0. - */ - if (sc != EXTERN && !(sc == STATIC && sym->s_type->t_tspec == FUNC)) - return; - - /* reset buffer */ - outclr(); - - /* - * line number of .c source, 'd' for declaration, Id of current - * source (.c or .h), and line in current source. - */ - outint(csrc_pos.p_line); - outchar('d'); - outint(getfnid(sym->s_dpos.p_file)); - outchar('.'); - outint(sym->s_dpos.p_line); - - /* flags */ - - switch (def) { - case DEF: - /* defined */ - outchar('d'); - break; - case TDEF: - /* tentative defined */ - outchar('t'); - break; - case DECL: - /* declared */ - outchar('e'); - break; - default: - lerror("outsym() 2"); - } - if (llibflg && def != DECL) { - /* - * mark it as used so we get no warnings from lint2 about - * unused symbols in libraries. - */ - outchar('u'); - } - - if (sc == STATIC) - outchar('s'); - - /* name of the symbol */ - outname(sym->s_name); - - /* type of the symbol */ - outtype(sym->s_type); -} - -/* - * write information about function definition - * - * this is also done for static functions so we are able to check if - * they are called with proper argument types - */ -void -outfdef(sym_t *fsym, pos_t *posp, int rval, int osdef, sym_t *args) -{ - int narg; - sym_t *arg; - - /* reset the buffer */ - outclr(); - - /* - * line number of .c source, 'd' for declaration, Id of current - * source (.c or .h), and line in current source - * - * we are already at the end of the function. If we are in the - * .c source, posp->p_line is correct, otherwise csrc_pos.p_line - * (for functions defined in header files). - */ - if (posp->p_file == csrc_pos.p_file) { - outint(posp->p_line); - } else { - outint(csrc_pos.p_line); - } - outchar('d'); - outint(getfnid(posp->p_file)); - outchar('.'); - outint(posp->p_line); - - /* flags */ - - /* both SCANFLIKE and PRINTFLIKE imply VARARGS */ - if (prflstrg != -1) { - nvararg = prflstrg; - } else if (scflstrg != -1) { - nvararg = scflstrg; - } - - if (nvararg != -1) { - outchar('v'); - outint(nvararg); - } - if (scflstrg != -1) { - outchar('S'); - outint(scflstrg); - } - if (prflstrg != -1) { - outchar('P'); - outint(prflstrg); - } - nvararg = prflstrg = scflstrg = -1; - - outchar('d'); - - if (rval) - /* has return value */ - outchar('r'); - - if (llibflg) - /* - * mark it as used so lint2 does not complain about - * unused symbols in libraries - */ - outchar('u'); - - if (osdef) - /* old style function definition */ - outchar('o'); - - if (fsym->s_scl == STATIC) - outchar('s'); - - /* name of function */ - outname(fsym->s_name); - - /* argument types and return value */ - if (osdef) { - narg = 0; - for (arg = args; arg != NULL; arg = arg->s_nxt) - narg++; - outchar('f'); - outint(narg); - for (arg = args; arg != NULL; arg = arg->s_nxt) - outtype(arg->s_type); - outtype(fsym->s_type->t_subt); - } else { - outtype(fsym->s_type); - } -} - -/* - * write out all information necessary for lint2 to check function - * calls - * - * rvused is set if the return value is used (asigned to a variable) - * rvdisc is set if the return value is not used and not ignored - * (casted to void) - */ -void -outcall(tnode_t *tn, int rvused, int rvdisc) -{ - tnode_t *args, *arg; - int narg, n, i; - quad_t q; - tspec_t t; - - /* reset buffer */ - outclr(); - - /* - * line number of .c source, 'c' for function call, Id of current - * source (.c or .h), and line in current source - */ - outint(csrc_pos.p_line); - outchar('c'); - outint(getfnid(curr_pos.p_file)); - outchar('.'); - outint(curr_pos.p_line); - - /* - * flags; 'u' and 'i' must be last to make sure a letter - * is between the numeric argument of a flag and the name of - * the function - */ - narg = 0; - args = tn->tn_right; - for (arg = args; arg != NULL; arg = arg->tn_right) - narg++; - /* informations about arguments */ - for (n = 1; n <= narg; n++) { - /* the last argument is the top one in the tree */ - for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ; - arg = arg->tn_left; - if (arg->tn_op == CON) { - if (isityp(t = arg->tn_type->t_tspec)) { - /* - * XXX it would probably be better to - * explicitly test the sign - */ - if ((q = arg->tn_val->v_quad) == 0) { - /* zero constant */ - outchar('z'); - } else if (msb(q, t, 0) == 0) { - /* positive if casted to signed */ - outchar('p'); - } else { - /* negative if casted to signed */ - outchar('n'); - } - outint(n); - } - } else { - if (arg->tn_op == CVT && !arg->tn_cast) - arg = arg->tn_left; - if (arg->tn_op == AMPER && - arg->tn_left->tn_op == STRING && - arg->tn_left->tn_strg->st_tspec == CHAR) { - /* constant string, write format specifiers */ - outchar('s'); - outint(n); - outfstrg(arg->tn_left->tn_strg); - } - } - - } - /* return value discarded/used/ignored */ - outchar(rvdisc ? 'd' : (rvused ? 'u' : 'i')); - - /* name of the called function */ - outname(tn->tn_left->tn_left->tn_sym->s_name); - - /* types of arguments */ - outchar('f'); - outint(narg); - for (n = 1; n <= narg; n++) { - /* the last argument is the top one in the tree */ - for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ; - outtype(arg->tn_left->tn_type); - } - /* expected type of return value */ - outtype(tn->tn_type); -} - -/* - * extracts potential format specifiers for printf() and scanf() and - * writes them, enclosed in "" and quoted if necessary, to the output buffer - */ -static void -outfstrg(strg_t *strg) -{ - int c, oc, first; - u_char *cp; - - if (strg->st_tspec != CHAR) - lerror("outfstrg() 1"); - - cp = strg->st_cp; - - outchar('"'); - - c = *cp++; - - while (c != '\0') { - - if (c != '%') { - c = *cp++; - continue; - } - - outqchar('%'); - c = *cp++; - - /* flags for printf and scanf and *-fieldwidth for printf */ - while (c != '\0' && (c == '-' || c == '+' || c == ' ' || - c == '#' || c == '0' || c == '*')) { - outqchar(c); - c = *cp++; - } - - /* numeric field width */ - while (isdigit(c)) { - outqchar(c); - c = *cp++; - } - - /* precision for printf */ - if (c == '.') { - outqchar(c); - if ((c = *cp++) == '*') { - outqchar(c); - c = *cp++; - } else { - while (isdigit(c)) { - outqchar(c); - c = *cp++; - } - } - } - - /* h, l, L and q flags fpr printf and scanf */ - if (c == 'h' || c == 'l' || c == 'L' || c == 'q') { - outqchar(c); - c = *cp++; - } - - /* - * The last character. It is always written so we can detect - * invalid format specifiers. - */ - if (c != '\0') { - outqchar(c); - oc = c; - c = *cp++; - /* - * handle [ for scanf. [-] means that a minus sign - * was found at an undefined position. - */ - if (oc == '[') { - if (c == '^') - c = *cp++; - if (c == ']') - c = *cp++; - first = 1; - while (c != '\0' && c != ']') { - if (c == '-') { - if (!first && *cp != ']') - outqchar(c); - } - first = 0; - c = *cp++; - } - if (c == ']') { - outqchar(c); - c = *cp++; - } - } - } - - } - - outchar('"'); -} - -/* - * writes a record if sym was used - */ -void -outusg(sym_t *sym) -{ - /* reset buffer */ - outclr(); - - /* - * line number of .c source, 'u' for used, Id of current - * source (.c or .h), and line in current source - */ - outint(csrc_pos.p_line); - outchar('u'); - outint(getfnid(curr_pos.p_file)); - outchar('.'); - outint(curr_pos.p_line); - - /* necessary to delimit both numbers */ - outchar('x'); - - /* Den Namen des Symbols ausgeben */ - outname(sym->s_name); -} diff --git a/usr.bin/xlint/lint1/err.c b/usr.bin/xlint/lint1/err.c deleted file mode 100644 index 98c6b59d204..00000000000 --- a/usr.bin/xlint/lint1/err.c +++ /dev/null @@ -1,547 +0,0 @@ -/* $OpenBSD: err.c,v 1.28 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: err.c,v 1.8 1995/10/02 17:37:00 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* number of errors found */ -int nerr; - -/* number of syntax errors */ -int sytxerr; - -#include <stdlib.h> -#include <stdarg.h> -#include <err.h> - -#include "lint1.h" - -static const char *lbasename(const char *); -static void verror(int, va_list); -static void vwarning(int, va_list); -static void excerpt(pos_t *); - -const char *msgs[] = { - "syntax error: empty declaration", /* 0 */ - "old style declaration; add int", /* 1 */ - "empty declaration", /* 2 */ - "%s declared in argument declaration list", /* 3 */ - "illegal type combination", /* 4 */ - "modifying typedef with '%s'; only qualifiers allowed", /* 5 */ - "use 'double' instead of 'long float'", /* 6 */ - "only one storage class allowed", /* 7 */ - "illegal storage class", /* 8 */ - "only register valid as formal parameter storage class", /* 9 */ - "duplicate '%s'", /* 10 */ - "bit-field initializer out of range", /* 11 */ - "compiler takes size of function", /* 12 */ - "incomplete enum type: %s", /* 13 */ - "compiler takes alignment of function", /* 14 */ - "function returns illegal type", /* 15 */ - "array of function is illegal", /* 16 */ - "null dimension", /* 17 */ - "illegal use of 'void'", /* 18 */ - "void type for %s", /* 19 */ - "zero or negative array dimension", /* 20 */ - "redeclaration of formal parameter %s", /* 21 */ - "incomplete or misplaced function definition", /* 22 */ - "undefined label %s", /* 23 */ - "cannot initialize function: %s", /* 24 */ - "cannot initialize typedef: %s", /* 25 */ - "cannot initialize extern declaration: %s", /* 26 */ - "redeclaration of %s", /* 27 */ - "redefinition of %s", /* 28 */ - "previously declared extern, becomes static: %s", /* 29 */ - "redeclaration of %s; ANSI C requires static", /* 30 */ - "incomplete structure or union %s: %s", /* 31 */ - "argument type defaults to 'int': %s", /* 32 */ - "duplicate member name: %s", /* 33 */ - "nonportable bit-field type", /* 34 */ - "illegal bit-field type", /* 35 */ - "illegal bit-field size", /* 36 */ - "zero size bit-field", /* 37 */ - "function illegal in structure or union", /* 38 */ - "illegal zero sized structure member: %s", /* 39 */ - "unknown size: %s", /* 40 */ - "illegal use of bit-field", /* 41 */ - "forward reference to enum type", /* 42 */ - "redefinition hides earlier one: %s", /* 43 */ - "declaration introduces new type in ANSI C: %s %s", /* 44 */ - "base type is really '%s %s'", /* 45 */ - "(%s) tag redeclared", /* 46 */ - "zero sized %s", /* 47 */ - "overflow in enumeration values: %s", /* 48 */ - "struct or union member must be named", /* 49 */ - "a function is declared as an argument: %s", /* 50 */ - "parameter mismatch: %d declared, %d defined", /* 51 */ - "cannot initialize parameter: %s", /* 52 */ - "declared argument %s is missing", /* 53 */ - "trailing ',' prohibited in enum declaration", /* 54 */ - "integral constant expression expected", /* 55 */ - "integral constant too large", /* 56 */ - "enumeration constant hides parameter: %s", /* 57 */ - "type does not match prototype: %s", /* 58 */ - "formal parameter lacks name: param #%d", /* 59 */ - "void must be sole parameter", /* 60 */ - "void parameter cannot have name: %s", /* 61 */ - "function prototype parameters must have types", /* 62 */ - "prototype does not match old-style definition", /* 63 */ - "()-less function definition", /* 64 */ - "%s has no named members", /* 65 */ - "syntax requires ';' after last struct/union member", /* 66 */ - "cannot return incomplete type", /* 67 */ - "typedef already qualified with '%s'", /* 68 */ - "inappropriate qualifiers with 'void'", /* 69 */ - "%soperand of '%s' is unsigned in ANSI C", /* 70 */ - "too many characters in character constant", /* 71 */ - "typedef declares no type name", /* 72 */ - "empty character constant", /* 73 */ - "no hex digits follow \\x", /* 74 */ - "overflow in hex escape", /* 75 */ - "character escape does not fit in character", /* 76 */ - "bad octal digit %c", /* 77 */ - "nonportable character escape", /* 78 */ - "dubious escape \\%c", /* 79 */ - "dubious escape \\%o", /* 80 */ - "\\a undefined in traditional C", /* 81 */ - "\\x undefined in traditional C", /* 82 */ - "storage class after type is obsolescent", /* 83 */ - "ANSI C requires formal parameter before '...'", /* 84 */ - "dubious tag declaration: %s %s", /* 85 */ - "automatic hides external declaration: %s", /* 86 */ - "static hides external declaration: %s", /* 87 */ - "typedef hides external declaration: %s", /* 88 */ - "typedef redeclared: %s", /* 89 */ - "inconsistent redeclaration of extern: %s", /* 90 */ - "declaration hides parameter: %s", /* 91 */ - "inconsistent redeclaration of static: %s", /* 92 */ - "dubious static function at block level: %s", /* 93 */ - "function has illegal storage class: %s", /* 94 */ - "declaration hides earlier one: %s", /* 95 */ - "cannot dereference non-pointer type", /* 96 */ - "suffix U is illegal in traditional C", /* 97 */ - "suffixes F and L are illegal in traditional C", /* 98 */ - "%s undefined", /* 99 */ - "unary + is illegal in traditional C", /* 100 */ - "undefined struct/union member: %s", /* 101 */ - "illegal member use: %s", /* 102 */ - "left operand of '.' must be struct/union object", /* 103 */ - "left operand of '->' must be pointer to struct/union", /* 104 */ - "non-unique member requires struct/union %s", /* 105 */ - "left operand of '->' must be pointer", /* 106 */ - "operands of '%s' have incompatible types", /* 107 */ - "operand of '%s' has incompatible type", /* 108 */ - "void type illegal in expression", /* 109 */ - "pointer to function is not allowed here", /* 110 */ - "unacceptable operand of '%s'", /* 111 */ - "cannot take address of bit-field", /* 112 */ - "cannot take address of register %s", /* 113 */ - "%soperand of '%s' must be lvalue", /* 114 */ - "%soperand of '%s' must be modifiable lvalue", /* 115 */ - "illegal pointer subtraction", /* 116 */ - "bitwise operation on signed value possibly nonportable", /* 117 */ - "semantics of '%s' change in ANSI C; use explicit cast", /* 118 */ - "conversion of '%s' to '%s' is out of range", /* 119 */ - "bitwise operation on signed value nonportable", /* 120 */ - "negative shift", /* 121 */ - "shift greater than size of object", /* 122 */ - "illegal combination of pointer and integer, op %s", /* 123 */ - "illegal pointer combination, op %s", /* 124 */ - "ANSI C forbids ordered comparisons of pointers to functions",/* 125 */ - "incompatible types in conditional", /* 126 */ - "'&' before array or function: ignored", /* 127 */ - "operands have incompatible pointer types, op %s", /* 128 */ - "expression has null effect", /* 129 */ - "enum type mismatch, op %s", /* 130 */ - "conversion from '%s' to '%s' may sign-extend incorrectly", /* 131 */ - "converted from '%s' to '%s'", /* 132 */ - "conversion of pointer to '%s' loses bits", /* 133 */ - "conversion of pointer to '%s' may lose bits", /* 134 */ - "possible pointer alignment problem", /* 135 */ - "cannot do pointer arithmetic on operand of unknown size", /* 136 */ - "use of incomplete enum type, op %s", /* 137 */ - "unknown operand size, op %s", /* 138 */ - "division by 0", /* 139 */ - "modulus by 0", /* 140 */ - "integer overflow detected, op %s", /* 141 */ - "floating point overflow detected, op %s", /* 142 */ - "cannot take size of incomplete type", /* 143 */ - "cannot take size of function", /* 144 */ - "cannot take size of bit-field", /* 145 */ - "cannot take size of void", /* 146 */ - "invalid cast expression", /* 147 */ - "improper cast of void expression", /* 148 */ - "illegal function", /* 149 */ - "argument mismatch: %d arg%s passed, %d expected", /* 150 */ - "void expressions may not be arguments, arg #%d", /* 151 */ - "argument cannot have unknown size, arg #%d", /* 152 */ - "%s() arg #%d: incompatible pointer type", /* 153 */ - "%s() arg #%d: illegal combination of pointer and integer", /* 154 */ - "%s() arg #%d: argument is incompatible with prototype", /* 155 */ - "%s() arg #%d: enum type mismatch", /* 156 */ - "ANSI C treats constant as unsigned", /* 157 */ - "%s may be used before set", /* 158 */ - "assignment in conditional context", /* 159 */ - "operator '==' found where '=' was expected", /* 160 */ - "constant in conditional context", /* 161 */ - "comparison of %s with %s, op %s", /* 162 */ - "a cast does not yield an lvalue", /* 163 */ - "assignment of negative constant to unsigned type", /* 164 */ - "constant truncated by assignment", /* 165 */ - "precision lost in bit-field assignment", /* 166 */ - "array subscript cannot be negative: %ld", /* 167 */ - "array subscript cannot be > %d: %ld", /* 168 */ - "precedence confusion possible: parenthesize!", /* 169 */ - "first operand must have scalar type, op ? :", /* 170 */ - "assignment type mismatch", /* 171 */ - "too many struct/union initializers", /* 172 */ - "too many array initializers", /* 173 */ - "too many initializers", /* 174 */ - "initialisation of an incomplete type", /* 175 */ - "invalid initializer", /* 176 */ - "non-constant initializer", /* 177 */ - "initializer does not fit", /* 178 */ - "cannot initialize struct/union with no named member", /* 179 */ - "bit-field initializer does not fit", /* 180 */ - "{}-enclosed initializer required", /* 181 */ - "incompatible pointer types", /* 182 */ - "illegal combination of pointer and integer", /* 183 */ - "illegal pointer combination", /* 184 */ - "initialisation type mismatch", /* 185 */ - "bit-field initialisation is illegal in traditional C", /* 186 */ - "non-null byte ignored in string initializer", /* 187 */ - "no automatic aggregate initialization in traditional C", /* 188 */ - "assignment of struct/union illegal in traditional C", /* 189 */ - "empty array declaration: %s", /* 190 */ - "%s set but not used in function %s", /* 191 */ - "%s unused in function %s", /* 192 */ - "statement not reached", /* 193 */ - "label %s redefined", /* 194 */ - "case not in switch", /* 195 */ - "case label affected by conversion", /* 196 */ - "non-constant case expression", /* 197 */ - "non-integral case expression", /* 198 */ - "duplicate case in switch: %ld", /* 199 */ - "duplicate case in switch: %lu", /* 200 */ - "default outside switch", /* 201 */ - "duplicate default in switch", /* 202 */ - "case label must be of type `int' in traditional C", /* 203 */ - "controlling expressions must have scalar type", /* 204 */ - "switch expression must have integral type", /* 205 */ - "enumeration value(s) not handled in switch", /* 206 */ - "loop not entered at top", /* 207 */ - "break outside loop or switch", /* 208 */ - "continue outside loop", /* 209 */ - "enum type mismatch in initialisation", /* 210 */ - "return value type mismatch", /* 211 */ - "cannot return incomplete type", /* 212 */ - "void function %s cannot return value", /* 213 */ - "function %s expects to return value", /* 214 */ - "function implicitly declared to return int", /* 215 */ - "function %s has return (e); and return;", /* 216 */ - "function %s falls off bottom without returning value", /* 217 */ - "ANSI C treats constant as unsigned, op %s", /* 218 */ - "concatenated strings are illegal in traditional C", /* 219 */ - "fallthrough on case statement", /* 220 */ - "initialisation of unsigned with negative constant", /* 221 */ - "conversion of negative constant to unsigned type", /* 222 */ - "end-of-loop code not reached", /* 223 */ - "cannot recover from previous errors", /* 224 */ - "static function called but not defined: %s()", /* 225 */ - "static variable %s unused", /* 226 */ - "const object %s should have initializer", /* 227 */ - "function cannot return const or volatile object", /* 228 */ - "questionable conversion of function pointer", /* 229 */ - "nonportable character comparison, op %s", /* 230 */ - "argument %s unused in function %s()", /* 231 */ - "label %s unused in function %s()", /* 232 */ - "struct %s never defined", /* 233 */ - "union %s never defined", /* 234 */ - "enum %s never defined", /* 235 */ - "static function %s unused", /* 236 */ - "redeclaration of formal parameter %s", /* 237 */ - "initialisation of union is illegal in traditional C", /* 238 */ - "constant argument to NOT", /* 239 */ - "assignment of different structures", /* 240 */ - "dubious operation on enum, op %s", /* 241 */ - "combination of '%s' and '%s', op %s", /* 242 */ - "dubious comparison of enums, op %s", /* 243 */ - "illegal structure pointer combination", /* 244 */ - "illegal structure pointer combination, op %s", /* 245 */ - "dubious conversion of enum to '%s'", /* 246 */ - "pointer casts may be troublesome", /* 247 */ - "floating-point constant out of range", /* 248 */ - "syntax error", /* 249 */ - "unknown character \\%o", /* 250 */ - "malformed integer constant", /* 251 */ - "integer constant out of range", /* 252 */ - "unterminated character constant", /* 253 */ - "newline in string or char constant", /* 254 */ - "undefined or invalid # directive", /* 255 */ - "unterminated comment", /* 256 */ - "extra characters in lint comment", /* 257 */ - "unterminated string constant", /* 258 */ - "%s() arg #%d: converted from '%s' to '%s'", /* 259 */ - "previous declaration of %s", /* 260 */ - "previous definition of %s", /* 261 */ - "\\\" inside character constants undefined in traditional C", /* 262 */ - "\\? undefined in traditional C", /* 263 */ - "\\v undefined in traditional C", /* 264 */ - "%s C does not support 'long long'", /* 265 */ - "'long double' is illegal in traditional C", /* 266 */ - "shift equal to size of object", /* 267 */ - "variable declared inline: %s", /* 268 */ - "argument declared inline: %s", /* 269 */ - "function prototypes are illegal in traditional C", /* 270 */ - "switch expression must be of type `int' in traditional C", /* 271 */ - "empty translation unit", /* 272 */ - "bit-field type '%s' invalid in ANSI C", /* 273 */ - "ANSI C forbids comparison of %s with %s", /* 274 */ - "cast discards 'const' from pointer target type", /* 275 */ - "", /* 276 */ - "initialisation of '%s' with '%s'", /* 277 */ - "%s() arg #%d: combination of '%s' and '%s'", /* 278 */ - "combination of '%s' and '%s' in return", /* 279 */ - "must be outside function: /* %s */", /* 280 */ - "duplicate use of /* %s */", /* 281 */ - "must precede function definition: /* %s */", /* 282 */ - "argument number mismatch with directive: /* %s */", /* 283 */ - "fallthrough on default statement", /* 284 */ - "prototype declaration", /* 285 */ - "function definition is not a prototype", /* 286 */ - "function declaration is not a prototype", /* 287 */ - "dubious use of /* VARARGS */ with /* %s */", /* 288 */ - "can't be used together: /* PRINTFLIKE */ /* SCANFLIKE */", /* 289 */ - "static function %s declared but not defined", /* 290 */ - "invalid multibyte character", /* 291 */ - "cannot concatenate wide and regular string literals", /* 292 */ - "argument %d must be 'char *' for PRINTFLIKE/SCANFLIKE", /* 293 */ - "multi-character character constant", /* 294 */ - "%s() arg #%d: conversion of '%s' to '%s' is out of range", /* 295 */ - "%s() arg #%d: conversion of negative constant to unsigned type", /* 296 */ - "%s() arg #%d: conversion from '%s' to '%s' may sign-extend incorrectly", /* 297 */ - "%s() arg #%d: converted from '%s' to '%s'", /* 298 */ - "prototype does not match old style definition, arg #%d", /* 299 */ - "old style definition", /* 300 */ - "array of incomplete type", /* 301 */ - "%s returns pointer to automatic object", /* 302 */ - "ANSI C forbids conversion of %s to %s", /* 303 */ - "ANSI C forbids conversion of %s to %s, arg #%d", /* 304 */ - "ANSI C forbids conversion of %s to %s, op %s", /* 305 */ - "constant truncated by conversion, op %s", /* 306 */ - "static variable %s set but not used", /* 307 */ - "", /* 308 */ - "extra bits set to 0 in conversion of '%s' to '%s', op %s", /* 309 */ - "right shift of %d-bit quantity by %lld bits", /* 310 */ - "case ranges are illegal in ANSI C", /* 311 */ - "suspicious operator for sizeof: %s", /* 312 */ - "conversion of %s() return value from '%s' to '%s'", /* 313 */ - "hexadecimal float constants are illegal in traditional C", /* 314 */ - "empty body of the if statement", /* 315 */ - "empty body of the else statement", /* 316 */ -}; - -/* - * If Fflag is not set lbasename() returns a pointer to the last - * component of the path, otherwise it returns the argument. - */ -static const char * -lbasename(const char *path) -{ - const char *cp, *cp1, *cp2; - - if (Fflag) - return (path); - - cp = cp1 = cp2 = path; - while (*cp != '\0') { - if (*cp++ == '/') { - cp2 = cp1; - cp1 = cp; - } - } - return (*cp1 == '\0' ? cp2 : cp1); -} - -static void -verror(int n, va_list ap) -{ - const char *fn; - - fn = lbasename(curr_pos.p_file); - (void)printf("%s:%d: ", fn, curr_pos.p_line); - (void)vprintf(msgs[n], ap); - (void)printf("\n"); - nerr++; - - if (fflag) - excerpt(&curr_pos); - -} - -static void -vwarning(int n, va_list ap) -{ - const char *fn; - - if (nowarn) - /* this warning is suppressed by a LINTED comment */ - return; - - fn = lbasename(curr_pos.p_file); - (void)printf("%s:%d: warning: ", fn, curr_pos.p_line); - (void)vprintf(msgs[n], ap); - (void)printf("\n"); - - if (fflag) - excerpt(&curr_pos); -} - -void -error(int n, ...) -{ - va_list ap; - - va_start(ap, n); - verror(n, ap); - va_end(ap); -} - -void -lerror(const char *msg, ...) -{ - va_list ap; - const char *fn; - - va_start(ap, msg); - fn = lbasename(curr_pos.p_file); - (void)fprintf(stderr, "%s:%d: lint error: ", fn, curr_pos.p_line); - (void)vfprintf(stderr, msg, ap); - (void)fprintf(stderr, "\n"); - va_end(ap); - exit(1); -} - -void -warning(int n, ...) -{ - va_list ap; - - va_start(ap, n); - vwarning(n, ap); - va_end(ap); -} - -void -message(int n, ...) -{ - va_list ap; - const char *fn; - - va_start(ap, n); - fn = lbasename(curr_pos.p_file); - (void)printf("%s:%d: ", fn, curr_pos.p_line); - (void)vprintf(msgs[n], ap); - (void)printf("\n"); - va_end(ap); - - if (fflag) - excerpt(&curr_pos); -} - -int -gnuism(int n, ...) -{ - va_list ap; - int msg; - - va_start(ap, n); - if (sflag && !gflag) { - verror(n, ap); - msg = 1; - } else if (!sflag && gflag) { - msg = 0; - } else { - vwarning(n, ap); - msg = 1; - } - va_end(ap); - - return (msg); -} - -static void -excerpt(pos_t *pos) -{ - static FILE *fp = NULL; - static const char *file = NULL; - static int lineno = 0; - char *buf, *lbuf; - size_t len; - - if (!pos || !pos->p_file) - return; - - /* don't print the same line twice */ - if (pos->p_line == lineno) - return; - - if (fp == NULL || file != pos->p_file || pos->p_line < lineno) { - if (fp) - fclose(fp); - - if (!(fp = fopen(pos->p_file, "r"))) - return; - - file = pos->p_file; - lineno = 0; - } - - lbuf = NULL; - while (lineno < pos->p_line && (buf = fgetln(fp, &len))) { - if (buf[len - 1] == '\n') - buf[len - 1] = '\0'; - else { - /* EOF without EOL, copy and add the NUL */ - if (!(lbuf = malloc(len + 1))) - err(1, NULL); - - lbuf[len] = '\0'; - buf = lbuf; - } - lineno++; - } - - if (buf) - printf("%s:%d: %s\n", pos->p_file, lineno, buf); - - free(lbuf); -} diff --git a/usr.bin/xlint/lint1/externs.h b/usr.bin/xlint/lint1/externs.h deleted file mode 100644 index a8834ab559f..00000000000 --- a/usr.bin/xlint/lint1/externs.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $OpenBSD: externs.h,v 1.4 2006/03/08 07:18:51 moritz Exp $ */ -/* $NetBSD: externs.h,v 1.2 1995/07/03 21:24:06 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * mem.c - */ -extern void *xmalloc(size_t); -extern void *xcalloc(size_t, size_t); -extern void *xrealloc(void *, size_t); -extern char *xstrdup(const char *); - -/* - * emit.c - */ -extern ob_t ob; - -extern void outopen(const char *); -extern void outclose(void); -extern void outclr(void); -extern void outchar(int); -extern void outqchar(int); -extern void outstrg(const char *); -extern void outint(int); -extern void outname(const char *); -extern void outsrc(const char *); diff --git a/usr.bin/xlint/lint1/externs1.h b/usr.bin/xlint/lint1/externs1.h deleted file mode 100644 index d9d19299b16..00000000000 --- a/usr.bin/xlint/lint1/externs1.h +++ /dev/null @@ -1,287 +0,0 @@ -/* $OpenBSD: externs1.h,v 1.16 2010/07/24 22:17:03 guenther Exp $ */ -/* $NetBSD: externs1.h,v 1.7 1995/10/02 17:31:39 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * main.c - */ -extern int cflag; -extern int dflag; -extern int eflag; -extern int fflag; -extern int Fflag; -extern int gflag; -extern int hflag; -extern int pflag; -extern int rflag; -extern int sflag; -extern int uflag; -extern int vflag; -extern int yflag; -extern int zflag; - -extern void norecover(void); - -/* - * cgram.y - */ -extern int blklev; -extern int mblklev; -extern int yydebug; - -extern int yyerror(char *); -extern int yyparse(void); - -/* - * scan.l - */ -extern pos_t curr_pos; -extern pos_t csrc_pos; -extern symt_t symtyp; -extern FILE *yyin; -extern u_quad_t qbmasks[], qlmasks[], qumasks[]; - -extern void initscan(void); -extern int sign(quad_t, tspec_t, int); -extern int msb(quad_t, tspec_t, int); -extern quad_t xsign(quad_t, tspec_t, int); -extern void clrwflgs(void); -extern sym_t *getsym(sbuf_t *); -extern void cleanup(void); -extern sym_t *pushdown(sym_t *); -extern void rmsym(sym_t *); -extern void rmsyms(sym_t *); -extern void inssym(int, sym_t *); -extern void freeyyv(void *, int); -extern int yylex(void); - -/* - * mem1.c - */ -extern const char *fnalloc(const char *); -extern const char *fnnalloc(const char *, size_t); -extern int getfnid(const char *); - -extern void initmem(void); - -extern void *getblk(size_t); -extern void *getlblk(int, size_t); -extern void freeblk(void); -extern void freelblk(int); - -extern void *tgetblk(size_t); -extern tnode_t *getnode(void); -extern void tfreeblk(void); -extern struct mbl *tsave(void); -extern void trestor(struct mbl *); - -/* - * err.c - */ -extern int nerr; -extern int sytxerr; -extern const char *msgs[]; - -extern void error(int, ...); -extern void warning(int, ...); -extern void message(int, ...); -extern int gnuism(int, ...); -extern void lerror(const char *, ...); - -/* - * decl.c - */ -extern dinfo_t *dcs; -extern const char *unnamed; -extern int enumval; - -extern void initdecl(void); -extern type_t *gettyp(tspec_t); -extern type_t *duptyp(const type_t *); -extern type_t *tduptyp(const type_t *); -extern int incompl(type_t *); -extern void setcompl(type_t *, int); -extern void addscl(scl_t); -extern void addtype(type_t *); -extern void addqual(tqual_t); -extern void pushdecl(scl_t); -extern void popdecl(void); -extern void setasm(void); -extern void clrtyp(void); -extern int mergedomain(tspec_t *, tspec_t); -extern void deftyp(void); -extern int length(type_t *, const char *); -extern int getbound(type_t *); -extern sym_t *lnklst(sym_t *, sym_t *); -extern void chktyp(sym_t *); -extern sym_t *decl1str(sym_t *); -extern sym_t *bitfield(sym_t *, int); -extern pqinf_t *mergepq(pqinf_t *, pqinf_t *); -extern sym_t *addptr(sym_t *, pqinf_t *); -extern sym_t *addarray(sym_t *, int, int); -extern sym_t *addfunc(sym_t *, sym_t *); -extern void chkfdef(sym_t *, int); -extern sym_t *dname(sym_t *); -extern sym_t *iname(sym_t *); -extern type_t *mktag(sym_t *, tspec_t, int, int); -extern const char *scltoa(scl_t); -extern type_t *compltag(type_t *, sym_t *); -extern sym_t *ename(sym_t *, int, int); -extern void decl1ext(sym_t *, int); -extern void cpuinfo(sym_t *, sym_t *); -extern int isredec(sym_t *, int *); -extern int eqtype(type_t *, type_t *, int, int, int *); -extern void compltyp(sym_t *, sym_t *); -extern sym_t *decl1arg(sym_t *, int); -extern void cluparg(void); -extern void decl1loc(sym_t *, int); -extern sym_t *aname(void); -extern void globclup(void); -extern sym_t *decl1abs(sym_t *); -extern void chksz(sym_t *); -extern void setsflg(sym_t *); -extern void setuflg(sym_t *, int, int); -extern void chkusage(dinfo_t *); -extern void chkusg1(int, sym_t *); -extern void chkglsyms(void); -extern void prevdecl(int, sym_t *); - -/* - * tree.c - */ -extern void initmtab(void); -extern type_t *incref(type_t *, tspec_t); -extern type_t *tincref(type_t *, tspec_t); -extern tnode_t *getcnode(type_t *, val_t *); -extern tnode_t *getnnode(sym_t *, int); -extern tnode_t *getsnode(strg_t *); -extern sym_t *strmemb(tnode_t *, op_t, sym_t *); -extern tnode_t *build(op_t, tnode_t *, tnode_t *); -extern tnode_t *cconv(tnode_t *); -extern int typeok(op_t, farg_t *, tnode_t *, tnode_t *); -extern tnode_t *promote(op_t, int, tnode_t *); -extern tnode_t *convert(op_t, farg_t *, type_t *, tnode_t *); -extern void cvtcon(op_t, farg_t *, type_t *, val_t *, val_t *); -extern const char *tyname(type_t *); -extern tnode_t *bldszof(type_t *); -extern tnode_t *bldszoftrm(tnode_t *); -extern tnode_t *cast(tnode_t *, type_t *); -extern tnode_t *funcarg(tnode_t *, tnode_t *); -extern tnode_t *funccall(tnode_t *, tnode_t *); -extern val_t *constant(tnode_t *); -extern void expr(tnode_t *, int, int); -extern void chkmisc(tnode_t *, int, int, int, int, int, int); -extern int conaddr(tnode_t *, sym_t **, ptrdiff_t *); -extern strg_t *catstrg(strg_t *, strg_t *); -extern void displexpr(tnode_t *, int); - -/* - * func.c - */ -extern sym_t *funcsym; -extern int reached; -extern int rchflg; -extern int ftflg; -extern int nargusg; -extern pos_t aupos; -extern int nvararg; -extern pos_t vapos; -extern int prflstrg; -extern pos_t prflpos; -extern int scflstrg; -extern pos_t scflpos; -extern int ccflg; -extern int llibflg; -extern int nowarn; -extern int noretflg; -extern int usedflg; -extern int plibflg; -extern int quadflg; - -extern void pushctrl(int); -extern void popctrl(int); -extern void chkreach(void); -extern void funcdef(sym_t *); -extern void funcend(void); -extern void label(int, sym_t *, tnode_t *); -extern void if1(tnode_t *); -extern void if2(void); -extern void if3(int); -extern void switch1(tnode_t *); -extern void switch2(void); -extern void while1(tnode_t *); -extern void while2(void); -extern void do1(void); -extern void do2(tnode_t *); -extern void for1(tnode_t *, tnode_t *, tnode_t *); -extern void for2(void); -extern void dogoto(sym_t *); -extern void docont(void); -extern void dobreak(void); -extern void doreturn(tnode_t *); -extern void glclup(int); -extern void argsused(int); -extern void noreturn(int); -extern void lintused(int); -extern void constcond(int); -extern void fallthru(int); -extern void notreach(int); -extern void lintlib(int); -extern void linted(int); -extern void varargs(int); -extern void printflike(int); -extern void scanflike(int); -extern void protolib(int); -extern void longlong(int); - -/* - * init.c - */ -extern int initerr; -extern sym_t *initsym; -extern int startinit; - -extern void prepinit(void); -extern void initrbr(void); -extern void initlbr(void); -extern void mkinit(tnode_t *); - -/* - * emit.c - */ -extern void outtype(type_t *); -extern const char *ttos(type_t *); -extern void outsym(sym_t *, scl_t, def_t); -extern void outfdef(sym_t *, pos_t *, int, int, sym_t *); -extern void outcall(tnode_t *, int, int); -extern void outusg(sym_t *); diff --git a/usr.bin/xlint/lint1/func.c b/usr.bin/xlint/lint1/func.c deleted file mode 100644 index a81c6948998..00000000000 --- a/usr.bin/xlint/lint1/func.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* $OpenBSD: func.c,v 1.22 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: func.c,v 1.7 1995/10/02 17:31:40 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <string.h> - -#include "lint1.h" -#include "y.tab.h" - -/* - * Contains a pointer to the symbol table entry of the current function - * definition. - */ -sym_t *funcsym; - -/* Is set as long as a statement can be reached. Must be set at level 0. */ -int reached = 1; - -/* - * Is set as long as NOTREACHED is in effect. - * Is reset everywhere where reached can become 0. - */ -int rchflg; - -/* - * In conjunction with reached controls printing of "fallthrough on ..." - * warnings. - * Reset by each statement and set by FALLTHROUGH, switch (switch1()) - * and case (label()). - * - * Control statements if, for, while and switch do not reset ftflg because - * this must be done by the controled statement. At least for if this is - * important because ** FALLTHROUGH ** after "if (expr) stmnt" is evaluated - * befor the following token, wich causes reduction of above, is read. - * This means that ** FALLTHROUGH ** after "if ..." would always be ignored. - */ -int ftflg; - -/* Top element of stack for control statements */ -cstk_t *cstk; - -/* - * Number of arguments which will be checked for usage in following - * function definition. -1 stands for all arguments. - * - * The position of the last ARGSUSED comment is stored in aupos. - */ -int nargusg = -1; -pos_t aupos; - -/* - * If the following function has been declared NORETURN, noretflg is set - * to 1. Otherwise it is set to 0. - */ -int noretflg = 0; - -/* - * If the following symbol should be marked as having been used, even if - * lint thinks otherwise, usedflg is set to 1. Otherwise it is set to 0. - */ -int usedflg = 0; - -/* - * Number of arguments of the following function definition whose types - * shall be checked by lint2. -1 stands for all arguments. - * - * The position of the last VARARGS comment is stored in vapos. - */ -int nvararg = -1; -pos_t vapos; - -/* - * Both prflstr and scflstrg contain the number of the argument which - * shall be used to check the types of remaining arguments (for PRINTFLIKE - * and SCANFLIKE). - * - * prflpos and scflpos are the positions of the last PRINTFLIKE or - * SCANFLIKE comment. - */ -int prflstrg = -1; -int scflstrg = -1; -pos_t prflpos; -pos_t scflpos; - -/* - * Are both plibflg and llibflg set, prototypes are written as function - * definitions to the output file. - */ -int plibflg; - -/* - * Nonzero means that no warnings about constants in conditional - * context are printed. - */ -int ccflg; - -/* - * llibflg is set if a lint library shall be created. The effect of - * llibflg is that all defined symbols are treated as used. - * (The LINTLIBRARY comment also resets vflag.) - */ -int llibflg; - -/* - * Nonzero if warnings are suppressed by a LINTED directive - */ -int nowarn; - -/* - * Nonzero if complaints about use of "long long" are suppressed in - * the next statement or declaration. - */ -int quadflg = 1; - -/* - * Puts a new element at the top of the stack used for control statements. - */ -void -pushctrl(int env) -{ - cstk_t *ci; - - ci = xcalloc(1, sizeof (cstk_t)); - ci->c_env = env; - ci->c_nxt = cstk; - cstk = ci; -} - -/* - * Removes the top element of the stack used for control statements. - */ -void -popctrl(int env) -{ - cstk_t *ci; - clst_t *cl; - - if (cstk == NULL || cstk->c_env != env) - lerror("popctrl() 1"); - - cstk = (ci = cstk)->c_nxt; - - while ((cl = ci->c_clst) != NULL) { - ci->c_clst = cl->cl_nxt; - free(cl); - } - - if (ci->c_swtype != NULL) - free(ci->c_swtype); - - free(ci); -} - -/* - * Prints a warning if a statement cannot be reached. - */ -void -chkreach(void) -{ - if (!reached && !rchflg) { - /* statement not reached */ - warning(193); - reached = 1; - } -} - -/* - * Called after a function declaration which introduces a function definition - * and before an (optional) old style argument declaration list. - * - * Puts all symbols declared in the prototype or in an old style argument - * list back to the symbol table. - * - * Does the usual checking of storage class, type (return value), - * redeclaration etc.. - */ -void -funcdef(sym_t *fsym) -{ - int n, warn; - sym_t *arg, *sym, *rdsym; - - funcsym = fsym; - - /* - * Put all symbols declared in the argument list back to the - * symbol table. - */ - for (sym = dcs->d_fpsyms; sym != NULL; sym = sym->s_dlnxt) { - if (sym->s_blklev != -1) { - if (sym->s_blklev != 1) - lerror("funcdef() 1"); - inssym(1, sym); - } - } - - /* - * __func__ is a "predefined identifier" in c99, which means it is a - * block-scope variable supplying the name of the enclosing function. - * It is defined as: - * - * static const char __func__[] = "function-name"; - * - */ - sym = getblk(sizeof (sym_t)); - sym->s_name = "__func__"; - sym->s_kind = FVFT; - sym->s_scl = STATIC; - sym->s_type = incref(gettyp(CHAR), ARRAY); - sym->s_blklev = 1; - sym->s_def = DEF; - sym->s_type->t_dim = strlen(fsym->s_name) + 1; - sym->s_type->t_subt = duptyp(gettyp(CHAR)); - sym->s_type->t_subt->t_const = 1; - inssym(1, sym); - - /* - * In osfunc() we did not know whether it is an old style function - * definition or only an old style declaration, if there are no - * arguments inside the argument list ("f()"). - */ - if (!fsym->s_type->t_proto && fsym->s_args == NULL) - fsym->s_osdef = 1; - - chktyp(fsym); - - /* - * chktyp() checks for almost all possible errors, but not for - * incomplete return values (these are allowed in declarations) - */ - if (fsym->s_type->t_subt->t_tspec != VOID && - incompl(fsym->s_type->t_subt)) { - /* cannot return incomplete type */ - error(67); - } - - fsym->s_def = DEF; - - if (fsym->s_scl == TYPEDEF) { - fsym->s_scl = EXTERN; - /* illegal storage class */ - error(8); - } - - if (dcs->d_inline) - fsym->s_inline = 1; - - /* - * Arguments in new style function declarations need a name. - * (void is already removed from the list of arguments) - */ - n = 1; - for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_nxt) { - if (arg->s_scl == ABSTRACT) { - if (arg->s_name != unnamed) - lerror("funcdef() 2"); - /* formal parameter lacks name: param #%d */ - error(59, n); - } else { - if (arg->s_name == unnamed) - lerror("funcdef() 3"); - } - n++; - } - - /* - * We must also remember the position. s_dpos is overwritten - * if this is an old style definition and we had already a - * prototype. - */ - STRUCT_ASSIGN(dcs->d_fdpos, fsym->s_dpos); - - if ((rdsym = dcs->d_rdcsym) != NULL) { - - if (!isredec(fsym, (warn = 0, &warn))) { - - /* - * Print nothing if the newly defined function - * is defined in old style. A better warning will - * be printed in cluparg(). - */ - if (warn && !fsym->s_osdef) { - /* redeclaration of %s */ - (*(sflag ? error : warning))(27, fsym->s_name); - prevdecl(-1, rdsym); - } - - /* copy usage information */ - cpuinfo(fsym, rdsym); - - /* - * If the old symbol was a prototype and the new - * one is none, overtake the position of the - * declaration of the prototype. - */ - if (fsym->s_osdef && rdsym->s_type->t_proto) - STRUCT_ASSIGN(fsym->s_dpos, rdsym->s_dpos); - - /* complete the type */ - compltyp(fsym, rdsym); - - /* once a function is inline it remains inline */ - if (rdsym->s_inline) - fsym->s_inline = 1; - - } - - /* remove the old symbol from the symbol table */ - rmsym(rdsym); - - } - - if (fsym->s_osdef && !fsym->s_type->t_proto) { - if (sflag && hflag && strcmp(fsym->s_name, "main") != 0) - /* function definition is not a prototype */ - warning(286); - } - - if (dcs->d_notyp) - /* return value is implicitly declared to be int */ - fsym->s_rimpl = 1; - - reached = 1; -} - -/* - * Called at the end of a function definition. - */ -void -funcend(void) -{ - sym_t *arg; - int n; - - if (reached) { - cstk->c_noretval = 1; - if (funcsym->s_type->t_subt->t_tspec != VOID && - !funcsym->s_rimpl) { - /* func. %s falls off bottom without returning value */ - warning(217, funcsym->s_name); - } - } - - /* - * This warning is printed only if the return value was implicitly - * declared to be int. Otherwise the wrong return statement - * has already printed a warning. - */ - if (cstk->c_noretval && cstk->c_retval && funcsym->s_rimpl) - /* function %s has return (e); and return; */ - warning(216, funcsym->s_name); - - /* Print warnings for unused arguments */ - arg = dcs->d_fargs; - n = 0; - while (arg != NULL && (nargusg == -1 || n < nargusg)) { - chkusg1(dcs->d_asm, arg); - arg = arg->s_nxt; - n++; - } - nargusg = -1; - - if (noretflg) - funcsym->s_noreturn = 1; - noretflg = 0; - - /* - * write the information about the function definition to the - * output file - * inline functions explicitly declared extern are written as - * declarations only. - */ - if (dcs->d_scl == EXTERN && funcsym->s_inline) { - outsym(funcsym, funcsym->s_scl, DECL); - } else { - outfdef(funcsym, &dcs->d_fdpos, cstk->c_retval, - funcsym->s_osdef, dcs->d_fargs); - } - - /* - * remove all symbols declared during argument declaration from - * the symbol table - */ - if (dcs->d_nxt != NULL || dcs->d_ctx != EXTERN) - lerror("funcend() 1"); - rmsyms(dcs->d_fpsyms); - - /* must be set on level 0 */ - reached = 1; -} - -/* - * Process a label. - * - * typ type of the label (T_NAME, T_DEFAULT or T_CASE). - * sym symbol table entry of label if typ == T_NAME - * tn expression if typ == T_CASE - */ -void -label(int typ, sym_t *sym, tnode_t *tn) -{ - cstk_t *ci; - clst_t *cl; - val_t *v, *nv; - tspec_t t; - - switch (typ) { - - case T_NAME: - if (sym->s_set) { - /* label %s redefined */ - error(194, sym->s_name); - } else { - setsflg(sym); - } - break; - - case T_CASE: - - /* find the stack entry for the innermost switch statement */ - for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt) ; - - if (ci == NULL) { - /* case not in switch */ - error(195); - tn = NULL; - } else if (tn != NULL && tn->tn_op != CON) { - /* non-constant case expression */ - error(197); - tn = NULL; - } else if (tn != NULL && !isityp(tn->tn_type->t_tspec)) { - /* non-integral case expression */ - error(198); - tn = NULL; - } - - if (tn != NULL) { - - if (ci->c_swtype == NULL) - lerror("label() 1"); - - if (reached && !ftflg) { - if (hflag) - /* fallthrough on case statement */ - warning(220); - } - - t = tn->tn_type->t_tspec; - - /* - * get the value of the expression and convert it - * to the type of the switch expression - */ - v = constant(tn); - nv = xcalloc(1, sizeof (val_t)); - cvtcon(CASE, NULL, ci->c_swtype, nv, v); - free(v); - - /* look if we had this value already */ - for (cl = ci->c_clst; cl != NULL; cl = cl->cl_nxt) { - if (cl->cl_val.v_quad == nv->v_quad) - break; - } - if (cl != NULL && isutyp(nv->v_tspec)) { - /* duplicate case in switch, %lu */ - error(200, (u_long)nv->v_quad); - } else if (cl != NULL) { - /* duplicate case in switch, %ld */ - error(199, (long)nv->v_quad); - } else { - /* - * append the value to the list of - * case values - */ - cl = xcalloc(1, sizeof (clst_t)); - STRUCT_ASSIGN(cl->cl_val, *nv); - cl->cl_nxt = ci->c_clst; - ci->c_clst = cl; - } - } - tfreeblk(); - break; - - case T_DEFAULT: - - /* find the stack entry for the innermost switch statement */ - for (ci = cstk; ci != NULL && !ci->c_switch; ci = ci->c_nxt) ; - - if (ci == NULL) { - /* default outside switch */ - error(201); - } else if (ci->c_default) { - /* duplicate default in switch */ - error(202); - } else { - if (reached && !ftflg) { - if (hflag) - /* fallthrough on default statement */ - warning(284); - } - ci->c_default = 1; - } - break; - }; - reached = 1; -} - -/* - * T_IF T_LPARN expr T_RPARN - */ -void -if1(tnode_t *tn) -{ - if (tn != NULL) - tn = cconv(tn); - if (tn != NULL) - tn = promote(NOOP, 0, tn); - expr(tn, 0, 1); - pushctrl(T_IF); -} - -/* - * if_without_else - * if_without_else T_ELSE - */ -void -if2(void) -{ - cstk->c_rchif = reached ? 1 : 0; - reached = 1; -} - -/* - * if_without_else - * if_without_else T_ELSE stmnt - */ -void -if3(int els) -{ - if (els) { - reached |= cstk->c_rchif; - } else { - reached = 1; - } - popctrl(T_IF); -} - -/* - * T_SWITCH T_LPARN expr T_RPARN - */ -void -switch1(tnode_t *tn) -{ - type_t *tp; - - if (tn != NULL) - tn = cconv(tn); - if (tn != NULL) - tn = promote(NOOP, 0, tn); - if (tn != NULL && !isityp(tn->tn_type->t_tspec)) { - /* switch expression must have integral type */ - error(205); - tn = NULL; - } - - /* - * Remember the type of the expression. Because its possible - * that (*tp) is allocated on tree memory the type must be - * duplicated. This is not too complicated because it is - * only an integer type. - */ - tp = xcalloc(1, sizeof (type_t)); - if (tn != NULL) { - tp->t_tspec = tn->tn_type->t_tspec; - if ((tp->t_isenum = tn->tn_type->t_isenum) != 0) - tp->t_enum = tn->tn_type->t_enum; - } else { - tp->t_tspec = INT; - } - - expr(tn, 1, 0); - - pushctrl(T_SWITCH); - cstk->c_switch = 1; - cstk->c_swtype = tp; - - reached = rchflg = 0; - ftflg = 1; -} - -/* - * switch_expr stmnt - */ -void -switch2(void) -{ - int nenum, nclab; - sym_t *esym; - clst_t *cl; - - if (cstk->c_swtype == NULL) - lerror("switch2() 1"); - - /* - * If the switch expression was of type enumeration, count the case - * labels and the number of enumerators. If both counts are not - * equal print a warning. - */ - if (cstk->c_swtype->t_isenum) { - nenum = nclab = 0; - if (cstk->c_swtype->t_enum == NULL) - lerror("switch2() 2"); - for (esym = cstk->c_swtype->t_enum->elem; - esym != NULL; esym = esym->s_nxt) { - nenum++; - } - for (cl = cstk->c_clst; cl != NULL; cl = cl->cl_nxt) - nclab++; - if (hflag && eflag && nenum != nclab && !cstk->c_default) { - /* enumeration value(s) not handled in switch */ - warning(206); - } - } - - if (cstk->c_break) { - /* - * end of switch always reached (c_break is only set if the - * break statement can be reached). - */ - reached = 1; - } else if (!cstk->c_default && - (!hflag || !cstk->c_swtype->t_isenum || nenum != nclab)) { - /* - * there are possible values which are not handled in - * switch - */ - reached = 1; - } /* - * otherwise the end of the switch expression is reached - * if the end of the last statement inside it is reached. - */ - - popctrl(T_SWITCH); -} - -/* - * T_WHILE T_LPARN expr T_RPARN - */ -void -while1(tnode_t *tn) -{ - if (!reached) { - /* loop not entered at top */ - warning(207); - reached = 1; - } - - if (tn != NULL) - tn = cconv(tn); - if (tn != NULL) - tn = promote(NOOP, 0, tn); - if (tn != NULL && !issclt(tn->tn_type->t_tspec)) { - /* controlling expressions must have scalar type */ - error(204); - tn = NULL; - } - - pushctrl(T_WHILE); - cstk->c_loop = 1; - if (tn != NULL && tn->tn_op == CON) { - if (isityp(tn->tn_type->t_tspec)) { - cstk->c_infinite = tn->tn_val->v_quad != 0; - } else { - cstk->c_infinite = tn->tn_val->v_ldbl != 0.0; - } - } - - expr(tn, 0, 1); -} - -/* - * while_expr stmnt - * while_expr error - */ -void -while2(void) -{ - /* - * The end of the loop can be reached if it is no endless loop - * or there was a break statement which was reached. - */ - reached = !cstk->c_infinite || cstk->c_break; - rchflg = 0; - - popctrl(T_WHILE); -} - -/* - * T_DO - */ -void -do1(void) -{ - if (!reached) { - /* loop not entered at top */ - warning(207); - reached = 1; - } - - pushctrl(T_DO); - cstk->c_loop = 1; -} - -/* - * do stmnt do_while_expr - * do error - */ -void -do2(tnode_t *tn) -{ - /* - * If there was a continue statement the expression controlling the - * loop is reached. - */ - if (cstk->c_cont) - reached = 1; - - if (tn != NULL) - tn = cconv(tn); - if (tn != NULL) - tn = promote(NOOP, 0, tn); - if (tn != NULL && !issclt(tn->tn_type->t_tspec)) { - /* controlling expressions must have scalar type */ - error(204); - tn = NULL; - } - - if (tn != NULL && tn->tn_op == CON) { - if (isityp(tn->tn_type->t_tspec)) { - cstk->c_infinite = tn->tn_val->v_quad != 0; - } else { - cstk->c_infinite = tn->tn_val->v_ldbl != 0.0; - } - } - - expr(tn, 0, 1); - - /* - * The end of the loop is only reached if it is no endless loop - * or there was a break statement which could be reached. - */ - reached = !cstk->c_infinite || cstk->c_break; - rchflg = 0; - - popctrl(T_DO); -} - -/* - * T_FOR T_LPARN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPARN - */ -void -for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3) -{ - /* - * If there is no initialisation expression it is possible that - * it is intended not to enter the loop at top. - */ - if (tn1 != NULL && !reached) { - /* loop not entered at top */ - warning(207); - reached = 1; - } - - pushctrl(T_FOR); - cstk->c_loop = 1; - - /* - * Store the tree memory for the reinitialisation expression. - * Also remember this expression itself. We must check it at - * the end of the loop to get "used but not set" warnings correct. - */ - cstk->c_fexprm = tsave(); - cstk->c_f3expr = tn3; - STRUCT_ASSIGN(cstk->c_fpos, curr_pos); - STRUCT_ASSIGN(cstk->c_cfpos, csrc_pos); - - if (tn1 != NULL) - expr(tn1, 0, 0); - - if (tn2 != NULL) - tn2 = cconv(tn2); - if (tn2 != NULL) - tn2 = promote(NOOP, 0, tn2); - if (tn2 != NULL && !issclt(tn2->tn_type->t_tspec)) { - /* controlling expressions must have scalar type */ - error(204); - tn2 = NULL; - } - if (tn2 != NULL) - expr(tn2, 0, 1); - - if (tn2 == NULL) { - cstk->c_infinite = 1; - } else if (tn2->tn_op == CON) { - if (isityp(tn2->tn_type->t_tspec)) { - cstk->c_infinite = tn2->tn_val->v_quad != 0; - } else { - cstk->c_infinite = tn2->tn_val->v_ldbl != 0.0; - } - } - - /* Checking the reinitialisation expression is done in for2() */ - - reached = 1; -} - -/* - * for_exprs stmnt - * for_exprs error - */ -void -for2(void) -{ - pos_t cpos, cspos; - tnode_t *tn3; - - if (cstk->c_cont) - reached = 1; - - STRUCT_ASSIGN(cpos, curr_pos); - STRUCT_ASSIGN(cspos, csrc_pos); - - /* Restore the tree memory for the reinitialisation expression */ - trestor(cstk->c_fexprm); - tn3 = cstk->c_f3expr; - STRUCT_ASSIGN(curr_pos, cstk->c_fpos); - STRUCT_ASSIGN(csrc_pos, cstk->c_cfpos); - - /* simply "statement not reached" would be confusing */ - if (!reached && !rchflg) { - /* end-of-loop code not reached */ - warning(223); - reached = 1; - } - - if (tn3 != NULL) { - expr(tn3, 0, 0); - } else { - tfreeblk(); - } - - STRUCT_ASSIGN(curr_pos, cpos); - STRUCT_ASSIGN(csrc_pos, cspos); - - /* An endless loop without break will never terminate */ - reached = cstk->c_break || !cstk->c_infinite; - rchflg = 0; - - popctrl(T_FOR); -} - -/* - * T_GOTO identifier T_SEMI - * T_GOTO error T_SEMI - */ -void -dogoto(sym_t *lab) -{ - setuflg(lab, 0, 0); - - chkreach(); - - reached = rchflg = 0; -} - -/* - * T_BREAK T_SEMI - */ -void -dobreak(void) -{ - cstk_t *ci; - - ci = cstk; - while (ci != NULL && !ci->c_loop && !ci->c_switch) - ci = ci->c_nxt; - - if (ci == NULL) { - /* break outside loop or switch */ - error(208); - } else { - if (reached) - ci->c_break = 1; - } - - /* Don't warn about unreachable breaks in a switch, e.g.: - * - * switch (foo) { - * case 1: - * return 1; - * break; - * case 2: - * // etc... - * } - */ - if (ci == NULL || !ci->c_switch) - chkreach(); - - reached = rchflg = 0; -} - -/* - * T_CONTINUE T_SEMI - */ -void -docont(void) -{ - cstk_t *ci; - - for (ci = cstk; ci != NULL && !ci->c_loop; ci = ci->c_nxt) ; - - if (ci == NULL) { - /* continue outside loop */ - error(209); - } else { - ci->c_cont = 1; - } - - chkreach(); - - reached = rchflg = 0; -} - -/* - * T_RETURN T_SEMI - * T_RETURN expr T_SEMI - */ -void -doreturn(tnode_t *tn) -{ - tnode_t *ln, *rn; - cstk_t *ci; - op_t op; - - for (ci = cstk; ci->c_nxt != NULL; ci = ci->c_nxt) ; - - if (tn != NULL) { - ci->c_retval = 1; - } else { - ci->c_noretval = 1; - } - - if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) { - /* void function %s cannot return value */ - error(213, funcsym->s_name); - tfreeblk(); - tn = NULL; - } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { - /* - * Assume that the function has a return value only if it - * is explicitly declared. - */ - if (!funcsym->s_rimpl) - /* function %s expects to return value */ - warning(214, funcsym->s_name); - } - - if (tn != NULL) { - - /* Create a temporary node for the left side */ - ln = tgetblk(sizeof (tnode_t)); - ln->tn_op = NAME; - ln->tn_type = tduptyp(funcsym->s_type->t_subt); - ln->tn_type->t_const = 0; - ln->tn_lvalue = 1; - ln->tn_sym = funcsym; /* better than nothing */ - - tn = build(RETURN, ln, tn); - - if (tn != NULL) { - rn = tn->tn_right; - while ((op = rn->tn_op) == CVT || op == PLUS) - rn = rn->tn_left; - if (rn->tn_op == AMPER && rn->tn_left->tn_op == NAME && - rn->tn_left->tn_sym->s_scl == AUTO) { - /* %s returns pointer to automatic object */ - warning(302, funcsym->s_name); - } - } - - expr(tn, 1, 0); - - } else { - - chkreach(); - - } - - reached = rchflg = 0; -} - -/* - * Do some cleanup after a global declaration or definition. - * Especially remove informations about unused lint comments. - */ -void -glclup(int silent) -{ - pos_t cpos; - - STRUCT_ASSIGN(cpos, curr_pos); - - if (nargusg != -1) { - if (!silent) { - STRUCT_ASSIGN(curr_pos, aupos); - /* must precede function definition: %s */ - warning(282, "ARGSUSED"); - } - nargusg = -1; - } - if (nvararg != -1) { - if (!silent) { - STRUCT_ASSIGN(curr_pos, vapos); - /* must precede function definition: %s */ - warning(282, "VARARGS"); - } - nvararg = -1; - } - if (prflstrg != -1) { - if (!silent) { - STRUCT_ASSIGN(curr_pos, prflpos); - /* must precede function definition: %s */ - warning(282, "PRINTFLIKE"); - } - prflstrg = -1; - } - if (scflstrg != -1) { - if (!silent) { - STRUCT_ASSIGN(curr_pos, scflpos); - /* must precede function definition: %s */ - warning(282, "SCANFLIKE"); - } - scflstrg = -1; - } - - STRUCT_ASSIGN(curr_pos, cpos); - - dcs->d_asm = 0; -} - -/* - * ARGSUSED comment - * - * Only the first n arguments of the following function are checked - * for usage. A missing argument is taken to be 0. - */ -void -argsused(int n) -{ - if (n == -1) - n = 0; - - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "ARGSUSED"); - return; - } - if (nargusg != -1) { - /* duplicate use of ** %s ** */ - warning(281, "ARGSUSED"); - } - nargusg = n; - STRUCT_ASSIGN(aupos, curr_pos); -} - -/* - * NORETURN comment - * - * The following function will never return, which means any code - * following a call to this function is unreachable. - */ -void -noreturn(int n) -{ - noretflg = 1; -} - -/* - * LINTUSED comment - * - * Mark a symbol as used, so lint2 does not complain. - */ -void -lintused(int n) -{ - usedflg = 1; -} - -/* - * VARARGS comment - * - * Makes that lint2 checks only the first n arguments for compatibility - * to the function definition. A missing argument is taken to be 0. - */ -void -varargs(int n) -{ - if (n == -1) - n = 0; - - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "VARARGS"); - return; - } - if (nvararg != -1) { - /* duplicate use of ** %s ** */ - warning(281, "VARARGS"); - } - nvararg = n; - STRUCT_ASSIGN(vapos, curr_pos); -} - -/* - * PRINTFLIKE comment - * - * Check all arguments until the (n-1)-th as usual. The n-th argument is - * used the check the types of remaining arguments. - */ -void -printflike(int n) -{ - if (n == -1) - n = 0; - - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "PRINTFLIKE"); - return; - } - if (prflstrg != -1) { - /* duplicate use of ** %s ** */ - warning(281, "PRINTFLIKE"); - } - prflstrg = n; - STRUCT_ASSIGN(prflpos, curr_pos); -} - -/* - * SCANFLIKE comment - * - * Check all arguments until the (n-1)-th as usual. The n-th argument is - * used the check the types of remaining arguments. - */ -void -scanflike(int n) -{ - if (n == -1) - n = 0; - - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "SCANFLIKE"); - return; - } - if (scflstrg != -1) { - /* duplicate use of ** %s ** */ - warning(281, "SCANFLIKE"); - } - scflstrg = n; - STRUCT_ASSIGN(scflpos, curr_pos); -} - -/* - * Set the linenumber for a CONSTCOND comment. At this and the following - * line no warnings about constants in conditional contexts are printed. - */ -/* ARGSUSED */ -void -constcond(int n) -{ - ccflg = 1; -} - -/* - * Suppress printing of "fallthrough on ..." warnings until next - * statement. - */ -/* ARGSUSED */ -void -fallthru(int n) -{ - ftflg = 1; -} - -/* - * Stop warnings about statements which cannot be reached. Also tells lint - * that the following statements cannot be reached (e.g. after exit()). - */ -/* ARGSUSED */ -void -notreach(int n) -{ - reached = 0; - rchflg = 1; -} - -/* ARGSUSED */ -void -lintlib(int n) -{ - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "LINTLIBRARY"); - return; - } - llibflg = 1; - vflag = 0; -} - -/* - * Suppress most warnings at the current and the following line. - */ -/* ARGSUSED */ -void -linted(int n) -{ - nowarn = 1; -} - -/* - * PROTOTLIB in conjunction with LINTLIBRARY can be used to handle - * prototypes like function definitions. This is done if the argument - * to PROTOLIB is nonzero. Otherwise prototypes are handled normaly. - */ -void -protolib(int n) -{ - if (dcs->d_ctx != EXTERN) { - /* must be outside function: ** %s ** */ - warning(280, "PROTOLIB"); - return; - } - plibflg = n == 0 ? 0 : 1; -} - -/* - * Set quadflg to nonzero which means that the next statement/declaration - * may use "long long" without an error or warning. - */ -/* ARGSUSED */ -void -longlong(int n) -{ - quadflg = 1; -} diff --git a/usr.bin/xlint/lint1/init.c b/usr.bin/xlint/lint1/init.c deleted file mode 100644 index 6fbec3194ed..00000000000 --- a/usr.bin/xlint/lint1/init.c +++ /dev/null @@ -1,486 +0,0 @@ -/* $OpenBSD: init.c,v 1.13 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: init.c,v 1.4 1995/10/02 17:21:37 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> - -#include "lint1.h" - -/* - * initerr is set as soon as a fatal error occurred in an initialisation. - * The effect is that the rest of the initialisation is ignored (parsed - * by yacc, expression trees built, but no initialisation takes place). - */ -int initerr; - -/* Pointer to the symbol which is to be initialized. */ -sym_t *initsym; - -/* Points to the top element of the initialisation stack. */ -istk_t *initstk; - - -static void popi2(void); -static void popinit(int); -static void pushinit(void); -static void testinit(void); -static void nextinit(int); -static int strginit(tnode_t *); - - -/* - * Initialize the initialisation stack by putting an entry for the variable - * which is to be initialized on it. - */ -void -prepinit(void) -{ - istk_t *istk; - - if (initerr) - return; - - /* free memory used in last initialisation */ - while ((istk = initstk) != NULL) { - initstk = istk->i_nxt; - free(istk); - } - - /* - * If the type which is to be initialized is an incomplete type, - * it must be duplicated. - */ - if (initsym->s_type->t_tspec == ARRAY && incompl(initsym->s_type)) - initsym->s_type = duptyp(initsym->s_type); - - istk = initstk = xcalloc(1, sizeof (istk_t)); - istk->i_subt = initsym->s_type; - istk->i_cnt = 1; - -} - -static void -popi2(void) -{ - istk_t *istk; - sym_t *m; - - initstk = (istk = initstk)->i_nxt; - if (initstk == NULL) - lerror("popi2() 1"); - free(istk); - - istk = initstk; - - istk->i_cnt--; - if (istk->i_cnt < 0) - lerror("popi2() 3"); - - /* - * If the removed element was a structure member, we must go - * to the next structure member. - */ - if (istk->i_cnt > 0 && istk->i_type->t_tspec == STRUCT) { - do { - m = istk->i_mem = istk->i_mem->s_nxt; - if (m == NULL) - lerror("popi2() 2"); - } while (m->s_field && m->s_name == unnamed); - istk->i_subt = m->s_type; - } -} - -static void -popinit(int brace) -{ - if (brace) { - /* - * Take all entries, including the first which requires - * a closing brace, from the stack. - */ - do { - brace = initstk->i_brace; - popi2(); - } while (!brace); - } else { - /* - * Take all entries which cannot be used for further - * initializers from the stack, but do this only if - * they do not require a closing brace. - */ - while (!initstk->i_brace && - initstk->i_cnt == 0 && !initstk->i_nolimit) { - popi2(); - } - } -} - -static void -pushinit(void) -{ - istk_t *istk; - int cnt; - sym_t *m; - - istk = initstk; - - /* Extend an incomplete array type by one element */ - if (istk->i_cnt == 0) { - /* - * Inside of other aggregate types must not be an incomplete - * type. - */ - if (istk->i_nxt->i_nxt != NULL) - lerror("pushinit() 1"); - istk->i_cnt = 1; - if (istk->i_type->t_tspec != ARRAY) - lerror("pushinit() 2"); - istk->i_type->t_dim++; - /* from now its an complete type */ - setcompl(istk->i_type, 0); - } - - if (istk->i_cnt <= 0) - lerror("pushinit() 3"); - if (istk->i_type != NULL && issclt(istk->i_type->t_tspec)) - lerror("pushinit() 4"); - - initstk = xcalloc(1, sizeof (istk_t)); - initstk->i_nxt = istk; - initstk->i_type = istk->i_subt; - if (initstk->i_type->t_tspec == FUNC) - lerror("pushinit() 5"); - - istk = initstk; - - switch (istk->i_type->t_tspec) { - case ARRAY: - if (incompl(istk->i_type) && istk->i_nxt->i_nxt != NULL) { - /* initialisation of an incomplete type */ - error(175); - initerr = 1; - return; - } - istk->i_subt = istk->i_type->t_subt; - istk->i_nolimit = incompl(istk->i_type); - istk->i_cnt = istk->i_type->t_dim; - break; - case UNION: - /* FALLTHROUGH */ - case STRUCT: - if (incompl(istk->i_type)) { - /* initialisation of an incomplete type */ - error(175); - initerr = 1; - return; - } - cnt = 0; - for (m = istk->i_type->t_str->memb; m != NULL; m = m->s_nxt) { - if (m->s_field && m->s_name == unnamed) - continue; - if (++cnt == 1) { - istk->i_mem = m; - istk->i_subt = m->s_type; - } - } - if (cnt == 0) { - /* cannot init. struct/union with no named member */ - error(179); - initerr = 1; - return; - } - istk->i_cnt = istk->i_type->t_tspec == STRUCT ? cnt : 1; - break; - default: - istk->i_cnt = 1; - break; - } -} - -static void -testinit(void) -{ - istk_t *istk; - - istk = initstk; - - /* - * If a closing brace is expected we have at least one initializer - * too much. - */ - if (istk->i_cnt == 0 && !istk->i_nolimit) { - switch (istk->i_type->t_tspec) { - case ARRAY: - /* too many array initializers */ - error(173); - break; - case STRUCT: - case UNION: - /* too many struct/union initializers */ - error(172); - break; - default: - /* too many initializers */ - error(174); - break; - } - initerr = 1; - } -} - -static void -nextinit(int brace) -{ - if (!brace) { - if (initstk->i_type == NULL && - !issclt(initstk->i_subt->t_tspec)) { - /* {}-enclosed initializer required */ - error(181); - } - /* - * Make sure an entry with a scalar type is at the top - * of the stack. - */ - if (!initerr) - testinit(); - while (!initerr && (initstk->i_type == NULL || - !issclt(initstk->i_type->t_tspec))) { - if (!initerr) - pushinit(); - } - } else { - if (initstk->i_type != NULL && - issclt(initstk->i_type->t_tspec)) { - /* invalid initializer */ - error(176); - initerr = 1; - } - if (!initerr) - testinit(); - if (!initerr) - pushinit(); - if (!initerr) - initstk->i_brace = 1; - } -} - -void -initlbr(void) -{ - if (initerr) - return; - - /* - * Remove all entries which cannot be used for further initializers - * and do not expect a closing brace. - */ - popinit(0); - - nextinit(1); -} - -void -initrbr(void) -{ - if (initerr) - return; - - popinit(1); -} - -void -mkinit(tnode_t *tn) -{ - ptrdiff_t offs; - sym_t *sym; - tspec_t lt, rt; - tnode_t *ln; - struct mbl *tmem; - scl_t sc; - - if (initerr || tn == NULL) - goto end; - - sc = initsym->s_scl; - - /* - * Do not test for automatic aggregate initialisation. If the - * initializer starts with a brace we have the warning already. - * If not, an error will be printed that the initializer must - * be enclosed by braces. - */ - - /* - * Local initialisation of non-array-types with only one expression - * without braces is done by ASSIGN - */ - if ((sc == AUTO || sc == REG) && - initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) { - ln = getnnode(initsym, 0); - ln->tn_type = tduptyp(ln->tn_type); - ln->tn_type->t_const = 0; - tn = build(ASSIGN, ln, tn); - expr(tn, 0, 0); - goto end; - } - - /* - * Remove all entries which cannot be used for further initializers - * and do not require a closing brace. - */ - popinit(0); - - /* Initialisations by strings are done in strginit(). */ - if (strginit(tn)) - goto end; - - nextinit(0); - if (initerr || tn == NULL) - goto end; - - initstk->i_cnt--; - - /* Create a temporary node for the left side. */ - ln = tgetblk(sizeof (tnode_t)); - ln->tn_op = NAME; - ln->tn_type = tduptyp(initstk->i_type); - ln->tn_type->t_const = 0; - ln->tn_lvalue = 1; - ln->tn_sym = initsym; /* better than nothing */ - - tn = cconv(tn); - - lt = ln->tn_type->t_tspec; - rt = tn->tn_type->t_tspec; - - if (!issclt(lt)) - lerror("mkinit() 1"); - - if (!typeok(INIT, NULL, ln, tn)) - goto end; - - /* - * Store the tree memory. This is necessary because otherwise - * expr() would free it. - */ - tmem = tsave(); - expr(tn, 1, 0); - trestor(tmem); - - if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON)) - tn = convert(INIT, NULL, initstk->i_type, tn); - - if (tn != NULL && tn->tn_op != CON) { - sym = NULL; - offs = 0; - if (conaddr(tn, &sym, &offs) == -1) { - if (sc == AUTO || sc == REG) { - /* non-constant initializer */ - (void)gnuism(177); - } else { - /* non-constant initializer */ - error(177); - } - } - } - - end: - tfreeblk(); -} - - -static int -strginit(tnode_t *tn) -{ - tspec_t t; - istk_t *istk; - int len; - strg_t *strg; - - if (tn->tn_op != STRING) - return (0); - - istk = initstk; - strg = tn->tn_strg; - - /* - * Check if we have an array type which can be initialized by - * the string. - */ - if (istk->i_subt != NULL && istk->i_subt->t_tspec == ARRAY) { - t = istk->i_subt->t_subt->t_tspec; - if (!((strg->st_tspec == CHAR && - (t == CHAR || t == UCHAR || t == SCHAR)) || - (strg->st_tspec == WCHAR && t == WCHAR))) { - return (0); - } - /* Put the array at top of stack */ - pushinit(); - istk = initstk; - } else if (istk->i_type != NULL && istk->i_type->t_tspec == ARRAY) { - t = istk->i_type->t_subt->t_tspec; - if (!((strg->st_tspec == CHAR && - (t == CHAR || t == UCHAR || t == SCHAR)) || - (strg->st_tspec == WCHAR && t == WCHAR))) { - return (0); - } - /* - * If the array is already partly initialized, we are - * wrong here. - */ - if (istk->i_cnt != istk->i_type->t_dim) - return (0); - } else { - return (0); - } - - /* Get length without trailing NUL character. */ - len = strg->st_len; - - if (istk->i_nolimit) { - istk->i_nolimit = 0; - istk->i_type->t_dim = len + 1; - /* from now complete type */ - setcompl(istk->i_type, 0); - } else { - if (istk->i_type->t_dim < len) { - /* non-null byte ignored in string initializer */ - warning(187); - } - } - - /* In every case the array is initialized completely. */ - istk->i_cnt = 0; - - return (1); -} diff --git a/usr.bin/xlint/lint1/lint.h b/usr.bin/xlint/lint1/lint.h deleted file mode 100644 index 570832e04e5..00000000000 --- a/usr.bin/xlint/lint1/lint.h +++ /dev/null @@ -1,131 +0,0 @@ -/* $OpenBSD: lint.h,v 1.7 2010/07/24 22:17:03 guenther Exp $ */ -/* $NetBSD: lint.h,v 1.2 1995/07/03 21:24:18 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <stdio.h> -#include <stddef.h> - -#include "param.h" - -/* - * Type specifiers, used in type structures (type_t) and elsewhere. - */ -typedef enum { - NOTSPEC, - SIGNED, /* keyword "signed", only used in the parser */ - UNSIGN, /* keyword "unsigned", only used in the parser */ - BOOL, /* _Bool */ - CHAR, /* char */ - SCHAR, /* signed char */ - UCHAR, /* unsigned char */ - SHORT, /* (signed) short */ - USHORT, /* unsigned short */ - INT, /* (signed) int */ - UINT, /* unsigned int */ - LONG, /* (signed) long */ - ULONG, /* unsigned long */ - QUAD, /* (signed) long long */ - UQUAD, /* unsigned long long */ - FLOAT, /* float */ - DOUBLE, /* double */ - LDOUBLE, /* long double */ - COMPLEX, /* float _Complex */ - DCOMPLEX, /* double _Complex */ - LDCOMPLEX, /* long double _Complex */ - IMAGINARY, /* float _Imaginary */ - DIMAGINARY, /* double _Imaginary */ - LDIMAGINARY, /* long double _Imaginary */ - VOID, /* void */ - STRUCT, /* structure tag */ - UNION, /* union tag */ - ENUM, /* enum tag */ - PTR, /* pointer */ - ARRAY, /* array */ - FUNC /* function */ -#define NTSPEC ((int)FUNC + 1) -} tspec_t; - -/* - * size of types, name and classification - */ -typedef struct { - int tt_sz; /* size in bits */ - int tt_psz; /* size, different from tt_sz - if pflag is set */ - int tt_rank; /* rank (C99), similar to tt_psz */ - tspec_t tt_styp; /* signed counterpart */ - tspec_t tt_utyp; /* unsigned counterpart */ - u_int tt_isityp : 1; /* 1 if integer type */ - u_int tt_isutyp : 1; /* 1 if unsigned integer type */ - u_int tt_isftyp : 1; /* 1 if floating point type */ - u_int tt_isatyp : 1; /* 1 if arithmetic type */ - u_int tt_domain : 2; /* 0 if non-scalar, 1 if real, - 2 if imaginary, 3 if complex */ - char *tt_name; /* type name */ -} ttab_t; - -#define size(t) (ttab[t].tt_sz) -#define psize(t) (ttab[t].tt_psz) -#define rank(t) (ttab[t].tt_rank) -#define styp(t) (ttab[t].tt_styp) -#define utyp(t) (ttab[t].tt_utyp) -#define isityp(t) (ttab[t].tt_isityp) -#define isutyp(t) (ttab[t].tt_isutyp) -#define isftyp(t) (ttab[t].tt_isftyp) -#define isatyp(t) (ttab[t].tt_isatyp) -#define issclt(t) (ttab[t].tt_domain != 0) -#define iscomplex(t) (ttab[t].tt_domain == 3) -#define isimag(t) (ttab[t].tt_domain == 2) - -extern ttab_t ttab[]; - - -typedef enum { - NODECL, /* until now not declared */ - DECL, /* declared */ - TDEF, /* tentative defined */ - DEF /* defined */ -} def_t; - -/* - * Following structure contains some data used for the output buffer. - */ -typedef struct ob { - char *o_buf; /* buffer */ - char *o_end; /* first byte after buffer */ - size_t o_len; /* length of buffer */ - char *o_nxt; /* next free byte in buffer */ -} ob_t; - -#include "externs.h" diff --git a/usr.bin/xlint/lint1/lint1.h b/usr.bin/xlint/lint1/lint1.h deleted file mode 100644 index 780b0913412..00000000000 --- a/usr.bin/xlint/lint1/lint1.h +++ /dev/null @@ -1,399 +0,0 @@ -/* $OpenBSD: lint1.h,v 1.15 2011/05/30 15:15:58 martynas Exp $ */ -/* $NetBSD: lint1.h,v 1.6 1995/10/02 17:31:41 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "lint.h" -#include "op.h" - -/* - * Describes the position of a declaration or anything else. - */ -typedef struct { - int p_line; - const char *p_file; -} pos_t; - -/* - * Strings cannot be referenced to simply by a pointer to its first - * char. This is because strings can contain NUL characters other than the - * trailing NUL. - * - * Strings are stored with a trailing NUL. - */ -typedef struct strg { - tspec_t st_tspec; /* CHAR or WCHAR */ - size_t st_len; /* length without trailing NUL */ - union { - u_char *_st_cp; - wchar_t *_st_wcp; - } st_u; -} strg_t; - -#define st_cp st_u._st_cp -#define st_wcp st_u._st_wcp - -/* - * qualifiers (only for lex/yacc interface) - */ -typedef enum { - CONST, VOLATILE, RESTRICT -} tqual_t; - -/* - * Integer and floating point values are stored in this structure - */ -typedef struct { - tspec_t v_tspec; - int v_ansiu; /* set if an integer constant is - unsigned in ANSI C */ - tspec_t v_lspec; /* the underlying type of a literal */ - union { - quad_t _v_quad; /* integers */ - ldbl_t _v_ldbl; /* floats */ - } v_u; -} val_t; - -#define v_quad v_u._v_quad -#define v_ldbl v_u._v_ldbl - -/* - * Structures of type str_t uniqely identify structures. This can't - * be done in structures of type type_t, because these are copied - * if they must be modified. So it would not be possible to check - * if two structures are identical by comparing the pointers to - * the type structures. - * - * The typename is used if the structure is unnamed to identify - * the structure type in pass 2. - */ -typedef struct { - u_int size; /* size in bit */ - u_int align : 15; /* alignment in bit */ - u_int sincompl : 1; /* set if incomplete type */ - struct sym *memb; /* list of members */ - struct sym *stag; /* symbol table entry of tag */ - struct sym *stdef; /* symbol table entry of first typename */ -} str_t; - -/* - * same as above for enums - */ -typedef struct { - u_int eincompl : 1; /* incomplete enum type */ - struct sym *elem; /* list of enumerators */ - struct sym *etag; /* symbol table entry of tag */ - struct sym *etdef; /* symbol table entry of first typename */ -} enum_t; - -/* - * Types are represented by concatenation of structures of type type_t - * via t_subt. - */ -typedef struct type { - tspec_t t_tspec; /* type specifier */ - u_int t_aincompl : 1; /* incomplete array type */ - u_int t_const : 1; /* const modifier */ - u_int t_volatile : 1; /* volatile modifier */ - u_int t_restrict : 1; /* restrict modifier */ - u_int t_proto : 1; /* function prototype (t_args valid) */ - u_int t_vararg : 1; /* protoype with ... */ - u_int t_typedef : 1; /* type defined with typedef */ - u_int t_isfield : 1; /* type is bitfield */ - u_int t_isenum : 1; /* type is (or was) enum (t_enum valid) */ - union { - int _t_dim; /* dimension */ - str_t *_t_str; /* struct/union tag */ - enum_t *_t_enum; /* enum tag */ - struct sym *_t_args; /* arguments (if t_proto) */ - struct { - u_int _t_flen : 8; /* length of bit-field */ - u_int _t_foffs : 24; /* offset of bit-field */ - } _t_u; - } t_u; - struct type *t_subt; /* element type (arrays), return value - (functions), or type pointer points to */ -} type_t; - -#define t_dim t_u._t_dim -#define t_str t_u._t_str -#define t_field t_u._t_field -#define t_enum t_u._t_enum -#define t_args t_u._t_args -#define t_flen t_u._t_u._t_flen -#define t_foffs t_u._t_u._t_foffs - -/* - * types of symbols - */ -typedef enum { - FVFT, /* variables, functions, type names, enums */ - FMOS, /* members of structs or unions */ - FTAG, /* tags */ - FLAB /* labels */ -} symt_t; - -/* - * storage classes - */ -typedef enum { - NOSCL, - EXTERN, /* external symbols (indep. of decl_t) */ - STATIC, /* static symbols (local and global) */ - AUTO, /* automatic symbols (except register) */ - REG, /* register */ - TYPEDEF, /* typedef */ - STRTAG, - UNIONTAG, - ENUMTAG, - MOS, /* member of struct */ - MOU, /* member of union */ - ENUMCON, /* enumerator */ - ABSTRACT, /* abstract symbol (sizeof, casts, unnamed argument) */ - ARG, /* argument */ - PARG, /* used in declaration stack during prototype - declaration */ - INLINE /* only used by the parser */ -} scl_t; - -/* - * symbol table entry - */ -typedef struct sym { - const char *s_name; /* name */ - pos_t s_dpos; /* position of last (prototype)definition, - prototypedeclaration, no-prototype-def., - tentative definition or declaration, - in this order */ - pos_t s_spos; /* position of first initialisation */ - pos_t s_upos; /* position of first use */ - symt_t s_kind; /* type of symbol */ - u_int s_keyw : 1; /* keyword */ - u_int s_field : 1; /* bit-field */ - u_int s_set : 1; /* variable set, label defined */ - u_int s_used : 1; /* variable/label used */ - u_int s_arg : 1; /* symbol is function argument */ - u_int s_reg : 1; /* symbol is register variable */ - u_int s_defarg : 1; /* undefined symbol in old style function - definition */ - u_int s_rimpl : 1; /* return value of function implicit decl. */ - u_int s_osdef : 1; /* symbol stems from old style function def. */ - u_int s_inline : 1; /* true if this is a inline function */ - u_int s_noreturn : 1; /* true if this is a NORETURN function */ - struct sym *s_xsym; /* for local declared external symbols pointer - to external symbol with same name */ - def_t s_def; /* declared, tentative defined, defined */ - scl_t s_scl; /* storage class */ - int s_blklev; /* level of declaration, -1 if not in symbol - table */ - type_t *s_type; /* type */ - val_t s_value; /* value (if enumcon) */ - union { - str_t *_s_st; /* tag, if it is a struct/union member */ - enum_t *_s_et; /* tag, if it is a enumerator */ - tspec_t _s_tsp; /* type (only for keywords) */ - tqual_t _s_tqu; /* qualifier (only for keywords) */ - struct sym *_s_args; /* arguments in old style function - definitions */ - op_t _s_op; /* op type (only for operators) */ - } u; - struct sym *s_link; /* next symbol with same hash value */ - struct sym **s_rlink; /* pointer to s_link of prev. symbol */ - struct sym *s_nxt; /* next struct/union member, enumerator, - argument */ - struct sym *s_dlnxt; /* next symbol declared on same level */ -} sym_t; - -#define s_styp u._s_st -#define s_etyp u._s_et -#define s_tspec u._s_tsp -#define s_tqual u._s_tqu -#define s_op u._s_op -#define s_args u._s_args - -/* - * Used to keep some informations about symbols before they are entered - * into the symbol table. - */ -typedef struct sbuf { - const char *sb_name; /* name of symbol */ - size_t sb_len; /* length (without '\0') */ - int sb_hash; /* hash value */ - sym_t *sb_sym; /* symbol table entry */ - struct sbuf *sb_nxt; /* for freelist */ -} sbuf_t; - - -/* - * tree node - */ -typedef struct tnode { - op_t tn_op; /* operator */ - type_t *tn_type; /* type */ - u_int tn_lvalue : 1; /* node is lvalue */ - u_int tn_cast : 1; /* if tn_op == CVT its an explicit cast */ - u_int tn_parn : 1; /* node parenthesized */ - union { - struct { - struct tnode *_tn_left; /* (left) operand */ - struct tnode *_tn_right; /* right operand */ - } tn_s; - sym_t *_tn_sym; /* symbol if op == NAME */ - val_t *_tn_val; /* value if op == CON */ - strg_t *_tn_strg; /* string if op == STRING */ - } tn_u; -} tnode_t; - -#define tn_left tn_u.tn_s._tn_left -#define tn_right tn_u.tn_s._tn_right -#define tn_sym tn_u._tn_sym -#define tn_val tn_u._tn_val -#define tn_strg tn_u._tn_strg - -/* - * For nested declarations a stack exists, which holds all information - * needed for the current level. dcs points to the top element of this - * stack. - * - * ctx describes the context of the current declaration. Its value is - * one of - * EXTERN global declarations - * MOS oder MOU declarations of struct or union members - * ENUMCON declarations of enums - * ARG declaration of arguments in old style function definitions - * PARG declaration of arguments in function prototypes - * AUTO declaration of local symbols - * ABSTRACT abstract declarations (sizeof, casts) - * - */ -typedef struct dinfo { - tspec_t d_atyp; /* NOTSPEC, VOID, CHAR, INT, FLOAT or DOUBLE */ - tspec_t d_smod; /* sign: NOTSPEC, SIGNED or UNSIGN */ - tspec_t d_lmod; /* length: NOTSPEC, SHORT, LONG or QUAD */ - tspec_t d_dmod; /* domain: NOTSPEC, COMPLEX or IMAGINARY */ - scl_t d_scl; /* storage class */ - type_t *d_type; /* after deftyp() pointer to the type used - for all declarators */ - sym_t *d_rdcsym; /* redeclared symbol */ - int d_offset; /* offset of next structure member */ - int d_stralign; /* alignment required for current structure */ - scl_t d_ctx; /* context of declaration */ - u_int d_const : 1; /* const in declaration specifiers */ - u_int d_volatile : 1; /* volatile in declaration specifiers */ - u_int d_restrict : 1; /* restrict in declaration specifiers */ - u_int d_inline : 1; /* inline in declaration specifiers */ - u_int d_mscl : 1; /* multiple storage classes */ - u_int d_terr : 1; /* invalid type combination */ - u_int d_nedecl : 1; /* 1 if at least a tag is declared */ - u_int d_vararg : 1; /* ... in current function decl. */ - u_int d_proto : 1; /* current funct. decl. is prototype */ - u_int d_notyp : 1; /* set if no type specifier was present */ - u_int d_asm : 1; /* set if d_ctx == AUTO and asm() present */ - type_t *d_tagtyp; /* tag during member declaration */ - sym_t *d_fargs; /* list of arguments during function def. */ - pos_t d_fdpos; /* position of function definition */ - sym_t *d_dlsyms; /* first symbol declared at this level */ - sym_t **d_ldlsym; /* points to s_dlnxt in last symbol decl. - at this level */ - sym_t *d_fpsyms; /* symbols defined in prototype */ - struct dinfo *d_nxt; /* next level */ -} dinfo_t; - -/* - * Type of stack which is used for initialisation of aggregate types. - */ -typedef struct istk { - type_t *i_type; /* type of initialisation */ - type_t *i_subt; /* type of next level */ - u_int i_brace : 1; /* need } for pop */ - u_int i_nolimit : 1; /* incomplete array type */ - sym_t *i_mem; /* next structure member */ - int i_cnt; /* # of remaining elements */ - struct istk *i_nxt; /* previous level */ -} istk_t; - -/* - * Used to collect information about pointers and qualifiers in - * declarators. - */ -typedef struct pqinf { - int p_pcnt; /* number of asterisks */ - u_int p_const : 1; - u_int p_volatile : 1; - u_int p_restrict : 1; - struct pqinf *p_nxt; -} pqinf_t; - -/* - * Case values are stored in a list of type clst_t. - */ -typedef struct clst { - val_t cl_val; - struct clst *cl_nxt; -} clst_t; - -/* - * Used to keep informations about nested control statements. - */ -typedef struct cstk { - int c_env; /* type of statement (T_IF, ...) */ - u_int c_loop : 1; /* continue && break are valid */ - u_int c_switch : 1; /* case && break are valid */ - u_int c_break : 1; /* loop/switch has break */ - u_int c_cont : 1; /* loop has continue */ - u_int c_default : 1; /* switch has default */ - u_int c_infinite : 1; /* break condition always false - (for (;;), while (1)) */ - u_int c_rchif : 1; /* end of if-branch reached */ - u_int c_noretval : 1; /* had "return;" */ - u_int c_retval : 1; /* had "return (e);" */ - type_t *c_swtype; /* type of switch expression */ - clst_t *c_clst; /* list of case values */ - struct mbl *c_fexprm; /* saved memory for end of loop - expression in for() */ - tnode_t *c_f3expr; /* end of loop expr in for() */ - pos_t c_fpos; /* position of end of loop expr */ - pos_t c_cfpos; /* same for csrc_pos */ - struct cstk *c_nxt; /* outer control statement */ -} cstk_t; - -/* - * Used to keep information about arguments passed to functions with - * prototypes. - */ -typedef struct farg { - int fa_num; /* argument number (1-basde) */ - sym_t *fa_sym; /* argument symbol */ - tnode_t *fa_func; /* function name */ -} farg_t; - -#include "externs1.h" diff --git a/usr.bin/xlint/lint1/main1.c b/usr.bin/xlint/lint1/main1.c deleted file mode 100644 index 99916e5f47b..00000000000 --- a/usr.bin/xlint/lint1/main1.c +++ /dev/null @@ -1,170 +0,0 @@ -/* $OpenBSD: main1.c,v 1.12 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: main1.c,v 1.3 1995/10/02 17:29:56 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <err.h> - -#include "lint1.h" - -/* set yydebug to 1*/ -int yflag; - -/* Print warnings for pointer casts. */ -int cflag; - -/* Print various debug information. */ -int dflag; - -/* Perform stricter checking of enum types and operations on enum types. */ -int eflag; - -/* Print complete pathnames, not only the basename. */ -int Fflag = 1; - -/* After an error or warning, print the actual text of the program source code */ -int fflag = 0; - -/* Enable some extensions of gcc */ -int gflag; - -/* - * Apply a number of heuristic tests to attempt to intuit bugs, improve - * style, and reduce waste. - */ -int hflag; - -/* Attempt to check portability to other dialects of C. */ -int pflag; - -/* - * In case of redeclarations/redefinitions print the location of the - * previous declaration/definition. - */ -int rflag; - -/* Strict ANSI C mode. */ -int sflag; - -/* - * Complain about functions and external variables used and not defined, - * or defined and not used. - */ -int uflag = 1; - -/* Complain about unused function arguments. */ -int vflag = 1; - -/* Complain about structures which are never defined. */ -int zflag = 0; - -static void usage(void); - -int -main(int argc, char *argv[]) -{ - int c; - - while ((c = getopt(argc, argv, "abcdefghprstuvyzF")) != -1) { - switch (c) { - case 'a': /* obsolete */ break; - case 'b': /* obsolete */ break; - case 'c': cflag = 1; break; - case 'd': dflag = 1; break; - case 'e': eflag = 1; break; - case 'F': Fflag = 1; break; - case 'g': gflag = 1; break; - case 'h': hflag = 1; break; - case 'f': fflag = 1; break; - case 'p': pflag = 1; break; - case 'r': rflag = 1; break; - case 's': sflag = 1; break; - case 't': /* obsolete */ break; - case 'u': uflag = 0; break; - case 'v': vflag = 0; break; - case 'y': yflag = 1; break; - case 'z': zflag = 0; break; - case '?': usage(); - } - } - argc -= optind; - argv += optind; - - if (argc != 2) - usage(); - - /* open the input file */ - if ((yyin = fopen(argv[0], "r")) == NULL) - err(1, "cannot open '%s'", argv[0]); - - /* initialize output */ - outopen(argv[1]); - -#if YYDEBUG - if (yflag) - yydebug = 1; -#endif - - initmem(); - initdecl(); - initscan(); - initmtab(); - - yyparse(); - - /* Following warnings cannot be suppressed by LINTED */ - nowarn = 0; - - chkglsyms(); - - outclose(); - - return (nerr != 0); -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: lint1 [-abcdeghprstuvyzF] src dest\n"); - exit(1); -} - -void -norecover(void) -{ - /* cannot recover from previous errors */ - error(224); - exit(1); -} diff --git a/usr.bin/xlint/lint1/mem.c b/usr.bin/xlint/lint1/mem.c deleted file mode 100644 index e2f605188cb..00000000000 --- a/usr.bin/xlint/lint1/mem.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenBSD: mem.c,v 1.5 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: mem.c,v 1.2 1995/07/03 21:24:24 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <string.h> -#include <err.h> - -#include "lint.h" - -void * -xmalloc(size_t s) -{ - void *p; - - if ((p = malloc(s)) == NULL) - err(1, NULL); - return (p); -} - -void * -xcalloc(size_t n, size_t s) -{ - void *p; - - if ((p = calloc(n, s)) == NULL) - err(1, NULL); - return (p); -} - -void * -xrealloc(void *p, size_t s) -{ - if ((p = realloc(p, s)) == NULL) - err(1, NULL); - return (p); -} - -char * -xstrdup(const char *s) -{ - char *s2; - - if ((s2 = strdup(s)) == NULL) - err(1, NULL); - return (s2); -} diff --git a/usr.bin/xlint/lint1/mem1.c b/usr.bin/xlint/lint1/mem1.c deleted file mode 100644 index 19976272f62..00000000000 --- a/usr.bin/xlint/lint1/mem1.c +++ /dev/null @@ -1,328 +0,0 @@ -/* $OpenBSD: mem1.c,v 1.12 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: mem1.c,v 1.2 1995/07/03 21:24:25 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/param.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <err.h> - -#include "lint1.h" - -/* - * Filenames allocated by fnalloc() and fnnalloc() are shared. - */ -typedef struct fn { - char *fn_name; - size_t fn_len; - int fn_id; - struct fn *fn_nxt; -} fn_t; - -static fn_t *fnames; - -static fn_t *srchfn(const char *, size_t); - -/* - * Look for a Filename of length l. - */ -static fn_t * -srchfn(const char *s, size_t len) -{ - fn_t *fn; - - for (fn = fnames; fn != NULL; fn = fn->fn_nxt) { - if (fn->fn_len == len && memcmp(fn->fn_name, s, len) == 0) - break; - } - return (fn); -} - -/* - * Return a shared string for filename s. - */ -const char * -fnalloc(const char *s) -{ - return (s != NULL ? fnnalloc(s, strlen(s)) : NULL); -} - -const char * -fnnalloc(const char *s, size_t len) -{ - fn_t *fn; - - static int nxt_id = 0; - - if (s == NULL) - return (NULL); - - if ((fn = srchfn(s, len)) == NULL) { - fn = xmalloc(sizeof (fn_t)); - /* Do not used strdup() because string is not NUL-terminated.*/ - fn->fn_name = xmalloc(len + 1); - (void)memcpy(fn->fn_name, s, len); - fn->fn_name[len] = '\0'; - fn->fn_len = len; - fn->fn_id = nxt_id++; - fn->fn_nxt = fnames; - fnames = fn; - /* Write id of this filename to the output file. */ - outclr(); - outint(fn->fn_id); - outchar('s'); - outstrg(fn->fn_name); - } - return (fn->fn_name); -} - -/* - * Get id of a filename. - */ -int -getfnid(const char *s) -{ - fn_t *fn; - - if (s == NULL || (fn = srchfn(s, strlen(s))) == NULL) - return (-1); - return (fn->fn_id); -} - -/* - * Memory for declarations and other things which must be available - * until the end of a block (or the end of the translation unit) - * are associated with the level (mblklev) of the block (or with 0). - * Because this memory is allocated in large blocks associated with - * a given level it can be freed easily at the end of a block. - */ -#define ML_INC ((size_t)32) /* Increment for length of *mblks */ - -typedef struct mbl { - void *blk; /* beginning of memory block */ - void *ffree; /* first free byte */ - size_t nfree; /* # of free bytes */ - size_t size; /* total size of memory block */ - struct mbl *nxt; /* next block */ -} mbl_t; - -/* - * Array of pointers to lists of memory blocks. mblklev is used as - * index into this array. - */ -static mbl_t **mblks; - -/* number of elements in *mblks */ -static size_t nmblks; - -/* free list for memory blocks */ -static mbl_t *frmblks; - -/* length of new allocated memory blocks */ -static size_t mblklen; - -static void *xgetblk(mbl_t **, size_t); -static void xfreeblk(mbl_t **); -static mbl_t *xnewblk(void); - -static mbl_t * -xnewblk(void) -{ - mbl_t *mb; - - mb = xmalloc(sizeof (mbl_t)); - mb->blk = xmalloc(mblklen); - mb->size = mblklen; - return (mb); -} - -/* - * Allocate new memory. If the first block of the list has not enough - * free space, or there is no first block, get a new block. The new - * block is taken from the free list or, if there is no block on the - * free list, is allocated using xnewblk(). If a new block is allocated - * it is initialized with zero. Blocks taken from the free list are - * zero'd in xfreeblk(). - */ -static void * -xgetblk(mbl_t **mbp, size_t s) -{ - mbl_t *mb; - void *p; - - s = ALIGN(s); - if ((mb = *mbp) == NULL || mb->nfree < s) { - if ((mb = frmblks) == NULL) { - mb = xnewblk(); - (void)memset(mb->blk, 0, mb->size); - } else { - frmblks = mb->nxt; - } - mb->ffree = mb->blk; - mb->nfree = mb->size; - mb->nxt = *mbp; - *mbp = mb; - } - p = mb->ffree; - mb->ffree = (char *)mb->ffree + s; - mb->nfree -= s; - return (p); -} - -/* - * Move all blocks from list *fmbp to free list. For each block, set all - * used memory to zero. - */ -static void -xfreeblk(mbl_t **fmbp) -{ - mbl_t *mb; - - while ((mb = *fmbp) != NULL) { - *fmbp = mb->nxt; - mb->nxt = frmblks; - frmblks = mb; - (void)memset(mb->blk, 0, mb->size - mb->nfree); - } -} - -void -initmem(void) -{ - int pgsz; - - pgsz = getpagesize(); - mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz; - - mblks = xcalloc(nmblks = ML_INC, sizeof (mbl_t *)); -} - - -/* - * Allocate memory associated with level l. - */ -void * -getlblk(int l, size_t s) -{ - while (l >= nmblks) { - mblks = xrealloc(mblks, (nmblks + ML_INC) * sizeof (mbl_t *)); - (void)memset(&mblks[nmblks], 0, ML_INC * sizeof (mbl_t *)); - nmblks += ML_INC; - } - return (xgetblk(&mblks[l], s)); -} - -void * -getblk(size_t s) -{ - return (getlblk(mblklev, s)); -} - -/* - * Free all memory associated with level l. - */ -void -freelblk(int l) -{ - xfreeblk(&mblks[l]); -} - -void -freeblk(void) -{ - freelblk(mblklev); -} - -/* - * tgetblk() returns memory which is associated with the current - * expression. - */ -static mbl_t *tmblk; - -void * -tgetblk(size_t s) -{ - return (xgetblk(&tmblk, s)); -} - -/* - * Get memory for a new tree node. - */ -tnode_t * -getnode(void) -{ - return (tgetblk(sizeof (tnode_t))); -} - -/* - * Free all memory which is allocated by the current expression. - */ -void -tfreeblk(void) -{ - xfreeblk(&tmblk); -} - -/* - * Save the memory which is used by the current expression. This memory - * is not freed by the next tfreeblk() call. The pointer returned can be - * used to restore the memory. - */ -mbl_t * -tsave(void) -{ - mbl_t *tmem; - - tmem = tmblk; - tmblk = NULL; - return (tmem); -} - -/* - * Free all memory used for the current expression and the memory used - * be a previous expression and saved by tsave(). The next call to - * tfreeblk() frees the restored memory. - */ -void -trestor(mbl_t *tmem) -{ - tfreeblk(); - if (tmblk != NULL) { - free(tmblk->blk); - free(tmblk); - } - tmblk = tmem; -} diff --git a/usr.bin/xlint/lint1/op.h b/usr.bin/xlint/lint1/op.h deleted file mode 100644 index 2198822f8aa..00000000000 --- a/usr.bin/xlint/lint1/op.h +++ /dev/null @@ -1,123 +0,0 @@ -/* $OpenBSD: op.h,v 1.4 2010/07/24 22:17:03 guenther Exp $ */ -/* $NetBSD: op.h,v 1.2 1995/07/03 21:24:27 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Various information about operators - */ -typedef struct { - u_int m_binary : 1; /* binary op. */ - u_int m_logop : 1; /* logical op., result is int */ - u_int m_rqint : 1; /* operands must have integer type */ - u_int m_rqsclt : 1; /* operands must have scalar type */ - u_int m_rqatyp : 1; /* operands must have arithmetic type */ - u_int m_fold : 1; /* operands should be folded */ - u_int m_vctx : 1; /* value context for left operand */ - u_int m_tctx : 1; /* test context for left operand */ - u_int m_balance : 1; /* op. requires balancing */ - u_int m_sideeff : 1; /* op. has side effect */ - u_int m_tlansiu : 1; /* warning if left op. is unsign. in ANSI C */ - u_int m_transiu : 1; /* warning if right op. is unsign. in ANSI C */ - u_int m_tpconf : 1; /* test possible precedence confusion */ - u_int m_comp : 1; /* op. performs comparison */ - u_int m_enumop : 1; /* valid operation on enums */ - u_int m_badeop : 1; /* dubious operation on enums */ - u_int m_eqwarn : 1; /* warning if on operand stems from == */ - const char *m_name; /* name of op. */ -} mod_t; - -typedef enum { - NOOP = 0, - ARROW, - POINT, - NOT, - COMPL, - INC, - DEC, - INCBEF, - DECBEF, - INCAFT, - DECAFT, - UPLUS, - UMINUS, - STAR, - AMPER, - MULT, - DIV, - MOD, - PLUS, - MINUS, - SHL, - SHR, - LT, - LE, - GT, - GE, - EQ, - NE, - AND, - XOR, - OR, - LOGAND, - LOGOR, - QUEST, - COLON, - ASSIGN, - MULASS, - DIVASS, - MODASS, - ADDASS, - SUBASS, - SHLASS, - SHRASS, - ANDASS, - XORASS, - ORASS, - NAME, - CON, - STRING, - FSEL, - CALL, - COMMA, - CVT, - ICALL, - LOAD, - PUSH, - RETURN, - REAL, /* gcc extension: __real__ */ - IMAG, /* gcc extension: __imag__ */ - INIT, /* pseudo op, not used in trees */ - CASE, /* pseudo op, not used in trees */ - FARG /* pseudo op, not used in trees */ -#define NOPS ((int)FARG + 1) -} op_t; diff --git a/usr.bin/xlint/lint1/param.h b/usr.bin/xlint/lint1/param.h deleted file mode 100644 index f8f86fc132a..00000000000 --- a/usr.bin/xlint/lint1/param.h +++ /dev/null @@ -1,88 +0,0 @@ -/* $OpenBSD: param.h,v 1.15 2007/10/11 07:30:07 otto Exp $ */ -/* $NetBSD: param.h,v 1.6 1996/04/01 21:47:57 mark Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Minimun size of string buffer. If this is not enough, the buffer - * is enlarged in steps of STRBLEN bytes. - */ -#define STRBLEN 256 - -/* - * This defines the size of memory blocks which are used to allocate - * memory in larger chunks. - */ -#define MBLKSIZ ((size_t)0x4000) - -/* - * Sizes of hash tables - * Should be a prime. Possible primes are - * 307, 401, 503, 601, 701, 809, 907, 1009, 1103, 1201, 1301, 1409, 1511. - * - * HSHSIZ1 symbol table 1st pass - * HSHSIZ2 symbol table 2nd pass - * THSHSIZ2 type table 2nd pass - */ -#define HSHSIZ1 503 -#define HSHSIZ2 1009 -#define THSHSIZ2 1009 - -/* - * Should be set to 1 if the difference of two pointers is of type long - * or the value of sizeof is of type unsigned long. - */ -#define PTRDIFF_IS_LONG 1 -#define SIZEOF_IS_ULONG 1 - -/* - * Make sure this matches wchar_t. - */ -#define WCHAR INT - -#if !defined(__GNUC__) && !defined(__PCC__) -#ifndef lint -#ifndef QUAD_MAX /* necessary for mkdep */ -#define QUAD_MAX LONG_MAX -#define QUAD_MIN LONG_MIN -#define UQUAD_MAX ULONG_MAX -#endif -typedef long quad_t; -typedef u_long u_quad_t; -#endif -#endif -typedef long double ldbl_t; - -/* - * Modern compilers are able to assign structures. - */ -#define STRUCT_ASSIGN(dest, src) (dest) = (src) diff --git a/usr.bin/xlint/lint1/scan.l b/usr.bin/xlint/lint1/scan.l deleted file mode 100644 index 7f9464ffd00..00000000000 --- a/usr.bin/xlint/lint1/scan.l +++ /dev/null @@ -1,1484 +0,0 @@ -%{ -/* $OpenBSD: scan.l,v 1.33 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: scan.l,v 1.8 1995/10/23 13:38:51 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <float.h> -#include <ctype.h> -#include <errno.h> -#include <math.h> -#include <err.h> - -#include "lint1.h" -#include "y.tab.h" - -#define CHAR_MASK (~(~0 << CHAR_BIT)) - -/* Current position (its also updated when an included file is parsed) */ -pos_t curr_pos = { 1, "" }; - -/* - * Current position in C source (not updated when an included file is - * parsed). - */ -pos_t csrc_pos = { 1, "" }; - -static void incline(void); -static void badchar(int); -static sbuf_t *allocsb(void); -static void freesb(sbuf_t *); -static int inpc(void); -static int hash(const char *); -static sym_t *search(sbuf_t *); -static int name(void); -static int keyw(sym_t *); -static int icon(int); -static int fcon(void); -static int fhexcon(void); -static int operator(int, op_t); -static int ccon(void); -static int wccon(void); -static int getescc(int); -static void directive(void); -static void comment(void); -static void slashslashcomment(void); -static int string(void); -static int wcstrg(void); - -%} - -L [_A-Za-z] -D [0-9] -NZD [1-9] -OD [0-7] -HD [0-9A-Fa-f] -EX ([eE][+-]?[0-9]+) -HEX ([pP][+-]?[0-9]+) -FSUFF ([fFlL][iIjJ]?|[iIjJ][fFlL]?)? - -%% - -{L}({L}|{D})* return (name()); -0{OD}*[lLuU]* return (icon(8)); -{NZD}{D}*[lLuU]* return (icon(10)); -0[xX]{HD}+[lLuU]* return (icon(16)); -{D}+\.{D}*{EX}?{FSUFF} | -{D}+{EX}{FSUFF} | -\.{D}+{EX}?{FSUFF} return (fcon()); -0[xX]{HD}+\.{HD}*{HEX}{FSUFF} | -0[xX]{HD}+{HEX}{FSUFF} | -0[xX]\.{HD}+{HEX}{FSUFF} return (fhexcon()); -"=" return (operator(T_ASSIGN, ASSIGN)); -"*=" return (operator(T_OPASS, MULASS)); -"/=" return (operator(T_OPASS, DIVASS)); -"%=" return (operator(T_OPASS, MODASS)); -"+=" return (operator(T_OPASS, ADDASS)); -"-=" return (operator(T_OPASS, SUBASS)); -"<<=" return (operator(T_OPASS, SHLASS)); -">>=" return (operator(T_OPASS, SHRASS)); -"&=" return (operator(T_OPASS, ANDASS)); -"^=" return (operator(T_OPASS, XORASS)); -"|=" return (operator(T_OPASS, ORASS)); -"||" return (operator(T_LOGOR, LOGOR)); -"&&" return (operator(T_LOGAND, LOGAND)); -"|" return (operator(T_OR, OR)); -"&" return (operator(T_AND, AND)); -"^" return (operator(T_XOR, XOR)); -"==" return (operator(T_EQOP, EQ)); -"!=" return (operator(T_EQOP, NE)); -"<" return (operator(T_RELOP, LT)); -">" return (operator(T_RELOP, GT)); -"<=" return (operator(T_RELOP, LE)); -">=" return (operator(T_RELOP, GE)); -"<<" return (operator(T_SHFTOP, SHL)); -">>" return (operator(T_SHFTOP, SHR)); -"++" return (operator(T_INCDEC, INC)); -"--" return (operator(T_INCDEC, DEC)); -"->" return (operator(T_STROP, ARROW)); -"." return (operator(T_STROP, POINT)); -"+" return (operator(T_ADDOP, PLUS)); -"-" return (operator(T_ADDOP, MINUS)); -"*" return (operator(T_MULT, MULT)); -"/" return (operator(T_DIVOP, DIV)); -"%" return (operator(T_DIVOP, MOD)); -"!" return (operator(T_UNOP, NOT)); -"~" return (operator(T_UNOP, COMPL)); -"\"" return (string()); -"L\"" return (wcstrg()); -";" return (T_SEMI); -"{" return (T_LBRACE); -"}" return (T_RBRACE); -"," return (T_COMMA); -":" return (T_COLON); -"?" return (T_QUEST); -"[" return (T_LBRACK); -"]" return (T_RBRACK); -"(" return (T_LPARN); -")" return (T_RPARN); -"..." return (T_ELLIPSE); -"'" return (ccon()); -"L'" return (wccon()); -^#.*$ directive(); -\n incline(); -\t|" "|\f|\v ; -"/*" comment(); -"//" slashslashcomment(); -. badchar(yytext[0]); - -%% - -static void -incline(void) -{ - curr_pos.p_line++; - if (curr_pos.p_file == csrc_pos.p_file) - csrc_pos.p_line++; -} - -static void -badchar(int c) -{ - /* unknown character \%o */ - error(250, c); -} - -/* - * Keywords. - * During initialisation they are written to the symbol table. - */ -static struct kwtab { - const char *kw_name; /* keyword */ - int kw_token; /* token returned by yylex() */ - union { - scl_t kw_scl; /* storage class if kw_token T_SCLASS */ - tspec_t kw_tspec; /* type spec. if kw_token T_TYPE or T_SOU */ - tqual_t kw_tqual; /* type qual. if kw_token T_QUAL */ - op_t kw_op; /* operator if kw_token T_UNOP */ - } kw_u; - u_int kw_stdc : 1; /* STDC keyword */ - u_int kw_gcc : 1; /* GCC keyword */ -} kwtab[] = { - { "asm", T_ASM, { 0 }, 0, 1 }, - { "__asm", T_ASM, { 0 }, 0, 0 }, - { "__asm__", T_ASM, { 0 }, 0, 0 }, - { "__attribute__", T_ATTRIBUTE, { 0 }, 0, 0 }, - { "auto", T_SCLASS, { AUTO }, 0, 0 }, - { "_Bool", T_TYPE, { BOOL }, 1, 0 }, - { "break", T_BREAK, { 0 }, 0, 0 }, - { "case", T_CASE, { 0 }, 0, 0 }, - { "char", T_TYPE, { CHAR }, 0, 0 }, - { "_Complex", T_TYPE, { COMPLEX }, 1, 0 }, - { "__complex__", T_TYPE, { COMPLEX }, 0, 1 }, - { "const", T_QUAL, { CONST }, 1, 0 }, - { "__const__", T_QUAL, { CONST }, 0, 0 }, - { "__const", T_QUAL, { CONST }, 0, 0 }, - { "continue", T_CONTINUE, { 0 }, 0, 0 }, - { "default", T_DEFAULT, { 0 }, 0, 0 }, - { "do", T_DO, { 0 }, 0, 0 }, - { "double", T_TYPE, { DOUBLE }, 0, 0 }, - { "else", T_ELSE, { 0 }, 0, 0 }, - { "enum", T_ENUM, { 0 }, 0, 0 }, - { "extern", T_SCLASS, { EXTERN }, 0, 0 }, - { "float", T_TYPE, { FLOAT }, 0, 0 }, - { "for", T_FOR, { 0 }, 0, 0 }, - { "goto", T_GOTO, { 0 }, 0, 0 }, - { "if", T_IF, { 0 }, 0, 0 }, - { "__imag__", T_UNOP, { IMAG }, 0, 0 /*1*/ }, -/* { "_Imaginary", T_TYPE, { IMAGINARY }, 1, 0 }, */ - { "inline", T_SCLASS, { INLINE }, 1, 0 }, - { "__inline__", T_SCLASS, { INLINE }, 0, 0 }, - { "__inline", T_SCLASS, { INLINE }, 0, 0 }, - { "int", T_TYPE, { INT }, 0, 0 }, - { "__lint_equal__", T_LEQUAL, { 0 }, 0, 0 }, - { "long", T_TYPE, { LONG }, 0, 0 }, - { "__real__", T_UNOP, { REAL }, 0, 0 /*1*/ }, - { "register", T_SCLASS, { REG }, 0, 0 }, - { "__restrict", T_QUAL, { RESTRICT }, 0, 0 }, - { "__restrict__", T_QUAL, { RESTRICT }, 0, 0 }, - { "return", T_RETURN, { 0 }, 0, 0 }, - { "short", T_TYPE, { SHORT }, 0, 0 }, - { "signed", T_TYPE, { SIGNED }, 1, 0 }, - { "__signed__", T_TYPE, { SIGNED }, 0, 0 }, - { "__signed", T_TYPE, { SIGNED }, 0, 0 }, - { "sizeof", T_SIZEOF, { 0 }, 0, 0 }, - { "static", T_SCLASS, { STATIC }, 0, 0 }, - { "struct", T_SOU, { STRUCT }, 0, 0 }, - { "switch", T_SWITCH, { 0 }, 0, 0 }, - { "typedef", T_SCLASS, { TYPEDEF }, 0, 0 }, - { "union", T_SOU, { UNION }, 0, 0 }, - { "unsigned", T_TYPE, { UNSIGN }, 0, 0 }, - { "void", T_TYPE, { VOID }, 0, 0 }, - { "volatile", T_QUAL, { VOLATILE }, 1, 0 }, - { "__volatile__", T_QUAL, { VOLATILE }, 0, 0 }, - { "__volatile", T_QUAL, { VOLATILE }, 0, 0 }, - { "while", T_WHILE, { 0 }, 0, 0 }, - { NULL, 0, { 0 }, 0, 0 } -}; - -#define kw_scl kw_u.kw_scl -#define kw_tspec kw_u.kw_tspec -#define kw_tqual kw_u.kw_tqual -#define kw_op kw_u.kw_op - -/* Symbol table */ -static sym_t *symtab[HSHSIZ1]; - -/* bit i of the entry with index i is set */ -u_quad_t qbmasks[sizeof(u_quad_t) * CHAR_BIT]; - -/* least significant i bits are set in the entry with index i */ -u_quad_t qlmasks[sizeof(u_quad_t) * CHAR_BIT + 1]; - -/* least significant i bits are not set in the entry with index i */ -u_quad_t qumasks[sizeof(u_quad_t) * CHAR_BIT + 1]; - -/* free list for sbuf structures */ -static sbuf_t *sbfrlst; - -/* type of next expected symbol */ -symt_t symtyp; - - -/* - * All keywords are written to the symbol table. This saves us looking - * in a extra table for each name we found. - */ -void -initscan(void) -{ - struct kwtab *kw; - sym_t *sym; - int h, i; - u_quad_t uq; - - for (kw = kwtab; kw->kw_name != NULL; kw++) { - if (kw->kw_gcc && !gflag) - continue; - sym = getblk(sizeof (sym_t)); - sym->s_name = kw->kw_name; - sym->s_keyw = 1; - sym->s_value.v_quad = kw->kw_token; - if (kw->kw_token == T_TYPE || kw->kw_token == T_SOU) { - sym->s_tspec = kw->kw_tspec; - } else if (kw->kw_token == T_SCLASS) { - sym->s_scl = kw->kw_scl; - } else if (kw->kw_token == T_QUAL) { - sym->s_tqual = kw->kw_tqual; - } else if (kw->kw_token == T_UNOP) { - sym->s_op = kw->kw_op; - } - h = hash(sym->s_name); - if ((sym->s_link = symtab[h]) != NULL) - symtab[h]->s_rlink = &sym->s_link; - (symtab[h] = sym)->s_rlink = &symtab[h]; - } - - /* initialize bit-masks for quads */ - for (i = 0; i < sizeof (u_quad_t) * CHAR_BIT; i++) { - qbmasks[i] = (u_quad_t)1 << i; - uq = ~(u_quad_t)0 << i; - qumasks[i] = uq; - qlmasks[i] = ~uq; - } - qumasks[i] = 0; - qlmasks[i] = ~(u_quad_t)0; -} - -/* - * Get a free sbuf structure, if possible from the free list - */ -static sbuf_t * -allocsb(void) -{ - sbuf_t *sb; - - if ((sb = sbfrlst) != NULL) { - sbfrlst = sb->sb_nxt; - } else { - sb = xmalloc(sizeof (sbuf_t)); - } - (void)memset(sb, 0, sizeof (sbuf_t)); - return (sb); -} - -/* - * Put a sbuf structure to the free list - */ -static void -freesb(sbuf_t *sb) -{ - sb->sb_nxt = sbfrlst; - sbfrlst = sb; -} - -/* - * Read a character and ensure that it is positive (except EOF). - * Increment line count(s) if necessary. - */ -static int -inpc(void) -{ - int c; - - if ((c = input()) != EOF && (c &= CHAR_MASK) == '\n') - incline(); - return (c); -} - -static int -hash(const char *s) -{ - u_int v; - const u_char *us; - - v = 0; - for (us = (const u_char *)s; *us != '\0'; us++) { - v = (v << sizeof (v)) + *us; - v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v)); - } - return (v % HSHSIZ1); -} - -/* - * Lex has found a letter followed by zero or more letters or digits. - * It looks for a symbol in the symbol table with the same name. This - * symbol must either be a keyword or a symbol of the type required by - * symtyp (label, member, tag, ...). - * - * If it is a keyword, the token is returned. In some cases it is described - * more deeply by data written to yylval. - * - * If it is a symbol, T_NAME is returned and the pointer to a sbuf struct - * is stored in yylval. This struct contains the name of the symbol, it's - * length and hash value. If there is already a symbol of the same name - * and type in the symbol table, the sbuf struct also contains a pointer - * to the symbol table entry. - */ -static int -name(void) -{ - char *s; - sbuf_t *sb; - sym_t *sym; - int tok; - - sb = allocsb(); - sb->sb_name = yytext; - sb->sb_len = yyleng; - sb->sb_hash = hash(yytext); - - if ((sym = search(sb)) != NULL && sym->s_keyw) { - freesb(sb); - return (keyw(sym)); - } - - sb->sb_sym = sym; - - if (sym != NULL) { - if (blklev < sym->s_blklev) - lerror("name() 1"); - sb->sb_name = sym->s_name; - sb->sb_len = strlen(sym->s_name); - tok = sym->s_scl == TYPEDEF ? T_TYPENAME : T_NAME; - } else { - s = getblk(yyleng + 1); - (void)memcpy(s, yytext, yyleng + 1); - sb->sb_name = s; - sb->sb_len = yyleng; - tok = T_NAME; - } - - yylval.y_sb = sb; - return (tok); -} - -static sym_t * -search(sbuf_t *sb) -{ - sym_t *sym; - - for (sym = symtab[sb->sb_hash]; sym != NULL; sym = sym->s_link) { - if (strcmp(sym->s_name, sb->sb_name) == 0) { - if (sym->s_keyw || sym->s_kind == symtyp) - return (sym); - } - } - - return (NULL); -} - -static int -keyw(sym_t *sym) -{ - int t; - - if ((t = (int)sym->s_value.v_quad) == T_SCLASS) { - yylval.y_scl = sym->s_scl; - } else if (t == T_TYPE || t == T_SOU) { - yylval.y_tspec = sym->s_tspec; - } else if (t == T_QUAL) { - yylval.y_tqual = sym->s_tqual; - } else if (t == T_UNOP) { - yylval.y_op = sym->s_op; - } - return (t); -} - -/* - * Convert a string representing an integer into internal representation. - * The value is returned in yylval. icon() (and yylex()) returns T_CON. - */ -static int -icon(int base) -{ - int l_suffix, u_suffix; - int len; - const char *cp; - char c, *eptr; - tspec_t typ; - u_long ul; - u_quad_t uq; - int ansiu; - static tspec_t contypes[2][3] = { - { INT, LONG, QUAD }, - { UINT, ULONG, UQUAD } - }; - - cp = yytext; - len = yyleng; - - /* skip 0x */ - if (base == 16) { - cp += 2; - len -= 2; - } - - /* read suffixes */ - l_suffix = u_suffix = 0; - for ( ; ; ) { - if ((c = cp[len - 1]) == 'l' || c == 'L') { - l_suffix++; - } else if (c == 'u' || c == 'U') { - u_suffix++; - } else { - break; - } - len--; - } - if (l_suffix > 2 || u_suffix > 1) { - /* malformed integer constant */ - warning(251); - if (l_suffix > 2) - l_suffix = 2; - if (u_suffix > 1) - u_suffix = 1; - } - typ = contypes[u_suffix][l_suffix]; - - errno = 0; - if (l_suffix < 2) { - ul = strtoul(cp, &eptr, base); - } else { - uq = strtouq(cp, &eptr, base); - } - if (eptr != cp + len) - lerror("icon() 1"); - if (errno != 0) - /* integer constant out of range */ - warning(252); - - /* - * If the value is too big for the current type, we must choose - * another type. - */ - ansiu = 0; - switch (typ) { - case INT: - if (ul <= INT_MAX) { - /* ok */ - } else if (ul <= (unsigned)UINT_MAX && base != 10) { - typ = UINT; - } else if (ul <= LONG_MAX) { - typ = LONG; - } else { - typ = ULONG; - } - if (typ == UINT || typ == ULONG) { - if (!sflag) { - /* - * Remember that the constant is unsigned - * only in ANSI C - */ - ansiu = 1; - } - } - break; - case UINT: - if (ul > (u_int)UINT_MAX) - typ = ULONG; - break; - case LONG: - if (ul > LONG_MAX) { - typ = ULONG; - if (!sflag) - ansiu = 1; - } - break; - case QUAD: - if (uq > QUAD_MAX) { - typ = UQUAD; - if (!sflag) - ansiu = 1; - } - break; - /* LINTED (enumeration values not handled in switch) */ - } - - if (typ != QUAD && typ != UQUAD) { - if (isutyp(typ)) { - uq = ul; - } else { - uq = (quad_t)(long)ul; - } - } - - uq = (u_quad_t)xsign((quad_t)uq, typ, -1); - - (yylval.y_val = xcalloc(1, sizeof (val_t)))->v_tspec = typ; - yylval.y_val->v_ansiu = ansiu; - yylval.y_val->v_quad = (quad_t)uq; - - return (T_CON); -} - -/* - * Returns 1 if t is a signed type and the value is negative. - * - * len is the number of significant bits. If len is -1, len is set - * to the width of type t. - */ -int -sign(quad_t q, tspec_t t, int len) -{ - if (t == PTR || isutyp(t)) - return (0); - return (msb(q, t, len)); -} - -int -msb(quad_t q, tspec_t t, int len) -{ - if (len <= 0) - len = size(t); - return ((q & qbmasks[len - 1]) != 0); -} - -/* - * Extends the sign of q. - */ -quad_t -xsign(quad_t q, tspec_t t, int len) -{ - if (len <= 0) - len = size(t); - - if (t == PTR || isutyp(t) || !sign(q, t, len)) { - q &= qlmasks[len]; - } else { - q |= qumasks[len]; - } - return (q); -} - -/* - * Convert a string representing a floating point value into its integral - * representation. Type and value are returned in yylval. fcon() - * (and yylex()) returns T_CON. - * XXX Currently it is not possible to convert constants of type - * long double which are greater then DBL_MAX. - */ -static int -fcon(void) -{ - const char *cp; - int len; - tspec_t typ; - tspec_t domain = NOTSPEC; - char c, *eptr; - double d; - float f; - - cp = yytext; - len = yyleng; - - c = cp[len - 1]; - if (c == 'i' || c == 'I' || c == 'j' || c == 'J') { - domain = COMPLEX; /* XXX should be IMAGINARY */ - len--; - c = cp[len - 1]; - } - if (c == 'f' || c == 'F') { - typ = FLOAT; - len--; - c = cp[len - 1]; - } else if (c == 'l' || c == 'L') { - typ = LDOUBLE; - len--; - c = cp[len - 1]; - } else { - typ = DOUBLE; - } - if (c == 'i' || c == 'I' || c == 'j' || c == 'J') { - if (domain != NOTSPEC) - lerror("fcon() 2"); /* can't happen */ - domain = COMPLEX; /* XXX should be IMAGINARY */ - len--; - } - - errno = 0; - d = strtod(cp, &eptr); - if (eptr != cp + len) - lerror("fcon() 1"); - if (errno != 0) - /* floating-point constant out of range */ - warning(248); - - if (typ == FLOAT) { - f = (float)d; - if (isinf(f)) { - /* floating-point constant out of range */ - warning(248); - f = f > 0 ? FLT_MAX : -FLT_MAX; - } - } - - yylval.y_val = xcalloc(1, sizeof (val_t)); - if (typ == FLOAT) { - yylval.y_val->v_ldbl = f; - } else { - yylval.y_val->v_ldbl = d; - } - if (mergedomain(&typ, domain)) - lerror("fcon() 3"); - yylval.y_val->v_tspec = typ; - - return (T_CON); -} - -/* - * Convert an hexadecimal representation of a floating point value - * into its integral representation. - * Type and value are returned in yylval. fhexcon() - * (and yylex()) returns T_CON. - * XXX Currently no actual values are parsed. - */ -static int -fhexcon(void) -{ - const char *cp; - int len; - tspec_t typ; - tspec_t domain = NOTSPEC; - char c; - double d; - float f; - - cp = yytext; - len = yyleng; - - c = cp[len - 1]; - if (c == 'i' || c == 'I' || c == 'j' || c == 'J') { - domain = COMPLEX; /* XXX should be IMAGINARY */ - len--; - c = cp[len - 1]; - } - if (c == 'f' || c == 'F') { - typ = FLOAT; - len--; - c = cp[len - 1]; - } else if (c == 'l' || c == 'L') { - typ = LDOUBLE; - len--; - c = cp[len - 1]; - } else { - typ = DOUBLE; - } - if (c == 'i' || c == 'I' || c == 'j' || c == 'J') { - if (domain != NOTSPEC) - lerror("fhexcon() 1"); /* can't happen */ - domain = COMPLEX; /* XXX should be IMAGINARY */ - len--; - } - - /* arbitrary value, until strtod can cope */ - d = 1.0; - - if (typ == FLOAT) { - f = (float)d; - } - - yylval.y_val = xcalloc(1, sizeof (val_t)); - if (typ == FLOAT) { - yylval.y_val->v_ldbl = f; - } else { - yylval.y_val->v_ldbl = d; - } - if (mergedomain(&typ, domain)) - lerror("fhexcon() 2"); - yylval.y_val->v_tspec = typ; - - return (T_CON); -} - -static int -operator(int t, op_t o) -{ - yylval.y_op = o; - return (t); -} - -/* - * Called if lex found a leading '. - */ -static int -ccon(void) -{ - int n, val, c; - char cv; - - n = 0; - val = 0; - while ((c = getescc('\'')) >= 0) { - val = (val << CHAR_BIT) + c; - n++; - } - if (c == -2) { - /* unterminated character constant */ - error(253); - } else { - if (n > sizeof (int) || (n > 1 && (pflag || hflag))) { - /* too many characters in character constant */ - error(71); - } else if (n > 1) { - /* multi-character character constant */ - warning(294); - } else if (n == 0) { - /* empty character constant */ - error(73); - } - } - if (n == 1) { - cv = (char)val; - val = cv; - } - - yylval.y_val = xcalloc(1, sizeof (val_t)); - yylval.y_val->v_tspec = INT; - yylval.y_val->v_lspec = CHAR; - yylval.y_val->v_quad = val; - - return (T_CON); -} - -/* - * Called if lex found a leading L\' - */ -static int -wccon(void) -{ - static char buf[MB_LEN_MAX + 1]; - int i, c; - wchar_t wc; - - i = 0; - while ((c = getescc('\'')) >= 0) { - if (i < MB_CUR_MAX) - buf[i] = (char)c; - i++; - } - - wc = 0; - - if (c == -2) { - /* unterminated character constant */ - error(253); - } else if (c == 0) { - /* empty character constant */ - error(73); - } else { - if (i > MB_CUR_MAX) { - i = MB_CUR_MAX; - /* too many characters in character constant */ - error(71); - } else { - buf[i] = '\0'; - (void)mbtowc(NULL, NULL, 0); - if (mbtowc(&wc, buf, MB_CUR_MAX) < 0) - /* invalid multibyte character */ - error(291); - } - } - - yylval.y_val = xcalloc(1, sizeof (val_t)); - yylval.y_val->v_tspec = WCHAR; - yylval.y_val->v_quad = wc; - - return (T_CON); -} - -/* - * Read a character which is part of a character constant or of a string - * and handle escapes. - * - * The Argument is the character which delimits the character constant or - * string. - * - * Returns -1 if the end of the character constant or string is reached, - * -2 if the EOF is reached, and the charachter otherwise. - */ -static int -getescc(int d) -{ - static int pbc = -1; - int n, c, v; - - if (pbc == -1) { - c = inpc(); - } else { - c = pbc; - pbc = -1; - } - if (c == d) - return (-1); - switch (c) { - case '\n': - /* newline in string or char constant */ - error(254); - return (-2); - case EOF: - return (-2); - case '\\': - switch (c = inpc()) { - case '"': - return ('"'); - case '\'': - return ('\''); - case '?': - return ('?'); - case '\\': - return ('\\'); - case 'a': - return ('\a'); - case 'b': - return ('\b'); - case 'f': - return ('\f'); - case 'n': - return ('\n'); - case 'r': - return ('\r'); - case 't': - return ('\t'); - case 'v': - return ('\v'); - case '8': case '9': - /* bad octal digit %c */ - warning(77, c); - /* FALLTHROUGH */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - n = 3; - v = 0; - do { - v = (v << 3) + (c - '0'); - c = inpc(); - } while (--n && isdigit(c) && (c <= '7')); - pbc = c; - if (v > UCHAR_MAX) { - /* character escape does not fit in char. */ - warning(76); - v &= CHAR_MASK; - } - return (v); - case 'x': - v = 0; - n = 0; - while ((c = inpc()) >= 0 && isxdigit(c)) { - c = isdigit(c) ? - c - '0' : toupper(c) - 'A' + 10; - v = (v << 4) + c; - if (n >= 0) { - if ((v & ~CHAR_MASK) != 0) { - /* overflow in hex escape */ - warning(75); - n = -1; - } else { - n++; - } - } - } - pbc = c; - if (n == 0) { - /* no hex digits follow \x */ - error(74); - } if (n == -1) { - v &= CHAR_MASK; - } - return (v); - case '\n': - return (getescc(d)); - case EOF: - return (-2); - default: - if (isprint(c)) { - /* dubious escape \%c */ - warning(79, c); - } else { - /* dubious escape \%o */ - warning(80, c); - } - } - } - return (c); -} - -/* - * Called for preprocessor directives. Currently implemented are: - * # lineno - * # lineno "filename" - */ -static void -directive(void) -{ - const char *cp, *fn; - char c, *eptr; - size_t fnl; - long ln; - static int first = 1; - - /* Go to first non-whitespace after # */ - for (cp = yytext + 1; (c = *cp) == ' ' || c == '\t'; cp++) ; - - if (!isdigit(c)) { - error: - /* undefined or invalid # directive */ - warning(255); - return; - } - ln = strtol(--cp, &eptr, 10); - if (cp == eptr) - goto error; - if ((c = *(cp = eptr)) != ' ' && c != '\t' && c != '\0') - goto error; - while ((c = *cp++) == ' ' || c == '\t') ; - if (c != '\0') { - if (c != '"') - goto error; - fn = cp; - while ((c = *cp) != '"' && c != '\0') - cp++; - if (c != '"') - goto error; - if ((fnl = cp++ - fn) > PATH_MAX) - goto error; - while ((c = *cp++) == ' ' || c == '\t') ; -#if 0 - if (c != '\0') - warning("extra character(s) after directive"); -#endif - curr_pos.p_file = fnnalloc(fn, fnl); - /* - * If this is the first directive, the name is the name - * of the C source file as specified at the command line. - * It is written to the output file. - */ - if (first) { - csrc_pos.p_file = curr_pos.p_file; - outsrc(curr_pos.p_file); - first = 0; - } - } - curr_pos.p_line = (int)ln - 1; - if (curr_pos.p_file == csrc_pos.p_file) - csrc_pos.p_line = (int)ln - 1; -} - -/* - * Handle lint comments. Following comments are currently understood: - * ARGSUSEDn - * CONSTCOND CONSTANTCOND CONSTANTCONDITION - * FALLTHRU FALLTHROUGH - * LINTLIBRARY - * LINTED NOSTRICT - * LONGLONG - * NORETURN - * NOTREACHED - * PRINTFLIKEn - * PROTOLIB - * SCANFLIKEn - * VARARGSn - * If one of this comments is recognized, the arguments, if any, are - * parsed and a function which handles this comment is called. - */ -static void -comment(void) -{ - int c, lc; - static struct { - const char *keywd; - int arg; - void (*func)(int); - } keywtab[] = { - { "ARGSUSED", 1, argsused }, - { "CONSTCOND", 0, constcond }, - { "CONSTANTCOND", 0, constcond }, - { "CONSTANTCONDITION", 0, constcond }, - { "FALLTHRU", 0, fallthru }, - { "FALLTHROUGH", 0, fallthru }, - { "LINTLIBRARY", 0, lintlib }, - { "LINTED", 0, linted }, - { "LINTUSED", 0, lintused }, - { "LONGLONG", 0, longlong }, - { "NORETURN", 1, noreturn }, - { "NOSTRICT", 0, linted }, - { "NOTREACHED", 0, notreach }, - { "PRINTFLIKE", 1, printflike }, - { "PROTOLIB", 1, protolib }, - { "SCANFLIKE", 1, scanflike }, - { "VARARGS", 1, varargs }, - }; - char keywd[32]; - char arg[32]; - int l, i, a; - int eoc; - - eoc = 0; - - /* Skip white spaces after the start of the comment */ - while ((c = inpc()) != EOF && isspace(c)) ; - - /* Read the potential keyword to keywd */ - l = 0; - while (c != EOF && isupper(c) && l < sizeof (keywd) - 1) { - keywd[l++] = (char)c; - c = inpc(); - } - keywd[l] = '\0'; - - /* look for the keyword */ - for (i = 0; i < sizeof (keywtab) / sizeof (keywtab[0]); i++) { - if (strcmp(keywtab[i].keywd, keywd) == 0) - break; - } - if (i == sizeof (keywtab) / sizeof (keywtab[0])) - goto skip_rest; - - /* skip white spaces after the keyword */ - while (c != EOF && isspace(c)) - c = inpc(); - - /* read the argument, if the keyword accepts one and there is one */ - l = 0; - if (keywtab[i].arg) { - while (c != EOF && isdigit(c) && l < sizeof (arg) - 1) { - arg[l++] = (char)c; - c = inpc(); - } - } - arg[l] = '\0'; - a = l != 0 ? atoi(arg) : -1; - - /* skip white spaces after the argument */ - while (c != EOF && isspace(c)) - c = inpc(); - - if (c != '*' || (c = inpc()) != '/') { - if (keywtab[i].func != linted) - /* extra characters in lint comment */ - warning(257); - } else { - /* - * remember that we have already found the end of the - * comment - */ - eoc = 1; - } - - if (keywtab[i].func != NULL) - (*keywtab[i].func)(a); - - skip_rest: - while (!eoc) { - lc = c; - if ((c = inpc()) == EOF) { - /* unterminated comment */ - error(256); - break; - } - if (lc == '*' && c == '/') - eoc = 1; - } -} - -/* - * Handle // style comments, which are valid in C99. - */ -static void -slashslashcomment(void) -{ - int c; - - while ((c = inpc()) != EOF && c != '\n'); -} - -/* - * Clear flags for lint comments LINTED, LONGLONG and CONSTCOND. - * clrwflgs() is called after function definitions and global and - * local declarations and definitions. It is also called between - * the controlling expression and the body of control statements - * (if, switch, for, while). - */ -void -clrwflgs(void) -{ - nowarn = 0; - quadflg = 1; - ccflg = 0; - usedflg = 0; -} - -/* - * Strings are stored in a dynamically alloceted buffer and passed - * in yylval.y_xstrg to the parser. The parser or the routines called - * by the parser are responsible for freeing this buffer. - */ -static int -string(void) -{ - u_char *s; - int c; - size_t len, max; - strg_t *strg; - - s = xmalloc(max = 64); - - len = 0; - while ((c = getescc('"')) >= 0) { - /* +1 to reserve space for a trailing NUL character */ - if (len + 1 == max) - s = xrealloc(s, max *= 2); - s[len++] = (char)c; - } - s[len] = '\0'; - if (c == -2) - /* unterminated string constant */ - error(258); - - strg = xcalloc(1, sizeof (strg_t)); - strg->st_tspec = CHAR; - strg->st_len = len; - strg->st_cp = s; - - yylval.y_strg = strg; - return (T_STRING); -} - -static int -wcstrg(void) -{ - char *s; - int c, i, n, wi; - size_t len, max, wlen; - wchar_t *ws; - strg_t *strg; - - s = xmalloc(max = 64); - len = 0; - while ((c = getescc('"')) >= 0) { - /* +1 to save space for a trailing NUL character */ - if (len + 1 >= max) - s = xrealloc(s, max *= 2); - s[len++] = (char)c; - } - s[len] = '\0'; - if (c == -2) - /* unterminated string constant */ - error(258); - - /* get length of wide character string */ - (void)mblen(NULL, 0); - for (i = 0, wlen = 0; i < len; i += n, wlen++) { - if ((n = mblen(&s[i], MB_CUR_MAX)) == -1) { - /* invalid multibyte character */ - error(291); - break; - } - if (n == 0) - n = 1; - } - - ws = xmalloc((wlen + 1) * sizeof (wchar_t)); - - /* convert from multibyte to wide char */ - (void)mbtowc(NULL, NULL, 0); - for (i = 0, wi = 0; i < len; i += n, wi++) { - if ((n = mbtowc(&ws[wi], &s[i], MB_CUR_MAX)) == -1) - break; - if (n == 0) - n = 1; - } - ws[wi] = 0; - free(s); - - strg = xcalloc(1, sizeof (strg_t)); - strg->st_tspec = WCHAR; - strg->st_len = wlen; - strg->st_wcp = ws; - - yylval.y_strg = strg; - return (T_STRING); -} - -/* - * As noted above the scanner does not create new symbol table entries - * for symbols it cannot find in the symbol table. This is to avoid - * putting undeclared symbols into the symbol table if a syntax error - * occurs. - * - * getsym() is called as soon as it is probably ok to put the symbol to - * the symbol table. This does not mean that it is not possible that - * symbols are put to the symbol table which are than not completely - * declared due to syntax errors. To avoid too many problems in this - * case symbols get type int in getsym(). - * - * XXX calls to getsym() should be delayed until decl1*() is called - */ -sym_t * -getsym(sbuf_t *sb) -{ - dinfo_t *di; - char *s; - sym_t *sym; - - sym = sb->sb_sym; - - /* - * During member declaration it is possible that name() looked - * for symbols of type FVFT, although it should have looked for - * symbols of type FTAG. Same can happen for labels. Both cases - * are compensated here. - */ - if (symtyp == FMOS || symtyp == FLAB) { - if (sym == NULL || sym->s_kind == FVFT) - sym = search(sb); - } - - if (sym != NULL) { - if (sym->s_kind != symtyp) - lerror("storesym() 1"); - symtyp = FVFT; - freesb(sb); - return (sym); - } - - /* create a new symbol table entry */ - - /* labels must always be allocated at level 1 (outhermost block) */ - if (symtyp == FLAB) { - sym = getlblk(1, sizeof (sym_t)); - s = getlblk(1, sb->sb_len + 1); - (void)memcpy(s, sb->sb_name, sb->sb_len + 1); - sym->s_name = s; - sym->s_blklev = 1; - di = dcs; - while (di->d_nxt != NULL && di->d_nxt->d_nxt != NULL) - di = di->d_nxt; - if (di->d_ctx != AUTO) - lerror("storesym() 2"); - } else { - sym = getblk(sizeof (sym_t)); - sym->s_name = sb->sb_name; - sym->s_blklev = blklev; - di = dcs; - } - - STRUCT_ASSIGN(sym->s_dpos, curr_pos); - if ((sym->s_kind = symtyp) != FLAB) - sym->s_type = gettyp(INT); - - symtyp = FVFT; - - if ((sym->s_link = symtab[sb->sb_hash]) != NULL) - symtab[sb->sb_hash]->s_rlink = &sym->s_link; - (symtab[sb->sb_hash] = sym)->s_rlink = &symtab[sb->sb_hash]; - - *di->d_ldlsym = sym; - di->d_ldlsym = &sym->s_dlnxt; - - freesb(sb); - return (sym); -} - -/* - * Remove a symbol forever from the symbol table. s_blklev - * is set to -1 to avoid that the symbol will later be put - * back to the symbol table. - */ -void -rmsym(sym_t *sym) -{ - if ((*sym->s_rlink = sym->s_link) != NULL) - sym->s_link->s_rlink = sym->s_rlink; - sym->s_blklev = -1; - sym->s_link = NULL; -} - -/* - * Remove a list of symbols declared at one level from the symbol - * table. - */ -void -rmsyms(sym_t *syms) -{ - sym_t *sym; - - for (sym = syms; sym != NULL; sym = sym->s_dlnxt) { - if (sym->s_blklev != -1) { - if ((*sym->s_rlink = sym->s_link) != NULL) - sym->s_link->s_rlink = sym->s_rlink; - sym->s_link = NULL; - sym->s_rlink = NULL; - } - } -} - -/* - * Put a symbol into the symbol table - */ -void -inssym(int bl, sym_t *sym) -{ - int h; - - h = hash(sym->s_name); - if ((sym->s_link = symtab[h]) != NULL) - symtab[h]->s_rlink = &sym->s_link; - (symtab[h] = sym)->s_rlink = &symtab[h]; - sym->s_blklev = bl; - if (sym->s_link != NULL && sym->s_blklev < sym->s_link->s_blklev) - lerror("inssym()"); -} - -/* - * Called at level 0 after syntax errors - * Removes all symbols which are not declared at level 0 from the - * symbol table. Also frees all memory which is not associated with - * level 0. - */ -void -cleanup(void) -{ - sym_t *sym, *nsym; - int i; - - for (i = 0; i < HSHSIZ1; i++) { - for (sym = symtab[i]; sym != NULL; sym = nsym) { - nsym = sym->s_link; - if (sym->s_blklev >= 1) { - if ((*sym->s_rlink = nsym) != NULL) - nsym->s_rlink = sym->s_rlink; - } - } - } - - for (i = mblklev; i > 0; i--) - freelblk(i); -} - -/* - * Create a new symbol with the name of an existing symbol. - */ -sym_t * -pushdown(sym_t *sym) -{ - int h; - sym_t *nsym; - - h = hash(sym->s_name); - nsym = getblk(sizeof (sym_t)); - if (sym->s_blklev > blklev) - lerror("pushdown()"); - nsym->s_name = sym->s_name; - STRUCT_ASSIGN(nsym->s_dpos, curr_pos); - nsym->s_kind = sym->s_kind; - nsym->s_blklev = blklev; - - if ((nsym->s_link = symtab[h]) != NULL) - symtab[h]->s_rlink = &nsym->s_link; - (symtab[h] = nsym)->s_rlink = &symtab[h]; - - *dcs->d_ldlsym = nsym; - dcs->d_ldlsym = &nsym->s_dlnxt; - - return (nsym); -} - -/* - * Free any dynamically allocated memory referenced by - * the value stack or yylval. - * The type of information in yylval is described by tok. - */ -void -freeyyv(void *sp, int tok) -{ - if (tok == T_NAME || tok == T_TYPENAME) { - sbuf_t *sb = *(sbuf_t **)sp; - freesb(sb); - } else if (tok == T_CON) { - val_t *val = *(val_t **)sp; - free(val); - } else if (tok == T_STRING) { - strg_t *strg = *(strg_t **)sp; - if (strg->st_tspec == CHAR) { - free(strg->st_cp); - } else if (strg->st_tspec == WCHAR) { - free(strg->st_wcp); - } else { - lerror("fryylv() 1"); - } - free(strg); - } -} diff --git a/usr.bin/xlint/lint1/tree.c b/usr.bin/xlint/lint1/tree.c deleted file mode 100644 index ce6a1e20941..00000000000 --- a/usr.bin/xlint/lint1/tree.c +++ /dev/null @@ -1,3966 +0,0 @@ -/* $OpenBSD: tree.c,v 1.48 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: tree.c,v 1.12 1995/10/02 17:37:57 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <string.h> -#include <float.h> -#include <limits.h> -#include <math.h> - -#include "lint1.h" -#include "y.tab.h" - -/* Various flags for each operator. */ -static mod_t modtab[NOPS]; - -static tnode_t *getinode(tspec_t, quad_t); -static void ptrcmpok(op_t, tnode_t *, tnode_t *); -static int asgntypok(op_t, farg_t *, tnode_t *, tnode_t *); -static void chkbeop(op_t, tnode_t *, tnode_t *); -static void chkeop2(op_t, farg_t *, tnode_t *, tnode_t *); -static void chkeop1(op_t, farg_t *, tnode_t *, tnode_t *); -static tnode_t *mktnode(op_t, type_t *, tnode_t *, tnode_t *); -static void balance(op_t, tnode_t **, tnode_t **); -static void incompat(op_t, tspec_t, tspec_t); -static void illptrc(mod_t *, type_t *, type_t *); -static void mrgqual(type_t **, type_t *, type_t *); -static int conmemb(type_t *); -static tspec_t fcnconv(farg_t *, tspec_t, tspec_t, type_t *, tnode_t *); -static void iiconv(op_t, farg_t *, tspec_t, tspec_t, type_t *, tnode_t *); -static void piconv(op_t, tspec_t, type_t *, tnode_t *); -static void ppconv(op_t, tnode_t *, type_t *); -static tnode_t *bldstr(op_t, tnode_t *, tnode_t *); -static tnode_t *bldincdec(op_t, tnode_t *); -static tnode_t *bldamper(tnode_t *, int); -static tnode_t *bldplmi(op_t, tnode_t *, tnode_t *); -static tnode_t *bldshft(op_t, tnode_t *, tnode_t *); -static tnode_t *bldcol(tnode_t *, tnode_t *); -static tnode_t *bldasgn(op_t, tnode_t *, tnode_t *); -static tnode_t *plength(type_t *); -static tnode_t *fold(tnode_t *); -static tnode_t *foldtst(tnode_t *); -static tnode_t *foldflt(tnode_t *); -static tnode_t *chkfarg(tnode_t *, tnode_t *); -static tnode_t *parg(farg_t *, tnode_t *); -static int chkdbz(op_t, tnode_t *); -static void nulleff(tnode_t *); -static int nulleffexpr(tnode_t *); -static void chkaidx(tnode_t *, int); -static void chkcomp(op_t, tnode_t *, tnode_t *); -static void precconf(tnode_t *); -static const char *funcname(tnode_t *); - -/* - * Initialize mods of operators. - */ -void -initmtab(void) -{ - static struct { - op_t op; - mod_t m; - } imods[] = { - { ARROW, { 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, - "->" } }, - { POINT, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "." } }, - { NOT, { 0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,1,0, - "!" } }, - { COMPL, { 0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1, - "~" } }, - { INCBEF, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "prefix++" } }, - { DECBEF, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "prefix--" } }, - { INCAFT, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "postfix++" } }, - { DECAFT, { 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "postfix--" } }, - { UPLUS, { 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1, - "unary +" } }, - { UMINUS, { 0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,1,1, - "unary -" } }, - { STAR, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, - "unary *" } }, - { AMPER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "unary &" } }, - { MULT, { 1,0,0,0,1,1,1,0,1,0,0,1,0,0,0,1,1, - "*" } }, - { DIV, { 1,0,0,0,1,1,1,0,1,0,1,1,0,0,0,1,1, - "/" } }, - { MOD, { 1,0,1,0,0,1,1,0,1,0,1,1,0,0,0,1,1, - "%" } }, - { PLUS, { 1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0, - "+" } }, - { MINUS, { 1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0, - "-" } }, - { SHL, { 1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,1, - "<<" } }, - { SHR, { 1,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,1, - ">>" } }, - { LT, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, - "<" } }, - { LE, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, - "<=" } }, - { GT, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, - ">" } }, - { GE, { 1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1, - ">=" } }, - { EQ, { 1,1,0,1,0,1,1,0,1,0,0,0,0,1,1,0,0, - "==" } }, - { NE, { 1,1,0,1,0,1,1,0,1,0,0,0,0,1,1,0,1, - "!=" } }, - { AND, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, - "&" } }, - { XOR, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, - "^" } }, - { OR, { 1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0, - "|" } }, - { LOGAND, { 1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,1,0, - "&&" } }, - { LOGOR, { 1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,1,0, - "||" } }, - { QUEST, { 1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, - "?" } }, - { COLON, { 1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0, - ":" } }, - { ASSIGN, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, - "=" } }, - { MULASS, { 1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0, - "*=" } }, - { DIVASS, { 1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0, - "/=" } }, - { MODASS, { 1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0, - "%=" } }, - { ADDASS, { 1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "+=" } }, - { SUBASS, { 1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0, - "-=" } }, - { SHLASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - "<<=" } }, - { SHRASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - ">>=" } }, - { ANDASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - "&=" } }, - { XORASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - "^=" } }, - { ORASS, { 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0, - "|=" } }, - { NAME, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "NAME" } }, - { CON, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "CON" } }, - { STRING, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "STRING" } }, - { FSEL, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "FSEL" } }, - { CALL, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, - "CALL" } }, - { COMMA, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, - "," } }, - { CVT, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, - "CVT" } }, - { ICALL, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, - "ICALL" } }, - { LOAD, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - "LOAD" } }, - { PUSH, { 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, - "PUSH" } }, - { RETURN, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, - "RETURN" } }, - { REAL, { 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1, - "__real__" } }, - { IMAG, { 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1, - "__imag__" } }, - { INIT, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - "INIT" } }, - { FARG, { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - "FARG" } }, - { NOOP } - }; - int i; - - for (i = 0; imods[i].op != NOOP; i++) - STRUCT_ASSIGN(modtab[imods[i].op], imods[i].m); -} - -/* - * Increase degree of reference. - * This is most often used to change type "T" in type "pointer to T". - */ -type_t * -incref(type_t *tp, tspec_t t) -{ - type_t *tp2; - - tp2 = getblk(sizeof (type_t)); - tp2->t_tspec = t; - tp2->t_subt = tp; - return (tp2); -} - -/* - * same for use in expressions - */ -type_t * -tincref(type_t *tp, tspec_t t) -{ - type_t *tp2; - - tp2 = tgetblk(sizeof (type_t)); - tp2->t_tspec = t; - tp2->t_subt = tp; - return (tp2); -} - -/* - * Create a node for a constant. - */ -tnode_t * -getcnode(type_t *tp, val_t *v) -{ - tnode_t *n; - - n = getnode(); - n->tn_op = CON; - n->tn_type = tp; - n->tn_val = tgetblk(sizeof (val_t)); - n->tn_val->v_tspec = tp->t_tspec; - n->tn_val->v_lspec = v->v_lspec; - n->tn_val->v_ansiu = v->v_ansiu; - n->tn_val->v_u = v->v_u; - free(v); - return (n); -} - -/* - * Create a node for a integer constant. - */ -static tnode_t * -getinode(tspec_t t, quad_t q) -{ - tnode_t *n; - - n = getnode(); - n->tn_op = CON; - n->tn_type = gettyp(t); - n->tn_val = tgetblk(sizeof (val_t)); - n->tn_val->v_tspec = t; - n->tn_val->v_quad = q; - return (n); -} - -/* - * Create a node for a name (symbol table entry). - * ntok is the token which follows the name. - */ -tnode_t * -getnnode(sym_t *sym, int ntok) -{ - tnode_t *n; - - if (sym->s_scl == NOSCL) { - sym->s_scl = EXTERN; - sym->s_def = DECL; - if (ntok == T_LPARN) { - if (sflag) { - /* function implicitly declared to ... */ - warning(215); - } - sym->s_type = incref(sym->s_type, FUNC); - } else { - /* %s undefined */ - error(99, sym->s_name); - } - } - - if (sym->s_kind != FVFT && sym->s_kind != FMOS) - lerror("getnnode() 1"); - - n = getnode(); - n->tn_type = sym->s_type; - if (sym->s_scl != ENUMCON) { - n->tn_op = NAME; - n->tn_sym = sym; - if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) - n->tn_lvalue = 1; - } else { - n->tn_op = CON; - n->tn_val = tgetblk(sizeof (val_t)); - *n->tn_val = sym->s_value; - } - - return (n); -} - -/* - * Create a node for a string. - */ -tnode_t * -getsnode(strg_t *strg) -{ - size_t len; - tnode_t *n; - - len = strg->st_len; - - n = getnode(); - - n->tn_op = STRING; - n->tn_type = tincref(gettyp(strg->st_tspec), ARRAY); - n->tn_type->t_dim = len + 1; - n->tn_lvalue = 1; - - n->tn_strg = tgetblk(sizeof (strg_t)); - n->tn_strg->st_tspec = strg->st_tspec; - n->tn_strg->st_len = len; - - if (strg->st_tspec == CHAR) { - n->tn_strg->st_cp = tgetblk(len + 1); - (void)memcpy(n->tn_strg->st_cp, strg->st_cp, len + 1); - free(strg->st_cp); - } else { - n->tn_strg->st_wcp = tgetblk((len + 1) * sizeof (wchar_t)); - (void)memcpy(n->tn_strg->st_wcp, strg->st_wcp, - (len + 1) * sizeof (wchar_t)); - free(strg->st_wcp); - } - free(strg); - - return (n); -} - -/* - * Returns a symbol which has the same name as the msym argument and is a - * member of the struct or union specified by the tn argument. - */ -sym_t * -strmemb(tnode_t *tn, op_t op, sym_t *msym) -{ - str_t *str; - type_t *tp; - sym_t *sym, *csym; - int eq; - tspec_t t; - - /* - * Remove the member if it was unknown until now (Which means - * that no defined struct or union has a member with the same name). - */ - if (msym->s_scl == NOSCL) { - /* undefined struct/union member: %s */ - error(101, msym->s_name); - rmsym(msym); - msym->s_kind = FMOS; - msym->s_scl = MOS; - msym->s_styp = tgetblk(sizeof (str_t)); - msym->s_styp->stag = tgetblk(sizeof (sym_t)); - msym->s_styp->stag->s_name = unnamed; - msym->s_value.v_tspec = INT; - return (msym); - } - - /* Set str to the tag of which msym is expected to be a member. */ - str = NULL; - t = (tp = tn->tn_type)->t_tspec; - if (op == POINT) { - if (t == STRUCT || t == UNION) - str = tp->t_str; - } else if (op == ARROW && t == PTR) { - t = (tp = tp->t_subt)->t_tspec; - if (t == STRUCT || t == UNION) - str = tp->t_str; - } - - /* - * If this struct/union has a member with the name of msym, return - * return this it. - */ - if (str != NULL) { - for (sym = msym; sym != NULL; sym = sym->s_link) { - if (sym->s_scl != MOS && sym->s_scl != MOU) - continue; - if (sym->s_styp != str) - continue; - if (strcmp(sym->s_name, msym->s_name) != 0) - continue; - return (sym); - } - } - - /* - * Set eq to 0 if there are struct/union members with the same name - * and different types and/or offsets. - */ - eq = 1; - for (csym = msym; csym != NULL; csym = csym->s_link) { - if (csym->s_scl != MOS && csym->s_scl != MOU) - continue; - if (strcmp(msym->s_name, csym->s_name) != 0) - continue; - for (sym = csym->s_link ; sym != NULL; sym = sym->s_link) { - int w; - - if (sym->s_scl != MOS && sym->s_scl != MOU) - continue; - if (strcmp(csym->s_name, sym->s_name) != 0) - continue; - if (csym->s_value.v_quad != sym->s_value.v_quad) { - eq = 0; - break; - } - w = 0; - eq = eqtype(csym->s_type, sym->s_type, 0, 0, &w) && !w; - if (!eq) - break; - if (csym->s_field != sym->s_field) { - eq = 0; - break; - } - if (csym->s_field) { - type_t *tp1, *tp2; - - tp1 = csym->s_type; - tp2 = sym->s_type; - if (tp1->t_flen != tp2->t_flen) { - eq = 0; - break; - } - if (tp1->t_foffs != tp2->t_foffs) { - eq = 0; - break; - } - } - } - if (!eq) - break; - } - - /* - * Now handle the case in which the left operand refers really - * to a struct/union, but the right operand is not member of it. - */ - if (str != NULL) { - /* illegal member use: %s */ - error(102, msym->s_name); - return (msym); - } - - /* - * Now the left operand of ARROW does not point to a struct/union - * or the left operand of POINT is no struct/union. - */ - if (eq) { - if (op == POINT) { - /* left operand of "." must be struct/union object */ - error(103); - } else { - /* left operand of "->" must be pointer to ... */ - error(104); - } - } else { - /* unacceptable operand of %s */ - error(111, modtab[op].m_name); - } - - return (msym); -} - -/* - * Create a tree node. Called for most operands except function calls, - * sizeof and casts. - * - * op operator - * ln left operand - * rn if not NULL, right operand - */ -tnode_t * -build(op_t op, tnode_t *ln, tnode_t *rn) -{ - mod_t *mp; - tnode_t *ntn; - type_t *rtp; - - mp = &modtab[op]; - - /* If there was an error in one of the operands, return. */ - if (ln == NULL || (mp->m_binary && rn == NULL)) - return (NULL); - - /* - * Apply class conversions to the left operand, but only if its - * value is needed or it is compared with null. - */ - if (mp->m_vctx || mp->m_tctx) - ln = cconv(ln); - /* - * The right operand is almost always in a test or value context, - * except if it is a struct or union member. - */ - if (mp->m_binary && op != ARROW && op != POINT) - rn = cconv(rn); - - /* - * Print some warnings for comparisons of unsigned values with - * constants lower than or equal to null. This must be done - * before promote() because otherwise unsigned char and unsigned - * short would be promoted to int. Also types are tested to be - * CHAR, which would also become int. - */ - if (mp->m_comp) - chkcomp(op, ln, rn); - - /* - * Promote the left operand if it is in a test or value context - */ - if (mp->m_vctx || mp->m_tctx) - ln = promote(op, 0, ln); - /* - * Promote the right operand, but only if it is no struct or - * union member, or if it is not to be assigned to the left operand - */ - if (mp->m_binary && op != ARROW && op != POINT && - op != ASSIGN && op != RETURN) { - rn = promote(op, 0, rn); - } - - /* - * If the result of the operation is different for signed or - * unsigned operands and one of the operands is signed only in - * ANSI C, print a warning. - */ - if (mp->m_tlansiu && ln->tn_op == CON && ln->tn_val->v_ansiu) { - /* ANSI C treats constant as unsigned, op %s */ - warning(218, mp->m_name); - ln->tn_val->v_ansiu = 0; - } - if (mp->m_transiu && rn->tn_op == CON && rn->tn_val->v_ansiu) { - /* ANSI C treats constant as unsigned, op %s */ - warning(218, mp->m_name); - rn->tn_val->v_ansiu = 0; - } - - /* Make sure both operands are of the same type */ - if (mp->m_balance) - balance(op, &ln, &rn); - - /* - * Check types for compatibility with the operation and mutual - * compatibility. Return if there are serious problems. - */ - if (!typeok(op, NULL, ln, rn)) - return (NULL); - - /* And now create the node. */ - switch (op) { - case POINT: - case ARROW: - ntn = bldstr(op, ln, rn); - break; - case INCAFT: - case DECAFT: - case INCBEF: - case DECBEF: - ntn = bldincdec(op, ln); - break; - case AMPER: - ntn = bldamper(ln, 0); - break; - case STAR: - ntn = mktnode(STAR, ln->tn_type->t_subt, ln, NULL); - break; - case PLUS: - case MINUS: - ntn = bldplmi(op, ln, rn); - break; - case SHL: - case SHR: - ntn = bldshft(op, ln, rn); - break; - case COLON: - ntn = bldcol(ln, rn); - break; - case ASSIGN: - case MULASS: - case DIVASS: - case MODASS: - case ADDASS: - case SUBASS: - case SHLASS: - case SHRASS: - case ANDASS: - case XORASS: - case ORASS: - case RETURN: - ntn = bldasgn(op, ln, rn); - break; - case COMMA: - case QUEST: - ntn = mktnode(op, rn->tn_type, ln, rn); - break; - case REAL: - case IMAG: - rtp = ln->tn_type; - if (rtp->t_tspec == COMPLEX) - rtp = gettyp(FLOAT); - else if (rtp->t_tspec == DCOMPLEX) - rtp = gettyp(DOUBLE); - else if (rtp->t_tspec == LDCOMPLEX) - rtp = gettyp(LDOUBLE); - ntn = mktnode(op, rtp, ln, rn); - break; - default: - rtp = mp->m_logop ? gettyp(INT) : ln->tn_type; - if (!mp->m_binary && rn != NULL) - lerror("build() 1"); - ntn = mktnode(op, rtp, ln, rn); - break; - } - - /* Return if an error occurred. */ - if (ntn == NULL) - return (NULL); - - /* Print a warning if precedence confusion is possible */ - if (mp->m_tpconf) - precconf(ntn); - - /* - * Print a warning if one of the operands is in a context where - * it is compared with null and if this operand is a constant. - */ - if (mp->m_tctx) { - if (ln->tn_op == CON || - ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { - if (hflag && !ccflg) { - /* constant in conditional context */ - warning(161); - } - } - } - - /* Fold if the operator requires it */ - if (mp->m_fold) { - if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { - if (mp->m_tctx) { - ntn = foldtst(ntn); - } else if (isftyp(ntn->tn_type->t_tspec)) { - ntn = foldflt(ntn); - } else { - ntn = fold(ntn); - } - } else if (op == QUEST && ln->tn_op == CON) { - ntn = ln->tn_val->v_quad ? rn->tn_left : rn->tn_right; - } - } - - return (ntn); -} - -/* - * Perform class conversions. - * - * Arrays of type T are converted into pointers to type T. - * Functions are converted to pointers to functions. - * Lvalues are converted to rvalues. - */ -tnode_t * -cconv(tnode_t *tn) -{ - type_t *tp; - - /* - * Array-lvalue (array of type T) is converted into rvalue - * (pointer to type T) - */ - if (tn->tn_type->t_tspec == ARRAY) { - if (!tn->tn_lvalue) { - /* operand of '%s' must be lvalue */ - /* XXX print correct operator */ - (void)gnuism(114, "", modtab[AMPER].m_name); - } - tn = mktnode(AMPER, tincref(tn->tn_type->t_subt, PTR), - tn, NULL); - } - - /* - * Expression of type function (function with return value of type T) - * in rvalue-expression (pointer to function with return value - * of type T) - */ - if (tn->tn_type->t_tspec == FUNC) - tn = bldamper(tn, 1); - - /* lvalue to rvalue */ - if (tn->tn_lvalue) { - tp = tduptyp(tn->tn_type); - tp->t_const = tp->t_volatile = 0; - tn = mktnode(LOAD, tp, tn, NULL); - } - - return (tn); -} - -/* - * Perform most type checks. First the types are checked using - * information from modtab[]. After that it is done by hand for - * more complicated operators and type combinations. - * - * If the types are ok, typeok() returns 1, otherwise 0. - */ -int -typeok(op_t op, farg_t *farg, tnode_t *ln, tnode_t *rn) -{ - mod_t *mp; - tspec_t lt, rt = NOTSPEC, lst = NOTSPEC, rst = NOTSPEC, - olt = NOTSPEC, ort = NOTSPEC; - type_t *ltp, *rtp, *lstp, *rstp; - tnode_t *tn; - - mp = &modtab[op]; - - if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) - lst = (lstp = ltp->t_subt)->t_tspec; - if (mp->m_binary) { - if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) - rst = (rstp = rtp->t_subt)->t_tspec; - } - - if (mp->m_rqint) { - if (op == COMPL && iscomplex(lt)) { - /* use of '~' for complex conjugation is a GNUism */ - } else - /* integer types required */ - if (!isityp(lt) || (mp->m_binary && !isityp(rt))) { - incompat(op, lt, rt); - return (0); - } - } else if (mp->m_rqsclt) { - /* scalar types required */ - if (!issclt(lt) || (mp->m_binary && !issclt(rt))) { - incompat(op, lt, rt); - return (0); - } - } else if (mp->m_rqatyp) { - /* arithmetic types required */ - if (!isatyp(lt) || (mp->m_binary && !isatyp(rt))) { - incompat(op, lt, rt); - return (0); - } - } - - if (op == SHL || op == SHR || op == SHLASS || op == SHRASS) { - /* - * For these operations we need the types before promotion - * and balancing. - */ - for (tn=ln; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) ; - olt = tn->tn_type->t_tspec; - for (tn=rn; tn->tn_op==CVT && !tn->tn_cast; tn=tn->tn_left) ; - ort = tn->tn_type->t_tspec; - } - - switch (op) { - case POINT: - /* - * Most errors required by ANSI C are reported in strmemb(). - * Here we only must check for totally wrong things. - */ - if (lt == FUNC || lt == VOID || ltp->t_isfield || - ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { - /* we already have an error from strmemb() */ - return (0); - } - /* Now we have an object we can create a pointer to */ - break; - case ARROW: - if (lt != PTR) { - /* we already have an error from strmemb() */ - return (0); - } - break; - case INCAFT: - case DECAFT: - case INCBEF: - case DECBEF: - /* operands have scalar types (checked above) */ - if (!ln->tn_lvalue) { - if (ln->tn_op == CVT && ln->tn_cast && - ln->tn_left->tn_op == LOAD) { - /* a cast does not yield an lvalue */ - error(163); - } - /* %soperand of %s must be lvalue */ - error(114, "", mp->m_name); - return (0); - } else if (ltp->t_const) { - /* %soperand of %s must be modifiable lvalue */ - warning(115, "", mp->m_name); - } - break; - case AMPER: - if (lt == ARRAY || lt == FUNC) { - /* ok, a warning comes later (in bldamper()) */ - } else if (!ln->tn_lvalue) { - if (ln->tn_op == CVT && ln->tn_cast && - ln->tn_left->tn_op == LOAD) { - /* a cast does not yield an lvalue */ - error(163); - } - /* %soperand of %s must be lvalue */ - error(114, "", mp->m_name); - return (0); - } else if (issclt(lt)) { - if (ltp->t_isfield) { - /* cannot take address of bit-field */ - error(112); - return (0); - } - } else if (lt != STRUCT && lt != UNION) { - /* unacceptable operand of %s */ - error(111, mp->m_name); - return (0); - } - if (ln->tn_op == NAME && ln->tn_sym->s_reg) { - /* cannot take address of register %s */ - error(113, ln->tn_sym->s_name); - return (0); - } - break; - case STAR: - /* until now there were no type checks for this operator */ - if (lt != PTR) { - /* cannot dereference non-pointer type */ - error(96); - return (0); - } - break; - case PLUS: - /* operands have scalar types (checked above) */ - if ((lt == PTR && !isityp(rt)) || (rt == PTR && !isityp(lt))) { - incompat(op, lt, rt); - return (0); - } - break; - case MINUS: - /* operands have scalar types (checked above) */ - if (lt == PTR && (!isityp(rt) && rt != PTR)) { - incompat(op, lt, rt); - return (0); - } else if (rt == PTR && lt != PTR) { - incompat(op, lt, rt); - return (0); - } - if (lt == PTR && rt == PTR) { - if (!eqtype(lstp, rstp, 1, 0, NULL)) { - /* illegal pointer subtraction */ - error(116); - } - } - break; - case SHR: - /* operands have integer types (checked above) */ - if (pflag && !isutyp(lt)) { - /* - * The left operand is signed. This means that - * the operation is (possibly) nonportable. - */ - /* bitwise operation on signed value nonportable */ - if (ln->tn_op != CON) { - /* possibly nonportable */ - warning(117); - } else if (ln->tn_val->v_quad < 0) { - warning(120); - } - } else if (!sflag && !isutyp(olt) && isutyp(ort)) { - /* - * The left operand would become unsigned in - * traditional C. - */ - if (hflag && - (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { - /* semantics of %s change in ANSI C; use ... */ - warning(118, mp->m_name); - } - } else if (!sflag && !isutyp(olt) && !isutyp(ort) && - psize(lt) < psize(rt)) { - /* - * In traditional C the left operand would be extended, - * possibly with 1, and then shifted. - */ - if (hflag && - (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { - /* semantics of %s change in ANSI C; use ... */ - warning(118, mp->m_name); - } - } - - /* right shift of %d-bit quantity by %lld bits */ - if (rn->tn_op == CON && size(olt) <= rn->tn_val->v_quad) - warning(310, size(olt), rn->tn_val->v_quad); - - goto shift; - case SHL: - /* - * ANSI C does not perform balancing for shift operations, - * but traditional C does. If the width of the right operand - * is greather than the width of the left operand, than in - * traditional C the left operand would be extended to the - * width of the right operand. For SHL this may result in - * different results. - */ - if (psize(lt) < psize(rt)) { - /* - * XXX If both operands are constant make sure - * that there is really a difference between - * ANSI C and traditional C. - */ - if (hflag) - /* semantics of %s change in ANSI C; use ... */ - warning(118, mp->m_name); - } - shift: - if (rn->tn_op == CON) { - if (!isutyp(rt) && rn->tn_val->v_quad < 0) { - /* negative shift */ - warning(121); - } else if ((u_quad_t)rn->tn_val->v_quad == size(lt)) { - /* shift equal to size of object */ - warning(267); - } else if ((u_quad_t)rn->tn_val->v_quad > size(lt)) { - /* shift greater than size of object */ - warning(122); - } - } - break; - case EQ: - case NE: - /* - * Accept some things which are allowed with EQ and NE, - * but not with ordered comparisons. - */ - if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { - if (rn->tn_op == CON && rn->tn_val->v_quad == 0) - break; - } - if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { - if (ln->tn_op == CON && ln->tn_val->v_quad == 0) - break; - } - /* FALLTHROUGH */ - case LT: - case GT: - case LE: - case GE: - if ((lt == PTR || rt == PTR) && lt != rt) { - if (isityp(lt) || isityp(rt)) { - /* illegal comb. of pointer and int., op %s */ - warning(123, mp->m_name); - } else { - incompat(op, lt, rt); - return (0); - } - } else if (lt == PTR && rt == PTR) { - ptrcmpok(op, ln, rn); - } - break; - case QUEST: - if (!issclt(lt)) { - /* first operand must have scalar type, op ? : */ - error(170); - return (0); - } - if (rn->tn_op != COLON) - lerror("typeok() 2"); - break; - case COLON: - - if (isatyp(lt) && isatyp(rt)) - break; - - if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) - break; - if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) - break; - - /* combination of any pointer and 0, 0L or (void *)0 is ok */ - if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { - if (rn->tn_op == CON && rn->tn_val->v_quad == 0) - break; - } - if (rt == PTR && ((lt == PTR && lst == VOID) || isityp(lt))) { - if (ln->tn_op == CON && ln->tn_val->v_quad == 0) - break; - } - - if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { - /* illegal comb. of ptr. and int., op %s */ - warning(123, mp->m_name); - break; - } - - if (lt == VOID || rt == VOID) { - if (lt != VOID || rt != VOID) - /* incompatible types in conditional */ - warning(126); - break; - } - - if (lt == PTR && rt == PTR && ((lst == VOID && rst == FUNC) || - (lst == FUNC && rst == VOID))) { - /* (void *)0 handled above */ - if (sflag) - /* ANSI C forbids conv. of %s to %s, op %s */ - warning(305, "function pointer", "'void *'", - mp->m_name); - break; - } - - if (rt == PTR && lt == PTR) { - if (!eqtype(lstp, rstp, 1, 0, NULL)) - illptrc(mp, ltp, rtp); - break; - } - - /* incompatible types in conditional */ - error(126); - return (0); - - case ASSIGN: - case INIT: - case FARG: - case RETURN: - if (!asgntypok(op, farg, ln, rn)) - return (0); - goto assign; - case MULASS: - case DIVASS: - case MODASS: - goto assign; - case ADDASS: - case SUBASS: - /* operands have scalar types (checked above) */ - if ((lt == PTR && !isityp(rt)) || rt == PTR) { - incompat(op, lt, rt); - return (0); - } - goto assign; - case SHLASS: - goto assign; - case SHRASS: - if (pflag && !isutyp(lt)) { - /* bitwise operation on s.v. possibly nonportable */ - warning(117); - } - - /* right shift of %d-bit quantity by %d bits */ - if (rn->tn_op == CON && size(olt) <= rn->tn_val->v_quad) - warning(310, size(olt), rn->tn_val->v_quad); - - goto assign; - case ANDASS: - case XORASS: - case ORASS: - goto assign; - assign: - if (!ln->tn_lvalue) { - if (ln->tn_op == CVT && ln->tn_cast && - ln->tn_left->tn_op == LOAD) { - /* a cast does not yield an lvalue */ - error(163); - } - /* %soperand of %s must be lvalue */ - error(114, "left ", mp->m_name); - return (0); - } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && - conmemb(ltp))) { - /* %soperand of %s must be modifiable lvalue */ - warning(115, "left ", mp->m_name); - } - break; - case COMMA: - if (!modtab[ln->tn_op].m_sideeff) - nulleff(ln); - break; - /* LINTED (enumeration values not handled in switch) */ - } - - if (mp->m_badeop && - (ltp->t_isenum || (mp->m_binary && rtp->t_isenum))) { - chkbeop(op, ln, rn); - } else if (mp->m_enumop && (ltp->t_isenum && rtp->t_isenum)) { - chkeop2(op, farg, ln, rn); - } else if (mp->m_enumop && (ltp->t_isenum || rtp->t_isenum)) { - chkeop1(op, farg, ln, rn); - } - - return (1); -} - -static void -ptrcmpok(op_t op, tnode_t *ln, tnode_t *rn) -{ - type_t *ltp, *rtp; - tspec_t lt, rt; - const char *lts, *rts; - - lt = (ltp = ln->tn_type)->t_subt->t_tspec; - rt = (rtp = rn->tn_type)->t_subt->t_tspec; - - if (lt == VOID || rt == VOID) { - if (sflag && (lt == FUNC || rt == FUNC)) { - /* (void *)0 already handled in typeok() */ - *(lt == FUNC ? <s : &rts) = "function pointer"; - *(lt == VOID ? <s : &rts) = "'void *'"; - /* ANSI C forbids comparison of %s with %s */ - warning(274, lts, rts); - } - return; - } - - if (!eqtype(ltp->t_subt, rtp->t_subt, 1, 0, NULL)) { - illptrc(&modtab[op], ltp, rtp); - return; - } - - if (lt == FUNC && rt == FUNC) { - if (sflag && op != EQ && op != NE) - /* ANSI C forbids ordered comp. of func ptr */ - warning(125); - } -} - -/* - * Checks type compatibility for ASSIGN, INIT, FARG and RETURN - * and prints warnings/errors if necessary. - * If the types are (almost) compatible, 1 is returned, otherwise 0. - */ -static int -asgntypok(op_t op, farg_t *farg, tnode_t *ln, tnode_t *rn) -{ - tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; - type_t *ltp, *rtp, *lstp, *rstp; - mod_t *mp; - const char *lts, *rts; - int arg = (farg) ? farg->fa_num : 0; - - if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) - lst = (lstp = ltp->t_subt)->t_tspec; - if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) - rst = (rstp = rtp->t_subt)->t_tspec; - mp = &modtab[op]; - - /* be picky about conversion of function return types */ - if (rn->tn_op == CALL) { - if (size(lt) < size(rt) || - (size(lt) == size(rt) && isutyp(lt) && !isutyp(rt))) { - warning(313, funcname(rn), - tyname(rn->tn_type), tyname(ln->tn_type)); - } - } - - if (isatyp(lt) && isatyp(rt)) - return (1); - - if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) - /* both are struct or union */ - return (ltp->t_str == rtp->t_str); - - /* 0, 0L and (void *)0 may be assigned to any pointer */ - if (lt == PTR && ((rt == PTR && rst == VOID) || isityp(rt))) { - if (rn->tn_op == CON && rn->tn_val->v_quad == 0) - return (1); - } - - if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { - /* two pointers, at least one pointer to void */ - if (sflag && (lst == FUNC || rst == FUNC)) { - /* comb. of ptr to func and ptr to void */ - *(lst == FUNC ? <s : &rts) = "function pointer"; - *(lst == VOID ? <s : &rts) = "'void *'"; - switch (op) { - case INIT: - case RETURN: - /* ANSI C forbids conversion of %s to %s */ - warning(303, rts, lts); - break; - case FARG: - /* ANSI C forbids conv. of %s to %s, arg #%d */ - warning(304, rts, lts, arg); - break; - default: - /* ANSI C forbids conv. of %s to %s, op %s */ - warning(305, rts, lts, mp->m_name); - break; - } - } - } - - if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || - eqtype(lstp, rstp, 1, 0, NULL))) { - /* compatible pointer types (qualifiers ignored) */ - if (((!lstp->t_const && rstp->t_const) || - (!lstp->t_volatile && rstp->t_volatile))) { - /* left side has not all qualifiers of right */ - switch (op) { - case INIT: - case RETURN: - /* incompatible pointer types */ - warning(182); - break; - case FARG: - /* %s arg #%d: incompatible ptr. type */ - warning(153, funcname(farg->fa_func), arg); - break; - default: - /* operands have incompat. ptr. types, op %s */ - warning(128, mp->m_name); - break; - } - } - return (1); - } - - if ((lt == PTR && isityp(rt)) || (isityp(lt) && rt == PTR)) { - switch (op) { - case INIT: - case RETURN: - /* illegal combination of pointer and integer */ - warning(183); - break; - case FARG: - /* %s arg #%d: illegal comb. of ptr. and int. */ - warning(154, funcname(farg->fa_func), arg); - break; - default: - /* illegal comb. of ptr. and int., op %s */ - warning(123, mp->m_name); - break; - } - return (1); - } - - if (lt == PTR && rt == PTR) { - switch (op) { - case INIT: - case RETURN: - illptrc(NULL, ltp, rtp); - break; - case FARG: - /* %s arg #%d: incompatible pointer type */ - warning(153, funcname(farg->fa_func), arg); - break; - default: - illptrc(mp, ltp, rtp); - break; - } - return (1); - } - - switch (op) { - case INIT: - /* initialisation type mismatch */ - error(185); - break; - case RETURN: - /* return value type mismatch */ - error(211); - break; - case FARG: - /* %s arg #%d: argument is incompatible with prototype */ - warning(155, funcname(farg->fa_func), arg); - break; - default: - incompat(op, lt, rt); - break; - } - - return (0); -} - -/* - * Prints a warning if an operator, which should be senseless for an - * enum type, is applied to an enum type. - */ -static void -chkbeop(op_t op, tnode_t *ln, tnode_t *rn) -{ - mod_t *mp; - - if (!eflag) - return; - - mp = &modtab[op]; - - if (!(ln->tn_type->t_isenum || - (mp->m_binary && rn->tn_type->t_isenum))) { - return; - } - - /* - * Enum as offset to a pointer is an exception (otherwise enums - * could not be used as array indizes). - */ - if (op == PLUS && - ((ln->tn_type->t_isenum && rn->tn_type->t_tspec == PTR) || - (rn->tn_type->t_isenum && ln->tn_type->t_tspec == PTR))) { - return; - } - - /* dubious operation on enum, op %s */ - warning(241, mp->m_name); - -} - -/* - * Prints a warning if an operator is applied to two different enum types. - */ -static void -chkeop2(op_t op, farg_t *farg, tnode_t *ln, tnode_t *rn) -{ - mod_t *mp; - int arg = (farg) ? farg->fa_num : 0; - - mp = &modtab[op]; - - if (ln->tn_type->t_enum != rn->tn_type->t_enum) { - switch (op) { - case INIT: - /* enum type mismatch in initialisation */ - warning(210); - break; - case FARG: - /* %s arg #%d: enum type mismatch */ - warning(156, funcname(farg->fa_func), arg); - break; - case RETURN: - /* return value type mismatch */ - warning(211); - break; - default: - /* enum type mismatch, op %s */ - warning(130, mp->m_name); - break; - } -#if 0 - } else if (mp->m_comp && op != EQ && op != NE) { - if (eflag) - /* dubious comparisons of enums */ - warning(243, mp->m_name); -#endif - } -} - -/* - * Prints a warning if an operator has both enum end other integer - * types. - */ -static void -chkeop1(op_t op, farg_t *farg, tnode_t *ln, tnode_t *rn) -{ - int arg = (farg) ? farg->fa_num : 0; - - if (!eflag) - return; - - switch (op) { - case INIT: - /* - * Initializations with 0 should be allowed. Otherwise, - * we should complain about all uninitialized enums, - * consequently. - */ - if (!rn->tn_type->t_isenum && rn->tn_op == CON && - isityp(rn->tn_type->t_tspec) && rn->tn_val->v_quad == 0) { - return; - } - /* initialisation of '%s' with '%s' */ - warning(277, tyname(ln->tn_type), tyname(rn->tn_type)); - break; - case FARG: - /* %s arg #%d: combination of '%s' and '%s' */ - warning(278, funcname(farg->fa_func), arg, tyname(ln->tn_type), tyname(rn->tn_type)); - break; - case RETURN: - /* combination of '%s' and '%s' in return */ - warning(279, tyname(ln->tn_type), tyname(rn->tn_type)); - break; - default: - /* combination of '%s' and %s, op %s */ - warning(242, tyname(ln->tn_type), tyname(rn->tn_type), - modtab[op].m_name); - break; - } -} - -/* - * Build and initialize a new node. - */ -static tnode_t * -mktnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn) -{ - tnode_t *ntn; - tspec_t t; - - ntn = getnode(); - - ntn->tn_op = op; - ntn->tn_type = type; - ntn->tn_left = ln; - ntn->tn_right = rn; - - if (op == STAR || op == FSEL) { - if (ln->tn_type->t_tspec == PTR) { - t = ln->tn_type->t_subt->t_tspec; - if (t != FUNC && t != VOID) - ntn->tn_lvalue = 1; - } else { - lerror("mktnode() 2"); - } - } else if (op == REAL || op == IMAG) { - ntn->tn_lvalue = ln->tn_lvalue; - } - - return (ntn); -} - -/* - * Performs usual conversion of operands to (unsigned) int. - * - * If the operand is a function argument with no type information - * (no prototype or variable # of args), convert float to double. - */ -tnode_t * -promote(op_t op, int farg, tnode_t *tn) -{ - tspec_t t; - type_t *ntp; - int len; - - t = tn->tn_type->t_tspec; - - if (!isatyp(t)) - return (tn); - - /* - * ANSI C requires that the result is always of type INT - * if INT can represent all possible values of the previous - * type (it is "value preserving" rather than "sign - * preserving"). - * - * XXX: Adjust value-preserving rules for longs and long - * longs, too. - */ - if (tn->tn_type->t_isfield) { - len = tn->tn_type->t_flen; - if (size(INT) > len) { - t = INT; - } else { - if (size(INT) != len) - lerror("promote() 1"); - if (isutyp(t)) { - t = UINT; - } else { - t = INT; - } - } - } else if (t == CHAR || t == UCHAR || t == SCHAR) { - t = (size(CHAR) < size(INT) || t != UCHAR) ? - INT : UINT; - } else if (t == SHORT || t == USHORT) { - t = (size(SHORT) < size(INT) || t == SHORT) ? - INT : UINT; - } else if (t == ENUM) { - t = INT; - } else if (farg && t == FLOAT) { - t = DOUBLE; - } - - if (t != tn->tn_type->t_tspec) { - ntp = tduptyp(tn->tn_type); - ntp->t_tspec = t; - /* - * Keep t_isenum so we are later able to check compatibility - * of enum types. - */ - tn = convert(op, NULL, ntp, tn); - } - - return (tn); -} - -/* - * Insert conversions which are necessary to give both operands the same - * type. This is done in different ways for traditional C and ANSI C. - */ -static void -balance(op_t op, tnode_t **lnp, tnode_t **rnp) -{ - tspec_t lt, rt, t; - int i; - type_t *ntp; - static tspec_t tl[] = { - LDOUBLE, DOUBLE, FLOAT, UQUAD, QUAD, ULONG, LONG, UINT, INT, - }; - - lt = (*lnp)->tn_type->t_tspec; - rt = (*rnp)->tn_type->t_tspec; - - if (!isatyp(lt) || !isatyp(rt)) - return; - - if (lt == rt) { - t = lt; - } else if (lt == LDOUBLE || rt == LDOUBLE) { - t = LDOUBLE; - } else if (lt == DOUBLE || rt == DOUBLE) { - t = DOUBLE; - } else if (lt == FLOAT || rt == FLOAT) { - t = FLOAT; - } else { - /* - * If type A has more bits than type B it should - * be able to hold all possible values of type B. - */ - if (size(lt) > size(rt)) { - t = lt; - } else if (size(lt) < size(rt)) { - t = rt; - } else { - for (i = 3; tl[i] != INT; i++) { - if (tl[i] == lt || tl[i] == rt) - break; - } - if ((isutyp(lt) || isutyp(rt)) && - !isutyp(tl[i])) { - i--; - } - t = tl[i]; - } - } - - if (t != lt) { - ntp = tduptyp((*lnp)->tn_type); - ntp->t_tspec = t; - *lnp = convert(op, NULL, ntp, *lnp); - } - if (t != rt) { - ntp = tduptyp((*rnp)->tn_type); - ntp->t_tspec = t; - *rnp = convert(op, NULL, ntp, *rnp); - } -} - -/* - * Insert a conversion operator, which converts the type of the node - * to another given type. - * If op is FARG, farg contains the passed argument information. - */ -tnode_t * -convert(op_t op, farg_t *farg, type_t *tp, tnode_t *tn) -{ - tnode_t *ntn; - tspec_t nt, ot, ost = NOTSPEC; - int arg = (farg) ? farg->fa_num : 0; - - if (tn->tn_lvalue) - lerror("convert() 1"); - - nt = tp->t_tspec; - if ((ot = tn->tn_type->t_tspec) == PTR) - ost = tn->tn_type->t_subt->t_tspec; - - if (op == FARG) - nt = fcnconv(farg, nt, ot, tp, tn); - - if (isityp(nt) && isityp(ot)) { - iiconv(op, farg, nt, ot, tp, tn); - } else if (nt == PTR && ((ot == PTR && ost == VOID) || isityp(ot)) && - tn->tn_op == CON && tn->tn_val->v_quad == 0) { - /* 0, 0L and (void *)0 may be assigned to any pointer. */ - } else if (isityp(nt) && ot == PTR) { - piconv(op, nt, tp, tn); - } else if (nt == PTR && ot == PTR) { - ppconv(op, tn, tp); - } else if (isftyp(ot) && !isftyp(nt)) { - /* conversion from floating point to fixed point */ - if (tn->tn_op == CON) { - /* ok. cvtcon() warns if constant out of range */ - } else { - if (op == FARG) - /* %s arg #%d: converted from '%s' to '%s' */ - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - else - warning(132, tyname(tn->tn_type), - tyname(tp)); - } - } - - ntn = getnode(); - ntn->tn_op = CVT; - ntn->tn_type = tp; - ntn->tn_cast = op == CVT; - if (tn->tn_op != CON || nt == VOID) { - ntn->tn_left = tn; - } else { - ntn->tn_op = CON; - ntn->tn_val = tgetblk(sizeof (val_t)); - cvtcon(op, farg, ntn->tn_type, ntn->tn_val, tn->tn_val); - } - - return (ntn); -} - -/* - * Print warnings for conversions of function call arguments. Conversions - * happen differently between standard C and traditional C, and also happen - * differently in standard C depending on whether a prototype is present. - * - * Errors/Warnings about illegal type combinations are already printed - * in asgntypok(). - */ -static tspec_t -fcnconv(farg_t *farg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) -{ - tnode_t *ptn; - type_t *fcn = farg->fa_func->tn_type->t_subt; - tspec_t pt; - int arg = farg->fa_num; - - /* In standard C, if the function call is governed by a prototype, - * the arguments don't necessarily undergo the usual argument conversions - * before the call. They can be converted directly to the type of the - * formal parameter, without necessarily widening/narrowing. - */ - if (fcn->t_proto || !isatyp(nt) || !isatyp(ot)) - return nt; - - /* get default promotion */ - ptn = promote(NOOP, 1, tn); - pt = ptn->tn_type->t_tspec; - - /* - * If the type of the formal parameter is char/short, a warning - * would be useless, because functions declared the old style - * can't expect char/short arguments. - */ - if (nt == CHAR || nt == UCHAR || nt == SHORT || nt == USHORT) - return pt; - - /* return if types are the same with and without promotion */ - if (nt == pt || (nt == ENUM && pt == INT)) - return pt; - - if (isftyp(nt) != isftyp(pt) || psize(nt) != psize(pt)) { - /* representation and/or width change */ - if (styp(nt) != SHORT || !isityp(pt) || psize(pt) > psize(INT)) { - if (ptn->tn_op == CON) { - /* ok. promote() warns if constant out of range */ - } else { - /* %s arg #%d: converted from '%s' to '%s' */ - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - } - } - } else if (hflag) { - /* - * they differ in sign or base type (char, short, int, - * long, long long, float, double, long double) - * - * if they differ only in sign and the argument is a constant - * and the msb of the argument is not set, print no warning - */ - if (ptn->tn_op == CON && isityp(nt) && styp(nt) == styp(pt) && - msb(ptn->tn_val->v_quad, ot, -1) == 0) { - /* ok */ - } else if (ptn->tn_op != CON) { - /* %s arg #%d: converted from '%s' to '%s' */ - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - } - } - - return pt; -} - -/* - * Print warnings for conversions of integer types which may cause - * problems. - */ -/* ARGSUSED */ -static void -iiconv(op_t op, farg_t *farg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn) -{ - int arg = (farg) ? farg->fa_num : 0; - - if (tn->tn_op == CON) - return; - - if (op == CVT) - return; - - /* logical ops return int, so silently convert int to _Bool */ - if (ot == INT && nt == BOOL) - return; - - if (rank(nt) < rank(ot)) { - /* coercion from greater to lesser width */ - if (op == FARG) { - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - } else { - warning(132, tyname(tn->tn_type), tyname(tp)); - } - } else if (!isutyp(ot) && isutyp(nt)) { - /* signed to unsigned conversion */ - if (op == FARG) { - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - } else { - warning(132, tyname(tn->tn_type), tyname(tp)); - } - } else if (isutyp(ot) && !isutyp(nt) && rank(nt) == rank(ot)) { - /* signed to unsigned conversion */ - if (op == FARG) { - warning(259, funcname(farg->fa_func), arg, - tyname(tn->tn_type), tyname(tp)); - } else { - warning(132, tyname(tn->tn_type), tyname(tp)); - } - } -} - -/* - * Print warnings for dubious conversions of pointer to integer. - */ -static void -piconv(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) -{ - if (tn->tn_op == CON) - return; - - if (op != CVT) { - /* We already have an error. */ - return; - } - - if (psize(nt) < psize(PTR)) { - if (pflag && size(nt) >= size(PTR)) { - /* conv. of pointer to %s may lose bits */ - warning(134, tyname(tp)); - } else { - /* conv. of pointer to %s loses bits */ - warning(133, tyname(tp)); - } - } -} - -/* - * Print warnings for questionable pointer conversions. - */ -static void -ppconv(op_t op, tnode_t *tn, type_t *tp) -{ - tspec_t nt, ot; - const char *nts, *ots; - - /* - * We already have an error (pointers of different types - * without a cast) or we will not get a warning. - */ - if (op != CVT) - return; - - nt = tp->t_subt->t_tspec; - ot = tn->tn_type->t_subt->t_tspec; - - if (nt == VOID || ot == VOID) { - if (sflag && (nt == FUNC || ot == FUNC)) { - /* (void *)0 already handled in convert() */ - *(nt == FUNC ? &nts : &ots) = "function pointer"; - *(nt == VOID ? &nts : &ots) = "'void *'"; - /* ANSI C forbids conversion of %s to %s */ - warning(303, ots, nts); - } - return; - } else if (nt == FUNC && ot == FUNC) { - return; - } else if (nt == FUNC || ot == FUNC) { - /* questionable conversion of function pointer */ - warning(229); - return; - } - - if (getbound(tp->t_subt) > getbound(tn->tn_type->t_subt)) { - if (hflag) - /* possible pointer alignment problem */ - warning(135); - } - if (((nt == STRUCT || nt == UNION) && - tp->t_subt->t_str != tn->tn_type->t_subt->t_str) || - (psize(nt) != CHAR_BIT && psize(nt) != psize(ot))) { - if (cflag) { - /* pointer casts may be troublesome */ - warning(247); - } - } -} - -/* - * Converts a typed constant to a constant of another type. - * - * op operator which requires conversion - * farg if op is FARG, the passed argument info (else NULL) - * tp type to which to convert the constant - * nv new constant - * v old constant - */ -void -cvtcon(op_t op, farg_t *farg, type_t *tp, val_t *nv, val_t *v) -{ - tspec_t ot, nt; - ldbl_t max = 0, min = 0; - int sz, rchk; - quad_t xmask, xmsk1; - int osz, nsz, arg = (farg) ? farg->fa_num : 0; - - ot = v->v_tspec; - nt = nv->v_tspec = tp->t_tspec; - rchk = 0; - - if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { - switch (nt) { - case BOOL: - max = 1; min = 0; break; - case CHAR: - max = CHAR_MAX; min = CHAR_MIN; break; - case UCHAR: - max = UCHAR_MAX; min = 0; break; - case SCHAR: - max = SCHAR_MAX; min = SCHAR_MIN; break; - case SHORT: - max = SHRT_MAX; min = SHRT_MIN; break; - case USHORT: - max = USHRT_MAX; min = 0; break; - case ENUM: - case INT: - max = INT_MAX; min = INT_MIN; break; - case UINT: - max = (u_int)UINT_MAX; min = 0; break; - case LONG: - max = LONG_MAX; min = LONG_MIN; break; - case ULONG: - max = (u_long)ULONG_MAX; min = 0; break; - case QUAD: - max = QUAD_MAX; min = QUAD_MIN; break; - case UQUAD: - max = (u_quad_t)UQUAD_MAX; min = 0; break; - case FLOAT: - max = FLT_MAX; min = -FLT_MAX; break; - case DOUBLE: - max = DBL_MAX; min = -DBL_MAX; break; - case PTR: - /* Already an error because of float --> ptr */ - case LDOUBLE: - max = LDBL_MAX; min = -LDBL_MAX; break; - case COMPLEX: - max = FLT_MAX; min = -FLT_MAX; break; - case DCOMPLEX: - max = DBL_MAX; min = -DBL_MAX; break; - case LDCOMPLEX: - max = LDBL_MAX; min = -LDBL_MAX; break; - case IMAGINARY: - case DIMAGINARY: - case LDIMAGINARY: - max = 0; min = 0; break; - default: - lerror("cvtcon() 1"); - } - if (v->v_ldbl > max || v->v_ldbl < min) { - if (nt == LDOUBLE || nt == LDCOMPLEX) - lerror("cvtcon() 2"); - if (op == FARG) { - /* %s arg #%d: conv. of %s to %s is out of range */ - warning(295, funcname(farg->fa_func), arg, - tyname(gettyp(ot)), tyname(tp)); - } else { - /* conversion of %s to %s is out of range */ - warning(119, tyname(gettyp(ot)), tyname(tp)); - } - v->v_ldbl = v->v_ldbl > 0 ? max : min; - } - if (nt == FLOAT) { - nv->v_ldbl = (float)v->v_ldbl; - } else if (nt == DOUBLE) { - nv->v_ldbl = (double)v->v_ldbl; - } else if (nt == LDOUBLE) { - nv->v_ldbl = v->v_ldbl; - } else { - nv->v_quad = (nt == PTR || isutyp(nt)) ? - (u_quad_t)v->v_ldbl : (quad_t)v->v_ldbl; - } - } else { - if (nt == FLOAT || nt == COMPLEX) { - nv->v_ldbl = (ot == PTR || isutyp(ot)) ? - (float)(u_quad_t)v->v_quad : (float)v->v_quad; - } else if (nt == DOUBLE || nt == DCOMPLEX) { - nv->v_ldbl = (ot == PTR || isutyp(ot)) ? - (double)(u_quad_t)v->v_quad : (double)v->v_quad; - } else if (nt == LDOUBLE || nt == LDCOMPLEX) { - nv->v_ldbl = (ot == PTR || isutyp(ot)) ? - (ldbl_t)(u_quad_t)v->v_quad : (ldbl_t)v->v_quad; - } else if (nt == IMAGINARY || nt == DIMAGINARY || - nt == LDIMAGINARY) { - nv->v_ldbl = 0; - } else { - rchk = 1; /* Check for lost precision. */ - nv->v_quad = v->v_quad; - } - } - - if (v->v_ansiu && isftyp(nt)) { - /* ANSI C treats constant as unsigned */ - warning(157); - v->v_ansiu = 0; - } else if (v->v_ansiu && (isityp(nt) && !isutyp(nt) && - psize(nt) > psize(ot))) { - /* ANSI C treats constant as unsigned */ - warning(157); - v->v_ansiu = 0; - } - - if (nt != FLOAT && nt != DOUBLE && nt != LDOUBLE) { - sz = tp->t_isfield ? tp->t_flen : size(nt); - nv->v_quad = xsign(nv->v_quad, nt, sz); - } - - if (rchk && op != CVT) { - osz = size(ot); - nsz = tp->t_isfield ? tp->t_flen : size(nt); - xmask = qlmasks[nsz] ^ qlmasks[osz]; - xmsk1 = qlmasks[nsz] ^ qlmasks[osz - 1]; - /* - * For bitwise operations we are not interested in the - * value, but in the bits itself. - */ - if (op == ORASS || op == OR || op == XOR) { - /* - * Print a warning if bits which were set are - * lost due to the conversion. - * This can happen with operator ORASS only. - */ - if (nsz < osz && (v->v_quad & xmask) != 0) { - /* constant truncated by conv., op %s */ - warning(306, modtab[op].m_name); - } - } else if (op == ANDASS || op == AND) { - /* - * Print a warning if additional bits are not all 1 - * and the most significant bit of the old value is 1, - * or if at least one (but not all) removed bit was 0. - */ - if (nsz > osz && - (nv->v_quad & qbmasks[osz - 1]) != 0 && - (nv->v_quad & xmask) != xmask) { - /* - * extra bits set to 0 in conversion - * of '%s' to '%s', op %s - */ - warning(309, tyname(gettyp(ot)), - tyname(tp), modtab[op].m_name); - } else if (nsz < osz && - (v->v_quad & xmask) != xmask && - (v->v_quad & xmask) != 0) { - /* const. truncated by conv., op %s */ - warning(306, modtab[op].m_name); - } - } else if ((nt != PTR && isutyp(nt)) && - (ot != PTR && !isutyp(ot)) && v->v_quad < 0) { - if ((nt == CHAR || nt == UCHAR || nt == SCHAR) && - v->v_lspec == CHAR) { - /* - * Don't warn when assigning a character - * literal to any kind of character (signed, - * unsigned, or unspecified). - */ - } else if (op == ASSIGN) { - /* assignment of negative constant to ... */ - warning(164); - } else if (op == INIT) { - /* initialisation of unsigned with neg. ... */ - warning(221); - } else if (op == FARG) { - /* %s arg #%d: conversion of neg. const... */ - warning(296, funcname(farg->fa_func), arg); - } else if (modtab[op].m_comp) { - /* we get this warning already in chkcomp() */ - } else { - /* conversion of negative constant to ... */ - warning(222); - } - } else if (nv->v_quad != v->v_quad && nsz <= osz && - (v->v_quad & xmask) != 0 && - (isutyp(ot) || (v->v_quad & xmsk1) != xmsk1)) { - /* - * Loss of significant bit(s). All truncated bits - * of unsigned types or all truncated bits plus the - * msb of the target for signed types are considered - * to be significant bits. Loss of significant bits - * means that at least on of the bits was set in an - * unsigned type or that at least one, but not all of - * the bits was set in an signed type. - * Loss of significant bits means that it is not - * possible, also not with necessary casts, to convert - * back to the original type. A example for a - * necessary cast is: - * char c; int i; c = 128; - * i = c; ** yields -128 ** - * i = (unsigned char)c; ** yields 128 ** - */ - if ((nt == CHAR || nt == UCHAR || nt == SCHAR) && - v->v_lspec == CHAR) { - /* - * Don't warn when assigning a character - * literal to any kind of character (signed, - * unsigned, or unspecified). - */ - } else if (op == ASSIGN && tp->t_isfield) { - /* precision lost in bit-field assignment */ - warning(166); - } else if (op == ASSIGN) { - /* constant truncated by assignment */ - warning(165); - } else if (op == INIT && tp->t_isfield) { - /* bit-field initializer does not fit */ - warning(180); - } else if (op == INIT) { - /* initializer does not fit */ - warning(178); - } else if (op == CASE) { - /* case label affected by conversion */ - warning(196); - } else if (op == FARG) { - /* %s arg #%d: conv. of %s to %s is out of rng. */ - warning(295, funcname(farg->fa_func), arg, - tyname(gettyp(ot)), tyname(tp)); - } else { - /* conversion of %s to %s is out of range */ - warning(119, tyname(gettyp(ot)), tyname(tp)); - } - } else if (nv->v_quad != v->v_quad) { - if ((nt == CHAR || nt == UCHAR || nt == SCHAR) && - v->v_lspec == CHAR) { - /* - * Don't warn when assigning a character - * literal to any kind of character (signed, - * unsigned, or unspecified). - */ - } else if (op == ASSIGN && tp->t_isfield) { - /* precision lost in bit-field assignment */ - warning(166); - } else if (op == INIT && tp->t_isfield) { - /* bit-field initializer out of range */ - warning(11); - } else if (op == CASE) { - /* case label affected by conversion */ - warning(196); - } else if (op == FARG) { - /* %s arg #%d: conv. of %s to %s is out of rng. */ - warning(295, funcname(farg->fa_func), arg, - tyname(gettyp(ot)), tyname(tp)); - } else { - /* conversion of %s to %s is out of range */ - warning(119, tyname(gettyp(ot)), tyname(tp)); - } - } - } -} - -/* - * Called if incompatible types were detected. - * Prints a appropriate warning. - */ -static void -incompat(op_t op, tspec_t lt, tspec_t rt) -{ - mod_t *mp; - - mp = &modtab[op]; - - if (lt == VOID || (mp->m_binary && rt == VOID)) { - /* void type illegal in expression */ - error(109); - } else if (op == ASSIGN) { - if ((lt == STRUCT || lt == UNION) && - (rt == STRUCT || rt == UNION)) { - /* assignment of different structures */ - error(240); - } else { - /* assignment type mismatch */ - error(171); - } - } else if (mp->m_binary) { - /* operands of %s have incompatible types */ - error(107, mp->m_name); - } else { - /* operand of %s has incompatible type */ - error(108, mp->m_name); - } -} - -/* - * Called if incompatible pointer types are detected. - * Print an appropriate warning. - */ -static void -illptrc(mod_t *mp, type_t *ltp, type_t *rtp) -{ - tspec_t lt, rt; - - if (ltp->t_tspec != PTR || rtp->t_tspec != PTR) - lerror("illptrc() 1"); - - lt = ltp->t_subt->t_tspec; - rt = rtp->t_subt->t_tspec; - - if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { - if (mp == NULL) { - /* illegal structure pointer combination */ - warning(244); - } else { - /* illegal structure pointer combination, op %s */ - warning(245, mp->m_name); - } - } else { - if (mp == NULL) { - /* illegal pointer combination */ - warning(184); - } else { - /* illegal pointer combination, op %s */ - warning(124, mp->m_name); - } - } -} - -/* - * Make sure type (*tpp)->t_subt has at least the qualifiers - * of tp1->t_subt and tp2->t_subt. - */ -static void -mrgqual(type_t **tpp, type_t *tp1, type_t *tp2) -{ - if ((*tpp)->t_tspec != PTR || - tp1->t_tspec != PTR || tp2->t_tspec != PTR) { - lerror("mrgqual()"); - } - - if ((*tpp)->t_subt->t_const == - (tp1->t_subt->t_const | tp2->t_subt->t_const) && - (*tpp)->t_subt->t_volatile == - (tp1->t_subt->t_volatile | tp2->t_subt->t_volatile)) { - return; - } - - *tpp = tduptyp(*tpp); - (*tpp)->t_subt = tduptyp((*tpp)->t_subt); - (*tpp)->t_subt->t_const = - tp1->t_subt->t_const | tp2->t_subt->t_const; - (*tpp)->t_subt->t_volatile = - tp1->t_subt->t_volatile | tp2->t_subt->t_volatile; -} - -/* - * Returns 1 if the given structure or union has a constant member - * (maybe recursively). - */ -static int -conmemb(type_t *tp) -{ - sym_t *m; - tspec_t t; - - if ((t = tp->t_tspec) != STRUCT && t != UNION) - lerror("conmemb()"); - for (m = tp->t_str->memb; m != NULL; m = m->s_nxt) { - tp = m->s_type; - if (tp->t_const) - return (1); - if ((t = tp->t_tspec) == STRUCT || t == UNION) { - if (conmemb(m->s_type)) - return (1); - } - } - return (0); -} - -const char * -tyname(type_t *tp) -{ - tspec_t t; - const char *s; - - if ((t = tp->t_tspec) == INT && tp->t_isenum) - t = ENUM; - - switch (t) { - case BOOL: s = "_Bool"; break; - case CHAR: s = "char"; break; - case UCHAR: s = "unsigned char"; break; - case SCHAR: s = "signed char"; break; - case SHORT: s = "short"; break; - case USHORT: s = "unsigned short"; break; - case INT: s = "int"; break; - case UINT: s = "unsigned int"; break; - case LONG: s = "long"; break; - case ULONG: s = "unsigned long"; break; - case QUAD: s = "long long"; break; - case UQUAD: s = "unsigned long long"; break; - case FLOAT: s = "float"; break; - case DOUBLE: s = "double"; break; - case LDOUBLE: s = "long double"; break; - case COMPLEX: s = "float _Complex"; break; - case DCOMPLEX: s = "double _Complex"; break; - case LDCOMPLEX: s = "long double _Complex"; break; - case IMAGINARY: s = "float _Imaginary"; break; - case DIMAGINARY: s = "double _Imaginary"; break; - case LDIMAGINARY:s = "long double _Imaginary"; break; - case PTR: s = "pointer"; break; - case ENUM: s = "enum"; break; - case STRUCT: s = "struct"; break; - case UNION: s = "union"; break; - case FUNC: s = "function"; break; - case ARRAY: s = "array"; break; - default: - lerror("tyname()"); - } - return (s); -} - -/* - * Create a new node for one of the operators POINT and ARROW. - */ -static tnode_t * -bldstr(op_t op, tnode_t *ln, tnode_t *rn) -{ - tnode_t *ntn, *ctn; - int nolval; - - if (rn->tn_op != NAME) - lerror("bldstr() 1"); - if (rn->tn_sym->s_value.v_tspec != INT) - lerror("bldstr() 2"); - if (rn->tn_sym->s_scl != MOS && rn->tn_sym->s_scl != MOU) - lerror("bldstr() 3"); - - /* - * Remember if the left operand is an lvalue (structure members - * are lvalues if and only if the structure itself is an lvalue). - */ - nolval = op == POINT && !ln->tn_lvalue; - - if (op == POINT) { - ln = bldamper(ln, 1); - } else if (ln->tn_type->t_tspec != PTR) { - lerror("bldstr() 4"); - ln = convert(NOOP, NULL, tincref(gettyp(VOID), PTR), ln); - } - -#if PTRDIFF_IS_LONG - ctn = getinode(LONG, rn->tn_sym->s_value.v_quad / CHAR_BIT); -#else - ctn = getinode(INT, rn->tn_sym->s_value.v_quad / CHAR_BIT); -#endif - - ntn = mktnode(PLUS, tincref(rn->tn_type, PTR), ln, ctn); - if (ln->tn_op == CON) - ntn = fold(ntn); - - if (rn->tn_type->t_isfield) { - ntn = mktnode(FSEL, ntn->tn_type->t_subt, ntn, NULL); - } else { - ntn = mktnode(STAR, ntn->tn_type->t_subt, ntn, NULL); - } - - if (nolval) - ntn->tn_lvalue = 0; - - return (ntn); -} - -/* - * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. - */ -static tnode_t * -bldincdec(op_t op, tnode_t *ln) -{ - tnode_t *cn, *ntn; - - if (ln == NULL) - lerror("bldincdec() 1"); - - if (ln->tn_type->t_tspec == PTR) { - cn = plength(ln->tn_type); - } else { - cn = getinode(INT, (quad_t)1); - } - ntn = mktnode(op, ln->tn_type, ln, cn); - - return (ntn); -} - -/* - * Create a tree node for the & operator - */ -static tnode_t * -bldamper(tnode_t *tn, int noign) -{ - tnode_t *ntn; - tspec_t t; - - if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { - /* & before array or function: ignored */ - return (tn); - } - - /* eliminate &* */ - if (tn->tn_op == STAR && - tn->tn_left->tn_type->t_tspec == PTR && - tn->tn_left->tn_type->t_subt == tn->tn_type) { - return (tn->tn_left); - } - - ntn = mktnode(AMPER, tincref(tn->tn_type, PTR), tn, NULL); - - return (ntn); -} - -/* - * Create a node for operators PLUS and MINUS. - */ -static tnode_t * -bldplmi(op_t op, tnode_t *ln, tnode_t *rn) -{ - tnode_t *ntn, *ctn; - type_t *tp; - - /* If pointer and integer, then pointer to the lhs. */ - if (rn->tn_type->t_tspec == PTR && isityp(ln->tn_type->t_tspec)) { - ntn = ln; - ln = rn; - rn = ntn; - } - - if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { - - if (!isityp(rn->tn_type->t_tspec)) - lerror("bldplmi() 1"); - - ctn = plength(ln->tn_type); - if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) - rn = convert(NOOP, NULL, ctn->tn_type, rn); - rn = mktnode(MULT, rn->tn_type, rn, ctn); - if (rn->tn_left->tn_op == CON) - rn = fold(rn); - ntn = mktnode(op, ln->tn_type, ln, rn); - - } else if (rn->tn_type->t_tspec == PTR) { - - if (ln->tn_type->t_tspec != PTR || op != MINUS) - lerror("bldplmi() 2"); -#if PTRDIFF_IS_LONG - tp = gettyp(LONG); -#else - tp = gettyp(INT); -#endif - ntn = mktnode(op, tp, ln, rn); - if (ln->tn_op == CON && rn->tn_op == CON) - ntn = fold(ntn); - ctn = plength(ln->tn_type); - balance(NOOP, &ntn, &ctn); - ntn = mktnode(DIV, tp, ntn, ctn); - - } else { - - ntn = mktnode(op, ln->tn_type, ln, rn); - - } - return (ntn); -} - -/* - * Create a node for operators SHL and SHR. - */ -static tnode_t * -bldshft(op_t op, tnode_t *ln, tnode_t *rn) -{ - tspec_t t; - tnode_t *ntn; - - if ((t = rn->tn_type->t_tspec) != INT && t != UINT) - rn = convert(CVT, NULL, gettyp(INT), rn); - ntn = mktnode(op, ln->tn_type, ln, rn); - return (ntn); -} - -/* - * Create a node for COLON. - */ -static tnode_t * -bldcol(tnode_t *ln, tnode_t *rn) -{ - tspec_t lt, rt, pdt; - type_t *rtp; - tnode_t *ntn; - - lt = ln->tn_type->t_tspec; - rt = rn->tn_type->t_tspec; -#if PTRDIFF_IS_LONG - pdt = LONG; -#else - pdt = INT; -#endif - - /* - * Arithmetic types are balanced, all other type combinations - * still need to be handled. - */ - if (isatyp(lt) && isatyp(rt)) { - rtp = ln->tn_type; - } else if (lt == VOID || rt == VOID) { - rtp = gettyp(VOID); - } else if (lt == STRUCT || lt == UNION) { - /* Both types must be identical. */ - if (rt != STRUCT && rt != UNION) - lerror("bldcol() 1"); - if (ln->tn_type->t_str != rn->tn_type->t_str) - lerror("bldcol() 2"); - if (incompl(ln->tn_type)) { - /* unknown operand size, op %s */ - error(138, modtab[COLON].m_name); - return (NULL); - } - rtp = ln->tn_type; - } else if (lt == PTR && isityp(rt)) { - if (rt != pdt) { - rn = convert(NOOP, NULL, gettyp(pdt), rn); - rt = pdt; - } - rtp = ln->tn_type; - } else if (rt == PTR && isityp(lt)) { - if (lt != pdt) { - ln = convert(NOOP, NULL, gettyp(pdt), ln); - lt = pdt; - } - rtp = rn->tn_type; - } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { - if (rt != PTR) - lerror("bldcol() 4"); - rtp = ln->tn_type; - mrgqual(&rtp, ln->tn_type, rn->tn_type); - } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { - if (lt != PTR) - lerror("bldcol() 5"); - rtp = rn->tn_type; - mrgqual(&rtp, ln->tn_type, rn->tn_type); - } else { - if (lt != PTR || rt != PTR) - lerror("bldcol() 6"); - /* - * XXX For now we simply take the left type. This is - * probably wrong, if one type contains a function prototype - * and the other one, at the same place, only an old style - * declaration. - */ - rtp = ln->tn_type; - mrgqual(&rtp, ln->tn_type, rn->tn_type); - } - - ntn = mktnode(COLON, rtp, ln, rn); - - return (ntn); -} - -/* - * Create a node for an assignment operator (both = and op= ). - */ -static tnode_t * -bldasgn(op_t op, tnode_t *ln, tnode_t *rn) -{ - tspec_t lt, rt; - tnode_t *ntn, *ctn; - - if (ln == NULL || rn == NULL) - lerror("bldasgn() 1"); - - lt = ln->tn_type->t_tspec; - rt = rn->tn_type->t_tspec; - - if ((op == ADDASS || op == SUBASS) && lt == PTR) { - if (!isityp(rt)) - lerror("bldasgn() 2"); - ctn = plength(ln->tn_type); - if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) - rn = convert(NOOP, NULL, ctn->tn_type, rn); - rn = mktnode(MULT, rn->tn_type, rn, ctn); - if (rn->tn_left->tn_op == CON) - rn = fold(rn); - } - - if ((op == ASSIGN || op == RETURN) && (lt == STRUCT || rt == STRUCT)) { - if (rt != lt || ln->tn_type->t_str != rn->tn_type->t_str) - lerror("bldasgn() 3"); - if (incompl(ln->tn_type)) { - if (op == RETURN) { - /* cannot return incomplete type */ - error(212); - } else { - /* unknown operand size, op %s */ - error(138, modtab[op].m_name); - } - return (NULL); - } - } - - if (op == SHLASS || op == SHRASS) { - if (rt != INT) { - rn = convert(NOOP, NULL, gettyp(INT), rn); - rt = INT; - } - } else { - if (op == ASSIGN || lt != PTR) { - if (lt != rt || - (ln->tn_type->t_isfield && rn->tn_op == CON)) { - rn = convert(op, NULL, ln->tn_type, rn); - rt = lt; - } - } - } - - ntn = mktnode(op, ln->tn_type, ln, rn); - - return (ntn); -} - -/* - * Check for division by zero. Returns 1 if a division by zero is - * present, 0 otherwise. - */ -static int -chkdbz(op_t op, tnode_t *rn) -{ - int code; - - switch (op) { - case DIV: - case DIVASS: - code = 139; /* division by 0 */ - break; - case MOD: - case MODASS: - code = 140; /* modular division by 0 */ - break; - default: - return 0; - } - - /* no way of checking unless right side is a constant */ - if (rn->tn_op != CON) - return 0; - - if (isftyp(rn->tn_type->t_tspec)) { - if (rn->tn_val->v_ldbl == 0.0) { - /* division by 0 */ - warning(code); - return 1; - } - } else { - if (rn->tn_val->v_quad == 0) { - /* division by 0 */ - warning(code); - return 1; - } - } - - return 0; -} - -/* - * Get length of type tp->t_subt. - */ -static tnode_t * -plength(type_t *tp) -{ - int elem, elsz; - tspec_t st; - - if (tp->t_tspec != PTR) - lerror("plength() 1"); - tp = tp->t_subt; - - elem = 1; - elsz = 0; - - while (tp->t_tspec == ARRAY) { - elem *= tp->t_dim; - tp = tp->t_subt; - } - - switch (tp->t_tspec) { - case FUNC: - /* pointer to function is not allowed here */ - error(110); - break; - case VOID: - /* cannot do pointer arithmetic on operand of ... */ - (void)gnuism(136); - break; - case STRUCT: - case UNION: - if ((elsz = tp->t_str->size) == 0) - /* cannot do pointer arithmetic on operand of ... */ - error(136); - break; - case ENUM: - if (incompl(tp)) { - /* cannot do pointer arithmetic on operand of ... */ - warning(136); - } - /* FALLTHROUGH */ - default: - if ((elsz = size(tp->t_tspec)) == 0) { - /* cannot do pointer arithmetic on operand of ... */ - error(136); - } else if (elsz == -1) { - lerror("plength() 2"); - } - break; - } - - if (elem == 0 && elsz != 0) { - /* cannot do pointer arithmetic on operand of ... */ - error(136); - } - - if (elsz == 0) - elsz = CHAR_BIT; - -#if PTRDIFF_IS_LONG - st = LONG; -#else - st = INT; -#endif - - return (getinode(st, (quad_t)(elem * elsz / CHAR_BIT))); -} - -/* - * Do only as much as necessary to compute constant expressions. - * Called only if the operator allows folding and (both) operands - * are constants. - */ -static tnode_t * -fold(tnode_t *tn) -{ - val_t *v; - tspec_t t; - int utyp, ovfl; - quad_t sl, sr, q, mask; - u_quad_t ul, ur; - tnode_t *cn; - - v = xcalloc(1, sizeof (val_t)); - v->v_tspec = t = tn->tn_type->t_tspec; - - utyp = t == PTR || isutyp(t); - ul = sl = tn->tn_left->tn_val->v_quad; - if (modtab[tn->tn_op].m_binary) - ur = sr = tn->tn_right->tn_val->v_quad; - - ovfl = 0; - - switch (tn->tn_op) { - case UPLUS: - q = sl; - break; - case UMINUS: - q = -sl; - if (msb(q, t, -1) == msb(sl, t, -1)) - ovfl = 1; - break; - case COMPL: - q = ~sl; - break; - case MULT: - q = utyp ? ul * ur : sl * sr; - if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1))) - ovfl = 1; - break; - case DIV: - if (chkdbz(tn->tn_op, tn->tn_right)) { - q = utyp ? 0U: 0; - } else { - q = utyp ? ul / ur : sl / sr; - } - break; - case MOD: - if (chkdbz(tn->tn_op, tn->tn_right)) { - q = 0; - } else { - q = utyp ? ul % ur : sl % sr; - } - break; - case PLUS: - q = utyp ? ul + ur : sl + sr; - if (msb(sl, t, -1) != 0 && msb(sr, t, -1) != 0) { - if (msb(q, t, -1) == 0) - ovfl = 1; - } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) == 0) { - if (msb(q, t, -1) != 0) - ovfl = 1; - } - break; - case MINUS: - q = utyp ? ul - ur : sl - sr; - if (msb(sl, t, -1) != 0 && msb(sr, t, -1) == 0) { - if (msb(q, t, -1) == 0) - ovfl = 1; - } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) != 0) { - if (msb(q, t, -1) != 0) - ovfl = 1; - } - break; - case SHL: - q = utyp ? ul << sr : sl << sr; - break; - case SHR: - /* - * The sign must be explicitly extended because - * shifts of signed values are implementation dependent. - */ - q = ul >> sr; - q = xsign(q, t, size(t) - (int)sr); - break; - case LT: - q = utyp ? ul < ur : sl < sr; - break; - case LE: - q = utyp ? ul <= ur : sl <= sr; - break; - case GE: - q = utyp ? ul >= ur : sl >= sr; - break; - case GT: - q = utyp ? ul > ur : sl > sr; - break; - case EQ: - q = utyp ? ul == ur : sl == sr; - break; - case NE: - q = utyp ? ul != ur : sl != sr; - break; - case AND: - q = utyp ? ul & ur : sl & sr; - break; - case XOR: - q = utyp ? ul ^ ur : sl ^ sr; - break; - case OR: - q = utyp ? ul | ur : sl | sr; - break; - case REAL: - case IMAG: - q = sl; - default: - lerror("fold() 5"); - } - - mask = qlmasks[size(t)]; - - /* XXX does not work for quads. */ - if (ovfl || ((q | mask) != ~(u_quad_t)0 && (q & ~mask) != 0)) { - if (hflag) - /* integer overflow detected, op %s */ - warning(141, modtab[tn->tn_op].m_name); - } - - v->v_quad = xsign(q, t, -1); - - cn = getcnode(tn->tn_type, v); - - return (cn); -} - -/* - * Same for operators whose operands are compared with 0 (test context). - */ -static tnode_t * -foldtst(tnode_t *tn) -{ - int l, r; - val_t *v; - - v = xcalloc(1, sizeof (val_t)); - v->v_tspec = tn->tn_type->t_tspec; - if (tn->tn_type->t_tspec != INT) - lerror("foldtst() 1"); - - if (isftyp(tn->tn_left->tn_type->t_tspec)) { - l = tn->tn_left->tn_val->v_ldbl != 0.0; - } else { - l = tn->tn_left->tn_val->v_quad != 0; - } - - if (modtab[tn->tn_op].m_binary) { - if (isftyp(tn->tn_right->tn_type->t_tspec)) { - r = tn->tn_right->tn_val->v_ldbl != 0.0; - } else { - r = tn->tn_right->tn_val->v_quad != 0; - } - } - - switch (tn->tn_op) { - case NOT: - if (hflag) - /* constant argument to NOT */ - warning(239); - v->v_quad = !l; - break; - case LOGAND: - v->v_quad = l && r; - break; - case LOGOR: - v->v_quad = l || r; - break; - default: - lerror("foldtst() 1"); - } - - return (getcnode(tn->tn_type, v)); -} - -/* - * Same for operands with floating point type. - */ -static tnode_t * -foldflt(tnode_t *tn) -{ - val_t *v; - tspec_t t; - ldbl_t l, r; - - v = xcalloc(1, sizeof (val_t)); - v->v_tspec = t = tn->tn_type->t_tspec; - - if (!isftyp(t)) - lerror("foldflt() 1"); - - if (t != tn->tn_left->tn_type->t_tspec) - lerror("foldflt() 2"); - if (modtab[tn->tn_op].m_binary && t != tn->tn_right->tn_type->t_tspec) - lerror("foldflt() 3"); - - l = tn->tn_left->tn_val->v_ldbl; - if (modtab[tn->tn_op].m_binary) - r = tn->tn_right->tn_val->v_ldbl; - - switch (tn->tn_op) { - case UPLUS: - v->v_ldbl = l; - break; - case UMINUS: - v->v_ldbl = -l; - break; - case MULT: - v->v_ldbl = l * r; - break; - case DIV: - if (chkdbz(tn->tn_op, tn->tn_right)) { - if (t == FLOAT) { - v->v_ldbl = l < 0 ? -FLT_MAX : FLT_MAX; - } else if (t == DOUBLE) { - v->v_ldbl = l < 0 ? -DBL_MAX : DBL_MAX; - } else { - v->v_ldbl = l < 0 ? -LDBL_MAX : LDBL_MAX; - } - } else { - v->v_ldbl = l / r; - } - break; - case PLUS: - v->v_ldbl = l + r; - break; - case MINUS: - v->v_ldbl = l - r; - break; - case LT: - v->v_quad = l < r; - break; - case LE: - v->v_quad = l <= r; - break; - case GE: - v->v_quad = l >= r; - break; - case GT: - v->v_quad = l > r; - break; - case EQ: - v->v_quad = l == r; - break; - case NE: - v->v_quad = l != r; - break; - case REAL: - case IMAG: - v->v_ldbl = l; - break; - default: - lerror("foldflt() 4"); - } - - if (isnan((double)v->v_ldbl)) - lerror("foldflt() 5"); - if (isinf((double)v->v_ldbl) || - (t == FLOAT && - (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || - (t == DOUBLE && - (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { - /* floating point overflow detected, op %s */ - warning(142, modtab[tn->tn_op].m_name); - if (t == FLOAT) { - v->v_ldbl = v->v_ldbl < 0 ? -FLT_MAX : FLT_MAX; - } else if (t == DOUBLE) { - v->v_ldbl = v->v_ldbl < 0 ? -DBL_MAX : DBL_MAX; - } else { - v->v_ldbl = v->v_ldbl < 0 ? -LDBL_MAX: LDBL_MAX; - } - } - - return (getcnode(tn->tn_type, v)); -} - -/* - * Create a constant node for sizeof(term). - */ -tnode_t * -bldszoftrm(tnode_t *tn) -{ - switch (tn->tn_op) { - case POINT: - case STAR: - case NAME: - case STRING: - case REAL: - case IMAG: - break; - default: - warning(312, modtab[tn->tn_op].m_name); - } - - - return bldszof(tn->tn_type); -} - -/* - * Create a constant node for sizeof. - */ -tnode_t * -bldszof(type_t *tp) -{ - int elem, elsz; - tspec_t st; - - elem = 1; - while (tp->t_tspec == ARRAY) { - elem *= tp->t_dim; - tp = tp->t_subt; - } - if (elem == 0) { - /* cannot take size of incomplete type */ - error(143); - elem = 1; - } - switch (tp->t_tspec) { - case FUNC: - /* cannot take size of function */ - error(144); - elsz = 1; - break; - case STRUCT: - case UNION: - if (incompl(tp)) { - /* cannot take size of incomplete type */ - error(143); - elsz = 1; - } else { - elsz = tp->t_str->size; - } - break; - case ENUM: - if (incompl(tp)) { - /* cannot take size of incomplete type */ - warning(143); - } - /* FALLTHROUGH */ - default: - if (tp->t_isfield) { - /* cannot take size of bit-field */ - error(145); - } - if (tp->t_tspec == VOID) { - /* cannot take size of void */ - error(146); - elsz = 1; - } else { - elsz = size(tp->t_tspec); - if (elsz <= 0) - lerror("bldszof() 1"); - } - break; - } - -#if SIZEOF_IS_ULONG - st = ULONG; -#else - st = UINT; -#endif - - return (getinode(st, (quad_t)(elem * elsz / CHAR_BIT))); -} - -/* - * Type casts. - */ -tnode_t * -cast(tnode_t *tn, type_t *tp) -{ - tspec_t nt, ot; - - if (tn == NULL) - return (NULL); - - tn = cconv(tn); - - nt = tp->t_tspec; - ot = tn->tn_type->t_tspec; - - if (nt == VOID) { - /* - * XXX ANSI C requires scalar types or void (Plauger&Brodie). - * But this seams really questionable. - */ - } else if (nt == STRUCT || nt == UNION || nt == ARRAY || nt == FUNC) { - /* invalid cast expression */ - error(147); - return (NULL); - } else if (ot == STRUCT || ot == UNION) { - /* invalid cast expression */ - error(147); - return (NULL); - } else if (ot == VOID) { - /* improper cast of void expression */ - error(148); - return (NULL); - } else if (isityp(nt) && issclt(ot)) { - /* ok */ - } else if (isftyp(nt) && isatyp(ot)) { - /* ok */ - } else if (nt == PTR && isityp(ot)) { - /* ok */ - } else if (nt == PTR && ot == PTR) { - if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { - if (hflag) - /* cast discards 'const' from ... */ - warning(275); - } - } else { - /* invalid cast expression */ - error(147); - return (NULL); - } - - tn = convert(CVT, NULL, tp, tn); - tn->tn_cast = 1; - - return (tn); -} - -/* - * Create the node for a function argument. - * All necessary conversions and type checks are done in funccall(), because - * in funcarg() we have no information about expected argument types. - */ -tnode_t * -funcarg(tnode_t *args, tnode_t *arg) -{ - tnode_t *ntn; - - /* - * If there was a serious error in the expression for the argument, - * create a dummy argument so the positions of the remaining arguments - * will not change. - */ - if (arg == NULL) - arg = getinode(INT, (quad_t)0); - - ntn = mktnode(PUSH, arg->tn_type, arg, args); - - return (ntn); -} - -/* - * Create the node for a function call. Also check types of - * function arguments and insert conversions, if necessary. - */ -tnode_t * -funccall(tnode_t *func, tnode_t *args) -{ - tnode_t *ntn; - op_t fcop; - - if (func == NULL) - return (NULL); - - if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { - fcop = CALL; - } else { - fcop = ICALL; - } - - /* - * after cconv() func will always be a pointer to a function - * if it is a valid function designator. - */ - func = cconv(func); - - if (func->tn_type->t_tspec != PTR || - func->tn_type->t_subt->t_tspec != FUNC) { - /* illegal function */ - error(149); - return (NULL); - } - - args = chkfarg(func, args); - - ntn = mktnode(fcop, func->tn_type->t_subt->t_subt, func, args); - - return (ntn); -} - -/* - * Check types of all function arguments and insert conversions, - * if necessary. - * - * func: called function - * args: arguments to function - */ -static tnode_t * -chkfarg(tnode_t *func, tnode_t *args) -{ - type_t *ftp; - tnode_t *arg; - sym_t *asym; - farg_t farg; - tspec_t at; - int narg, npar, n, i; - - ftp = func->tn_type->t_subt; - - /* get # of args in the prototype */ - npar = 0; - for (asym = ftp->t_args; asym != NULL; asym = asym->s_nxt) - npar++; - - /* get # of args in function call */ - narg = 0; - for (arg = args; arg != NULL; arg = arg->tn_right) - narg++; - - asym = ftp->t_args; - if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { - /* argument mismatch: %d arg%s passed, %d expected */ - error(150, narg, narg > 1 ? "s" : "", npar); - asym = NULL; - } - - for (n = 1; n <= narg; n++) { - - /* - * The rightmost argument is at the top of the argument - * subtree. - */ - for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) ; - - /* some things which are never allowed */ - if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { - /* void expressions may not be arguments, arg #%d */ - error(151, n); - return (NULL); - } else if ((at == STRUCT || at == UNION) && - incompl(arg->tn_left->tn_type)) { - /* argument cannot have unknown size, arg #%d */ - error(152, n); - return (NULL); - } else if (isityp(at) && arg->tn_left->tn_type->t_isenum && - incompl(arg->tn_left->tn_type)) { - /* argument cannot have unknown size, arg #%d */ - warning(152, n); - } - - /* class conversions (arg in value context) */ - arg->tn_left = cconv(arg->tn_left); - farg.fa_num = n; - farg.fa_sym = asym; - farg.fa_func = func; - if (asym != NULL) { - arg->tn_left = parg(&farg, arg->tn_left); - } else { - arg->tn_left = promote(NOOP, 1, arg->tn_left); - } - arg->tn_type = arg->tn_left->tn_type; - - if (asym != NULL) - asym = asym->s_nxt; - } - - return (args); -} - -/* - * Compare the type of an argument with the corresponding type of a - * prototype parameter. If it is a valid combination, but both types - * are not the same, insert a conversion to convert the argument into - * the type of the parameter. - * - * n: position of arg - * tp: expected type (from prototype) - * tn: argument - */ -static tnode_t * -parg(farg_t *farg, tnode_t *tn) -{ - tnode_t *ln; - type_t *tp; - int warn; - - tp = farg->fa_sym->s_type; - ln = xcalloc(1, sizeof (tnode_t)); - ln->tn_type = tduptyp(tp); - ln->tn_type->t_const = 0; - ln->tn_lvalue = 1; - if (typeok(FARG, farg, ln, tn)) { - if (!eqtype(tp, tn->tn_type, 1, 0, (warn = 0, &warn)) || warn) - tn = convert(FARG, farg, tp, tn); - } - free(ln); - return (tn); -} - -/* - * Return the value of an integral constant expression. - * If the expression is not constant or its type is not an integer - * type, an error message is printed. - */ -val_t * -constant(tnode_t *tn) -{ - val_t *v; - - if (tn != NULL) - tn = cconv(tn); - if (tn != NULL) - tn = promote(NOOP, 0, tn); - - v = xcalloc(1, sizeof (val_t)); - - if (tn == NULL) { - if (nerr == 0) - lerror("constant() 1"); - v->v_tspec = INT; - v->v_quad = 1; - return (v); - } - - v->v_tspec = tn->tn_type->t_tspec; - - if (tn->tn_op == CON) { - if (tn->tn_type->t_tspec != tn->tn_val->v_tspec) - lerror("constant() 2"); - if (isityp(tn->tn_val->v_tspec)) { - v->v_ansiu = tn->tn_val->v_ansiu; - v->v_quad = tn->tn_val->v_quad; - return (v); - } - v->v_quad = tn->tn_val->v_ldbl; - } else { - v->v_quad = 1; - } - - /* integral constant expression expected */ - error(55); - - if (!isityp(v->v_tspec)) - v->v_tspec = INT; - - return (v); -} - -/* - * Perform some tests on expressions which can't be done in build() and - * functions called by build(). These tests must be done here because - * we need some information about the context in which the operations - * are performed. - * After all tests are performed, expr() frees the memory which is used - * for the expression. - */ -void -expr(tnode_t *tn, int vctx, int tctx) -{ - if (tn == NULL && nerr == 0) - lerror("expr() 1"); - - if (tn == NULL) { - tfreeblk(); - return; - } - - /* expr() is also called in global initialisations */ - if (dcs->d_ctx != EXTERN) - chkreach(); - - chkmisc(tn, vctx, tctx, !tctx, 0, 0, 0); - if (tn->tn_op == ASSIGN) { - if (hflag && tctx && !tn->tn_parn) - /* assignment in conditional context */ - warning(159); - } else if (tn->tn_op == CON) { - if (hflag && tctx && !ccflg) { - if (!isityp(tn->tn_type->t_tspec) || - (tn->tn_val->v_quad != 0 && - tn->tn_val->v_quad != 1)) { - /* constant in conditional context */ - warning(161); - } - } - } else if (tn->tn_op == CALL && tn->tn_left->tn_op == AMPER) { - if (tn->tn_left->tn_left->tn_sym->s_noreturn) - reached = rchflg = 0; - } - - if (!modtab[tn->tn_op].m_sideeff) { - /* - * for left operands of COMMA this warning is already - * printed - */ - if (tn->tn_op != COMMA && !vctx && !tctx) - nulleff(tn); - } - if (dflag) - displexpr(tn, 0); - - /* free the tree memory */ - tfreeblk(); -} - -static void -nulleff(tnode_t *tn) -{ - if (!hflag) - return; - if (nulleffexpr(tn)) { - /* expression has null effect */ - warning(129); - } -} - -static int -nulleffexpr(tnode_t *tn) -{ - int r1, r2; - - if (modtab[tn->tn_op].m_sideeff) - return (0); - - switch (tn->tn_op) { - case CVT: - if (tn->tn_type->t_tspec == VOID) - return (0); - else - return (nulleffexpr(tn->tn_left)); - case LOGAND: - case LOGOR: - /* - * && and || have a null effect if the right operand - * has null effect. - */ - return (nulleffexpr(tn->tn_right)); - case QUEST: - /* - * ? has null effect if both of its right * operands - * have null effect - */ - return (nulleffexpr(tn->tn_right)); - case COLON: - case COMMA: - /* - * : and , have null effect if both of the operands have - * null effect - */ - r1 = nulleffexpr(tn->tn_left); - r2 = nulleffexpr(tn->tn_right); - return (r1 && r2); - default: - return (1); - } -} - -/* - * Dump an expression to stdout - * only used for debugging - */ -void -displexpr(tnode_t *tn, int offs) -{ - u_quad_t uq; - - if (tn == NULL) { - (void)printf("%*s%s\n", offs, "", "NULL"); - return; - } - (void)printf("%*sop %s ", offs, "", modtab[tn->tn_op].m_name); - - if (tn->tn_op == NAME) { - (void)printf("%s: %s ", - tn->tn_sym->s_name, scltoa(tn->tn_sym->s_scl)); - } else if (tn->tn_op == CON && isftyp(tn->tn_type->t_tspec)) { - (void)printf("%#g ", (double)tn->tn_val->v_ldbl); - } else if (tn->tn_op == CON && isityp(tn->tn_type->t_tspec)) { - uq = tn->tn_val->v_quad; - (void)printf("0x %08lx %08lx ", (long)(uq >> 32) & 0xffffffffl, - (long)uq & 0xffffffffl); - } else if (tn->tn_op == CON) { - if (tn->tn_type->t_tspec != PTR) - lerror("displexpr() 1"); - (void)printf("0x%0*lx ", (int)(sizeof (void *) * CHAR_BIT / 4), - (u_long)tn->tn_val->v_quad); - } else if (tn->tn_op == STRING) { - if (tn->tn_strg->st_tspec == CHAR) { - (void)printf("\"%s\"", tn->tn_strg->st_cp); - } else { - char *s; - size_t n; - n = MB_CUR_MAX * (tn->tn_strg->st_len + 1); - s = xmalloc(n); - (void)wcstombs(s, tn->tn_strg->st_wcp, n); - (void)printf("L\"%s\"", s); - free(s); - } - (void)printf(" "); - } else if (tn->tn_op == FSEL) { - (void)printf("o=%d, l=%d ", tn->tn_type->t_foffs, - tn->tn_type->t_flen); - } - (void)printf("%s\n", ttos(tn->tn_type)); - if (tn->tn_op == NAME || tn->tn_op == CON || tn->tn_op == STRING) - return; - displexpr(tn->tn_left, offs + 2); - if (modtab[tn->tn_op].m_binary || - (tn->tn_op == PUSH && tn->tn_right != NULL)) { - displexpr(tn->tn_right, offs + 2); - } -} - -/* - * Called by expr() to recursively perform some tests. - */ -/* ARGSUSED */ -void -chkmisc(tnode_t *tn, int vctx, int tctx, int eqwarn, int fcall, int rvdisc, - int szof) -{ - tnode_t *ln, *rn; - mod_t *mp; - int nrvdisc, cvctx, ctctx; - op_t op; - scl_t sc; - dinfo_t *di; - - if (tn == NULL) - return; - - ln = tn->tn_left; - rn = tn->tn_right; - mp = &modtab[op = tn->tn_op]; - - switch (op) { - case AMPER: - if (ln->tn_op == NAME && (reached || rchflg)) { - if (!szof) - setsflg(ln->tn_sym); - setuflg(ln->tn_sym, fcall, szof); - } - if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) - /* check the range of array indices */ - chkaidx(ln->tn_left, 1); - break; - case LOAD: - if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) - /* check the range of array indices */ - chkaidx(ln->tn_left, 0); - /* FALLTHROUGH */ - case PUSH: - case INCBEF: - case DECBEF: - case INCAFT: - case DECAFT: - case ADDASS: - case SUBASS: - case MULASS: - case DIVASS: - case MODASS: - case ANDASS: - case ORASS: - case XORASS: - case SHLASS: - case SHRASS: - case REAL: - case IMAG: - if (ln->tn_op == NAME && (reached || rchflg)) { - sc = ln->tn_sym->s_scl; - /* - * Look if there was an asm statement in one of the - * compound statements we are in. If not, we don't - * print a warning. - */ - for (di = dcs; di != NULL; di = di->d_nxt) { - if (di->d_asm) - break; - } - if (sc != EXTERN && sc != STATIC && - !ln->tn_sym->s_set && !szof && di == NULL) { - /* %s may be used before set */ - warning(158, ln->tn_sym->s_name); - setsflg(ln->tn_sym); - } - setuflg(ln->tn_sym, 0, 0); - } - break; - case ASSIGN: - if (ln->tn_op == NAME && !szof && (reached || rchflg)) { - setsflg(ln->tn_sym); - if (ln->tn_sym->s_scl == EXTERN) - outusg(ln->tn_sym); - } - if (ln->tn_op == STAR && ln->tn_left->tn_op == PLUS) - /* check the range of array indices */ - chkaidx(ln->tn_left, 0); - break; - case CALL: - if (ln->tn_op != AMPER || ln->tn_left->tn_op != NAME) - lerror("chkmisc() 1"); - if (!szof) - outcall(tn, vctx || tctx, rvdisc); - break; - case EQ: - /* equality operator "==" found where "=" was exp. */ - if (hflag && eqwarn) - warning(160); - break; - case CON: - case NAME: - case STRING: - return; - /* LINTED (enumeration values not handled in switch) */ - } - - cvctx = mp->m_vctx; - ctctx = mp->m_tctx; - /* - * values of operands of ':' are not used if the type of at least - * one of the operands (for gcc compatibility) is void - * XXX test/value context of QUEST should probably be used as - * context for both operands of COLON - */ - if (op == COLON && tn->tn_type->t_tspec == VOID) - cvctx = ctctx = 0; - nrvdisc = op == CVT && tn->tn_type->t_tspec == VOID; - chkmisc(ln, cvctx, ctctx, mp->m_eqwarn, op == CALL, nrvdisc, szof); - - switch (op) { - case PUSH: - if (rn != NULL) - chkmisc(rn, 0, 0, mp->m_eqwarn, 0, 0, szof); - break; - case LOGAND: - case LOGOR: - chkmisc(rn, 0, 1, mp->m_eqwarn, 0, 0, szof); - break; - case COLON: - chkmisc(rn, cvctx, ctctx, mp->m_eqwarn, 0, 0, szof); - break; - default: - if (mp->m_binary) - chkmisc(rn, 1, 0, mp->m_eqwarn, 0, 0, szof); - break; - } - -} - -/* - * Checks the range of array indices, if possible. - * amper is set if only the address of the element is used. This - * means that the index is allowd to refer to the first element - * after the array. - */ -static void -chkaidx(tnode_t *tn, int amper) -{ - int dim; - tnode_t *ln, *rn; - int elsz; - quad_t con; - - ln = tn->tn_left; - rn = tn->tn_right; - - /* We can only check constant indices. */ - if (rn->tn_op != CON) - return; - - /* Return if the left node does not stem from an array. */ - if (ln->tn_op != AMPER) - return; - if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) - return; - if (ln->tn_left->tn_type->t_tspec != ARRAY) - return; - - /* - * For incomplete array types, we can print a warning only if - * the index is negative. - */ - if (incompl(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) - return; - - /* Get the size of one array element */ - if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) - return; - elsz /= CHAR_BIT; - - /* Change the unit of the index from bytes to element size. */ - if (isutyp(rn->tn_type->t_tspec)) { - con = (u_quad_t)rn->tn_val->v_quad / elsz; - } else { - con = rn->tn_val->v_quad / elsz; - } - - dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); - - if (!isutyp(rn->tn_type->t_tspec) && con < 0) { - /* array subscript cannot be negative: %ld */ - warning(167, (long)con); - } else if (dim > 0 && (u_quad_t)con >= dim) { - /* array subscript cannot be > %d: %ld */ - warning(168, dim - 1, (long)con); - } -} - -/* - * Check for ordered comparisons of unsigned values with 0. - */ -static void -chkcomp(op_t op, tnode_t *ln, tnode_t *rn) -{ - tspec_t lt, rt; - mod_t *mp; - - lt = ln->tn_type->t_tspec; - rt = rn->tn_type->t_tspec; - mp = &modtab[op]; - - if (ln->tn_op != CON && rn->tn_op != CON) - return; - - if (!isityp(lt) || !isityp(rt)) - return; - - if ((hflag || pflag) && lt == CHAR && rn->tn_op == CON && - (rn->tn_val->v_quad < 0 || - rn->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { - /* nonportable character comparison, op %s */ - warning(230, mp->m_name); - return; - } - if ((hflag || pflag) && rt == CHAR && ln->tn_op == CON && - (ln->tn_val->v_quad < 0 || - ln->tn_val->v_quad > ~(~0 << (CHAR_BIT - 1)))) { - /* nonportable character comparison, op %s */ - warning(230, mp->m_name); - return; - } - if (isutyp(lt) && !isutyp(rt) && - rn->tn_op == CON && rn->tn_val->v_quad <= 0) { - if (rn->tn_val->v_quad < 0) { - /* comparison of %s with %s, op %s */ - warning(162, tyname(ln->tn_type), "negative constant", - mp->m_name); - } else if (op == LT || op == GE || (hflag && op == LE)) { - /* comparison of %s with %s, op %s */ - warning(162, tyname(ln->tn_type), "0", mp->m_name); - } - return; - } - if (isutyp(rt) && !isutyp(lt) && - ln->tn_op == CON && ln->tn_val->v_quad <= 0) { - if (ln->tn_val->v_quad < 0) { - /* comparison of %s with %s, op %s */ - warning(162, "negative constant", tyname(rn->tn_type), - mp->m_name); - } else if (op == GT || op == LE || (hflag && op == GE)) { - /* comparison of %s with %s, op %s */ - warning(162, "0", tyname(rn->tn_type), mp->m_name); - } - return; - } -} - -/* - * Takes an expression and returns 0 if this expression can be used - * for static initialisation, otherwise -1. - * - * Constant initialisation expressions must be costant or an address - * of a static object with an optional offset. In the first case, - * the result is returned in *offsp. In the second case, the static - * object is returned in *symp and the offset in *offsp. - * - * The expression can consist of PLUS, MINUS, AMPER, NAME, STRING and - * CON. Type conversions are allowed if they do not change binary - * representation (including width). - */ -int -conaddr(tnode_t *tn, sym_t **symp, ptrdiff_t *offsp) -{ - sym_t *sym; - ptrdiff_t offs1, offs2; - tspec_t t, ot; - - switch (tn->tn_op) { - case MINUS: - if (tn->tn_right->tn_op != CON) - return (-1); - /* FALLTHROUGH */ - case PLUS: - offs1 = offs2 = 0; - if (tn->tn_left->tn_op == CON) { - offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; - if (conaddr(tn->tn_right, &sym, &offs2) == -1) - return (-1); - } else if (tn->tn_right->tn_op == CON) { - offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; - if (tn->tn_op == MINUS) - offs2 = -offs2; - if (conaddr(tn->tn_left, &sym, &offs1) == -1) - return (-1); - } else { - return (-1); - } - *symp = sym; - *offsp = offs1 + offs2; - break; - case AMPER: - if (tn->tn_left->tn_op == NAME) { - *symp = tn->tn_left->tn_sym; - *offsp = 0; - } else if (tn->tn_left->tn_op == STRING) { - /* - * If this would be the front end of a compiler we - * would return a label instead of 0. - */ - *offsp = 0; - } - break; - case CVT: - t = tn->tn_type->t_tspec; - ot = tn->tn_left->tn_type->t_tspec; - if ((!isityp(t) && t != PTR) || (!isityp(ot) && ot != PTR)) { - return (-1); - } else if (psize(t) != psize(ot)) { - return (-1); - } - if (conaddr(tn->tn_left, symp, offsp) == -1) - return (-1); - break; - default: - return (-1); - } - return (0); -} - -/* - * Concatenate two string constants. - */ -strg_t * -catstrg(strg_t *strg1, strg_t *strg2) -{ - size_t len1, len2, len; - - if (strg1->st_tspec != strg2->st_tspec) { - /* cannot concatenate wide and regular string literals */ - error(292); - return (strg1); - } - - len = (len1 = strg1->st_len) + (len2 = strg2->st_len); - - if (strg1->st_tspec == CHAR) { - strg1->st_cp = xrealloc(strg1->st_cp, len + 1); - (void)memcpy(strg1->st_cp + len1, strg2->st_cp, len2 + 1); - free(strg2->st_cp); - } else { - strg1->st_wcp = xrealloc(strg1->st_wcp, - (len + 1) * sizeof (wchar_t)); - (void)memcpy(strg1->st_wcp + len1, strg2->st_wcp, - (len2 + 1) * sizeof (wchar_t)); - free(strg2->st_wcp); - } - strg1->st_len = len; - free(strg2); - - return (strg1); -} - -/* - * Print a warning if the given node has operands which should be - * parenthesized. - * - * XXX Does not work if an operand is a constant expression. Constant - * expressions are already folded. - */ -static void -precconf(tnode_t *tn) -{ - tnode_t *ln, *rn; - op_t lop, rop = NOOP; - int lparn, rparn; - mod_t *mp; - int warn; - - if (!hflag) - return; - - mp = &modtab[tn->tn_op]; - - lparn = 0; - for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) - lparn |= ln->tn_parn; - lparn |= ln->tn_parn; - lop = ln->tn_op; - - if (mp->m_binary) { - rparn = 0; - for (rn = tn->tn_right; tn->tn_op == CVT; rn = rn->tn_left) - rparn |= rn->tn_parn; - rparn |= rn->tn_parn; - rop = rn->tn_op; - } - - warn = 0; - - switch (tn->tn_op) { - case SHL: - case SHR: - if (!lparn && (lop == PLUS || lop == MINUS)) { - warn = 1; - } else if (!rparn && (rop == PLUS || rop == MINUS)) { - warn = 1; - } - break; - case LOGOR: - if (!lparn && lop == LOGAND) { - warn = 1; - } else if (!rparn && rop == LOGAND) { - warn = 1; - } - break; - case AND: - case XOR: - case OR: - if (!lparn && lop != tn->tn_op) { - if (lop == PLUS || lop == MINUS) { - warn = 1; - } else if (lop == AND || lop == XOR) { - warn = 1; - } - } - if (!warn && !rparn && rop != tn->tn_op) { - if (rop == PLUS || rop == MINUS) { - warn = 1; - } else if (rop == AND || rop == XOR) { - warn = 1; - } - } - break; - /* LINTED (enumeration values not handled in switch) */ - } - - if (warn) { - /* precedence confusion possible: parenthesize! */ - warning(169); - } - -} - -/* - * Return the function name of a function (or of a pointer to a - * function). - */ -const char * -funcname(tnode_t *tn) -{ - /* dereference function pointer */ - switch (tn->tn_op) { - case AMPER: - return funcname(tn->tn_left); - case LOAD: - /* called as (*fptr)(args) */ - return funcname(tn->tn_left); - case CALL: - return funcname(tn->tn_left); - case NAME: - return tn->tn_sym->s_name; - default: - return "<unknown>"; - } -} diff --git a/usr.bin/xlint/lint2/Makefile b/usr.bin/xlint/lint2/Makefile deleted file mode 100644 index e6ac091582b..00000000000 --- a/usr.bin/xlint/lint2/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $OpenBSD: Makefile,v 1.2 1996/06/26 05:44:21 deraadt Exp $ -# $NetBSD: Makefile,v 1.2 1995/07/03 21:24:39 cgd Exp $ - -.PATH: ${.CURDIR}/../lint1 - -PROG= lint2 -SRCS= main2.c hash.c read.c mem.c mem2.c chk.c msg.c emit.c emit2.c -NOMAN= -CFLAGS+=-I${.CURDIR}/../lint1 -LINTFLAGS=-abehrz - -BINDIR= /usr/libexec - -.include <bsd.prog.mk> diff --git a/usr.bin/xlint/lint2/chk.c b/usr.bin/xlint/lint2/chk.c deleted file mode 100644 index 3e4839106da..00000000000 --- a/usr.bin/xlint/lint2/chk.c +++ /dev/null @@ -1,1412 +0,0 @@ -/* $OpenBSD: chk.c,v 1.26 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: chk.c,v 1.2 1995/07/03 21:24:42 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <ctype.h> -#include <limits.h> -#include <stdbool.h> -#include <complex.h> -#include <err.h> - -#include "lint2.h" - -/* various type information */ -ttab_t ttab[NTSPEC]; - - -static void chkund(hte_t *); -static void chkdnu(hte_t *); -static void chkdnud(hte_t *); -static void chkmd(hte_t *); -static void chkvtui(hte_t *, sym_t *, sym_t *); -static void chkvtdi(hte_t *, sym_t *, sym_t *); -static void chkfaui(hte_t *, sym_t *, sym_t *); -static void chkau(hte_t *, int, sym_t *, sym_t *, pos_t *, - fcall_t *, fcall_t *, type_t *, type_t *); -static void chkrvu(hte_t *, sym_t *); -static void chkadecl(hte_t *, sym_t *, sym_t *); -static void printflike(hte_t *,fcall_t *, int, const char *, type_t **); -static void scanflike(hte_t *, fcall_t *, int, const char *, type_t **); -static void badfmt(hte_t *, fcall_t *); -static void inconarg(hte_t *, fcall_t *, int); -static void tofewarg(hte_t *, fcall_t *); -static void tomanyarg(hte_t *, fcall_t *); -static int eqtype(type_t *, type_t *, int, int, int, int *); -static int eqargs(type_t *, type_t *, int *); -static int mnoarg(type_t *, int *); - - -void -inittyp(void) -{ - int i; - static struct { - tspec_t it_tspec; - ttab_t it_ttab; - } ittab[] = { - { SIGNED, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "signed" } }, - { UNSIGN, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "unsigned" } }, - { BOOL, { sizeof (_Bool) * CHAR_BIT, CHAR_BIT, 1, - BOOL, BOOL, - 1, 1, 0, 1, 1, "_Bool" } }, - { CHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "char" } }, - { SCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "signed char" } }, - { UCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 1, 0, 1, 1, "unsigned char" } }, - { SHORT, { sizeof (short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 0, 0, 1, 1, "short" } }, - { USHORT, { sizeof (u_short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 1, 0, 1, 1, "unsigned short" } }, - { INT, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 0, 0, 1, 1, "int" } }, - { UINT, { sizeof (u_int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 1, 0, 1, 1, "unsigned int" } }, - { LONG, { sizeof (long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 0, 0, 1, 1, "long" } }, - { ULONG, { sizeof (u_long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 1, 0, 1, 1, "unsigned long" } }, - { QUAD, { sizeof (quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 0, 0, 1, 1, "long long" } }, - { UQUAD, { sizeof (u_quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 1, 0, 1, 1, "unsigned long long" } }, - { FLOAT, { sizeof (float) * CHAR_BIT, 4 * CHAR_BIT, -1, - FLOAT, FLOAT, - 0, 0, 1, 1, 1, "float" } }, - { DOUBLE, { sizeof (double) * CHAR_BIT, 8 * CHAR_BIT, -1, - DOUBLE, DOUBLE, - 0, 0, 1, 1, 1, "double" } }, - { LDOUBLE, { sizeof (ldbl_t) * CHAR_BIT, 16 * CHAR_BIT, -1, - LDOUBLE, LDOUBLE, - 0, 0, 1, 1, 1, "long double" } }, - { COMPLEX, { sizeof (float _Complex) * CHAR_BIT, - 8 * CHAR_BIT, -1, - COMPLEX, COMPLEX, - 0, 0, 1, 1, 3, "float _Complex" } }, - { DCOMPLEX, { sizeof (double _Complex) * CHAR_BIT, - 16 * CHAR_BIT, -1, - DCOMPLEX, DCOMPLEX, - 0, 0, 1, 1, 3, "double _Complex" } }, - { LDCOMPLEX,{ sizeof (long double _Complex) * CHAR_BIT, - 32 * CHAR_BIT, -1, - LDCOMPLEX, LDCOMPLEX, - 0, 0, 1, 1, 3, "long double _Complex" } }, - { VOID, { -1, -1, -1, - VOID, VOID, - 0, 0, 0, 0, 0, "void" } }, - { STRUCT, { -1, -1, -1, - STRUCT, STRUCT, - 0, 0, 0, 0, 0, "struct" } }, - { UNION, { -1, -1, -1, - UNION, UNION, - 0, 0, 0, 0, 0, "union" } }, - { ENUM, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - ENUM, ENUM, - 1, 0, 0, 1, 1, "enum" } }, - { PTR, { sizeof (void *) * CHAR_BIT, 4 * CHAR_BIT, -1, - PTR, PTR, - 0, 1, 0, 0, 1, "pointer" } }, - { ARRAY, { -1, -1, -1, - ARRAY, ARRAY, - 0, 0, 0, 0, 0, "array" } }, - { FUNC, { -1, -1, -1, - FUNC, FUNC, - 0, 0, 0, 0, 0, "function" } }, - }; - - for (i = 0; i < sizeof (ittab) / sizeof (ittab[0]); i++) - STRUCT_ASSIGN(ttab[ittab[i].it_tspec], ittab[i].it_ttab); - if (!pflag) { - for (i = 0; i < NTSPEC; i++) - ttab[i].tt_psz = ttab[i].tt_sz; - } -} - - -/* - * If there is a symbol named "main", mark it as used. - */ -void -mainused(void) -{ - hte_t *hte; - - if ((hte = hsearch("main", 0)) != NULL) - hte->h_used = 1; -} - -/* - * Performs all tests for a single name - */ -void -chkname(hte_t *hte) -{ - sym_t *sym, *def, *pdecl, *decl; - - if (uflag) { - chkund(hte); - chkdnu(hte); - if (xflag) - chkdnud(hte); - } - chkmd(hte); - - /* Get definition, prototype declaration and declaration */ - def = pdecl = decl = NULL; - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (def == NULL && (sym->s_def == DEF || sym->s_def == TDEF)) - def = sym; - if (pdecl == NULL && sym->s_def == DECL && - TP(sym->s_type)->t_tspec == FUNC && - TP(sym->s_type)->t_proto) { - pdecl = sym; - } - if (decl == NULL && sym->s_def == DECL) - decl = sym; - } - - /* A prototype is better than an old style declaration. */ - if (pdecl != NULL) - decl = pdecl; - - chkvtui(hte, def, decl); - - chkvtdi(hte, def, decl); - - chkfaui(hte, def, decl); - - chkrvu(hte, def); - - chkadecl(hte, def, decl); -} - -/* - * Print a warning if the name has been used, but not defined. - */ -static void -chkund(hte_t *hte) -{ - fcall_t *fcall; - usym_t *usym; - - if (!hte->h_used || hte->h_def) - return; - - if ((fcall = hte->h_calls) != NULL) { - /* %s: %s used, but not defined */ - msg(0, mkpos(&fcall->f_pos), hte->h_name); - } else if ((usym = hte->h_usyms) != NULL) { - /* %s: %s used, but not defined */ - msg(0, mkpos(&usym->u_pos), hte->h_name); - } -} - -/* - * Print a warning if the name has been defined, but never used. - */ -static void -chkdnu(hte_t *hte) -{ - sym_t *sym; - - if (!hte->h_def || hte->h_used) - return; - - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (sym->s_def == DEF || sym->s_def == TDEF) { - /* %s: %s defined, but never used */ - msg(1, mkpos(&sym->s_pos), hte->h_name); - break; - } - } -} - -/* - * Print a warning if the name has been declared, but is not used - * or defined. - */ -static void -chkdnud(hte_t *hte) -{ - sym_t *sym; - - if (hte->h_syms == NULL || hte->h_used || hte->h_def) - return; - - if ((sym = hte->h_syms) != NULL) { - if (sym->s_def != DECL) - errx(1, "internal error: chkdnud() 1"); - - /* don't warn if the name was declared in a separate header */ - if (sym->s_pos.p_src != sym->s_pos.p_isrc) { - return; - } - - /* %s: %s declared, but never used or defined */ - msg(2, mkpos(&sym->s_pos), hte->h_name); - } -} - -/* - * Print a warning if there is more than one definition for - * this name. - */ -static void -chkmd(hte_t *hte) -{ - sym_t *sym, *def1; - char *pos1; - - if (!hte->h_def) - return; - - def1 = NULL; - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - /* - * ANSI C allows tentative definitions of the same name in - * only one compilation unit. - */ - if (sym->s_def != DEF && (!sflag || sym->s_def != TDEF)) - continue; - if (def1 == NULL) { - def1 = sym; - continue; - } - pos1 = xstrdup(mkpos(&def1->s_pos)); - /* %s: %s multiply defined (%s) */ - msg(3, pos1, hte->h_name, mkpos(&sym->s_pos)); - free(pos1); - } -} - -/* - * Print a warning if the return value assumed for a function call - * differs from the return value of the function definition or - * function declaration. - * - * If no definition/declaration can be found, the assumed return values - * are always int. So there is no need to compare with another function - * call as it's done for function arguments. - */ -static void -chkvtui(hte_t *hte, sym_t *def, sym_t *decl) -{ - fcall_t *call; - char *pos1; - type_t *tp1, *tp2; - /* LINTED (automatic hides external declaration: warn) */ - int warn, eq; - tspec_t t1; - - if (hte->h_calls == NULL) - return; - - if (def == NULL) - def = decl; - if (def == NULL) - return; - - t1 = (tp1 = TP(def->s_type)->t_subt)->t_tspec; - for (call = hte->h_calls; call != NULL; call = call->f_nxt) { - tp2 = TP(call->f_type)->t_subt; - eq = eqtype(tp1, tp2, 1, 0, 0, (warn = 0, &warn)); - if (!call->f_rused) { - /* no return value used */ - if ((t1 == STRUCT || t1 == UNION) && !eq) { - /* - * If a function returns a struct or union it - * must be declared to return a struct or - * union, also if the return value is ignored. - * This is necessary because the caller must - * allocate stack space for the return value. - * If it does not, the return value would over- - * write other data. - * XXX Following massage may be confusing - * because it appears also if the return value - * was declared inconsistently. But this - * behaviour matches pcc based lint, so it is - * accepted for now. - */ - pos1 = xstrdup(mkpos(&def->s_pos)); - /* %s: %s must be decl. before use (%s) */ - msg(17, pos1, hte->h_name, - mkpos(&call->f_pos)); - free(pos1); - } - continue; - } - if (!eq || (sflag && warn)) { - pos1 = xstrdup(mkpos(&def->s_pos)); - /* %s: %s used inconsistently (%s) */ - msg(4, pos1, hte->h_name, mkpos(&call->f_pos)); - free(pos1); - } - } -} - -/* - * Print a warning if a definition/declaration does not match another - * definition/declaration of the same name. For functions, only the - * types of return values are tested. - */ -static void -chkvtdi(hte_t *hte, sym_t *def, sym_t *decl) -{ - sym_t *sym; - type_t *tp1, *tp2; - /* LINTED (automatic hides external declaration: warn) */ - int eq, warn; - char *pos1; - - if (def == NULL) - def = decl; - if (def == NULL) - return; - - tp1 = TP(def->s_type); - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (sym == def) - continue; - tp2 = TP(sym->s_type); - warn = 0; - if (tp1->t_tspec == FUNC && tp2->t_tspec == FUNC) { - eq = eqtype(tp1->t_subt, tp2->t_subt, 1, 0, 0, &warn); - } else { - eq = eqtype(tp1, tp2, 0, 0, 0, &warn); - } - if (!eq || (sflag && warn)) { - pos1 = xstrdup(mkpos(&def->s_pos)); - /* %s: %s declared inconsistently (%s) */ - msg(5, pos1, hte->h_name, mkpos(&sym->s_pos)); - free(pos1); - } - } -} - -/* - * Print a warning if a function is called with arguments which does - * not match the function definition, declaration or another call - * of the same function. - */ -static void -chkfaui(hte_t *hte, sym_t *def, sym_t *decl) -{ - type_t *tp1, *tp2, **ap1, **ap2; - pos_t *pos1p; - fcall_t *calls, *call, *call1; - int n, as; - char *pos1; - arginf_t *ai; - - if ((calls = hte->h_calls) == NULL) - return; - - /* - * If we find a function definition, we use this for comparison, - * otherwise the first prototype we can find. If there is no - * definition or prototype declaration, the first function call - * is used. - */ - tp1 = NULL; - call1 = NULL; - if (def != NULL) { - if ((tp1 = TP(def->s_type))->t_tspec != FUNC) - return; - pos1p = &def->s_pos; - } else if (decl != NULL && TP(decl->s_type)->t_proto) { - if ((tp1 = TP(decl->s_type))->t_tspec != FUNC) - return; - pos1p = &decl->s_pos; - } - if (tp1 == NULL) { - call1 = calls; - calls = calls->f_nxt; - if ((tp1 = TP(call1->f_type))->t_tspec != FUNC) - return; - pos1p = &call1->f_pos; - } - - n = 1; - for (call = calls; call != NULL; call = call->f_nxt) { - if ((tp2 = TP(call->f_type))->t_tspec != FUNC) - continue; - ap1 = tp1->t_args; - ap2 = tp2->t_args; - n = 0; - while (*ap1 != NULL && *ap2 != NULL) { - if (def != NULL && def->s_va && n >= def->s_nva) - break; - n++; - chkau(hte, n, def, decl, pos1p, call1, call, - *ap1, *ap2); - ap1++; - ap2++; - } - if (*ap1 == *ap2) { - /* equal # of arguments */ - } else if (def != NULL && def->s_va && n >= def->s_nva) { - /* - * function definition with VARARGS; The # of - * arguments of the call must be at least as large - * as the parameter of VARARGS. - */ - } else if (*ap2 != NULL && tp1->t_proto && tp1->t_vararg) { - /* - * prototype with ... and function call with - * at least the same # of arguments as declared - * in the prototype. - */ - } else { - pos1 = xstrdup(mkpos(pos1p)); - /* %s: %s called with varying # of args (%s) */ - msg(7, pos1, hte->h_name, mkpos(&call->f_pos)); - free(pos1); - continue; - } - - /* perform SCANFLIKE/PRINTFLIKE tests */ - if (def == NULL || (!def->s_prfl && !def->s_scfl)) - continue; - as = def->s_prfl ? def->s_nprfl : def->s_nscfl; - for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) { - if (ai->a_num == as) - break; - } - if (ai == NULL || !ai->a_fmt) - continue; - if (def->s_prfl) { - printflike(hte, call, n, ai->a_fstrg, ap2); - } else { - scanflike(hte, call, n, ai->a_fstrg, ap2); - } - } -} - -/* - * Check a single argument in a function call. - * - * hte a pointer to the hash table entry of the function - * n the number of the argument (1..) - * def the function definition or NULL - * decl prototype declaration, old style declaration or NULL - * pos1p position of definition, declaration of first call - * call1 first call, if both def and decl are old style def/decl - * call checked call - * arg1 currently checked argument of def/decl/call1 - * arg2 currently checked argument of call - * - */ -static void -chkau(hte_t *hte, int n, sym_t *def, sym_t *decl, pos_t *pos1p, - fcall_t *call1, fcall_t *call, type_t *arg1, type_t *arg2) -{ - /* LINTED (automatic hides external declaration: warn) */ - int promote, asgn, warn; - tspec_t t1, t2; - arginf_t *ai, *ai1; - char *pos1; - - /* - * If a function definition is available (def != NULL), we compair the - * function call (call) with the definition. Otherwise, if a function - * definition is available and it is not an old style definition - * (decl != NULL && TP(decl->s_type)->t_proto), we compair the call - * with this declaration. Otherwise we compair it with the first - * call we have found (call1). - */ - - /* arg1 must be promoted if it stems from an old style definition */ - promote = def != NULL && def->s_osdef; - - /* - * If we compair with a definition or declaration, we must perform - * the same checks for qualifiers in indirected types as in - * assignments. - */ - asgn = def != NULL || (decl != NULL && TP(decl->s_type)->t_proto); - - warn = 0; - if (eqtype(arg1, arg2, 1, promote, asgn, &warn) && (!sflag || !warn)) - return; - - /* - * Other lint implementations print warnings as soon as the type - * of an argument does not match exactly the expected type. The - * result are lots of warnings which are really not necessary. - * We print a warning only if - * (0) at least one type is not an interger type and types differ - * (1) hflag is set and types differ - * (2) types differ, except in signedness - * If the argument is an integer constant whose msb is not set, - * signedness is ignored (e.g. 0 matches both signed and unsigned - * int). This is with and without hflag. - * If the argument is an integer constant with value 0 and the - * expected argument is of type pointer and the width of the - * interger constant is the same as the width of the pointer, - * no warning is printed. - */ - t1 = arg1->t_tspec; - t2 = arg2->t_tspec; - if (isityp(t1) && isityp(t2) && !arg1->t_isenum && !arg2->t_isenum) { - if (promote) { - /* - * XXX Here is a problem: Althrough it is possible to - * pass an int where a char/short it expected, there - * may be loss in significant digits. We should first - * check for const arguments if they can be converted - * into the original parameter type. - */ - if (t1 == FLOAT) { - t1 = DOUBLE; - } else if (t1 == CHAR || t1 == SCHAR) { - t1 = INT; - } else if (t1 == UCHAR) { - t1 = INT; - } else if (t1 == SHORT) { - t1 = INT; - } else if (t1 == USHORT) { - /* CONSTCOND */ - t1 = INT_MAX < USHRT_MAX ? UINT : INT; - } - } - - if (styp(t1) == styp(t2)) { - - /* - * types differ only in signedness; get information - * about arguments - */ - - /* - * treat a definition like a call with variable - * arguments - */ - ai1 = call1 != NULL ? call1->f_args : NULL; - - /* - * if two calls are compared, ai1 is set to the - * information for the n-th argument, if this was - * a constant, otherwise to NULL - */ - for ( ; ai1 != NULL; ai1 = ai1->a_nxt) { - if (ai1->a_num == n) - break; - } - /* - * ai is set to the information of the n-th arg - * of the (second) call, if this was a constant, - * otherwise to NULL - */ - for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) { - if (ai->a_num == n) - break; - } - - if (ai1 == NULL && ai == NULL) { - /* no constant at all */ - if (!hflag) - return; - } else if (ai1 == NULL || ai == NULL) { - /* one constant */ - if (ai == NULL) - ai = ai1; - if (ai->a_zero || ai->a_pcon) - /* same value in signed and unsigned */ - return; - /* value (not representation) differently */ - } else { - /* - * two constants, one signed, one unsigned; - * if the msb of one of the constants is set, - * the argument is used inconsistently. - */ - if (!ai1->a_ncon && !ai->a_ncon) - return; - } - } - - } else if (t1 == PTR && isityp(t2) && psize(t1) == psize(t2)) { - for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) { - if (ai->a_num == n) - break; - } - if (ai != NULL && ai->a_zero) - return; - } - - pos1 = xstrdup(mkpos(pos1p)); - /* %s: %s arg %d used inconsistently (%s) */ - msg(6, pos1, hte->h_name, n, mkpos(&call->f_pos)); - free(pos1); -} - -/* - * Compare the types in the NULL-terminated array ap with the format - * string fmt. - */ -static void -printflike(hte_t *hte, fcall_t *call, int n, const char *fmt, type_t **ap) -{ - const char *fp; - int fc; - int fwidth, prec, left, sign, space, alt, zero; - tspec_t sz, t1, t2 = NOTSPEC; - type_t *tp; - - fp = fmt; - fc = *fp++; - - for ( ; ; ) { - if (fc == '\0') { - if (*ap != NULL) - tomanyarg(hte, call); - break; - } - if (fc != '%') { - badfmt(hte, call); - break; - } - fc = *fp++; - fwidth = prec = left = sign = space = alt = zero = 0; - sz = NOTSPEC; - - /* Flags */ - for ( ; ; ) { - if (fc == '-') { - if (left) - break; - left = 1; - } else if (fc == '+') { - if (sign) - break; - sign = 1; - } else if (fc == ' ') { - if (space) - break; - space = 1; - } else if (fc == '#') { - if (alt) - break; - alt = 1; - } else if (fc == '0') { - if (zero) - break; - zero = 1; - } else { - break; - } - fc = *fp++; - } - - /* field width */ - if (isdigit(fc)) { - fwidth = 1; - do { fc = *fp++; } while (isdigit(fc)) ; - } else if (fc == '*') { - fwidth = 1; - fc = *fp++; - if ((tp = *ap++) == NULL) { - tofewarg(hte, call); - break; - } - n++; - if ((t1 = tp->t_tspec) != INT && (hflag || t1 != UINT)) - inconarg(hte, call, n); - } - - /* precision */ - if (fc == '.') { - fc = *fp++; - prec = 1; - if (isdigit(fc)) { - do { fc = *fp++; } while (isdigit(fc)); - } else if (fc == '*') { - fc = *fp++; - if ((tp = *ap++) == NULL) { - tofewarg(hte, call); - break; - } - n++; - if (tp->t_tspec != INT) - inconarg(hte, call, n); - } else { - badfmt(hte, call); - break; - } - } - - if (fc == 'h') { - sz = SHORT; - } else if (fc == 'l') { - sz = LONG; - } else if (fc == 'q') { - sz = QUAD; - } else if (fc == 'L') { - sz = LDOUBLE; - } - if (sz != NOTSPEC) - fc = *fp++; - - if (fc == '%' || fc == 'm') { - if (sz != NOTSPEC || left || sign || space || - alt || zero || prec || fwidth) { - badfmt(hte, call); - } - fc = *fp++; - continue; - } - - if (fc == '\0') { - badfmt(hte, call); - break; - } - - if ((tp = *ap++) == NULL) { - tofewarg(hte, call); - break; - } - n++; - if ((t1 = tp->t_tspec) == PTR) - t2 = tp->t_subt->t_tspec; - - if (fc == 'd' || fc == 'i') { - if (alt || sz == LDOUBLE) { - badfmt(hte, call); - break; - } - int_conv: - if (sz == LONG) { - if (t1 != LONG && (hflag || t1 != ULONG)) - inconarg(hte, call, n); - } else if (sz == QUAD) { - if (t1 != QUAD && (hflag || t1 != UQUAD)) - inconarg(hte, call, n); - } else { - /* - * SHORT is always promoted to INT, USHORT - * to INT or UINT. - */ - if (t1 != INT && (hflag || t1 != UINT)) - inconarg(hte, call, n); - } - } else if (fc == 'o' || fc == 'u' || fc == 'x' || fc == 'X') { - if ((alt && fc == 'u') || sz == LDOUBLE) - badfmt(hte, call); - uint_conv: - if (sz == LONG) { - if (t1 != ULONG && (hflag || t1 != LONG)) - inconarg(hte, call, n); - } else if (sz == QUAD) { - if (t1 != UQUAD && (hflag || t1 != QUAD)) - inconarg(hte, call, n); - } else if (sz == SHORT) { - /* USHORT was promoted to INT or UINT */ - if (t1 != UINT && t1 != INT) - inconarg(hte, call, n); - } else { - if (t1 != UINT && (hflag || t1 != INT)) - inconarg(hte, call, n); - } - } else if (fc == 'D' || fc == 'O' || fc == 'U') { - /* DOU are deprecated */ - badfmt(hte, call); - sz = LONG; - if (fc == 'D') { - goto int_conv; - } else { - goto uint_conv; - } - } else if (fc == 'e' || fc == 'E' || - fc == 'f' || fc == 'F' || - fc == 'g' || fc == 'G' || - fc == 'a' || fc == 'A') { - if (sz == NOTSPEC) - sz = DOUBLE; - if (sz != DOUBLE && sz != LDOUBLE) - badfmt(hte, call); - if (t1 != sz) - inconarg(hte, call, n); - } else if (fc == 'c') { - if (sz != NOTSPEC || alt || zero) - badfmt(hte, call); - if (t1 != INT) - inconarg(hte, call, n); - } else if (fc == 's') { - if (sz != NOTSPEC || alt || zero) - badfmt(hte, call); - if (t1 != PTR || - (t2 != CHAR && t2 != UCHAR && t2 != SCHAR)) { - inconarg(hte, call, n); - } - } else if (fc == 'p') { - if (fwidth || prec || sz != NOTSPEC || alt || zero) - badfmt(hte, call); - if (t1 != PTR || (hflag && t2 != VOID)) - inconarg(hte, call, n); - } else if (fc == 'n') { - if (fwidth || prec || alt || zero || sz == LDOUBLE) - badfmt(hte, call); - if (t1 != PTR) { - inconarg(hte, call, n); - } else if (sz == LONG) { - if (t2 != LONG && t2 != ULONG) - inconarg(hte, call, n); - } else if (sz == SHORT) { - if (t2 != SHORT && t2 != USHORT) - inconarg(hte, call, n); - } else { - if (t2 != INT && t2 != UINT) - inconarg(hte, call, n); - } - } else { - badfmt(hte, call); - break; - } - - fc = *fp++; - } -} - -/* - * Compare the types in the NULL-terminated array ap with the format - * string fmt. - */ -static void -scanflike(hte_t *hte, fcall_t *call, int n, const char *fmt, type_t **ap) -{ - const char *fp; - int fc; - int noasgn, fwidth; - tspec_t sz, t1 = NOTSPEC, t2 = NOTSPEC; - type_t *tp; - - fp = fmt; - fc = *fp++; - - for ( ; ; ) { - if (fc == '\0') { - if (*ap != NULL) - tomanyarg(hte, call); - break; - } - if (fc != '%') { - badfmt(hte, call); - break; - } - fc = *fp++; - - noasgn = fwidth = 0; - sz = NOTSPEC; - - if (fc == '*') { - noasgn = 1; - fc = *fp++; - } - - if (isdigit(fc)) { - fwidth = 1; - do { fc = *fp++; } while (isdigit(fc)); - } - - if (fc == 'h') { - sz = SHORT; - } else if (fc == 'l') { - sz = LONG; - } else if (fc == 'q') { - sz = QUAD; - } else if (fc == 'L') { - sz = LDOUBLE; - } - if (sz != NOTSPEC) - fc = *fp++; - - if (fc == '%') { - if (sz != NOTSPEC || noasgn || fwidth) - badfmt(hte, call); - fc = *fp++; - continue; - } - - if (!noasgn) { - if ((tp = *ap++) == NULL) { - tofewarg(hte, call); - break; - } - n++; - if ((t1 = tp->t_tspec) == PTR) - t2 = tp->t_subt->t_tspec; - } - - if (fc == 'd' || fc == 'i' || fc == 'n') { - if (sz == LDOUBLE) - badfmt(hte, call); - if (sz != SHORT && sz != LONG && sz != QUAD) - sz = INT; - conv: - if (!noasgn) { - if (t1 != PTR) { - inconarg(hte, call, n); - } else if (t2 != styp(sz)) { - inconarg(hte, call, n); - } else if (hflag && t2 != sz) { - inconarg(hte, call, n); - } else if (tp->t_subt->t_const) { - inconarg(hte, call, n); - } - } - } else if (fc == 'o' || fc == 'u' || fc == 'x') { - if (sz == LDOUBLE) - badfmt(hte, call); - if (sz == SHORT) { - sz = USHORT; - } else if (sz == LONG) { - sz = ULONG; - } else if (sz == QUAD) { - sz = UQUAD; - } else { - sz = UINT; - } - goto conv; - } else if (fc == 'D') { - badfmt(hte, call); - sz = LONG; - goto conv; - } else if (fc == 'O') { - badfmt(hte, call); - sz = ULONG; - goto conv; - } else if (fc == 'X') { - /* - * XXX valid in ANSI C, but in NetBSD's libc imple- - * mented as "lx". Thats why it should be avoided. - */ - badfmt(hte, call); - sz = ULONG; - goto conv; - } else if (fc == 'e' || fc == 'E' || - fc == 'f' || fc == 'F' || - fc == 'g' || fc == 'G' || - fc == 'a' || fc == 'A') { - if (sz == NOTSPEC) { - sz = FLOAT; - } else if (sz == LONG) { - sz = DOUBLE; - } else if (sz != LDOUBLE) { - badfmt(hte, call); - sz = FLOAT; - } - goto conv; - } else if (fc == 's' || fc == '[' || fc == 'c') { - if (sz != NOTSPEC) - badfmt(hte, call); - if (fc == '[') { - if ((fc = *fp++) == '-') { - badfmt(hte, call); - fc = *fp++; - } - if (fc != ']') { - badfmt(hte, call); - if (fc == '\0') - break; - } - } - if (!noasgn) { - if (t1 != PTR) { - inconarg(hte, call, n); - } else if (t2 != CHAR && t2 != UCHAR && - t2 != SCHAR) { - inconarg(hte, call, n); - } - } - } else if (fc == 'p') { - if (sz != NOTSPEC) - badfmt(hte, call); - if (!noasgn) { - if (t1 != PTR || t2 != PTR) { - inconarg(hte, call, n); - } else if (tp->t_subt->t_subt->t_tspec!=VOID) { - if (hflag) - inconarg(hte, call, n); - } - } - } else { - badfmt(hte, call); - break; - } - - fc = *fp++; - } -} - -static void -badfmt(hte_t *hte, fcall_t *call) -{ - /* %s: malformed format string argument to %s */ - msg(13, mkpos(&call->f_pos), hte->h_name); -} - -static void -inconarg(hte_t *hte, fcall_t *call, int n) -{ - /* %s: arg %d to %s is inconsistent with format */ - msg(14, mkpos(&call->f_pos), n, hte->h_name); -} - -static void -tofewarg(hte_t *hte, fcall_t *call) -{ - /* %s: too few format args to %s */ - msg(15, mkpos(&call->f_pos), hte->h_name); -} - -static void -tomanyarg(hte_t *hte, fcall_t *call) -{ - /* %s: too many format args to %s */ - msg(16, mkpos(&call->f_pos), hte->h_name); -} - - -/* - * Print warnings for return values which are used, but not returned, - * or return values which are always or sometimes ignored. - */ -static void -chkrvu(hte_t *hte, sym_t *def) -{ - fcall_t *call; - int used, ignored; - - if (def == NULL) - /* don't know wheter or not the functions returns a value */ - return; - - if (hte->h_calls == NULL) - return; - - if (def->s_rval) { - /* function has return value */ - used = ignored = 0; - for (call = hte->h_calls; call != NULL; call = call->f_nxt) { - used |= call->f_rused || call->f_rdisc; - ignored |= !call->f_rused && !call->f_rdisc; - } - /* - * XXX as soon as we are able to disable single warnings - * the following dependencies from hflag should be removed. - * but for now I do'nt want to be botherd by this warnings - * which are almost always useless. - */ - if (!used && ignored) { - if (hflag) - /* %s returns value which is always ignored */ - msg(8, hte->h_name); - } else if (used && ignored) { - if (hflag) - /* %s returns value which is sometimes ign. */ - msg(9, hte->h_name); - } - } else { - /* function has no return value */ - for (call = hte->h_calls; call != NULL; call = call->f_nxt) { - if (call->f_rused) - /* %s: return value of %s is used, but none ret. */ - msg(10, mkpos(&call->f_pos), hte->h_name); - } - } -} - -/* - * Print warnings for inconsistent argument declarations. - */ -static void -chkadecl(hte_t *hte, sym_t *def, sym_t *decl) -{ - /* LINTED (automatic hides external declaration: warn) */ - int osdef, eq, warn, n; - sym_t *sym1, *sym; - type_t **ap1, **ap2, *tp1, *tp2; - char *pos1; - const char *pos2; - - osdef = 0; - if (def != NULL) { - osdef = def->s_osdef; - sym1 = def; - } else if (decl != NULL && TP(decl->s_type)->t_proto) { - sym1 = decl; - } else { - return; - } - if (TP(sym1->s_type)->t_tspec != FUNC) - return; - - /* - * XXX Prototypes should also be compared with old style function - * declarations. - */ - - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (sym == sym1 || !TP(sym->s_type)->t_proto) - continue; - ap1 = TP(sym1->s_type)->t_args; - ap2 = TP(sym->s_type)->t_args; - n = 0; - while (*ap1 != NULL && *ap2 != NULL) { - warn = 0; - eq = eqtype(*ap1, *ap2, 1, osdef, 0, &warn); - if (!eq || warn) { - pos1 = xstrdup(mkpos(&sym1->s_pos)); - pos2 = mkpos(&sym->s_pos); - /* %s: %s arg %d declared inconsistently ... */ - msg(11, pos1, hte->h_name, n + 1, pos2); - free(pos1); - } - n++; - ap1++; - ap2++; - } - if (*ap1 == *ap2) { - tp1 = TP(sym1->s_type); - tp2 = TP(sym->s_type); - if (tp1->t_vararg == tp2->t_vararg) - continue; - if (tp2->t_vararg && - sym1->s_va && sym1->s_nva == n && !sflag) { - continue; - } - } - /* %s: %s declared with varying # of args (%s) */ - pos1 = xstrdup(mkpos(&sym1->s_pos)); - msg(12, pos1, hte->h_name, mkpos(&sym->s_pos)); - free(pos1); - } -} - - -/* - * Check compatibility of two types. Returns 1 if types are compatible, - * otherwise 0. - * - * ignqual if set, ignore qualifiers of outhermost type; used for - * function arguments - * promote if set, promote left type before comparison; used for - * comparisons of arguments with parameters of old style - * definitions - * asgn left indirected type must have at least the same qualifiers - * like right indirected type (for assignments and function - * arguments) - * *warn set to 1 if an old style declaration was compared with - * an incompatible prototype declaration - */ -static int -eqtype(type_t *tp1, type_t *tp2, int ignqual, int promot, int asgn, int *warn) -{ - tspec_t t, to; - int indir; - - to = NOTSPEC; - indir = 0; - - while (tp1 != NULL && tp2 != NULL) { - - t = tp1->t_tspec; - if (promot) { - if (t == FLOAT) { - t = DOUBLE; - } else if (t == CHAR || t == SCHAR) { - t = INT; - } else if (t == UCHAR) { - t = INT; - } else if (t == SHORT) { - t = INT; - } else if (t == USHORT) { - /* CONSTCOND */ - t = INT_MAX < USHRT_MAX ? UINT : INT; - } - } - - if (asgn && to == PTR) { - if (indir == 1 && (t == VOID || tp2->t_tspec == VOID)) - return (1); - } - - if (t != tp2->t_tspec) { - /* - * Give pointer to types which differ only in - * signedness a chance if not sflag and not hflag. - */ - if (sflag || hflag || to != PTR) - return (0); - if (styp(t) != styp(tp2->t_tspec)) - return (0); - } - - if (tp1->t_isenum && tp2->t_isenum) { - if (tp1->t_istag && tp2->t_istag) { - return (tp1->t_tag == tp2->t_tag); - } else if (tp1->t_istynam && tp2->t_istynam) { - return (tp1->t_tynam == tp2->t_tynam); - } else { - return (0); - } - } - - /* - * XXX Handle combinations of enum and int if eflag is set. - * But note: enum and 0 should be allowed. - */ - - if (asgn && indir == 1) { - if (!tp1->t_const && tp2->t_const) - return (0); - if (!tp1->t_volatile && tp2->t_volatile) - return (0); - } else if (!ignqual) { - if (tp1->t_const != tp2->t_const) - return (0); - if (tp1->t_const != tp2->t_const) - return (0); - } - - if (t == STRUCT || t == UNION) { - if (tp1->t_istag && tp2->t_istag) { - return (tp1->t_tag == tp2->t_tag); - } else if (tp1->t_istynam && tp2->t_istynam) { - return (tp1->t_tynam == tp2->t_tynam); - } else { - return (0); - } - } - - if (t == ARRAY && tp1->t_dim != tp2->t_dim) { - if (tp1->t_dim != 0 && tp2->t_dim != 0) - return (0); - } - - if (t == FUNC) { - if (tp1->t_proto && tp2->t_proto) { - if (!eqargs(tp1, tp2, warn)) - return (0); - } else if (tp1->t_proto) { - if (!mnoarg(tp1, warn)) - return (0); - } else if (tp2->t_proto) { - if (!mnoarg(tp2, warn)) - return (0); - } - } - - tp1 = tp1->t_subt; - tp2 = tp2->t_subt; - ignqual = promot = 0; - to = t; - indir++; - - } - - return (tp1 == tp2); -} - -/* - * Compares arguments of two prototypes - */ -static int -eqargs(type_t *tp1, type_t *tp2, int *warn) -{ - type_t **a1, **a2; - - if (tp1->t_vararg != tp2->t_vararg) - return (0); - - a1 = tp1->t_args; - a2 = tp2->t_args; - - while (*a1 != NULL && *a2 != NULL) { - - if (eqtype(*a1, *a2, 1, 0, 0, warn) == 0) - return (0); - - a1++; - a2++; - - } - - return (*a1 == *a2); -} - -/* - * mnoarg() (matches functions with no argument type information) - * returns 1 if all parameters of a prototype are compatible with - * and old style function declaration. - * This is the case if following conditions are met: - * 1. the prototype must have a fixed number of parameters - * 2. no parameter is of type float - * 3. no parameter is converted to another type if integer promotion - * is applied on it - */ -static int -mnoarg(type_t *tp, int *warn) -{ - type_t **arg; - tspec_t t; - - if (tp->t_vararg && warn != NULL) - *warn = 1; - for (arg = tp->t_args; *arg != NULL; arg++) { - if ((t = (*arg)->t_tspec) == FLOAT) - return (0); - if (t == CHAR || t == SCHAR || t == UCHAR) - return (0); - if (t == SHORT || t == USHORT) - return (0); - } - return (1); -} diff --git a/usr.bin/xlint/lint2/emit2.c b/usr.bin/xlint/lint2/emit2.c deleted file mode 100644 index 2e60ceec3a8..00000000000 --- a/usr.bin/xlint/lint2/emit2.c +++ /dev/null @@ -1,235 +0,0 @@ -/* $OpenBSD: emit2.c,v 1.7 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: emit2.c,v 1.2 1995/07/03 21:24:44 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <err.h> - -#include "lint2.h" - -static void outtype(type_t *); -static void outdef(hte_t *, sym_t *); -static void dumpname(hte_t *); - -/* - * Write type into the output buffer. - */ -static void -outtype(type_t *tp) -{ - int t, s, na; - tspec_t ts; - type_t **ap; - - while (tp != NULL) { - if ((ts = tp->t_tspec) == INT && tp->t_isenum) - ts = ENUM; - switch (ts) { - case BOOL: t = 'B'; s = '\0'; break; - case CHAR: t = 'C'; s = '\0'; break; - case SCHAR: t = 'C'; s = 's'; break; - case UCHAR: t = 'C'; s = 'u'; break; - case SHORT: t = 'S'; s = '\0'; break; - case USHORT: t = 'S'; s = 'u'; break; - case INT: t = 'I'; s = '\0'; break; - case UINT: t = 'I'; s = 'u'; break; - case LONG: t = 'L'; s = '\0'; break; - case ULONG: t = 'L'; s = 'u'; break; - case QUAD: t = 'Q'; s = '\0'; break; - case UQUAD: t = 'Q'; s = 'u'; break; - case FLOAT: t = 'D'; s = 's'; break; - case DOUBLE: t = 'D'; s = '\0'; break; - case LDOUBLE: t = 'D'; s = 'l'; break; - case COMPLEX: t = 'X'; s = 's'; break; - case DCOMPLEX: t = 'X'; s = '\0'; break; - case LDCOMPLEX: t = 'X'; s = 'l'; break; - case IMAGINARY: t = 'J'; s = 's'; break; - case DIMAGINARY: t = 'J'; s = '\0'; break; - case LDIMAGINARY:t = 'J'; s = 'l'; break; - case VOID: t = 'V'; s = '\0'; break; - case PTR: t = 'P'; s = '\0'; break; - case ARRAY: t = 'A'; s = '\0'; break; - case ENUM: t = 'T'; s = 'e'; break; - case STRUCT: t = 'T'; s = 's'; break; - case UNION: t = 'T'; s = 'u'; break; - case FUNC: - if (tp->t_args != NULL && !tp->t_proto) { - t = 'f'; - } else { - t = 'F'; - } - s = '\0'; - break; - default: - errx(1, "internal error: outtype() 1"); - } - if (tp->t_const) - outchar('c'); - if (tp->t_volatile) - outchar('v'); - if (s != '\0') - outchar(s); - outchar(t); - if (ts == ARRAY) { - outint(tp->t_dim); - } else if (ts == ENUM || ts == STRUCT || ts == UNION) { - if (tp->t_istag) { - outint(1); - outname(tp->t_tag->h_name); - } else if (tp->t_istynam) { - outint(2); - outname(tp->t_tynam->h_name); - } else { - outint(0); - } - } else if (ts == FUNC && tp->t_args != NULL) { - na = 0; - for (ap = tp->t_args; *ap != NULL; ap++) - na++; - if (tp->t_vararg) - na++; - outint(na); - for (ap = tp->t_args; *ap != NULL; ap++) - outtype(*ap); - if (tp->t_vararg) - outchar('E'); - } - tp = tp->t_subt; - } -} - -/* - * Write a definition. - */ -static void -outdef(hte_t *hte, sym_t *sym) -{ - /* reset output buffer */ - outclr(); - - /* line number in C source file */ - outint(0); - - /* this is a definition */ - outchar('d'); - - /* index of file where symbol was defined and line number of def. */ - outint(0); - outchar('.'); - outint(0); - - /* flags */ - if (sym->s_va) { - outchar('v'); /* varargs */ - outint(sym->s_nva); - } - if (sym->s_scfl) { - outchar('S'); /* scanflike */ - outint(sym->s_nscfl); - } - if (sym->s_prfl) { - outchar('P'); /* printflike */ - outint(sym->s_nprfl); - } - /* definition or tentative definition */ - outchar(sym->s_def == DEF ? 'd' : 't'); - if (TP(sym->s_type)->t_tspec == FUNC) { - if (sym->s_rval) - outchar('r'); /* fkt. has return value */ - if (sym->s_osdef) - outchar('o'); /* old style definition */ - } - outchar('u'); /* used (no warning if not used) */ - - /* name */ - outname(hte->h_name); - - /* type */ - outtype(TP(sym->s_type)); -} - -/* - * Write the first definition of a name into the lint library. - */ -static void -dumpname(hte_t *hte) -{ - sym_t *sym, *def; - - /* static and undefined symbols are not written */ - if (hte->h_static || !hte->h_def) - return; - - /* - * If there is a definition, write it. Otherwise write a tentative - * definition. This is necessary because more than one tentative - * definition is allowed (except with sflag). - */ - def = NULL; - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (sym->s_def == DEF) { - def = sym; - break; - } - if (sym->s_def == TDEF && def == NULL) - def = sym; - } - if (def == NULL) - errx(1, "internal error: dumpname() %s", hte->h_name); - - outdef(hte, def); -} - -/* - * Write a new lint library. - */ -void -outlib(const char *name) -{ - /* Open of output file and initialisation of the output buffer */ - outopen(name); - - /* write name of lint library */ - outsrc(name); - - /* name of lint lib has index 0 */ - outclr(); - outint(0); - outchar('s'); - outstrg(name); - - /* write all definitions with external linkage */ - forall(dumpname); - - /* close the output */ - outclose(); -} diff --git a/usr.bin/xlint/lint2/externs2.h b/usr.bin/xlint/lint2/externs2.h deleted file mode 100644 index 0e54ce8dabe..00000000000 --- a/usr.bin/xlint/lint2/externs2.h +++ /dev/null @@ -1,88 +0,0 @@ -/* $OpenBSD: externs2.h,v 1.6 2006/05/29 20:47:22 cloder Exp $ */ -/* $NetBSD: externs2.h,v 1.2 1995/07/03 21:24:46 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * main.c - */ -extern int xflag; -extern int uflag; -extern int Cflag; -extern const char *libname; -extern int pflag; -extern int sflag; -extern int Hflag; -extern int hflag; -extern int Fflag; - - -/* - * hash.c - */ -extern void inithash(void); -extern hte_t *hsearch(const char *, int); -extern void forall(void (*)(hte_t *)); - -/* - * read.c - */ -extern const char **fnames; -extern type_t **tlst; -extern int csrcfile; - -extern void readfile(const char *); -extern void mkstatic(hte_t *); - -/* - * mem2.c - */ -extern void initmem(void); -extern void *xalloc(size_t); - -/* - * chk.c - */ -extern void inittyp(void); -extern void mainused(void); -extern void chkname(hte_t *); - -/* - * msg.c - */ -extern void msg(int, ...); -extern const char *mkpos(pos_t *); - -/* - * emit2.c - */ -extern void outlib(const char *); diff --git a/usr.bin/xlint/lint2/hash.c b/usr.bin/xlint/lint2/hash.c deleted file mode 100644 index 028c9b6dc51..00000000000 --- a/usr.bin/xlint/lint2/hash.c +++ /dev/null @@ -1,117 +0,0 @@ -/* $OpenBSD: hash.c,v 1.6 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: hash.c,v 1.2 1995/07/03 21:24:47 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stddef.h> -#include <string.h> -#include <limits.h> - -#include "lint2.h" - -/* pointer to hash table, initialized in inithash() */ -static hte_t **htab; - -static int hash(const char *); - -/* - * Initialize hash table. - */ -void -inithash(void) -{ - htab = xcalloc(HSHSIZ2, sizeof (hte_t *)); -} - -/* - * Compute hash value from a string. - */ -static int -hash(const char *s) -{ - u_int v; - const u_char *us; - - v = 0; - for (us = (const u_char *)s; *us != '\0'; us++) { - v = (v << sizeof (v)) + *us; - v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v)); - } - return (v % HSHSIZ2); -} - -/* - * Look for a hash table entry. If no hash table entry for the - * given name exists and mknew is set, create a new one. - */ -hte_t * -hsearch(const char *s, int mknew) -{ - int h; - hte_t *hte; - - h = hash(s); - for (hte = htab[h]; hte != NULL; hte = hte->h_link) { - if (strcmp(hte->h_name, s) == 0) - break; - } - - if (hte != NULL || !mknew) - return (hte); - - /* create a new hte */ - hte = xalloc(sizeof (hte_t)); - memset(hte, 0, sizeof (hte_t)); - hte->h_name = xstrdup(s); - hte->h_lsym = &hte->h_syms; - hte->h_lcall = &hte->h_calls; - hte->h_lusym = &hte->h_usyms; - hte->h_link = htab[h]; - htab[h] = hte; - - return (hte); -} - -/* - * Call function f for each name in the hash table. - */ -void -forall(void (*f)(hte_t *)) -{ - int i; - hte_t *hte; - - for (i = 0; i < HSHSIZ2; i++) { - for (hte = htab[i]; hte != NULL; hte = hte->h_link) - (*f)(hte); - } -} diff --git a/usr.bin/xlint/lint2/lint2.h b/usr.bin/xlint/lint2/lint2.h deleted file mode 100644 index 8ddc1a9d80d..00000000000 --- a/usr.bin/xlint/lint2/lint2.h +++ /dev/null @@ -1,178 +0,0 @@ -/* $OpenBSD: lint2.h,v 1.3 2005/11/20 17:42:50 deraadt Exp $ */ -/* $NetBSD: lint2.h,v 1.2 1995/07/03 21:24:49 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "lint.h" - -/* - * Types are described by structures of type type_t. - */ -typedef struct type { - tspec_t t_tspec; /* type specifier */ - u_int t_const : 1; /* constant */ - u_int t_volatile : 1; /* volatile */ - u_int t_vararg : 1; /* function has variable number of arguments */ - u_int t_isenum : 1; /* enum type */ - u_int t_proto : 1; /* this is a prototype */ - u_int t_istag : 1; /* tag with _t_tag valid */ - u_int t_istynam : 1; /* tag with _t_tynam valid */ - union { - int _t_dim; /* if the type is an ARRAY than this - is the dimension of the array. */ - struct hte *_t_tag; /* hash table entry of tag if - t_isenum, STRUCT or UNION */ - struct hte *_t_tynam; /* hash table entry of typename if - t_isenum, STRUCT or UNION */ - struct type **_t_args; /* list of argument types if this - is a prototype */ - } t_u; - struct type *t_subt; /* indirected type (array element, pointed to - type, type of return value) */ -} type_t; - -#define t_dim t_u._t_dim -#define t_tag t_u._t_tag -#define t_tynam t_u._t_tynam -#define t_args t_u._t_args - -/* - * argument information - * - * Such a structure is created for each argument of a function call - * which is an integer constant or a constant string. - */ -typedef struct arginf { - int a_num; /* # of argument (1..) */ - u_int a_zero : 1; /* argument is 0 */ - u_int a_pcon : 1; /* msb of argument is not set */ - u_int a_ncon : 1; /* msb of argument is set */ - u_int a_fmt : 1; /* a_fstrg points to format string */ - char *a_fstrg; /* format string */ - struct arginf *a_nxt; /* information for next const. argument */ -} arginf_t; - -/* - * Keeps information about position in source file. - */ -typedef struct { - u_short p_src; /* index of name of translation unit - (the name which was specified at the - command line) */ - u_short p_line; /* line number in p_src */ - u_short p_isrc; /* index of (included) file */ - u_short p_iline; /* line number in p_iline */ -} pos_t; - -/* - * Used for definitions and declarations - * - * To save memory, variable sized structures are used. If - * all s_va, s_prfl and s_scfl are not set, the memory allocated - * for a symbol is only large enough to keep the first member of - * struct sym, s_s. - */ -typedef struct sym { - struct { - pos_t s_pos; /* pos of def./decl. */ -#ifndef lint - u_int s_def : 3; /* DECL, TDEF or DEF */ -#else - def_t s_def; -#endif - u_int s_rval : 1; /* function has return value */ - u_int s_osdef : 1; /* old style function definition */ - u_int s_static : 1; /* symbol is static */ - u_int s_va : 1; /* check only first s_nva arguments */ - u_int s_prfl : 1; /* printflike */ - u_int s_scfl : 1; /* scanflike */ - u_short s_type; /* type */ - struct sym *s_nxt; /* next symbol with same name */ - } s_s; - short s_nva; - short s_nprfl; - short s_nscfl; -} sym_t; - -#define s_pos s_s.s_pos -#define s_rval s_s.s_rval -#define s_osdef s_s.s_osdef -#define s_static s_s.s_static -#define s_def s_s.s_def -#define s_va s_s.s_va -#define s_prfl s_s.s_prfl -#define s_scfl s_s.s_scfl -#define s_type s_s.s_type -#define s_nxt s_s.s_nxt - -/* - * Used to store informations about function calls. - */ -typedef struct fcall { - pos_t f_pos; /* position of call */ - u_int f_rused : 1; /* return value used */ - u_int f_rdisc : 1; /* return value discarded (casted to void) */ - u_short f_type; /* types of expected return value and args */ - arginf_t *f_args; /* information about constant arguments */ - struct fcall *f_nxt; /* next call of same function */ -} fcall_t; - -/* - * Used to store information about usage of symbols other - * than for function calls. - */ -typedef struct usym { - pos_t u_pos; /* position */ - struct usym *u_nxt; /* next usage */ -} usym_t; - -/* - * hash table entry - */ -typedef struct hte { - const char *h_name; /* name */ - u_int h_used : 1; /* symbol is used */ - u_int h_def : 1; /* symbol is defined */ - u_int h_static : 1; /* static symbol */ - sym_t *h_syms; /* declarations and definitions */ - sym_t **h_lsym; /* points to s_nxt of last decl./def. */ - fcall_t *h_calls; /* function calls */ - fcall_t **h_lcall; /* points to f_nxt of last call */ - usym_t *h_usyms; /* usage info */ - usym_t **h_lusym; /* points to u_nxt of last usage info */ - struct hte *h_link; /* next hte with same hash function */ -} hte_t; - -/* maps type indices into pointers to type structs */ -#define TP(idx) (tlst[idx]) - -#include "externs2.h" diff --git a/usr.bin/xlint/lint2/main2.c b/usr.bin/xlint/lint2/main2.c deleted file mode 100644 index bd80c945aa6..00000000000 --- a/usr.bin/xlint/lint2/main2.c +++ /dev/null @@ -1,180 +0,0 @@ -/* $OpenBSD: main2.c,v 1.10 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: main2.c,v 1.2 1995/07/03 21:24:53 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "lint2.h" - -/* warnings for symbols which are declared but not defined or used */ -int xflag; - -/* - * warnings for symbols which are used and not defined or defined - * and not used - */ -int uflag = 1; - -/* Create a lint library in the current directory with name libname. */ -int Cflag; -const char *libname; - -int pflag; - -/* - * warnings for (tentative) definitions of the same name in more than - * one translation unit - */ -int sflag; - -/* - * If a complaint stems from a included file, print the name of the included - * file instead of the name spezified at the command line followed by '?' - */ -int Hflag; - -int hflag; - -/* Print full path names, not only the last component */ -int Fflag = 1; - -/* - * List of libraries (from -l flag). These libraries are read after all - * other input files has been read and, for Cflag, after the new lint library - * has been written. - */ -const char **libs; - -static void usage(void); - - -int -main(int argc, char *argv[]) -{ - int c, i; - size_t len; - char *lname; - - libs = xcalloc(1, sizeof (char *)); - - opterr = 0; - while ((c = getopt(argc, argv, "hpstxuC:HFl:")) != -1) { - switch (c) { - case 's': - sflag = 1; - break; - case 'u': - uflag = 0; - break; - case 'x': - xflag = 1; - break; - case 'p': - pflag = 1; - break; - case 'C': - len = strlen(optarg); - lname = xmalloc(len + 10); - (void)snprintf(lname, len + 10, "llib-l%s.ln", optarg); - libname = lname; - Cflag = 1; - uflag = 0; - break; - case 'H': - Hflag = 1; - break; - case 'h': - hflag = 1; - break; - case 'F': - Fflag = 1; - break; - case 'l': - for (i = 0; libs[i] != NULL; i++) ; - libs = xrealloc(libs, (i + 2) * sizeof (char *)); - libs[i] = xstrdup(optarg); - libs[i + 1] = NULL; - break; - case '?': - usage(); - } - } - - argc -= optind; - argv += optind; - - if (argc == 0) - usage(); - - initmem(); - - /* initialize hash table */ - inithash(); - - inittyp(); - - for (i = 0; i < argc; i++) - readfile(argv[i]); - - /* write the lint library */ - if (Cflag) { - forall(mkstatic); - outlib(libname); - } - - /* read additional libraries */ - for (i = 0; libs[i] != NULL; i++) - readfile(libs[i]); - - forall(mkstatic); - - mainused(); - - /* perform all tests */ - forall(chkname); - - exit(0); - /* NOTREACHED */ -} - -static void -usage(void) -{ - (void)fprintf(stderr, - "usage: lint2 -hpstxuHF -Clib -l lib ... src1 ...\n"); - exit(1); -} - diff --git a/usr.bin/xlint/lint2/mem2.c b/usr.bin/xlint/lint2/mem2.c deleted file mode 100644 index 6f60ac50283..00000000000 --- a/usr.bin/xlint/lint2/mem2.c +++ /dev/null @@ -1,93 +0,0 @@ -/* $OpenBSD: mem2.c,v 1.5 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: mem2.c,v 1.3 1995/10/02 17:27:11 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <unistd.h> -#include <string.h> -#include <err.h> - -#include "lint2.h" - -/* length of new allocated memory blocks */ -static size_t mblklen; - -/* offset of next free byte in mbuf */ -static size_t nxtfree; - -/* current buffer to server memory requests from */ -static void *mbuf; - -void -initmem(void) -{ - int pgsz; - - pgsz = getpagesize(); - mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz; - - nxtfree = mblklen; -} - -/* - * Allocate memory in large chunks to avoid space and time overhead of - * malloc(). This is possible because memory allocated by xalloc() - * need never to be freed. - */ -void * -xalloc(size_t sz) -{ - void *ptr; - int prot, flags; - - sz = ALIGN(sz); - if (nxtfree + sz > mblklen) { - /* use mmap() instead of malloc() to avoid malloc overhead. */ - prot = PROT_READ | PROT_WRITE; - flags = MAP_ANON | MAP_PRIVATE; - mbuf = mmap(NULL, mblklen, prot, flags, -1, (off_t)0); - if (mbuf == MAP_FAILED) - err(1, "can't map memory"); - if (ALIGN((u_long)mbuf) != (u_long)mbuf) - errx(1, "mapped address is not aligned"); - (void)memset(mbuf, 0, mblklen); - nxtfree = 0; - } - - ptr = (char *)mbuf + nxtfree; - nxtfree += sz; - - return (ptr); -} diff --git a/usr.bin/xlint/lint2/msg.c b/usr.bin/xlint/lint2/msg.c deleted file mode 100644 index ec61ad92a2c..00000000000 --- a/usr.bin/xlint/lint2/msg.c +++ /dev/null @@ -1,135 +0,0 @@ -/* $OpenBSD: msg.c,v 1.9 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: msg.c,v 1.2 1995/07/03 21:24:56 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <string.h> - -#include <stdio.h> -#include <stdarg.h> - -#include "lint2.h" - - -static const char *msgs[] = { - "%s: %s used, but not defined", /* 0 */ - "%s: %s defined, but never used", /* 1 */ - "%s: %s declared, but never used or defined", /* 2 */ - "%s: %s multiply defined (%s)", /* 3 */ - "%s: %s used inconsistently (%s)", /* 4 */ - "%s: %s declared inconsistently (%s)", /* 5 */ - "%s: %s arg %d used inconsistently (%s)", /* 6 */ - "%s: %s called with varying # of args (%s)", /* 7 */ - "%s returns value which is always ignored", /* 8 */ - "%s returns value which is sometimes ignored", /* 9 */ - "%s: return value of %s is used, but none returned", /* 10 */ - "%s: %s arg %d declared inconsistently (%s)", /* 11 */ - "%s: %s declared with varying # of args (%s)", /* 12 */ - "%s: malformed format string to %s", /* 13 */ - "%s, arg %d to %s inconsistent with format", /* 14 */ - "%s: too few format args to %s", /* 15 */ - "%s: too many format args to %s", /* 16 */ - "%s: %s must be declared before use (%s)", /* 17 */ -}; - -static const char *lbasename(const char *); - -void -msg(int n, ...) -{ - va_list ap; - - va_start(ap, n); - - (void)vprintf(msgs[n], ap); - (void)printf("\n"); - - va_end(ap); -} - -/* - * Return a pointer to the last component of a path. - */ -static const char * -lbasename(const char *path) -{ - const char *cp, *cp1, *cp2; - - if (Fflag) - return (path); - - cp = cp1 = cp2 = path; - while (*cp != '\0') { - if (*cp++ == '/') { - cp2 = cp1; - cp1 = cp; - } - } - return (*cp1 == '\0' ? cp2 : cp1); -} - -/* - * Create a string which describes a position in a source file. - */ -const char * -mkpos(pos_t *posp) -{ - size_t len; - const char *fn; - static char *buf; - static size_t blen = 0; - int qm, src, line; - - if (Hflag && posp->p_src != posp->p_isrc) { - src = posp->p_isrc; - line = posp->p_iline; - } else { - src = posp->p_src; - line = posp->p_line; - } - qm = !Hflag && posp->p_src != posp->p_isrc; - - len = strlen(fn = lbasename(fnames[src])); - len += 3 * sizeof (u_short) + 4; - - if (len > blen) - buf = xrealloc(buf, blen = len); - if (line != 0) { - (void)snprintf(buf, blen, "%s%s:%hu", - fn, qm ? "?" : "", line); - } else { - (void)snprintf(buf, blen, "%s", fn); - } - - return (buf); -} - diff --git a/usr.bin/xlint/lint2/read.c b/usr.bin/xlint/lint2/read.c deleted file mode 100644 index 7564eba0fd9..00000000000 --- a/usr.bin/xlint/lint2/read.c +++ /dev/null @@ -1,1132 +0,0 @@ -/* $OpenBSD: read.c,v 1.12 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <limits.h> -#include <err.h> - -#include "lint2.h" - - -/* index of current (included) source file */ -static int srcfile; - -/* - * The array pointed to by inpfns maps the file name indices of input files - * to the file name indices used in lint2 - */ -static short *inpfns; -static size_t ninpfns; - -/* - * The array pointed to by *fnames maps file name indizes to file names. - * Indices of type short are used instead of pointers to save memory. - */ -const char **fnames; -static size_t nfnames; - -/* - * Types are shared (to save memory for the types itself) and accessed - * via indices (to save memory for references to types (indices are short)). - * To share types, a equal type must be located fast. This is done by a - * hash table. Access by indices is done via an array of pointers to the - * types. - */ -typedef struct thtab { - const char *th_name; - u_short th_idx; - struct thtab *th_nxt; -} thtab_t; -static thtab_t **thtab; /* hash table */ -type_t **tlst; /* array for indexed access */ -static size_t tlstlen; /* length of tlst */ - -/* index of current C source file (as spezified at the command line) */ -int csrcfile; - - -static void inperr(void); -static void setsrc(const char *); -static void setfnid(int, const char *); -static void funccall(pos_t *, const char *); -static void decldef(pos_t *, const char *); -static void usedsym(pos_t *, const char *); -static u_short inptype(const char *, const char **); -static int gettlen(const char *, const char **); -static u_short findtype(const char *, size_t, int); -static u_short storetyp(type_t *, const char *, size_t, int); -static int thash(const char *, size_t); -static char *inpqstrg(const char *, const char **); -static const char *inpname(const char *, const char **); -static int getfnidx(const char *); - -void -readfile(const char *name) -{ - FILE *inp; - size_t len; - const char *cp; - char *line, *eptr, rt; - int cline, isrc, iline; - pos_t pos; - - if (inpfns == NULL) - inpfns = xcalloc(ninpfns = 128, sizeof (short)); - if (fnames == NULL) - fnames = xcalloc(nfnames = 256, sizeof (char *)); - if (tlstlen == 0) - tlst = xcalloc(tlstlen = 256, sizeof (type_t *)); - if (thtab == NULL) - thtab = xcalloc(THSHSIZ2, sizeof (thtab_t)); - - srcfile = getfnidx(name); - - if ((inp = fopen(name, "r")) == NULL) - err(1, "cannot open %s", name); - - while ((line = fgetln(inp, &len)) != NULL) { - - if (len == 0 || line[len - 1] != '\n') - inperr(); - line[len - 1] = '\0'; - cp = line; - - /* line number in csrcfile */ - cline = (int)strtol(cp, &eptr, 10); - if (cp == eptr) { - cline = -1; - } else { - cp = eptr; - } - - /* record type */ - if (*cp != '\0') { - rt = *cp++; - } else { - inperr(); - } - - if (rt == 'S') { - setsrc(cp); - continue; - } else if (rt == 's') { - setfnid(cline, cp); - continue; - } - - /* - * Index of (included) source file. If this index is - * different from csrcfile, it refers to an included - * file. - */ - isrc = (int)strtol(cp, &eptr, 10); - if (cp == eptr) - inperr(); - cp = eptr; - if (isrc < 0 || isrc >= ninpfns) - inperr(); - isrc = inpfns[isrc]; - - /* line number in isrc */ - if (*cp++ != '.') - inperr(); - iline = (int)strtol(cp, &eptr, 10); - if (cp == eptr) - inperr(); - cp = eptr; - - pos.p_src = (u_short)csrcfile; - pos.p_line = (u_short)cline; - pos.p_isrc = (u_short)isrc; - pos.p_iline = (u_short)iline; - - /* process rest of this record */ - switch (rt) { - case 'c': - funccall(&pos, cp); - break; - case 'd': - decldef(&pos, cp); - break; - case 'u': - usedsym(&pos, cp); - break; - default: - inperr(); - } - - } - - if (ferror(inp)) - err(1, "read error on %s", name); - - (void)fclose(inp); -} - - -static void -inperr(void) -{ - errx(1, "input file error: %s", fnames[srcfile]); -} - -/* - * Set the name of the C source file of the .ln file which is - * currently read. - */ -static void -setsrc(const char *cp) -{ - csrcfile = getfnidx(cp); -} - -/* - * setfnid() gets as input an index as used in an input file and the - * associated file name. If necessary, it creates a new lint2 file - * name index for this file name and creates the mapping of the index - * as used in the input file to the index used in lint2. - */ -static void -setfnid(int fid, const char *cp) -{ - if (fid == -1) - inperr(); - - if (fid >= ninpfns) { - inpfns = xrealloc(inpfns, (ninpfns * 2) * sizeof (short)); - (void)memset(inpfns + ninpfns, 0, ninpfns * sizeof (short)); - ninpfns *= 2; - } - /* - * Should always be true because indices written in the output - * file by lint1 are always the previous index + 1. - */ - if (fid >= ninpfns) - errx(1, "internal error: setfnid()"); - inpfns[fid] = (u_short)getfnidx(cp); -} - -/* - * Process a function call record (c-record). - */ -static void -funccall(pos_t *posp, const char *cp) -{ - arginf_t *ai, **lai; - char c, *eptr; - int rused, rdisc; - hte_t *hte; - fcall_t *fcall; - - fcall = xalloc(sizeof (fcall_t)); - STRUCT_ASSIGN(fcall->f_pos, *posp); - - /* read flags */ - rused = rdisc = 0; - lai = &fcall->f_args; - while ((c = *cp) == 'u' || c == 'i' || c == 'd' || - c == 'z' || c == 'p' || c == 'n' || c == 's') { - cp++; - switch (c) { - case 'u': - if (rused || rdisc) - inperr(); - rused = 1; - break; - case 'i': - if (rused || rdisc) - inperr(); - break; - case 'd': - if (rused || rdisc) - inperr(); - rdisc = 1; - break; - case 'z': - case 'p': - case 'n': - case 's': - ai = xalloc(sizeof (arginf_t)); - ai->a_num = (int)strtol(cp, &eptr, 10); - if (cp == eptr) - inperr(); - cp = eptr; - if (c == 'z') { - ai->a_pcon = ai->a_zero = 1; - } else if (c == 'p') { - ai->a_pcon = 1; - } else if (c == 'n') { - ai->a_ncon = 1; - } else { - ai->a_fmt = 1; - ai->a_fstrg = inpqstrg(cp, &cp); - } - *lai = ai; - lai = &ai->a_nxt; - break; - } - } - fcall->f_rused = rused; - fcall->f_rdisc = rdisc; - - /* read name of function */ - hte = hsearch(inpname(cp, &cp), 1); - hte->h_used = 1; - - fcall->f_type = inptype(cp, &cp); - - *hte->h_lcall = fcall; - hte->h_lcall = &fcall->f_nxt; - - if (*cp != '\0') - inperr(); -} - -/* - * Process a declaration or definition (d-record). - */ -static void -decldef(pos_t *posp, const char *cp) -{ - sym_t *symp, sym; - char c, *ep; - int used; - hte_t *hte; - - (void)memset(&sym, 0, sizeof (sym)); - STRUCT_ASSIGN(sym.s_pos, *posp); - sym.s_def = NODECL; - - used = 0; - - while ((c = *cp) == 't' || c == 'd' || c == 'e' || c == 'u' || - c == 'r' || c == 'o' || c == 's' || c == 'v' || - c == 'P' || c == 'S') { - cp++; - switch (c) { - case 't': - if (sym.s_def != NODECL) - inperr(); - sym.s_def = TDEF; - break; - case 'd': - if (sym.s_def != NODECL) - inperr(); - sym.s_def = DEF; - break; - case 'e': - if (sym.s_def != NODECL) - inperr(); - sym.s_def = DECL; - break; - case 'u': - if (used) - inperr(); - used = 1; - break; - case 'r': - if (sym.s_rval) - inperr(); - sym.s_rval = 1; - break; - case 'o': - if (sym.s_osdef) - inperr(); - sym.s_osdef = 1; - break; - case 's': - if (sym.s_static) - inperr(); - sym.s_static = 1; - break; - case 'v': - if (sym.s_va) - inperr(); - sym.s_va = 1; - sym.s_nva = (short)strtol(cp, &ep, 10); - if (cp == ep) - inperr(); - cp = ep; - break; - case 'P': - if (sym.s_prfl) - inperr(); - sym.s_prfl = 1; - sym.s_nprfl = (short)strtol(cp, &ep, 10); - if (cp == ep) - inperr(); - cp = ep; - break; - case 'S': - if (sym.s_scfl) - inperr(); - sym.s_scfl = 1; - sym.s_nscfl = (short)strtol(cp, &ep, 10); - if (cp == ep) - inperr(); - cp = ep; - break; - } - } - - /* read symbol name */ - hte = hsearch(inpname(cp, &cp), 1); - hte->h_used |= used; - if (sym.s_def == DEF || sym.s_def == TDEF) - hte->h_def = 1; - - sym.s_type = inptype(cp, &cp); - - /* - * Allocate memory for this symbol only if it was not already - * declared or tentatively defined at the same location with - * the same type. Works only for symbols with external linkage, - * because static symbols, tentatively defined at the same location - * but in different translation units are really different symbols. - */ - for (symp = hte->h_syms; symp != NULL; symp = symp->s_nxt) { - if (symp->s_pos.p_isrc == sym.s_pos.p_isrc && - symp->s_pos.p_iline == sym.s_pos.p_iline && - symp->s_type == sym.s_type && - ((symp->s_def == DECL && sym.s_def == DECL) || - (!sflag && symp->s_def == TDEF && sym.s_def == TDEF)) && - !symp->s_static && !sym.s_static) { - break; - } - } - - if (symp == NULL) { - /* allocsym reserviert keinen Platz fuer s_nva */ - if (sym.s_va || sym.s_prfl || sym.s_scfl) { - symp = xalloc(sizeof (sym_t)); - STRUCT_ASSIGN(*symp, sym); - } else { - symp = xalloc(sizeof (symp->s_s)); - STRUCT_ASSIGN(symp->s_s, sym.s_s); - } - *hte->h_lsym = symp; - hte->h_lsym = &symp->s_nxt; - } - - if (*cp != '\0') - inperr(); -} - -/* - * Read an u-record (emited by lint1 if a symbol was used). - */ -static void -usedsym(pos_t *posp, const char *cp) -{ - usym_t *usym; - hte_t *hte; - - usym = xalloc(sizeof (usym_t)); - STRUCT_ASSIGN(usym->u_pos, *posp); - - /* needed as delimiter between two numbers */ - if (*cp++ != 'x') - inperr(); - - hte = hsearch(inpname(cp, &cp), 1); - hte->h_used = 1; - - *hte->h_lusym = usym; - hte->h_lusym = &usym->u_nxt; -} - -/* - * Read a type and return the index of this type. - */ -static u_short -inptype(const char *cp, const char **epp) -{ - char c, s, *eptr; - const char *ep; - type_t *tp; - int narg, i, osdef; - size_t tlen; - u_short tidx; - int h; - - /* If we have this type already, return it's index. */ - tlen = gettlen(cp, &ep); - h = thash(cp, tlen); - if ((tidx = findtype(cp, tlen, h)) != 0) { - *epp = ep; - return (tidx); - } - - /* No, we must create a new type. */ - tp = xalloc(sizeof (type_t)); - - tidx = storetyp(tp, cp, tlen, h); - - c = *cp++; - - while (c == 'c' || c == 'v') { - if (c == 'c') { - tp->t_const = 1; - } else { - tp->t_volatile = 1; - } - c = *cp++; - } - - if (c == 's' || c == 'u' || c == 'l' || c == 'e') { - s = c; - c = *cp++; - } else { - s = '\0'; - } - - switch (c) { - case 'B': - tp->t_tspec = BOOL; - break; - case 'C': - tp->t_tspec = s == 's' ? SCHAR : (s == 'u' ? UCHAR : CHAR); - break; - case 'S': - tp->t_tspec = s == 'u' ? USHORT : SHORT; - break; - case 'I': - tp->t_tspec = s == 'u' ? UINT : INT; - break; - case 'L': - tp->t_tspec = s == 'u' ? ULONG : LONG; - break; - case 'Q': - tp->t_tspec = s == 'u' ? UQUAD : QUAD; - break; - case 'D': - tp->t_tspec = s == 's' ? FLOAT : (s == 'l' ? LDOUBLE : DOUBLE); - break; - case 'X': - tp->t_tspec = s == 's' ? COMPLEX : (s == 'l' ? - LDCOMPLEX : DCOMPLEX); - break; - case 'J': - tp->t_tspec = s == 's' ? IMAGINARY : (s == 'l' ? - LDIMAGINARY : DIMAGINARY); - break; - case 'V': - tp->t_tspec = VOID; - break; - case 'P': - tp->t_tspec = PTR; - break; - case 'A': - tp->t_tspec = ARRAY; - break; - case 'F': - case 'f': - osdef = c == 'f'; - tp->t_tspec = FUNC; - break; - case 'T': - tp->t_tspec = s == 'e' ? ENUM : (s == 's' ? STRUCT : UNION); - break; - } - - switch (tp->t_tspec) { - case ARRAY: - tp->t_dim = (int)strtol(cp, &eptr, 10); - cp = eptr; - tp->t_subt = TP(inptype(cp, &cp)); - break; - case PTR: - tp->t_subt = TP(inptype(cp, &cp)); - break; - case FUNC: - c = *cp; - if (isdigit((u_char)c)) { - if (!osdef) - tp->t_proto = 1; - narg = (int)strtol(cp, &eptr, 10); - cp = eptr; - tp->t_args = xcalloc((size_t)(narg + 1), - sizeof (type_t *)); - for (i = 0; i < narg; i++) { - if (i == narg - 1 && *cp == 'E') { - tp->t_vararg = 1; - cp++; - } else { - tp->t_args[i] = TP(inptype(cp, &cp)); - } - } - } - tp->t_subt = TP(inptype(cp, &cp)); - break; - case ENUM: - tp->t_tspec = INT; - tp->t_isenum = 1; - /* FALLTHROUGH */ - case STRUCT: - case UNION: - switch (*cp++) { - case '0': - break; - case '1': - tp->t_istag = 1; - tp->t_tag = hsearch(inpname(cp, &cp), 1); - break; - case '2': - tp->t_istynam = 1; - tp->t_tynam = hsearch(inpname(cp, &cp), 1); - break; - } - break; - /* LINTED (enumeration value(s) not handled in switch) */ - } - - *epp = cp; - return (tidx); -} - -/* - * Get the length of a type string. - */ -static int -gettlen(const char *cp, const char **epp) -{ - const char *cp1; - char c, s, *eptr; - tspec_t t; - int narg, i, cm, vm; - - cp1 = cp; - - c = *cp++; - - cm = vm = 0; - - while (c == 'c' || c == 'v') { - if (c == 'c') { - if (cm) - inperr(); - cm = 1; - } else { - if (vm) - inperr(); - vm = 1; - } - c = *cp++; - } - - if (c == 's' || c == 'u' || c == 'l' || c == 'e') { - s = c; - c = *cp++; - } else { - s = '\0'; - } - - t = NOTSPEC; - - switch (c) { - case 'B': - t = BOOL; - break; - case 'C': - if (s == 's') { - t = SCHAR; - } else if (s == 'u') { - t = UCHAR; - } else if (s == '\0') { - t = CHAR; - } - break; - case 'S': - if (s == 'u') { - t = USHORT; - } else if (s == '\0') { - t = SHORT; - } - break; - case 'I': - if (s == 'u') { - t = UINT; - } else if (s == '\0') { - t = INT; - } - break; - case 'L': - if (s == 'u') { - t = ULONG; - } else if (s == '\0') { - t = LONG; - } - break; - case 'Q': - if (s == 'u') { - t = UQUAD; - } else if (s == '\0') { - t = QUAD; - } - break; - case 'D': - if (s == 's') { - t = FLOAT; - } else if (s == 'l') { - t = LDOUBLE; - } else if (s == '\0') { - t = DOUBLE; - } - break; - case 'X': - if (s == 's') { - t = COMPLEX; - } else if (s == 'l') { - t = LDCOMPLEX; - } else if (s == '\0') { - t = DCOMPLEX; - } - break; - case 'J': - if (s == 's') { - t = IMAGINARY; - } else if (s == 'l') { - t = LDIMAGINARY; - } else if (s == '\0') { - t = DIMAGINARY; - } - break; - case 'V': - if (s == '\0') - t = VOID; - break; - case 'P': - if (s == '\0') - t = PTR; - break; - case 'A': - if (s == '\0') - t = ARRAY; - break; - case 'F': - case 'f': - if (s == '\0') - t = FUNC; - break; - case 'T': - if (s == 'e') { - t = ENUM; - } else if (s == 's') { - t = STRUCT; - } else if (s == 'u') { - t = UNION; - } - break; - default: - inperr(); - } - - if (t == NOTSPEC) - inperr(); - - switch (t) { - case ARRAY: - (void)strtol(cp, &eptr, 10); - if (cp == eptr) - inperr(); - cp = eptr; - (void)gettlen(cp, &cp); - break; - case PTR: - (void)gettlen(cp, &cp); - break; - case FUNC: - c = *cp; - if (isdigit((u_char)c)) { - narg = (int)strtol(cp, &eptr, 10); - cp = eptr; - for (i = 0; i < narg; i++) { - if (i == narg - 1 && *cp == 'E') { - cp++; - } else { - (void)gettlen(cp, &cp); - } - } - } - (void)gettlen(cp, &cp); - break; - case ENUM: - case STRUCT: - case UNION: - switch (*cp++) { - case '0': - break; - case '1': - (void)inpname(cp, &cp); - break; - case '2': - (void)inpname(cp, &cp); - break; - default: - inperr(); - } - break; - /* LINTED (enumeration value(s) not handled in switch) */ - } - - *epp = cp; - return (cp - cp1); -} - -/* - * Search a type by it's type string. - */ -static u_short -findtype(const char *cp, size_t len, int h) -{ - thtab_t *thte; - - for (thte = thtab[h]; thte != NULL; thte = thte->th_nxt) { - if (strncmp(thte->th_name, cp, len) != 0) - continue; - if (thte->th_name[len] == '\0') - return (thte->th_idx); - } - - return (0); -} - -/* - * Store a type and it's type string so we can later share this type - * if we read the same type string from the input file. - */ -static u_short -storetyp(type_t *tp, const char *cp, size_t len, int h) -{ - /* 0 ist reserved */ - static u_int tidx = 1; - thtab_t *thte; - char *name; - - if (tidx >= USHRT_MAX) - errx(1, "sorry, too many types"); - - if (tidx == tlstlen - 1) { - tlst = xrealloc(tlst, (tlstlen * 2) * sizeof (type_t *)); - (void)memset(tlst + tlstlen, 0, tlstlen * sizeof (type_t *)); - tlstlen *= 2; - } - - tlst[tidx] = tp; - - /* create a hash table entry */ - name = xalloc(len + 1); - (void)memcpy(name, cp, len); - name[len] = '\0'; - - thte = xalloc(sizeof (thtab_t)); - thte->th_name = name; - thte->th_idx = tidx; - thte->th_nxt = thtab[h]; - thtab[h] = thte; - - return ((u_short)tidx++); -} - -/* - * Hash function for types - */ -static int -thash(const char *s, size_t len) -{ - u_int v; - - v = 0; - while (len-- != 0) { - v = (v << sizeof (v)) + (u_char)*s++; - v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v)); - } - return (v % THSHSIZ2); -} - -/* - * Read a string enclosed by "". This string may contain quoted chars. - */ -static char * -inpqstrg(const char *src, const char **epp) -{ - char *strg, *dst; - size_t slen; - int c; - int v; - - dst = strg = xmalloc(slen = 32); - - if ((c = *src++) != '"') - inperr(); - if ((c = *src++) == '\0') - inperr(); - - while (c != '"') { - if (c == '\\') { - if ((c = *src++) == '\0') - inperr(); - switch (c) { - case 'n': - c = '\n'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case 'b': - c = '\b'; - break; - case 'r': - c = '\r'; - break; - case 'f': - c = '\f'; - break; - case 'a': - c = '\a'; - break; - case '\\': - c = '\\'; - break; - case '"': - c = '"'; - break; - case '\'': - c = '\''; - break; - case '0': case '1': case '2': case '3': - v = (c - '0') << 6; - if ((c = *src++) < '0' || c > '7') - inperr(); - v |= (c - '0') << 3; - if ((c = *src++) < '0' || c > '7') - inperr(); - v |= c - '0'; - c = (u_char)v; - break; - default: - inperr(); - } - } - /* keep space for trailing '\0' */ - if (dst - strg == slen - 1) { - strg = xrealloc(strg, slen * 2); - dst = strg + (slen - 1); - slen *= 2; - } - *dst++ = (char)c; - if ((c = *src++) == '\0') - inperr(); - } - *dst = '\0'; - - *epp = src; - return (strg); -} - -/* - * Read the name of a symbol in static memory. - */ -static const char * -inpname(const char *cp, const char **epp) -{ - static char *buf; - static size_t blen = 0; - size_t len, i; - char *eptr, c; - - len = (int)strtol(cp, &eptr, 10); - if (cp == eptr) - inperr(); - cp = eptr; - if (len + 1 > blen) - buf = xrealloc(buf, blen = len + 1); - for (i = 0; i < len; i++) { - c = *cp++; - if (!isalnum(c) && c != '_') - inperr(); - buf[i] = c; - } - buf[i] = '\0'; - - *epp = cp; - return (buf); -} - -/* - * Return the index of a file name. If the name cannot be found, create - * a new entry and return the index of the newly created entry. - */ -static int -getfnidx(const char *fn) -{ - int i; - - /* 0 ist reserved */ - for (i = 1; fnames[i] != NULL; i++) { - if (strcmp(fnames[i], fn) == 0) - break; - } - if (fnames[i] != NULL) - return (i); - - if (i == nfnames - 1) { - fnames = xrealloc(fnames, (nfnames * 2) * sizeof (char *)); - (void)memset(fnames + nfnames, 0, nfnames * sizeof (char *)); - nfnames *= 2; - } - - fnames[i] = xstrdup(fn); - return (i); -} - -/* - * Separate symbols with static and external linkage. - */ -void -mkstatic(hte_t *hte) -{ - sym_t *sym1, **symp, *sym; - fcall_t **callp, *call; - usym_t **usymp, *usym; - hte_t *nhte; - int ofnd; - - /* Look for first static definition */ - for (sym1 = hte->h_syms; sym1 != NULL; sym1 = sym1->s_nxt) { - if (sym1->s_static) - break; - } - if (sym1 == NULL) - return; - - /* Do nothing if this name is used only in one translation unit. */ - ofnd = 0; - for (sym = hte->h_syms; sym != NULL && !ofnd; sym = sym->s_nxt) { - if (sym->s_pos.p_src != sym1->s_pos.p_src) - ofnd = 1; - } - for (call = hte->h_calls; call != NULL && !ofnd; call = call->f_nxt) { - if (call->f_pos.p_src != sym1->s_pos.p_src) - ofnd = 1; - } - for (usym = hte->h_usyms; usym != NULL && !ofnd; usym = usym->u_nxt) { - if (usym->u_pos.p_src != sym1->s_pos.p_src) - ofnd = 1; - } - if (!ofnd) { - hte->h_used = 1; - /* errors about undef. static symbols are printed in lint1 */ - hte->h_def = 1; - hte->h_static = 1; - return; - } - - /* - * Create a new hash table entry - * - * XXX this entry should be put at the beginning of the list to - * avoid to process the same symbol twice. - */ - for (nhte = hte; nhte->h_link != NULL; nhte = nhte->h_link) ; - nhte->h_link = xalloc(sizeof (hte_t)); - memset(nhte->h_link, 0, sizeof (hte_t)); - nhte = nhte->h_link; - nhte->h_name = hte->h_name; - nhte->h_static = 1; - nhte->h_used = 1; - nhte->h_def = 1; /* error in lint1 */ - nhte->h_lsym = &nhte->h_syms; - nhte->h_lcall = &nhte->h_calls; - nhte->h_lusym = &nhte->h_usyms; - - /* - * move all symbols used in this translation unit into the new - * hash table entry. - */ - for (symp = &hte->h_syms; (sym = *symp) != NULL; ) { - if (sym->s_pos.p_src == sym1->s_pos.p_src) { - sym->s_static = 1; - (*symp) = sym->s_nxt; - if (hte->h_lsym == &sym->s_nxt) - hte->h_lsym = symp; - sym->s_nxt = NULL; - *nhte->h_lsym = sym; - nhte->h_lsym = &sym->s_nxt; - } else { - symp = &sym->s_nxt; - } - } - for (callp = &hte->h_calls; (call = *callp) != NULL; ) { - if (call->f_pos.p_src == sym1->s_pos.p_src) { - (*callp) = call->f_nxt; - if (hte->h_lcall == &call->f_nxt) - hte->h_lcall = callp; - call->f_nxt = NULL; - *nhte->h_lcall = call; - nhte->h_lcall = &call->f_nxt; - } else { - callp = &call->f_nxt; - } - } - for (usymp = &hte->h_usyms; (usym = *usymp) != NULL; ) { - if (usym->u_pos.p_src == sym1->s_pos.p_src) { - (*usymp) = usym->u_nxt; - if (hte->h_lusym == &usym->u_nxt) - hte->h_lusym = usymp; - usym->u_nxt = NULL; - *nhte->h_lusym = usym; - nhte->h_lusym = &usym->u_nxt; - } else { - usymp = &usym->u_nxt; - } - } - - /* h_def must be recalculated for old hte */ - hte->h_def = nhte->h_def = 0; - for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { - if (sym->s_def == DEF || sym->s_def == TDEF) { - hte->h_def = 1; - break; - } - } - - mkstatic(hte); -} diff --git a/usr.bin/xlint/llib/Makefile b/usr.bin/xlint/llib/Makefile deleted file mode 100644 index 59f1b431107..00000000000 --- a/usr.bin/xlint/llib/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $OpenBSD: Makefile,v 1.4 1997/04/27 20:56:59 millert Exp $ -# $NetBSD: Makefile,v 1.2 1995/07/03 21:25:05 cgd Exp $ - -LIBS= llib-lposix.ln llib-lstdc.ln - -all: ${LIBS} - -install: - ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${NONBINMODE} \ - ${LIBS} ${DESTDIR}${LINTLIBDIR} - -clean cleanall: - rm -f ${LIBS} - -llib-lposix.ln: llib-lposix - lint -Cposix ${.ALLSRC} - -llib-lstdc.ln: llib-lstdc - lint -Cstdc ${.ALLSRC} - -.include <bsd.prog.mk> diff --git a/usr.bin/xlint/llib/llib-lposix b/usr.bin/xlint/llib/llib-lposix deleted file mode 100644 index 31bde403454..00000000000 --- a/usr.bin/xlint/llib/llib-lposix +++ /dev/null @@ -1,410 +0,0 @@ -/* $OpenBSD: llib-lposix,v 1.4 2010/12/30 21:45:31 guenther Exp $ */ -/* $NetBSD: llib-lposix,v 1.2 1995/07/03 21:25:09 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* LINTLIBRARY */ - -#define _POSIX_SOURCE -#define _ANSI_LIBRARY - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <sys/times.h> -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <assert.h> -#include <termios.h> -#include <dirent.h> -#include <fcntl.h> -#include <grp.h> -#include <pwd.h> -#include <ctype.h> -#include <signal.h> -#include <locale.h> -#include <setjmp.h> -#include <string.h> -#include <syslog.h> -#include <utime.h> -#include <wchar.h> -#include <wctype.h> - - -/* PROTOLIB1 */ - - -void (abort)(void); -int (abs)(int j); -int (access)(const char *path, int amode); -double (acos)(double x); -unsigned (alarm)(unsigned seconds); -char *(asctime)(const struct tm *timeptr); -double (asin)(double x); -void (__assert)(const char *expression, int line, const char *file); -double (atan)(double x); -double (atan2)(double y, double x); -int (atexit)(void (*func)(void)); -double (atof)(const char *nptr); -int (atoi)(const char *nptr); -long (atol)(const char *nptr); -void *(bsearch)(const void *key, const void *base, size_t nmemb, - size_t size, int (*compar)(const void *, const void *)); -wint_t (btowc)(int); -void *(calloc)(size_t nmemb, size_t size); -double (ceil)(double x); -speed_t (cfgetispeed)(const struct termios *p); -speed_t (cfgetospeed)(const struct termios *p); -int (cfsetispeed)(struct termios *p, speed_t speed); -int (cfsetospeed)(struct termios *p, speed_t speed); -int (chdir)(const char *path); -int (chmod)(const char *path, mode_t mode); -int (chown)(const char *path, uid_t owner, gid_t group); -void (clearerr)(FILE *stream); -clock_t (clock)(void); -int (close)(int fildes); -int (closedir)(DIR *dirp); -void (closelog)(void); -double (cos)(double x); -double (cosh)(double x); -int (creat)(const char *path, mode_t mode); -char *(ctermid)(char *s); -char *(ctime)(const time_t *timer); -char *(cuserid)(char *s); -double (difftime)(time_t time1, time_t time0); -div_t (div)(int numer, int denom); -int (dup)(int fildes); -int (dup2)(int fildes, int fildes2); -int (errno); -int (execl)(const char *path, const char *arg, ...); -int (execle)(const char *path, const char *arg, ...); -int (execlp)(const char *file, const char *arg, ...); -int (execv)(const char *path, char *const argv[]); -int (execve)(const char *path, char *const argv[], char *const *envp); -int (execvp)(const char *file, char *const argv[]); -void (exit)(int status); -void (_exit)(int status); -double (exp)(double x); -double (fabs)(double x); -int (fclose)(FILE *stream); -int (fcntl)(int fildes, int cmd, ...); -FILE *(fdopen)(int fildes, const char *type); -int (feof)(FILE *stream); -int (ferror)(FILE *stream); -int (fflush)(FILE *stream); -int (fgetc)(FILE *stream); -int (fgetpos)(FILE *stream, fpos_t *pos); -char *(fgets)(char *s, int n, FILE *stream); -wint_t (fgetwc)(FILE *); -wchar_t *(fgetws)(wchar_t *, int, FILE *); -int (fileno)(FILE *stream); -double (floor)(double x); -double (fmod)(double x, double y); -FILE *(fopen)(const char *filename, const char *mode); -pid_t (fork)(void); -long (fpathconf)(int fildes, int name); -/* PRINTFLIKE2 */ -int (fprintf)(FILE *stream, const char *format, ...); -int (fputc)(int c, FILE *stream); -int (fputs)(const char *s, FILE *stream); -wint_t (fputwc)(wchar_t, FILE *); -int (fputws)(const wchar_t *, FILE *); -size_t (fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); -void (free)(void *ptr); -FILE *(freopen)(const char *filename, const char *mode, FILE *stream); -double (frepx)(double value, int *exp); -/* SCANFLIKE2 */ -int (fscanf)(FILE *stream, const char *format, ...); -int (fseek)(FILE *stream, long int offset, int whence); -int (fsetpos)(FILE *stream, const fpos_t *pos); -int (fstat)(int fildes, struct stat *buf); -long (ftell)(FILE *stream); -int (fwide)(FILE *, int); -size_t (fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream); -int (getc)(FILE *stream); -int (getchar)(void); -char *(getcwd)(char *buf, size_t size); -gid_t (getegid)(void); -char *(getenv)(const char *name); -uid_t (geteuid)(void); -gid_t (getgid)(void); -struct group *(getgrgid)(gid_t gid); -struct group *(getgrnam)(const char *name); -int (getgroups)(int gidsetsize, gid_t grouplist[]); -char *(getlogin)(void); -pid_t (getpgrp)(void); -pid_t (getpid)(void); -pid_t (getppid)(void); -struct passwd *(getpwnam)(const char *name); -struct passwd *(getpwuid)(uid_t uid); -char *(gets)(char *s); -uid_t (getuid)(void); -wint_t (getwc)(FILE *); -wint_t (getwchar)(void); -struct tm *(gmtime)(const time_t *timer); -int (isalnum)(int c); -int (isalpha)(int c); -int (isatty)(int fildes); -int (iscntrl)(int c); -int (isdigit)(int c); -int (isgraph)(int c); -int (islower)(int c); -int (isprint)(int c); -int (ispunct)(int c); -int (isspace)(int c); -int (isupper)(int c); -int (iswalnum)(wint_t wc); -int (iswalpha)(wint_t wc); -int (iswcntrl)(wint_t wc); -int (iswctype)(wint_t wc, wctype_t charclass); -int (iswdigit)(wint_t wc); -int (iswgraph)(wint_t wc); -int (iswlower)(wint_t wc); -int (iswprint)(wint_t wc); -int (iswpunct)(wint_t wc); -int (iswspace)(wint_t wc); -int (iswupper)(wint_t wc); -int (iswxdigit)(wint_t wc); -int (isxdigit)(int c); -int (kill)(pid_t pid, int sig); -long (labs)(long j); -double (ldexp)(double x, int exp); -ldiv_t (ldiv)(long numer, long denom); -int (link)(const char *existing, const char *new); -struct lconv *(localeconv)(void); -struct tm *(localtime)(const time_t *timer); -double (log)(double x); -double (log10)(double x); -void (longjmp)(jmp_buf env, int val); -off_t (lseek)(int fildes, off_t offset, int whence); -int (lstat)(const char *path, struct stat *buf); -void *(malloc)(size_t size); -int (mblen)(const char *s, size_t n); -size_t (mbrlen)(const char *, size_t, mbstate_t *); -size_t (mbrtowc)(wchar_t *, const char *, size_t, mbstate_t *); -int (mbsinit)(const mbstate_t *); -size_t (mbsrtowcs)(wchar_t *, const char **, size_t, mbstate_t *); -size_t (mbstowcs)(wchar_t *pwcs, const char *s, size_t n); -int (mbtowc)(wchar_t *pwc, const char *s, size_t n); -void *(memchr)(const void *s, int c, size_t n); -int (memcmp)(const void *s1, const void *s2, size_t n); -void *(memcpy)(void *s1, const void *s2, size_t n); -void *(memmove)(void *s1, const void *s2, size_t n); -void *(memset)(void *s, int c, size_t n); -int (mkdir)(const char *path, mode_t mode); -int (mkfifo)(const char *path, mode_t mode); -time_t (mktime)(struct tm *timeptr); -double (modf)(double value, double *iptr); -int (open)(const char *path, int oflag, ...); -void (openlog)(const char *, int, int); -DIR *(opendir)(const char *dirname); -long (pathconf)(const char *path, int name); -int (pause)(void); -void (perror)(const char *s); -int (pipe)(int fildes[2]); -double (pow)(double x, double y); -/* PRINTFLIKE1 */ -int (printf)(const char *format, ...); -int (putc)(int c, FILE *stream); -int (putchar)(int c); -int (puts)(const char *s); -wint_t (putwc)(wchar_t, FILE *); -wint_t (putwchar)(wchar_t); -void (qsort)(void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *)); -int (raise)(int sig); -int (rand)(void); -ssize_t (read)(int fildes, void *buf, size_t nbyte); -struct dirent *(readdir)(DIR *dirp); -void *(realloc)(void *ptr, size_t size); -int (remove)(const char *filename); -int (rename)(const char *old, const char *new); -void (rewind)(FILE *stream); -void (rewinddir)(DIR *dirp); -int (rmdir)(const char *path); -/* SCANFLIKE1 */ -int (scanf)(const char *format, ...); -void (setbuf)(FILE *stream, char *buf); -int (setgid)(gid_t gid); -int (setjmp)(jmp_buf env); -char *(setlocale)(int category, const char *locale); -int (setlogmask)(int); -int (setpgid)(pid_t pid, pid_t pgid); -pid_t (setsid)(void); -int (setuid)(uid_t uid); -int (setvbuf)(FILE *stream, char *buf, int mode, size_t size); -int (sigaction)(int sig, const struct sigaction *act, - struct sigaction *oact); -int (sigaddset)(sigset_t *set, int signo); -int (sigdelset)(sigset_t *set, int signo); -int (sigemptyset)(sigset_t *set); -int (sigfillset)(sigset_t *set); -int (sigismember)(const sigset_t *set, int signo); -void (siglongjmp)(sigjmp_buf env, int val); -void (*(signal)(int sig, void (*func)(int)))(int); -int (sigpending)(sigset_t *set); -int (sigprocmask)(int how, const sigset_t *set, sigset_t *oset); -int (sigsetjmp)(sigjmp_buf env, int savemask); -int (sigsuspend)(const sigset_t *sigmask); -double (sin)(double x); -double (sinh)(double x); -unsigned (sleep)(unsigned seconds); -/* PRINTFLIKE2 */ -int (sprintf)(char *s, const char *format, ...); -double (sqrt)(double x); -void (srand)(unsigned seed); -/* SCANFLIKE2 */ -int (sscanf)(const char *s, const char *format, ...); -int (stat)(const char *path, struct stat *buf); -char *(strcat)(char *s1, const char *s2); -char *(strchr)(const char *s, int c); -int (strcmp)(const char *s1, const char *s2); -int (strcoll)(const char *s1, const char *s2); -char *(strcpy)(char *s1, const char *s2); -size_t (strcspn)(const char *s1, const char *s2); -char *(strerror)(int errnum); -size_t (strftime)(char *s, size_t maxsize, const char *format, - const struct tm *timeptr); -size_t (strlen)(const char *s); -char *(strncat)(char *s1, const char *s2, size_t n); -int (strncmp)(const char *s1, const char *s2, size_t n); -char *(strncpy)(char *s1, const char *s2, size_t n); -char *(strpbrk)(const char *s1, const char *s2); -char *(strrchr)(const char *s, int c); -size_t (strspn)(const char *s1, const char *s2); -char *(strstr)(const char *s1, const char *s2); -double (strtod)(const char *nptr, char **endptr); -char *(strtok)(char *s1, const char *s2); -long (strtol)(const char *nptr, char **endptr, int base); -unsigned long (strtoul)(const char *nptr, char **endptr, int base); -size_t (strxfrm)(char *s1, const char *s2, size_t n); -long (sysconf)(int name); -/* PRINTFLIKE2 */ -void (syslog)(int, const char *, ...); -int (system)(const char *string); -double (tan)(double x); -double (tanh)(double x); -int (tcdrain)(int fildes); -int (tcflow)(int fildes, int action); -int (tcflush)(int fildes, int queue_selector); -int (tcgetattr)(int fildes, struct termios *tp); -pid_t (tcgetpgrp)(int fildes); -int (tcsendbreak)(int fildes, int duration); -int (tcsetattr)(int fildes, int options, const struct termios *tp); -int (tcsetpgrp)(int fildes, pid_t pgrpid); -time_t (time)(time_t *timer); -clock_t (times)(struct tms *buffer); -FILE *(tmpfile)(void); -char *(tmpnam)(char *s); -int (tolower)(int c); -int (toupper)(int c); -wint_t (towctrans)(wint_t wc, wctrans_t charmap); -wint_t (towlower)(wint_t wc); -wint_t (towupper)(wint_t wc); -char *(ttyname)(int filedes); -void (tzset)(void); -mode_t (umask)(mode_t cmask); -int (uname)(struct utsname *name); -int (ungetc)(int c, FILE *stream); -wint_t (ungetwc)(wint_t, FILE *); -int (unlink)(const char *path); -int (utime)(const char *path, const struct utimbuf *times); -int (vfprintf)(FILE *stream, const char *format, va_list arg); -int (vprintf)(const char *format, va_list arg); -int (vsprintf)(char *s, const char *format, va_list arg); -pid_t (wait)(int *statloc); -pid_t (waitpid)(pid_t pid, int *stat_loc, int options); -size_t (wcrtomb)(char *, wchar_t, mbstate_t *); -wchar_t *(wcscat)(wchar_t *, const wchar_t *); -wchar_t *(wcschr)(const wchar_t *, wchar_t); -int (wcscmp)(const wchar_t *, const wchar_t *); -wchar_t *(wcscpy)(wchar_t *, const wchar_t *); -size_t (wcscspn)(const wchar_t *, const wchar_t *); -size_t (wcslen)(const wchar_t *); -wchar_t *(wcsncat)(wchar_t *, const wchar_t *, size_t); -int (wcsncmp)(const wchar_t *, const wchar_t *, size_t); -wchar_t *(wcsncpy)(wchar_t *, const wchar_t *, size_t); -wchar_t *(wcspbrk)(const wchar_t *, const wchar_t *); -wchar_t *(wcsrchr)(const wchar_t *, wchar_t); -size_t (wcsrtombs)(char *, const wchar_t **, size_t, mbstate_t *); -size_t (wcsspn)(const wchar_t *, const wchar_t *); -wchar_t *(wcsstr)(const wchar_t *, const wchar_t *); -double (wcstod)(const wchar_t *, wchar_t **); -wchar_t *(wcstok)(wchar_t *, const wchar_t *, wchar_t **); -long (wcstol)(const wchar_t *, wchar_t **, int); -size_t (wcstombs)(char *s, const wchar_t *pwcs, size_t n); -unsigned long (wcstoul)(const wchar_t *, wchar_t **, int); -int (wctob)(wint_t); -wchar_t *(wmemchr)(const wchar_t *, wchar_t, size_t); -int (wmemcmp)(const wchar_t *, const wchar_t *, size_t); -wchar_t *(wmemcpy)(wchar_t *, const wchar_t *, size_t); -wchar_t *(wmemmove)(wchar_t *, const wchar_t *, size_t); -wchar_t *(wmemset)(wchar_t *, wchar_t, size_t); -float (wcstof)(const wchar_t *, wchar_t **); -long double (wcstold)(const wchar_t *, wchar_t **); -long long (wcstoll)(const wchar_t *, wchar_t **, int); -unsigned long long (wcstoull)(const wchar_t *, wchar_t **, int); -int (wctomb)(char *s, wchar_t wchar); -wctrans_t (wctrans)(const char *charmap); -wctype_t (wctype)(const char *charclass); -ssize_t (write)(int fildes, const void *buf, size_t nbyte); - -#if 0 /* not yet implemented */ -/* PRINTFLIKE2 */ -int (fwprintf)(FILE *, const wchar_t *, ...); -/* SCANFLIKE2 */ -int (fwscanf)(FILE *, const wchar_t *, ...); -/* PRINTFLIKE3 */ -int (swprintf)(wchar_t *, size_t, const wchar_t *, ...); -/* SCANFLIKE3 */ -int (swscanf)(const wchar_t *, const wchar_t *, ...); -int (vfwprintf)(FILE *, const wchar_t *, va_list); -int (vfwscanf)(FILE *, const wchar_t *, va_list); -int (vswprintf)(wchar_t *, size_t, const wchar_t *, va_list); -int (vswscanf)(const wchar_t *, const wchar_t *, va_list); -int (vwprintf)(const wchar_t *, va_list); -int (vwscanf)(const wchar_t *, va_list); -int (wcscoll)(const wchar_t *, const wchar_t *); -size_t (wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *); -int (wcswidth)(const wchar_t *, size_t); -size_t (wcsxfrm)(wchar_t *, const wchar_t *, size_t); -int (wcwidth)(wchar_t); -/* PRINTFLIKE1 */ -int (wprintf)(const wchar_t *, ...); -/* SCANFLIKE1 */ -int (wscanf)(const wchar_t *, ...); -#endif - diff --git a/usr.bin/xlint/llib/llib-lstdc b/usr.bin/xlint/llib/llib-lstdc deleted file mode 100644 index c1f19e8daeb..00000000000 --- a/usr.bin/xlint/llib/llib-lstdc +++ /dev/null @@ -1,254 +0,0 @@ -/* $OpenBSD: llib-lstdc,v 1.4 2002/12/11 23:01:40 millert Exp $ */ -/* $NetBSD: llib-lstdc,v 1.3 1995/07/03 21:39:28 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* LINTLIBRARY */ - -#define _ANSI_SOURCE -#define _ANSI_LIBRARY - -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <locale.h> -#include <math.h> -#include <setjmp.h> -#include <signal.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -/* PROTOLIB1 */ - -/* - * assert.h - */ -#if defined(__NetBSD__) || defined(__OpenBSD__) -void (__assert)(const char *expression, int line, const char *file); -#else -void (assert)(int expression); -#endif - -/* - * ctype.h - */ -int (isalnum)(int c); -int (isalpha)(int c); -int (iscntrl)(int c); -int (isdigit)(int c); -int (isgraph)(int c); -int (islower)(int c); -int (isprint)(int c); -int (ispunct)(int c); -int (isspace)(int c); -int (isupper)(int c); -int (isxdigit)(int c); -int (tolower)(int c); -int (toupper)(int c); - -/* - * errno.h - */ -int (errno); - -/* - * locale.h - */ -char *(setlocale)(int category, const char *locale); -struct lconv *(localeconv)(void); - -/* - * math.h - */ -double (acos)(double x); -double (asin)(double x); -double (atan)(double x); -double (atan2)(double y, double x); -double (cos)(double x); -double (sin)(double x); -double (tan)(double x); -double (cosh)(double x); -double (sinh)(double x); -double (tanh)(double x); -double (exp)(double x); -double (frexp)(double value, int *exp); -double (ldexp)(double x, int exp); -double (log)(double x); -double (log10)(double x); -double (modf)(double value, double *iptr); -double (pow)(double x, double y); -double (sqrt)(double x); -double (ceil)(double x); -double (fabs)(double x); -double (floor)(double x); -double (fmod)(double x, double y); - -/* - * setjmp.h - */ -int (setjmp)(jmp_buf env); -void (longjmp)(jmp_buf env, int val); - -/* - * signal.h - */ -void (*(signal)(int sig, void (*func)(int)))(int); -int (raise)(int sig); - -/* - * stdio.h - */ -int (remove)(const char *filename); -int (rename)(const char *old, const char *new); -FILE *(tmpfile)(void); -char *(tmpnam)(char *s); -int (fclose)(FILE *stream); -int (fflush)(FILE *stream); -FILE *(fopen)(const char *filename, const char *mode); -FILE *(freopen)(const char *filename, const char *mode, FILE *stream); -void (setbuf)(FILE *stream, char *buf); -int (setvbuf)(FILE *stream, char *buf, int mode, size_t size); -/* PRINTFLIKE2 */ -int (fprintf)(FILE *stream, const char *format, ...); -/* SCANFLIKE2 */ -int (fscanf)(FILE *stream, const char *format, ...); -/* PRINTFLIKE1 */ -int (printf)(const char *format, ...); -/* SCANFLIKE1 */ -int (scanf)(const char *format, ...); -/* PRINTFLIKE2 */ -int (sprintf)(char *s, const char *format, ...); -/* SCANFLIKE2 */ -int (sscanf)(const char *s, const char *format, ...); -int (vfprintf)(FILE *stream, const char *format, va_list arg); -int (vprintf)(const char *format, va_list arg); -int (vsprintf)(char *s, const char *format, va_list arg); -int (fgetc)(FILE *stream); -char *(fgets)(char *s, int n, FILE *stream); -int (fputc)(int c, FILE *stream); -int (fputs)(const char *s, FILE *stream); -int (getc)(FILE *stream); -int (getchar)(void); -char *(gets)(char *s); -int (putc)(int c, FILE *stream); -int (putchar)(int c); -int (puts)(const char *s); -int (ungetc)(int c, FILE *stream); -size_t (fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); -size_t (fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream); -int (fgetpos)(FILE *stream, fpos_t *pos); -int (fseek)(FILE *stream, long offset, int whence); -int (fsetpos)(FILE *stream, const fpos_t *pos); -long (ftell)(FILE *stream); -void (rewind)(FILE *stream); -void (clearerr)(FILE *stream); -int (feof)(FILE *stream); -int (ferror)(FILE *stream); -void (perror)(const char *s); - -/* - * stdlib.h - */ -double (atof)(const char *nptr); -int (atoi)(const char *nptr); -long (atol)(const char *nptr); -double (strtod)(const char *nptr, char **endptr); -long (strtol)(const char *nptr, char **endptr, int base); -unsigned long (strtoul)(const char *nptr, char **endptr, int base); -int (rand)(void); -void (srand)(unsigned seed); -void *(calloc)(size_t nmemb, size_t size); -void (free)(void *ptr); -void *(malloc)(size_t size); -void *(realloc)(void *ptr, size_t size); -void (abort)(void); -int (atexit)(void (*func)(void)); -void (exit)(int status); -char *(getenv)(const char *name); -int (system)(const char *string); -void *(bsearch)(const void *key, const void *base, size_t nmemb, - size_t size, int (*compar)(const void *, const void *)); -void (qsort)(void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *)); -int (abs)(int j); -div_t (div)(int numer, int denom); -long (labs)(long j); -ldiv_t (ldiv)(long numer, long denom); -int (mblen)(const char *s, size_t n); -int (mbtowc)(wchar_t *PWC, const char *s, size_t n); -int (wctomb)(char *s, wchar_t wchar); -size_t (mbstowcs)(wchar_t *pwcs, const char *s, size_t n); -size_t (wcstombs)(char *s, const wchar_t *pwcs, size_t n); - -/* - * string.h - */ -void *(memcpy)(void *s1, const void *s2, size_t n); -void *(memmove)(void *s1, const void *s2, size_t n); -char *(strcpy)(char *s1, const char *s2); -char *(strncpy)(char *s1, const char *s2, size_t n); -char *(strcat)(char *s1, const char *s2); -char *(strncat)(char *s1, const char *s2, size_t n); -int (memcmp)(const void *s1, const void *s2, size_t n); -int (strcmp)(const char *s1, const char *s2); -int (strcoll)(const char *s1, const char *s2); -int (strncmp)(const char *s1, const char *s2, size_t n); -size_t (strxfrm)(char *s1, const char *s2, size_t n); -void *(memchr)(const void *s, int c, size_t n); -char *(strchr)(const char *s, int c); -size_t (strcspn)(const char *s1, const char *s2); -char *(strpbrk)(const char *s1, const char *s2); -char *(strrchr)(const char *s1, int c); -size_t (strspn)(const char *s1, const char *s2); -char *(strstr)(const char *s1, const char *s2); -char *(strtok)(char *s1, const char *s2); -void *(memset)(void *s, int c, size_t n); -char *(strerror)(int errnom); -size_t (strlen)(const char *s); - -/* - * time.h - */ -clock_t (clock)(void); -double (difftime)(time_t time1, time_t time2); -time_t (mktime)(struct tm *timeptr); -time_t (time)(time_t *timer); -char *(asctime)(const struct tm *timeptr); -char *(ctime)(const time_t *timer); -struct tm *(gmtime)(const time_t *timer); -struct tm *(localtime)(const time_t *timer); -size_t (strftime)(char *s, size_t maxsize, const char *format, - const struct tm *timeptr); diff --git a/usr.bin/xlint/xlint/Makefile b/usr.bin/xlint/xlint/Makefile deleted file mode 100644 index ce5334a8842..00000000000 --- a/usr.bin/xlint/xlint/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $OpenBSD: Makefile,v 1.5 2011/11/08 10:37:10 guenther Exp $ -# $NetBSD: Makefile,v 1.2 1995/07/03 21:25:14 cgd Exp $ - -.PATH: ${.CURDIR}/../lint1 - -PROG= xlint -SRCS= xlint.c mem.c -MAN= lint.1 - -CFLAGS+=-I${.CURDIR}/../lint1 - -realinstall: - ${INSTALL} ${INSTALL_COPY} -S ${INSTALL_STRIP} \ - -o ${BINOWN} -g ${BINGRP} \ - -m ${BINMODE} ${PROG} ${DESTDIR}${BINDIR}/lint - - -.include "${.CURDIR}/../../Makefile.inc" -.include <bsd.prog.mk> diff --git a/usr.bin/xlint/xlint/lint.1 b/usr.bin/xlint/xlint/lint.1 deleted file mode 100644 index 8e9fd24a008..00000000000 --- a/usr.bin/xlint/xlint/lint.1 +++ /dev/null @@ -1,513 +0,0 @@ -.\" $OpenBSD: lint.1,v 1.27 2011/06/09 15:19:03 jsg Exp $ -.\" $NetBSD: lint.1,v 1.3 1995/10/23 13:45:31 jpo Exp $ -.\" -.\" Copyright (c) 1994, 1995 Jochen Pohl -.\" All Rights Reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Jochen Pohl for -.\" The NetBSD Project. -.\" 4. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd $Mdocdate: June 9 2011 $ -.Dt LINT 1 -.Os -.Sh NAME -.Nm lint -.Nd a C program verifier -.Sh SYNOPSIS -.Nm lint -.Op Fl ceFfgHhprsVvxz -.Op Fl i | nu -.Op Fl D Ns Ar name Ns Op =def -.Op Fl I Ns Ar directory -.Op Fl L Ns Ar directory -.Op Fl l Ns Ar library -.Op Fl MD -.Op Fl o Ns Ar outputfile -.Op Fl U Ns Ar name -.Ar -.Nm lint -.Op Fl ceFfgHhprsVvz -.Fl C Ns Ar library -.Op Fl D Ns Ar name Ns Op =def -.Op Fl I Ns Ar directory -.Op Fl MD -.Op Fl U Ns Ar name -.Ar -.Sh DESCRIPTION -.Nm -attempts to detect features of the named C program files -that are likely to be bugs, non-portable, or wasteful. -It also performs stricter type checking than the C compiler. -.Nm -runs the C preprocessor as its first phase, with the -preprocessor symbol -.Sy lint -defined to allow certain questionable code to be altered -or skipped by -.Nm lint . -Therefore, this symbol should be thought of as a reserved -word for all code that is to be checked by -.Nm lint . -.Pp -Among the possible problems that are currently noted are -unreachable statements, loops not entered at the top, -variables declared and not used, and logical expressions -with constant values. -Function calls are checked for inconsistencies, such as -calls to functions that return values in some places and -not in others, functions called with varying numbers of -arguments, function calls that pass arguments of a type -other than the type the function expects to receive, -functions whose values are not used, and calls to functions -not returning values that use the non-existent return value -of the function. -.Pp -Filename arguments ending with -.Pa \&.c -are taken to be C source files. -Filename arguments with names ending with -.Pa \&.ln -are taken to be the result of an earlier invocation of -.Nm lint , -with either the -.Fl i , -.Fl o , -or -.Fl C -option in effect. -The -.Pa \&.ln -files are analogous to the -.Pa \&.o -(object) files produced by -.Xr cc 1 -from -.Pa \&.c -files. -.Nm -also accepts special libraries specified with the -.Fl l -option, which contain definitions of library routines and -variables. -.Pp -.Nm -takes all the -.Pa \&.c , \&.ln , -and -.Pa llib-l Ns Ar library Ns Pa \&.ln -(lint library) files and processes them in command-line order. -By default, -.Nm -appends the standard C lint library -.Pq Pa llib-lc.ln , -if it exists, -to the end of the list of files. -When the -.Fl i -option is used, the -.Pa \&.ln -files are ignored. -Also, when the -.Fl o -or -.Fl i -options are used, the -.Pa llib-l Ns Ar library Ns Pa \&.ln -files are ignored. -When the -.Fl i -option is -.Em omitted -the second pass of -.Nm -checks this list of files for mutual compatibility. -At this point, if a complaint stems not from a given source -file, but from one of its included files, the source filename -will be printed followed by a question mark. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl C Ns Ar library -Create a -.Nm -library with the name -.Pa llib-l Ns Ar library Ns Pa .ln . -This library is built from all -.Pa \&.c -and -.Pa \&.ln -input files. -After all global definitions of functions and -variables in these files are written to the newly created library, -.Nm -checks all input files, including libraries specified with the -.Fl l -option, for mutual compatibility. -.It Fl c -Complain about casts which have questionable portability. -.It Fl D Ns Ar name Ns Op =def -Define -.Ar name -for -.Xr cpp 1 , -as if by a -.Li #define -directive. -If no definition is given, -.Ar name -is defined as 1. -.It Fl e -Complain about unusual operations on -.Sy enum Ns -Types -and combinations of -.Sy enum Ns - -and -.Sy integer Ns -Types. -.It Fl F -Print pathnames of files. -.Nm -normally prints the filename without the path. -.It Fl f -For each warning or error, print the offending line of the -corresponding source code file. -.It Fl g -Don't print warnings for some extensions of -.Xr gcc 1 -to the C language. -Currently these are nonconstant initializers in -automatic aggregate initializations, arithmetic on pointer to void, -zero sized structures, subscripting of non-lvalue arrays, prototypes -overriding old style function declarations and long long -integer types. -The -.Fl g -flag also turns on the keywords -.Sy asm -and -.Sy inline -(alternate keywords with leading underscores for both -.Sy asm -and -.Sy inline -are always available). -.It Fl H -If a complaint stems from an included file -.Nm -prints the name of the included file instead of the source file name -followed by a question mark. -.It Fl h -Apply a number of heuristic tests to attempt to intuit -bugs, improve style, and reduce waste. -.It Fl I Ns Ar directory -Add -.Ar directory -to the list of directories in which to search for include files. -.It Fl i -Produce a -.Pa \&.ln -file for every -.Pa \&.c -file on the command line. -These -.Pa \&.ln -files are the product of -.Nm lint Ns 's -first pass only, and are not checked for compatibility -between functions. -.It Fl L Ns Ar directory -Search for lint libraries in -.Ar directory -and -.Ar directory Ns Pa /lint -before searching the standard place. -.It Fl l Ns Ar library -Include the lint library -.Pa llib-l Ns Ar library Ns Pa \&.ln . -.It Fl MD -Ignored, so the same flags can be passed to -.Nm lint -and -.Xr cpp 1 . -.It Fl n -Do not check compatibility against the standard library. -.It Fl o Ns Ar outputfile -Name the output file -.Ar outputfile . -The output file produced is the input that is given to -.Nm lint Ns 's -second pass. -The -.Fl o -option simply saves this file in the named output file. -If the -.Fl i -option is also used the files are not checked for compatibility. -To produce a -.Pa llib-l Ns Ar library Ns Pa \&.ln -without extraneous messages, use of the -.Fl u -option is suggested. -The -.Fl v -option is useful if the source file(s) for the lint library -are just external interfaces. -.It Fl p -Attempt to check portability of code to other dialects of C. -.It Fl r -In case of redeclarations report the position of the -previous declaration. -.It Fl s -Strict ANSI C mode. -Issue warnings and errors required by ANSI C. -Also do not produce warnings for constructs which behave -differently in traditional C and ANSI C. -With the -.Fl s -flag, -.Li __STRICT_ANSI__ -is a predefined preprocessor macro. -.It Fl U Ns Ar name -Remove any initial definition of -.Ar name -for the preprocessor. -.It Fl u -Do not complain about functions and external variables used -and not defined, or defined and not used (this is suitable -for running -.Nm -on a subset of files comprising part of a larger program). -.It Fl V -Print the command lines constructed by the controller program to -run the C preprocessor and -.Nm lint Ns 's -first and second pass. -.It Fl v -Suppress complaints about unused arguments in functions. -.It Fl x -Report variables referred to by -.Sy extern -declarations, but never used. -.It Fl z -Do not complain about structures that are never defined -(for example, using a structure pointer without knowing -its contents). -.El -.Pp -.Sy Input Grammar -.Pp -.Nm lint Ns 's -first pass reads standard C source files. -.Nm -recognizes the following C comments as commands. -.Bl -tag -width Fl -.It Li /* ARGSUSED Ns Ar n Li */ -Make -.Nm -check only the first -.Ar n -arguments for usage; a missing -.Ar n -is taken to be 0 (this option acts like the -.Fl v -option for the next function). -.It Li /* CONSTCOND */ No or Xo -.Li /* CONSTANTCOND */ No or -.Li /* CONSTANTCONDITION */ -.Xc -Suppress complaints about constant operands for the next expression. -.It Li /*\ FALLTHRU\ */ No or Xo -.Li /* FALLTHROUGH */ -.Xc -Suppress complaints about fall through to a -.Sy case -or -.Sy default -labelled statement. -This directive should be placed immediately preceding the label. -.It Li /* LINTLIBRARY */ -At the beginning of a file, mark all functions and variables defined -in this file as -.Em used . -Also shut off complaints about unused function arguments. -.It Li /* LINTED Xo -.Op Ar comment -.Li */ No or -.Li /* NOSTRICT -.Op Ar comment -.Li */ -.Xc -Suppress any intra-file warning except those dealing with -unused variables or functions. -This directive should be placed on the line immediately -preceding where the -.Nm -warning occurred. -.It Li /* LONGLONG */ -Suppress complaints about use of long long integer types. -.It Li /* NORETURN */ -Tell -.Nm -that the function will never return, which means any code -following a call to this function is unreachable. -This directive should be placed immediately preceding the function. -.It Li /* NOTREACHED */ -At appropriate points, inhibit complaints about unreachable code. -This comment is typically placed just after calls to functions -like -.Xr exit 3 . -.It Li /* PRINTFLIKE Ns Ar n Li */ -Make -.Nm -check the first -.Pq Ar n Ns -1 -arguments as usual. -The -.Ar n Ns -th -argument is interpreted as a -.Sy printf -format string that is used to check the remaining arguments. -.It Li /* PROTOLIB Ns Ar n Li */ -Cause -.Nm -to treat function declaration prototypes as function definitions -if -.Ar n -is non-zero. -This directive can only be used in conjunction with the -.Li /* LINTLIBRARY */ -directive. -If -.Ar n -is zero, function prototypes will be treated normally. -.It Li /* SCANFLIKE Ns Ar n Li */ -Make -.Nm -check the first -.Pq Ar n Ns -1 -arguments as usual. -The -.Ar n Ns -th -argument is interpreted as a -.Sy scanf -format string that is used to check the remaining arguments. -.It Li /* VARARGS Ns Ar n Li */ -Suppress the usual checking for variable numbers of arguments in -the following function declaration. -The data types of the first -.Ar n -arguments are checked; a missing -.Ar n -is taken to be 0. -.El -.Pp -The behavior of the -.Fl i -and the -.Fl o -options allows for incremental use of -.Nm -on a set of C source files. -Generally, one invokes -.Nm -once for each source file with the -.Fl i -option. -Each of these invocations produces a -.Pa \&.ln -file that corresponds to the -.Pa \&.c -file, and prints all messages that are about just that -source file. -After all the source files have been separately run through -.Nm lint , -it is invoked once more (without the -.Fl i -option), listing all the -.Pa \&.ln -files with the needed -.Fl l Ns Ar library -options. -This will print all the inter-file inconsistencies. -This scheme works well with -.Xr make 1 ; -it allows -.Xr make 1 -to be used to -.Nm -only the source files that have been modified since the last -time the set of source files were -.Nm lint Ns ed . -.Sh ENVIRONMENT -.Bl -tag -width Fl -.It Ev LIBDIR -the directory where the lint libraries specified by the -.Fl l Ns Ar library -option must exist. -If this environment variable is undefined, then the default path -.Pa /usr/libdata/lint -will be used to search for the libraries. -.It Ev TMPDIR -usually the path for temporary files can be redefined by setting -this environment variable. -.El -.Sh FILES -.Bl -tag -width /usr/libdata/lint/llib-lposix.ln -compact -.It Pa /usr/libexec/lint Ns Bq 12 -programs -.It Pa /usr/libdata/lint/llib-lposix.ln -prebuilt POSIX C lint library -.It Pa /usr/libdata/lint/llib-lstdc.ln -prebuilt ANSI/ISO C lint library -.It Pa /tmp/lint* -temporaries -.El -.Sh SEE ALSO -.Xr cc 1 , -.Xr cpp 1 , -.Xr make 1 -.Sh AUTHORS -Jochen Pohl -.Sh BUGS -The routines -.Xr exit 3 , -.Xr longjmp 3 -and other functions that do not return are not understood; this -causes various incorrect diagnostics. -.Pp -Static functions which are used only before their first -extern declaration are reported as unused. -.Pp -Libraries created by the -.Fl o -option will, when used in later -.Nm -runs, cause certain errors that were reported when the libraries -were created to be reported again, and cause line numbers and file -names from the original source used to create those libraries -to be reported in error messages. -For these reasons, it is recommended to use the -.Fl C -option to create lint libraries. diff --git a/usr.bin/xlint/xlint/pathnames.h b/usr.bin/xlint/xlint/pathnames.h deleted file mode 100644 index fdb64a50345..00000000000 --- a/usr.bin/xlint/xlint/pathnames.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: pathnames.h,v 1.2 1996/06/26 05:44:31 deraadt Exp $ */ -/* $NetBSD: pathnames.h,v 1.2 1995/07/03 21:25:20 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* directory where lint1 and lint2 reside */ -#define PATH_LIBEXEC "/usr/libexec" - -/* default library search path */ -#define PATH_LINTLIB "/usr/libdata/lint" diff --git a/usr.bin/xlint/xlint/xlint.c b/usr.bin/xlint/xlint/xlint.c deleted file mode 100644 index 2b6d588f72e..00000000000 --- a/usr.bin/xlint/xlint/xlint.c +++ /dev/null @@ -1,763 +0,0 @@ -/* $OpenBSD: xlint.c,v 1.36 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: xlint.c,v 1.3 1995/10/23 14:29:30 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <err.h> -#include <errno.h> -#include <paths.h> - -#include "lint.h" -#include "pathnames.h" - -/* directory for temporary files */ -static const char *tmpdir; - -/* path name for cpp output */ -static char *cppout; - -/* files created by 1st pass */ -static char **p1out; - -/* input files for 2nd pass (without libraries) */ -static char **p2in; - -/* library which will be created by 2nd pass */ -static char *p2out; - -/* flags always passed to cpp */ -static char **cppflags; - -/* flags for cpp, controled by sflag/tflag */ -static char **lcppflgs; - -/* flags for lint1 */ -static char **l1flags; - -/* flags for lint2 */ -static char **l2flags; - -/* libraries for lint2 */ -static char **l2libs; - -/* default libraries */ -static char **deflibs; - -/* additional libraries */ -static char **libs; - -/* search path for libraries */ -static char **libsrchpath; - -/* flags */ -static int iflag, oflag, Cflag, sflag, tflag, Fflag = 1; - -/* print the commands executed to run the stages of compilation */ -static int Vflag; - -/* filename for oflag */ -static char *outputfn; - -/* reset after first .c source has been processed */ -static int first = 1; - -/* - * name of a file which is currently written by a child and should - * be removed after abnormal termination of the child - */ -static const char *currfn; - -static void appstrg(char ***, char *); -static void appcstrg(char ***, const char *); -static void applst(char ***, char *const *); -static void freelst(char ***); -static char *concat2(const char *, const char *); -static char *concat3(const char *, const char *, const char *); -static void terminate(int); -static const char *lbasename(const char *, int); -static void appdef(char ***, const char *); -static void usage(void); -static void fname(const char *); -static int runchild(const char *, char *const *, const char *); -static void findlibs(char *const *); -static int rdok(const char *); -static void lint2(void); -static void cat(char *const *, const char *); - -/* - * Some functions to deal with lists of strings. - * Take care that we get no surprises in case of asynchronous signals. - */ -static void -appstrg(char ***lstp, char *s) -{ - char **lst, **olst; - int i; - - olst = *lstp; - for (i = 0; olst[i] != NULL; i++) ; - lst = xmalloc((i + 2) * sizeof (char *)); - (void)memcpy(lst, olst, i * sizeof (char *)); - lst[i] = s; - lst[i + 1] = NULL; - *lstp = lst; -} - -static void -appcstrg(char ***lstp, const char *s) -{ - appstrg(lstp, xstrdup(s)); -} - -static void -applst(char ***destp, char *const *src) -{ - int i, k; - char **dest, **odest; - - odest = *destp; - for (i = 0; odest[i] != NULL; i++) ; - for (k = 0; src[k] != NULL; k++) ; - dest = xmalloc((i + k + 1) * sizeof (char *)); - (void)memcpy(dest, odest, i * sizeof (char *)); - for (k = 0; src[k] != NULL; k++) - dest[i + k] = xstrdup(src[k]); - dest[i + k] = NULL; - *destp = dest; - free(odest); -} - -static void -freelst(char ***lstp) -{ - char *s; - int i; - - for (i = 0; (*lstp)[i] != NULL; i++) ; - while (i-- > 0) { - s = (*lstp)[i]; - (*lstp)[i] = NULL; - free(s); - } -} - -static char * -concat2(const char *s1, const char *s2) -{ - char *s; - size_t len = strlen(s1) + strlen(s2) + 1; - - s = xmalloc(len); - (void)strlcpy(s, s1, len); - (void)strlcat(s, s2, len); - - return (s); -} - -static char * -concat3(const char *s1, const char *s2, const char *s3) -{ - char *s; - size_t len = strlen(s1) + strlen(s2) + strlen(s3) + 1; - - s = xmalloc(len); - (void)strlcpy(s, s1, len); - (void)strlcat(s, s2, len); - (void)strlcat(s, s3, len); - - return (s); -} - -/* - * Clean up after a signal. - */ -static void -terminate(int signo) -{ - int i; - - if (cppout != NULL) - (void)remove(cppout); - - if (p1out != NULL) { - for (i = 0; p1out[i] != NULL; i++) - (void)remove(p1out[i]); - } - - if (p2out != NULL) - (void)remove(p2out); - - if (currfn != NULL) - (void)remove(currfn); - - _exit(signo != 0 ? 1 : 0); -} - -/* - * Returns a pointer to the last component of strg after delim. - * Returns strg if the string does not contain delim. - */ -static const char * -lbasename(const char *strg, int delim) -{ - const char *cp, *cp1, *cp2; - - cp = cp1 = cp2 = strg; - while (*cp != '\0') { - if (*cp++ == delim) { - cp2 = cp1; - cp1 = cp; - } - } - return (*cp1 == '\0' ? cp2 : cp1); -} - -static void -appdef(char ***lstp, const char *def) -{ - appstrg(lstp, concat2("-D__", def)); - appstrg(lstp, concat3("-D__", def, "__")); -} - -static void -usage() -{ - (void)printf("usage: lint [-ceFfgHhprsVvxz] [-i | -nu] [-Dname[=def]] [-Idirectory]\n"); - (void)printf("\t[-Ldirectory] [-llibrary] [-ooutputfile] [-MD] [-Uname] file ...\n"); - (void)printf(" lint [-ceFfgHhprsVvz] -Clibrary [-Dname[=def]]\n"); - (void)printf("\t[-Idirectory] [-MD] [-Uname] file ...\n"); - terminate(-1); -} - -int -main(int argc, char *argv[]) -{ - int c; - int fd; - char flgbuf[3], *tmp, *s; - size_t len; - struct utsname un; - - if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) { - tmpdir = xstrdup(_PATH_TMP); - } else { - s = xmalloc(len + 2); - (void)snprintf(s, len + 2, "%s%s", - tmp, tmp[len - 1] == '/' ? "" : "/"); - tmpdir = s; - } - - if (asprintf(&cppout, "%slint0.XXXXXXXXXX", tmpdir) == -1) - err(1, NULL); - if ((fd = mkstemp(cppout)) == -1) { - warn("can't make temp"); - terminate(-1); - } - close(fd); - - p1out = xcalloc(1, sizeof (char *)); - p2in = xcalloc(1, sizeof (char *)); - cppflags = xcalloc(1, sizeof (char *)); - lcppflgs = xcalloc(1, sizeof (char *)); - l1flags = xcalloc(1, sizeof (char *)); - l2flags = xcalloc(1, sizeof (char *)); - l2libs = xcalloc(1, sizeof (char *)); - deflibs = xcalloc(1, sizeof (char *)); - libs = xcalloc(1, sizeof (char *)); - libsrchpath = xcalloc(1, sizeof (char *)); - - appcstrg(&cppflags, "-x"); - appcstrg(&cppflags, "c"); - appcstrg(&cppflags, "-undef"); - /* even with -undef cpp still identifies as GNUC */ - appcstrg(&cppflags, "-U__GNUC__"); -#if defined(__GNUC__) -#if __GNUC__ < 3 - appcstrg(&cppflags, "-$"); - appcstrg(&cppflags, "-C"); -#else - appcstrg(&cppflags, "-CC"); -#endif -#endif - appcstrg(&cppflags, "-Wcomment"); - appcstrg(&cppflags, "-D__OpenBSD__"); - appcstrg(&cppflags, "-Dlint"); /* XXX don't def. with -s */ - appdef(&cppflags, "lint"); - appdef(&cppflags, "unix"); - - if (uname(&un) == -1) - err(1, "uname"); - appdef(&cppflags, un.machine); - appstrg(&lcppflgs, concat2("-D", un.machine)); - -#ifdef MACHINE_ARCH -#ifdef MACHINE_CPU - if (strcmp(MACHINE_ARCH, MACHINE_CPU) != 0) { - appdef(&cppflags, MACHINE_CPU); - appstrg(&lcppflgs, concat2("-D", MACHINE_CPU)); - } -#endif - if (strcmp(un.machine, MACHINE_ARCH) != 0) { - appdef(&cppflags, MACHINE_ARCH); - appstrg(&lcppflgs, concat2("-D", MACHINE_ARCH)); - } -#endif - - appcstrg(&deflibs, "c"); - - if (signal(SIGHUP, terminate) == SIG_IGN) - (void)signal(SIGHUP, SIG_IGN); - (void)signal(SIGINT, terminate); - (void)signal(SIGQUIT, terminate); - (void)signal(SIGTERM, terminate); - - while (argc > optind) { - c = getopt(argc, argv, "abcefghil:no:prstuvxyzC:D:FHI:L:M:U:V"); - - switch (c) { - - case 'a': - case 'b': - case 'c': - case 'e': - case 'f': - case 'g': - case 'r': - case 'v': - case 'y': - case 'z': - (void)snprintf(flgbuf, sizeof flgbuf, "-%c", c); - appcstrg(&l1flags, flgbuf); - break; - - case 'F': - Fflag = 1; - /* FALLTHROUGH */ - case 'u': - case 'h': - (void)snprintf(flgbuf, sizeof flgbuf, "-%c", c); - appcstrg(&l1flags, flgbuf); - appcstrg(&l2flags, flgbuf); - break; - - case 'i': - if (Cflag) - usage(); - iflag = 1; - break; - - case 'n': - freelst(&deflibs); - break; - - case 'p': - appcstrg(&l1flags, "-p"); - appcstrg(&l2flags, "-p"); - if (*deflibs != NULL) { - freelst(&deflibs); - appcstrg(&deflibs, "c"); - } - break; - - case 's': - if (tflag) - usage(); - freelst(&lcppflgs); - appcstrg(&lcppflgs, "-trigraphs"); - appcstrg(&lcppflgs, "-Wtrigraphs"); - appcstrg(&lcppflgs, "-pedantic"); - appcstrg(&lcppflgs, "-D__STRICT_ANSI__"); - appcstrg(&l1flags, "-s"); - appcstrg(&l2flags, "-s"); - sflag = 1; - break; - - case 't': - if (sflag) - usage(); - freelst(&lcppflgs); - appcstrg(&lcppflgs, "-traditional"); - appstrg(&lcppflgs, concat2("-D", MACHINE)); - appstrg(&lcppflgs, concat2("-D", MACHINE_ARCH)); - appcstrg(&l1flags, "-t"); - appcstrg(&l2flags, "-t"); - tflag = 1; - break; - - case 'x': - appcstrg(&l2flags, "-x"); - break; - - case 'C': - if (Cflag || oflag || iflag) - usage(); - Cflag = 1; - appstrg(&l2flags, concat2("-C", optarg)); - if (asprintf(&p2out, "llib-l%s.ln", optarg) == -1) - err(1, NULL); - freelst(&deflibs); - break; - - case 'D': - case 'I': - case 'U': - (void)snprintf(flgbuf, sizeof flgbuf, "-%c", c); - appstrg(&cppflags, concat2(flgbuf, optarg)); - break; - - case 'l': - appcstrg(&libs, optarg); - break; - - case 'o': - if (Cflag || oflag) - usage(); - oflag = 1; - outputfn = xstrdup(optarg); - break; - - case 'L': - appcstrg(&libsrchpath, optarg); - break; - - case 'M': - break; - - case 'H': - appcstrg(&l2flags, "-H"); - break; - - case 'V': - Vflag = 1; - break; - - case '?': - usage(); - /* NOTREACHED */ - - case -1: - /* filename */ - if (argv[optind] == NULL) - break; - fname(argv[optind++]); - first = 0; - } - - } - argc -= optind; - argv += optind; - - if (first) - usage(); - - if (iflag) - terminate(0); - - if (!oflag) { - if ((s = getenv("LIBDIR")) == NULL || strlen(s) == 0) - s = PATH_LINTLIB; - appcstrg(&libsrchpath, s); - findlibs(libs); - findlibs(deflibs); - } - - (void)printf("Lint pass2:\n"); - lint2(); - - if (oflag) - cat(p2in, outputfn); - - if (Cflag) - p2out = NULL; - - terminate(0); - /* NOTREACHED */ -} - -/* - * Read a file name from the command line - * and pass it through lint1 if it is a C source. - */ -static void -fname(const char *name) -{ - const char *bn, *suff; - char **args, *ofn, *path; - size_t len; - int error; - int fd; - - bn = lbasename(name, '/'); - suff = lbasename(bn, '.'); - - if (strcmp(suff, "ln") == 0) { - /* only for lint2 */ - if (!iflag) - appcstrg(&p2in, name); - return; - } - - if (strcmp(suff, "c") != 0 && - (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) { - warnx("unknown file type: %s", name); - return; - } - - /* build the name of the output file of lint1 */ - if (oflag) { - ofn = outputfn; - outputfn = NULL; - oflag = 0; - } else if (iflag) { - len = strlen(bn) + (bn == suff ? 4 : 2); - ofn = xmalloc(len); - (void)snprintf(ofn, len, "%.*s", - bn == suff ? strlen(bn) : (suff - 1) - bn, bn); - (void)strlcat(ofn, ".ln", len); - } else { - if (asprintf(&ofn, "%slint1.XXXXXXXXXX", tmpdir) == -1) - err(1, NULL); - if ((fd = mkstemp(ofn)) == -1) { - warn("can't make temp"); - terminate(-1); - } - close(fd); - } - if (!iflag) - appcstrg(&p1out, ofn); - - args = xcalloc(1, sizeof (char *)); - - /* run cpp */ - - if (asprintf(&path, "%s/cpp", PATH_LIBEXEC) == -1) - err(1, NULL); - - appcstrg(&args, path); - applst(&args, cppflags); - applst(&args, lcppflgs); - appcstrg(&args, name); - appcstrg(&args, cppout); - - error = runchild(path, args, cppout); - free(path); - freelst(&args); - if (error) - return; - - /* run lint1 */ - - if (asprintf(&path, "%s/lint1", PATH_LIBEXEC) == -1) - err(1, NULL); - - appcstrg(&args, path); - applst(&args, l1flags); - appcstrg(&args, cppout); - appcstrg(&args, ofn); - - error = runchild(path, args, ofn); - free(path); - freelst(&args); - if (error) - return; - - appcstrg(&p2in, ofn); - free(ofn); - - free(args); -} - -static int -runchild(const char *path, char *const *args, const char *crfn) -{ - int status, signo, i; - pid_t rv; - - if (Vflag) { - for (i = 0; args[i] != NULL; i++) - (void)printf("%s ", args[i]); - (void)printf("\n"); - } - - currfn = crfn; - - (void)fflush(stdout); - - switch (fork()) { - case -1: - warn("cannot fork"); - terminate(-1); - /* NOTREACHED */ - default: - /* parent */ - break; - case 0: - /* child */ - (void)execv(path, args); - warn("cannot exec %s", path); - exit(1); - /* NOTREACHED */ - } - currfn = NULL; - - while ((rv = wait(&status)) == -1 && errno == EINTR) ; - if (rv == -1) { - warn("wait"); - return(-1); - } - if (WIFSIGNALED(status)) { - signo = WTERMSIG(status); - warnx("%s got SIG%s", path, sys_signame[signo]); - return(-1); - } - if (WEXITSTATUS(status) != 0) - return(-1); - return(0); -} - -static void -findlibs(char *const *liblst) -{ - int i, k; - const char *lib, *path; - char *lfn; - size_t len, l; - - lfn = NULL; - - for (i = 0; (lib = liblst[i]) != NULL; i++) { - for (k = 0; (path = libsrchpath[k]) != NULL; k++) { - len = strlen(path) + strlen(lib); - l = len + sizeof ("/llib-l.ln"); - lfn = xrealloc(lfn, l); - (void)snprintf(lfn, l, "%s/llib-l%s.ln", path, lib); - if (rdok(lfn)) - break; - l = len + sizeof ("/lint/llib-l.ln"); - lfn = xrealloc(lfn, l); - (void)snprintf(lfn, l, "%s/lint/llib-l%s.ln", path, lib); - if (rdok(lfn)) - break; - } - if (path != NULL) { - appstrg(&l2libs, concat2("-l", lfn)); - } else { - warnx("cannot find llib-l%s.ln", lib); - } - } - - free(lfn); -} - -static int -rdok(const char *path) -{ - struct stat sbuf; - - if (stat(path, &sbuf) == -1) - return (0); - if ((sbuf.st_mode & S_IFMT) != S_IFREG) - return (0); - if (access(path, R_OK) == -1) - return (0); - return (1); -} - -static void -lint2() -{ - char *path, **args; - - args = xcalloc(1, sizeof (char *)); - - if (asprintf(&path, "%s/lint2", PATH_LIBEXEC) == -1) - err(1, NULL); - - appcstrg(&args, path); - applst(&args, l2flags); - applst(&args, l2libs); - applst(&args, p2in); - - (void)runchild(path, args, p2out); - free(path); - freelst(&args); - free(args); -} - -static void -cat(char *const *srcs, const char *dest) -{ - int ifd, ofd, i; - char *src, *buf; - ssize_t rlen; - - if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { - warn("cannot open %s", dest); - terminate(-1); - } - - buf = xmalloc(MBLKSIZ); - - for (i = 0; (src = srcs[i]) != NULL; i++) { - if ((ifd = open(src, O_RDONLY)) == -1) { - free(buf); - warn("cannot open %s", src); - terminate(-1); - } - do { - if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) { - free(buf); - warn("read error on %s", src); - terminate(-1); - } - if (write(ofd, buf, (size_t)rlen) == -1) { - free(buf); - warn("write error on %s", dest); - terminate(-1); - } - } while (rlen == MBLKSIZ); - (void)close(ifd); - } - (void)close(ofd); - free(buf); -} - |