1.\" $OpenBSD: unifdef.1,v 1.31 2023/08/13 02:20:23 jsg 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: August 13 2023 $ 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 Oo Cm i Oc Ns Cm D Ns Ar sym Ns Op = Ns Ar val 43.Op Fl Oo Cm i Oc Ns Cm 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. 315If a zero length 316.Ar backext 317is given, no backup will be saved. 318.Pp 319.It Fl m 320Modify one or more input files in place. 321.Pp 322.It Fl n 323Add 324.Li #line 325directives to the output following any deleted lines, 326so that errors produced when compiling the output file correspond to 327line numbers in the input file. 328.Pp 329.It Fl o Ar outfile 330Write output to the file 331.Ar outfile 332instead of the standard output when processing a single file. 333.Pp 334.It Fl S 335Like the 336.Fl s 337option, but the nesting depth of each macro is also printed. 338This is useful for working out the number of possible combinations 339of interdependent defined/undefined macros. 340.Pp 341.It Fl s 342Instead of processing an input file as usual, 343this option causes 344.Nm 345to produce a list of macros that are used in 346preprocessor directive controlling expressions. 347.Pp 348.It Fl t 349Disables parsing for C strings, comments, 350and line continuations, 351which is useful 352for plain text. 353This is a blanket version of the 354.Fl iD 355and 356.Fl iU 357flags. 358.Pp 359.It Fl V 360Print version details. 361.Pp 362.It Fl x Cm 0 | 1 | 2 363Set exit status mode to zero, one, or two. 364See the 365.Sx EXIT STATUS 366section below for details. 367.El 368.Pp 369The 370.Nm 371utility takes its input from 372.Em stdin 373if there are no 374.Ar file 375arguments. 376The 377.Fl m 378or 379.Fl M 380options must be used if there are multiple input files. 381A dash 382.Pq - 383specifies input from stdin or output to stdout. 384.Pp 385The 386.Nm 387utility works nicely with the 388.Fl D 389option of 390.Xr diff 1 . 391.Sh EXIT STATUS 392In normal usage the 393.Nm 394utility's exit status depends on the mode set using the 395.Fl x 396option. 397.Pp 398If the exit mode is zero (the default) then 399.Nm 400exits with status 0 if the output is an exact copy of the input, 401or with status 1 if the output differs. 402.Pp 403If the exit mode is one, 404.Nm 405exits with status 1 if the output is unmodified 406or 0 if it differs. 407.Pp 408If the exit mode is two, 409.Nm 410exits with status zero in both cases. 411.Pp 412In all exit modes, 413.Nm 414exits with status 2 if there is an error. 415.Pp 416The exit status is 0 if the 417.Fl h 418or 419.Fl V 420command line options are given. 421.Sh DIAGNOSTICS 422.Bl -item 423.It 424.Tn EOF 425in comment 426.It 427Inappropriate 428.Ic #elif , 429.Ic #else 430or 431.Ic #endif 432.It 433Obfuscated preprocessor control line 434.It 435Premature 436.Tn EOF 437(with the line number of the most recent unterminated 438.Ic #if ) 439.It 440Too many levels of nesting 441.El 442.Sh SEE ALSO 443.Xr cpp 1 , 444.Xr diff 1 445.Pp 446The unifdef home page is 447.Lk https://dotat.at/prog/unifdef . 448.Sh HISTORY 449The 450.Nm 451command appeared in 452.Bx 4.1c . 453.Tn ANSI\~C 454support was added in 455.Fx 4.7 . 456.Sh AUTHORS 457The original implementation was written by 458.An Dave Yost Aq Mt Dave@Yost.com . 459.An Tony Finch Aq Mt dot@dotat.at 460rewrote it to support 461.Tn ANSI\~C . 462.Sh BUGS 463Expression evaluation is very limited. 464.Pp 465Handling one line at a time means 466preprocessor directives split across more than one physical line 467(because of comments or backslash-newline) 468cannot be handled in every situation. 469.Pp 470Trigraphs are not recognized. 471.Pp 472There is no support for macros with different definitions at 473different points in the source file. 474.Pp 475The text-mode and ignore functionality does not correspond to modern 476.Xr cpp 1 477behaviour. 478