util/bin/syncqt
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 #!/usr/bin/perl -w
       
     2 ######################################################################
       
     3 #
       
     4 # Synchronizes Qt header files - internal development tool.
       
     5 #
       
     6 # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     7 # Contact: Nokia Corporation (qt-info@nokia.com)
       
     8 #
       
     9 ######################################################################
       
    10 
       
    11 # use packages -------------------------------------------------------
       
    12 use File::Basename;
       
    13 use File::Path;
       
    14 use Cwd;
       
    15 use Config;
       
    16 use strict;
       
    17 
       
    18 for (my $i = 0; $i < $#ARGV; $i++) {
       
    19     if ($ARGV[$i] eq "-base-dir" && $i < $#ARGV - 1) {
       
    20         $ENV{"QTDIR"} = $ARGV[$i + 1];
       
    21         last;
       
    22     }
       
    23 }
       
    24 
       
    25 die "syncqt: QTDIR not defined" if ! $ENV{"QTDIR"}; # sanity check
       
    26 
       
    27 # global variables
       
    28 my $isunix = 0;
       
    29 my $basedir = $ENV{"QTDIR"};
       
    30 $basedir =~ s=\\=/=g;
       
    31 my %modules = ( # path to module name map
       
    32         "QtGui" => "$basedir/src/gui",
       
    33         "QtOpenGL" => "$basedir/src/opengl",
       
    34         "QtOpenVG" => "$basedir/src/openvg",
       
    35         "QtCore" => "$basedir/src/corelib",
       
    36         "QtXml" => "$basedir/src/xml",
       
    37         "QtXmlPatterns" => "$basedir/src/xmlpatterns",
       
    38         "QtSql" => "$basedir/src/sql",
       
    39         "QtNetwork" => "$basedir/src/network",
       
    40         "QtSvg" => "$basedir/src/svg",
       
    41         "QtDeclarative" => "$basedir/src/declarative",
       
    42         "QtScript" => "$basedir/src/script",
       
    43         "QtScriptTools" => "$basedir/src/scripttools",
       
    44         "Qt3Support" => "$basedir/src/qt3support",
       
    45         "ActiveQt" => "$basedir/src/activeqt/container;$basedir/src/activeqt/control;$basedir/src/activeqt/shared",
       
    46         "QtTest" => "$basedir/src/testlib",
       
    47         "QtAssistant" => "$basedir/tools/assistant/compat/lib",
       
    48         "QtHelp" => "$basedir/tools/assistant/lib",
       
    49         "QtDesigner" => "$basedir/tools/designer/src/lib",
       
    50         "QtUiTools" => "$basedir/tools/designer/src/uitools",
       
    51         "QtDBus" => "$basedir/src/dbus",
       
    52         "QtWebKit" => "$basedir/src/3rdparty/webkit/WebCore",
       
    53         "phonon" => "$basedir/src/phonon",
       
    54         "QtMultimedia" => "$basedir/src/multimedia",
       
    55 );
       
    56 my %moduleheaders = ( # restrict the module headers to those found in relative path
       
    57         "QtWebKit" => "../WebKit/qt/Api",
       
    58         "phonon" => "../3rdparty/phonon/phonon",
       
    59 );
       
    60 
       
    61 #$modules{"QtCore"} .= ";$basedir/mkspecs/" . $ENV{"MKSPEC"} if defined $ENV{"MKSPEC"};
       
    62 
       
    63 # global variables (modified by options)
       
    64 my $module = 0;
       
    65 my $showonly = 0;
       
    66 my $remove_stale = 1;
       
    67 my $force_win = 0;
       
    68 my $force_relative = 0;
       
    69 my $check_includes = 0;
       
    70 my $copy_headers = 0;
       
    71 my $create_uic_class_map = 1;
       
    72 my $create_private_headers = 1;
       
    73 my $oneway = 0;
       
    74 my @modules_to_sync ;
       
    75 $force_relative = 1 if ( -d "/System/Library/Frameworks" );
       
    76 my $out_basedir = $basedir;
       
    77 $out_basedir =~ s=\\=/=g;
       
    78 my $out_subdir = 'include';
       
    79 
       
    80 # functions ----------------------------------------------------------
       
    81 
       
    82 ######################################################################
       
    83 # Syntax:  showUsage()
       
    84 # Params:  -none-
       
    85 #
       
    86 # Purpose: Show the usage of the script.
       
    87 # Returns: -none-
       
    88 ######################################################################
       
    89 sub showUsage
       
    90 {
       
    91     print "$0 usage:\n";
       
    92     print "  -copy                 Copy headers instead of include-fwd(default: " . ($copy_headers ? "yes" : "no") . ")\n";
       
    93     print "  -remove-stale         Removes stale headers              (default: " . ($remove_stale ? "yes" : "no") . ")\n";
       
    94     print "  -relative             Force relative symlinks            (default: " . ($force_relative ? "yes" : "no") . ")\n";
       
    95     print "  -windows              Force platform to Windows          (default: " . ($force_win ? "yes" : "no") . ")\n";
       
    96     print "  -showonly             Show action but not perform        (default: " . ($showonly ? "yes" : "no") . ")\n";
       
    97     print "  -outdir <PATH>        Specify output directory for sync  (default: $out_basedir)\n";
       
    98     print "  -outsubdir <DIR>      Target subdir under outdir         (default: $out_subdir)\n";
       
    99     print "  -public               Create only public headers         (default: " . ($create_private_headers ? "no" : "yes") . ")\n";
       
   100     print "  -oneway               Don't sync back from outdir        (default: " . ($oneway ? "yes" : "no") . ")\n";
       
   101     print "  -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR> Create headers for <NAME> with original headers in <HEADERDIR> relative to <PROFILEDIR> \n";
       
   102     print "  -help                 This help\n";
       
   103     exit 0;
       
   104 }
       
   105 
       
   106 ######################################################################
       
   107 # Syntax:  checkUnix()
       
   108 # Params:  -none-
       
   109 #
       
   110 # Purpose: Check if script runs on a Unix system or not. Cygwin
       
   111 #          systems are _not_ detected as Unix systems.
       
   112 # Returns: 1 if a unix system, else 0.
       
   113 ######################################################################
       
   114 sub checkUnix {
       
   115     my ($r) = 0;
       
   116     if ( $force_win != 0) {
       
   117         return 0;
       
   118     } elsif ( -f "/bin/uname" ) {
       
   119         $r = 1;
       
   120         (-f "\\bin\\uname") && ($r = 0);
       
   121     } elsif ( -f "/usr/bin/uname" ) {
       
   122         $r = 1;
       
   123         (-f "\\usr\\bin\\uname") && ($r = 0);
       
   124     }
       
   125     if($r) {
       
   126         $_ = $Config{'osname'};
       
   127         $r = 0 if( /(ms)|(cyg)win/i );
       
   128     }
       
   129     return $r;
       
   130 }
       
   131 
       
   132 sub checkRelative {
       
   133     my ($dir) = @_;
       
   134     return 0 if($dir =~ /^\//);
       
   135     return 0 if(!checkUnix() && $dir =~ /[a-zA-Z]:[\/\\]/);
       
   136     return 1;
       
   137 }
       
   138 
       
   139 ######################################################################
       
   140 # Syntax:  shouldMasterInclude(iheader)
       
   141 # Params:  iheader, string, filename to verify inclusion
       
   142 #
       
   143 # Purpose: Determines if header should be in the master include file.
       
   144 # Returns: 0 if file contains "#pragma qt_no_master_include" or not
       
   145 #          able to open, else 1.
       
   146 ######################################################################
       
   147 sub shouldMasterInclude {
       
   148     my ($iheader) = @_;
       
   149     return 0 if(basename($iheader) =~ /_/);
       
   150     return 0 if(basename($iheader) =~ /qconfig/);
       
   151     if(open(F, "<$iheader")) {
       
   152         while(<F>) {
       
   153 	    chomp;
       
   154 	    return 0 if(/^\#pragma qt_no_master_include$/);
       
   155 	}
       
   156 	close(F);
       
   157     } else {
       
   158 	return 0;
       
   159     }
       
   160     return 1;
       
   161 }
       
   162 
       
   163 ######################################################################
       
   164 # Syntax:  classNames(iheader)
       
   165 # Params:  iheader, string, filename to parse for classname "symlinks"
       
   166 #
       
   167 # Purpose: Scans through iheader to find all classnames that should be
       
   168 #          synced into library's include structure.
       
   169 # Returns: List of all class names in a file.
       
   170 ######################################################################
       
   171 sub classNames {
       
   172     my @ret;
       
   173     my ($iheader) = @_;
       
   174     if(basename($iheader) eq "qglobal.h") {
       
   175 	push @ret, "QtGlobal";
       
   176     } elsif(basename($iheader) eq "qendian.h") {
       
   177 	push @ret, "QtEndian";
       
   178     } elsif(basename($iheader) eq "qconfig.h") {
       
   179         push @ret, "QtConfig";
       
   180     } elsif(basename($iheader) eq "qplugin.h") {
       
   181 	push @ret, "QtPlugin";
       
   182     } elsif(basename($iheader) eq "qalgorithms.h") {
       
   183 	push @ret, "QtAlgorithms";
       
   184     } elsif(basename($iheader) eq "qcontainerfwd.h") {
       
   185 	push @ret, "QtContainerFwd";
       
   186     } elsif(basename($iheader) eq "qdebug.h") {
       
   187         push @ret, "QtDebug";
       
   188     } elsif(basename($iheader) eq "qevent.h") {
       
   189         push @ret, "QtEvents";
       
   190     } elsif(basename($iheader) eq "qnamespace.h") {
       
   191         push @ret, "Qt"
       
   192     } elsif(basename($iheader) eq "qssl.h") {
       
   193 	push @ret, "QSsl";
       
   194     } elsif(basename($iheader) eq "qtest.h") {
       
   195         push @ret, "QTest"
       
   196     } elsif(basename($iheader) eq "qtconcurrentmap.h") {
       
   197         push @ret, "QtConcurrentMap"
       
   198     } elsif(basename($iheader) eq "qtconcurrentfilter.h") {
       
   199         push @ret, "QtConcurrentFilter"
       
   200     } elsif(basename($iheader) eq "qtconcurrentrun.h") {
       
   201         push @ret, "QtConcurrentRun"
       
   202     } elsif(basename($iheader) eq "qaudio.h") {
       
   203         push @ret, "QAudio"
       
   204     }
       
   205 
       
   206     my $parsable = "";
       
   207     if(open(F, "<$iheader")) {
       
   208         while(<F>) {
       
   209             my $line = $_;
       
   210             chomp $line;
       
   211 			chop $line if ($line =~ /\r$/);
       
   212             if($line =~ /^\#/) {
       
   213                 if($line =~ /\\$/) {
       
   214                     while($line = <F>) {
       
   215                         chomp $line;
       
   216                         last unless($line =~ /\\$/);
       
   217                     }
       
   218                 }
       
   219 		return @ret if($line =~ m/^#pragma qt_sync_stop_processing/);
       
   220                 push(@ret, "$1") if($line =~ m/^#pragma qt_class\(([^)]*)\)[\r\n]*$/);
       
   221 		$line = 0;
       
   222             }
       
   223 	    if($line) {
       
   224                 $line =~ s,//.*$,,; #remove c++ comments
       
   225 	        $line .= ";" if($line =~ m/^Q_[A-Z_]*\(.*\)[\r\n]*$/); #qt macro
       
   226 	        $line .= ";" if($line =~ m/^QT_(BEGIN|END)_HEADER[\r\n]*$/); #qt macro
       
   227 	        $line .= ";" if($line =~ m/^QT_(BEGIN|END)_NAMESPACE[\r\n]*$/); #qt macro
       
   228 	        $line .= ";" if($line =~ m/^QT_MODULE\(.*\)[\r\n]*$/); # QT_MODULE macro
       
   229                 $parsable .= " " . $line;
       
   230 	    }
       
   231         }
       
   232         close(F);
       
   233     }
       
   234 
       
   235     my $last_definition = 0;
       
   236     my @namespaces;
       
   237     for(my $i = 0; $i < length($parsable); $i++) {
       
   238         my $definition = 0;
       
   239         my $character = substr($parsable, $i, 1);
       
   240         if($character eq "/" && substr($parsable, $i+1, 1) eq "*") { #I parse like this for greedy reasons
       
   241             for($i+=2; $i < length($parsable); $i++) {
       
   242                 my $end = substr($parsable, $i, 2);
       
   243                 if($end eq "*/") {
       
   244                     $last_definition = $i+2;
       
   245                     $i++;
       
   246                     last;
       
   247                 }
       
   248             }
       
   249         } elsif($character eq "{") {
       
   250             my $brace_depth = 1;
       
   251             my $block_start = $i + 1;
       
   252           BLOCK: for($i+=1; $i < length($parsable); $i++) {
       
   253               my $ignore = substr($parsable, $i, 1);
       
   254               if($ignore eq "{") {
       
   255                   $brace_depth++;
       
   256               } elsif($ignore eq "}") {
       
   257                   $brace_depth--;
       
   258                   unless($brace_depth) {
       
   259                       for(my $i2 = $i+1; $i2 < length($parsable); $i2++) {
       
   260                           my $end = substr($parsable, $i2, 1);
       
   261                           if($end eq ";" || $end ne " ") {
       
   262                               $definition = substr($parsable, $last_definition, $block_start - $last_definition) . "}";
       
   263                               $i = $i2 if($end eq ";");
       
   264                               $last_definition = $i + 1;
       
   265                               last BLOCK;
       
   266 			  }
       
   267                       }
       
   268                   }
       
   269               }
       
   270           }
       
   271         } elsif($character eq ";") {
       
   272             $definition = substr($parsable, $last_definition, $i - $last_definition + 1);
       
   273             $last_definition = $i + 1;
       
   274 	} elsif($character eq "}") {
       
   275 	    # a naked } must be a namespace ending
       
   276 	    # if it's not a namespace, it's eaten by the loop above
       
   277 	    pop @namespaces;
       
   278 	    $last_definition = $i + 1;
       
   279 	}
       
   280 
       
   281 	if (substr($parsable, $last_definition, $i - $last_definition + 1) =~ m/ namespace ([^ ]*) /
       
   282 	    && substr($parsable, $i+1, 1) eq "{") {
       
   283 	    push @namespaces, $1;
       
   284 
       
   285 	    # Eat the opening { so that the condensing loop above doesn't see it
       
   286 	    $i++;
       
   287 	    $last_definition = $i + 1;
       
   288 	}
       
   289 
       
   290         if($definition) {
       
   291 	    $definition =~ s=[\n\r]==g;
       
   292             my @symbols;
       
   293             if($definition =~ m/^ *typedef *.*\(\*([^\)]*)\)\(.*\);$/) {
       
   294 		push @symbols, $1;
       
   295             } elsif($definition =~ m/^ *typedef +(.*) +([^ ]*);$/) {
       
   296 		push @symbols, $2;
       
   297             } elsif($definition =~ m/^ *(template *<.*> *)?(class|struct) +([^ ]* +)?([^<\s]+) ?(<[^>]*> ?)?\s*((,|:)\s*(public|protected|private) *.*)? *\{\}$/) {
       
   298 		push @symbols, $4;
       
   299             } elsif($definition =~ m/^ *Q_DECLARE_.*ITERATOR\((.*)\);$/) {
       
   300 		push @symbols, "Q" . $1 . "Iterator";
       
   301 		push @symbols, "QMutable" . $1 . "Iterator";
       
   302 	    }
       
   303 
       
   304 	    foreach (@symbols) {
       
   305 		my $symbol = $_;
       
   306 		$symbol = (join("::", @namespaces) . "::" . $symbol) if (scalar @namespaces);
       
   307 		push @ret, $symbol
       
   308 		    if ($symbol =~ /^Q[^:]*$/		# no-namespace, starting with Q
       
   309 			|| $symbol =~ /^Phonon::/);	# or in the Phonon namespace
       
   310             }
       
   311         }
       
   312     }
       
   313     return @ret;
       
   314 }
       
   315 
       
   316 ######################################################################
       
   317 # Syntax:  syncHeader(header, iheader, copy)
       
   318 # Params:  header, string, filename to create "symlink" for
       
   319 #          iheader, string, destination name of symlink
       
   320 #          copy, forces header to be a copy of iheader
       
   321 #
       
   322 # Purpose: Syncronizes header to iheader
       
   323 # Returns: 1 if successful, else 0.
       
   324 ######################################################################
       
   325 sub syncHeader {
       
   326     my ($header, $iheader, $copy) = @_;
       
   327     $iheader =~ s=\\=/=g;
       
   328     $header =~ s=\\=/=g;
       
   329     return copyFile($iheader, $header) if($copy);
       
   330 
       
   331     unless(-e "$header") {
       
   332         my $header_dir = dirname($header);
       
   333         mkpath $header_dir, 0777;
       
   334 
       
   335         #write it
       
   336         my $iheader_out = fixPaths($iheader, $header_dir);
       
   337         open HEADER, ">$header" || die "Could not open $header for writing!\n";
       
   338         print HEADER "#include \"$iheader_out\"\n";
       
   339         close HEADER;
       
   340         return 1;
       
   341     }
       
   342     return 0;
       
   343 }
       
   344 
       
   345 ######################################################################
       
   346 # Syntax:  fixPaths(file, dir)
       
   347 # Params:  file, string, filepath to be made relative to dir
       
   348 #          dir, string, dirpath for point of origin
       
   349 #
       
   350 # Purpose: file is made relative (if possible) of dir.
       
   351 # Returns: String with the above applied conversion.
       
   352 ######################################################################
       
   353 sub fixPaths {
       
   354     my ($file, $dir) = @_;
       
   355     $dir =~ s=^$basedir/=$out_basedir/= if(!($basedir eq $out_basedir));
       
   356     $file =~ s=\\=/=g;
       
   357     $file =~ s/\+/\\+/g;
       
   358     $dir =~ s=\\=/=g;
       
   359     $dir =~ s/\+/\\+/g;
       
   360 
       
   361     #setup
       
   362     my $ret = $file;
       
   363     my $file_dir = dirname($file);
       
   364     if($file_dir eq ".") {
       
   365         $file_dir = getcwd();
       
   366         $file_dir =~ s=\\=/=g;
       
   367     }
       
   368     $file_dir =~ s,/cygdrive/([a-zA-Z])/,$1:,g;
       
   369     if($dir eq ".") {
       
   370         $dir = getcwd();
       
   371         $dir =~ s=\\=/=g;
       
   372     }
       
   373     $dir =~ s,/cygdrive/([a-zA-Z])/,$1:/,g;
       
   374     return basename($file) if("$file_dir" eq "$dir");
       
   375 
       
   376     #guts
       
   377     my $match_dir = 0;
       
   378     for(my $i = 1; $i < length($file_dir); $i++) {
       
   379         my $slash = index($file_dir, "/", $i);
       
   380         last if($slash == -1);
       
   381         my $tmp = substr($file_dir, 0, $slash);
       
   382         last unless($dir =~ m,^$tmp/,);
       
   383         $match_dir = $tmp;
       
   384         $i = $slash;
       
   385     }
       
   386     if($match_dir) {
       
   387         my $after = substr($dir, length($match_dir));
       
   388         my $count = ($after =~ tr,/,,);
       
   389         my $dots = "";
       
   390         for(my $i = 0; $i < $count; $i++) {
       
   391             $dots .= "../";
       
   392         }
       
   393         $ret =~ s,^$match_dir,$dots,;
       
   394     }
       
   395     $ret =~ s,/+,/,g;
       
   396     return $ret;
       
   397 }
       
   398 
       
   399 ######################################################################
       
   400 # Syntax:  fileContents(filename)
       
   401 # Params:  filename, string, filename of file to return contents
       
   402 #
       
   403 # Purpose: Get the contents of a file.
       
   404 # Returns: String with contents of the file, or empty string if file
       
   405 #          doens't exist.
       
   406 # Warning: Dies if it does exist but script cannot get read access.
       
   407 ######################################################################
       
   408 sub fileContents {
       
   409     my ($filename) = @_;
       
   410     my $filecontents = "";
       
   411     if (-e $filename) {
       
   412         open(I, "< $filename") || die "Could not open $filename for reading, read block?";
       
   413         local $/;
       
   414         binmode I;
       
   415         $filecontents = <I>;
       
   416         close I;
       
   417     }
       
   418     return $filecontents;
       
   419 }
       
   420 
       
   421 ######################################################################
       
   422 # Syntax:  fileCompare(file1, file2)
       
   423 # Params:  file1, string, filename of first file
       
   424 #          file2, string, filename of second file
       
   425 #
       
   426 # Purpose: Determines if files are equal, and which one is newer.
       
   427 # Returns: 0 if files are equal no matter the timestamp, -1 if file1
       
   428 #          is newer, 1 if file2 is newer.
       
   429 ######################################################################
       
   430 sub fileCompare {
       
   431     my ($file1, $file2) = @_;
       
   432     my $file1contents = fileContents($file1);
       
   433     my $file2contents = fileContents($file2);
       
   434     if (! -e $file1) { return 1; }
       
   435     if (! -e $file2) { return -1; }
       
   436     return $file1contents ne $file2contents ? (stat("$file2"))[9] <=> (stat("$file1"))[9] : 0;
       
   437 }
       
   438 
       
   439 ######################################################################
       
   440 # Syntax:  copyFile(file, ifile)
       
   441 # Params:  file, string, filename to create duplicate for
       
   442 #          ifile, string, destination name of duplicate
       
   443 #
       
   444 # Purpose: Keeps files in sync so changes in the newer file will be
       
   445 #          written to the other. Don't sync back if $oneway is set.
       
   446 # Returns: 1 if files were synced, else 0.
       
   447 # Warning: Dies if script cannot get write access.
       
   448 ######################################################################
       
   449 sub copyFile
       
   450 {
       
   451     my ($file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
       
   452     # Bi-directional synchronization
       
   453     open( I, "< " . $file ) || die "Could not open $file for reading";
       
   454     local $/;
       
   455     binmode I;
       
   456     $filecontents = <I>;
       
   457     close I;
       
   458     if ( open(I, "< " . $ifile) ) {
       
   459 	local $/;
       
   460 	binmode I;
       
   461 	$ifilecontents = <I>;
       
   462 	close I;
       
   463 	$copy = fileCompare($file, $ifile);
       
   464 	$knowdiff = 0,
       
   465     } else {
       
   466 	$copy = -1;
       
   467 	$knowdiff = 1;
       
   468     }
       
   469 
       
   470     if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
       
   471 	if ( $copy > 0 && !$oneway) {
       
   472 	    my $file_dir = dirname($file);
       
   473 	    mkpath $file_dir, 0777 unless(-e "$file_dir");
       
   474 	    print "$file $ifile $copy\n";
       
   475 	    open(O, "> " . $file) || die "Could not open $file for writing (no write permission?)";
       
   476 	    local $/;
       
   477 	    binmode O;
       
   478 	    print O $ifilecontents;
       
   479 	    close O;
       
   480 	    return 1;
       
   481 	} elsif ( $copy < 0 ) {
       
   482 	    my $ifile_dir = dirname($ifile);
       
   483 	    mkpath $ifile_dir, 0777 unless(-e "$ifile_dir");
       
   484 	    open(O, "> " . $ifile) || die "Could not open $ifile for writing (no write permission?)";
       
   485 	    local $/;
       
   486 	    binmode O;
       
   487 	    print O $filecontents;
       
   488 	    close O;
       
   489 	    return 1;
       
   490 	}
       
   491     }
       
   492     return 0;
       
   493 }
       
   494 
       
   495 ######################################################################
       
   496 # Syntax:  symlinkFile(file, ifile)
       
   497 # Params:  file, string, filename to create "symlink" for
       
   498 #          ifile, string, destination name of symlink
       
   499 #
       
   500 # Purpose: File is symlinked to ifile (or copied if filesystem doesn't
       
   501 #          support symlink).
       
   502 # Returns: 1 on success, else 0.
       
   503 ######################################################################
       
   504 sub symlinkFile
       
   505 {
       
   506     my ($file,$ifile) = @_;
       
   507 
       
   508     if ($isunix) {
       
   509         print "symlink created for $file ";
       
   510         if ( $force_relative && ($ifile =~ /^$basedir/)) {
       
   511             my $t = getcwd();
       
   512             my $c = -1;
       
   513             my $p = "../";
       
   514             $t =~ s-^$basedir/--;
       
   515             $p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
       
   516             $file =~ s-^$basedir/-$p-;
       
   517             print " ($file)\n";
       
   518         }
       
   519         print "\n";
       
   520         return symlink($file, $ifile);
       
   521     }
       
   522     return copyFile($file, $ifile);
       
   523 }
       
   524 
       
   525 ######################################################################
       
   526 # Syntax:  findFiles(dir, match, descend)
       
   527 # Params:  dir, string, directory to search for name
       
   528 #          match, string, regular expression to match in dir
       
   529 #          descend, integer, 0 = non-recursive search
       
   530 #                            1 = recurse search into subdirectories
       
   531 #
       
   532 # Purpose: Finds files matching a regular expression.
       
   533 # Returns: List of matching files.
       
   534 #
       
   535 # Examples:
       
   536 #   findFiles("/usr","\.cpp$",1)  - finds .cpp files in /usr and below
       
   537 #   findFiles("/tmp","^#",0)      - finds #* files in /tmp
       
   538 ######################################################################
       
   539 sub findFiles {
       
   540     my ($dir,$match,$descend) = @_;
       
   541     my ($file,$p,@files);
       
   542     local(*D);
       
   543     $dir =~ s=\\=/=g;
       
   544     ($dir eq "") && ($dir = ".");
       
   545     if ( opendir(D,$dir) ) {
       
   546         if ( $dir eq "." ) {
       
   547             $dir = "";
       
   548         } else {
       
   549             ($dir =~ /\/$/) || ($dir .= "/");
       
   550         }
       
   551         foreach $file ( sort readdir(D) ) {
       
   552             next if ( $file  =~ /^\.\.?$/ );
       
   553             $p = $file;
       
   554             ($file =~ /$match/) && (push @files, $p);
       
   555             if ( $descend && -d $p && ! -l $p ) {
       
   556                 push @files, &findFiles($p,$match,$descend);
       
   557             }
       
   558         }
       
   559         closedir(D);
       
   560     }
       
   561     return @files;
       
   562 }
       
   563 
       
   564 # --------------------------------------------------------------------
       
   565 # "main" function
       
   566 # --------------------------------------------------------------------
       
   567 
       
   568 while ( @ARGV ) {
       
   569     my $var = 0;
       
   570     my $val = 0;
       
   571 
       
   572     #parse
       
   573     my $arg = shift @ARGV;
       
   574     if ("$arg" eq "-h" || "$arg" eq "-help" || "$arg" eq "?") {
       
   575 	$var = "show_help";
       
   576 	$val = "yes";
       
   577     } elsif("$arg" eq "-copy") {
       
   578 	$var = "copy";
       
   579 	$val = "yes";
       
   580     } elsif("$arg" eq "-o" || "$arg" eq "-outdir") {
       
   581 	$var = "output";
       
   582 	$val = shift @ARGV;
       
   583     } elsif("$arg" eq "-showonly" || "$arg" eq "-remove-stale" || "$arg" eq "-windows" ||
       
   584 	    "$arg" eq "-relative" || "$arg" eq "-check-includes") {
       
   585 	$var = substr($arg, 1);
       
   586 	$val = "yes";
       
   587     } elsif("$arg" =~ /^-no-(.*)$/) {
       
   588 	$var = $1;
       
   589 	$val = "no";
       
   590 	#these are for commandline compat
       
   591     } elsif("$arg" eq "-inc") {
       
   592 	$var = "output";
       
   593 	$val = shift @ARGV;
       
   594     } elsif("$arg" eq "-module") {
       
   595 	$var = "module";
       
   596 	$val = shift @ARGV;
       
   597     } elsif("$arg" eq "-separate-module") {
       
   598 	$var = "separate-module";
       
   599 	$val = shift @ARGV;
       
   600     } elsif("$arg" eq "-show") {
       
   601 	$var = "showonly";
       
   602 	$val = "yes";
       
   603     } elsif("$arg" eq "-base-dir") {
       
   604         # skip, it's been dealt with at the top of the file
       
   605         shift @ARGV;
       
   606         next;
       
   607     } elsif("$arg" eq '*') {
       
   608         # workaround for windows 9x where "%*" expands to "*"
       
   609         $var = 1;
       
   610     } elsif("$arg" eq "-outsubdir") {
       
   611 	$var = "outsubdir";
       
   612 	$val = shift @ARGV;
       
   613     } elsif("$arg" eq "-public") {
       
   614 	$var = "public";
       
   615 	$val = "yes";
       
   616     } elsif("$arg" eq "-oneway") {
       
   617 	$var = "oneway";
       
   618 	$val = "yes";
       
   619     }
       
   620 
       
   621     #do something
       
   622     if(!$var || "$var" eq "show_help") {
       
   623 	print "Unknown option: $arg\n\n" if(!$var);
       
   624 	showUsage();
       
   625     } elsif ("$var" eq "copy") {
       
   626 	if("$val" eq "yes") {
       
   627 	    $copy_headers++;
       
   628 	} elsif($showonly) {
       
   629 	    $copy_headers--;
       
   630 	}
       
   631     } elsif ("$var" eq "showonly") {
       
   632 	if("$val" eq "yes") {
       
   633 	    $showonly++;
       
   634 	} elsif($showonly) {
       
   635 	    $showonly--;
       
   636 	}
       
   637     } elsif ("$var" eq "check-includes") {
       
   638 	if("$val" eq "yes") {
       
   639 	    $check_includes++;
       
   640 	} elsif($check_includes) {
       
   641 	    $check_includes--;
       
   642 	}
       
   643     } elsif ("$var" eq "remove-stale") {
       
   644 	if("$val" eq "yes") {
       
   645 	    $remove_stale++;
       
   646 	} elsif($remove_stale) {
       
   647 	    $remove_stale--;
       
   648 	}
       
   649     } elsif ("$var" eq "windows") {
       
   650 	if("$val" eq "yes") {
       
   651 	    $force_win++;
       
   652 	} elsif($force_win) {
       
   653 	    $force_win--;
       
   654 	}
       
   655     } elsif ("$var" eq "relative") {
       
   656 	if("$val" eq "yes") {
       
   657 	    $force_relative++;
       
   658 	} elsif($force_relative) {
       
   659 	    $force_relative--;
       
   660 	}
       
   661     } elsif ("$var" eq "public") {
       
   662 	$create_private_headers = ("$val" eq "yes" ? 0 : 1);
       
   663     } elsif ("$var" eq "oneway") {
       
   664 	$oneway = ("$val" eq "yes" ? 1 : 0);
       
   665     } elsif ("$var" eq "outsubdir") {
       
   666 	$out_subdir = $val;
       
   667     } elsif ("$var" eq "module") {
       
   668 	print "module :$val:\n";
       
   669 	die "No such module: $val" unless(defined $modules{$val});
       
   670 	push @modules_to_sync, $val;
       
   671     } elsif ("$var" eq "separate-module") {
       
   672         my ($module, $prodir, $headerdir) = split(/:/, $val);
       
   673         $modules{$module} = $prodir;
       
   674         push @modules_to_sync, $module;
       
   675         $moduleheaders{$module} = $headerdir;
       
   676         $create_uic_class_map = 0;
       
   677         $create_private_headers = 0;
       
   678     } elsif ("$var" eq "output") {
       
   679 	my $outdir = $val;
       
   680 	if(checkRelative($outdir)) {
       
   681 	    $out_basedir = getcwd();
       
   682 	    chomp $out_basedir;
       
   683 	    $out_basedir .= "/" . $outdir;
       
   684 	} else {
       
   685 	    $out_basedir = $outdir;
       
   686 	}
       
   687 	# \ -> /
       
   688 	$out_basedir =~ s=\\=/=g;
       
   689     }
       
   690 }
       
   691 @modules_to_sync = keys(%modules) if($#modules_to_sync == -1);
       
   692 
       
   693 $isunix = checkUnix; #cache checkUnix
       
   694 
       
   695 # create path
       
   696 mkpath "$out_basedir/$out_subdir", 0777;
       
   697 
       
   698 my @ignore_headers = ();
       
   699 my $class_lib_map_contents = "";
       
   700 my @ignore_for_master_contents = ( "qt.h", "qpaintdevicedefs.h" );
       
   701 my @ignore_for_include_check = ( "qatomic.h" );
       
   702 my @ignore_for_qt_begin_header_check = ( "qiconset.h", "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qt_windows.h" );
       
   703 my @ignore_for_qt_begin_namespace_check = ( "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qatomic_arch.h", "qatomic_windowsce.h", "qt_windows.h", "qatomic_macosx.h" );
       
   704 my @ignore_for_qt_module_check = ( "$modules{QtCore}/arch", "$modules{QtCore}/global", "$modules{QtSql}/drivers", "$modules{QtTest}", "$modules{QtAssistant}", "$modules{QtDesigner}", "$modules{QtUiTools}", "$modules{QtDBus}", "$modules{phonon}" );
       
   705 
       
   706 foreach (@modules_to_sync) {
       
   707     #iteration info
       
   708     my $lib = $_;
       
   709     my $dir = "$modules{$lib}";
       
   710     my $pathtoheaders = "";
       
   711     $pathtoheaders = "$moduleheaders{$lib}" if ($moduleheaders{$lib});
       
   712 
       
   713     #information used after the syncing
       
   714     my $pri_install_classes = "";
       
   715     my $pri_install_files = "";
       
   716     my $pri_install_pfiles = "";
       
   717 
       
   718     my $libcapitals = $lib;
       
   719     $libcapitals =~ y/a-z/A-Z/;
       
   720     my $master_contents = "#ifndef QT_".$libcapitals."_MODULE_H\n#define QT_".$libcapitals."_MODULE_H\n";
       
   721 
       
   722     #get dependencies
       
   723     if(-e "$dir/" . basename($dir) . ".pro") {
       
   724 	if(open(F, "<$dir/" . basename($dir) . ".pro")) {
       
   725 	    while(<F>) {
       
   726 		my $line = $_;
       
   727 		chomp $line;
       
   728 		if($line =~ /^ *QT *\+?= *([^\r\n]*)/) {
       
   729 		    foreach(split(/ /, "$1")) {
       
   730 			$master_contents .= "#include <QtCore/QtCore>\n" if("$_" eq "core");
       
   731 			$master_contents .= "#include <QtGui/QtGui>\n" if("$_" eq "gui");
       
   732 			$master_contents .= "#include <QtNetwork/QtNetwork>\n" if("$_" eq "network");
       
   733 			$master_contents .= "#include <QtSvg/QtSvg>\n" if("$_" eq "svg");
       
   734 			$master_contents .= "#include <QtDeclarative/QtDeclarative>\n" if("$_" eq "declarative");
       
   735 			$master_contents .= "#include <QtScript/QtScript>\n" if("$_" eq "script");
       
   736 			$master_contents .= "#include <QtScriptTools/QtScriptTools>\n" if("$_" eq "scripttools");
       
   737 			$master_contents .= "#include <Qt3Support/Qt3Support>\n" if("$_" eq "qt3support");
       
   738 			$master_contents .= "#include <QtSql/QtSql>\n" if("$_" eq "sql");
       
   739 			$master_contents .= "#include <QtXml/QtXml>\n" if("$_" eq "xml");
       
   740 			$master_contents .= "#include <QtXmlPatterns/QtXmlPatterns>\n" if("$_" eq "xmlpatterns");
       
   741 			$master_contents .= "#include <QtOpenGL/QtOpenGL>\n" if("$_" eq "opengl");
       
   742 			$master_contents .= "#include <QtOpenVG/QtOpenVG>\n" if("$_" eq "openvg");
       
   743 		    }
       
   744 		}
       
   745 	    }
       
   746 	    close(F);
       
   747 	}
       
   748     }
       
   749 
       
   750     #remove the old files
       
   751     if($remove_stale) {
       
   752 	my @subdirs = ("$out_basedir/$out_subdir/$lib");
       
   753 	foreach (@subdirs) {
       
   754 	    my $subdir = "$_";
       
   755 	    if (opendir DIR, "$subdir") {
       
   756 		while(my $t = readdir(DIR)) {
       
   757 		    my $file = "$subdir/$t";
       
   758 		    if(-d "$file") {
       
   759 			push @subdirs, "$file" unless($t eq "." || $t eq "..");
       
   760 		    } else {
       
   761 			my @files = ("$file");
       
   762 			#push @files, "$out_basedir/$out_subdir/Qt/$t" if(-e "$out_basedir/$out_subdir/Qt/$t");
       
   763 			foreach (@files) {
       
   764 			   my $file = $_;
       
   765 			   my $remove_file = 0;
       
   766 			   if(open(F, "<$file")) {
       
   767 				while(<F>) {
       
   768 				    my $line = $_;
       
   769 				    chomp $line;
       
   770 				    if($line =~ /^\#include \"([^\"]*)\"$/) {
       
   771 					my $include = $1;
       
   772 					$include = $subdir . "/" . $include unless(substr($include, 0, 1) eq "/");
       
   773 					$remove_file = 1 unless(-e "$include");
       
   774 				    } else {
       
   775 					$remove_file = 0;
       
   776 					last;
       
   777 				    }
       
   778 				}
       
   779 				close(F);
       
   780 				unlink "$file" if($remove_file);
       
   781 			    }
       
   782 			}
       
   783 		    }
       
   784 		}
       
   785 		closedir DIR;
       
   786             }
       
   787 
       
   788 	}
       
   789     }
       
   790 
       
   791     #create the new ones
       
   792     foreach (split(/;/, $dir)) {
       
   793 	my $current_dir = "$_";
       
   794 	my $headers_dir = $current_dir;
       
   795         $headers_dir .= "/$pathtoheaders" if ($pathtoheaders);
       
   796         #calc subdirs
       
   797         my @subdirs = ($headers_dir);
       
   798         foreach (@subdirs) {
       
   799             my $subdir = "$_";
       
   800             opendir DIR, "$subdir" or next;
       
   801             while(my $t = readdir(DIR)) {
       
   802                 push @subdirs, "$subdir/$t" if(-d "$subdir/$t" && !($t eq ".") &&
       
   803 					       !($t eq "..") && !($t eq ".obj") &&
       
   804                                                !($t eq ".moc") && !($t eq ".rcc") &&
       
   805                                                !($t eq ".uic") && !($t eq "build"));
       
   806             }
       
   807             closedir DIR;
       
   808         }
       
   809 
       
   810         #calc files and "copy" them
       
   811         foreach (@subdirs) {
       
   812             my $subdir = "$_";
       
   813             my @headers = findFiles("$subdir", "^[-a-z0-9_]*\\.h\$" , 0);
       
   814             foreach (@headers) {
       
   815                 my $header = "$_";
       
   816                 $header = 0 if("$header" =~ /^ui_.*.h/);
       
   817                 foreach (@ignore_headers) {
       
   818                     $header = 0 if("$header" eq "$_");
       
   819                 }
       
   820                 if($header) {
       
   821 		    my $header_copies = 0;
       
   822 		    #figure out if it is a public header
       
   823 		    my $public_header = $header;
       
   824 		    if($public_header =~ /_p.h$/ || $public_header =~ /_pch.h$/) {
       
   825 			$public_header = 0;
       
   826 		    } else {
       
   827 			foreach (@ignore_for_master_contents) {
       
   828 			    $public_header = 0 if("$header" eq "$_");
       
   829 			}
       
   830 		    }
       
   831 
       
   832                     my $iheader = $subdir . "/" . $header;
       
   833 		    my @classes = $public_header ? classNames($iheader) : ();
       
   834                     if($showonly) {
       
   835                         print "$header [$lib]\n";
       
   836 			foreach(@classes) {
       
   837 			    print "SYMBOL: $_\n";
       
   838 			}
       
   839                     } else {
       
   840 			#find out all the places it goes..
       
   841 			my @headers;
       
   842 			if ($public_header) {
       
   843 			    @headers = ( "$out_basedir/$out_subdir/$lib/$header" );
       
   844 			    push @headers, "$out_basedir/$out_subdir/Qt/$header"
       
   845 			      if ("$lib" ne "phonon" && "$subdir" =~ /^$basedir\/src/);
       
   846 
       
   847 			    foreach(@classes) {
       
   848 				my $header_base = basename($header);
       
   849 				my $class = $_;
       
   850 				# Strip namespaces:
       
   851 				$class =~ s/^.*:://;
       
   852 #				if ($class =~ m/::/) {
       
   853 #				   class =~ s,::,/,g;
       
   854 #				}
       
   855 				$class_lib_map_contents .= "QT_CLASS_LIB($_, $lib, $header_base)\n";
       
   856 				$header_copies++ if(syncHeader("$out_basedir/$out_subdir/$lib/$class", "$out_basedir/$out_subdir/$lib/$header", 0));
       
   857 
       
   858 				# KDE-Compat headers for Phonon
       
   859 				if ($lib eq "phonon") {
       
   860 				    $header_copies++ if (syncHeader("$out_basedir/$out_subdir/phonon_compat/Phonon/$class", "$out_basedir/$out_subdir/$lib/$header", 0));
       
   861 				}
       
   862 			    }
       
   863 			} elsif ($create_private_headers) {
       
   864 			    @headers = ( "$out_basedir/$out_subdir/$lib/private/$header" );
       
   865 			    push @headers, "$out_basedir/$out_subdir/Qt/private/$header"
       
   866                               if ("$lib" ne "phonon");
       
   867 			}
       
   868 			foreach(@headers) { #sync them
       
   869 			    $header_copies++ if(syncHeader($_, $iheader, $copy_headers));
       
   870 			}
       
   871 
       
   872 			if($public_header) {
       
   873 			    #put it into the master file
       
   874 			    $master_contents .= "#include \"$public_header\"\n" if(shouldMasterInclude($iheader));
       
   875 
       
   876 			    #deal with the install directives
       
   877 			    if($public_header) {
       
   878 				my $pri_install_iheader = fixPaths($iheader, $current_dir);
       
   879 				foreach(@classes) {
       
   880 				    my $class = $_;
       
   881 				    # Strip namespaces:
       
   882 				    $class =~ s/^.*:://;
       
   883 #				    if ($class =~ m/::/) {
       
   884 #					$class =~ s,::,/,g;
       
   885 #				    }
       
   886 				    my $class_header = fixPaths("$out_basedir/$out_subdir/$lib/$class",
       
   887 								$current_dir) . " ";
       
   888 				    $pri_install_classes .= $class_header
       
   889 								unless($pri_install_classes =~ $class_header);
       
   890 				}
       
   891 				$pri_install_files.= "$pri_install_iheader ";;
       
   892 			    }
       
   893 			}
       
   894 			else {
       
   895 			    my $pri_install_iheader = fixPaths($iheader, $current_dir);
       
   896 			    $pri_install_pfiles.= "$pri_install_iheader ";;
       
   897 			}
       
   898                     }
       
   899 		    print "header created for $iheader ($header_copies)\n" if($header_copies > 0);
       
   900                 }
       
   901             }
       
   902         }
       
   903     }
       
   904 
       
   905     # close the master include:
       
   906     $master_contents .= "#endif\n";
       
   907 
       
   908     unless($showonly) {
       
   909         my @master_includes;
       
   910 	push @master_includes, "$out_basedir/$out_subdir/$lib/$lib";
       
   911 	push @master_includes, "$out_basedir/$out_subdir/phonon_compat/Phonon/Phonon" if ($lib eq "phonon");
       
   912         foreach my $master_include (@master_includes) {
       
   913             #generate the "master" include file
       
   914             $pri_install_files .= fixPaths($master_include, "$modules{$lib}") . " "; #get the master file installed too
       
   915             if($master_include && -e "$master_include") {
       
   916                 open MASTERINCLUDE, "<$master_include";
       
   917                 local $/;
       
   918                 binmode MASTERINCLUDE;
       
   919                 my $oldmaster = <MASTERINCLUDE>;
       
   920                 close MASTERINCLUDE;
       
   921                 $oldmaster =~ s/\r//g; # remove \r's , so comparison is ok on all platforms
       
   922                 $master_include = 0 if($oldmaster eq $master_contents);
       
   923             }
       
   924             if($master_include && $master_contents) {
       
   925                 my $master_dir = dirname($master_include);
       
   926                 mkpath $master_dir, 0777;
       
   927                 print "header (master) created for $lib\n";
       
   928                 open MASTERINCLUDE, ">$master_include";
       
   929                 print MASTERINCLUDE "$master_contents";
       
   930                 close MASTERINCLUDE;
       
   931             }
       
   932         }
       
   933 
       
   934         #handle the headers.pri for each module
       
   935 	my $headers_pri_contents = "";
       
   936 	$headers_pri_contents .= "SYNCQT.HEADER_FILES = $pri_install_files\n";
       
   937 	$headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n";
       
   938 	$headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n";
       
   939         my $headers_pri_file = "$out_basedir/$out_subdir/$lib/headers.pri";
       
   940         if(-e "$headers_pri_file") {
       
   941             open HEADERS_PRI_FILE, "<$headers_pri_file";
       
   942             local $/;
       
   943             binmode HEADERS_PRI_FILE;
       
   944             my $old_headers_pri_contents = <HEADERS_PRI_FILE>;
       
   945             close HEADERS_PRI_FILE;
       
   946             $old_headers_pri_contents =~ s/\r//g; # remove \r's , so comparison is ok on all platforms
       
   947             $headers_pri_file = 0 if($old_headers_pri_contents eq $headers_pri_contents);
       
   948         }
       
   949         if($headers_pri_file && $master_contents) {
       
   950             my $headers_pri_dir = dirname($headers_pri_file);
       
   951             mkpath $headers_pri_dir, 0777;
       
   952             print "headers.pri file created for $lib\n";
       
   953             open HEADERS_PRI_FILE, ">$headers_pri_file";
       
   954             print HEADERS_PRI_FILE "$headers_pri_contents";
       
   955             close HEADERS_PRI_FILE;
       
   956         }
       
   957     }
       
   958 }
       
   959 unless($showonly || !$create_uic_class_map) {
       
   960     my $class_lib_map = "$out_basedir/src/tools/uic/qclass_lib_map.h";
       
   961     if(-e "$class_lib_map") {
       
   962 	open CLASS_LIB_MAP, "<$class_lib_map";
       
   963 	local $/;
       
   964 	binmode CLASS_LIB_MAP;
       
   965 	my $old_class_lib_map_contents = <CLASS_LIB_MAP>;
       
   966 	close CLASS_LIB_MAP;
       
   967 	$old_class_lib_map_contents =~ s/\r//g; # remove \r's , so comparison is ok on all platforms
       
   968 	$class_lib_map = 0 if($old_class_lib_map_contents eq $class_lib_map_contents);
       
   969     }
       
   970     if($class_lib_map) {
       
   971 	my $class_lib_map_dir = dirname($class_lib_map);
       
   972 	mkpath $class_lib_map_dir, 0777;
       
   973 	open CLASS_LIB_MAP, ">$class_lib_map";
       
   974 	print CLASS_LIB_MAP "$class_lib_map_contents";
       
   975 	close CLASS_LIB_MAP;
       
   976     }
       
   977 }
       
   978 
       
   979 if($check_includes) {
       
   980     for (keys(%modules)) {
       
   981 	#iteration info
       
   982 	my $lib = $_;
       
   983 	my $dir = "$modules{$lib}";
       
   984 	foreach (split(/;/, $dir)) {
       
   985 	    my $current_dir = "$_";
       
   986 	    #calc subdirs
       
   987 	    my @subdirs = ($current_dir);
       
   988 	    foreach (@subdirs) {
       
   989 		my $subdir = "$_";
       
   990 		opendir DIR, "$subdir";
       
   991 		while(my $t = readdir(DIR)) {
       
   992                     push @subdirs, "$subdir/$t" if(-d "$subdir/$t" && !($t eq ".") &&
       
   993                                                    !($t eq "..") && !($t eq ".obj") &&
       
   994                                                    !($t eq ".moc") && !($t eq ".rcc") &&
       
   995                                                    !($t eq ".uic") && !($t eq "build"));
       
   996 		}
       
   997 		closedir DIR;
       
   998 	    }
       
   999 
       
  1000 	    foreach (@subdirs) {
       
  1001 		my $subdir = "$_";
       
  1002                 my $header_skip_qt_module_test = 0;
       
  1003                 foreach(@ignore_for_qt_module_check) {
       
  1004                     foreach (split(/;/, $_)) {
       
  1005                         $header_skip_qt_module_test = 1 if ("$subdir" =~ /^$_/);
       
  1006                     }
       
  1007                 }
       
  1008 		my @headers = findFiles("$subdir", "^[-a-z0-9_]*\\.h\$" , 0);
       
  1009 		foreach (@headers) {
       
  1010 		    my $header = "$_";
       
  1011                     my $header_skip_qt_begin_header_test = 0;
       
  1012                     my $header_skip_qt_begin_namespace_test = 0;
       
  1013 		    $header = 0 if("$header" =~ /^ui_.*.h/);
       
  1014 		    foreach (@ignore_headers) {
       
  1015 			$header = 0 if("$header" eq "$_");
       
  1016 		    }
       
  1017 		    if($header) {
       
  1018 			my $public_header = $header;
       
  1019 			if($public_header =~ /_p.h$/ || $public_header =~ /_pch.h$/) {
       
  1020 			    $public_header = 0;
       
  1021 			} else {
       
  1022 			    foreach (@ignore_for_master_contents) {
       
  1023 				$public_header = 0 if("$header" eq "$_");
       
  1024 			    }
       
  1025 			    if($public_header) {
       
  1026 				foreach (@ignore_for_include_check) {
       
  1027 				    $public_header = 0 if("$header" eq "$_");
       
  1028 				}
       
  1029                                 foreach(@ignore_for_qt_begin_header_check) {
       
  1030                                     $header_skip_qt_begin_header_test = 1 if ("$header" eq "$_");
       
  1031                                 }
       
  1032                                 foreach(@ignore_for_qt_begin_namespace_check) {
       
  1033                                     $header_skip_qt_begin_namespace_test = 1 if ("$header" eq "$_");
       
  1034                                 }
       
  1035 			    }
       
  1036 			}
       
  1037 
       
  1038 			my $iheader = $subdir . "/" . $header;
       
  1039 			if($public_header) {
       
  1040 			    if(open(F, "<$iheader")) {
       
  1041                                 my $qt_module_found = 0;
       
  1042 				my $qt_begin_header_found = 0;
       
  1043 				my $qt_end_header_found = 0;
       
  1044 				my $qt_begin_namespace_found = 0;
       
  1045 				my $qt_end_namespace_found = 0;
       
  1046 				my $line;
       
  1047 				while($line = <F>) {
       
  1048 				    chomp $line;
       
  1049 				    my $output_line = 1;
       
  1050                                     if($line =~ /^ *\# *pragma (qt_no_included_check|qt_sync_stop_processing)/) {
       
  1051 			                last;
       
  1052 				    } elsif($line =~ /^ *\# *include/) {
       
  1053 					my $include = $line;
       
  1054 					if($line =~ /<.*>/) {
       
  1055 					    $include =~ s,.*<(.*)>.*,$1,;
       
  1056 					} elsif($line =~ /".*"/) {
       
  1057 					    $include =~ s,.*"(.*)".*,$1,;
       
  1058 					} else {
       
  1059 					    $include = 0;
       
  1060 					}
       
  1061 					if($include) {
       
  1062 					    for (keys(%modules)) {
       
  1063 						my $trylib = $_;
       
  1064 						if(-e "$out_basedir/$out_subdir/$trylib/$include") {
       
  1065 						    print "WARNING: $iheader includes $include when it should include $trylib/$include\n";
       
  1066 						}
       
  1067 					    }
       
  1068 					}
       
  1069 				    } elsif ($header_skip_qt_begin_header_test == 0 and $line =~ /^QT_BEGIN_HEADER\s*$/) {
       
  1070 					$qt_begin_header_found = 1;
       
  1071 				    } elsif ($header_skip_qt_begin_header_test == 0 and $line =~ /^QT_END_HEADER\s*$/) {
       
  1072 					$qt_end_header_found = 1;
       
  1073 				    } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_BEGIN_NAMESPACE\s*$/) {
       
  1074 					$qt_begin_namespace_found = 1;
       
  1075 				    } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_END_NAMESPACE\s*$/) {
       
  1076 					$qt_end_namespace_found = 1;
       
  1077                                     } elsif ($header_skip_qt_module_test == 0 and $line =~ /^QT_MODULE\(.*\)\s*$/) {
       
  1078                                         $qt_module_found = 1;
       
  1079                                     }
       
  1080 				}
       
  1081                                 if ($header_skip_qt_begin_header_test == 0) {
       
  1082                                     if ($qt_begin_header_found == 0) {
       
  1083                                         print "WARNING: $iheader does not include QT_BEGIN_HEADER\n";
       
  1084                                     }
       
  1085 
       
  1086                                     if ($qt_begin_header_found && $qt_end_header_found == 0) {
       
  1087                                         print "WARNING: $iheader has QT_BEGIN_HEADER but no QT_END_HEADER\n";
       
  1088                                     }
       
  1089                                 }
       
  1090 
       
  1091                                 if ($header_skip_qt_begin_namespace_test == 0) {
       
  1092                                     if ($qt_begin_namespace_found == 0) {
       
  1093                                         print "WARNING: $iheader does not include QT_BEGIN_NAMESPACE\n";
       
  1094                                     }
       
  1095 
       
  1096                                     if ($qt_begin_namespace_found && $qt_end_namespace_found == 0) {
       
  1097                                         print "WARNING: $iheader has QT_BEGIN_NAMESPACE but no QT_END_NAMESPACE\n";
       
  1098                                     }
       
  1099                                 }
       
  1100 
       
  1101                                 if ($header_skip_qt_module_test == 0) {
       
  1102                                     if ($qt_module_found == 0) {
       
  1103                                         print "WARNING: $iheader does not include QT_MODULE\n";
       
  1104                                     }
       
  1105                                 }
       
  1106 				close(F);
       
  1107 			    }
       
  1108 			}
       
  1109 		    }
       
  1110 		}
       
  1111 	    }
       
  1112 	}
       
  1113     }
       
  1114 }
       
  1115 
       
  1116 exit 0;