Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Mar 2015 09:55:36 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r279643 - in stable/9/usr.bin: find indent jot setchannel tr unifdef vgrind
Message-ID:  <201503050955.t259tacH051234@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu Mar  5 09:55:35 2015
New Revision: 279643
URL: https://svnweb.freebsd.org/changeset/base/279643

Log:
  MFC r227243, r233456, r248258, r248849 and r279297:
  
  Update to upstream version 2.10
  
  The most notable new feature is support for definition files.
  
  The most notable new feature is support for processing multiple
  files in one invocation. There is also support for more make-friendly
  exit statuses.
  
  The most notable bug fix is #line directives now include the input
  file name.
  
  Obtained from:	http://dotat.at/prog/unifdef

Added:
  stable/9/usr.bin/unifdef/unifdef.h
     - copied, changed from r248849, head/usr.bin/unifdef/unifdef.h
Modified:
  stable/9/usr.bin/find/find.1
  stable/9/usr.bin/indent/indent.1
  stable/9/usr.bin/jot/jot.1
  stable/9/usr.bin/setchannel/setchannel.1
  stable/9/usr.bin/tr/tr.1
  stable/9/usr.bin/unifdef/unifdef.1
  stable/9/usr.bin/unifdef/unifdef.c
  stable/9/usr.bin/unifdef/unifdefall.sh
  stable/9/usr.bin/vgrind/vgrindefs.5
Directory Properties:
  stable/9/usr.bin/   (props changed)
  stable/9/usr.bin/calendar/   (props changed)
  stable/9/usr.bin/find/   (props changed)
  stable/9/usr.bin/indent/   (props changed)

Modified: stable/9/usr.bin/find/find.1
==============================================================================
--- stable/9/usr.bin/find/find.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/find/find.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -156,7 +156,6 @@ This option is equivalent to the depreca
 primary.
 .El
 .Sh PRIMARIES
-.Pp
 All primaries which take a numeric argument allow the number to be
 preceded by a plus sign
 .Pq Dq Li +

Modified: stable/9/usr.bin/indent/indent.1
==============================================================================
--- stable/9/usr.bin/indent/indent.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/indent/indent.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -488,7 +488,6 @@ The
 utility fits as many words (separated by blanks, tabs, or newlines) on a
 line as possible.
 Blank lines break paragraphs.
