From owner-svn-src-all@FreeBSD.ORG Tue Jan 19 18:13:54 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 896C01065694; Tue, 19 Jan 2010 18:13:54 +0000 (UTC) (envelope-from fanf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 77D3D8FC0A; Tue, 19 Jan 2010 18:13:54 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0JIDshs068345; Tue, 19 Jan 2010 18:13:54 GMT (envelope-from fanf@svn.freebsd.org) Received: (from fanf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JIDsPs068342; Tue, 19 Jan 2010 18:13:54 GMT (envelope-from fanf@svn.freebsd.org) Message-Id: <201001191813.o0JIDsPs068342@svn.freebsd.org> From: Tony Finch Date: Tue, 19 Jan 2010 18:13:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202635 - head/usr.bin/unifdef X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Jan 2010 18:13:54 -0000 Author: fanf Date: Tue Jan 19 18:13:54 2010 New Revision: 202635 URL: http://svn.freebsd.org/changeset/base/202635 Log: 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 Modified: head/usr.bin/unifdef/unifdef.1 head/usr.bin/unifdef/unifdef.c Modified: head/usr.bin/unifdef/unifdef.1 ============================================================================== --- head/usr.bin/unifdef/unifdef.1 Tue Jan 19 17:20:34 2010 (r202634) +++ head/usr.bin/unifdef/unifdef.1 Tue Jan 19 18:13:54 2010 (r202635) @@ -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 . All rights reserved. +.\" Copyright (c) 2002 - 2010 Tony Finch . 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 d 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 Modified: head/usr.bin/unifdef/unifdef.c ============================================================================== --- head/usr.bin/unifdef/unifdef.c Tue Jan 19 17:20:34 2010 (r202634) +++ head/usr.bin/unifdef/unifdef.c Tue Jan 19 18:13:54 2010 (r202635) @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 - 2009 Tony Finch + * Copyright (c) 2002 - 2010 Tony Finch * * 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 - -#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 +#include + #include #include +#include #include #include #include @@ -65,6 +56,13 @@ __FBSDID("$FreeBSD$"); #include #include +#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; /* numb 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; /* c 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_C * 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"); }