1.\" $OpenBSD: unifdef.1,v 1.23 2015/02/17 16:29:16 bentley Exp $ 2.\" Copyright (c) 1985, 1991, 1993 3.\" The Regents of the University of California. All rights reserved. 4.\" Copyright (c) 2002 - 2013 Tony Finch <dot@dotat.at>. All rights reserved. 5.\" 6.\" This code is derived from software contributed to Berkeley by 7.\" Dave Yost. It was rewritten to support ANSI C by Tony Finch. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 3. Neither the name of the University nor the names of its contributors 18.\" may be used to endorse or promote products derived from this software 19.\" without specific prior written permission. 20.\" 21.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" SUCH DAMAGE. 32.\" 33.Dd $Mdocdate: February 17 2015 $ 34.Dt UNIFDEF 1 35.Os 36.Sh NAME 37.Nm unifdef 38.Nd remove preprocessor conditionals from code 39.Sh SYNOPSIS 40.Nm 41.Op Fl BbcdehKkmnSstV 42.Op Fl [i]D Ns Ar sym Ns Op = Ns Ar val 43.Op Fl [i]U Ns Ar sym 44.Op Fl f Ar defile 45.Op Fl M Ar backext 46.Op Fl o Ar outfile 47.Op Fl x Cm 0 | 1 | 2 48.Ar 49.Sh DESCRIPTION 50The 51.Nm 52utility selectively processes conditional 53.Xr cpp 1 54directives. 55It removes from a file 56both the directives 57and any additional text that they specify should be removed, 58while otherwise leaving the file alone. 59.Pp 60The 61.Nm 62utility acts on 63.Ic #if , #ifdef , #ifndef , 64.Ic #elif , #else , 65and 66.Ic #endif 67lines, 68using macros specified in 69.Fl D 70and 71.Fl U 72command line options or in 73.Fl f 74definition files. 75A directive is processed 76if the macro specifications are sufficient to provide 77a definite value for its control expression. 78If the result is false, 79the directive and the following lines under its control are removed. 80If the result is true, 81only the directive is removed. 82An 83.Ic #ifdef 84or 85.Ic #ifndef 86directive is passed through unchanged 87if its controlling macro is not specified. 88Any 89.Ic #if 90or 91.Ic #elif 92control expression that has an unknown value or that 93.Nm 94cannot parse is passed through unchanged. 95By default, 96.Nm 97ignores 98.Ic #if 99and 100.Ic #elif 101lines with constant expressions; 102it can be told to process them by specifying the 103.Fl k 104flag on the command line. 105.Pp 106It understands a commonly-used subset 107of the expression syntax for 108.Ic #if 109and 110.Ic #elif 111lines: 112integer constants, 113integer values of macros defined on the command line, 114the 115.Fn defined 116operator, 117the operators 118.Ic \&! , < , > , 119.Ic <= , >= , == , != , 120.Ic && , || , 121and parenthesized expressions. 122A kind of 123.Dq "short circuit" 124evaluation is used for the 125.Ic && 126operator: 127if either operand is definitely false then the result is false, 128even if the value of the other operand is unknown. 129Similarly, 130if either operand of 131.Ic || 132is definitely true then the result is true. 133.Pp 134When evaluating an expression, 135.Nm 136does not expand macros first. 137The value of a macro must be a simple number, 138not an expression. 139A limited form of indirection is allowed, 140where one macro's value is the name of another. 141.Pp 142In most cases, 143.Nm 144does not distinguish between object-like macros 145(without arguments) and function-like macros (with arguments). 146A function-like macro invocation can appear in 147.Ic #if 148and 149.Ic #elif 150control expressions. 151If the macro is not explicitly defined, 152or is defined with the 153.Fl D 154flag on the command-line, 155or with 156.Ic #define 157in a 158.Fl f 159definition file, 160its arguments are ignored. 161If a macro is explicitly undefined on the command line with the 162.Fl U 163flag, 164or with 165.Ic #undef 166in a 167.Fl f 168definition file, 169it may not have any arguments since this leads to a syntax error. 170.Pp 171The 172.Nm 173utility understands just enough about C 174to know when one of the directives is inactive 175because it is inside 176a comment, 177or affected by a backslash-continued line. 178It spots unusually-formatted preprocessor directives 179and knows when the layout is too odd for it to handle. 180.Pp 181The options are as follows: 182.Pp 183.Bl -tag -width indent -compact 184.It Fl B 185Compress blank lines around a deleted section. 186Mutually exclusive with the 187.Fl b 188option. 189.Pp 190.It Fl b 191Replace removed lines with blank lines 192instead of deleting them. 193Mutually exclusive with the 194.Fl B 195option. 196.Pp 197.It Fl c 198Complement. 199That is, lines that would have been removed or blanked 200are retained and vice versa. 201.Pp 202.Sm off 203.It Xo 204.Fl D Ar sym 205.Op = Ar val 206.Xc 207.Sm on 208.It Fl U Ns Ar sym 209Specify that a macro is defined 210.Pq Fl D 211to a given value, 212to 1 if no value is given, 213or undefined 214.Pq Fl U . 215.Pp 216If the same macro appears in more than one argument, 217the last occurrence dominates. 218.Pp 219.It Fl d 220Turn on printing of debugging messages. 221.Pp 222.It Fl e 223By default, 224.Nm 225will report an error if it needs to remove 226a preprocessor directive that spans more than one line, 227for example, if it has a multi-line 228comment hanging off its right hand end. 229The 230.Fl e 231flag makes it ignore the line instead. 232.Pp 233.It Fl f Ar defile 234The file 235.Ar defile 236contains 237.Ic #define 238and 239.Ic #undef 240preprocessor directives, 241which have the same effect as the corresponding 242.Fl D 243and 244.Fl U 245command line arguments. 246Multiple 247.Fl f 248arguments can be given and mixed with 249.Fl D 250and 251.Fl U 252arguments; 253later options override earlier ones. 254.Pp 255Each directive must be on a single line. 256Object-like macro definitions (without arguments) 257are set to the given value. 258Function-like macro definitions (with arguments) 259are treated as if they are set to 1. 260.Pp 261.Sm off 262.It Xo 263.Fl iD Ar sym 264.Op = Ar val 265.Xc 266.Sm on 267.It Fl iU Ns Ar sym 268Ignore 269.Ic #ifdef Ns s . 270If C code uses 271.Ic #ifdef Ns s 272to delimit non-C lines, 273such as comments 274or code which is under construction, 275this tells 276.Nm 277which symbols are used for that purpose so that it will not try to parse 278comments and line continuations 279inside those 280.Ic #ifdef Ns s . 281.Pp 282If the same macro appears in more than one argument, 283the last occurrence dominates. 284.Pp 285.It Fl h 286Print help. 287.Pp 288.It Fl K 289Always treat the result of 290.Ic && 291and 292.Ic || 293operators as unknown if either operand is unknown, 294instead of short-circuiting when unknown operands can't affect the result. 295This option is for compatibility with older versions of 296.Nm . 297.Pp 298.It Fl k 299Process 300.Ic #if 301and 302.Ic #elif 303lines with constant expressions. 304By default, sections controlled by such lines are passed through unchanged 305because they typically start 306.Dq Li "#if 0" 307and are used as a kind of comment to sketch out future or past development. 308It would be rude to strip them out, just as it would be for normal comments. 309.Pp 310.It Fl M Ar backext 311Modify input files in place, and keep backups of the original files by 312appending the 313.Ar backext 314to the input filenames. 315.Pp 316.It Fl m 317Modify one or more input files in place. 318.Pp 319.It Fl n 320Add 321.Li #line 322directives to the output following any deleted lines, 323so that errors produced when compiling the output file correspond to 324line numbers in the input file. 325.Pp 326.It Fl o Ar outfile 327Write output to the file 328.Ar outfile 329instead of the standard output when processing a single file. 330.Pp 331.It Fl S 332Like the 333.Fl s 334option, but the nesting depth of each macro is also printed. 335This is useful for working out the number of possible combinations 336of interdependent defined/undefined macros. 337.Pp 338.It Fl s 339Instead of processing an input file as usual, 340this option causes 341.Nm 342to produce a list of macros that are used in 343preprocessor directive controlling expressions. 344.Pp 345.It Fl t 346Disables parsing for C strings, comments, 347and line continuations, 348which is useful 349for plain text. 350This is a blanket version of the 351.Fl iD 352and 353.Fl iU 354flags. 355.Pp 356.It Fl V 357Print version details. 358.Pp 359.It Fl x Cm 0 | 1 | 2 360Set exit status mode to zero, one, or two. 361See the 362.Sx EXIT STATUS 363section below for details. 364.El 365.Pp 366The 367.Nm 368utility takes its input from 369.Em stdin 370if there are no 371.Ar file 372arguments. 373The 374.Fl m 375or 376.Fl M 377options must be used if there are multiple input files. 378A dash 379.Pq - 380specifies input from stdin or output to stdout. 381.Pp 382The 383.Nm 384utility works nicely with the 385.Fl D 386option of 387.Xr diff 1 . 388.Sh EXIT STATUS 389In normal usage the 390.Nm 391utility's exit status depends on the mode set using the 392.Fl x 393option. 394.Pp 395If the exit mode is zero (the default) then 396.Nm 397exits with status 0 if the output is an exact copy of the input, 398or with status 1 if the output differs. 399.Pp 400If the exit mode is one, 401.Nm 402exits with status 1 if the output is unmodified 403or 0 if it differs. 404.Pp 405If the exit mode is two, 406.Nm 407exits with status zero in both cases. 408.Pp 409In all exit modes, 410.Nm 411exits with status 2 if there is an error. 412.Pp 413The exit status is 0 if the 414.Fl h 415or 416.Fl V 417command line options are given. 418.Sh DIAGNOSTICS 419.Bl -item 420.It 421Too many levels of nesting. 422.It 423Inappropriate 424.Ic #elif , 425.Ic #else 426or 427.Ic #endif . 428.It 429Obfuscated preprocessor control line. 430.It 431Premature 432.Tn EOF 433(with the line number of the most recent unterminated 434.Ic #if ) . 435.It 436.Tn EOF 437in comment. 438.El 439.Sh SEE ALSO 440.Xr cpp 1 , 441.Xr diff 1 442.Pp 443The unifdef home page is 444.Pa http://dotat.at/prog/unifdef 445.Sh HISTORY 446The 447.Nm 448command appeared in 449.Bx 2.9 . 450.Tn ANSI\~C 451support was added in 452.Fx 4.7 . 453.Sh AUTHORS 454The original implementation was written by 455.An Dave Yost Aq Mt Dave@Yost.com . 456.An Tony Finch Aq Mt dot@dotat.at 457rewrote it to support 458.Tn ANSI\~C . 459.Sh BUGS 460Expression evaluation is very limited. 461.Pp 462Handling one line at a time means 463preprocessor directives split across more than one physical line 464(because of comments or backslash-newline) 465cannot be handled in every situation. 466.Pp 467Trigraphs are not recognized. 468.Pp 469There is no support for macros with different definitions at 470different points in the source file. 471.Pp 472The text-mode and ignore functionality does not correspond to modern 473.Xr cpp 1 474behaviour. 475