diff --git a/usr.bin/unifdef/unifdef.1 b/usr.bin/unifdef/unifdef.1 index cd6ef6f980cd..fb75d851c1b7 100644 --- a/usr.bin/unifdef/unifdef.1 +++ b/usr.bin/unifdef/unifdef.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: unifdef.1,v 1.11 2003/11/11 13:48:50 wiz Exp $ +.\" $NetBSD: unifdef.1,v 1.12 2009/06/11 03:16:34 ginsbach Exp $ .\" .\" Copyright (c) 1985, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -65,7 +65,7 @@ .\" $dotat: things/unifdef.1,v 1.45 2003/01/20 14:37:08 fanf2 Exp $ .\" $FreeBSD: src/usr.bin/unifdef/unifdef.1,v 1.19 2003/01/20 12:41:41 fanf Exp $ .\" -.Dd September 24, 2002 +.Dd June 5, 2009 .Dt UNIFDEF 1 .Os .Sh NAME @@ -81,6 +81,7 @@ .Op Fl iD Ns Ar sym Ns Op = Ns Ar val .Op Fl iU Ns Ar sym .Ar ... +.Op Fl o Ar output .Op Ar file .Nm unifdefall .Op Fl I Ns Ar path @@ -212,6 +213,11 @@ It would be rude to strip them out, just as it would be for normal comments. .It Fl l Replace removed lines with blank lines instead of deleting them. +.It Fl o Ar output +The argument given is the name of an +.Ar output +file to be used instead of the standard output. +This file can be the same as the input file. .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 023ef6810957..1cce7d9ba922 100644 --- a/usr.bin/unifdef/unifdef.c +++ b/usr.bin/unifdef/unifdef.c @@ -1,4 +1,4 @@ -/* $NetBSD: unifdef.c,v 1.13 2006/04/30 23:56:42 christos Exp $ */ +/* $NetBSD: unifdef.c,v 1.14 2009/06/11 03:16:34 ginsbach Exp $ */ /* * Copyright (c) 1985, 1993 @@ -77,7 +77,7 @@ static const char copyright[] = #endif #ifdef __IDSTRING __IDSTRING(Berkeley, "@(#)unifdef.c 8.1 (Berkeley) 6/6/93"); -__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.13 2006/04/30 23:56:42 christos Exp $"); +__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.14 2009/06/11 03:16:34 ginsbach Exp $"); __IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.161 2003/07/01 15:32:48 fanf2 Exp $"); #endif #endif /* not lint */ @@ -102,12 +102,16 @@ __FBSDID("$FreeBSD: src/usr.bin/unifdef/unifdef.c,v 1.18 2003/07/01 15:30:43 fan #include #include +#include #include #include #include #include #include +#include +#include + #include "stdbool.h" /* types of input lines: */ @@ -216,8 +220,12 @@ static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */ static int nsyms; /* number of symbols */ static FILE *input; /* input file pointer */ +static FILE *output; /* output file pointer */ static const char *filename; /* input file name */ +static char *ofilename; /* output file name */ +static char tmpname[MAXPATHLEN]; /* used when overwriting */ static int linenum; /* current line number */ +static int overwriting; /* output overwrites input */ static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ static char *keyword; /* used for editing #elif's */ @@ -260,8 +268,9 @@ int main(int argc, char *argv[]) { int opt; + struct stat isb, osb; - while ((opt = getopt(argc, argv, "i:D:U:I:cdeklst")) != -1) + while ((opt = getopt(argc, argv, "i:D:U:I:o:cdeklst")) != -1) switch (opt) { case 'i': /* treat stuff controlled by these symbols as text */ /* @@ -301,6 +310,9 @@ main(int argc, char *argv[]) case 'l': /* blank deleted lines instead of omitting them */ lnblank = true; break; + case 'o': /* output to a file */ + ofilename = optarg; + break; case 's': /* only output list of symbols that control #ifs */ symlist = true; break; @@ -327,6 +339,32 @@ main(int argc, char *argv[]) filename = "[stdin]"; input = stdin; } + if (ofilename == NULL) { + output = stdout; + } else { + if (stat(ofilename, &osb) != 0) + err(2, "can't stat %s", ofilename); + if (fstat(fileno(input), &isb) != 0) + err(2, "can't fstat %s", filename); + + overwriting = (osb.st_dev == isb.st_dev && + osb.st_ino == osb.st_ino); + if (overwriting) { + int ofd; + + snprintf(tmpname, sizeof(tmpname), "%s/unifdef.XXXXXX", + dirname(ofilename)); + if ((ofd = mkstemp(tmpname)) != -1) + output = fdopen(ofd, "w+"); + if (output == NULL) + err(2, "can't create temporary file"); + fchmod(ofd, isb.st_mode & ACCESSPERMS); + } else { + output = fopen(ofilename, "w"); + if (output == NULL) + err(2, "can't open %s", ofilename); + } + } process(); abort(); /* bug */ } @@ -334,7 +372,7 @@ main(int argc, char *argv[]) static void usage(void) { - fprintf(stderr, "usage: unifdef [-cdeklst]" + fprintf(stderr, "usage: unifdef [-cdeklst] [-o output]" " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); exit(2); } @@ -465,6 +503,16 @@ done(void) { if (incomment) error("EOF in comment"); + if (fclose(output)) { + if (overwriting) { + unlink(tmpname); + errx(2, "%s unchanged", filename); + } + } + if (overwriting && rename(tmpname, filename)) { + unlink(tmpname); + errx(2, "%s unchanged", filename); + } exit(exitstat); } static void @@ -506,10 +554,10 @@ flushline(bool keep) if (symlist) return; if (keep ^ complement) - fputs(tline, stdout); + fputs(tline, output); else { if (lnblank) - putc('\n', stdout); + putc('\n', output); exitstat = 1; } } @@ -983,5 +1031,10 @@ error(const char *msg) else warnx("%s: %d: %s (#if line %d depth %d)", filename, linenum, msg, stifline[depth], depth); + fclose(output); + if (overwriting) { + unlink(tmpname); + errx(2, "%s unchanged", filename); + } errx(2, "output may be truncated"); }