1#!/bin/awk -f 2 3# scripts/options.awk - library build configuration control 4# 5# Copyright (c) 1998-2014 Glenn Randers-Pehrson 6# 7# This code is released under the libpng license. 8# For conditions of distribution and use, see the disclaimer 9# and license in png.h 10 11# The output of this script is written to the file given by 12# the variable 'out'. The script is run twice, once with 13# an intermediate output file, 'options.tmp' then again on 14# that file to produce the final output: 15# 16# awk -f scripts/options.awk out=options.tmp scripts/options.dfa 1>&2 17# awk -f scripts/options.awk out=options.dfn options.tmp 1>&2 18# 19# Some options may be specified on the command line: 20# 21# deb=1 Causes debugging to be output 22# logunsupported=1 Causes all options to be recorded in the output 23# everything=off Causes all options to be disabled by default 24# everything=on Causes all options to be enabled by default 25# 26# If awk fails on your platform, try nawk instead. 27# 28# These options may also be specified in the original input file (and 29# are copied to the preprocessed file). 30 31BEGIN{ 32 out="" # intermediate, preprocessed, file 33 pre=-1 # preprocess (first line) 34 version="libpng version unknown" # version information 35 version_file="" # where to find the version 36 err=0 # in-line exit sets this 37 # The following definitions prevent the C preprocessor noticing the lines 38 # that will be in the final output file. Some C preprocessors tokenise 39 # the lines, for example by inserting spaces around operators, and all 40 # C preprocessors notice lines that start with '#', most remove comments. 41 # The technique adopted here is to make the final output lines into 42 # C strings (enclosed in double quotes), preceded by PNG_DFN. As a 43 # consequence the output cannot contain a 'raw' double quote - instead put 44 # @' in, this will be replaced by a single " afterward. See the parser 45 # script dfn.awk for more capabilities (not required here). Note that if 46 # you need a " in a 'setting' in pnglibconf.dfa it must also be @'! 47 dq="@'" # For a single double quote 48 start=" PNG_DFN \"" # Start stuff to output (can't contain a "!) 49 end="\" " # End stuff to output 50 subs="@\" " # Substitute start (substitute a C macro) 51 sube=" \"@" # Substitute end 52 comment=start "/*" # Comment start 53 cend="*/" end # Comment end 54 def=start "#define PNG_" # Arbitrary define 55 sup="_SUPPORTED" end # end supported option 56 und=comment "#undef PNG_" # Unsupported option 57 une="_SUPPORTED" cend # end unsupported option 58 error=start "ERROR:" # error message, terminate with 'end' 59 60 # Variables 61 deb=0 # debug - set on command line 62 everything="" # do not override defaults 63 logunsupported=0 # write unsupported options too 64 65 # Precreate arrays 66 # for each option: 67 option[""] = "" # list of all options: default enabled/disabled 68 done[""] = 1 # marks option as having been output 69 requires[""] = "" # requires by option 70 iffs[""] = "" # if by option 71 enabledby[""] = "" # options that enable it by option 72 sets[""] = "" # settings set by each option 73 setval[""] = "" # value to set (indexed: 'option sets[option]') 74 # for each setting: 75 setting[""] = "" # requires by setting 76 defaults[""] = "" # used for a defaulted value 77 doneset[""] = 1 # marks setting as having been output 78 r[""] = "" # Temporary array 79 80 # For decorating the output file 81 protect = "" 82} 83 84# The output file must be specified before any input: 85out == "" { 86 print "out=output.file must be given on the command line" 87 err = 1 88 exit 1 89} 90 91# The very first line indicates whether we are reading pre-processed 92# input or not, this must come *first* because 'PREPROCESSED' needs 93# to be the very first line in the temporary file. 94pre == -1{ 95 if ($0 == "PREPROCESSED") { 96 pre = 0 97 next 98 } else { 99 pre = 1 100 print "PREPROCESSED" >out 101 # And fall through to continue processing 102 } 103} 104 105# While pre-processing if version is set to "search" look for a version string 106# in the following file. 107pre && version == "search" && version_file == ""{ 108 version_file = FILENAME 109} 110 111pre && version == "search" && version_file != FILENAME{ 112 print "version string not found in", version_file 113 err = 1 114 exit 1 115} 116 117pre && version == "search" && $0 ~ /^ \* libpng version/{ 118 version = substr($0, 4) 119 print "version =", version >out 120 next 121} 122 123pre && FILENAME == version_file{ 124 next 125} 126 127# variable=value 128# Sets the given variable to the given value (the syntax is fairly 129# free form, except for deb (you are expected to understand how to 130# set the debug variable...) 131# 132# This happens before the check on 'pre' below skips most of the 133# rest of the actions, so the variable settings happen during 134# preprocessing but are recorded in the END action too. This 135# allows them to be set on the command line too. 136$0 ~ /^[ ]*version[ ]*=/{ 137 sub(/^[ ]*version[ ]*=[ ]*/, "") 138 version = $0 139 next 140} 141$0 ~ /^[ ]*everything[ =]*off[ ]*$/{ 142 everything = "off" 143 next 144} 145$0 ~ /^[ ]*everything[ =]*on[ ]*$/{ 146 everything = "on" 147 next 148} 149$0 ~ /^[ ]*logunsupported[ =]*0[ ]*$/{ 150 logunsupported = 0 151 next 152} 153$0 ~ /^[ ]*logunsupported[ =]*1[ ]*$/{ 154 logunsupported = 1 155 next 156} 157$1 == "deb" && $2 == "=" && NF == 3{ 158 deb = $3 159 next 160} 161 162# Preprocessing - this just copies the input file with lines 163# that need preprocessing (just chunk at present) expanded 164# The bare "pre" instead of "pre != 0" crashes under Sunos awk 165pre && $1 != "chunk"{ 166 print >out 167 next 168} 169 170# The first characters of the line determine how it is processed, 171# leading spaces are ignored. In general tokens that are not 172# keywords are the names of options. An option 'name' is 173# controlled by the definition of the corresponding macros: 174# 175# PNG_name_SUPPORTED The option is turned on 176# PNG_NO_name 177# PNG_NO_name_SUPPORTED If the first macro is not defined 178# either of these will turn the option off 179# 180# If none of these macros are defined the option is turned on, unless 181# the keyword 'off' is given in a line relating to the option. The 182# keyword 'on' can also be given, but it will be ignored (since it is 183# the default.) 184# 185# In the syntax below a 'name' is indicated by "NAME", other macro 186# values are indicated by "MACRO", as with "NAME" the leading "PNG_" 187# is omitted, but in this case the "NO_" prefix and the "_SUPPORTED" 188# suffix are never used. 189# 190# Each line is introduced by a keyword - the first non-space characters 191# on the line. A line starting with a '#' is a comment - it is totally 192# ignored. Keywords are as follows, a NAME, is simply a macro name 193# without the leading PNG_, PNG_NO_ or the trailing _SUPPORTED. 194 195$1 ~ /^#/ || $0 ~ /^[ ]*$/{ 196 next 197} 198 199# com <comment> 200# The whole line is placed in the output file as a comment with 201# the preceding 'com' removed 202$1 == "com"{ 203 if (NF > 1) { 204 # sub(/^[ ]*com[ ]*/, "") 205 $1 = "" 206 print comment $0, cend >out 207 } else 208 print start end >out 209 next 210} 211 212# version 213# Inserts a version comment 214$1 == "version" && NF == 1{ 215 if (version == "") { 216 print "ERROR: no version string set" 217 err = 1 # prevent END{} running 218 exit 1 219 } 220 221 print comment, version, cend >out 222 next 223} 224 225# file output input protect 226# Informational: the official name of the input file (without 227# make generated local directories), the official name of the 228# output file and, if required, a name to use in a protection 229# macro for the contents. 230$1 == "file" && NF >= 2{ 231 print comment, $2, cend >out 232 print comment, "Machine generated file: DO NOT EDIT", cend >out 233 if (NF >= 3) 234 print comment, "Derived from:", $3, cend >out 235 protect = $4 236 if (protect != "") { 237 print start "#ifndef", protect end >out 238 print start "#define", protect end >out 239 } 240 next 241} 242 243# option NAME ( (requires|enables|if) NAME* | on | off | disabled | 244# sets SETTING VALUE+ )* 245# 246# Declares an option 'NAME' and describes its default setting (disabled) 247# and its relationship to other options. The option is disabled 248# unless *all* the options listed after 'requires' are set and at 249# least one of the options listed after 'if' is set. If the 250# option is set then it turns on all the options listed after 'enables'. 251# 252# Note that "enables" takes priority over the required/if/disabled/off 253# setting of the target option. 254# 255# The definition file may list an option as 'disabled': off by default, 256# otherwise the option is enabled: on by default. A later (and it must 257# be later) entry may turn an option on or off explicitly. 258 259$1 == "option" && NF >= 2{ 260 opt = $2 261 sub(/,$/,"",opt) 262 onoff = option[opt] # records current (and the default is "", enabled) 263 key = "" 264 istart = 3 265 do { 266 if (istart == 1) { # continuation line 267 val = getline 268 269 if (val != 1) { # error reading it 270 if (val == 0) 271 print "option", opt ": ERROR: missing continuation line" 272 else 273 print "option", opt ": ERROR: error reading continuation line" 274 275 # This is a hard error 276 err = 1 # prevent END{} running 277 exit 1 278 } 279 } 280 281 for (i=istart; i<=NF; ++i) { 282 val=$(i) 283 sub(/,$/,"",val) 284 if (val == "on" || val == "off" || val == "disabled" || val =="enabled") { 285 key = "" 286 if (onoff != val) { 287 # on or off can zap disabled or enabled: 288 if (onoff == "" || (onoff == "disabled" || onoff == "enabled") && 289 (val == "on" || val == "off")) { 290 # It's easy to mis-spell the option when turning it 291 # on or off, so warn about it here: 292 if (onoff == "" && (val == "on" || val == "off")) { 293 print "option", opt ": ERROR: turning unrecognized option", val 294 # For the moment error out - it is safer 295 err = 1 # prevent END{} running 296 exit 1 297 } 298 onoff = val 299 } else { 300 # Print a message, otherwise the error 301 # below is incomprehensible 302 print "option", opt ": currently", onoff ": attempt to turn", val 303 break 304 } 305 } 306 } else if (val == "requires" || val == "if" || val == "enables" || val =="sets") { 307 key = val 308 } else if (key == "requires") { 309 requires[opt] = requires[opt] " " val 310 } else if (key == "if") { 311 iffs[opt] = iffs[opt] " " val 312 } else if (key == "enables") { 313 enabledby[val] = enabledby[val] " " opt 314 } else if (key == "sets") { 315 sets[opt] = sets[opt] " " val 316 key = "setval" 317 set = val 318 } else if (key == "setval") { 319 setval[opt " " set] = setval[opt " " set] " " val 320 } else 321 break # bad line format 322 } 323 324 istart = 1 325 } while (i > NF && $0 ~ /,$/) 326 327 if (i > NF) { 328 # Set the option, defaulting to 'enabled' 329 if (onoff == "") onoff = "enabled" 330 option[opt] = onoff 331 next 332 } 333 # Else fall through to the error handler 334} 335 336# chunk NAME [requires OPT] [enables LIST] [on|off|disabled] 337# Expands to the 'option' settings appropriate to the reading and 338# writing of an ancillary PNG chunk 'NAME': 339# 340# option READ_NAME requires READ_ANCILLARY_CHUNKS [READ_OPT] 341# option READ_NAME enables NAME LIST 342# [option READ_NAME off] 343# option WRITE_NAME requires WRITE_ANCILLARY_CHUNKS [WRITE_OPT] 344# option WRITE_NAME enables NAME LIST 345# [option WRITE_NAME off] 346 347pre != 0 && $1 == "chunk" && NF >= 2{ 348 # 'chunk' is handled on the first pass by writing appropriate 349 # 'option' lines into the intermediate file. 350 opt = $2 351 sub(/,$/,"",opt) 352 onoff = "" 353 reqread = "" 354 reqwrite = "" 355 enables = "" 356 req = 0 357 istart = 3 358 do { 359 if (istart == 1) { # continuation line 360 val = getline 361 362 if (val != 1) { # error reading it 363 if (val == 0) 364 print "chunk", opt ": ERROR: missing continuation line" 365 else 366 print "chunk", opt ": ERROR: error reading continuation line" 367 368 # This is a hard error 369 err = 1 # prevent END{} running 370 exit 1 371 } 372 } 373 374 # read the keywords/additional OPTS 375 for (i=istart; i<=NF; ++i) { 376 val = $(i) 377 sub(/,$/,"",val) 378 if (val == "on" || val == "off" || val == "disabled") { 379 if (onoff != val) { 380 if (onoff == "") 381 onoff = val 382 else 383 break # on/off conflict 384 } 385 req = 0 386 } else if (val == "requires") 387 req = 1 388 else if (val == "enables") 389 req = 2 390 else if (req == 1){ 391 reqread = reqread " READ_" val 392 reqwrite = reqwrite " WRITE_" val 393 } else if (req == 2) 394 enables = enables " " val 395 else 396 break # bad line: handled below 397 } 398 399 istart = 1 400 } while (i > NF && $0 ~ /,$/) 401 402 if (i > NF) { 403 # Output new 'option' lines to the intermediate file (out) 404 print "option READ_" opt, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", opt enables , onoff >out 405 print "option WRITE_" opt, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", opt enables, onoff >out 406 next 407 } 408 # Else hit the error handler below - bad line format! 409} 410 411# setting MACRO ( requires MACRO* )* [ default VALUE ] 412# Behaves in a similar way to 'option' without looking for NO_ or 413# _SUPPORTED; the macro is enabled if it is defined so long as all 414# the 'requires' macros are also defined. The definitions may be 415# empty, an error will be issued if the 'requires' macros are 416# *not* defined. If given the 'default' value is used if the 417# macro is not defined. The default value will be re-tokenised. 418# (BTW: this is somewhat restrictive, it mainly exists for the 419# support of non-standard configurations and numeric parameters, 420# see the uses in scripts/options.dat 421 422$1 == "setting" && (NF == 2 || NF >= 3 && ($3 == "requires" || $3 == "default")){ 423 reqs = "" 424 deflt = "" 425 isdef = 0 426 key = "" 427 for (i=3; i<=NF; ++i) 428 if ($(i) == "requires" || $(i) == "default") { 429 key = $(i) 430 if (key == "default") isdef = 1 431 } else if (key == "requires") 432 reqs = reqs " " $(i) 433 else if (key == "default") 434 deflt = deflt " " $(i) 435 else 436 break # Format error, handled below 437 438 setting[$2] = reqs 439 # NOTE: this overwrites a previous value silently 440 if (isdef && deflt == "") 441 deflt = " " # as a flag to force output 442 defaults[$2] = deflt 443 next 444} 445 446# The order of the dependency lines (option, chunk, setting) is irrelevant 447# - the 'enables', 'requires' and 'if' settings will be used to determine 448# the correct order in the output and the final values in pnglibconf.h are 449# not order dependent. 'requires' and 'if' entries take precedence over 450# 'enables' from other options; if an option requires another option it 451# won't be set regardless of any options that enable it unless the other 452# option is also enabled. 453# 454# Similarly 'enables' trumps a NO_ definition in CFLAGS or pngusr.h 455# 456# For simplicity cycles in the definitions are regarded as errors, 457# even if they are not ambiguous. 458# A given NAME can be specified in as many 'option' lines as required, the 459# definitions are additive. 460 461# For backwards compatibility equivalent macros may be listed thus: 462# 463# = [NO_]NAME MACRO 464# Makes -DMACRO equivalent to -DPNG_NO_NAME or -DPNG_NAME_SUPPORTED 465# as appropriate. 466# 467# The definition is injected into the C compiler input when encountered 468# in the second pass (so all these definitions appear *after* the @ 469# lines!) 470# 471# 'NAME' is as above, but 'MACRO' is the full text of the equivalent 472# old, deprecated, macro. 473 474$1 == "=" && NF == 3{ 475 print "#ifdef PNG_" $3 >out 476 if ($2 ~ /^NO_/) 477 print "# define PNG_" $2 >out 478 else 479 print "# define PNG_" $2 "_SUPPORTED" >out 480 print "#endif" >out 481 next 482} 483 484# Lines may be injected into the C compiler input by preceding them 485# with an "@" character. The line is copied with just the leading 486# @ removed. 487 488$1 ~ /^@/{ 489 # sub(/^[ ]*@/, "") 490 $1 = substr($1, 2) 491 print >out 492 next 493} 494 495# Check for unrecognized lines, because of the preprocessing chunk 496# format errors will be detected on the first pass independent of 497# any other format errors. 498{ 499 print "options.awk: bad line (" NR "):", $0 500 err = 1 # prevent END{} running 501 exit 1 502} 503 504# For checking purposes names that start with "ok_" or "fail_" are 505# not output to pnglibconf.h and must be either enabled or disabled 506# respectively for the build to succeed. This allows interdependencies 507# between options of the form "at least one of" or "at most one of" 508# to be checked. For example: 509# 510# option FLOATING_POINT enables ok_math 511# option FIXED_POINT enables ok_math 512# This ensures that at least one of FLOATING_POINT and FIXED_POINT 513# must be set for the build to succeed. 514# 515# option fail_math requires FLOATING_POINT FIXED_POINT 516# This means the build will fail if *both* FLOATING_POINT and 517# FIXED_POINT are set (this is an example; in fact both are allowed.) 518# 519# If all these options were given the build would require exactly one 520# of the names to be enabled. 521 522END{ 523 # END{} gets run on an exit (a traditional awk feature) 524 if (err) exit 1 525 526 if (pre) { 527 # Record the final value of the variables 528 print "deb =", deb >out 529 if (everything != "") { 530 print "everything =", everything >out 531 } 532 print "logunsupported =", logunsupported >out 533 exit 0 534 } 535 536 # Do the options first (allowing options to set settings). The dependency 537 # tree is thus: 538 # 539 # name > name 540 # name requires name 541 # name if name 542 # name enabledby name 543 # 544 # First build a list 'tree' by option of all the things on which 545 # it depends. 546 print "" >out 547 print "/* OPTIONS */" >out 548 print comment, "options", cend >out 549 for (opt in enabledby) tree[opt] = 1 # may not be explicit options 550 for (opt in option) if (opt != "") { 551 o = option[opt] 552 # option should always be one of the following values 553 if (o != "on" && o != "off" && o != "disabled" && o != "enabled") { 554 print "internal option error (" o ")" 555 exit 1 556 } 557 tree[opt] = "" # so unlisted options marked 558 } 559 for (opt in tree) if (opt != "") { 560 if (tree[opt] == 1) { 561 tree[opt] = "" 562 if (option[opt] != "") { 563 print "internal error (1)" 564 exit 1 565 } 566 # Macros only listed in 'enables' remain off unless 567 # one of the enabling macros is on. 568 option[opt] = "disabled" 569 } 570 571 split("", list) # clear 'list' 572 # Now add every requires, iffs or enabledby entry to 'list' 573 # so that we can add a unique list of requirements to tree[i] 574 split(requires[opt] iffs[opt] enabledby[opt], r) 575 for (i in r) list[r[i]] = 1 576 for (i in list) tree[opt] = tree[opt] " " i 577 } 578 579 # print the tree for extreme debugging 580 if (deb > 2) for (i in tree) if (i != "") print i, "depends-on" tree[i] 581 582 # Ok, now check all options marked explicitly 'on' or 'off': 583 # 584 # If an option[opt] is 'on' then turn on all requires[opt] 585 # If an option[opt] is 'off' then turn off all enabledby[opt] 586 # 587 # Error out if we have to turn 'on' to an 'off' option or vice versa. 588 npending = 0 589 for (opt in option) if (opt != "") { 590 if (option[opt] == "on" || option[opt] == "off") { 591 pending[++npending] = opt 592 } 593 } 594 595 err = 0 # set on error 596 while (npending > 0) { 597 opt = pending[npending--] 598 if (option[opt] == "on") { 599 nreqs = split(requires[opt], r) 600 for (j=1; j<=nreqs; ++j) { 601 if (option[r[j]] == "off") { 602 print "option", opt, "turned on, but requirement", r[j], "is turned off" 603 err = 1 604 } else if (option[r[j]] != "on") { 605 option[r[j]] = "on" 606 pending[++npending] = r[j] 607 } 608 } 609 } else { 610 if (option[opt] != "off") { 611 print "internal error (2)" 612 exit 1 613 } 614 nreqs = split(enabledby[opt], r) 615 for (j=1; j<=nreqs; ++j) { 616 if (option[r[j]] == "on") { 617 print "option", opt, "turned off, but enabled by", r[j], "which is turned on" 618 err = 1 619 } else if (option[r[j]] != "off") { 620 option[r[j]] = "off" 621 pending[++npending] = r[j] 622 } 623 } 624 } 625 } 626 if (err) exit 1 627 628 # Sort options: 629 print "PNG_DFN_START_SORT 2" >out 630 631 # option[i] is now the complete list of all the tokens we may 632 # need to output, go through it as above, depth first. 633 finished = 0 634 while (!finished) { 635 finished = 1 636 movement = 0 # done nothing 637 for (i in option) if (!done[i]) { 638 nreqs = split(tree[i], r) 639 if (nreqs > 0) { 640 for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { 641 break 642 } 643 if (j<=nreqs) { 644 finished = 0 645 continue # next option 646 } 647 } 648 649 # All the requirements have been processed, output 650 # this option. An option is _SUPPORTED if: 651 # 652 # all 'requires' are _SUPPORTED AND 653 # at least one of the 'if' options are _SUPPORTED AND 654 # EITHER: 655 # The name is _SUPPORTED (on the command line) 656 # OR: 657 # an 'enabledby' is _SUPPORTED 658 # OR: 659 # NO_name is not defined AND 660 # the option is not disabled; an option is disabled if: 661 # option == off 662 # option == disabled && everything != on 663 # option == "" && everything == off 664 if (deb) print "option", i 665 print "" >out 666 print "/* option:", i, option[i] >out 667 print " * requires: " requires[i] >out 668 print " * if: " iffs[i] >out 669 print " * enabled-by:" enabledby[i] >out 670 print " * sets: " sets[i], "*/" >out 671 print "#undef PNG_on" >out 672 print "#define PNG_on 1" >out 673 674 # requires 675 nreqs = split(requires[i], r) 676 for (j=1; j<=nreqs; ++j) { 677 print "#ifndef PNG_" r[j] "_SUPPORTED" >out 678 print "# undef PNG_on /*!" r[j] "*/" >out 679 # This error appears in the final output if something 680 # was switched 'on' but the processing above to force 681 # the requires did not work 682 if (option[i] == "on") { 683 print error, i, "requires", r[j] end >out 684 } 685 print "#endif" >out 686 } 687 688 # if 689 have_ifs = 0 690 nreqs = split(iffs[i], r) 691 print "#undef PNG_no_if" >out 692 if (nreqs > 0) { 693 have_ifs = 1 694 print "/* if" iffs[i], "*/" >out 695 print "#define PNG_no_if 1" >out 696 for (j=1; j<=nreqs; ++j) { 697 print "#ifdef PNG_" r[j] "_SUPPORTED" >out 698 print "# undef PNG_no_if /*" r[j] "*/" >out 699 print "#endif" >out 700 } 701 print "#ifdef PNG_no_if /*missing if*/" >out 702 print "# undef PNG_on" >out 703 # There is no checking above for this, because we 704 # don't know which 'if' to choose, so whine about 705 # it here: 706 if (option[i] == "on") { 707 print error, i, "needs one of:", iffs[i] end >out 708 } 709 print "#endif" >out 710 } 711 712 print "#ifdef PNG_on /*requires, if*/" >out 713 # enables 714 print "# undef PNG_not_enabled" >out 715 print "# define PNG_not_enabled 1" >out 716 print " /* enabled by" enabledby[i], "*/" >out 717 nreqs = split(enabledby[i], r) 718 for (j=1; j<=nreqs; ++j) { 719 print "#ifdef PNG_" r[j] "_SUPPORTED" >out 720 print "# undef PNG_not_enabled /*" r[j] "*/" >out 721 # Oops, probably not intended (should be factored 722 # out by the checks above). 723 if (option[i] == "off") { 724 print error, i, "enabled by:", r[j] end >out 725 } 726 print "#endif" >out 727 } 728 729 print "# ifndef PNG_" i "_SUPPORTED /*!command line*/" >out 730 print "# ifdef PNG_not_enabled /*!enabled*/" >out 731 # 'have_ifs' here means that everything = "off" still allows an 'if' on 732 # an otherwise enabled option to turn it on; otherwise the 'if' 733 # handling is effectively disabled by 'everything = off' 734 if (option[i] == "off" || option[i] == "disabled" && everything != "on" || option[i] == "enabled" && everything == "off" && !have_ifs) { 735 print "# undef PNG_on /*default off*/" >out 736 } else { 737 print "# ifdef PNG_NO_" i >out 738 print "# undef PNG_on /*turned off*/" >out 739 print "# endif" >out 740 print "# ifdef PNG_NO_" i "_SUPPORTED" >out 741 print "# undef PNG_on /*turned off*/" >out 742 print "# endif" >out 743 } 744 print "# endif /*!enabled*/" >out 745 print "# ifdef PNG_on" >out 746 # The _SUPPORTED macro must be defined so that dependent 747 # options output later work. 748 print "# define PNG_" i "_SUPPORTED" >out 749 print "# endif" >out 750 print "# endif /*!command line*/" >out 751 # If PNG_on is still set the option should be defined in 752 # pnglibconf.h 753 print "# ifdef PNG_on" >out 754 if (i ~ /^fail_/) { 755 print error, i, "is on: enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out 756 } else if (i !~ /^ok_/) { 757 print def i sup >out 758 # Supported option, set required settings 759 nreqs = split(sets[i], r) 760 for (j=1; j<=nreqs; ++j) { 761 print "# ifdef PNG_set_" r[j] >out 762 # Some other option has already set a value: 763 print error, i, "sets", r[j] ": duplicate setting" end >out 764 print error, " previous value: " end "PNG_set_" r[j] >out 765 print "# else" >out 766 # Else set the default: note that this won't accept arbitrary 767 # values, the setval string must be acceptable to all the C 768 # compilers we use. That means it must be VERY simple; a number, 769 # a name or a string. 770 print "# define PNG_set_" r[j], setval[i " " r[j]] >out 771 print "# endif" >out 772 } 773 } 774 print "# endif /* definition */" >out 775 print "#endif /*requires, if*/" >out 776 if (logunsupported || i ~ /^ok_/) { 777 print "#ifndef PNG_on" >out 778 if (logunsupported) { 779 print und i une >out 780 } 781 if (i ~ /^ok_/) { 782 print error, i, "not enabled: requires:" requires[i] ", enabled by:" iffs[i] enabledby[i] end >out 783 } 784 print "#endif" >out 785 } 786 787 done[i] = 1 788 ++movement 789 } 790 791 if (!finished && !movement) { 792 print "option: loop or missing option in dependency tree, cannot process:" 793 for (i in option) if (!done[i]) { 794 print " option", i, "depends on" tree[i], "needs:" 795 nreqs = split(tree[i], r) 796 if (nreqs > 0) for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { 797 print " " r[j] 798 } 799 } 800 exit 1 801 } 802 } 803 print "PNG_DFN_END_SORT" >out 804 print comment, "end of options", cend >out 805 806 # Do the 'setting' values second, the algorithm the standard 807 # tree walk (O(1)) done in an O(2) while/for loop; iterations 808 # settings x depth, outputting the deepest required macros 809 # first. 810 print "" >out 811 print "/* SETTINGS */" >out 812 print comment, "settings", cend >out 813 # Sort (in dfn.awk) on field 2, the setting name 814 print "PNG_DFN_START_SORT 2" >out 815 finished = 0 816 while (!finished) { 817 finished = 1 818 movement = 0 # done nothing 819 for (i in setting) if (!doneset[i]) { 820 nreqs = split(setting[i], r) 821 if (nreqs > 0) { 822 # By default assume the requires values are options, but if there 823 # is no option with that name check for a setting 824 for (j=1; j<=nreqs; ++j) if (option[r[j]] == "" && !doneset[r[j]]) { 825 break 826 } 827 if (j<=nreqs) { 828 finished = 0 829 continue # try a different setting 830 } 831 } 832 833 # All the requirements have been processed, output 834 # this setting. 835 if (deb) print "setting", i 836 deflt = defaults[i] 837 # Remove any spurious trailing spaces 838 sub(/ *$/,"",deflt) 839 # A leading @ means leave it unquoted so the preprocessor 840 # can substitute the build time value 841 if (deflt ~ /^ @/) 842 deflt = " " subs substr(deflt, 3) sube 843 print "" >out 844 print "/* setting: ", i >out 845 print " * requires:" setting[i] >out 846 print " * default: ", defaults[i] deflt, "*/" >out 847 for (j=1; j<=nreqs; ++j) { 848 if (option[r[j]] != "") 849 print "#ifndef PNG_" r[j] "_SUPPORTED" >out 850 else 851 print "#ifndef PNG_" r[j] >out 852 print error, i, "requires", r[j] end >out 853 print "# endif" >out 854 } 855 # The precedence is: 856 # 857 # 1) External definition; trumps: 858 # 2) Option 'sets' value; trumps: 859 # 3) Setting 'default' 860 # 861 print "#ifdef PNG_" i >out 862 # PNG_<i> is defined, so substitute the value: 863 print def i, subs "PNG_" i sube end >out 864 print "#else /* use default */" >out 865 print "# ifdef PNG_set_" i >out 866 # Value from an option 'sets' argument 867 print def i, subs "PNG_set_" i sube end >out 868 # This is so that subsequent tests on the setting work: 869 print "# define PNG_" i, "1" >out 870 if (defaults[i] != "") { 871 print "# else /*default*/" >out 872 print def i deflt end >out 873 print "# define PNG_" i, "1" >out 874 } 875 print "# endif /* defaults */" >out 876 print "#endif /* setting", i, "*/" >out 877 878 doneset[i] = 1 879 ++movement 880 } 881 882 if (!finished && !movement) { 883 print "setting: loop or missing setting in 'requires', cannot process:" 884 for (i in setting) if (!doneset[i]) { 885 print " setting", i, "requires" setting[i] 886 } 887 exit 1 888 } 889 } 890 print "PNG_DFN_END_SORT" >out 891 print comment, "end of settings", cend >out 892 893 # Regular end - everything looks ok 894 if (protect != "") { 895 print start "#endif", "/*", protect, "*/" end >out 896 } 897} 898