1#!/bin/awk -f
2
3function get_values(var, arr) {
4	return split(ENVIRON[var], arr, " ")
5}
6
7# Add a line of data to config.mk.
8function add_line_to_config_mk(line) {
9	print(line) >> config_mk
10}
11
12function add_to_config_h_if_yes(value, define) {
13	if (value == "yes")
14		print(define) >> config_h
15	else
16		print("/* " define " */") >> config_h
17}
18
19#
20# Feature handling functions
21#
22
23# Get the name of the feature
24function get_feature_name(feature) {
25	return ENVIRON["_feature_" feature "_name"]
26}
27
28# Check whether the feature is enabled
29function get_feature_state(feature) {
30	get_values("_feature_" feature "_settings", settings)
31	for (i in settings) {
32		if (ENVIRON[settings[i]] == "yes")
33			return "yes"
34	}
35	return "no"
36}
37
38
39#
40# Engine handling functions
41#
42
43# Get the name of the engine
44function get_engine_name(engine) {
45	return ENVIRON["_engine_" engine "_name"]
46}
47
48# Will this engine be built?
49function get_engine_build(engine) {
50	return ENVIRON["_engine_" engine "_build"]
51}
52
53# Was this engine set to be built by default?
54function get_engine_build_default(engine) {
55	return ENVIRON["_engine_" engine "_build_default"]
56}
57
58# Get the subengines
59function get_engine_subengines(engine, subengines) {
60	return get_values("_engine_" engine "_subengines", subengines)
61}
62
63# Get the dependencies
64function get_engine_dependencies(engine, deps) {
65	return get_values("_engine_" engine "_deps", deps)
66}
67
68# Get the base engine game support description
69function get_engine_base(engine) {
70	return ENVIRON["_engine_" engine "_base"]
71}
72
73# Ask if this is a subengine
74function get_engine_sub(engine) {
75	subeng = ENVIRON["_engine_" engine "_sub"]
76	if (subeng == "")
77		subeng = "no"
78	return subeng
79}
80
81# Get a subengine's parent (undefined for non-subengines)
82function get_subengine_parent(engine) {
83	return ENVIRON["_engine_" engine "_parent"]
84}
85
86function disable_engine(engine) {
87	ENVIRON["_engine_" engine "_build"] = "no"
88}
89
90function check_engine_deps(engine) {
91	unmet_deps = ""
92
93	# Check whether the engine is enabled
94	if (get_engine_build(engine) != "no") {
95		# Collect unmet dependencies
96		depcount = get_engine_dependencies(engine, deps)
97		for (d = 1; d <= depcount; d++) {
98			if (get_feature_state(deps[d]) == "no")
99				unmet_deps = unmet_deps get_feature_name(deps[d]) " "
100		}
101
102		# Check whether there is any unmet dependency
103		if (unmet_deps) {
104			print("WARNING: Disabling engine " get_engine_name(engine) " because the following dependencies are unmet: " unmet_deps)
105			disable_engine(engine)
106		}
107	}
108}
109
110# Prepare the strings about the engines to build
111function prepare_engine_build_strings(engine) {
112	if (string = get_engine_build_string(engine, "static"))
113		_engines_built_static[++_static] = string
114
115	if (string = get_engine_build_string(engine, "dynamic"))
116		_engines_built_dynamic[++_dynamic] = string
117
118	if (string = get_engine_build_string(engine, "no"))
119		_engines_skipped[++_skipped] = string
120
121	if (string = get_engine_build_string(engine, "wip"))
122		_engines_built_wip[++_wip] = string
123}
124
125# Get the string about building an engine
126function get_engine_build_string(engine, request_status) {
127	engine_build = get_engine_build(engine)
128	engine_build_default = get_engine_build_default(engine)
129	show = 0
130
131	# Convert static/dynamic to yes to ease the check of subengines
132	if (engine_build == "no")
133		subengine_filter = "no"
134	else
135		subengine_filter = "yes"
136
137	# Check if the current engine should be shown for the current status
138	if (engine_build == request_status) {
139		show = 1
140	} else {
141		# Test for disabled sub-engines
142		if (request_status == "no") {
143			get_engine_subengines(engine, subengines)
144			for (subeng in subengines) {
145				if (get_engine_build(subengines[subeng]) == "no") {
146					# In this case we to display _disabled_ subengines
147					subengine_filter = "no"
148					show = 1
149					break
150				}
151			}
152		}
153		# Test for enabled wip sub-engines
154		if (request_status == "wip") {
155			get_engine_subengines(engine, subengines)
156			for (subeng in subengines) {
157				if (get_engine_build(subengines[subeng]) != "no" && get_engine_build_default(subengines[subeng]) == "no") {
158					show = 1
159					break
160				}
161			}
162		}
163	}
164
165
166	# Check if it is a wip engine
167	if (request_status == "wip" && engine_build != "no" && engine_build_default == "no")
168		show = 1
169
170	# The engine should be shown, build the string
171	if (show)
172		return get_engine_name(engine) " " get_subengines_build_string(engine, subengine_filter, request_status)
173}
174
175# Get the string about building subengines
176function get_subengines_build_string(parent_engine, subengine_filter, request_status) {
177	parent_engine_build_default = get_engine_build_default(parent_engine)
178	subengine_string = ""
179
180	# If the base engine isn't built at all, no need to list subengines
181	# in any of the possible categories.
182	if (get_engine_build(parent_engine) == "no")
183		return
184
185	all = 1
186	subeng_count = get_engine_subengines(parent_engine, subengines)
187	# If there are no subengines, never display "[all games]" (for brevity).
188	if (!subeng_count)
189		all = 0
190	# If the base engine does not fit the category we're displaying here
191	# (WIP or Skipped), we should never show "[all games]"
192	if (request_status == "wip" && parent_engine_build_default == "yes")
193		all = 0
194	if (request_status == "no") {
195		# If we're here, the parent engine is built, so no need to check that.
196		all = 0
197	}
198
199
200	# In the static/dynamic categories, also display the engine's base games.
201	if (subeng_count && request_status != "no" && request_status != "wip")
202		subengine_string = "[" get_engine_base(parent_engine) "]"
203
204	for (s = 1; s <= subeng_count; s++) {
205		subeng = subengines[s]
206		subengine_build = get_engine_build(subeng)
207		subengine_build_default = get_engine_build_default(subeng)
208
209		# Display this subengine if it matches the filter, unless it is
210		# a stable subengine in the WIP request.
211		if ((subengine_build == subengine_filter) && !(request_status == "wip" && subengine_build_default == "yes")) {
212			name = "[" get_engine_name(subeng) "]"
213			if (subengine_string)
214				subengine_string = subengine_string " " name
215			else
216				subengine_string = name
217		} else {
218			all = 0
219		}
220	}
221
222	# Summarize the full list, where applicable
223	if (all)
224		subengine_string = "[all games]"
225
226	return subengine_string
227}
228
229function print_engines(headline, engines, count) {
230	if (!count)
231		return
232	print("\n" headline)
233	for (e = 1; e <= count; e++)
234		print("    " engines[e])
235}
236
237BEGIN {
238	config_mk = "config.mk.engines"
239	config_h = "config.h.engines"
240	# Clear previous contents if any
241	printf("") > config_h
242	printf("") > config_mk
243}
244
245END {
246	engine_count = get_values("_engines", engines)
247	for (e = 1; e <= engine_count; e++) {
248		engine = engines[e]
249		check_engine_deps(engine)
250		if (get_engine_sub(engine) == "no") {
251			# It's a main engine
252			if (get_engine_build(engine) == "no") {
253				isbuilt = "no"
254			} else {
255				# If dynamic plugins aren't supported, mark
256				# all the engines as static
257				if (ENVIRON["_dynamic_modules"] == "no") {
258					ENVIRON["_engine_" engine "_build"] = "static"
259				} else {
260					# If it wasn't explicitly marked as static or
261					# dynamic, use the configured default
262					if (get_engine_build(engine) == "yes")
263						ENVIRON["_engine_" engine "_build"] = ENVIRON["_plugins_default"]
264				}
265
266				# Prepare the defines
267				if (get_engine_build(engine) == "dynamic") {
268					isbuilt = "DYNAMIC_PLUGIN"
269				} else {
270					ENVIRON["_engine_" engine "_build"] = "static"
271					isbuilt = "STATIC_PLUGIN"
272				}
273			}
274		} else {
275			# It's a subengine, just say yes or no
276			if (get_engine_build(engine) == "no")
277				isbuilt = "no"
278			else
279				isbuilt = "1"
280		}
281
282		# Save the settings
283		defname = "ENABLE_" toupper(engine)
284		if (isbuilt == "no")
285			add_line_to_config_mk("# " defname)
286		else
287			add_line_to_config_mk(defname " = " isbuilt)
288	}
289
290	# Sort engines to place our headline engine at start...
291	# No technical reason, just historical convention
292	headline_engine = "scumm"
293	sorted_engines[++sorted] = headline_engine
294	for (e = 1; e <= engine_count; e++) {
295		if (engines[e] != headline_engine)
296			sorted_engines[++sorted] = engines[e]
297	}
298
299	# Prepare the information to be shown
300	for (e = 1; e <= engine_count; e++) {
301		engine = sorted_engines[e]
302		if (get_engine_sub(engine) == "no") {
303			# It's a main engine
304			prepare_engine_build_strings(engine)
305		}
306	}
307
308	#
309	# Detection of WIP/unstable engines
310	#
311	for (e in engines) {
312		engine = engines[e]
313		if (get_engine_build(engine) != "no" && get_engine_build_default(engine) == "no") {
314			_tainted_build = "yes"
315			break
316		}
317	}
318
319	add_to_config_h_if_yes(_tainted_build, "#define TAINTED_BUILD")
320	print_engines("Engines (builtin):", _engines_built_static, _static)
321	print_engines("Engines (plugins):", _engines_built_dynamic, _dynamic)
322	print_engines("Engines Skipped:", _engines_skipped, _skipped)
323	print_engines("WARNING: This ScummVM build contains the following UNSTABLE engines:", _engines_built_wip, _wip)
324
325	# Ensure engines folder exists prior to trying to generate
326	# files into it (used for out-of-tree-builds)
327	system("mkdir -p engines")
328
329	print("")
330	print("Creating engines/engines.mk")
331	engines_mk = "engines/engines.mk.new"
332	print("# This file is automatically generated by configure\n" \
333	      "# DO NOT EDIT MANUALLY\n" \
334	      "# This file is being included by \"Makefile.common\"") > engines_mk
335
336	for (e = 1; e <= engine_count; e++) {
337		engine = sorted_engines[e]
338		j = toupper(engine)
339		if (get_engine_sub(engine) == "no") {
340			# main engine
341			print("\n" \
342			      "ifdef ENABLE_" j "\n" \
343			      "DEFINES += -DENABLE_" j "=$(ENABLE_" j ")\n" \
344			      "MODULES += engines/" engine) >> engines_mk
345
346			subeng_count = get_engine_subengines(engine, subengines)
347			for (s = 1; s <= subeng_count; s++) {
348				k = toupper(subengines[s])
349				print("\n" \
350				      "ifdef ENABLE_" k "\n" \
351				      "DEFINES += -DENABLE_" k "\n" \
352				      "endif") >> engines_mk
353			}
354
355			print("endif") >> engines_mk
356		}
357	}
358
359	# Name which is suffixed to each detection plugin
360	detectId = "_DETECTION"
361	det_table = "engines/detection_table.h.new"
362
363	print("Creating engines/detection_table.h")
364	print("/* This file is automatically generated by configure */\n" \
365	      "/* DO NOT EDIT MANUALLY */\n" \
366	      "// This file is being included by \"base/plugins.cpp\"") > det_table
367
368	for (e = 1; e <= engine_count; e++) {
369		engine = sorted_engines[e]
370		if (get_engine_sub(engine) == "no") {
371			j = toupper(engine)
372			detectEngine = j detectId
373			print("#if defined(ENABLE_" j ") || defined(DETECTION_FULL)\n" \
374			      "LINK_PLUGIN(" j detectId ")\n" \
375			      "#endif") >> det_table
376		}
377	}
378
379	plugins_table = "engines/plugins_table.h.new"
380	print("Creating engines/plugins_table.h")
381	print("/* This file is automatically generated by configure */\n" \
382	      "/* DO NOT EDIT MANUALLY */\n" \
383	      "// This file is being included by \"base/plugins.cpp\"") > plugins_table
384
385	for (e = 1; e <= engine_count; e++) {
386		engine = sorted_engines[e]
387		if (get_engine_sub(engine) == "no") {
388			j = toupper(engine)
389			print("#if PLUGIN_ENABLED_STATIC(" j ")\n" \
390			      "LINK_PLUGIN(" j ")\n" \
391			      "#endif") >> plugins_table
392		}
393	}
394}
395