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