build: auto generate ASN1 and ET rules
[ira/wip.git] / buildtools / mktowscript / mktowscript.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Data::Dumper;
5 use File::Basename;
6
7 my $filename=$ARGV[0];
8 my $dname=dirname($filename);
9 my $globals;
10
11 sub read_file($)
12 {
13         my $filename = shift;
14         open(CONFIG_MK, "$filename");
15         my @lines = <CONFIG_MK>;
16         close(CONFIG_MK);
17         return @lines;
18 }
19
20 sub trim($)
21 {
22         my $string = shift;
23         $string =~ s/^\s+//;
24         $string =~ s/\s+$//;
25         return $string;
26 }
27
28 sub strlist($)
29 {
30         my $s = shift;
31         $s =~ s/\$\(SHLIBEXT\)/so/g;
32         $s =~ s/\$\(heimdalsrcdir\)/..\/heimdal/g;
33         $s =~ s/\$\(heimdalbuildsrcdir\)/..\/heimdal_build/g;
34         $s =~ s/\$\(nsswitchsrcdir\)/..\/nsswitch/g;
35         $s =~ s/\$\(param_OBJ_FILES\)/..\/pyparam.c/g;
36         $s =~ s/\$\(libclisrcdir\)\///g;
37         $s =~ s/\$\(socketwrappersrcdir\)\///g;
38         $s =~ s/\$\(libcompressionsrcdir\)\///g;
39         $s =~ s/\$\(\w*srcdir\)\///g;
40         $s =~ s/\$\(libgpodir\)\///g;
41         $s =~ s/\:\.o=\.ho//g;
42         $s =~ s/\:\.o=\.d//g;
43
44         # this one doesn't exist?
45         $s =~ s/\bLDAP_ENCODE\b//g;
46
47         # these need to use the library names
48         $s =~ s/\bLIBLDB\b/ldb/g;
49         $s =~ s/\bLIBTALLOC\b/talloc/g;
50         $s =~ s/\bLIBTEVENT\b/tevent/g;
51         $s =~ s/\bRESOLV\b/resolv/g;
52
53         return trim(join(' ', split(/\s+/, $s)));
54 }
55
56 sub expand_vars($$)
57 {
58         my $vars = shift;
59         my $s = shift;
60         foreach my $v (keys %{$vars}) {
61                 if ($s =~ /\$\($v\)/) {
62                         $s =~ s/\$\($v\)/$vars->{$v}/g;
63                         delete($vars->{$v});
64                 }
65         }
66         foreach my $v (keys %{$globals}) {
67                 if ($s =~ /\$\($v\)/) {
68                         $s =~ s/\$\($v\)/$globals->{$v}/g;
69                 }
70         }
71         return $s;
72 }
73
74 sub find_file($)
75 {
76         my $f = shift;
77         my $orig = $f;
78
79         if ($f =~ /\$/) {
80                 printf(STDERR "bad variable expansion for file $orig in $dname\n");
81                 exit(1);
82         }
83
84         my $b = basename($f);
85         return $b if (-e $b);
86
87         return $f if (-e $f);
88         while ($f =~ /\//) {
89                 $f =~ s/^[^\/]+\///g;
90                 #printf(STDERR "Trying $f in $dname\n");
91                 return $f if (-e $f);
92         }
93         my $f2;
94         $f2 = `find . -name "$f" -type f`;
95         return $f2 unless ($f2 eq "");
96         $f2 = `find .. -name "$f" -type f`;
97         return $f2 unless ($f2 eq "");
98         $f2 = `find ../.. -name "$f" -type f`;
99         return $f2 unless ($f2 eq "");
100         $f2 = `find ../../.. -name "$f" -type f`;
101         return $f2 unless ($f2 eq "");
102         printf(STDERR "Failed to find $orig in $dname\n");
103         exit(1);
104         return '';
105 }
106
107 sub find_files($)
108 {
109         my $list = shift;
110         my $ret = '';
111         foreach my $f (split(/\s+/, $list)) {
112                 if ($f =~ /\.[0-9]$/) {
113                         # a man page
114                         my $m = find_file($f . ".xml");
115                         die("Unable to find man page $f\n") if ($m eq "");
116                         $m =~ s/\.xml$//;
117                         return $m;
118                 }
119                 $f = find_file($f);
120                 $f =~ s/^[.]\///;
121                 $ret .= ' ' . $f;
122         }
123         return strlist($ret);
124 }
125
126 sub read_config_mk($)
127 {
128         my $filename = shift;
129         my @lines = read_file($filename);
130         my $prev = "";
131         my $linenum = 1;
132         my $section = "GLOBAL";
133         my $infragment;
134         my $result;
135         my $line = "";
136         my $secnumber = 1;
137
138         $result->{"GLOBAL"}->{SECNUMBER} = $secnumber++;
139
140         foreach (@lines) {
141                 $linenum++;
142
143                 # lines beginning with '#' are ignored
144                 next if (/^\#.*$/);
145
146                 if (/^(.*)\\$/) {
147                         $prev .= $1;
148                         next;
149                 } else {
150                         $line = "$prev$_";
151                         $prev = "";
152                 }
153
154                 if ($line =~ /^mkinclude.*asn1_deps.pl\s+([^\s]+)\s+([^\s]+)\s+\\\$\\\(\w+\\\)\/([^\s|]+)\s*([^|]*)\|$/) {
155                         my $src = $1;
156                         $section = $2;
157                         my $dir = $3;
158                         my $options = $4;
159                         $section = "HEIMDAL_" . uc($section);
160                         $result->{$section}->{TYPE} = 'ASN1';
161                         $result->{$section}->{SECNUMBER} = $secnumber++;
162                         if ($options ne '') {
163                                 $result->{$section}->{OPTIONS} = $options;
164                         }
165                         $result->{$section}->{DIRECTORY} = $dir;
166                         $result->{$section}->{$section . '_OBJ_FILES'} = $src;
167                         next;
168                 }
169
170                 if ($line =~ /^mkinclude.*et_deps.pl\s+([^\s]+)\s+\\\$\\\(\w+\\\)\/([^\s|]+)\|$/) {
171                         my $src = $1;
172                         my $dir = $2;
173                         $section = basename($src);
174                         $section =~ s/\./_/g;
175                         $section = "HEIMDAL_" . uc($section);
176                         $result->{$section}->{TYPE} = 'ERRTABLE';
177                         $result->{$section}->{SECNUMBER} = $secnumber++;
178                         $result->{$section}->{DIRECTORY} = "$dir";
179                         $result->{$section}->{$section . '_OBJ_FILES'} = $src;
180                         next;
181                 }
182
183                 if ($line =~ /^\[(\w+)::([\w-]+)\]/)
184                 {
185                         my $type = $1;
186                         $section = $2;
187                         $infragment = 0;
188
189                         $result->{$section}->{TYPE} = $type;
190                         $result->{$section}->{SECNUMBER} = $secnumber++;
191                         next;
192                 }
193
194                 # include
195                 if ($line =~ /^mkinclude (.*)$/) {
196                         my $subfile = $1;
197                         $result->{$subfile}->{TYPE} = 'SUBCONFIG';
198                         $result->{$subfile}->{SECNUMBER} = $secnumber++;
199                         next;
200                 }
201
202                 # empty line
203                 if ($line =~ /^[ \t]*$/) {
204                         next;
205                 }
206
207                 # global stuff is considered part of the makefile
208                 if ($section eq "GLOBAL") {
209                         $infragment = 1;
210                         next;
211                 }
212
213                 # Assignment
214                 if ($line =~ /^([a-zA-Z0-9_-]+)[\t ]*=(.*)$/) {
215                         $result->{$section}->{$1} = expand_vars($result->{$section}, strlist($2));
216                         $globals->{$1} = $result->{$section}->{$1};
217                         next;
218                 }
219
220                 # +=
221                 if ($line =~ /^([a-zA-Z0-9_-]+)[\t ]*\+=(.*)$/) {
222                         if (!$result->{$section}->{$1}) {
223                                 $result->{$section}->{$1}="";
224                         }
225                         $result->{$section}->{$1} .= " " . expand_vars($result->{$section}, strlist($2));
226                         $globals->{$1} = $result->{$section}->{$1};
227                         next;
228                 }
229
230                 if ($line =~ /\$\(eval.\$\(call.proto_header_template.*,(.*),.*/) {
231                         $result->{$section}->{AUTOPROTO} = $1;
232                 }
233                 if ($line =~ /^\$\(eval/) {
234                         # skip eval lines for now
235                         next;
236                 }
237
238                 printf(STDERR "$linenum: Bad line: $line");
239         }
240
241         return $result;
242 }
243
244
245 my $result = read_config_mk($filename);
246
247 #print Dumper $result;
248
249 print "# AUTOGENERATED by mktowscript.pl\n# Please remove this notice if hand editing\n\n";
250
251 chdir($dname);
252
253 foreach my $s (sort {$result->{$a}->{SECNUMBER} <=> $result->{$b}->{SECNUMBER}} keys %{$result}) {
254     next if ($s eq "GLOBAL");
255     my $sec = $result->{$s};
256     if ($sec->{TYPE} eq "SUBCONFIG") {
257             my $d = dirname($s);
258             next if ($d eq ".");
259             printf "bld.BUILD_SUBDIR('%s')\n", dirname($s);
260     } else {
261             printf "\nbld.SAMBA_%s('%s'", $sec->{TYPE}, $s;
262             my $trailer="";
263             my $got_src = 0;
264
265             foreach my $k (keys %{$sec}) {
266                     #print "key=$k\n";
267
268                     next if ($k eq "SECNUMBER");
269                     next if ($k eq "TYPE");
270                     if ($k eq "INIT_FUNCTION") {
271                             $trailer .= sprintf(",\n\tinit_function='%s'", trim($sec->{$k}));
272                             next;
273                     }
274                     if ($k eq "INIT_FUNCTION_SENTINEL") {
275                             $trailer .= sprintf(",\n\tinit_function_sentinal='%s'", trim($sec->{$k}));
276                             next;
277                     }
278                     if ($k eq "_PY_FILES" ||
279                         $k eq "EPYDOC_OPTIONS" ||
280                         $k eq "COV_TARGET" ||
281                         $k eq "GCOV" ||
282                         $k eq "PC_FILES" ||
283                         $k eq "CONFIG4FILE" ||
284                         $k eq "LMHOSTSFILE4") {
285                             $trailer .= sprintf(",\n\t# %s='%s'", $k, trim($sec->{$k}));
286                             next;
287                     }
288                     if ($k eq "SUBSYSTEM") {
289                             $trailer .= sprintf(",\n\tsubsystem='%s'", trim($sec->{$k}));
290                             next;
291                     }
292                     if ($k eq "PRIVATE_DEPENDENCIES") {
293                             $trailer .= sprintf(",\n\tdeps='%s'", strlist($sec->{$k}));
294                             next;
295                     }
296                     if ($k eq "PUBLIC_DEPENDENCIES") {
297                             $trailer .= sprintf(",\n\tpublic_deps='%s'", strlist($sec->{$k}));
298                             next;
299                     }
300                     if ($k eq "ALIASES") {
301                             $trailer .= sprintf(",\n\taliases='%s'", strlist($sec->{$k}));
302                             next;
303                     }
304                     if ($k eq "CFLAGS") {
305                             $trailer .= sprintf(",\n\tcflags='%s'", strlist($sec->{$k}));
306                             next;
307                     }
308                     if ($k eq "OPTIONS") {
309                             $trailer .= sprintf(",\n\toptions='%s'", strlist($sec->{$k}));
310                             next;
311                     }
312                     if ($k eq "DIRECTORY") {
313                             $trailer .= sprintf(",\n\tdirectory='%s'", strlist($sec->{$k}));
314                             next;
315                     }
316                     if ($k eq "LDFLAGS") {
317                             $trailer .= sprintf(",\n\tldflags='%s'", strlist($sec->{$k}));
318                             next;
319                     }
320                     if ($k eq "INSTALLDIR") {
321                             $trailer .= sprintf(",\n\tinstalldir='%s'", strlist($sec->{$k}));
322                             next;
323                     }
324                     if ($k eq "ASN1C") {
325                             $trailer .= sprintf(",\n\tcompiler='%s'", strlist($sec->{$k}));
326                             next;
327                     }
328                     if ($k eq "ET_COMPILER") {
329                             $trailer .= sprintf(",\n\tcompiler='%s'", strlist($sec->{$k}));
330                             next;
331                     }
332                     if ($k eq "ENABLE") {
333                             my $v = strlist($sec->{$k});
334                             if ($v eq "NO") {
335                                     $trailer .= sprintf(",\n\tenabled=False");
336                                     next;
337                             }
338                             next if ($v eq "YES");
339                             die("Unknown ENABLE value $v in $s\n");
340                     }
341                     if ($k eq "USE_HOSTCC") {
342                             my $v = strlist($sec->{$k});
343                             if ($v eq "YES") {
344                                     $trailer .= sprintf(",\n\tuse_hostcc=True");
345                                     next;
346                             }
347                             next if ($v eq "NO");
348                             die("Unknown HOST_CC value $v in $s\n");
349                     }
350                     if ($k eq "$s" . "_VERSION") {
351                             $trailer .= sprintf(",\n\tvnum='%s'", strlist($sec->{$k}));
352                             next;
353                     }
354                     if ($k eq "$s" . "_SOVERSION") {
355                             next;
356                     }
357                     if ($k eq "LIBRARY_REALNAME") {
358                             $trailer .= sprintf(",\n\trealname='%s'", strlist($sec->{$k}));
359                             next;
360                     }
361                     if ($k eq "OUTPUT_TYPE") {
362                             $trailer .= sprintf(",\n\toutput_type='%s'", strlist($sec->{$k}));
363                             next;
364                     }
365                     if ($k eq "AUTOPROTO") {
366                             my $list = trim(find_files(strlist($sec->{$k})));
367                             $trailer .= sprintf(",\n\tautoproto='%s'", $list);
368                             next;
369                     }
370                     if ($k eq "PUBLIC_HEADERS") {
371                             my $list = trim(strlist($sec->{$k}));
372                             if ($list =~ /\$\(addprefix .*,(.*)\)(.*)$/) {
373                                     $list = trim("$1 $2");
374                                     $list = find_files($list);
375                             } else {
376                                     $list = trim(find_files(strlist($sec->{$k})));
377                             }
378                             $trailer .= sprintf(",\n\tpublic_headers='%s'", $list);
379                             next;
380                     }
381                     if ($k eq "MANPAGES") {
382                             my $list = trim(find_files(strlist($sec->{$k})));
383                             $trailer .= sprintf(",\n\tmanpages='%s'", $list);
384                             next;
385                     }
386                     if ($k eq "$s" . "_OBJ_FILES") {
387                             my $list = trim(strlist($sec->{$k}));
388                             $list =~ s/\.o/.c/g;
389                             if ($list =~ /\$\(addprefix .*,(.*)\)(.*)$/) {
390                                     $list = trim("$1 $2");
391                                     $list = find_files($list);
392                                     $list = "'$list'";
393                             } elsif ($list =~ /\$\(addprefix \$\((\w+)\)(.*),(.*)\)(.*)$/) {
394                                     my $src = trim($3);
395                                     my $dir = "$1$2";
396                                     $dir =~ s/\/$//;
397                                     my $res = "bld.SUBDIR('$dir', '$src')";
398                                     if ($4) {
399                                             $res = "$res + '$4'";
400                                     }
401                                     $list = $res;
402                             } else {
403                                     $list = find_files($list);
404                                     $list="'$list'";
405                             }
406                             $list =~ s/\$\(\w+srcdir\)\///g;
407                             printf(",\n\t%s", $list);
408                             $got_src = 1;
409                             next;
410                     }
411                     if ($k eq "HEIMDAL_GSSAPI_KRB5_OBJ_FILES" ||
412                         $k eq "HEIMDAL_GSSAPI_SPNEGO_OBJ_FILES" ||
413                         $k eq "HEIMDAL_HEIM_ASN1_DER_OBJ_FILES" ||
414                         $k eq "HEIMDAL_HX509_OBJH_FILES" ||
415                         $k eq "HEIMDAL_HX509_OBJG_FILES" ||
416                         $k eq "HEIMDAL_ROKEN_OBJ_FILES"
417                         ) {
418                             next;
419                     }
420                     die("Unknown keyword $k in $s\n");
421             }
422             die("No source list in $s\n") unless $got_src;
423             printf("%s\n\t)\n\n", $trailer);
424     }
425 }
426
427 #print Dumper $result;