summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorfanf <fanf@FreeBSD.org>2010-01-19 18:13:54 +0000
committerfanf <fanf@FreeBSD.org>2010-01-19 18:13:54 +0000
commitd3169e6c49b93a0a22537a3659660db49759e6fb (patch)
treecea4a04dd4bb5e44cbf43fd1dafa6a067e740430 /usr.bin
parent0ab6ce0ba0bce27067280abbb3d31f887f040380 (diff)
downloadFreeBSD-src-d3169e6c49b93a0a22537a3659660db49759e6fb.zip
FreeBSD-src-d3169e6c49b93a0a22537a3659660db49759e6fb.tar.gz
Add a -o outfile option, which can be used to specify an output file. The
file can safely be the same as the input file. Idea from IRIX unifdef(1). This version fixes a bug in the NetBSD unifdef which refuses to write to a -o outfile which does not exist. Obtained from: NetBSD
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/unifdef/unifdef.121
-rw-r--r--usr.bin/unifdef/unifdef.c128
2 files changed, 119 insertions, 30 deletions
diff --git a/usr.bin/unifdef/unifdef.1 b/usr.bin/unifdef/unifdef.1
index 80ee7ba..2e75f0a 100644
--- a/usr.bin/unifdef/unifdef.1
+++ b/usr.bin/unifdef/unifdef.1
@@ -1,6 +1,6 @@
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
-.\" Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>. All rights reserved.
+.\" Copyright (c) 2002 - 2010 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.
@@ -30,10 +30,10 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)unifdef.1 8.2 (Berkeley) 4/1/94
-.\" $dotat: unifdef/unifdef.1,v 1.60 2009/11/25 00:11:02 fanf2 Exp $
+.\" $dotat: unifdef/unifdef.1,v 1.62 2010/01/19 17:33:53 fanf2 Exp $
.\" $FreeBSD$
.\"
-.Dd September 24, 2002
+.Dd January 19, 2010
.Dt UNIFDEF 1
.Os
.Sh NAME
@@ -48,7 +48,8 @@
.Op Fl iD Ns Ar sym Ns Op = Ns Ar val
.Op Fl iU Ns Ar sym
.Ar ...
-.Op Ar file
+.Op Fl o Ar outfile
+.Op Ar infile
.Nm unifdefall
.Op Fl I Ns Ar path
.Ar ...
@@ -254,6 +255,18 @@ directives to the output following any deleted lines,
so that errors produced when compiling the output file correspond to
line numbers in the input file.
.Pp
+.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.
+.Pp
.It Fl s
Instead of processing the input file as usual,
this option causes
diff --git a/usr.bin/unifdef/unifdef.c b/usr.bin/unifdef/unifdef.c
index be5b4fc..86cd18a 100644
--- a/usr.bin/unifdef/unifdef.c
+++ b/usr.bin/unifdef/unifdef.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
+ * Copyright (c) 2002 - 2010 Tony Finch <dot@dotat.at>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,27 +24,14 @@
*/
/*
+ * unifdef - remove ifdef'ed lines
+ *
* This code was derived from software contributed to Berkeley by Dave Yost.
* It was rewritten to support ANSI C by Tony Finch. The original version
* of unifdef carried the 4-clause BSD copyright licence. None of its code
* remains in this version (though some of the names remain) so it now
* carries a more liberal licence.
*
- * The latest version is available from http://dotat.at/prog/unifdef
- */
-
-#include <sys/cdefs.h>
-
-#ifdef __IDSTRING
-__IDSTRING(dotat, "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $");
-#endif
-#ifdef __FBSDID
-__FBSDID("$FreeBSD$");
-#endif
-
-/*
- * unifdef - remove ifdef'ed lines
- *
* Wishlist:
* provide an option which will append the name of the
* appropriate symbol after #else's and #endif's
@@ -56,8 +43,12 @@ __FBSDID("$FreeBSD$");
* also make it possible to handle all "dodgy" directives correctly.
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
@@ -65,6 +56,13 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
+#ifdef __IDSTRING
+__IDSTRING(dotat, "$dotat: unifdef/unifdef.c,v 1.193 2010/01/19 18:03:02 fanf2 Exp $");
+#endif
+#ifdef __FBSDID
+__FBSDID("$FreeBSD$");
+#endif
+
/* types of input lines: */
typedef enum {
LT_TRUEI, /* a true #if with ignore flag */
@@ -157,6 +155,11 @@ static char const * const linestate_name[] = {
#define EDITSLOP 10
/*
+ * For temporary filenames
+ */
+#define TEMPLATE "unifdef.XXXXXX"
+
+/*
* Globals.
*/
@@ -179,6 +182,10 @@ static int nsyms; /* number of symbols */
static FILE *input; /* input file pointer */
static const char *filename; /* input file name */
static int linenum; /* current line number */
+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 char tline[MAXLINE+EDITSLOP];/* input buffer plus space */
static char *keyword; /* used for editing #elif's */
@@ -197,6 +204,7 @@ static bool constexpr; /* constant #if expression */
static int exitstat; /* program exit status */
static void addsym(bool, bool, char *);
+static void closeout(void);
static void debug(const char *, ...);
static void done(void);
static void error(const char *);
@@ -227,7 +235,7 @@ main(int argc, char *argv[])
{
int opt;
- while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
+ while ((opt = getopt(argc, argv, "i:D:U:I:o:BbcdeKklnst")) != -1)
switch (opt) {
case 'i': /* treat stuff controlled by these symbols as text */
/*
@@ -277,6 +285,9 @@ main(int argc, char *argv[])
case 'n': /* add #line directive after deleted lines */
lnnum = true;
break;
+ case 'o': /* output to a file */
+ ofilename = optarg;
+ break;
case 's': /* only output list of symbols that control #ifs */
symlist = true;
break;
@@ -301,6 +312,43 @@ main(int argc, char *argv[])
filename = "[stdin]";
input = stdin;
}
+ if (ofilename == NULL) {
+ output = stdout;
+ } else {
+ struct stat ist, ost;
+ memset(&ist, 0, sizeof(ist));
+ memset(&ost, 0, sizeof(ost));
+
+ if (fstat(fileno(input), &ist) != 0)
+ err(2, "can't fstat %s", filename);
+ if (stat(ofilename, &ost) != 0 && errno != ENOENT)
+ warn("can't stat %s", ofilename);
+
+ 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,
+ dirsep - ofilename, ofilename);
+ else
+ strlcpy(tempname, TEMPLATE, sizeof(tempname));
+ ofd = mkstemp(tempname);
+ if (ofd != -1)
+ output = fdopen(ofd, "w+");
+ if (output == NULL)
+ err(2, "can't create temporary file");
+ fchmod(ofd, ist.st_mode & ACCESSPERMS);
+ } else {
+ output = fopen(ofilename, "w");
+ if (output == NULL)
+ err(2, "can't open %s", ofilename);
+ }
+ }
process();
abort(); /* bug */
}
@@ -435,13 +483,6 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
* State machine utility functions
*/
static void
-done(void)
-{
- if (incomment)
- error("EOF in comment");
- exit(exitstat);
-}
-static void
ignoreoff(void)
{
if (depth == 0)
@@ -498,13 +539,13 @@ flushline(bool keep)
} else {
if (lnnum && delcount > 0)
printf("#line %d\n", linenum);
- fputs(tline, stdout);
+ fputs(tline, output);
delcount = 0;
blankmax = blankcount = blankline ? blankcount + 1 : 0;
}
} else {
if (lnblank)
- putc('\n', stdout);
+ putc('\n', output);
exitstat = 1;
delcount += 1;
blankcount = 0;
@@ -533,6 +574,40 @@ process(void)
}
/*
+ * Flush the output and handle errors.
+ */
+static void
+closeout(void)
+{
+ if (fclose(output) == EOF) {
+ warn("couldn't write to output");
+ if (overwriting) {
+ unlink(tempname);
+ errx(2, "%s unchanged", filename);
+ } else {
+ exit(2);
+ }
+ }
+}
+
+/*
+ * Clean up and exit.
+ */
+static void
+done(void)
+{
+ if (incomment)
+ error("EOF in comment");
+ closeout();
+ if (overwriting && rename(tempname, filename) == -1) {
+ warn("couldn't rename temporary file");
+ unlink(tempname);
+ errx(2, "%s unchanged", filename);
+ }
+ exit(exitstat);
+}
+
+/*
* Parse a line and determine its type. We keep the preprocessor line
* parser state between calls in the global variable linestate, with
* help from skipcomment().
@@ -1097,5 +1172,6 @@ error(const char *msg)
else
warnx("%s: %d: %s (#if line %d depth %d)",
filename, linenum, msg, stifline[depth], depth);
+ closeout();
errx(2, "output may be truncated");
}
OpenPOWER on IntegriCloud