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