1#!/usr/bin/perl
2
3if ($ENV{"ACTION"} eq "installhdrs") {
4	exit 0;
5}
6
7# Generates the libc-features.h files used to control #ifdef behaviour in Libc
8use warnings;
9use Data::Dumper;
10use File::Path qw(mkpath);
11
12#printf Dumper(\%ENV);
13
14my $unifdef = 0;
15my %unifdefs = ();
16my $bash = 0;
17if (scalar(@ARGV) > 0) {
18	$unifdef = 1 if $ARGV[0] =~ /--unifdef/;
19	$bash = 1 if $ARGV[0] =~ /--bash/;
20}
21
22for my $arch (split(/ /, $ENV{"ARCHS"}))
23{
24	# set ENV{"CURRENT_ARCH"} so we can predicate on it
25	$ENV{"CURRENT_ARCH"} = $arch;
26
27	my $platformName = $ENV{"PLATFORM_NAME"};
28	$platformName =~ s/simulator/os/;
29
30	my $platformPath = $ENV{"SRCROOT"} . "/Platforms/" . $platformName . "/Makefile.inc";
31	my $featuresHeaderDir = $ENV{"DERIVED_FILES_DIR"}."/".$arch;
32	my $featuresHeader = $featuresHeaderDir."/libc-features.h";
33
34	open FEATURESFILE, "<$platformPath" or die "Unable to open: $platformPath";
35
36	my %features = ();
37	my $skip = 0;
38	my $nested = 0;
39
40	while (<FEATURESFILE>) {
41		next if $_ =~ /\s*#/;
42
43		if ($_ =~ /^.endif/) {
44			$skip-- if $skip > 0;
45			$nested--;
46		}
47
48		elsif ($_ =~ /^\.if\s+(\S+)\s+(\S+)/) {
49			# an if statement, very rudimentary regex against envvar
50			my $envvar = $1;
51			my $regex = $2;
52
53			$nested++;
54			if (!defined($ENV{$envvar}) || ($ENV{$envvar} !~ /$regex/)) {
55				$skip += 1;
56			}
57		}
58
59		elsif ($_ =~ /^\s*([^= ]+)\s*=\s*(\d)/) {
60			if ($skip == 0) {
61				if ($2 == 1) {
62					$features{$1} = $2;
63				} elsif (defined($features{$1})) {
64					delete $features{$1};
65				}
66			}
67		}
68	}
69
70	close FEATURESFILE;
71
72	if ($bash == 1) {
73		for my $f (keys %features) {
74			print "$f=$features{$f} ";
75		}
76		printf "\n";
77		exit 0;
78	}
79
80	elsif ($unifdef == 1) {
81		if ($platformName eq "macosx") {
82			$unifdefs{"__OSX_OPEN_SOURCE__"} = 1;
83		}
84		# assume FEATURE_BLOCKS was on by default
85		$unifdefs{"UNIFDEF_BLOCKS"} = 1;
86		$unifdefs{"UNIFDEF_LEGACY_64_APIS"} = defined($features{"FEATURE_LEGACY_64_APIS"});
87		$unifdefs{"UNIFDEF_LEGACY_RUNE_APIS"} = defined($features{"FEATURE_LEGACY_RUNE_APIS"});
88		$unifdefs{"UNIFDEF_LEGACY_UTMP_APIS"} = defined($features{"FEATURE_LEGACY_UTMP_APIS"});
89		$unifdefs{"UNIFDEF_MOVE_LOCALTIME"} = defined($features{"FEATURE_MOVE_LOCALTIME"});
90		$unifdefs{"UNIFDEF_TZDIR_SYMLINK"} = defined($features{"FEATURE_TZDIR_SYMLINK"});
91
92		my $output = "";
93		for my $d (keys %unifdefs) {
94			$output .= " " . ($unifdefs{$d} == 1 ? "-D" : "-U") . $d;
95		}
96
97		chomp $output;
98		print "$output\n";
99		exit 0;
100	}
101
102	elsif ($unifdef == 0) {
103		# If we touch this file on every build, then every other iterative build in Xcode will rebuild *everything*
104		my $platform_mtime = (stat($platformPath))[9];
105		my $header_mtime = (stat($featuresHeader))[9];
106
107		if (defined($header_mtime) && defined($platform_mtime) && ($header_mtime > $platform_mtime)) {
108			exit 0;
109		}
110
111		printf $arch." features:\n";
112		printf Dumper(\%features);
113
114		if ($nested != 0) {
115			die "Unbalanced .if/.endif directive";
116		}
117
118		# And the meat, new header options should go under here
119		if (! -d $featuresHeaderDir) {
120			mkpath $featuresHeaderDir or die "Unable to mkdir: $featuresHeaderDir";
121		}
122		open HEADER, ">$featuresHeader" or die "Unable to open (for writing): $featuresHeader";
123
124		printf HEADER "#ifndef _LIBC_FEATURES_H_\n";
125		printf HEADER "#define _LIBC_FEATURES_H_\n\n";
126
127		my $shortarch = $arch;
128		$shortarch =~ s/armv\d+[a-z]?/arm/g;
129
130		printf HEADER "#if !defined(__".$shortarch."__)\n";
131		printf HEADER "#error Mismatched libc-features.h architecture\n";
132		printf HEADER "#endif\n\n";
133
134		if (defined($features{"FEATURE_LEGACY_RUNE_APIS"})) {
135			printf HEADER "#define UNIFDEF_LEGACY_RUNE_APIS 1\n";
136		} else {
137			printf HEADER "/* #undef UNIFDEF_LEGACY_RUNE_APIS */\n";
138		}
139
140		if (defined($features{"FEATURE_LEGACY_CRT1_ENVIRON"})) {
141			printf HEADER "#define LEGACY_CRT1_ENVIRON 1\n";
142		} else {
143			printf HEADER "/* #undef LEGACY_CRT1_ENVIRON */\n";
144		}
145
146		if (defined($features{"FEATURE_LEGACY_UTMP_APIS"})) {
147			printf HEADER "#define UNIFDEF_LEGACY_UTMP_APIS 1\n";
148		} else {
149			printf HEADER "/* #undef UNIFDEF_LEGACY_UTMP_APIS */\n";
150		}
151
152		if (defined($features{"FEATURE_MOVE_LOCALTIME"})) {
153			printf HEADER "#define UNIFDEF_MOVE_LOCALTIME 1\n";
154		} else {
155			printf HEADER "/* #undef UNIFDEF_MOVE_LOCALTIME */\n";
156		}
157
158		if (defined($features{"FEATURE_TZDIR_SYMLINK"})) {
159			printf HEADER "#define UNIFDEF_TZDIR_SYMLINK 1\n";
160		} else {
161			printf HEADER "/* #undef UNIFDEF_TZDIR_SYMLINK */\n";
162		}
163
164		if (defined($features{"FEATURE_ONLY_1050_VARIANTS"})) {
165			printf HEADER "#if !__DARWIN_ONLY_VERS_1050\n";
166			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_VERS_1050 == 0\n";
167			printf HEADER "#endif /* !__DARWIN_ONLY_VERS_1050 */\n";
168		} else {
169			printf HEADER "#if __DARWIN_ONLY_VERS_1050\n";
170			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_VERS_1050 == 1\n";
171			printf HEADER "#endif /* __DARWIN_ONLY_VERS_1050 */\n";
172		}
173
174		if (defined($features{"FEATURE_ONLY_UNIX_CONFORMANCE"})) {
175			printf HEADER "#if !__DARWIN_ONLY_UNIX_CONFORMANCE\n";
176			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_UNIX_CONFORMANCE == 0\n";
177			printf HEADER "#endif /* !__DARWIN_ONLY_UNIX_CONFORMANCE */\n";
178		} else {
179			printf HEADER "#if __DARWIN_ONLY_UNIX_CONFORMANCE\n";
180			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_UNIX_CONFORMANCE == 1\n";
181			printf HEADER "#endif /* __DARWIN_ONLY_UNIX_CONFORMANCE */\n";
182		}
183
184		if (defined($features{"FEATURE_ONLY_64_BIT_INO_T"})) {
185			printf HEADER "#if !__DARWIN_ONLY_64_BIT_INO_T\n";
186			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_64_BIT_INO_T == 0\n";
187			printf HEADER "#endif /* !__DARWIN_ONLY_64_BIT_INO_T */\n";
188		} else {
189			printf HEADER "#if __DARWIN_ONLY_64_BIT_INO_T\n";
190			printf HEADER "#  error Feature mismatch: __DARWIN_ONLY_64_BIT_INO_T == 1\n";
191			printf HEADER "#endif /* __DARWIN_ONLY_64_BIT_INO_T */\n";
192		}
193
194		if (defined($features{"FEATURE_PATCH_3417676"})) {
195			printf HEADER "#define __APPLE_PR3417676_HACK__ 1\n";
196		} else {
197			printf HEADER "/* #undef __APPLE_PR3417676_HACK__ */\n";
198		}
199
200		if (defined($features{"FEATURE_PLOCKSTAT"})) {
201			printf HEADER "#define PLOCKSTAT 1\n";
202		} else {
203			printf HEADER "/* #undef PLOCKSTAT */\n";
204		}
205
206		if (defined($features{"FEATURE_TIMEZONE_CHANGE_NOTIFICATION"})) {
207			printf HEADER "#define NOTIFY_TZ 1\n";
208		} else {
209			printf HEADER "/* #undef NOTIFY_TZ */\n";
210		}
211
212		if (defined($features{"FEATURE_NO_LIBCRASHREPORTERCLIENT"})) {
213			printf HEADER "#define LIBC_NO_LIBCRASHREPORTERCLIENT 1\n";
214		} else {
215			printf HEADER "/* #undef LIBC_NO_LIBCRASHREPORTERCLIENT */\n";
216		}
217
218		if (defined($features{"FEATURE_SMALL_STDIOBUF"})) {
219			printf HEADER "#define FEATURE_SMALL_STDIOBUF 1\n";
220		} else {
221			printf HEADER "/* #undef FEATURE_SMALL_STDIOBUF */\n";
222		}
223
224		if (defined($features{"FEATURE_XPRINTF_PERF"})) {
225			printf HEADER "#define XPRINTF_PERF 1\n";
226		} else {
227			printf HEADER "/* #undef XPRINTF_PERF */\n";
228		}
229
230		printf HEADER "#endif // _LIBC_FEATURES_H_\n";
231		close HEADER;
232	}
233}
234
235exit 0;
236