source: trunk/IPs/systemC/processor/Morpheo/Behavioural/configure.mkf @ 2

Last change on this file since 2 was 2, checked in by kane, 17 years ago

Import Morpheo

File size: 20.9 KB
Line 
1#!/usr/bin/perl
2
3#    This file is part of MKF.
4#
5#    MKF is free software; you can redistribute it and/or modify
6#    it under the terms of the GNU General Public License as published by
7#    the Free Software Foundation; either version 2 of the License, or
8#    (at your option) any later version.
9#
10#    MKF is distributed in the hope that it will be useful,
11#    but WITHOUT ANY WARRANTY; without even the implied warranty of
12#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#    GNU General Public License for more details.
14#
15#    You should have received a copy of the GNU General Public License
16#    along with MKF; if not, write to the Free Software
17#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18#
19#    Copyright (c) 2004 Alexandre Becoulet <alexandre.becoulet@epita.fr>
20
21#use strict;
22
23my $mkf_file_gc = "mkf.info";
24
25######################################################
26#               temporary files
27#
28
29my @temp_files;
30my $tmp_dir = "/tmp";
31
32sub get_temp_file
33{
34    my ($ext_p) = @_;
35
36    my $fname;
37
38    do
39    {
40        my $random = int(rand(10000));
41        $fname = "$tmp_dir/configure_".$random."_".$ext_p;
42    }
43    while (-f $fname);
44
45    push (@temp_files, $fname);
46
47    return $fname;
48}
49
50sub clear_temp_files
51{
52    unlink($_) foreach (@temp_files);
53}
54
55######################################################
56#               Display functions
57#
58
59sub error
60{
61    $_ = @_[0];
62#    s/'/'\033[01;31m/g;
63#    s/`/\033[01;36m`/g;
64    print "[ Error ] $_\n";
65#    print "[ Error ] \033[01;31m$_\033[m\n";
66    clear_temp_files;
67    exit -1;
68}
69
70sub warning
71{
72    $_ = @_[0];
73#    s/'/'\033[01;93m/g;
74#    s/`/\033[01;36m`/g;
75    print "[Warning] $_\n";
76#    print "[Warning] \033[01;93m$_\033[m\n";
77}
78
79######################################################
80#               strings replace functions
81#
82
83sub replace
84{
85    my ($str_p, $value_p, $keyword_p) = @_;
86
87    $str_p =~ s/{$keyword_p}/$value_p/g;
88
89    return $str_p;
90}
91
92sub replace_vars
93{
94    my ($str_p, $vars_p, $keyword_p) = @_;
95
96    $str_p =~ s/{$keyword_p,([^\}]+)}/$$vars_p{$1}/g;
97
98    return $str_p;
99}
100
101sub replace_vars_list
102{
103    my ($str_p, $vars_p, $keyword_p) = @_;
104
105    while ($str_p =~ /{$keyword_p,([^\,]*),([^\}]+)}/)
106    {
107        my $var = $2;
108        my $pre = $1;
109        my $list;
110
111        $list = "$list $pre$_" foreach (split(/ +/, $$vars_p{$var}));
112        $str_p =~ s/{$keyword_p,$pre,$var}/$list/;
113    }
114
115    return $str_p;
116}
117
118sub replace_list
119{
120    my ($str_p, $list, $keyword_p) = @_;
121
122    return $str_p if (! $list);
123
124    while ($str_p =~ /{$keyword_p(!?),([^\},]+),?([^\}]*)}/)
125    {
126        my $val;
127        my $strip = $1;
128        my $match_p = $2;
129        my $prefix = $3;
130
131        foreach (@$list)
132        {
133            if (/^$match_p$/)
134            {
135                my $item = $_;
136                $item =~ s/\..*$// if ($strip);
137                $val .= " ".$prefix.$item;
138            }
139        }
140
141        $str_p =~ s/{$keyword_p$strip,[^\}]+}/$val/;
142    }
143
144    return $str_p;
145}
146
147sub replace_temp_file
148{
149    my ($str_p, $keyword_p) = @_;
150
151    while ($str_p =~ /{$keyword_p,([^\,]+),([^\}]+)}/)
152    {
153        my $id = $1;
154        my $ext = $2;
155        my $fname = get_temp_file ($ext);
156
157        $str_p =~ s/{$keyword_p,$id,$ext}/$fname/g;
158    }
159
160    return $str_p;
161}
162
163######################################################
164#           Mkf file commands functions
165#
166
167sub cmd_end_if
168{
169    my ($line_num, $dir_p, $params_p, $state_p) = @_;
170
171    error "line $line_num: no parameter expected for `@$params_p[0]'"
172        if (@$params_p != 1);
173
174    my $if_depth = $$state_p{if_depth};
175    my $if_bool = $$state_p{if_bool};
176
177    error "line $line_num: no previous _if command to end" 
178        if (! $if_depth);
179
180    $$state_p{if_depth} = $if_depth - 1;
181}
182
183sub cmd_else
184{
185    my ($line_num, $dir_p, $params_p, $state_p) = @_;
186
187    error "line $line_num: no parameter expected for `@$params_p[0]'"
188        if (@$params_p != 1);
189
190    my $if_depth = $$state_p{if_depth};
191    my $if_bool = $$state_p{if_bool};
192
193    error "line $line_num: no previous _if command" 
194        if (! $if_depth);
195
196    @{$if_bool}[$if_depth] = @{$if_bool}[$if_depth - 1] && ! @{$if_bool}[$if_depth];
197}
198
199sub cmd_if_exec_ok
200{
201    my ($line_num, $dir_p, $params_p, $state_p) = @_;
202
203    error "line $line_num: more parameters expected for `@$params_p[0]'"
204        if (@$params_p < 2);
205
206    my $if_depth = $$state_p{if_depth};
207    my $if_bool = $$state_p{if_bool};
208    my $cmd = replace_temp_file(@$params_p[1], "TEMP");
209
210    @{$if_bool}[$if_depth + 1] = @{$if_bool}[$if_depth]
211        && ! system($cmd . " > /dev/null 2>&1");
212
213    $$state_p{if_depth} = $if_depth + 1;
214}
215
216sub cmd_if_file_exists
217{
218    my ($line_num, $dir_p, $params_p, $state_p) = @_;
219
220    error "line $line_num: one parameters expected for `@$params_p[0]'"
221        if (@$params_p != 2);
222
223    my $file = @$params_p[1];
224    my $if_depth = $$state_p{if_depth};
225    my $if_bool = $$state_p{if_bool};
226
227    @{$if_bool}[$if_depth + 1] = @{$if_bool}[$if_depth] && -e $file;
228
229    $$state_p{if_depth} = $if_depth + 1;
230}
231
232sub cmd_if_in_path
233{
234    my ($line_num, $dir_p, $params_p, $state_p) = @_;
235
236    error "line $line_num: one parameters expected for `@$params_p[0]'"
237        if (@$params_p != 2);
238
239    my $exec_file = @$params_p[1];
240    my $if_depth = $$state_p{if_depth};
241    my $if_bool = $$state_p{if_bool};
242
243    @{$if_bool}[$if_depth + 1] = 0;
244
245    if (@{$if_bool}[$if_depth])
246    {
247        if ($exec_file =~ /\//)
248        {
249            @{$if_bool}[$if_depth + 1] = -x $exec_file;
250        }
251        else
252        {
253            foreach (split(/:/, $ENV{"PATH"}))
254            {
255                if (-x "$_/$exec_file")
256                {
257                    @{$if_bool}[$if_depth + 1] = 1;
258                    last;
259                }
260            }
261        }
262    }
263
264    $$state_p{if_depth} = $if_depth + 1;
265}
266
267sub cmd_if_stdout_match
268{
269    my ($line_num, $dir_p, $params_p, $state_p) = @_;
270
271    error "line $line_num: two parameters expected for `@$params_p[0]'"
272        if (@$params_p != 3);
273
274    my $str = @$params_p[1];
275    my $exec_cmd = @$params_p[2];
276    my $if_depth = $$state_p{if_depth};
277    my $if_bool = $$state_p{if_bool};
278
279    @{$if_bool}[$if_depth + 1] = @{$if_bool}[$if_depth]
280        && (`$exec_cmd 2>&1` =~ /$str/);
281
282    $$state_p{if_depth} = $if_depth + 1;
283}
284
285sub cmd_if_var_eq
286{
287    my ($line_num, $dir_p, $params_p, $state_p) = @_;
288
289    error "line $line_num: two parameters expected for `@$params_p[0]'"
290        if (@$params_p < 2);
291
292    my $vars = $$state_p{vars};
293    my $var_name = @$params_p[1];
294    my $var_value = @$params_p[2];
295    my $if_depth = $$state_p{if_depth};
296    my $if_bool = $$state_p{if_bool};
297
298    @{$if_bool}[$if_depth + 1] = @{$if_bool}[$if_depth] && (${$vars}{$var_name} eq $var_value);
299
300    $$state_p{if_depth} = $if_depth + 1;
301}
302
303sub cmd_command_add
304{
305    my ($line_num, $dir_p, $params_p, $state_p) = @_;
306
307    error "line $line_num: three parameters expected for `@$params_p[0]'"
308        if (@$params_p < 4);
309
310    my $oper = "@$params_p[1]_@$params_p[2]";
311    my $jobs = $$state_p{jobs};
312
313    $$jobs{$oper} = [] if (! exists $$jobs{$oper});
314    my $jobs_list = $$jobs{$oper};
315
316    push (@$jobs_list, join (" ", @$params_p[3..@$params_p - 1]));
317}
318
319sub cmd_clean_add
320{
321    my ($line_num, $dir_p, $params_p, $state_p) = @_;
322
323    error "line $line_num: three parameters expected for `@$params_p[0]'"
324        if (@$params_p < 4);
325
326    my $oper = "@$params_p[1]_@$params_p[2]";
327    my $torm = $$state_p{torm};
328
329    $$torm{$oper} = [] if (! exists $$torm{$oper});
330    my $torm_list = $$torm{$oper};
331
332    foreach my $item (split(/ +/, @$params_p[3]))
333    {
334        push (@$torm_list, $item);
335    }
336}
337
338# parse C like source files to get included files
339sub auto_dep_c
340{
341    my ($dir_p, $deps_p, $c_src_p, $inc_dirs) = @_;
342
343    if (! open (C_SRC, "$dir_p/$c_src_p"))
344    {
345        warning "can't open `$c_src_p' c source file";
346        return;
347    }
348
349    foreach my $c_line (<C_SRC>)
350    {
351        # find #include "" lines
352        if ($c_line =~ /^[ \t]*\#[ \t]*include[ \t]*\"(.*)\"/)
353        {
354            my $inc_file = $1;
355
356            # find included file in include directories
357            foreach my $inc_dir ((split(/ +/, $inc_dirs), "."))
358            {
359                my $abs_path = $inc_dir =~ /^\// ? $inc_dir : "$dir_p/$inc_dir";
360
361                if (! -d $abs_path)
362                {
363                    warning "can't find `$abs_path' include directory";
364                    next;
365                }
366
367                next if (! -f "$abs_path/$inc_file");
368
369                my $dep_hdr = "$inc_dir/$inc_file";
370                $dep_hdr =~ s/^.\///;
371
372                push(@$deps_p, $dep_hdr);
373            }
374        }
375    }
376}
377
378# dummy function, nothing to parse in file
379sub auto_dep_none
380{
381}
382
383my %auto_src_cmd = 
384(
385 "c_src" => \&auto_dep_c,
386 "none" => \&auto_dep_none,
387);
388
389sub cmd_auto_source_dep
390{
391    my ($line_num, $dir_p, $params_p, $state_p) = @_;
392
393    error "line $line_num: three parameters expected for `@$params_p[0]'"
394        if (@$params_p != 4);
395
396    my $deps = $$state_p{deps};                         # hash table for all target/deps of current Makefile
397    my $src_type = @$params_p[1];
398    my $ext = @$params_p[2];
399    my $ext_out = @$params_p[3];
400
401    foreach my $c_src (<$dir_p/*.$ext>)
402    {
403        $c_src = $1 if ($c_src =~ /.*\/(.*)/);
404
405        my $target = $c_src;
406        $target =~ s/\.$ext$/.$ext_out/g;
407
408        next if (${$deps}{$target});
409
410        ${$deps}{$target} = [];
411
412        push(@{${$deps}{$target}}, $c_src);
413
414        # get pointer on function for source file parse
415        if (my $func_ptr = $auto_src_cmd{$src_type})
416        {
417            # call command function
418            $func_ptr -> ($dir_p, ${$deps}{$target}, $c_src, ${$$state_p{vars}}{"inc_dirs"});
419        }
420        else
421        {
422            # error if unknow function
423            error "line $line_num: unknown source file type `$src_type'";
424        }
425    }
426}
427
428sub cmd_auto_dep
429{
430    my ($line_num, $dir_p, $params_p, $state_p) = @_;
431
432    error "line $line_num: two parameters expected for `@$params_p[0]'"
433        if (@$params_p != 3);
434
435    my $deps = $$state_p{deps};                         # hash table for all target/deps of current Makefile
436    my $ext = @$params_p[1];
437    my $ext_out = @$params_p[2];
438
439    foreach my $dep (keys(%$deps))
440    {
441        # match file name extention in existing target
442
443        next if (not ($dep =~ /[^.]*\.(.*)$/));
444        next if ($1 ne $ext);
445
446        # change extention to $ext_out
447        my $target = $dep;
448        $target =~ s/\.$ext$/.$ext_out/g;
449
450        # skip if target already exist
451
452        ${$deps}{$target} = [];
453        push(@{${$deps}{$dep}}, $target);
454    }
455}
456
457
458sub cmd_target_dep
459{
460    my ($line_num, $dir_p, $params_p, $state_p) = @_;
461
462    error "line $line_num: two parameters expected for `@$params_p[0]'"
463        if (@$params_p != 3);
464
465    my $deps = $$state_p{deps};                         # hash table for all target/deps of current Makefile
466    my $target = @$params_p[1];                         # target name
467    my @target_deps = split(/ +/, @$params_p[2]);       # target dependencies name list
468
469#    error "line $line_num: redefinition of `$target' target dependencies"
470#       if (${$deps}{$target});
471
472    foreach (@target_deps)
473    {
474        ${$deps}{$_} = [] if (! exists ${$deps}{$_});
475    }
476
477    push(@{${$deps}{$target}}, @target_deps);
478}
479
480sub cmd_target_dep_add
481{
482    my ($line_num, $dir_p, $params_p, $state_p) = @_;
483
484    error "line $line_num: two parameters expected for `@$params_p[0]'"
485        if (@$params_p != 3);
486
487    my $deps = $$state_p{deps};                         # hash table for all target/deps of current Makefile
488    my $target = @$params_p[1];                         # target name
489    my @target_deps = split(/ +/, @$params_p[2]);       # target dependencies name list
490
491    error "line $line_num: no previous dependencies for `$target' target"
492        if (! ${$deps}{$target});
493
494    foreach (@target_deps)
495    {
496        ${$deps}{$_} = "0" if (! exists ${$deps}{$_});
497    }
498
499    push (@{${$deps}{$target}}, @target_deps);
500}
501
502sub cmd_install_cmd
503{
504    my ($line_num, $dir_p, $params_p, $state_p) = @_;
505
506    error "line $line_num: one parameters expected for `@$params_p[0]'"
507        if (@$params_p != 2);
508
509    my $jobs_list = $$state_p{install};
510
511    push (@$jobs_list, @$params_p[1]);
512}
513
514sub cmd_msg_info
515{
516    my ($line_num, $dir_p, $params_p, $state_p) = @_;
517
518    print "[ info ] ", @$params_p[1], "\n";
519}
520
521sub cmd_msg_error
522{
523    my ($line_num, $dir_p, $params_p, $state_p) = @_;
524
525    error join (" ", @$params_p[1..@$params_p - 1]);
526}
527
528sub cmd_msg_warning
529{
530    my ($line_num, $dir_p, $params_p, $state_p) = @_;
531
532    warning join (" ", @$params_p[1..@$params_p - 1]);
533}
534
535sub cmd_mkf_include
536{
537    my ($line_num, $dir_p, $params_p, $state_p) = @_;
538
539    error "line $line_num: one parameters expected for `@$params_p[0]'"
540        if (@$params_p != 2);
541
542    my $filename = @$params_p[1];
543
544    local *MKF_FILE;
545    error "line $line_num: can't open `$filename' included file"
546        if (! open (MKF_FILE, "$dir_p/$filename"));
547
548    process_dir_mkffile($dir_p, $state_p, *MKF_FILE);
549}
550
551sub cmd_path_parent
552{
553    my ($line_num, $dir_p, $params_p, $state_p) = @_;
554
555    error "line $line_num: one parameters expected for `@$params_p[0]'"
556        if (@$params_p != 2);
557
558    my $vars = $$state_p{vars};
559
560    foreach my $var_name (split(/ +/, @$params_p[1]))
561    {
562        ${$vars}{$var_name} =~ s/(^| )([^\/][^ ]+)/$1..\/$2/g;
563    }
564}
565
566sub cmd_var_append
567{
568    my ($line_num, $dir_p, $params_p, $state_p) = @_;
569
570    error "line $line_num: two parameters expected for `@$params_p[0]'"
571        if (@$params_p != 3);
572
573    my $vars = $$state_p{vars};
574    my $var_name = @$params_p[1];
575    my $var_value = @$params_p[2];
576
577#    warning "line $line_num: variable `$var_name' not defined before"
578#       if (! defined $$vars{$var_name});
579
580    ${$vars}{$var_name} .= " $var_value";
581}
582
583sub cmd_var_define
584{
585    my ($line_num, $dir_p, $params_p, $state_p) = @_;
586
587    error "line $line_num: two parameters expected for `@$params_p[0]'"
588        if (@$params_p != 3);
589
590    my $vars = $$state_p{vars};
591    my $var_name = @$params_p[1];
592    my $var_value = @$params_p[2];
593
594    ${$vars}{$var_name} = $var_value;
595}
596
597sub cmd_var_undefine
598{
599    my ($line_num, $dir_p, $params_p, $state_p) = @_;
600
601    error "line $line_num: one parameters expected for `@$params_p[0]'"
602        if (@$params_p != 2);
603
604    my $vars = $$state_p{vars};
605    my $var_name = @$params_p[1];
606
607    ${$vars}{$var_name} = undef;
608}
609
610my %mkf_cmd = 
611(
612 "_end_if" => \&cmd_end_if,
613 "_else" => \&cmd_else,
614 "_if_exec_ok" => \&cmd_if_exec_ok,
615 "_if_file_exists" => \&cmd_if_file_exists,
616 "_if_in_path" => \&cmd_if_in_path,
617 "_if_stdout_match" => \&cmd_if_stdout_match,
618 "_if_var_eq" => \&cmd_if_var_eq,
619 "command_add" => \&cmd_command_add,
620 "clean_add" => \&cmd_clean_add,
621 "auto_source_dep" => \&cmd_auto_source_dep,
622 "auto_dep" => \&cmd_auto_dep,
623 "target_dep" => \&cmd_target_dep,
624 "target_dep_add" => \&cmd_target_dep_add,
625 "install_cmd" => \&cmd_install_cmd,
626 "msg_error" => \&cmd_msg_error,
627 "msg_info" => \&cmd_msg_info,
628 "msg_warning" => \&cmd_msg_warning,
629 "mkf_include" => \&cmd_mkf_include,
630 "path_parent" => \&cmd_path_parent,
631 "var_define" => \&cmd_var_define,
632 "var_append" => \&cmd_var_append,
633 "var_undefine" => \&cmd_var_undefine
634);
635
636######################################################
637#           Main processing functions
638#
639
640sub process_makefile_rule
641{
642    (my $dir_p, my $target, my $state_p, local *MAKEFILE) = @_;
643
644    return if (${$$state_p{done}}{$target});
645    ${$$state_p{done}}{$target} = "1";
646
647    # get dependencies
648    my $deps = ${$$state_p{deps}}{$target};
649    my $target_name = $target;
650
651    # get jobs list
652    my $hash;
653
654    if (-d "$dir_p/$target")
655    {
656        $hash = "enter_dir";
657        $target_name = "_".$target;
658    }
659    else
660    {
661        if (($deps && (@$deps[0] =~ /[^.]*\.(.*)/)) || ($target =~ /(all)/))
662        { $hash = $1; }
663        else
664        { $hash = "noext"; }
665       
666        if (($target =~ /[^.]*\.(.*)/) || ($target =~ /(all)/))
667        { $hash .= "_$1"; }
668        else
669        { $hash .= "_noext"; }
670    }
671
672    my $job_list = ${$$state_p{jobs}}{$hash};
673    my $rm_list = ${$$state_p{torm}}{$hash};
674
675    if ((!$deps) && (!$job_list))
676    {
677        print MAKEFILE "all:\n\n" if ($target =~ /^all$/);
678        return;
679    }
680
681    # write target
682    print MAKEFILE "$target_name:";
683
684    if ($deps)
685    {
686        foreach (@$deps)
687        {
688            if (-d "$dir_p/$_")
689            { print MAKEFILE " _$_"; }
690            else
691            { print MAKEFILE " $_"; }
692        }
693    }
694    print MAKEFILE "\n";
695
696    foreach my $job (@$job_list)
697    {
698        my $job_line = $job;
699
700        $job_line = replace_vars($job_line, $$state_p{vars}, "JVAR");
701        $job_line = replace_vars_list($job_line, $$state_p{vars}, "JLIST");
702        $job_line = replace_list($job_line, $deps, "SRC");
703        $job_line = replace($job_line, $target, "OUT");
704
705        $job_line =~ s/[\t\n ]+/ /g;
706
707        print MAKEFILE "\t$job_line\n";
708    }
709    print MAKEFILE "\n";
710
711    push (@{$$state_p{outs}}, $target) if (@$job_list); # add to out files target list
712
713    foreach my $rm (@$rm_list)
714    {
715        my $rm_line = $rm;
716
717        $rm_line = replace_vars($rm_line, $$state_p{vars}, "JVAR");
718        $rm_line = replace_list($rm_line, $deps, "SRC");
719
720        $target =~ /^([^.]*)/;
721        $rm_line = replace($rm_line, $1, "OUT!");
722
723        push (@{$$state_p{outs}}, $rm_line);
724    }
725
726    if ($deps)
727    {
728        process_makefile_rule ($dir_p, "$_", $state_p) foreach (@$deps);
729    }
730}
731
732sub process_makefile_clean
733{
734    (my $dir_p, my $target, my $state_p, local *MAKEFILE) = @_;
735
736    print MAKEFILE "clean:\n";
737
738    my @files, my @dirs;
739
740    foreach (@{$$state_p{outs}})
741    {
742        if (-d "$dir_p/$_")
743        { push (@dirs, $_) }
744        else
745        { push (@files, $_) }
746    }
747
748    foreach my $job (@{${$$state_p{jobs}}{"clean_file"}})
749    {
750        foreach (@files)
751        {
752            my $job_line = $job;
753            $job_line = replace($job_line, $_, "FILE");
754
755            print MAKEFILE "\t$job_line\n";
756        }
757    }
758
759    foreach my $job (@{${$$state_p{jobs}}{"clean_dir"}})
760    {
761        foreach (@dirs)
762        {
763            my $job_line = $job;
764            $job_line = replace($job_line, $_, "DIR");
765
766            print MAKEFILE "\t$job_line\n";
767        }
768    }
769
770    print MAKEFILE "\n";
771    print MAKEFILE "re: clean all\n\n";
772}
773
774sub process_makefile_install
775{
776    (my $dir_p, my $target, my $state_p, local *MAKEFILE) = @_;
777
778    print MAKEFILE "install:\n";
779
780    foreach my $job (@{${$$state_p{jobs}}{"install_dir"}})
781    {
782        foreach (@{$$state_p{outs}})
783        {
784            next if (! -d "$dir_p/$_");
785
786            my $job_line = $job;
787            $job_line = replace($job_line, $_, "DIR");
788
789            print MAKEFILE "\t$job_line\n";
790        }
791    }
792
793    foreach (@{$$state_p{install}})
794    {
795            print MAKEFILE "\t$_\n";
796    }
797    print MAKEFILE "\n";
798}
799
800sub process_makefile
801{
802    my ($dir_p, $state_p) = @_;
803
804    open (MAKEFILE, ">$dir_p/Makefile.mkf");
805
806    print MAKEFILE
807        "#\n".
808        "# Makefile generated by MKF configure script\n".
809        "#\n\n";
810
811    process_makefile_rule ($dir_p, "all", $state_p, *MAKEFILE);
812    process_makefile_clean ($dir_p, "clean", $state_p, *MAKEFILE);
813    process_makefile_install ($dir_p, "install", $state_p, *MAKEFILE);
814
815    close (MAKEFILE);
816}
817
818sub process_dir_mkffile
819{
820    (my $dir_p, my $state_p, local *MKF_FILE) = @_;
821
822    # line counter for error repporting
823    my $line_num = 0;
824
825    my $enter_if_depth = $$state_p{if_depth};
826
827    # used to append lines when ended with \
828    my $last = "";
829
830    # parse mkf.info file line at once
831    foreach my $line (<MKF_FILE>)
832    {
833        $line_num++;
834
835        # keep lines and concat lines ending with \
836        if ($line =~ /^(.*)\\$/)
837        {
838            $last .= $1;
839            next;
840        }
841
842        # add last line ending with \ if any
843        if ($last)
844        {
845            $line = $last.$line;
846            $last = "";
847        }
848
849        # remove leading spaces
850        $line =~ s/^[ \t]*//g;
851
852        # skip empty lines and comment lines
853        next if ($line =~ /^[ \t]*(\#.*)?$/);
854
855        # skip if conditional state is false
856        next if ((not $line =~ /^_/) && (! @{$$state_p{if_bool}}[$$state_p{if_depth}]));
857
858        # replace variables in command line
859        $line = replace_vars($line, $$state_p{vars}, "PVAR");
860        $line = replace($line, $dir_p, "PWD");
861
862        # split fields
863        my @line_l = split(/[\n\t]+/, $line);
864
865        # get pointer on function for command
866        if (my $func_ptr = $mkf_cmd{@line_l[0]})
867        {
868            # call command function
869            $func_ptr -> ($line_num, $dir_p, \@line_l, $state_p);
870        }
871        else
872        {
873            # error if unknow function
874            error "line $line_num: unknown command `@line_l[0]'";
875        }
876    }
877
878    error "line $line_num: if not closed at end of file"
879        if ($$state_p{if_depth} != $enter_if_depth);
880}
881
882sub process_dir
883{
884    my ($dir_p, %state_p) = @_;
885
886    # add local field to state structure
887    $state_p{deps} = {};                # target/dependencies for current Makefile
888    $state_p{done} = {};                # already done targets
889
890    $state_p{if_bool} = ["1"];          # conditional state stack
891    $state_p{if_depth} = 0;             # conditional state stack index
892    $state_p{outs} = [];                # output files
893    $state_p{install} = [];             # install commands
894
895    # undefine previous local variable
896    foreach (keys(%{$state_p{vars}}))
897    {
898        ${$state_p{vars}}{$_} = undef if (/^_/);
899    }
900
901    ${$state_p{vars}}{_dir} = $dir_p;
902
903    print "entering $dir_p\n";
904
905    # open mkf.info file in directory
906    local *MKF_FILE;
907    open (MKF_FILE, "$dir_p/$mkf_file_gc") || error "no $mkf_file_gc file in directory";
908
909    process_dir_mkffile($dir_p, \%state_p, *MKF_FILE);
910
911    foreach my $subdir (keys(%{$state_p{deps}}))
912    {
913        next if (! -d "$dir_p/$subdir");
914
915        my %state = 
916            (
917             "vars" => {%{$state_p{vars}}},
918             "jobs" => {%{$state_p{jobs}}},
919             "torm" => {%{$state_p{torm}}}
920             );
921
922        process_dir ("$dir_p/$subdir", %state);
923    }
924
925    # close file
926    close (MKF_FILE);
927
928    process_makefile ("$dir_p", \%state_p);
929}
930
931sub main
932{
933    # param passed to configure script on command line
934    my %param_h;
935
936    # extract variable name and value from parameter
937    foreach my $param (@ARGV)
938    {
939        if ($param =~ /--help/)
940        {
941            -f "mkf.help" && system("cat mkf.help");
942            return 0;
943        }
944
945        if ($param =~ /--enable-(.*)/)
946        {
947            $param_h{$1} = "yes";
948            next;
949        }
950
951        if ($param =~ /--disable-(.*)/)
952        {
953            $param_h{$1} = "no";
954            next;
955        }
956
957        error "bad command line parameter `$param'"
958            if (! ($param =~ /--(.*)=(.*)/));
959
960        error "command line parameter `--$1' used twice"
961            if (defined ($param_h{$1}));
962
963        $param_h{$1} = $2;
964    }
965
966    # state structure used during configure process
967    my %state =
968    (
969     "vars" => {%param_h},
970     "jobs" => {},
971     "torm" => {}
972    );
973
974    # process current directory
975    return process_dir (".", %state);
976}
977
978main;
979clear_temp_files;
980print "Done.\n";
981exit 0;
982
Note: See TracBrowser for help on using the repository browser.