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, 405 "enables", opt enables , onoff >out 406 print "option WRITE_" opt, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, 407 "enables", opt enables, onoff >out 408 next 409 } 410 # Else hit the error handler below - bad line format! 411} 412 413# setting MACRO ( requires MACRO* )* [ default VALUE ] 414# Behaves in a similar way to 'option' without looking for NO_ or 415# _SUPPORTED; the macro is enabled if it is defined so long as all 416# the 'requires' macros are also defined. The definitions may be 417# empty, an error will be issued if the 'requires' macros are 418# *not* defined. If given the 'default' value is used if the 419# macro is not defined. The default value will be re-tokenised. 420# (BTW: this is somewhat restrictive, it mainly exists for the 421# support of non-standard configurations and numeric parameters, 422# see the uses in scripts/options.dat 423 424$1 == "setting" && (NF == 2 || NF >= 3 && ($3 == "requires" || $3 == "default")){ 425 reqs = "" 426 deflt = "" 427 isdef = 0 428 key = "" 429 for (i=3; i<=NF; ++i) 430 if ($(i) == "requires" || $(i) == "default") { 431 key = $(i) 432 if (key == "default") isdef = 1 433 } else if (key == "requires") 434 reqs = reqs " " $(i) 435 else if (key == "default") 436 deflt = deflt " " $(i) 437 else 438 break # Format error, handled below 439 440 setting[$2] = reqs 441 # NOTE: this overwrites a previous value silently 442 if (isdef && deflt == "") 443 deflt = " " # as a flag to force output 444 defaults[$2] = deflt 445 next 446} 447 448# The order of the dependency lines (option, chunk, setting) is irrelevant 449# - the 'enables', 'requires' and 'if' settings will be used to determine 450# the correct order in the output and the final values in pnglibconf.h are 451# not order dependent. 'requires' and 'if' entries take precedence over 452# 'enables' from other options; if an option requires another option it 453# won't be set regardless of any options that enable it unless the other 454# option is also enabled. 455# 456# Similarly 'enables' trumps a NO_ definition in CFLAGS or pngusr.h 457# 458# For simplicity cycles in the definitions are regarded as errors, 459# even if they are not ambiguous. 460# A given NAME can be specified in as many 'option' lines as required, the 461# definitions are additive. 462 463# For backwards compatibility equivalent macros may be listed thus: 464# 465# = [NO_]NAME MACRO 466# Makes -DMACRO equivalent to -DPNG_NO_NAME or -DPNG_NAME_SUPPORTED 467# as appropriate. 468# 469# The definition is injected into the C compiler input when encountered 470# in the second pass (so all these definitions appear *after* the @ 471# lines!) 472# 473# 'NAME' is as above, but 'MACRO' is the full text of the equivalent 474# old, deprecated, macro. 475 476$1 == "=" && NF == 3{ 477 print "#ifdef PNG_" $3 >out 478 if ($2 ~ /^NO_/) 479 print "# define PNG_" $2 >out 480 else 481 print "# define PNG_" $2 "_SUPPORTED" >out 482 print "#endif" >out 483 next 484} 485 486# Lines may be injected into the C compiler input by preceding them 487# with an "@" character. The line is copied with just the leading 488# @ removed. 489 490$1 ~ /^@/{ 491 # sub(/^[ ]*@/, "") 492 $1 = substr($1, 2) 493 print >out 494 next 495} 496 497# Check for unrecognized lines, because of the preprocessing chunk 498# format errors will be detected on the first pass independent of 499# any other format errors. 500{ 501 print "options.awk: bad line (" NR "):", $0 502 err = 1 # prevent END{} running 503 exit 1 504} 505 506# For checking purposes names that start with "ok_" or "fail_" are 507# not output to pnglibconf.h and must be either enabled or disabled 508# respectively for the build to succeed. This allows interdependencies 509# between options of the form "at least one of" or "at most one of" 510# to be checked. For example: 511# 512# option FLOATING_POINT enables ok_math 513# option FIXED_POINT enables ok_math 514# This ensures that at least one of FLOATING_POINT and FIXED_POINT 515# must be set for the build to succeed. 516# 517# option fail_math requires FLOATING_POINT FIXED_POINT 518# This means the build will fail if *both* FLOATING_POINT and 519# FIXED_POINT are set (this is an example; in fact both are allowed.) 520# 521# If all these options were given the build would require exactly one 522# of the names to be enabled. 523 524END{ 525 # END{} gets run on an exit (a traditional awk feature) 526 if (err) exit 1 527 528 if (pre) { 529 # Record the final value of the variables 530 print "deb =", deb >out 531 if (everything != "") { 532 print "everything =", everything >out 533 } 534 print "logunsupported =", logunsupported >out 535 exit 0 536 } 537 538 # Do the options first (allowing options to set settings). The dependency 539 # tree is thus: 540 # 541 # name > name 542 # name requires name 543 # name if name 544 # name enabledby name 545 # 546 # First build a list 'tree' by option of all the things on which 547 # it depends. 548 print "" >out 549 print "/* OPTIONS */" >out 550 print comment, "options", cend >out 551 for (opt in enabledby) tree[opt] = 1 # may not be explicit options 552 for (opt in option) if (opt != "") { 553 o = option[opt] 554 # option should always be one of the following values 555 if (o != "on" && o != "off" && o != "disabled" && o != "enabled") { 556 print "internal option error (" o ")" 557 exit 1 558 } 559 tree[opt] = "" # so unlisted options marked 560 } 561 for (opt in tree) if (opt != "") { 562 if (tree[opt] == 1) { 563 tree[opt] = "" 564 if (option[opt] != "") { 565 print "internal error (1)" 566 exit 1 567 } 568 # Macros only listed in 'enables' remain off unless 569 # one of the enabling macros is on. 570 option[opt] = "disabled" 571 } 572 573 split("", list) # clear 'list' 574 # Now add every requires, iffs or enabledby entry to 'list' 575 # so that we can add a unique list of requirements to tree[i] 576 split(requires[opt] iffs[opt] enabledby[opt], r) 577 for (i in r) list[r[i]] = 1 578 for (i in list) tree[opt] = tree[opt] " " i 579 } 580 581 # print the tree for extreme debugging 582 if (deb > 2) for (i in tree) if (i != "") print i, "depends-on" tree[i] 583 584 # Ok, now check all options marked explicitly 'on' or 'off': 585 # 586 # If an option[opt] is 'on' then turn on all requires[opt] 587 # If an option[opt] is 'off' then turn off all enabledby[opt] 588 # 589 # Error out if we have to turn 'on' to an 'off' option or vice versa. 590 npending = 0 591 for (opt in option) if (opt != "") { 592 if (option[opt] == "on" || option[opt] == "off") { 593 pending[++npending] = opt 594 } 595 } 596 597 err = 0 # set on error 598 while (npending > 0) { 599 opt = pending[npending--] 600 if (option[opt] == "on") { 601 nreqs = split(requires[opt], r) 602 for (j=1; j<=nreqs; ++j) { 603 if (option[r[j]] == "off") { 604 print "option", opt, "turned on, but requirement", r[j], "is turned off" 605 err = 1 606 } else if (option[r[j]] != "on") { 607 option[r[j]] = "on" 608 pending[++npending] = r[j] 609 } 610 } 611 } else { 612 if (option[opt] != "off") { 613 print "internal error (2)" 614 exit 1 615 } 616 nreqs = split(enabledby[opt], r) 617 for (j=1; j<=nreqs; ++j) { 618 if (option[r[j]] == "on") { 619 print "option", opt, "turned off, but enabled by", r[j], "which is turned on" 620 err = 1 621 } else if (option[r[j]] != "off") { 622 option[r[j]] = "off" 623 pending[++npending] = r[j] 624 } 625 } 626 } 627 } 628 if (err) exit 1 629 630 # Sort options: 631 print "PNG_DFN_START_SORT 2" >out 632 633 # option[i] is now the complete list of all the tokens we may 634 # need to output, go through it as above, depth first. 635 finished = 0 636 while (!finished) { 637 finished = 1 638 movement = 0 # done nothing 639 for (i in option) if (!done[i]) { 640 nreqs = split(tree[i], r) 641 if (nreqs > 0) { 642 for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { 643 break 644 } 645 if (j<=nreqs) { 646 finished = 0 647 continue # next option 648 } 649 } 650 651 # All the requirements have been processed, output 652 # this option. An option is _SUPPORTED if: 653 # 654 # all 'requires' are _SUPPORTED AND 655 # at least one of the 'if' options are _SUPPORTED AND 656 # EITHER: 657 # The name is _SUPPORTED (on the command line) 658 # OR: 659 # an 'enabledby' is _SUPPORTED 660 # OR: 661 # NO_name is not defined AND 662 # the option is not disabled; an option is disabled if: 663 # option == off 664 # option == disabled && everything != on 665 # option == "" && everything == off 666 if (deb) print "option", i 667 print "" >out 668 print "/* option:", i, option[i] >out 669 print " * requires: " requires[i] >out 670 print " * if: " iffs[i] >out 671 print " * enabled-by:" enabledby[i] >out 672 print " * sets: " sets[i], "*/" >out 673 print "#undef PNG_on" >out 674 print "#define PNG_on 1" >out 675 676 # requires 677 nreqs = split(requires[i], r) 678 for (j=1; j<=nreqs; ++j) { 679 print "#ifndef PNG_" r[j] "_SUPPORTED" >out 680 print "# undef PNG_on /*!" r[j] "*/" >out 681 # This error appears in the final output if something 682 # was switched 'on' but the processing above to force 683 # the requires did not work 684 if (option[i] == "on") { 685 print error, i, "requires", r[j] end >out 686 } 687 print "#endif" >out 688 } 689 690 # if 691 have_ifs = 0 692 nreqs = split(iffs[i], r) 693 print "#undef PNG_no_if" >out 694 if (nreqs > 0) { 695 have_ifs = 1 696 print "/* if" iffs[i], "*/" >out 697 print "#define PNG_no_if 1" >out 698 for (j=1; j<=nreqs; ++j) { 699 print "#ifdef PNG_" r[j] "_SUPPORTED" >out 700 print "# undef PNG_no_if /*" r[j] "*/" >out 701 print "#endif" >out 702 } 703 print "#ifdef PNG_no_if /*missing if*/" >out 704 print "# undef PNG_on" >out 705 # There is no checking above for this, because we 706 # don't know which 'if' to choose, so whine about 707 # it here: 708 if (option[i] == "on") { 709 print error, i, "needs one of:", iffs[i] end >out 710 } 711 print "#endif" >out 712 } 713 714 print "#ifdef PNG_on /*requires, if*/" >out 715 # enables 716 print "# undef PNG_not_enabled" >out 717 print "# define PNG_not_enabled 1" >out 718 print " /* enabled by" enabledby[i], "*/" >out 719 nreqs = split(enabledby[i], r) 720 for (j=1; j<=nreqs; ++j) { 721 print "#ifdef PNG_" r[j] "_SUPPORTED" >out 722 print "# undef PNG_not_enabled /*" r[j] "*/" >out 723 # Oops, probably not intended (should be factored 724 # out by the checks above). 725 if (option[i] == "off") { 726 print error, i, "enabled by:", r[j] end >out 727 } 728 print "#endif" >out 729 } 730 731 print "# ifndef PNG_" i "_SUPPORTED /*!command line*/" >out 732 print "# ifdef PNG_not_enabled /*!enabled*/" >out 733 # 'have_ifs' here means that everything = "off" still allows an 'if' on 734 # an otherwise enabled option to turn it on; otherwise the 'if' 735 # handling is effectively disabled by 'everything = off' 736 if ((option[i] == "off") || 737 (option[i] == "disabled" && everything != "on") || 738 (option[i] == "enabled" && everything == "off" && !have_ifs)) { 739 print "# undef PNG_on /*default off*/" >out 740 } else { 741 print "# ifdef PNG_NO_" i >out 742 print "# undef PNG_on /*turned off*/" >out 743 print "# endif" >out 744 print "# ifdef PNG_NO_" i "_SUPPORTED" >out 745 print "# undef PNG_on /*turned off*/" >out 746 print "# endif" >out 747 } 748 print "# endif /*!enabled*/" >out 749 print "# ifdef PNG_on" >out 750 # The _SUPPORTED macro must be defined so that dependent 751 # options output later work. 752 print "# define PNG_" i "_SUPPORTED" >out 753 print "# endif" >out 754 print "# endif /*!command line*/" >out 755 # If PNG_on is still set the option should be defined in 756 # pnglibconf.h 757 print "# ifdef PNG_on" >out 758 if (i ~ /^fail_/) { 759 print error, i, "is on:", 760 "enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out 761 } else if (i !~ /^ok_/) { 762 print def i sup >out 763 # Supported option, set required settings 764 nreqs = split(sets[i], r) 765 for (j=1; j<=nreqs; ++j) { 766 print "# ifdef PNG_set_" r[j] >out 767 # Some other option has already set a value: 768 print error, i, "sets", r[j] ": duplicate setting" end >out 769 print error, " previous value: " end "PNG_set_" r[j] >out 770 print "# else" >out 771 # Else set the default: note that this won't accept arbitrary 772 # values, the setval string must be acceptable to all the C 773 # compilers we use. That means it must be VERY simple; a number, 774 # a name or a string. 775 print "# define PNG_set_" r[j], setval[i " " r[j]] >out 776 print "# endif" >out 777 } 778 } 779 print "# endif /* definition */" >out 780 print "#endif /*requires, if*/" >out 781 if (logunsupported || i ~ /^ok_/) { 782 print "#ifndef PNG_on" >out 783 if (logunsupported) { 784 print und i une >out 785 } 786 if (i ~ /^ok_/) { 787 print error, i, "not enabled: ", 788 "requires:" requires[i] ", enabled by:" iffs[i] enabledby[i] end >out 789 } 790 print "#endif" >out 791 } 792 793 done[i] = 1 794 ++movement 795 } 796 797 if (!finished && !movement) { 798 print "option: loop or missing option in dependency tree, cannot process:" 799 for (i in option) if (!done[i]) { 800 print " option", i, "depends on" tree[i], "needs:" 801 nreqs = split(tree[i], r) 802 if (nreqs > 0) for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { 803 print " " r[j] 804 } 805 } 806 exit 1 807 } 808 } 809 print "PNG_DFN_END_SORT" >out 810 print comment, "end of options", cend >out 811 812 # Do the 'setting' values second, the algorithm the standard 813 # tree walk (O(1)) done in an O(2) while/for loop; iterations 814 # settings x depth, outputting the deepest required macros 815 # first. 816 print "" >out 817 print "/* SETTINGS */" >out 818 print comment, "settings", cend >out 819 # Sort (in dfn.awk) on field 2, the setting name 820 print "PNG_DFN_START_SORT 2" >out 821 finished = 0 822 while (!finished) { 823 finished = 1 824 movement = 0 # done nothing 825 for (i in setting) if (!doneset[i]) { 826 nreqs = split(setting[i], r) 827 if (nreqs > 0) { 828 # By default assume the requires values are options, but if there 829 # is no option with that name check for a setting 830 for (j=1; j<=nreqs; ++j) if (option[r[j]] == "" && !doneset[r[j]]) { 831 break 832 } 833 if (j<=nreqs) { 834 finished = 0 835 continue # try a different setting 836 } 837 } 838 839 # All the requirements have been processed, output 840 # this setting. 841 if (deb) print "setting", i 842 deflt = defaults[i] 843 # Remove any spurious trailing spaces 844 sub(/ *$/,"",deflt) 845 # A leading @ means leave it unquoted so the preprocessor 846 # can substitute the build time value 847 if (deflt ~ /^ @/) 848 deflt = " " subs substr(deflt, 3) sube 849 print "" >out 850 print "/* setting: ", i >out 851 print " * requires:" setting[i] >out 852 print " * default: ", defaults[i] deflt, "*/" >out 853 for (j=1; j<=nreqs; ++j) { 854 if (option[r[j]] != "") 855 print "#ifndef PNG_" r[j] "_SUPPORTED" >out 856 else 857 print "#ifndef PNG_" r[j] >out 858 print error, i, "requires", r[j] end >out 859 print "# endif" >out 860 } 861 # The precedence is: 862 # 863 # 1) External definition; trumps: 864 # 2) Option 'sets' value; trumps: 865 # 3) Setting 'default' 866 # 867 print "#ifdef PNG_" i >out 868 # PNG_<i> is defined, so substitute the value: 869 print def i, subs "PNG_" i sube end >out 870 print "#else /* use default */" >out 871 print "# ifdef PNG_set_" i >out 872 # Value from an option 'sets' argument 873 print def i, subs "PNG_set_" i sube end >out 874 # This is so that subsequent tests on the setting work: 875 print "# define PNG_" i, "1" >out 876 if (defaults[i] != "") { 877 print "# else /*default*/" >out 878 print def i deflt end >out 879 print "# define PNG_" i, "1" >out 880 } 881 print "# endif /* defaults */" >out 882 print "#endif /* setting", i, "*/" >out 883 884 doneset[i] = 1 885 ++movement 886 } 887 888 if (!finished && !movement) { 889 print "setting: loop or missing setting in 'requires', cannot process:" 890 for (i in setting) if (!doneset[i]) { 891 print " setting", i, "requires" setting[i] 892 } 893 exit 1 894 } 895 } 896 print "PNG_DFN_END_SORT" >out 897 print comment, "end of settings", cend >out 898 899 # Regular end - everything looks ok 900 if (protect != "") { 901 print start "#endif", "/*", protect, "*/" end >out 902 } 903} 904