]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/libdrm.git/blob - scripts/drm-scripts-gentree.pl
Use headers copied from kernel instead of shared-core
[glsdk/libdrm.git] / scripts / drm-scripts-gentree.pl
1 #!/usr/bin/perl
2 #
3 # Original version were part of Gerd Knorr's v4l scripts.
4 #
5 # Several improvements by (c) 2005-2007 Mauro Carvalho Chehab
6 #
7 # Largely re-written (C) 2007 Trent Piepho <xyzzy@speakeasy.org>
8 # Stolen for DRM usage by airlied
9 #
10 # Theory of Operation
11 #
12 # This acts as a sort of mini version of cpp, which will process
13 # #if/#elif/#ifdef/etc directives to strip out code used to support
14 # multiple kernel versions or otherwise not wanted to be sent upstream to
15 # git.
16 #
17 # Conditional compilation directives fall into two catagories,
18 # "processed" and "other".  The "other" directives are ignored and simply
19 # output as they come in without changes (see 'keep' exception).  The
20 # "processed" variaty are evaluated and only the lines in the 'true' part
21 # are kept, like cpp would do.
22 #
23 # If gentree knows the result of an expression, that directive will be
24 # "processed", otherwise it will be an "other".  gentree knows the value
25 # of LINUX_VERSION_CODE, BTTV_VERSION_CODE, the KERNEL_VERSION(x,y,z)
26 # macro, numeric constants like 0 and 1, and a few defines like MM_KERNEL
27 # and STV0297_CS2.
28 #
29 # An exception is if the comment "/*KEEP*/" appears after the expression,
30 # in which case that directive will be considered an "other" and not
31 # processed, other than to remove the keep comment.
32 #
33 # Known bugs:
34 # don't specify the root directory e.g. '/' or even '////'
35 # directives continued with a back-slash will always be ignored
36 # you can't modify a source tree in-place, i.e. source dir == dest dir
38 use strict;
39 use File::Find;
40 use Fcntl ':mode';
42 my $VERSION = shift;
43 my $SRC = shift;
44 my $DESTDIR = shift;
46 if (!defined($DESTDIR)) {
47         print "Usage:\ngentree.pl\t<version> <source dir> <dest dir>\n\n";
48         exit;
49 }
51 my $BTTVCODE = KERNEL_VERSION(0,9,17);
52 my ($LINUXCODE, $extra) = kernel_version($VERSION);
53 my $DEBUG = 0;
55 my %defs = (
56         'LINUX_VERSION_CODE' => $LINUXCODE,
57         'MM_KERNEL' => ($extra =~ /-mm/)?1:0,
58         'DRM_ODD_MM_COMPAT' => 0,
59         'I915_HAVE_FENCE' => 1,
60         'I915_HAVE_BUFFER' => 1,
61         'VIA_HAVE_DMABLIT' => 1,
62         'VIA_HAVE_CORE_MM' => 1,
63         'VIA_HAVE_FENCE' => 1,
64         'VIA_HAVE_BUFFER' => 1,
65         'SIS_HAVE_CORE_MM' => 1,
66         'DRM_FULL_MM_COMPAT' => 1,   
67         '__linux__' => 1,
68 );
70 #################################################################
71 # helpers
73 sub kernel_version($) {
74         $_[0] =~ m/(\d+)\.(\d+)\.(\d+)(.*)/;
75         return ($1*65536 + $2*256 + $3, $4);
76 }
78 # used in eval()
79 sub KERNEL_VERSION($$$) { return $_[0]*65536 + $_[1]*256 + $_[2]; }
81 sub evalexp($) {
82         local $_ = shift;
83         s|/\*.*?\*/||go;        # delete /* */ comments
84         s|//.*$||o;             # delete // comments
85         s/\bdefined\s*\(/(/go;  # defined(foo) to (foo)
86         while (/\b([_A-Za-z]\w*)\b/go) {
87                 if (exists $defs{$1}) {
88                         my $id = $1; my $pos = $-[0];
89                         s/$id/$defs{$id}/;
90                         pos = $-[0];
91                 } elsif ($1 ne 'KERNEL_VERSION') {
92                         return(undef);
93                 }
94         }
95         return(eval($_) ? 1 : 0);
96 }
98 #################################################################
99 # filter out version-specific code
101 sub filter_source ($$) {
102         my ($in,$out) = @_;
103         my $line;
104         my $level=0;
105         my %if = ();
106         my %state = ();
108         my @dbgargs = \($level, %state, %if, $line);
109         sub dbgline($\@) {
110                 my $level = ${$_[1][0]};
111                 printf STDERR ("/* BP %4d $_[0] state=$_[1][1]->{$level} if=$_[1][2]->{$level} level=$level (${$_[1][3]}) */\n", $.) if $DEBUG;
112         }
114         open IN, '<', $in or die "Error opening $in: $!\n";
115         open OUT, '>', $out or die "Error opening $out: $!\n";
117         print STDERR "File: $in, for kernel $VERSION($LINUXCODE)/\n" if $DEBUG;
119         while ($line = <IN>) {
120                 chomp $line;
121                 next if ($line =~ m/^#include \"compat.h\"/o);
122 #               next if ($line =~ m/[\$]Id:/);
124                 # For "#if 0 /*KEEP*/;" the ; should be dropped too
125                 if ($line =~ m@^\s*#\s*if(n?def)?\s.*?(\s*/\*\s*(?i)keep\s*\*/;?)@) {
126                         $state{$level} = "ifother";
127                         $if{$level} = 1;
128                         dbgline "#if$1 (keep)", @dbgargs;
129                         $line =~ s/\Q$2\E//;
130                         $level++;
131                 }
132                 # handle all ifdef/ifndef lines
133                 elsif ($line =~ /^\s*#\s*if(n?)def\s*(\w+)/o) {
134                         if (exists $defs{$2}) {
135                                 $state{$level} = 'if';
136                                 $if{$level} = ($1 eq 'n') ? !$defs{$2} : $defs{$2};
137                                 dbgline "#if$1def $2", @dbgargs;
138                                 $level++;
139                                 next;
140                         }
141                         $state{$level} = "ifother";
142                         $if{$level} = 1;
143                         dbgline "#if$1def (other)", @dbgargs;
144                         $level++;
145                 }
146                 # handle all ifs
147                 elsif ($line =~ /^\s*#\s*if\s+(.*)$/o) {
148                         my $res = evalexp($1);
149                         if (defined $res) {
150                                 $state{$level} = 'if';
151                                 $if{$level} = $res;
152                                 dbgline '#if '.($res?'(yes)':'(no)'), @dbgargs;
153                                 $level++;
154                                 next;
155                         } else {
156                                 $state{$level} = 'ifother';
157                                 $if{$level} = 1;
158                                 dbgline '#if (other)', @dbgargs;
159                                 $level++;
160                         }
161                 }
162                 # handle all elifs
163                 elsif ($line =~ /^\s*#\s*elif\s+(.*)$/o) {
164                         my $exp = $1;
165                         $level--;
166                         $level < 0 and die "more elifs than ifs";
167                         $state{$level} =~ /if/ or die "unmatched elif";
169                         if ($state{$level} eq 'if' && !$if{$level}) {
170                                 my $res = evalexp($exp);
171                                 defined $res or die 'moving from if to ifother';
172                                 $state{$level} = 'if';
173                                 $if{$level} = $res;
174                                 dbgline '#elif1 '.($res?'(yes)':'(no)'), @dbgargs;
175                                 $level++;
176                                 next;
177                         } elsif ($state{$level} ne 'ifother') {
178                                 $if{$level} = 0;
179                                 $state{$level} = 'elif';
180                                 dbgline '#elif0', @dbgargs;
181                                 $level++;
182                                 next;
183                         }
184                         $level++;
185                 }
186                 elsif ($line =~ /^\s*#\s*else/o) {
187                         $level--;
188                         $level < 0 and die "more elses than ifs";
189                         $state{$level} =~ /if/ or die "unmatched else";
190                         $if{$level} = !$if{$level} if ($state{$level} eq 'if');
191                         $state{$level} =~ s/^if/else/o; # if -> else, ifother -> elseother, elif -> elif
192                         dbgline '#else', @dbgargs;
193                         $level++;
194                         next if $state{$level-1} !~ /other$/o;
195                 }
196                 elsif ($line =~ /^\s*#\s*endif/o) {
197                         $level--;
198                         $level < 0 and die "more endifs than ifs";
199                         dbgline '#endif', @dbgargs;
200                         next if $state{$level} !~ /other$/o;
201                 }
203                 my $print = 1;
204                 for (my $i=0;$i<$level;$i++) {
205                         next if $state{$i} =~ /other$/o;        # keep code in ifother/elseother blocks
206                         if (!$if{$i}) {
207                                 $print = 0;
208                                 dbgline 'DEL', @{[\$i, \%state, \%if, \$line]};
209                                 last;
210                         }
211                 }
212                 print OUT "$line\n" if $print;
213         }
214         close IN;
215         close OUT;
218 #################################################################
220 sub parse_dir {
221         my $file = $File::Find::name;
223         return if ($file =~ /CVS/);
224         return if ($file =~ /~$/);
226         my $f2 = $file;
227         $f2 =~ s/^\Q$SRC\E/$DESTDIR/;
229         my $mode = (stat($file))[2];
230         if ($mode & S_IFDIR) {
231                 print("mkdir -p '$f2'\n");
232                 system("mkdir -p '$f2'");  # should check for error
233                 return;
234         }
235         print "from $file to $f2\n";
237         if ($file =~ m/.*\.[ch]$/) {
238                 filter_source($file, $f2);
239         } else {
240                 system("cp $file $f2");
241         }
245 # main
247 printf "kernel is %s (0x%x)\n",$VERSION,$LINUXCODE;
249 # remove any trailing slashes from dir names.  don't pass in just '/'
250 $SRC =~ s|/*$||; $DESTDIR =~ s|/*$||;
252 print "finding files at $SRC\n";
254 find({wanted => \&parse_dir, no_chdir => 1}, $SRC);