Code

Base implementation of a layers dialog.
[inkscape.git] / src / mkdep.pl
1 #!/usr/bin/perl
2 ############################################################################
3 #
4 # Creates make.dep - a list of all dependencies.
5 # Uses make.files as input; mkfiles.pl should be run before mkdep.pl.
6 #
7 ############################################################################
9 $obj_ext       = "o";
10 $linebreak     = "\\";
11 $dir_sep       = "/";
12 $nodepend      = 0;
13 $tolower       = 1; # lowercase all filenames
14 $include_path  = "";
16 #
17 # main - top level code
18 #
20 if ( @ARGV ) {                          # parse command line args
21     foreach $a ( @ARGV ) {
22         if ( $a eq "-w" ) {
23             $warnon = 1;
24         }
25         elsif ( ( $a eq "-?" ) || ( $a eq "-h" ) ) {
26             print "usage: perl mkdep.pl includedirs...\"\n\n" .
27               "\"includedirs\" is any number of include directories that are located\n".
28               "outside of your project directory tree.\n\n".
29               "example:\n   perl mkdep.pl s:\\ w:\\include\n";
30             exit 1;
31         }
32         else {
33             push @extradirs, $a;
34             $include_path = $include_path . $a . ";";
35         }
36     }
37     print "Includepath used: ".join(" ",@extradirs)."\n";
38 }
40 &make_files;
41 &make_dep;
42     
43 exit 0;
46 #
47 # make_files: read "make.files", create "make.ofiles"
48 #
50 sub make_files {
52     # create output file (now, to check for permissions)
53     open OFILES, ">make.ofiles" or
54         die("Can't create make.ofiles");
56     # read file list
57     #open FILES,"<make.files" or 
58     #    die "Can't open make.files";
59     #@lines = <FILES>;
60     #close FILES;
62     open FILES, "<make.files" or
63         die "Can't open make.files: $!";
64     while (<FILES>)
65         {
66         $line = $_;
67         #Trim whitespace from ends
68         $line =~ s/^\s|\t|\n//;
69         #Ignore if no text in line
70         next if ( length($line) < 1 );
71         #Ignore if starts with '#'
72         next if ( $line =~ /^#/ );
73         # print $line, "\n";
74         push @lines, $line;
75         }
76     close FILES;
78     # sort out header and source files
79     @hdr = sort grep(/\.(h|hpp|icc|ia|xpm)$/i,@lines);
80     @src = sort grep(/\.(c|cpp|cc|s)$/i,@lines);
82     print STDERR scalar @lines ." files found (".scalar @src." sources and ".scalar @hdr." headers) in \"make.files\".\n";
84     # scan specified include dirs
85     for ( @extradirs ) {
86         push @extrafiles, &find_files($_,"\.*",1);
87     }
88     # add external includefiles to file list
89     push @lines, @extrafiles;
91     print STDERR scalar @lines . " files found everywhere.\n";
93     # create @inc and %full_path
94     $last = "";
95     for ( @lines ) {
96         m/^(.*\/)([^\/]*)$/ || m/^()(.*)$/;
97         $path = $1;
98         $filepart = $2;
99         if ( $path ne $last ) {
100             # store dir path
101             if (length($path) > 0) {
102                 push (@inc, $path );
103             }
104             $last = $path;
105         }
107         # remove any newlines at end of line
108         $filepart =~ s/(.*)\n+$/$1/g;
110         # store full path for all include files
111         if ( !defined $full_path{ lc $filepart } ) {
112             $full_path{lc $filepart} = $path.$filepart;
113         }
114     }
116     $includes = join (" \\\n\t-I", @inc);
117     $includes =~ s/\/ \\/ \\/g; # remove trailing slashes
119     # save source list for use by make_depend
120     $sourcelist = join(" ",@src);
122     # create object list from source list
123     $objects = &Objects( $sourcelist );
125     # save object list for use by make_depend
126     $objectlist = $objects;
128     # make a "lints" list for linting
129     $lints = $objects;
130     $lints =~ s/\.${obj_ext}/\.lint/g;
131     $lints =~ s/ / \\\n\t/g;
133     # put newline+tab on all files (to make nice lists)
134     $objects =~ s/ / \\\n\t/g;
136     # print file
137     $datestr = gmtime();
138     print OFILES "########################################################\n";
139     print OFILES "## File: make.ofiles\n";
140     print OFILES "## Purpose: Object file listing for use by Makefiles\n";
141     print OFILES "## Generated by mkdep.pl at :$datestr\n";
142     print OFILES "## Do not edit this file! Changes will be lost.\n";
143     print OFILES "########################################################\n\n";
144     print OFILES "OBJECTS = \\\n\t" . $objects . "\n\n";
145     print OFILES "LINTS = \\\n\t" . $lints . "\n\n";
146     if ( $includes ne "" ) {
147         print OFILES "INCLUDEPATH = \\\n\t-I" . $includes . "\n";
148     }
150     close OFILES;
156 # Finds files.
158 # Examples:
159 #   find_files("/usr","\.cpp$",1)   - finds .cpp files in /usr and below
160 #   find_files("/tmp","^#",0)       - finds #* files in /tmp
163 sub find_files {
164     my($dir,$match,$descend) = @_;
165     my($file,$p,@files);
166     local(*D);
167     $dir =~ s=\\=/=g;
168     ($dir eq "") && ($dir = ".");
170     if ( opendir(D,$dir) ) {
171         if ( $dir eq "." ) {
172             $dir = "";
173         } else {
174             ($dir =~ /\/$/) || ($dir .= "/");
175         }
176         foreach $file ( readdir(D) ) {
177             
178             next if ( $file  =~ /^\.\.?$/ );
179             $p = $dir . $file;
180 #            ($file =~ /$match/i) && (push @files, ($tolower==0 ? $p : lc($p)));
181             ($file =~ /$match/i) && (push @files, $p );
182             if ( $descend && -d $p && ! -l $p ) {
183                 push @files, &find_files($p,$match,$descend);
184             }
185         }
186         closedir(D);
187     }
188     return @files;
193 # strip_project_val(tag)
195 # Strips white space from project value strings.
198 sub strip_project_val {
199     my($v) = @_;
200     $v =~ s/^\s+//;                             # trim white space
201     $v =~ s/\s+$//;
202     return $v;
206 # Objects(files)
208 # Replaces any extension with .o ($obj_ext).
211 sub Objects {
212     local($_) = @_;
213     my(@a);
214     @a = split(/\s+/,$_);
215     foreach ( @a ) {
216         s-\.\w+$-.${obj_ext}-;
217     }
218     return join(" ",@a);
222 sub make_dep {
224     $outfile = "make.dep";
225     
226     print STDERR "Parsing source files...\n";
228     open(DEP,">" . fix_path($outfile)) or
229         die ("Can't create \"$outfile\"");
231     &BuildObj( $objectlist, $sourcelist );
233     $datestr = gmtime();
234     print DEP "########################################################\n";
235     print DEP "## File: make.dep\n";
236     print DEP "## Purpose: Dependency listing for use by Makefiles\n";
237     print DEP "## Generated by mkdep.pl at :$datestr\n";
238     print DEP "## Do not edit this file! Changes will be lost.\n";
239     print DEP "########################################################\n\n";
240     print DEP $text;
241     close DEP;
242     print STDERR "\n";
245     if ( $warnon && (keys %missing) ) {
246         # print out missing files
247         if ( !open MISSING, ">makemiss.txt" ) {
248             print "Couldn't create \"makemiss.txt\": $!\n";
249             print "Printing on screen.\n";
250             *MISSING = *STDOUT;
251         }
252     
253         print MISSING "Missing files: (Note: only the first miss for each file is logged)\n\n";
254         printf MISSING "%-32s %s\n","<file>","<included from>";
255         printf MISSING "%-32s %s\n","------","---------------";
256         @missingfiles = sort @missingfiles;
257         foreach ( @missingfiles ) {
258             @a = split( ",", $_ );
259             printf MISSING "%-32s %s\n",$a[0],$a[1];
260         }
261         close MISSING;
263         print STDOUT "(missing files written to \"makemiss.txt\")\n";
264     }
269 # BuildObj(objects,sources)
271 # Builds the object files.
274 sub uniq (@) {
275     if ($#_ <= 0) {
276         return @_;
277     }
278     my $prev = shift(@_);
279     my @ret = ($prev);
280     while(@_) {
281         my $curr = shift(@_);
282         if ($curr ne $prev) {
283             push @ret, $curr;
284             $prev = $curr;
285         }
286     }
287     return @ret;
290 sub BuildObj {
291     my($obj,$src) = @_;
292     my(@objv,$srcv,$i,$s,$o,$d,$c,$comp,$cimp);
293     $text = "";
294     @objv = split(/\s+/,$obj);
295     @srcv = split(/\s+/,$src);
296     $tot = $#objv;
298     # fix dependpath
299     if ( ! $depend_path_fixed ) {
300         $depend_path_fixed = 1;
301         $depend_path = $include_path;
302         $count = 0;
304         while ( $count < 100 ) {
305             if ( $depend_path =~ s/(\$[\{\(]?\w+[\}\)]?)/035/ ) {
306                 $_ = $1;
307                 s/[\$\{\}\(\)]//g;
308                 $depend_path =~ s/035/$ENV{$_}/g;
309             } else {
310                 $count = 100;
311             }
312         }
313         @dep_path = &split_path($depend_path);
314         unshift @dep_path, ""; # current dir first
315     }
317     %missing = ();
318     # go through file list
319     for $i ( 0..$#objv ) {
320         $s = $srcv[$i];
321         $o = $objv[$i];
322         next if $s eq "";
324         if ( $warnon ) {
325             print STDERR "\r" . ($i+1) . "   missing files: ". scalar keys %missing;
326         }
327         else {
328             print STDERR "\r" . ($i+1);
329         }
331         @incfiles = ();
332         $d = &make_depend(lc $s);
334         for ( @incfiles ) {
335             push @ifiles, $full_path{$n};
336         }
338         $text .= $o . ": ${linebreak}\n\t" . $s;
340         @incpath = ();
341         for ( @incfiles ) {
342             if ( defined $full_path{$_} ) {
343                 push @incpath, $full_path{$_};
344             }
345         }
346         @incpath = uniq sort @incpath;
347         for ( @incpath ) {
348             $text .= " ${linebreak}\n\t" . $_;
349         }
350         $text .= "\n\n";
352         # -----------------------------
353 #        print "\n". $text;
354 #        exit;
355     }
356     chop $text;
361 # build_dep() - Internal for make_depend()
364 sub build_dep {
365     my($file) = @_;
366     my(@i,$a,$n);
367     $a = "";
369     if ( !defined $depend_dict{$file} ) {
370         return $a;
371     }
373     @i = split(/ /,$depend_dict{$file});
374 #    print "INC2: ($file) ".$depend_dict{$file}."\n";
376     for $n ( @i ) {
377 #        if ( (!defined $dep_dict{$n}) && defined($full_path{$n}) ) {
378         if ( !defined $dep_dict{$n} ) {
379             $dep_dict{$n} = 1;
380             push @incfiles, $n;
381 #            $a .= $full_path{$n} . " " . &build_dep($n);
382             &build_dep($n);
383         }
384     }
385 #    print "INCFILES ($file): ".@incfiles."\n";
386     return $a;
391 # make_depend(file)
393 # Returns a list of included files.
394 # Uses the global $depend_path variable.
397 sub make_depend {
398     my($file) = @_;
399     my($i,$count);
400     if ( $nodepend ) {
401         return "";
402     }
404     @cur_dep_path = @dep_path;
405     if ( $file =~ /(.*[\/\\])/ ) {
406         $dep_curdir = $1;
407         splice( @cur_dep_path, 0, 0, $dep_curdir );
408     } else {
409         $dep_curdir = "";
410     }
411     $dep_file = $file;
412     &canonical_dep($file);
413     %dep_dict = ();
416     $i = &build_dep($file);
417 #    chop $i;
419     $i =~ s=/=$dir_sep=g unless $is_unix;
420     $i =~ s=([a-zA-Z]):/=//$1/=g if (defined($gnuwin32) && $gnuwin32);
421 #    @l = sort split(/ /,$i);
422     @l = split(/ /,$i);
423     return join(" ${linebreak}\n\t", @l );
424 #    return $i; # all on one line!
428 # canonical_dep(file) - Internal for make_depend()
430 # Reads the file and all included files recursively.
431 # %depend_dict associates a file name to a list of included files.
434 sub canonical_dep {
435     my($file) = @_;
436     my(@inc,$i);
437     push @sfile, $file;
438     # -----------------------------
439 #    print "FILE: $file\n";
440     @inc = &scan_dep($file);
442     if ( @inc ) {
443         $depend_dict{$file} = join(" ",@inc);
445         # recursively scan all files not already scanned
446         for $i ( @inc ) {
447             if ( ! defined( $depend_dict{$i} ) ) {
448                 &canonical_dep($i);
450                 # still nothing defined?
451                 if ( ! defined( $depend_dict{$i} ) ) {
452                     # insert dummy string, so we don't parse the file again
453                     $depend_dict{$i} = "";
454                 }
455 #                print "CACHE: $i: $depend_dict{$i}\n";
456             }
457         }
458     }
459     pop @sfile, $file;
463 # scan_dep(file) - Internal for make_depend()
465 # Returns an array of included files.
468 sub scan_dep {
469     my($file) = @_;
470     my($dir,$path,$found,@allincs,@includes,%incs);
471     $path = ($file eq $dep_file) ? $file : $dep_curdir . $file;
472     @includes = ();
474 #    print STDERR "SCAN_DEP $file\n";
476     # replace backslash with regular slash
477     $file =~ s-\\-/-g;
479     # look in the file list
480     if ( !defined $full_path{$file} ) {
481         # file not in list - some special case
483         # handle explicit path'ed includes (such as #include "common/bsp821.h")
484         if ( $file =~ /[\/\\]([^\\\/]+)$/ ) {
485             $full_path{$file} = $full_path{$1};
486         }
487     }
489     $open = open TMP,fix_path( $full_path{$file} );
491     if ( $open ) {
492         @source = <TMP>;
494         # find all lines with include as first text in line (no comments allowed)
495         @allincs = grep(/^\s*[\#\.]\s*include/,@source); 
497 #        print "SCAN_ALLINC: $#allincs include lines found\n";
499         # iterate all include lines
500         foreach ( @allincs ) {
501             # parse out filename
502             if ( !(/\s*[\#\.]\s*include\s+[<\"]([^>\"]*)[>\"]/) || defined($incs{$1}) ) {
503                 next;
504             }
505             push(@includes, ($tolower==0 ? $1 : lc($1)));
507 #           print "SCAN_INC: $1\n";
509             $incs{$1} = "1";
510         }
512         # -----------------------------
513 #        print "INC: ".join( ",", @includes)."\n";
514         close(TMP);
515     }
516     else {
517         &add_missing( $file );
518     }
519     $/ = "\n";
520     return @includes;
524 sub add_missing {
525     my($file) = @_;
526     @s = @sfile;
527     pop @s;
528     push @missingfiles, $file.",".join(" -> ",@s);
529     $missing{$file} = 1;
533 # split_path(path)
535 # Splits a path containing : (Unix) or ; (MSDOS, NT etc.) separators.
536 # Returns an array.
539 sub split_path {
540     my($p) = @_;
541     return ""  if !defined($p);
542     $p =~ s=:=;=g if $is_unix;
543     $p =~ s=[/\\]+=/=g;
544     $p =~ s=([^/:]);=$1/;=g;
545     $p =~ s=([^:;/])$=$1/=;
546     $p =~ s=/=$dir_sep=g unless $is_unix;
547     return split(/;/,$p);
551 # fix_path(path)
553 # Converts all '\' to '/' if this really seems to be a Unix box.
556 sub fix_path {
557     my($p) = @_;
558 #    if ( $really_unix ) {
559 #        $p =~ s-\\-/-g;
560 #    } else {
561 #        $p =~ s-/-\\-g;
562         $p =~ s-\\-/-g;
563 #    }
564     return $p;