-.Pp
 .Ss Comment indentation
 If a comment is on a line with code it is started in the `comment column',
 which is set by the
@@ -504,7 +503,6 @@ command line parameter.
 If the code on a line extends past the comment
 column, the comment starts further to the right, and the right margin may be
 automatically extended in extreme cases.
-.Pp
 .Ss Preprocessor lines
 In general,
 .Nm
@@ -519,7 +517,6 @@ is recognized and
 .Nm
 attempts to correctly
 compensate for the syntactic peculiarities introduced.
-.Pp
 .Ss C syntax
 The
 .Nm

Modified: stable/9/usr.bin/jot/jot.1
==============================================================================
--- stable/9/usr.bin/jot/jot.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/jot/jot.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -242,7 +242,6 @@ specifying an integer format:
 .Bd -literal -offset indent
 $ jot -w %d 6 1 10 0.5
 .Ed
-.Pp
 .Sh EXIT STATUS
 .Ex -std
 .Sh EXAMPLES

Modified: stable/9/usr.bin/setchannel/setchannel.1
==============================================================================
--- stable/9/usr.bin/setchannel/setchannel.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/setchannel/setchannel.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -33,7 +33,6 @@
 .Nd Hauppage PVR250/350 channel selector
 .Sh SYNOPSIS
 .Cd pvr250-setchannel [-a {on | off}] [-c | -r | -s | -t] [-g geom] [-m channel_set] [channel | freq]
-.Pp
 .Sh DESCRIPTION
 .Nm
 provides support for selecting channels on Hauppauge WinTV cards,

Modified: stable/9/usr.bin/tr/tr.1
==============================================================================
--- stable/9/usr.bin/tr/tr.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/tr/tr.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -145,7 +145,6 @@ the octal sequence to the full 3 octal d
 .It \echaracter
 A backslash followed by certain special characters maps to special
 values.
-.Pp
 .Bl -column "\ea"
 .It "\ea	<alert character>
 .It "\eb	<backspace>
@@ -177,7 +176,6 @@ previous implementations.
 .It [:class:]
 Represents all characters belonging to the defined character class.
 Class names are:
-.Pp
 .Bl -column "phonogram"
 .It "alnum	<alphanumeric characters>
 .It "alpha	<alphabetic characters>

Modified: stable/9/usr.bin/unifdef/unifdef.1
==============================================================================
--- stable/9/usr.bin/unifdef/unifdef.1	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/unifdef/unifdef.1	Thu Mar  5 09:55:35 2015	(r279643)
@@ -1,6 +1,6 @@
 .\" Copyright (c) 1985, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
-.\" Copyright (c) 2002 - 2010 Tony Finch <dot@dotat.at>.  All rights reserved.
+.\" Copyright (c) 2002 - 2013 Tony Finch <dot@dotat.at>.  All rights reserved.
 .\"
 .\" This code is derived from software contributed to Berkeley by
 .\" Dave Yost. It was rewritten to support ANSI C by Tony Finch.
@@ -31,23 +31,24 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 11, 2010
-.Dt UNIFDEF 1
-.Os
+.Dd January 7, 2014
+.Dt UNIFDEF 1 PRM
+.Os " "
 .Sh NAME
 .Nm unifdef , unifdefall
 .Nd remove preprocessor conditionals from code
 .Sh SYNOPSIS
 .Nm
-.Op Fl bBcdeKknsStV
+.Op Fl bBcdehKkmnsStV
 .Op Fl I Ns Ar path
-.Op Fl D Ns Ar sym Ns Op = Ns Ar val
-.Op Fl U Ns Ar sym
-.Op Fl iD Ns Ar sym Ns Op = Ns Ar val
-.Op Fl iU Ns Ar sym
+.Op Fl [i]D Ns Ar sym Ns Op = Ns Ar val
+.Op Fl [i]U Ns Ar sym
 .Ar ...
+.Op Fl f Ar defile
+.Op Fl x Bro Ar 012 Brc
+.Op Fl M Ar backext
 .Op Fl o Ar outfile
-.Op Ar infile
+.Op Ar infile ...
 .Nm unifdefall
 .Op Fl I Ns Ar path
 .Ar ...
@@ -66,14 +67,21 @@ while otherwise leaving the file alone.
 The
 .Nm
 utility acts on
-.Ic #if , #ifdef , #ifndef , #elif , #else ,
+.Ic #if , #ifdef , #ifndef ,
+.Ic #elif , #else ,
 and
 .Ic #endif
-lines.
-A directive is only processed
-if the symbols specified on the command line are sufficient to allow
-.Nm
-to get a definite value for its control expression.
+lines,
+using macros specified in
+.Fl D
+and
+.Fl U
+command line options or in
+.Fl f
+definitions files.
+A directive is processed
+if the macro specifications are sufficient to provide
+a definite value for its control expression.
 If the result is false,
 the directive and the following lines under its control are removed.
 If the result is true,
@@ -83,7 +91,7 @@ An
 or
 .Ic #ifndef
 directive is passed through unchanged
-if its controlling symbol is not specified on the command line.
+if its controlling macro is not specified.
 Any
 .Ic #if
 or
@@ -109,12 +117,14 @@ and
 .Ic #elif
 lines:
 integer constants,
-integer values of symbols defined on the command line,
+integer values of macros defined on the command line,
 the
 .Fn defined
 operator,
 the operators
-.Ic \&! , < , > , <= , >= , == , != , && , || ,
+.Ic \&! , < , > ,
+.Ic <= , >= , == , != ,
+.Ic && , || ,
 and parenthesized expressions.
 A kind of
 .Dq "short circuit"
@@ -128,16 +138,42 @@ if either operand of
 .Ic ||
 is definitely true then the result is true.
 .Pp
-In most cases, the
+When evaluating an expression,
 .Nm
-utility does not distinguish between object-like macros
-(without arguments) and function-like arguments (with arguments).
-If a macro is not explicitly defined, or is defined with the
+does not expand macros first.
+The value of a macro must be a simple number,
+not an expression.
+A limited form of indirection is allowed,
+where one macro's value is the name of another.
+.Pp
+In most cases,
+.Nm
+does not distinguish between object-like macros
+(without arguments) and function-like macros (with arguments).
+A function-like macro invocation can appear in
+.Ic #if
+and
+.Ic #elif
+control expressions.
+If the macro is not explicitly defined,
+or is defined with the
 .Fl D
-flag on the command-line, its arguments are ignored.
+flag on the command-line,
+or with
+.Ic #define
+in a
+.Fl f
+definitions file,
+its arguments are ignored.
 If a macro is explicitly undefined on the command line with the
 .Fl U
-flag, it may not have any arguments since this leads to a syntax error.
+flag,
+or with
+.Ic #undef
+in a
+.Fl f
+definitions file,
+it may not have any arguments since this leads to a syntax error.
 .Pp
 The
 .Nm
@@ -158,30 +194,65 @@ It uses
 .Nm Fl s
 and
 .Nm cpp Fl dM
-to get lists of all the controlling symbols
+to get lists of all the controlling macros
 and their definitions (or lack thereof),
 then invokes
 .Nm
 with appropriate arguments to process the file.
 .Sh OPTIONS
-.Pp
 .Bl -tag -width indent -compact
 .It Fl D Ns Ar sym Ns = Ns Ar val
-Specify that a symbol is defined to a given value
-which is used when evaluating
-.Ic #if
-and
-.Ic #elif
-control expressions.
+Specify that a macro is defined to a given value.
 .Pp
 .It Fl D Ns Ar sym
-Specify that a symbol is defined to the value 1.
+Specify that a macro is defined to the value 1.
 .Pp
 .It Fl U Ns Ar sym
-Specify that a symbol is undefined.
-If the same symbol appears in more than one argument,
+Specify that a macro is undefined.
+.Pp
+If the same macro appears in more than one argument,
 the last occurrence dominates.
 .Pp
+.It Fl iD Ns Ar sym Ns Op = Ns Ar val
+.It Fl iU Ns Ar sym
+C strings, comments,
+and line continuations
+are ignored within
+.Ic #ifdef
+and
+.Ic #ifndef
+blocks
+controlled by macros
+specified with these options.
+.Pp
+.It Fl f Ar defile
+The file
+.Ar defile
+contains
+.Ic #define
+and
+.Ic #undef
+preprocessor directives,
+which have the same effect as the corresponding
+.Fl D
+and
+.Fl U
+command-line arguments.
+You can have multiple
+.Fl f
+arguments and mix them with
+.Fl D
+and
+.Fl U
+arguments;
+later options override earlier ones.
+.Pp
+Each directive must be on a single line.
+Object-like macro definitions (without arguments)
+are set to the given value.
+Function-like macro definitions (with arguments)
+are treated as if they are set to 1.
+.Pp
 .It Fl b
 Replace removed lines with blank lines
 instead of deleting them.
@@ -196,35 +267,39 @@ Mutually exclusive with the
 option.
 .Pp
 .It Fl c
-If the
-.Fl c
-flag is specified,
-then the operation of
-.Nm
-is complemented,
-i.e., the lines that would have been removed or blanked
+Complement,
+i.e., lines that would have been removed or blanked
 are retained and vice versa.
 .Pp
 .It Fl d
 Turn on printing of debugging messages.
 .Pp
 .It Fl e
-Because
-.Nm
-processes its input one line at a time,
-it cannot remove preprocessor directives that span more than one line.
-The most common example of this is a directive with a multi-line
-comment hanging off its right hand end.
 By default,
-if
 .Nm
-has to process such a directive,
-it will complain that the line is too obfuscated.
+will report an error if it needs to remove
+a preprocessor directive that spans more than one line,
+for example, if it has a multi-line
+comment hanging off its right hand end.
 The
 .Fl e
-option changes the behaviour so that,
-where possible,
-such lines are left unprocessed instead of reporting an error.
+flag makes it ignore the line instead.
+.Pp
+.It Fl h
+Print help.
+.Pp
+.It Fl I Ns Ar path
+Specifies to
+.Nm unifdefall
+an additional place to look for
+.Ic #include
+files.
+This option is ignored by
+.Nm
+for compatibility with
+.Xr cpp 1
+and to simplify the implementation of
+.Nm unifdefall .
 .Pp
 .It Fl K
 Always treat the result of
@@ -248,6 +323,15 @@ because they typically start
 and are used as a kind of comment to sketch out future or past development.
 It would be rude to strip them out, just as it would be for normal comments.
 .Pp
+.It Fl m
+Modify one or more input files in place.
+.Pp
+.It Fl M Ar backext
+Modify input files in place, and keep backups of the original files by
+appending the
+.Ar backext
+to the input filenames.
+.Pp
 .It Fl n
 Add
 .Li #line
@@ -258,96 +342,57 @@ line numbers in the input file.
 .It Fl o Ar outfile
 Write output to the file
 .Ar outfile
-instead of the standard output.
-If
-.Ar outfile
-is the same as the input file,
-the output is written to a temporary file
-which is renamed into place when
-.Nm
-completes successfully.
+instead of the standard output when processing a single file.
 .Pp
 .It Fl s
-Instead of processing the input file as usual,
+Instead of processing an input file as usual,
 this option causes
 .Nm
-to produce a list of symbols that appear in expressions
-that
-.Nm
-understands.
-It is useful in conjunction with the
-.Fl dM
-option of
-.Xr cpp 1
-for creating
-.Nm
-command lines.
+to produce a list of macros that are used in
+preprocessor directive controlling expressions.
 .Pp
 .It Fl S
 Like the
 .Fl s
-option, but the nesting depth of each symbol is also printed.
+option, but the nesting depth of each macro is also printed.
 This is useful for working out the number of possible combinations
-of interdependent defined/undefined symbols.
+of interdependent defined/undefined macros.
 .Pp
 .It Fl t
-Disables parsing for C comments
+Disables parsing for C strings, comments,
 and line continuations,
 which is useful
 for plain text.
-.Pp
-.It Fl iD Ns Ar sym Ns Op = Ns Ar val
-.It Fl iU Ns Ar sym
-Ignore
-.Ic #ifdef Ns s .
-If your C code uses
-.Ic #ifdef Ns s
-to delimit non-C lines,
-such as comments
-or code which is under construction,
-then you must tell
-.Nm
-which symbols are used for that purpose so that it will not try to parse
-comments
-and line continuations
-inside those
-.Ic #ifdef Ns s .
-You can specify ignored symbols with
-.Fl iD Ns Ar sym Ns Oo = Ns Ar val Oc
-and
-.Fl iU Ns Ar sym
-similar to
-.Fl D Ns Ar sym Ns Op = Ns Ar val
+This is a blanket version of the
+.Fl iD
 and
-.Fl U Ns Ar sym
-above.
-.Pp
-.It Fl I Ns Ar path
-Specifies to
-.Nm unifdefall
-an additional place to look for
-.Ic #include
-files.
-This option is ignored by
-.Nm
-for compatibility with
-.Xr cpp 1
-and to simplify the implementation of
-.Nm unifdefall .
+.Fl iU
+flags.
 .Pp
 .It Fl V
 Print version details.
+.Pp
+.It Fl x Bro Ar 012 Brc
+Set exit status mode to zero, one, or two.
+See the
+.Sx EXIT STATUS
+section below for details.
 .El
 .Pp
 The
 .Nm
-utility copies its output to
-.Em stdout
-and will take its input from
+utility takes its input from
 .Em stdin
-if no
+if there are no
 .Ar file
-argument is given.
+arguments.
+You must use the
+.Fl m
+or
+.Fl M
+options if there are multiple input files.
+You can specify inut from stdin or output to stdout with
+.Ql - .
 .Pp
 The
 .Nm
@@ -356,10 +401,35 @@ utility works nicely with the
 option of
 .Xr diff 1 .
 .Sh EXIT STATUS
-The
+In normal usage the
+.Nm
+utility's exit status depends on the mode set using the
+.Fl x
+option.
+.Pp
+If the exit mode is zero (the default) then
+.Nm
+exits with status 0 if the output is an exact copy of the input,
+or with status 1 if the output differs.
+.Pp
+If the exit mode is one,
+.Nm
+exits with status 1 if the output is unmodified
+or 0 if it differs.
+.Pp
+If the exit mode is two,
 .Nm
-utility exits 0 if the output is an exact copy of the input,
-1 if not, and 2 if in trouble.
+exits with status zero in both cases.
+.Pp
+In all exit modes,
+.Nm
+exits with status 2 if there is an error.
+.Pp
+The exit status is 0 if the
+.Fl h
+or
+.Fl V
+command line options are given.
 .Sh DIAGNOSTICS
 .Bl -item
 .It
@@ -384,6 +454,9 @@ in comment.
 .Sh SEE ALSO
 .Xr cpp 1 ,
 .Xr diff 1
+.Pp
+The unifdef home page is
+.Pa http://dotat.at/prog/unifdef
 .Sh HISTORY
 The
 .Nm
@@ -401,13 +474,14 @@ rewrote it to support
 .Sh BUGS
 Expression evaluation is very limited.
 .Pp
-Preprocessor control lines split across more than one physical line
+Handling one line at a time means
+preprocessor directives split across more than one physical line
 (because of comments or backslash-newline)
 cannot be handled in every situation.
 .Pp
 Trigraphs are not recognized.
 .Pp
-There is no support for symbols with different definitions at
+There is no support for macros with different definitions at
 different points in the source file.
 .Pp
 The text-mode and ignore functionality does not correspond to modern

Modified: stable/9/usr.bin/unifdef/unifdef.c
==============================================================================
--- stable/9/usr.bin/unifdef/unifdef.c	Thu Mar  5 09:51:59 2015	(r279642)
+++ stable/9/usr.bin/unifdef/unifdef.c	Thu Mar  5 09:55:35 2015	(r279643)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002 - 2011 Tony Finch <dot@dotat.at>
+ * Copyright (c) 2002 - 2014 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,21 +43,10 @@
  *   it possible to handle all "dodgy" directives correctly.
  */
 
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "unifdef.h"
 
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-const char copyright[] =
-    "@(#) $Version: unifdef-2.5.6.21f1388 $\n"
+static const char copyright[] =
+    "@(#) $Version: unifdef-2.10 $\n"
     "@(#) $FreeBSD$\n"
     "@(#) $Author: Tony Finch (dot@dotat.at) $\n"
     "@(#) $URL: http://dotat.at/prog/unifdef $\n"
@@ -93,6 +82,9 @@ static char const * const linetype_name[
 	"PLAIN", "EOF", "ERROR"
 };
 
+#define linetype_if2elif(lt) ((Linetype)(lt - LT_IF + LT_ELIF))
+#define linetype_2dodgy(lt) ((Linetype)(lt + LT_DODGY))
+
 /* state of #if processing */
 typedef enum {
 	IS_OUTSIDE,
@@ -146,7 +138,7 @@ static char const * const linestate_name
  */
 #define	MAXDEPTH        64			/* maximum #if nesting */
 #define	MAXLINE         4096			/* maximum length of line */
-#define	MAXSYMS         4096			/* maximum number of symbols */
+#define	MAXSYMS         16384			/* maximum number of symbols */
 
 /*
  * Sometimes when editing a keyword the replacement text is longer, so
@@ -155,11 +147,6 @@ static char const * const linestate_name
 #define	EDITSLOP        10
 
 /*
- * For temporary filenames
- */
-#define TEMPLATE        "unifdef.XXXXXX"
-
-/*
  * Globals.
  */
 
@@ -167,6 +154,7 @@ static bool             compblank;		/* -
 static bool             lnblank;		/* -b: blank deleted lines */
 static bool             complement;		/* -c: do the complement */
 static bool             debugging;		/* -d: debugging reports */
+static bool             inplace;		/* -m: modify in place */
 static bool             iocccok;		/* -e: fewer IOCCC errors */
 static bool             strictlogic;		/* -K: keep ambiguous #ifs */
 static bool             killconsts;		/* -k: eval constant #ifs */
@@ -183,14 +171,24 @@ static int              nsyms;			/* numb
 static FILE            *input;			/* input file pointer */
 static const char      *filename;		/* input file name */
 static int              linenum;		/* current line number */
+static const char      *linefile;		/* file name for #line */
 static FILE            *output;			/* output file pointer */
 static const char      *ofilename;		/* output file name */
-static bool             overwriting;		/* output overwrites input */
-static char             tempname[FILENAME_MAX];	/* used when overwriting */
+static const char      *backext;		/* backup extension */
+static char            *tempname;		/* avoid splatting input */
 
 static char             tline[MAXLINE+EDITSLOP];/* input buffer plus space */
 static char            *keyword;		/* used for editing #elif's */
 
+/*
+ * When processing a file, the output's newline style will match the
+ * input's, and unifdef correctly handles CRLF or LF endings whatever
+ * the platform's native style. The stdio streams are opened in binary
+ * mode to accommodate platforms whose native newline style is CRLF.
+ * When the output isn't a processed input file (when it is error /
+ * debug / diagnostic messages) then unifdef uses native line endings.
+ */
+
 static const char      *newline;		/* input file format */
 static const char       newline_unix[] = "\n";
 static const char       newline_crlf[] = "\r\n";
@@ -205,33 +203,47 @@ static int              delcount;		/* co
 static unsigned         blankcount;		/* count of blank lines */
 static unsigned         blankmax;		/* maximum recent blankcount */
 static bool             constexpr;		/* constant #if expression */
-static bool             zerosyms = true;	/* to format symdepth output */
+static bool             zerosyms;		/* to format symdepth output */
 static bool             firstsym;		/* ditto */
 
+static int              exitmode;		/* exit status mode */
 static int              exitstat;		/* program exit status */
 
-static void             addsym(bool, bool, char *);
-static void             closeout(void);
+static void             addsym1(bool, bool, char *);
+static void             addsym2(bool, const char *, const char *);
+static char            *astrcat(const char *, const char *);
+static void             cleantemp(void);
+static void             closeio(void);
 static void             debug(const char *, ...);
+static void             debugsym(const char *, int);
+static bool             defundef(void);
+static void             defundefile(const char *);
 static void             done(void);
 static void             error(const char *);
-static int              findsym(const char *);
+static int              findsym(const char **);
 static void             flushline(bool);
-static Linetype         parseline(void);
+static void             hashline(void);
+static void             help(void);
 static Linetype         ifeval(const char **);
 static void             ignoreoff(void);
 static void             ignoreon(void);
+static void             indirectsym(void);
 static void             keywordedit(const char *);
+static const char      *matchsym(const char *, const char *);
 static void             nest(void);
+static Linetype         parseline(void);
 static void             process(void);
+static void             processinout(const char *, const char *);
 static const char      *skipargs(const char *);
 static const char      *skipcomment(const char *);
+static const char      *skiphash(void);
+static const char      *skipline(const char *);
 static const char      *skipsym(const char *);
 static void             state(Ifstate);
-static int              strlcmp(const char *, const char *, size_t);
 static void             unnest(void);
 static void             usage(void);
 static void             version(void);
+static const char      *xstrdup(const char *, const char *);
 
 #define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
@@ -243,7 +255,7 @@ main(int argc, char *argv[])
 {
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1)
+	while ((opt = getopt(argc, argv, "i:D:U:f:I:M:o:x:bBcdehKklmnsStV")) != -1)
 		switch (opt) {
 		case 'i': /* treat stuff controlled by these symbols as text */
 			/*
@@ -253,17 +265,17 @@ main(int argc, char *argv[])
 			 */
 			opt = *optarg++;
 			if (opt == 'D')
-				addsym(true, true, optarg);
+				addsym1(true, true, optarg);
 			else if (opt == 'U')
-				addsym(true, false, optarg);
+				addsym1(true, false, optarg);
 			else
 				usage();
 			break;
 		case 'D': /* define a symbol */
-			addsym(false, true, optarg);
+			addsym1(false, true, optarg);
 			break;
 		case 'U': /* undef a symbol */
-			addsym(false, false, optarg);
+			addsym1(false, false, optarg);
 			break;
 		case 'I': /* no-op for compatibility with cpp */
 			break;
@@ -283,12 +295,25 @@ main(int argc, char *argv[])
 		case 'e': /* fewer errors from dodgy lines */
 			iocccok = true;
 			break;
+		case 'f': /* definitions file */
+			defundefile(optarg);
+			break;
+		case 'h':
+			help();
+			break;
 		case 'K': /* keep ambiguous #ifs */
 			strictlogic = true;
 			break;
 		case 'k': /* process constant #ifs */
 			killconsts = true;
 			break;
+		case 'm': /* modify in place */
+			inplace = true;
+			break;
+		case 'M': /* modify in place and keep backup */
+			inplace = true;
+			backext = optarg;
+			break;
 		case 'n': /* add #line directive after deleted lines */
 			lnnum = true;
 			break;
@@ -304,8 +329,14 @@ main(int argc, char *argv[])
 		case 't': /* don't parse C comments */
 			text = true;
 			break;
-		case 'V': /* print version */
+		case 'V':
 			version();
+			break;
+		case 'x':
+			exitmode = atoi(optarg);
+			if(exitmode < 0 || exitmode > 2)
+				usage();
+			break;
 		default:
 			usage();
 		}
@@ -313,54 +344,98 @@ main(int argc, char *argv[])
 	argv += optind;
 	if (compblank && lnblank)
 		errx(2, "-B and -b are mutually exclusive");
-	if (argc > 1) {
-		errx(2, "can only do one file");
-	} else if (argc == 1 && strcmp(*argv, "-") != 0) {
-		filename = *argv;
-		input = fopen(filename, "rb");
-		if (input == NULL)
-			err(2, "can't open %s", filename);
-	} else {
-		filename = "[stdin]";
-		input = stdin;
+	if (symlist && (ofilename != NULL || inplace || argc > 1))
+		errx(2, "-s only works with one input file");
+	if (argc > 1 && ofilename != NULL)
+		errx(2, "-o cannot be used with multiple input files");
+	if (argc > 1 && !inplace)
+		errx(2, "multiple input files require -m or -M");
+	if (argc == 0)
+		argc = 1;
+	if (argc == 1 && !inplace && ofilename == NULL)
+		ofilename = "-";
+	indirectsym();
+
+	atexit(cleantemp);
+	if (ofilename != NULL)
+		processinout(*argv, ofilename);
+	else while (argc-- > 0) {
+		processinout(*argv, *argv);
+		argv++;
 	}
-	if (ofilename == NULL) {
-		ofilename = "[stdout]";
-		output = stdout;
+	switch(exitmode) {
+	case(0): exit(exitstat);
+	case(1): exit(!exitstat);
+	case(2): exit(0);
+	default: abort(); /* bug */
+	}
+}
+
+/*
+ * File logistics.
+ */
+static void
+processinout(const char *ifn, const char *ofn)
+{
+	struct stat st;
+
+	if (ifn == NULL || strcmp(ifn, "-") == 0) {
+		filename = "[stdin]";
+		linefile = NULL;
+		input = fbinmode(stdin);
 	} else {
-		struct stat ist, ost;
-		if (stat(ofilename, &ost) == 0 &&
-		    fstat(fileno(input), &ist) == 0)
-			overwriting = (ist.st_dev == ost.st_dev
-				    && ist.st_ino == ost.st_ino);
-		if (overwriting) {
-			const char *dirsep;
-			int ofd;
-
-			dirsep = strrchr(ofilename, '/');
-			if (dirsep != NULL)
-				snprintf(tempname, sizeof(tempname),
-				    "%.*s/" TEMPLATE,
-				    (int)(dirsep - ofilename), ofilename);
-			else
-				snprintf(tempname, sizeof(tempname),
-				    TEMPLATE);
-			ofd = mkstemp(tempname);
-			if (ofd != -1)
-				output = fdopen(ofd, "wb+");
-			if (output == NULL)
-				err(2, "can't create temporary file");
-			fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
-		} else {
-			output = fopen(ofilename, "wb");
-			if (output == NULL)
-				err(2, "can't open %s", ofilename);
-		}
+		filename = ifn;
+		linefile = ifn;
+		input = fopen(ifn, "rb");
+		if (input == NULL)
+			err(2, "can't open %s", ifn);
+	}
+	if (strcmp(ofn, "-") == 0) {
+		output = fbinmode(stdout);
+		process();
+		return;
 	}
+	if (stat(ofn, &st) < 0) {
+		output = fopen(ofn, "wb");
+		if (output == NULL)
+			err(2, "can't create %s", ofn);
+		process();
+		return;
+	}
+
+	tempname = astrcat(ofn, ".XXXXXX");
+	output = mktempmode(tempname, st.st_mode);
+	if (output == NULL)
+		err(2, "can't create %s", tempname);
+
 	process();
-	abort(); /* bug */
+
+	if (backext != NULL) {
+		char *backname = astrcat(ofn, backext);
+		if (rename(ofn, backname) < 0)
+			err(2, "can't rename \"%s\" to \"%s\"", ofn, backname);
+		free(backname);
+	}
+	if (replace(tempname, ofn) < 0)
+		err(2, "can't rename \"%s\" to \"%s\"", tempname, ofn);
+	free(tempname);
+	tempname = NULL;
 }
 
+/*
+ * For cleaning up if there is an error.
+ */
+static void
+cleantemp(void)
+{
+	if (tempname != NULL)
+		remove(tempname);
+}
+
+/*
+ * Self-identification functions.
+ */
+
 static void
 version(void)
 {
@@ -376,13 +451,54 @@ version(void)
 }
 
 static void
+synopsis(FILE *fp)
+{
+	fprintf(fp,
+	    "usage:	unifdef [-bBcdehKkmnsStV] [-x{012}] [-Mext] [-opath] \\\n"
+	    "		[-[i]Dsym[=val]] [-[i]Usym] [-fpath] ... [file] ...\n");
+}
+
+static void
 usage(void)
 {
-	fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]"
-	    " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
+	synopsis(stderr);
 	exit(2);
 }
 
+static void
+help(void)
+{
+	synopsis(stdout);
+	printf(
+	    "	-Dsym=val  define preprocessor symbol with given value\n"
+	    "	-Dsym      define preprocessor symbol with value 1\n"
+	    "	-Usym	   preprocessor symbol is undefined\n"
+	    "	-iDsym=val \\  ignore C strings and comments\n"
+	    "	-iDsym      ) in sections controlled by these\n"
+	    "	-iUsym	   /  preprocessor symbols\n"
+	    "	-fpath	file containing #define and #undef directives\n"
+	    "	-b	blank lines instead of deleting them\n"
+	    "	-B	compress blank lines around deleted section\n"
+	    "	-c	complement (invert) keep vs. delete\n"
+	    "	-d	debugging mode\n"
+	    "	-e	ignore multiline preprocessor directives\n"
+	    "	-h	print help\n"
+	    "	-Ipath	extra include file path (ignored)\n"
+	    "	-K	disable && and || short-circuiting\n"
+	    "	-k	process constant #if expressions\n"
+	    "	-Mext	modify in place and keep backups\n"
+	    "	-m	modify input files in place\n"
+	    "	-n	add #line directives to output\n"
+	    "	-opath	output file name\n"
+	    "	-S	list #if control symbols with nesting\n"
+	    "	-s	list #if control symbols\n"
+	    "	-t	ignore C strings and comments\n"
+	    "	-V	print version\n"
+	    "	-x{012}	exit status mode\n"
+	);
+	exit(0);
+}
+
 /*
  * A state transition function alters the global #if processing state
  * in a particular way. The table below is indexed by the current
@@ -396,7 +512,7 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct. We use strncpy() to
+ * latter into a #if to keep the nesting correct. We use memcpy() to
  * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
@@ -451,7 +567,7 @@ static void Idrop (void) { Fdrop();  ign
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503050955.t259tacH051234>