summaryrefslogtreecommitdiffstats
path: root/usr.bin/xlint/xlint
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1995-11-05 15:56:42 +0000
committerjoerg <joerg@FreeBSD.org>1995-11-05 15:56:42 +0000
commit97ea65b2cb83e7b5b2c4afcacc3a185482457c2a (patch)
treee48ecf34ec80fd6977218c2852e4419794cc64d7 /usr.bin/xlint/xlint
downloadFreeBSD-src-97ea65b2cb83e7b5b2c4afcacc3a185482457c2a.zip
FreeBSD-src-97ea65b2cb83e7b5b2c4afcacc3a185482457c2a.tar.gz
Jochen Pohl's lint(1) from NetBSD. Yet another import.
This is just a vendor import by now. I'll wait until i'll get the imported files back via CTM before applying the FreeBSD patches. Don't use it yet. Submitted by: Jochen Pohl <jpo.drs@sni.de> Obtained from: (NetBSD -- this version is directly from Jochen)
Diffstat (limited to 'usr.bin/xlint/xlint')
-rw-r--r--usr.bin/xlint/xlint/Makefile17
-rw-r--r--usr.bin/xlint/xlint/lint.1509
-rw-r--r--usr.bin/xlint/xlint/pathnames.h38
-rw-r--r--usr.bin/xlint/xlint/xlint.c761
4 files changed, 1325 insertions, 0 deletions
diff --git a/usr.bin/xlint/xlint/Makefile b/usr.bin/xlint/xlint/Makefile
new file mode 100644
index 0000000..41c833c
--- /dev/null
+++ b/usr.bin/xlint/xlint/Makefile
@@ -0,0 +1,17 @@
+# $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 ${COPY} ${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
new file mode 100644
index 0000000..99d459c
--- /dev/null
+++ b/usr.bin/xlint/xlint/lint.1
@@ -0,0 +1,509 @@
+.\" $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 August 28, 1994
+.Dt LINT 1
+.Os NetBSD
+.Sh NAME
+.Nm lint
+.Nd a C program verifier.
+.Sh SYNOPSIS
+.Nm lint
+.Op Fl abceghprvxzHFV
+.Op Fl s Ns | Ns Fl t
+.Op Fl i Ns | Ns Fl nu
+.Op Fl D Ns Ar name Ns Op =def
+.Op Fl U Ns Ar name
+.Op Fl I Ns Ar directory
+.Op Fl L Ns Ar directory
+.Op Fl l Ns Ar library
+.Op Fl o Ns Ar outputfile
+.Ar
+.Nm lint
+.Op Fl abceghprvzHFV
+.Op Fl s Ns | Ns Fl t
+.Fl C Ns Ar library
+.Op Fl D Ns Ar name Ns Op =def
+.Op Fl I Ns Ar directory
+.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, to be non-portable, or to be
+wasteful. It also performs stricter type checking then does
+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
+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
+.Sy Options
+.Bl -tag -width Fl
+.It Fl a
+Report assignments of
+.Sy long
+values to variables that are not
+.Sy long .
+.It Fl aa
+Additional to
+.Fl a ,
+report
+.Em all
+assignments of integer values to other integer values which
+cause implicit narrowing conversion.
+.It Fl b
+Report
+.Sy break
+statements that cannot be reached. This is not the default
+because, unfortunately, most
+.Xr lex 1
+and many
+.Xr yacc 1
+outputs produce many such complaints.
+.It Fl c
+Complain about casts which have questionable portability.
+.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 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
+Apply a number of heuristic tests to attempt to intuit
+bugs, improve style, and reduce waste.
+.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 n
+Do not check compatibility against the standard library.
+.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 t
+Traditional C mode.
+.Li __STDC__
+is not predefined in this mode. Warnings are printed for constructs
+not allowed in traditional C. Warnings for constructs which behave
+differently in traditional C and ANSI C are suppressed. Preprocessor
+macros describing the machine type (e.g.
+.Li sun3 Ns )
+and machine architecture (e.g.
+.Li m68k Ns )
+are defined without leading and trailing underscores. The keywords
+.Sy const Ns ,
+.Sy volatile
+and
+.Sy signed
+are not available in traditional C mode (although the alternate
+keywords with leading underscores still are).
+.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
+Suppress complaints about unused arguments in functions.
+.It Fl x
+Report variables refferd 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).
+.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 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 I Ns Ar directory
+Add
+.Ar directory
+to the list of directories in which to search for include files.
+.It Fl l Ns Ar library
+Include the lint library
+.Pa llib-l Ns Ar library Ns Pa \&.ln .
+.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 F
+Print pathnames of files.
+.Nm
+normally prints the filename without the path.
+.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 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 U Ns Ar name
+Remove any initial definition of
+.Ar name
+for the preprocessor.
+.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.
+.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 */
+makes
+.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
+Suppresses any intra-file warning except those dealing with
+unused variables or functions. This directive should be placed
+on the line immediately preceding where the lint warning occured.
+.It Li /* LONGLONG */
+Suppress complaints about use of long long integer types.
+.It Li /* NOTREACHED */
+At appropriate points, inhibit complaints about unreachable code.
+(This comment is typically placed just after calls to functions
+like
+.Xr exit 2 ).
+.It Li /* PRINTFLIKE Ns Ar n Li */
+makes
+.Nm
+check the first
+.Pq Ar n Ns No -1
+arguments as usual. The
+.Ar n Ns No -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 */
+causes
+.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 */
+makes
+.Nm
+check the first
+.Pq Ar n Ns No -1
+arguments as usual. The
+.Ar n Ns No -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 separetely
+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 No 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-lc.ln -compact
+.It Pa /usr/libexec/lint Ns Bq 12
+programs
+.It Pa /usr/libdata/lint/llib-l*.ln
+various prebuilt lint libraries
+.It Pa /tmp/lint*
+temporaries
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr cpp 1 ,
+.Xr make 1
+.Sh AUTHORS
+Jochen Pohl
+.Sh BUGS
+The routines
+.Xr exit 2 ,
+.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
new file mode 100644
index 0000000..d03845d
--- /dev/null
+++ b/usr.bin/xlint/xlint/pathnames.h
@@ -0,0 +1,38 @@
+/* $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
new file mode 100644
index 0000000..3e57797
--- /dev/null
+++ b/usr.bin/xlint/xlint/xlint.c
@@ -0,0 +1,761 @@
+/* $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.
+ */
+
+#ifndef lint
+static char rcsid[] = "$NetBSD: xlint.c,v 1.3 1995/10/23 14:29:30 jpo Exp $";
+#endif
+
+#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;
+
+/* 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 __P((char ***, char *));
+static void appcstrg __P((char ***, const char *));
+static void applst __P((char ***, char *const *));
+static void freelst __P((char ***));
+static char *concat2 __P((const char *, const char *));
+static char *concat3 __P((const char *, const char *, const char *));
+static void terminate __P((int));
+static const char *basename __P((const char *, int));
+static void appdef __P((char ***, const char *));
+static void usage __P((void));
+static void fname __P((const char *, int));
+static void runchild __P((const char *, char *const *, const char *));
+static void findlibs __P((char *const *));
+static int rdok __P((const char *));
+static void lint2 __P((void));
+static void cat __P((char *const *, const char *));
+
+/*
+ * Some functions to deal with lists of strings.
+ * Take care that we get no surprises in case of asyncron signals.
+ */
+static void
+appstrg(lstp, s)
+ char ***lstp, *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(lstp, s)
+ char ***lstp;
+ const char *s;
+{
+ appstrg(lstp, xstrdup(s));
+}
+
+static void
+applst(destp, src)
+ 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(lstp)
+ 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(s1, s2)
+ const char *s1, *s2;
+{
+ char *s;
+
+ s = xmalloc(strlen(s1) + strlen(s2) + 1);
+ (void)strcpy(s, s1);
+ (void)strcat(s, s2);
+
+ return (s);
+}
+
+static char *
+concat3(s1, s2, s3)
+ const char *s1, *s2, *s3;
+{
+ char *s;
+
+ s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
+ (void)strcpy(s, s1);
+ (void)strcat(s, s2);
+ (void)strcat(s, s3);
+
+ return (s);
+}
+
+/*
+ * Clean up after a signal.
+ */
+static void
+terminate(signo)
+ 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 *
+basename(strg, delim)
+ 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(lstp, def)
+ char ***lstp;
+ const char *def;
+{
+ appstrg(lstp, concat2("-D__", def));
+ appstrg(lstp, concat3("-D__", def, "__"));
+}
+
+static void
+usage()
+{
+ (void)printf("lint [-abceghprvxzHF] [-s|-t] [-i|-nu] [-Dname[=def]] [-Uname]\n");
+ (void)printf(" [-Idirectory] [-Ldirectory] [-llibrary] [-ooutputfile] file ...\n");
+ (void)printf("\n");
+ (void)printf("lint [-abceghprvzHF] [-s|-t] -Clibrary [-Dname[=def]]\n");
+ (void)printf(" [-Idirectory] [-Uname] file ...\n");
+ terminate(-1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int c;
+ 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)sprintf(s, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/");
+ tmpdir = s;
+ }
+
+ cppout = xmalloc(strlen(tmpdir) + sizeof ("lint0.XXXXXX"));
+ (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir);
+ if (mktemp(cppout) == NULL) {
+ warn("can't make temp");
+ terminate(-1);
+ }
+
+ 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, "-lang-c");
+ appcstrg(&cppflags, "-undef");
+ appcstrg(&cppflags, "-$");
+ appcstrg(&cppflags, "-C");
+ appcstrg(&cppflags, "-Wcomment");
+ appcstrg(&cppflags, "-D__NetBSD__");
+ appcstrg(&cppflags, "-Dlint"); /* XXX don't def. with -s */
+ appdef(&cppflags, "lint");
+ appdef(&cppflags, "unix");
+
+ appcstrg(&lcppflgs, "-Wtraditional");
+
+ if (uname(&un) == -1)
+ err(1, "uname");
+ appdef(&cppflags, un.machine);
+ appstrg(&lcppflgs, concat2("-D", un.machine));
+
+#ifdef MACHINE_ARCH
+ 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) {
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ c = getopt(argc, argv, "abceghil:no:prstuvxzC:D:FHI:L:U:V");
+
+ switch (c) {
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'e':
+ case 'g':
+ case 'r':
+ case 'v':
+ case 'z':
+ (void)sprintf(flgbuf, "-%c", c);
+ appcstrg(&l1flags, flgbuf);
+ break;
+
+ case 'F':
+ Fflag = 1;
+ /* FALLTHROUGH */
+ case 'u':
+ case 'h':
+ (void)sprintf(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));
+ p2out = xmalloc(sizeof ("llib-l.ln") + strlen(optarg));
+ (void)sprintf(p2out, "llib-l%s.ln", optarg);
+ freelst(&deflibs);
+ break;
+
+ case 'D':
+ case 'I':
+ case 'U':
+ (void)sprintf(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 'H':
+ appcstrg(&l2flags, "-H");
+ break;
+
+ case 'V':
+ Vflag = 1;
+ break;
+
+ case '?':
+ usage();
+ /* NOTREACHED */
+
+ case -1:
+ /* filename */
+ fname(argv[0], argc == 1);
+ first = 0;
+ optind = 1;
+ }
+
+ }
+
+ 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(name, last)
+ const char *name;
+ int last;
+{
+ const char *bn, *suff;
+ char **args, *ofn, *path;
+ size_t len;
+
+ bn = basename(name, '/');
+ suff = basename(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\n", name);
+ return;
+ }
+
+ if (!iflag || !first || !last)
+ (void)printf("%s:\n", Fflag ? name : bn);
+
+ /* build the name of the output file of lint1 */
+ if (oflag) {
+ ofn = outputfn;
+ outputfn = NULL;
+ oflag = 0;
+ } else if (iflag) {
+ ofn = xmalloc(strlen(bn) + (bn == suff ? 4 : 2));
+ len = bn == suff ? strlen(bn) : (suff - 1) - bn;
+ (void)sprintf(ofn, "%.*s", (int)len, bn);
+ (void)strcat(ofn, ".ln");
+ } else {
+ ofn = xmalloc(strlen(tmpdir) + sizeof ("lint1.XXXXXX"));
+ (void)sprintf(ofn, "%slint1.XXXXXX", tmpdir);
+ if (mktemp(ofn) == NULL) {
+ warn("can't make temp");
+ terminate(-1);
+ }
+ }
+ if (!iflag)
+ appcstrg(&p1out, ofn);
+
+ args = xcalloc(1, sizeof (char *));
+
+ /* run cpp */
+
+ path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/cpp"));
+ (void)sprintf(path, "%s/cpp", PATH_LIBEXEC);
+
+ appcstrg(&args, path);
+ applst(&args, cppflags);
+ applst(&args, lcppflgs);
+ appcstrg(&args, name);
+ appcstrg(&args, cppout);
+
+ runchild(path, args, cppout);
+ free(path);
+ freelst(&args);
+
+ /* run lint1 */
+
+ path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint1"));
+ (void)sprintf(path, "%s/lint1", PATH_LIBEXEC);
+
+ appcstrg(&args, path);
+ applst(&args, l1flags);
+ appcstrg(&args, cppout);
+ appcstrg(&args, ofn);
+
+ runchild(path, args, ofn);
+ free(path);
+ freelst(&args);
+
+ appcstrg(&p2in, ofn);
+ free(ofn);
+
+ free(args);
+}
+
+static void
+runchild(path, args, crfn)
+ const char *path, *crfn;
+ char *const *args;
+{
+ int status, rv, signo, i;
+
+ 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 */
+ }
+
+ while ((rv = wait(&status)) == -1 && errno == EINTR) ;
+ if (rv == -1) {
+ warn("wait");
+ terminate(-1);
+ }
+ if (WIFSIGNALED(status)) {
+ signo = WTERMSIG(status);
+ warnx("%s got SIG%s", path, sys_signame[signo]);
+ terminate(-1);
+ }
+ if (WEXITSTATUS(status) != 0)
+ terminate(-1);
+ currfn = NULL;
+}
+
+static void
+findlibs(liblst)
+ char *const *liblst;
+{
+ int i, k;
+ const char *lib, *path;
+ char *lfn;
+ size_t len;
+
+ lfn = NULL;
+
+ for (i = 0; (lib = liblst[i]) != NULL; i++) {
+ for (k = 0; (path = libsrchpath[k]) != NULL; k++) {
+ len = strlen(path) + strlen(lib);
+ lfn = xrealloc(lfn, len + sizeof ("/llib-l.ln"));
+ (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib);
+ if (rdok(lfn))
+ break;
+ lfn = xrealloc(lfn, len + sizeof ("/lint/llib-l.ln"));
+ (void)sprintf(lfn, "%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(path)
+ 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 *));
+
+ path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint2"));
+ (void)sprintf(path, "%s/lint2", PATH_LIBEXEC);
+
+ appcstrg(&args, path);
+ applst(&args, l2flags);
+ applst(&args, l2libs);
+ applst(&args, p2in);
+
+ runchild(path, args, p2out);
+ free(path);
+ freelst(&args);
+ free(args);
+}
+
+static void
+cat(srcs, dest)
+ 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);
+}
+
OpenPOWER on IntegriCloud