blob: 9286cd11a43862df1194e7521fe9c57ad4530dc2 [file] [log] [blame]
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -05001#!/bin/awk -f
2# scripts/options.awk - library build configuration control
3#
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -05004# last changed in libpng version 1.5.0 - June 21, 2010
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -05005#
6# Copyright (c) 1998-2010 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
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050015# that file to produce the final output:
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050016#
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050017# 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#
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -050027# If awk fails on your platform, try nawk instead.
28#
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050029# These options may also be specified in the original input file (and
30# are copied to the preprocessed file).
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050031
32BEGIN{
33 out="/dev/null" # intermediate, preprocessed, file
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050034 pre=-1 # preprocess (first line)
35 err=0 # in-line exit sets this
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050036 start="PNG_DEFN_MAGIC-" # Arbitrary start
37 end="-PNG_DEFN_END" # Arbitrary end
38 cx= "/@@@*" # Open C comment for output file
39 comment=start cx # Comment start
40 cend="*/" end # Comment end
41 def=start "#define PNG_@@@" # Arbitrary define
42 sup="@@@_SUPPORTED" end # end supported option
43 und=comment "#undef PNG_@@@" # Unsupported option
44 une="@@@_SUPPORTED" cend # end unsupported option
45 error=start "ERROR:" # error message
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050046
47 # Variables
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050048 deb=0 # debug - set on command line
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050049 everything="" # do not override defaults
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050050 logunsupported=0 # write unsupported options too
51
52 # Precreate arrays
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050053 option[""] = "" # list of all options: default enabled/disabled
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050054 done[""] = 1 # marks option as having been output
55 requires[""] = "" # requires by option
56 iffs[""] = "" # if by option
57 enabledby[""] = "" # options that enable it by option
58 setting[""] = "" # requires by setting
59 defaults[""] = "" # used for a defaulted value
60 doneset[""] = 1 # marks setting as having been output
61 r[""] = "" # Temporary array
62
63 # For decorating the output file
64 protect = ""
65}
66
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -050067# The output file must be specified before any input:
68out == "/dev/null" {
69 print "out=output.file must be given on the command line"
70 err = 1
71 exit 1
72}
73
74# The very first line indicates whether we are reading pre-processed
75# input or not, this must come *first* because 'PREPROCESSED' needs
76# to be the very first line in the temporary file.
77pre == -1{
78 if ($0 == "PREPROCESSED") {
79 pre = 0
80 next
81 } else {
82 pre = 1
83 print "PREPROCESSED" >out
84 # And fall through to continue processing
85 }
86}
87
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050088# Preprocessing - this just copies the input file with lines
89# that need preprocessing (just chunk at present) expanded
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -050090# The bare "pre" instead of "pre != 0" crashes under Sunos awk
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -050091pre && $1 != "chunk"{
92 print >out
93 next
94}
95
96# The first characters of the line determine how it is processed,
97# leading spaces are ignored. In general tokens that are not
98# keywords are the names of options. An option 'name' is
99# controlled by the definition of the corresponding macros:
100#
101# PNG_name_SUPPORTED The option is turned on
102# PNG_NO_name
103# PNG_NO_name_SUPPORTED If the first macro is not defined
104# either of these will turn the option off
105#
106# If none of these macros are defined the option is turned on, unless
107# the keyword 'off' is given in a line relating to the option. The
108# keyword 'on' can also be given, but it will be ignored (since it is
109# the default.)
110#
111# In the syntax below a 'name' is indicated by "NAME", other macro
112# values are indicated by "MACRO", as with "NAME" the leading "PNG_"
113# is omitted, but in this case the "NO_" prefix and the "_SUPPORTED"
114# suffix are never used.
115#
116# Each line is introduced by a keyword - the first non-space characters
117# on the line. A line starting with a '#' is a comment - it is totally
118# ignored. Keywords are as follows, a NAME, is simply a macro name
119# without the leading PNG_, PNG_NO_ or the trailing _SUPPORTED.
120
121$1 ~ /^#/ || $0 ~ /^[ ]*$/{
122 next
123}
124
125# com <comment>
126# The whole line is placed in the output file as a comment with
127# the preceding 'com' removed
128$1 == "com"{
129 if (NF > 1) {
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500130 # sub(/^[ ]*com[ ]*/, "")
131 $1 = ""
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500132 print comment, $0, cend >out
133 } else
134 print start end >out
135 next
136}
137
138# file output input protect
139# Informational: the official name of the input file (without
140# make generated local directories), the official name of the
141# output file and, if required, a name to use in a protection
142# macro for the contents.
143$1 == "file" && NF >= 2{
144 print comment, $2, cend >out
145 print comment, "Machine generated file: DO NOT EDIT", cend >out
146 if (NF >= 3)
147 print comment, "Derived from:", $3, cend >out
148 protect = $4
149 if (protect != "") {
150 print start "#ifndef", protect end >out
151 print start "#define", protect end >out
152 }
153 next
154}
155
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500156# variable=value
157# Sets the given variable to the given value (the syntax is fairly
158# free form, except for deb (you are expected to understand how to
159# set the debug variable...)
160$0 ~ /^[ ]*everything[ =]*off[ ]*$/{
161 everything = "off"
162 next
163}
164$0 ~ /^[ ]*everything[ =]*on[ ]*$/{
165 everything = "on"
166 next
167}
168$0 ~ /^[ ]*logunsupported[ =]*0[ ]*$/{
169 logunsupported = 0
170 next
171}
172$0 ~ /^[ ]*logunsupported[ =]*1[ ]*$/{
173 logunsupported = 1
174 next
175}
176$1 == "deb" && $2 == "=" && NF == 3{
177 deb = $3
178 next
179}
180
181# option NAME ( (requires|enables|if) NAME* | on | off | disabled )*
182# Declares an option 'NAME' and describes its default setting (disabled)
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500183# and its relationship to other options. The option is disabled
184# unless *all* the options listed after 'requires' are set and at
185# least one of the options listed after 'if' is set. If the
186# option is set then it turns on all the options listed after 'enables'.
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500187#
188# Note that "enables" takes priority over the required/if/disabled/off
189# setting of the target option.
190#
191# The definition file may list an option as 'disabled': off by default,
192# otherwise the option is enabled: on by default. A later (and it must
193# be later) entry may turn an option on or off explicitly.
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500194
195$1 == "option" && NF >= 2{
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500196 onoff = option[$2] # records current (and the default is "", enabled)
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500197 key = ""
198 for (i=3; i<=NF; ++i) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500199 if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500200 key = ""
201 if (onoff != $(i)) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500202 # on or off can zap disabled or enabled:
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500203 if (onoff == "" || (onoff == "disabled" || onoff == "enabled") && ($(i) == "on" || $(i) == "off")) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500204 # It's easy to mis-spell the option when turning it
205 # on or off, so warn about it here:
206 if (onoff == "" && ($(i) == "on" || $(i) == "off")) {
207 print $2 ": ERROR: turning unrecognized option", $(i)
208 # For the moment error out - it is safer
209 err = 1 # prevent END{} running
210 exit 1
211 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500212 onoff = $(i)
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500213 } else {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500214 # Print a message, otherwise the error
215 # below is incomprehensible
216 print $2 ": currently", onoff ": attempt to turn", $(i)
217 break
218 }
219 }
220 } else if ($(i) == "requires" || $(i) == "if" || $(i) == "enables") {
221 key = $(i)
222 } else if (key == "requires") {
223 requires[$2] = requires[$2] " " $(i)
224 } else if (key == "if") {
225 iffs[$2] = iffs[$2] " " $(i)
226 } else if (key == "enables") {
227 enabledby[$(i)] = enabledby[$(i)] " " $2
228 } else
229 break # bad line format
230 }
231
232 if (i > NF) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500233 # Set the option, defaulting to 'enabled'
234 if (onoff == "") onoff = "enabled"
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500235 option[$2] = onoff
236 next
237 }
238 # Else fall through to the error handler
239}
240
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500241# chunk NAME [requires OPT] [on|off|disabled]
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500242# Expands to the 'option' settings appropriate to the reading and
243# writing of an ancilliary PNG chunk 'NAME':
244#
245# option READ_NAME requires READ_ANCILLARY_CHUNKS [READ_OPT]
246# option READ_NAME enables NAME
247# [option READ_NAME off]
248# option WRITE_NAME requires WRITE_ANCILLARY_CHUNKS [WRITE_OPT]
249# option WRITE_NAME enables NAME
250# [option WRITE_NAME off]
251
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500252pre != 0 && $1 == "chunk" && NF >= 2{
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500253 # 'chunk' is handled on the first pass by writing appropriate
254 # 'option' lines into the intermediate file.
255 onoff = ""
256 reqread = ""
257 reqwrite = ""
258 i = 3 # indicates format error
259 if (NF > 2) {
260 # read the keywords/additional OPTS
261 req = 0
262 for (i=3; i<=NF; ++i) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500263 if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500264 if (onoff != $(i)) {
265 if (onoff == "")
266 onoff = $(i)
267 else
268 break # on/off conflict
269 }
270 } else if ($(i) == "requires")
271 req = 1
272 else if (req != 1)
273 break # bad line: handled below
274 else {
275 reqread = reqread " READ_" $(i)
276 reqwrite = reqwrite " WRITE_" $(i)
277 }
278 }
279 }
280
281 if (i > NF) {
282 # Output new 'option' lines to the intermediate file (out)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500283 print "option READ_" $2, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", $2, onoff >out
284 print "option WRITE_" $2, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", $2, onoff >out
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500285 next
286 }
287 # Else hit the error handler below - bad line format!
288}
289
290# setting MACRO ( requires MACRO* )* [ default VALUE ]
291# Behaves in a similar way to 'option' without looking for NO_ or
292# _SUPPORTED; the macro is enabled if it is defined so long as all
293# the 'requires' macros are also defined. The definitions may be
294# empty, an error will be issued if the 'requires' macros are
295# *not* defined. If given the 'default' value is used if the
296# macro is not defined. The default value will be re-tokenised.
297# (BTW: this is somewhat restrictive, it mainly exists for the
298# support of non-standard configurations and numeric parameters,
299# see the uses in scripts/options.dat
300
301$1 == "setting" && (NF == 2 || NF >= 3 && ($3 == "requires" || $3 == "default")){
302 reqs = ""
303 deflt = ""
304 isdef = 0
305 key = ""
306 for (i=3; i<=NF; ++i)
307 if ($(i) == "requires" || $(i) == "default") {
308 key = $(i)
309 if (key == "default") isdef = 1
310 } else if (key == "requires")
311 reqs = reqs " " $(i)
312 else if (key == "default")
313 deflt = deflt " " $(i)
314 else
315 break # Format error, handled below
316
317 setting[$2] = reqs
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500318 # NOTE: this overwrites a previous value silently
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500319 if (isdef && deflt == "")
320 deflt = " " # as a flag to force output
321 defaults[$2] = deflt
322 next
323}
324
325# The order of the dependency lines (option, chunk, setting) is irrelevant
326# - the 'enables', 'requires' and 'if' settings will be used to determine
Glenn Randers-Pehrson98b4f002010-04-16 22:30:26 -0500327# the correct order in the output and the final values in pnglibconf.h are
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500328# not order dependent. 'requires' and 'if' entries take precedence over
329# 'enables' from other options; if an option requires another option it
330# won't be set regardless of any options that enable it unless the other
331# option is also enabled.
332#
333# Similarly 'enables' trumps a NO_ definition in CFLAGS or pngusr.h
334#
335# For simplicity cycles in the definitions are regarded as errors,
336# even if they are not ambiguous.
337# A given NAME can be specified in as many 'option' lines as required, the
338# definitions are additive.
339
340# For backwards compatibility equivalent macros may be listed thus:
341#
342# = [NO_]NAME MACRO
343# Makes -DMACRO equivalent to -DPNG_NO_NAME or -DPNG_NAME_SUPPORTED
344# as appropriate.
345#
346# The definition is injected into the C compiler input when encountered
347# in the second pass (so all these definitions appear *after* the @
348# lines!)
349#
350# 'NAME' is as above, but 'MACRO' is the full text of the equivalent
351# old, deprecated, macro.
352
353$1 == "=" && NF == 3{
354 print "#ifdef PNG_" $3 >out
355 if ($2 ~ /^NO_/)
356 print "# define PNG_" $2 >out
357 else
358 print "# define PNG_" $2 "_SUPPORTED" >out
359 print "#endif" >out
360 next
361}
362
363# Lines may be injected into the C compiler input by preceding them
364# with an "@" character. The line is copied with just the leading
365# @ removed.
366
367$1 ~ /^@/{
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500368 # sub(/^[ ]*@/, "")
369 $1 = substr($1, 2)
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500370 print >out
371 next
372}
373
374# Check for unreognized lines, because of the preprocessing chunk
375# format errors will be detected on the first pass independent of
376# any other format errors.
377{
378 print "options.awk: bad line (" NR "):", $0
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500379 err = 1 # prevent END{} running
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500380 exit 1
381}
382
383# For checking purposes names that start with "ok_" or "fail_" are
Glenn Randers-Pehrson98b4f002010-04-16 22:30:26 -0500384# not output to pnglibconf.h and must be either enabled or disabled
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500385# respectively for the build to succeed. This allows interdependencies
386# between options of the form "at least one of" or "at most one of"
387# to be checked. For example:
388#
389# option FLOATING_POINT enables ok_math
390# option FIXED_POINT enables ok_math
391# This ensures that at least one of FLOATING_POINT and FIXED_POINT
392# must be set for the build to succeed.
393#
394# option fail_math requires FLOATING_POINT FIXED_POINT
395# This means the build will fail if *both* FLOATING_POINT and
396# FIXED_POINT are set (this is an example; in fact both are allowed.)
397#
398# If all these options were given the build would require exactly one
399# of the names to be enabled.
400
401END{
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500402 # END{} gets run on an exit (a traditional awk feature)
403 if (err) exit 1
404
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500405 if (pre) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500406 # Record the variables
407 print "deb =", deb
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500408 if (everything != "") {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500409 print "everything =", everything
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500410 }
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500411 print "logunsupported =", logunsupported
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500412 exit 0
413 }
414
415 # Do the 'setting' values first, the algorithm the standard
416 # tree walk (O(1)) done in an O(2) while/for loop; interations
417 # settings x depth, outputing the deepest required macros
418 # first.
419 print "" >out
420 print "/* SETTINGS */" >out
421 print comment, "settings", cend >out
422 finished = 0
423 while (!finished) {
424 finished = 1
425 movement = 0 # done nothing
426 for (i in setting) if (!doneset[i]) {
427 nreqs = split(setting[i], r)
428 if (nreqs > 0) {
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500429 for (j=1; j<=nreqs; ++j) if (!doneset[r[j]]) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500430 break
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500431 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500432 if (j<=nreqs) {
433 finished = 0
434 continue # try a different setting
435 }
436 }
437
438 # All the requirements have been processed, output
439 # this setting.
440 if (deb) print "setting", i
441 print "" >out
442 print "/* setting: ", i >out
443 print " * requires:" setting[i] >out
444 print " * default: ", defaults[i], "*/" >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500445 if (defaults[i] == "") { # no default, only check if defined
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500446 print "#ifdef PNG_" i >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500447 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500448 for (j=1; j<=nreqs; ++j) {
449 print "# ifndef PNG_" r[j] >out
450 print error, i, "requires", r[j] end >out
451 print "# endif" >out
452 }
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500453 if (defaults[i] != "") { # default handling
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500454 print "#ifdef PNG_" i >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500455 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500456 print def i, "PNG_" i end >out
457 if (defaults[i] != "") {
458 print "#else /*default*/" >out
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500459 # And add the default definition for the benefit
460 # of later settings an options test:
461 print "# define PNG_" i defaults[i] >out
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500462 print def i defaults[i] end >out
463 }
464 print "#endif" >out
465
466 doneset[i] = 1
467 ++movement
468 }
469
470 if (!finished && !movement) {
471 print "setting: loop or missing setting in 'requires', cannot process:"
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500472 for (i in setting) if (!doneset[i]) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500473 print " setting", i, "requires" setting[i]
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500474 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500475 exit 1
476 }
477 }
478 print comment, "end of settings", cend >out
479
480 # Now do the options - somewhat more complex. The dependency
481 # tree is thus:
482 #
483 # name > name
484 # name requires name
485 # name if name
486 # name enabledby name
487 #
488 # First build a list 'tree' by option of all the things on which
489 # it depends.
490 print "" >out
491 print "/* OPTIONS */" >out
492 print comment, "options", cend >out
493 for (opt in enabledby) tree[opt] = 1 # may not be explicit options
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500494 for (opt in option) if (opt != "") {
495 o = option[opt]
496 # option should always be one of the following values
497 if (o != "on" && o != "off" && o != "disabled" && o != "enabled") {
498 print "internal option error (" o ")"
499 exit 1
500 }
501 tree[opt] = "" # so unlisted options marked
502 }
503 for (opt in tree) if (opt != "") {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500504 if (tree[opt] == 1) {
505 tree[opt] = ""
506 if (option[opt] != "") {
507 print "internal error (1)"
508 exit 1
509 }
510 # Macros only listed in 'enables' remain off unless
511 # one of the enabling macros is on.
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500512 option[opt] = "disabled"
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500513 }
514
515 split("", list) # clear 'list'
516 # Now add every requires, iffs or enabledby entry to 'list'
517 # so that we can add a unique list of requirements to tree[i]
518 split(requires[opt] iffs[opt] enabledby[opt], r)
519 for (i in r) list[r[i]] = 1
520 for (i in list) tree[opt] = tree[opt] " " i
521 }
522
523 # print the tree for extreme debugging
524 if (deb > 2) for (i in tree) if (i != "") print i, "depends-on" tree[i]
525
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500526 # Ok, now check all options marked explicitly 'on' or 'off':
527 #
528 # If an option[opt] is 'on' then turn on all requires[opt]
529 # If an option[opt] is 'off' then turn off all enabledby[opt]
530 #
531 # Error out if we have to turn 'on' an 'off' option or vice versa.
532 npending = 0
533 for (opt in option) if (opt != "") {
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500534 if (option[opt] == "on" || option[opt] == "off") {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500535 pending[++npending] = opt
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500536 }
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500537 }
538
539 err = 0 # set on error
540 while (npending > 0) {
541 opt = pending[npending--]
542 if (option[opt] == "on") {
543 nreqs = split(requires[opt], r)
544 for (j=1; j<=nreqs; ++j) {
545 if (option[r[j]] == "off") {
546 print "option", opt, "turned on, but requirement", r[j], "is turned off"
547 err = 1
548 } else if (option[r[j]] != "on") {
549 option[r[j]] = "on"
550 pending[++npending] = r[j]
551 }
552 }
553 } else {
554 if (option[opt] != "off") {
555 print "internal error (2)"
556 exit 1
557 }
558 nreqs = split(enabledby[opt], r)
559 for (j=1; j<=nreqs; ++j) {
560 if (option[r[j]] == "on") {
561 print "option", opt, "turned off, but enabled by", r[j], "which is turned on"
562 err = 1
563 } else if (option[r[j]] != "off") {
564 option[r[j]] = "off"
565 pending[++npending] = r[j]
566 }
567 }
568 }
569 }
570 if (err) exit 1
571
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500572 # option[i] is now the complete list of all the tokens we may
573 # need to output, go through it as above, depth first.
574 finished = 0
575 while (!finished) {
576 finished = 1
577 movement = 0 # done nothing
578 for (i in option) if (!done[i]) {
579 nreqs = split(tree[i], r)
580 if (nreqs > 0) {
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500581 for (j=1; j<=nreqs; ++j) if (!done[r[j]]) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500582 break
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500583 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500584 if (j<=nreqs) {
585 finished = 0
586 continue # next option
587 }
588 }
589
590 # All the requirements have been processed, output
591 # this option. An option is _SUPPORTED if:
592 #
593 # all 'requires' are _SUPPORTED AND
594 # at least one of the 'if' options are _SUPPORTED AND
595 # EITHER:
596 # The name is _SUPPORTED (on the command line)
597 # OR:
598 # an 'enabledby' is _SUPPORTED
599 # OR:
600 # NO_name is not defined AND
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500601 # the option is not disabled; an option is disabled if:
602 # option == off
603 # option == disabled && everything != on
604 # option == "" && everything == off
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500605 if (deb) print "option", i
606 print "" >out
607 print "/* option:", i, option[i] >out
608 print " * requires: " requires[i] >out
609 print " * if: " iffs[i] >out
610 print " * enabled-by:" enabledby[i], "*/" >out
611 print "#undef PNG_on" >out
612 print "#define PNG_on 1" >out
613
614 # requires
615 nreqs = split(requires[i], r)
616 for (j=1; j<=nreqs; ++j) {
617 print "#ifndef PNG_" r[j] "_SUPPORTED" >out
618 print "# undef PNG_on /*!" r[j] "*/" >out
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500619 # this error appears in the final output if something
620 # was switched 'on' but the processing above to force
621 # the requires did not work
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500622 if (option[i] == "on") {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500623 print error, i, "requires", r[j] end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500624 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500625 print "#endif" >out
626 }
627
628 # if
629 nreqs = split(iffs[i], r)
630 print "#undef PNG_no_if" >out
631 if (nreqs > 0) {
632 print "/* if" iffs[i], "*/" >out
633 print "#define PNG_no_if 1" >out
634 for (j=1; j<=nreqs; ++j) {
635 print "#ifdef PNG_" r[j] "_SUPPORTED" >out
636 print "# undef PNG_no_if /*" r[j] "*/" >out
637 print "#endif" >out
638 }
639 print "#ifdef PNG_no_if /*missing if*/" >out
640 print "# undef PNG_on" >out
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500641 # There is no checking above for this, because we
642 # don't know which 'if' to choose, so whine about
643 # it here:
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500644 if (option[i] == "on") {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500645 print error, i, "needs one of:", iffs[i] end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500646 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500647 print "#endif" >out
648 }
649
650 print "#ifdef PNG_on /*requires, if*/" >out
651 # enables
652 print "# undef PNG_not_enabled" >out
653 print "# define PNG_not_enabled 1" >out
654 print " /* enabled by" enabledby[i], "*/" >out
655 nreqs = split(enabledby[i], r)
656 for (j=1; j<=nreqs; ++j) {
657 print "#ifdef PNG_" r[j] "_SUPPORTED" >out
658 print "# undef PNG_not_enabled /*" r[j] "*/" >out
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500659 # Oops, probably not intended (should be factored
660 # out by the checks above).
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500661 if (option[i] == "off") {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500662 print error, i, "enabled by:", r[j] end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500663 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500664 print "#endif" >out
665 }
666
667 print "# ifndef PNG_" i "_SUPPORTED /*!command line*/" >out
668 print "# ifdef PNG_not_enabled /*!enabled*/" >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500669 if (option[i] == "off" || option[i] == "disabled" && everything != "on" || option[i] == "enabled" && everything == "off") {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500670 print "# undef PNG_on /*default off*/" >out
671 } else {
672 print "# ifdef PNG_NO_" i >out
673 print "# undef PNG_on /*turned off*/" >out
674 print "# endif" >out
675 print "# ifdef PNG_NO_" i "_SUPPORTED" >out
676 print "# undef PNG_on /*turned off*/" >out
677 print "# endif" >out
678 }
679 print "# endif /*!enabled*/" >out
680 print "# ifdef PNG_on" >out
681 # The _SUPPORTED macro must be defined so that dependent
682 # options output later work.
683 print "# define PNG_" i "_SUPPORTED" >out
684 print "# endif" >out
685 print "# endif /*!command line*/" >out
686 # If PNG_on is still set the option should be defined in
Glenn Randers-Pehrson98b4f002010-04-16 22:30:26 -0500687 # pnglibconf.h
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500688 print "# ifdef PNG_on" >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500689 if (i ~ /^fail_/) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500690 print error, i, "is on: enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500691 } else if (i !~ /^ok_/) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500692 print def i sup >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500693 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500694 print "# endif /* definition */" >out
695 print "#endif /*requires, if*/" >out
696 if (logunsupported || i ~ /^ok_/) {
697 print "#ifndef PNG_on" >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500698 if (logunsupported) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500699 print und i une >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500700 }
701 if (i ~ /^ok_/) {
Glenn Randers-Pehrsoncd745492010-04-28 07:52:16 -0500702 print error, i, "not enabled: requires:" requires[i] ", enabled by:" iffs[i] enabledby[i] end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500703 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500704 print "#endif" >out
705 }
706
707 done[i] = 1
708 ++movement
709 }
710
711 if (!finished && !movement) {
712 print "option: loop or missing option in dependency tree, cannot process:"
713 for (i in option) if (!done[i]) {
714 print " option", i, "depends on" tree[i], "needs:"
715 nreqs = split(tree[i], r)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500716 if (nreqs > 0) for (j=1; j<=nreqs; ++j) if (!done[r[j]]) {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500717 print " " r[j]
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500718 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500719 }
720 exit 1
721 }
722 }
723 print comment, "end of options", cend >out
724
725 # Regular end - everything looks ok
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500726 if (protect != "") {
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500727 print start "#endif", cx, protect, "*/" end >out
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500728 }
Glenn Randers-Pehrson862cb202010-04-16 22:12:51 -0500729}