Updated build-system. Does this help you khz?
[pinentry.git] / admin / am_edit
1 #!/usr/bin/perl -w
2
3 # Expands the specialised KDE tags in Makefile.in to (hopefully) valid
4 # make syntax.
5 # When called without file parameters, we work recursively on all Makefile.in
6 # in and below the current subdirectory. When called with file parameters,
7 # only those Makefile.in are changed.
8 # The currently supported tags are
9 #
10 # {program}_METASOURCES
11 # where you have a choice of two styles
12 #   {program}_METASOURCES = name1.moc name2.moc ... [\]
13 #   {program}_METASOURCES = AUTO
14 #       The second style requires other tags as well.
15 #
16 # To install icons :
17 #    KDE_ICON = iconname iconname2 ...
18 #    KDE_ICON = AUTO
19 #
20 # For documentation :
21 #    ...
22 #
23 # and more new tags TBD!
24 #
25 # The concept (and base code) for this program came from automoc,
26 # supplied by the following
27 #
28 # Matthias Ettrich <ettrich@kde.org>      (The originator)
29 # Kalle Dalheimer <kalle@kde.org>      (The original implementator)
30 # Harri Porten  <porten@tu-harburg.de>
31 # Alex Zepeda  <jazepeda@pacbell.net>
32 # David Faure <faure@kde.org>
33 # Stephan Kulow <coolo@kde.org>
34
35 use Cwd;
36 use File::Find;
37 use File::Basename;
38
39 # Prototype the functions
40 sub initialise ();
41 sub processMakefile ($);
42 sub updateMakefile ();
43 sub restoreMakefile ();
44
45 sub removeLine ($$);
46 sub appendLines ($);
47 sub substituteLine ($$);
48
49 sub findMocCandidates ();
50 sub pruneMocCandidates ($);
51 sub checkMocCandidates ();
52 sub addMocRules ();
53
54 sub tag_AUTOMAKE ();
55 sub tag_META_INCLUDES ();
56 sub tag_METASOURCES ();
57 sub tag_POFILES ();
58 sub tag_DOCFILES ();
59 sub tag_LOCALINSTALL();
60 sub tag_IDLFILES();
61 sub tag_UIFILES();
62 sub tag_SUBDIRS();
63 sub tag_ICON();
64 sub tag_CLOSURE();
65 sub tag_DIST();
66
67 # Some global globals...
68 $verbose    = 0;        # a debug flag
69 $thisProg   = "$0";     # This programs name
70 $topdir     = cwd();    # The current directory
71 @makefiles  = ();       # Contains all the files we'll process
72 @foreignfiles = ();
73 $start      = (times)[0]; # some stats for testing - comment out for release
74 $version    = "v0.2";
75 $errorflag  = 0;
76 $cppExt     = "(cpp|cc|cxx|C|c\\+\\+)";
77 $hExt       = "(h|H|hh|hxx|hpp|h\\+\\+)";
78 $progId     = "KDE tags expanded automatically by " . basename($thisProg);
79 $automkCall = "\n";
80 $printname  = "";  # used to display the directory the Makefile is in
81 $use_final  = 1;        # create code for --enable-final
82 $cleantarget = "clean";
83 $dryrun     = 0;
84 $pathoption = 0;
85 $foreign_libtool = 0;
86
87 while (defined ($ARGV[0]))
88 {
89     $_ = shift;
90     if (/^--version$/)
91     {
92         print STDOUT "\n";
93         print STDOUT basename($thisProg), " $version\n",
94                 "This is really free software, unencumbered by the GPL.\n",
95                 "You can do anything you like with it except sueing me.\n",
96                 "Copyright 1998 Kalle Dalheimer <kalle\@kde.org>\n",
97                 "Concept, design and unnecessary questions about perl\n",
98                 "       by Matthias Ettrich <ettrich\@kde.org>\n\n",
99                 "Making it useful by Stephan Kulow <coolo\@kde.org> and\n",
100                 "Harri Porten <porten\@kde.org>\n",
101                 "Updated (Feb-1999), John Birch <jb.nz\@writeme.com>\n",
102                 "Current Maintainer Stephan Kulow\n\n";
103         exit 0;
104     }
105     elsif (/^--verbose$|^-v$/)
106     {
107         $verbose = 1;       # Oh is there a problem...?
108     }
109     elsif (/^-p(.+)$|^--path=(.+)$/)
110     {
111         $thisProg = "$1/".basename($thisProg) if($1);
112         $thisProg = "$2/".basename($thisProg) if($2);
113         warn ("$thisProg doesn't exist\n")      if (!(-f $thisProg));
114         $pathoption=1;
115     }
116     elsif (/^--help$|^-h$/)
117     {
118         print STDOUT "Usage $thisProg [OPTION] ... [dir/Makefile.in]...\n",
119                 "\n",
120                 "Patches dir/Makefile.in generated from automake\n",
121                 "(where dir can be a full or relative directory name)",
122                 "\n",
123                 "  -v, --verbose      verbosely list files processed\n",
124                 "  -h, --help         print this help, then exit\n",
125                 "  --version          print version number, then exit\n",
126                 "  -p, --path=        use the path to am_edit if the path\n",
127                 "  --no-final         don't patch for --enable-final\n",
128                 "                     called from is not the one to be used\n";
129         
130         exit 0;
131     }
132     elsif (/^--no-final$/)
133     {
134         $use_final = 0;
135         $thisProg .= " --no-final";
136     }
137     elsif (/^--foreign-libtool$/)
138     {
139         $foreign_libtool = 1;
140         $thisProg .= " --foreign-libtool";
141     }
142     elsif (/^-n$/)
143     {
144         $dryrun = 1;
145     }
146     else
147     {
148         # user selects what input files to check
149         # add full path if relative path is given
150         $_ = cwd()."/".$_   if (! /^\//);
151         print "User wants $_\n" if ($verbose);
152         push (@makefiles, $_);
153     }
154 }
155
156 if ($thisProg =~ /^\// && !$pathoption )
157 {
158   print STDERR "Illegal full pathname call performed...\n",
159       "The call to \"$thisProg\"\nwould be inserted in some Makefile.in.\n",
160       "Please use option --path.\n";
161   exit 1;
162 }
163
164 # Only scan for files when the user hasn't entered data
165 if (!@makefiles)
166 {
167     print STDOUT "Scanning for Makefile.in\n"       if ($verbose);
168     find (\&add_makefile, cwd());
169     #chdir('$topdir');
170 } else {
171     print STDOUT "Using user enter input files\n"   if ($verbose);
172 }
173
174 foreach $makefile (sort(@makefiles))
175 {
176     processMakefile ($makefile);
177     last            if ($errorflag);
178 }
179
180 # Just some debug statistics - comment out for release as it uses printf.
181 printf STDOUT "Time %.2f CPU sec\n", (times)[0] - $start     if ($verbose);
182
183 exit $errorflag;        # causes make to fail if erroflag is set
184
185 #-----------------------------------------------------------------------------
186
187 # In conjunction with the "find" call, this builds the list of input files
188 sub add_makefile ()
189 {
190   push (@makefiles, $File::Find::name) if (/Makefile.in$/);
191 }
192
193 #-----------------------------------------------------------------------------
194
195 # Processes a single make file
196 # The parameter contains the full path name of the Makefile.in to use
197 sub processMakefile ($)
198 {
199     # some useful globals for the subroutines called here
200     local ($makefile)       = @_;
201     local @headerdirs       = ('.');
202     local $haveAutomocTag   = 0;
203     local $MakefileData     = "";
204
205     local $cxxsuffix  = "KKK";
206
207     local @programs = ();  # lists the names of programs and libraries
208     local $program = "";
209
210     local %realObjs = ();  # lists the objects compiled into $program
211     local %sources = ();   # lists the sources used for $program
212     local %finalObjs = (); # lists the objects compiled when final
213     local %realname = ();  # the binary name of program variable
214     local %idlfiles = ();  # lists the idl files used for $program
215     local %globalmocs = ();# list of all mocfiles (in %mocFiles format)
216     local %important = (); # list of files to be generated asap
217     local %uiFiles = ();
218
219     local $allidls = "";
220     local $idl_output = "";# lists all idl generated files for cleantarget
221     local $ui_output = "";# lists all uic generated files for cleantarget
222
223     local %depedmocs = ();
224     
225     local $metasourceTags = 0;
226     local $dep_files      = "";
227     local $dep_finals     = "";
228     local %target_adds    = (); # the targets to add
229     local $kdelang        = "";
230     local @cleanfiles     = ();
231     local $cleanMoc       = "";
232     local $closure_output = "";
233
234     $makefileDir = dirname($makefile);
235     chdir ($makefileDir);
236     $printname = $makefile;
237     $printname =~ s/^\Q$topdir\E\///;
238     $makefile = basename($makefile);
239
240     print STDOUT "Processing makefile $printname\n"   if ($verbose);
241     
242     # Setup and see if we need to do this.
243     return      if (!initialise());
244     
245     tag_AUTOMAKE ();            # Allows a "make" to redo the Makefile.in
246     tag_META_INCLUDES ();       # Supplies directories for src locations
247     
248     foreach $program (@programs) {
249         $sources_changed{$program} = 0;
250         $depedmocs{$program} = "";
251         $important{$program} = "";
252         tag_IDLFILES();             # Sorts out idl rules
253         tag_CLOSURE();
254         tag_UIFILES();             # Sorts out ui rules
255         tag_METASOURCES ();         # Sorts out the moc rules
256         if ($sources_changed{$program}) {
257             my $lookup = "$program" . '_SOURCES\s*=\s*(.*)';
258             substituteLine($lookup, "$program\_SOURCES=" . $sources{$program});
259         }
260         if ($important{$program}) {
261             local %source_dict = ();
262             for $source (split(/[\034\s]+/, $sources{$program})) {
263                 $source_dict{$source} = 1;
264             }
265             for $source (@cleanfiles) {
266                 $source_dict{$source} = 0;
267             }
268             for $source (keys %source_dict) {
269                 next if (!$source);
270                 if ($source_dict{$source}) {
271                     # sanity check
272                     if (! -f $source) {
273                         print STDERR "Error: $source is listed in a _SOURCE line in $printname, but doesn't exist yet. Put it in DISTCLEANFILES!\n";
274                     } else {
275                         $target_adds{"\$(srcdir)/$source"} .= $important{$program};
276                     }
277                 }
278             }
279         }
280     }
281     if ($cleanMoc) {
282         # Always add dist clean tag
283         # Add extra *.moc.cpp files created for USE_AUTOMOC because they
284         # aren't included in the normal *.moc clean rules.
285         appendLines ("$cleantarget-metasources:\n\t-rm -f $cleanMoc\n");
286         $target_adds{"$cleantarget-am"} .= "$cleantarget-metasources ";
287     }
288     tag_DIST();
289
290     if ($idl_output) {
291         appendLines ("$cleantarget-idl:\n\t-rm -f $idl_output\n");
292         $target_adds{"$cleantarget-am"} .= "$cleantarget-idl ";
293     }
294
295     if ($ui_output) {
296         appendLines ("$cleantarget-ui:\n\t-rm -f $ui_output\n");
297         $target_adds{"$cleantarget-am"} .= "$cleantarget-ui ";
298     }
299
300     if ($closure_output) {
301         appendLines ("$cleantarget-closures:\n\t-rm -f $closure_output\n");
302         $target_adds{"$cleantarget-am"} .= "$cleantarget-closures ";
303     }
304
305     if ($MakefileData =~ /\nKDE_LANG\s*=\s*(\S*)\s*\n/) {
306         $kdelang = '$(KDE_LANG)'
307     } else {
308         $kdelang = '';
309     }
310
311     tag_POFILES ();             # language rules for po directory
312     tag_DOCFILES ();            # language rules for doc directories
313     tag_LOCALINSTALL();         # add $(DESTDIR) before all kde_ dirs
314     tag_ICON();
315     tag_SUBDIRS();
316
317     my $tmp = "force-reedit:\n";
318     $tmp   .= "\t$automkCall\n\tcd \$(top_srcdir) && perl $thisProg $printname\n\n";
319     appendLines($tmp);
320     
321     make_meta_classes();
322     tag_FINAL() if (!$kdeopts{"nofinal"});
323
324     my $final_lines = "final:\n\t\$(MAKE) ";
325     my $final_install_lines = "final-install:\n\t\$(MAKE) ";
326     my $nofinal_lines = "no-final:\n\t\$(MAKE) ";
327     my $nofinal_install_lines = "no-final-install:\n\t\$(MAKE) ";
328
329     foreach $program (@programs) {
330         
331         my $lookup = "$program\_OBJECTS.*=[^\n]*";
332         
333         my $new = "";
334         
335         my @list = split(/[\034\s]+/, $realObjs{$program});
336         
337         if (!$kdeopts{"nofinal"} && @list > 1 && $finalObjs{$program}) {
338             
339             $new .= "$program\_final\_OBJECTS = " . $finalObjs{$program};
340             $new .= "\n$program\_nofinal\_OBJECTS = " . $realObjs{$program};
341             $new .= "\n\@KDE_USE_FINAL_FALSE\@$program\_OBJECTS = \$($program\_nofinal\_OBJECTS)";
342             $new .= "\n\@KDE_USE_FINAL_TRUE\@$program\_OBJECTS = \$($program\_final\_OBJECTS)";
343             
344             $final_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" ";
345             $final_install_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" ";
346             $nofinal_lines .= "$program\_OBJECTS=\"\$($program\_nofinal\_OBJECTS)\" ";
347             $nofinal_install_lines .= "$program\_OBJECTS=\"\$($program\_nofinal_OBJECTS)\" ";
348         } else {
349             $new = "$program\_OBJECTS = " . $realObjs{$program};
350         }
351         substituteLine ($lookup, $new);
352     }
353     appendLines($final_lines . "all-am");
354     appendLines($final_install_lines . "install-am");
355     appendLines($nofinal_lines . "all-am");
356     appendLines($nofinal_install_lines . "install-am");
357     
358     my $lookup = 'DEP_FILES\s*=([^\n]*)';
359     if ($MakefileData =~ /\n$lookup\n/o) {
360         $depfiles = $1;
361         
362         if ($dep_finals) {
363             $lines  = "\@KDE_USE_FINAL_TRUE\@DEP_FILES = $dep_files $dep_finals \034\t$depfiles\n";
364             $lines .= "\@KDE_USE_FINAL_FALSE\@DEP_FILES = $dep_files $depfiles\n";
365         } else {
366             $lines = "DEP_FILES = $dep_files $depfiles\n";
367         }
368         
369         substituteLine($lookup, $lines);
370     }
371     
372     my $cvs_lines = "cvs-clean:\n";
373     $cvs_lines .= "\t\$(MAKE) -f \$(top_srcdir)/admin/Makefile.common cvs-clean\n";
374     appendLines($cvs_lines);
375     
376     $cvs_lines  = "kde-rpo-clean:\n";
377     $cvs_lines .= "\t-rm -f *.rpo\n";
378     appendLines($cvs_lines);
379     $target_adds{"clean"} .= "kde-rpo-clean ";
380
381     # some strange people like to do a install-exec, and expect that also
382     # all modules are installed.  automake doesn't know this, so we need to move
383     # this here from install-data to install-exec.
384     if ($MakefileData =~ m/\nkde_module_LTLIBRARIES\s*=/) {
385       $target_adds{"install-exec-am"} .= "install-kde_moduleLTLIBRARIES";
386       my $lookup = 'install-data-am:\s*(.*)';
387       if ($MakefileData =~ /\n$lookup\n/) {
388         my $newdeps = $1;
389         $newdeps =~ s/\s*install-kde_moduleLTLIBRARIES\s*/ /g;
390         substituteLine($lookup, "install-data-am: " . $newdeps);
391       }
392     }
393     
394     my $lines = "";
395
396     foreach $add (keys %target_adds) {
397         my $lookup = quotemeta($add) . ':([^\n]*)';
398         if ($MakefileData =~ /\n$lookup\n/) {
399             substituteLine($lookup, "$add: " . $target_adds{$add} . $1);
400         } else {
401             $lines .= "$add: " . $target_adds{$add} . "\n";
402         }
403     }
404     if ($lines) {
405         appendLines($lines);
406     }
407
408     my $found = 1;
409     
410     while ($found) {
411         if ($MakefileData =~ m/\n(.*)\$\(CXXFLAGS\)(.*)\n/) {
412             my $vor = $1;   # "vor" means before in German
413             my $nach = $2; # "nach" means after in German
414             my $lookup = quotemeta("$1\$(CXXFLAGS)$2");
415             my $replacement = "$1\$(KCXXFLAGS)$2";
416             $MakefileData =~ s/$lookup/$replacement/;
417             $lookup =~ s/\\\$\\\(CXXFLAGS\\\)/\\\$\\\(KCXXFLAGS\\\)/;
418             $replacement = "$vor\$(KCXXFLAGS) \$(KDE_CXXFLAGS)$nach";
419             substituteLine($lookup, $replacement);
420         } else {
421             $found = 0;
422         }
423     }
424
425     if($foreign_libtool == 0) {
426         $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=link) (\$\(CXXLD\).*\$\(KCXXFLAGS\))';
427     
428         if ($MakefileData =~ m/$lookup/ ) {
429             $MakefileData =~ s/$lookup/$1 --tag=CXX $2/;
430         }
431
432         $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=compile) (\$\(CXX\).*\$\(KCXXFLAGS\))';
433         if ($MakefileData =~ m/$lookup/ ) {
434             $MakefileData =~ s/$lookup/$1 --tag=CXX $2/;
435         }
436     }
437
438     $MakefileData =~ s/\$\(KCXXFLAGS\)/\$\(CXXFLAGS\)/g;
439
440     $lookup = '(.*)cp -pr \$\$/\$\$file \$\(distdir\)/\$\$file(.*)';
441     if ($MakefileData =~ m/\n$lookup\n/) {
442         substituteLine($lookup, "$1cp -pr \$\$d/\$\$file \$(distdir)/\$\$file$2");
443     }
444
445     # Always update the Makefile.in
446     updateMakefile ();
447     return;
448 }
449
450 #-----------------------------------------------------------------------------
451
452 # Check to see whether we should process this make file.
453 # This is where we look for tags that we need to process.
454 # A small amount of initialising on the tags is also done here.
455 # And of course we open and/or create the needed make files.
456 sub initialise ()
457 {
458     if (! -r "Makefile.am") {
459         print STDOUT "found Makefile.in without Makefile.am\n" if ($verbose);
460         return 0;
461     }
462
463     # Checking for files to process...
464     open (FILEIN, $makefile)
465       || die "Could not open $makefileDir/$makefile: $!\n";
466     # Read the file
467     # stat(FILEIN)[7] might look more elegant, but is slower as it 
468     # requires stat'ing the file
469     seek(FILEIN, 0, 2);
470     my $fsize = tell(FILEIN);
471     seek(FILEIN, 0, 0);
472     read FILEIN, $MakefileData, $fsize;
473     close FILEIN;
474     print "DOS CRLF within $makefileDir/$makefile!\n" if($MakefileData =~ y/\r//d);
475
476     # Remove the line continuations, but keep them marked
477     # Note: we lose the trailing spaces but that's ok.
478     $MakefileData =~ s/\\\s*\n\s*/\034/g;
479
480     # If we've processed the file before...
481     restoreMakefile ()      if ($MakefileData =~ /$progId/);
482
483     foreach $dir (@foreignfiles) {
484       if (substr($makefileDir,0,length($dir)) eq $dir) {
485         return 0;
486       }
487     }
488
489     %kdeopts = ();
490     $kdeopts{"foreign"} = 0;
491     $kdeopts{"qtonly"} = 0;
492     $kdeopts{"foreign-libtool"} = $foreign_libtool;
493     $kdeopts{"nofinal"} = !$use_final; # default
494
495     if ($MakefileData =~ /\nKDE_OPTIONS\s*=\s*([^\n]*)\n/) {
496         local @kde_options = split(/[\s\034]/, $1);
497         if (grep(/^foreign$/, @kde_options)) {
498             push(@foreignfiles, $makefileDir . "/");
499             return 0; # don't touch me
500         }
501         for $opt (@kde_options) {
502             if (!defined $kdeopts{$opt}) {
503                 print STDERR "Warning: unknown option $opt in $printname\n";
504             } else {
505                 $kdeopts{$opt} = 1;
506             }
507         }
508     }
509
510     # Look for the tags that mean we should process this file.
511     $metasourceTags = 0;
512     $metasourceTags++    while ($MakefileData =~ /\n[^=\#]*METASOURCES\s*=/g);
513
514     my $pofileTag = 0;
515     $pofileTag++    while ($MakefileData =~ /\nPOFILES\s*=/g);
516     if ($pofileTag > 1)
517       {
518           print STDERR "Error: Only one POFILES tag allowed\n";
519           $errorflag = 1;
520       }
521
522     while ($MakefileData =~ /\n\.SUFFIXES:([^\n]+)\n/g) {
523         my @list=split(' ', $1);
524         foreach $ext (@list) {
525             if ($ext =~ /^\.$cppExt$/) {
526                 $cxxsuffix = $ext;
527                 $cxxsuffix =~ s/\.//g;
528                 print STDOUT "will use suffix $cxxsuffix\n" if ($verbose);
529                 last;
530             }
531         }
532     }
533                                                      
534     while ($MakefileData =~ /\n(\S*)_OBJECTS\s*=[ \t\034]*([^\n]*)\n/g) {
535         
536         my $program = $1;
537         my $objs = $2; # safe them
538         
539         my $ocv = 0;
540         
541         my @objlist = split(/[\s\034]+/, $objs);
542         foreach $obj (@objlist) {
543             if ($obj =~ /\$\((\S+)\)/ ) {
544                 my $variable = $1;
545                 if ($variable !~ 'OBJEXT') {
546                     $ocv = 1;
547                 }
548             }
549         }
550         
551         next if ($ocv);
552
553         $program =~ s/^am_// if ($program =~ /^am_/);
554         
555         my $sourceprogram = $program;
556         $sourceprogram =~ s/\@am_/\@/ if($sourceprogram =~ /^.*\@am_.+/);
557         
558         print STDOUT "found program $program\n" if ($verbose);
559         push(@programs, $program);
560         
561         $realObjs{$program} = $objs;
562         
563         if ($MakefileData =~ /\n$sourceprogram\_SOURCES\s*=\s*(.*)\n/) {
564             $sources{$program} = $1;
565         } 
566         else {
567             $sources{$program} = "";
568             print STDERR "found program with no _SOURCES: $program\n";
569         }
570         
571         my $realprogram = $program;
572         $realprogram =~ s/_/./g; # unmask to regexp
573         if ($MakefileData =~ /\n($realprogram)(\$\(EXEEXT\)?)?:.*\$\($program\_OBJECTS\)/) {
574             $realname{$program} = $1;
575         } else {
576             # not standard Makefile - nothing to worry about
577             $realname{$program} = "";
578         }
579     }
580     
581     my $lookup = '\nDEPDIR\s*=.*';
582     if ($MakefileData !~ /($lookup)\n/o) {
583         $lookup = '\nbindir\s*=.*';
584         if ($MakefileData =~ /($lookup)\n/) {
585             substituteLine ($lookup, "DEPDIR = .deps\n$1");
586         }
587     } 
588
589     my @marks = ('MAINTAINERCLEANFILES', 'CLEANFILES', 'DISTCLEANFILES');
590     foreach $mark (@marks) {
591         while ($MakefileData =~ /\n($mark)\s*=\s*([^\n]*)/g) {
592             foreach $file (split('[\034\s]', $2)) {
593                 $file =~ s/\.\///;
594                 push(@cleanfiles, $file);
595             }
596         }
597     }
598
599     my $localTag = 0;
600     $localTag++ if ($MakefileData =~ /\ninstall-\S+-local:/);
601     
602     return (!$errorflag);
603 }
604
605 #-----------------------------------------------------------------------------
606
607 # Gets the list of user defined directories - relative to $srcdir - where
608 # header files could be located.
609 sub tag_META_INCLUDES ()
610 {
611     my $lookup = '[^=\n]*META_INCLUDES\s*=\s*(.*)';
612     return 1    if ($MakefileData !~ /($lookup)\n/o);
613     print STDOUT "META_INCLUDE processing <$1>\n"       if ($verbose);
614
615     my $headerStr = $2;
616     removeLine ($lookup, $1);
617
618     $headerStr =~ tr/\034/ /;
619     my @headerlist = split(' ', $headerStr);
620
621     foreach $dir (@headerlist)
622     {
623         $dir =~ s#\$\(srcdir\)#.#;
624         if (! -d $dir)
625         {
626             print STDERR "Warning: $dir can't be found. ",
627                             "Must be a relative path to \$(srcdir)\n";
628         }
629         else
630         {
631             push (@headerdirs, $dir);
632         }
633     }
634
635     return 0;
636 }
637
638 #-----------------------------------------------------------------------------
639
640 sub tag_FINAL()
641 {
642     my @final_names = ();
643     
644     foreach $program (@programs) {
645         
646         if ($sources{$program} =~ /\(/) {
647             print STDOUT "found ( in $program\_SOURCES. skipping\n" if ($verbose);
648             next;
649         }
650         
651         my $mocsources = "";
652         
653         my @progsources = split(/[\s\034]+/, $sources{$program});
654         my %sourcelist = ();
655         
656         foreach $source (@progsources) {
657             my $suffix = $source;
658             $suffix =~ s/^.*\.([^\.]+)$/$1/;
659             
660             if (defined($sourcelist{$suffix})) {
661                 $sourcelist{$suffix} .= " " . $source;
662             } else {
663                 $sourcelist{$suffix} .= $source;
664             }
665         }
666         
667         foreach $suffix (keys %sourcelist) {
668             
669             # See if this file contains c++ code. (ie Just check the files suffix against
670             my $suffix_is_cxx = 0;
671             if($suffix =~ /($cppExt)$/) {
672               $cxxsuffix = $1;
673               $suffix_is_cxx = 1;
674             }
675             
676             my $mocfiles_in = ($suffix eq $cxxsuffix) &&
677               defined($depedmocs{$program});
678             
679             my @sourcelist = split(/[\s\034]+/, $sourcelist{$suffix});
680             
681             if ((@sourcelist == 1 && !$mocfiles_in) || $suffix_is_cxx != 1 ) {
682                 
683                 # we support IDL on our own
684                 if ($suffix =~ /^skel$/ || $suffix =~ /^stub/ || $suffix =~ /^h$/
685                     || $suffix =~ /^ui$/ ) {
686                     next;
687                 }
688                 
689                 foreach $file (@sourcelist) {
690                     
691                     $file =~ s/\Q$suffix\E$//;
692                     
693                     $finalObjs{$program} .= $file;
694                     if ($program =~ /_la$/) {
695                         $finalObjs{$program} .= "lo ";
696                     } else {
697                         $finalObjs{$program} .= "o ";
698                     }
699                 }
700                 next; # suffix
701             }
702             
703             my $source_deps = "";
704             foreach $source (@sourcelist) {
705                 if (-f $source) {
706                     $source_deps .= "\$(srcdir)/$source ";
707                 } else {
708                     $source_deps .= "$source ";
709                 }
710             }
711             
712             $handling = "$program.all_$suffix.$suffix: \$(srcdir)/Makefile.in " . $source_deps . " ";
713             
714             if ($mocfiles_in) {
715                 $handling .= $depedmocs{$program};
716                 foreach $mocfile (split(' ', $depedmocs{$program})) {
717                    
718                     if ($mocfile =~ m/\.$suffix$/) {
719                         $mocsources .= " " . $mocfile;
720                     }
721                 }
722             }
723             
724             $handling .= "\n";
725             $handling .= "\t\@echo 'creating $program.all_$suffix.$suffix ...'; \\\n";
726             $handling .= "\trm -f $program.all_$suffix.files $program.all_$suffix.final; \\\n";
727             $handling .= "\techo \"#define KDE_USE_FINAL 1\" >> $program.all_$suffix.final; \\\n";
728             $handling .= "\tfor file in " . $sourcelist{$suffix} . " $mocsources; do \\\n";
729             $handling .= "\t  echo \"#include \\\"\$\$file\\\"\" >> $program.all_$suffix.files; \\\n";
730             $handling .= "\t  test ! -f \$\(srcdir\)/\$\$file || egrep '^#pragma +implementation' \$\(srcdir\)/\$\$file >> $program.all_$suffix.final; \\\n";
731             $handling .= "\tdone; \\\n";
732             $handling .= "\tcat $program.all_$suffix.final $program.all_$suffix.files  > $program.all_$suffix.$suffix; \\\n";
733             $handling .= "\trm -f $program.all_$suffix.final $program.all_$suffix.files\n";
734             
735             appendLines($handling);
736             
737             push(@final_names, "$program.all_$suffix.$suffix");
738             $finalObjs{$program} .= "$program.all_$suffix.";
739             if ($program =~ /_la$/) {
740                 $finalObjs{$program} .= "lo ";
741             } else {
742                 $finalObjs{$program} .= "o ";
743             }
744         }
745     }
746     
747     if (!$kdeopts{"nofinal"} && @final_names >= 1) {
748         # add clean-final target
749         my $lines = "$cleantarget-final:\n";
750         $lines .= "\t-rm -f " . join(' ', @final_names) . "\n" if (@final_names);
751         appendLines($lines);
752         $target_adds{"$cleantarget-am"} .= "$cleantarget-final ";
753         
754         foreach $finalfile (@final_names) {
755             $finalfile =~ s/\.[^.]*$/.P/;
756             $dep_finals .= " \$(DEPDIR)/$finalfile";
757         }
758     }
759 }
760
761 # Organises the list of headers that we'll use to produce moc files
762 # from.
763 sub tag_METASOURCES ()
764 {
765     local @newObs           = ();  # here we add to create object files
766     local @deped            = ();  # here we add to create moc files
767     local $mocExt           = ".moc";
768     local %mocFiles         = ();
769
770     my $line = "";
771     my $postEqual = "";
772
773     my $lookup;
774     my $found = "";
775
776     if ($metasourceTags > 1) {
777         $lookup = $program . '_METASOURCES\s*=\s*(.*)';
778         return 1    if ($MakefileData !~ /\n($lookup)\n/);
779         $found = $1;
780     } else {
781         $lookup = $program . '_METASOURCES\s*=\s*(.*)';
782         if ($MakefileData !~ /\n($lookup)\n/) {
783             $lookup = 'METASOURCES\s*=\s*(.*)';
784             return 1    if ($MakefileData !~ /\n($lookup)\n/o);
785             $found = $1;
786             $metasourceTags = 0; # we can use the general target only once
787         } else {
788             $found = $1;
789         }
790     }
791     print STDOUT "METASOURCE processing <$found>)\n"      if ($verbose);
792     
793     $postEqual = $found;
794     $postEqual =~ s/[^=]*=//;
795     
796     removeLine ($lookup, $found);
797     
798     # Always find the header files that could be used to "moc"
799     return 1    if (findMocCandidates ());
800     
801     if ($postEqual =~ /AUTO\s*(\S*)|USE_AUTOMOC\s*(\S*)/)
802     {
803         print STDERR "$printname: the argument for AUTO|USE_AUTOMOC is obsolete" if ($+);
804         $mocExt = ".moc.$cxxsuffix";
805         $haveAutomocTag = 1;
806     }
807     else
808     {
809         # Not automoc so read the list of files supplied which
810         # should be .moc files.
811
812         $postEqual =~ tr/\034/ /;
813
814         # prune out extra headers - This also checks to make sure that
815         # the list is valid.
816         pruneMocCandidates ($postEqual);
817     }
818
819     checkMocCandidates ();
820     
821     if (@newObs) {
822         my $ext =  ($program =~ /_la$/) ? ".moc.lo " : ".moc.o ";
823         $realObjs{$program} .= "\034" . join ($ext, @newObs) . $ext;
824         $depedmocs{$program} = join (".moc.$cxxsuffix " , @newObs) . ".moc.$cxxsuffix";
825         foreach $file (@newObs) {
826             $dep_files .= " \$(DEPDIR)/$file.moc.P" if($dep_files !~/$file.moc.P/);
827         }
828     }
829     if (@deped) {
830         $depedmocs{$program} .= " ";
831         $depedmocs{$program} .= join('.moc ', @deped) . ".moc";
832         $depedmocs{$program} .= " ";
833     }
834     addMocRules ();
835     @globalmocs{keys %mocFiles}=values %mocFiles;
836 }
837
838 #-----------------------------------------------------------------------------
839
840 # Returns 0 if the line was processed - 1 otherwise.
841 # Errors are logged in the global $errorflags
842 sub tag_AUTOMAKE ()
843 {
844     my $lookup = '.*cd \$\(top_srcdir\)\s+&&[\s\034]+\$\(AUTOMAKE\)(.*)';
845     return 1    if ($MakefileData !~ /\n($lookup)\n/);
846     print STDOUT "AUTOMAKE processing <$1>\n"        if ($verbose);
847
848     my $newLine = $1."\n\tcd \$(top_srcdir) && perl $thisProg $printname";
849     substituteLine ($lookup, $newLine);
850     $automkCall = $1;
851     return 0;
852 }
853
854 #-----------------------------------------------------------------------------
855
856 sub handle_TOPLEVEL()
857 {
858     my $pofiles = "";
859     my @restfiles = ();
860     opendir (THISDIR, ".");
861     foreach $entry (readdir(THISDIR)) {
862         next if (-d $entry);
863         
864         next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/ || $entry =~ /.gmo$/);
865                  
866         if ($entry =~ /\.po$/) {
867              next;
868         }
869         push(@restfiles, $entry);
870     }
871     closedir (THISDIR);
872             
873     if (@restfiles) {
874         $target_adds{"install-data-am"} .= "install-nls-files ";
875         $lines = "install-nls-files:\n";
876         $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$kdelang\n";
877         for $file (@restfiles) {
878             $lines .= "\t\$(INSTALL_DATA) \$\(srcdir\)/$file \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n";
879         }
880         $target_adds{"uninstall"} .= "uninstall-nls-files ";
881         $lines .= "uninstall-nls-files:\n";
882         for $file (@restfiles) {
883             $lines .= "\t-rm -f \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n";
884         }
885         appendLines($lines);
886     }
887     
888     return 0;
889 }
890
891 #-----------------------------------------------------------------------------
892
893 sub tag_SUBDIRS ()
894 {
895   if ($MakefileData !~ /\nSUBDIRS\s*=\s*\$\(AUTODIRS\)\s*\n/) {
896     return 1;
897   }
898
899   my $subdirs = ".";
900
901   opendir (THISDIR, ".");
902   foreach $entry (readdir(THISDIR)) {
903     next if ($entry eq "CVS" || $entry =~ /^\./);
904     if (-d $entry && -f $entry . "/Makefile.am") {
905       $subdirs .= " $entry";
906       next;
907     }
908   }
909   closedir (THISDIR);
910
911   my $lines = "SUBDIRS =$subdirs\n";
912   substituteLine('SUBDIRS\s*=.*', $lines);
913   return 0;
914 }
915
916 sub tag_IDLFILES ()
917 {
918     my @psources = split(/[\034\s]+/, $sources{$program});
919     my $dep_lines = "";
920     my @cppFiles = ();
921     
922     foreach $source (@psources) {
923         
924         my $skel = ($source =~ m/\.skel$/);
925         
926         if ($source =~ m/\.stub$/ || $skel) {
927             
928             my $qs = quotemeta($source);
929             $sources{$program} =~ s/$qs//;
930             $sources_changed{$program} = 1;
931             
932             print STDOUT "adding IDL file $source\n" if ($verbose);
933             
934             $source =~ s/\.(stub|skel)$//;
935             
936             my $sourcename;
937             
938             if ($skel) {
939                 $sourcename = "$source\_skel";
940             } else {
941                 $sourcename = "$source\_stub";
942             }
943             
944             my $sourcedir = '';
945             if (-f "$makefileDir/$source.h") {
946                 $sourcedir = '$(srcdir)/';
947             } else {
948                 if ($MakefileData =~ /\n$source\_DIR\s*=\s*(\S+)\n/) {
949                     $sourcedir = $1;
950                     $sourcedir .= "/" if ($sourcedir !~ /\/$/);
951                 }
952             }
953             
954             if ($allidls !~ /$source\_kidl/) {
955                 
956                 $dep_lines .= "$source.kidl: $sourcedir$source.h \$(DCOPIDL_DEPENDENCIES)\n";
957                 $dep_lines .= "\t\$(DCOPIDL) $sourcedir$source.h > $source.kidl || ( rm -f $source.kidl ; /bin/false )\n";
958                 
959                 $allidls .= $source . "_kidl ";
960             }
961             
962             if ($allidls !~ /$sourcename/) {
963                 
964                 if ($skel) {
965                     $dep_lines .= "$sourcename.$cxxsuffix: $source.kidl\n";
966                     $dep_lines .= "\t\$(DCOPIDL2CPP) --c++-suffix $cxxsuffix --no-stub $source.kidl\n";
967                 } else {
968                     $target_adds{"$sourcename.$cxxsuffix"} .= "$sourcename.h ";
969                     $dep_lines .= "$sourcename.h: $source.kidl\n";
970                     $dep_lines .= "\t\$(DCOPIDL2CPP) --c++-suffix $cxxsuffix --no-skel $source.kidl\n";
971                 }
972                 
973                 $allidls .= $sourcename . " ";
974             }
975             
976             $idlfiles{$program} .= $sourcename . " ";
977             
978             if ($program =~ /_la$/) {
979                 $realObjs{$program} .= " $sourcename.lo";
980             } else {
981                 $realObjs{$program} .= " $sourcename.\$(OBJEXT)";
982             }
983             $sources{$program} .= " $sourcename.$cxxsuffix";
984             $sources_changed{$program} = 1;
985             $important{$program} .= "$sourcename.h " if (!$skel);
986             $idl_output .= "\\\n\t$sourcename.$cxxsuffix $sourcename.h $source.kidl ";
987             push(@cleanfiles, "$sourcename.$cxxsuffix");
988             push(@cleanfiles, "$sourcename.h");
989             push(@cleanfiles, "$sourcename.kidl");
990             $dep_files .= " \$(DEPDIR)/$sourcename.P" if ($dep_files !~/$sourcename.P/);
991         }
992     }
993     if ($dep_lines) {
994         appendLines($dep_lines);
995     }
996     
997     if (0) {
998         my $lookup = "($program)";
999         $lookup .= '(|\$\(EXEEXT\))';
1000         $lookup =~ s/\_/./g;
1001         $lookup .= ":(.*..$program\_OBJECTS..*)";
1002         #    $lookup = quotemeta($lookup);
1003         if ($MakefileData =~ /\n$lookup\n/) {
1004             
1005             my $line = "$1$2: ";
1006             foreach $file (split(' ', $idlfiles{$program})) {
1007                 $line .= "$file.$cxxsuffix ";
1008             }
1009             $line .= $3;
1010             substituteLine($lookup, $line);
1011         } else {
1012             print STDERR "no built dependency found $lookup\n";
1013         }
1014     }
1015 }
1016
1017 sub tag_UIFILES ()
1018 {
1019     my @psources = split(/[\034\s]+/, $sources{$program});
1020     my $dep_lines = "";
1021     my @depFiles = ();
1022     
1023     foreach $source (@psources) {
1024
1025         if ($source =~ m/\.ui$/) {
1026
1027             print STDERR "adding UI file $source\n" if ($verbose);
1028
1029             my $qs = quotemeta($source);
1030             $sources{$program} =~ s/$qs//;
1031             $sources_changed{$program} = 1;
1032       
1033             $source =~ s/\.ui$//;
1034
1035             my $sourcedir = '';
1036             if (-f "$makefileDir/$source.ui") {
1037                 $sourcedir = '$(srcdir)/';
1038             }
1039
1040             if (!$uiFiles{$source}) {
1041
1042                 $dep_lines .= "$source.$cxxsuffix: $sourcedir$source.ui $source.h $source.moc\n";
1043                 $dep_lines .= "\trm -f $source.$cxxsuffix\n";
1044                 if (!$kdeopts{"qtonly"}) {
1045                     $dep_lines .= "\techo '#include <klocale.h>' > $source.$cxxsuffix\n";
1046                     $dep_lines .= "\t\$(UIC) -tr \${UIC_TR} -i $source.h $sourcedir$source.ui | sed -e \"s,\${UIC_TR}( \\\"\\\" ),QString::null,g\" | sed -e \"s,\${UIC_TR}( \\\"\\\"\\, \\\"\\\" ),QString::null,g\" >> $source.$cxxsuffix || rm -f $source.$cxxsuffix\n";
1047                 } else {
1048                     $dep_lines .= "\t\$(UIC) -i $source.h $sourcedir$source.ui > $source.$cxxsuffix || rm -f $source.$cxxsuffix\n";
1049                 }
1050                 $dep_lines .= "\techo '#include \"$source.moc\"' >> $source.$cxxsuffix\n\n";
1051                 $dep_lines .= "$source.h: $sourcedir$source.ui\n";
1052                 $dep_lines .= "\t\$(UIC) -o $source.h $sourcedir$source.ui\n\n";
1053                 $dep_lines .= "$source.moc: $source.h\n";
1054                 $dep_lines .= "\t\$(MOC) $source.h -o $source.moc\n";
1055
1056                 $uiFiles{$source} = 1;
1057                 $depedmocs{$program} .= " $source.moc";
1058                 $globalmocs{$source} = "\035$source.h\035$source.cpp";
1059             }
1060             
1061             if ($program =~ /_la$/) {
1062                 $realObjs{$program} .= " $source.lo";
1063             } else {
1064                 $realObjs{$program} .= " $source.\$(OBJEXT)";
1065             }
1066             $sources{$program} .= " $source.$cxxsuffix";
1067             $sources_changed{$program} = 1;
1068             $important{$program} .= "$source.h ";
1069             $ui_output .= "\\\n\t$source.$cxxsuffix $source.h $source.moc ";
1070             push(@cleanfiles, "$source.$cxxsuffix");
1071             push(@cleanfiles, "source.h");
1072             push(@cleanfiles, "$source.moc");
1073             $dep_files .= " \$(DEPDIR)/$source.P" if($dep_files !~/$source.P/ );
1074         }
1075     }
1076     if ($dep_lines) {
1077         appendLines($dep_lines);
1078     }
1079 }
1080
1081 sub tag_ICON()
1082 {
1083     my $lookup = '([^\s]*)_ICON\s*=\s*([^\n]*)';
1084     my $install = "";
1085     my $uninstall = "";
1086
1087     while ($MakefileData =~ /\n$lookup/og) {
1088         my $destdir;
1089         if ($1 eq "KDE") {
1090             $destdir = "kde_icondir";
1091         } else {
1092             $destdir = $1 . "dir";
1093         }
1094         my $iconauto = ($2 =~ /AUTO\s*$/);
1095         my @appnames = ();
1096         if ( ! $iconauto ) {
1097             my @_appnames = split(" ", $2);
1098             print STDOUT "KDE_ICON processing <@_appnames>\n"   if ($verbose);
1099             foreach $appname (@_appnames) {
1100                 push(@appnames, quotemeta($appname));
1101             }
1102         } else {
1103             print STDOUT "KDE_ICON processing <AUTO>\n"   if ($verbose);
1104         }
1105
1106         my @files = ();
1107         opendir (THISDIR, ".");
1108         foreach $entry (readdir(THISDIR)) {
1109             next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/);
1110             next if (! -f $entry);
1111             if ( $iconauto )
1112               {
1113                   push(@files, $entry)
1114                     if ($entry =~ /\.xpm/ || $entry =~ /\.png/);
1115               } else {
1116                   foreach $appname (@appnames) {
1117                       push(@files, $entry)
1118                         if ($entry =~ /-$appname\.xpm/ || $entry =~ /-$appname\.png/);
1119                   }
1120               }
1121         }
1122         closedir (THISDIR);
1123         
1124         my %directories = ();
1125         
1126         foreach $file (@files) {
1127             my $newfile = $file;
1128             my $prefix = $file;
1129             $prefix =~ s/\.(png|xpm)$//;
1130             my $appname = $prefix;
1131             $appname =~ s/^[^-]+-// if ($appname =~ /-/) ;
1132             $appname =~ s/^[^-]+-// if ($appname =~ /-/) ;
1133             $appname = quotemeta($appname);
1134             $prefix =~ s/$appname$//;
1135             $prefix =~ s/-$//;
1136             
1137             $prefix = 'lo16-app' if ($prefix eq 'mini');
1138             $prefix = 'lo32-app' if ($prefix eq 'lo');
1139             $prefix = 'hi48-app' if ($prefix eq 'large');
1140             $prefix .= '-app' if ($prefix =~ m/^...$/);
1141             
1142             my $type = $prefix;
1143             $type =~ s/^.*-([^-]+)$/$1/;
1144             $prefix =~ s/^(.*)-[^-]+$/$1/;
1145             
1146             my %type_hash =
1147               (
1148                'action' => 'actions',
1149                'app' => 'apps',
1150                'device' => 'devices',
1151                'filesys' => 'filesystems',
1152                'mime' => 'mimetypes'
1153               );
1154             
1155             if (! defined $type_hash{$type} ) {
1156                 print STDERR "unknown icon type $type in $printname ($file)\n";
1157                 next;
1158             }
1159             
1160             my %dir_hash =
1161               (
1162                'los' => 'locolor/16x16',
1163                'lom' => 'locolor/32x32',
1164                'him' => 'hicolor/32x32',
1165                'hil' => 'hicolor/48x48',
1166                'lo16' => 'locolor/16x16',
1167                'lo22' => 'locolor/22x22',
1168                'lo32' => 'locolor/32x32',
1169                'hi16' => 'hicolor/16x16',
1170                'hi22' => 'hicolor/22x22',
1171                'hi32' => 'hicolor/32x32',
1172                'hi48' => 'hicolor/48x48',
1173                'hi64' => 'hicolor/64x64',
1174                'hisc' => 'hicolor/scalable'
1175               );
1176             
1177             $newfile =~ s@.*-($appname\.(png|xpm?))@$1@;
1178             
1179             if (! defined $dir_hash{$prefix}) {
1180                 print STDERR "unknown icon prefix $prefix in $printname\n";
1181                 next;
1182             }
1183             
1184             my $dir = $dir_hash{$prefix} . "/" . $type_hash{$type};
1185             if ($newfile =~ /-[^\.]/) {
1186                 my $tmp = $newfile;
1187                 $tmp =~ s/^([^-]+)-.*$/$1/;
1188                 $dir = $dir . "/" . $tmp;
1189                 $newfile =~ s/^[^-]+-//;
1190             }
1191             
1192             if (!defined $directories{$dir}) {
1193                 $install .= "\t\$(mkinstalldirs) \$(DESTDIR)\$($destdir)/$dir\n";
1194                 $directories{$dir} = 1;
1195             }
1196             
1197             $install .= "\t\$(INSTALL_DATA) \$(srcdir)/$file \$(DESTDIR)\$($destdir)/$dir/$newfile\n";
1198             $uninstall .= "\t-rm -f \$(DESTDIR)\$($destdir)/$dir/$newfile\n";
1199             
1200         }
1201     }
1202
1203     if (length($install)) {
1204         $target_adds{"install-data-am"} .= "install-kde-icons ";
1205         $target_adds{"uninstall-am"} .= "uninstall-kde-icons ";
1206         appendLines("install-kde-icons:\n" . $install . "\nuninstall-kde-icons:\n" . $uninstall);
1207     }
1208 }
1209
1210 sub handle_POFILES($$)
1211 {
1212   my @pofiles = split(" ", $_[0]);
1213   my $lang = $_[1];
1214
1215   # Build rules for creating the gmo files
1216   my $tmp = "";
1217   my $allgmofiles     = "";
1218   my $pofileLine   = "POFILES =";
1219   foreach $pofile (@pofiles)
1220     {
1221         $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1222         $tmp .= "$1.gmo: $pofile\n";
1223         $tmp .= "\trm -f $1.gmo; \$(GMSGFMT) -o $1.gmo \$(srcdir)/$pofile\n";
1224         $tmp .= "\ttest ! -f $1.gmo || touch $1.gmo\n";
1225         $allgmofiles .= " $1.gmo";
1226         $pofileLine  .= " $1.po";
1227     }
1228   appendLines ($tmp);
1229   my $lookup = 'POFILES\s*=([^\n]*)';
1230   if ($MakefileData !~ /\n$lookup/o) {
1231     appendLines("$pofileLine\nGMOFILES =$allgmofiles");
1232   } else {
1233     substituteLine ($lookup, "$pofileLine\nGMOFILES =$allgmofiles");
1234   }
1235
1236     if ($allgmofiles) {
1237
1238         # Add the "clean" rule so that the maintainer-clean does something
1239         appendLines ("clean-nls:\n\t-rm -f $allgmofiles\n");
1240
1241         $target_adds{"maintainer-clean"} .= "clean-nls ";
1242
1243         $lookup = 'DISTFILES\s*=\s*(.*)';
1244         if ($MakefileData =~ /\n$lookup\n/o) {
1245           $tmp = "DISTFILES = \$(GMOFILES) \$(POFILES) $1";
1246           substituteLine ($lookup, $tmp);
1247         }
1248     }
1249
1250   $target_adds{"install-data-am"} .= "install-nls ";
1251
1252   $tmp = "install-nls:\n";
1253   if ($lang) {
1254     $tmp  .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES\n";
1255   }
1256   $tmp .= "\t\@for base in ";
1257   foreach $pofile (@pofiles)
1258     {
1259       $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1260       $tmp .= "$1 ";
1261     }
1262
1263   $tmp .= "; do \\\n";
1264   if ($lang) {
1265     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n";
1266     $tmp .= "\t  test ! -f \$\$base.gmo || \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n"
1267   } else {
1268     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n";
1269     $tmp .= "\t  \$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES ; \\\n";
1270     $tmp .= "\t  test ! -f \$\$base.gmo || \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n";
1271   }
1272   $tmp .= "\tdone\n\n";
1273   appendLines ($tmp);
1274
1275   $target_adds{"uninstall"} .= "uninstall-nls ";
1276
1277   $tmp = "uninstall-nls:\n";
1278   foreach $pofile (@pofiles)
1279     {
1280       $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1281       if ($lang) {
1282         $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/$1.mo\n";
1283       } else {
1284         $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$1/LC_MESSAGES/\$(PACKAGE).mo\n";
1285       }
1286     }
1287   appendLines($tmp);
1288
1289   $target_adds{"all"} .= "all-nls ";
1290
1291   $tmp = "all-nls: \$(GMOFILES)\n";
1292
1293   appendLines($tmp);
1294
1295   $target_adds{"distdir"} .= "distdir-nls ";
1296
1297   $tmp = "distdir-nls:\$(GMOFILES)\n";
1298   $tmp .= "\tfor file in \$(POFILES); do \\\n";
1299   $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
1300   $tmp .= "\tdone\n";
1301   $tmp .= "\tfor file in \$(GMOFILES); do \\\n";
1302   $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
1303   $tmp .= "\tdone\n";
1304
1305   appendLines ($tmp);
1306
1307   if (!$lang) {
1308     appendLines("merge:\n\t\$(MAKE) -f \$(top_srcdir)/admin/Makefile.common package-merge POFILES=\"\${POFILES}\" PACKAGE=\${PACKAGE}\n\n");
1309   }
1310  
1311 }
1312
1313 #-----------------------------------------------------------------------------
1314
1315 # Returns 0 if the line was processed - 1 otherwise.
1316 # Errors are logged in the global $errorflags
1317 sub tag_POFILES ()
1318 {
1319     my $lookup = 'POFILES\s*=([^\n]*)';
1320     return 1    if ($MakefileData !~ /\n$lookup/o);
1321     print STDOUT "POFILES processing <$1>\n"   if ($verbose);
1322
1323     my $tmp = $1;
1324
1325     # make sure these are all gone.
1326     if ($MakefileData =~ /\n\.po\.gmo:\n/)
1327     {
1328         print STDERR "Warning: Found old .po.gmo rules in $printname. New po rules not added\n";
1329         return 1;
1330     }
1331
1332     # Either find the pofiles in the directory (AUTO) or use
1333     # only the specified po files.
1334     my $pofiles = "";
1335     if ($tmp =~ /^\s*AUTO\s*$/)
1336     {
1337         opendir (THISDIR, ".");
1338         $pofiles =  join(" ", grep(/\.po$/, readdir(THISDIR)));
1339         closedir (THISDIR);
1340         print STDOUT "pofiles found = $pofiles\n"   if ($verbose);
1341         if (-f "charset" && -f "kdelibs.po") {
1342             handle_TOPLEVEL();
1343         }
1344     }
1345     else
1346     {
1347         $tmp =~ s/\034/ /g;
1348         $pofiles = $tmp;
1349     }
1350     return 1    if (!$pofiles);        # Nothing to do
1351
1352     handle_POFILES($pofiles, $kdelang);
1353
1354     return 0;
1355 }
1356
1357 sub helper_LOCALINSTALL($)
1358 {
1359   my $lookup = "\n" . $_[0] . ":";
1360   if ($MakefileData =~ /($lookup)/) {
1361
1362     my $install = $MakefileData;
1363     $install =~ s/\n/\035/g;
1364     $install =~ s/.*\035$_[0]:[^\035]*\035//;
1365     my $emptyline = 0;
1366     while (! $emptyline) {
1367       if ($install =~ /([^\035]*)\035(.*)/) {
1368         local $line = $1;
1369         $install = $2;
1370         if ($line !~ /^\s*$/ && $line !~ /^(\@.*\@)*\t/) {
1371           $emptyline = 1;
1372         } else {
1373           replaceDestDir($line);
1374         }
1375       } else {
1376         $emptyline = 1;
1377       }
1378     }
1379   }
1380
1381 }
1382
1383 sub tag_LOCALINSTALL ()
1384 {
1385   helper_LOCALINSTALL('install-exec-local');
1386   helper_LOCALINSTALL('install-data-local');
1387   helper_LOCALINSTALL('uninstall-local');
1388
1389   return 0;
1390 }
1391
1392 sub replaceDestDir($) {
1393   local $line = $_[0];
1394
1395   if (   $line =~ /^\s*(\@.*\@)*\s*\$\(mkinstalldirs\)/
1396       || $line =~ /^\s*(\@.*\@)*\s*\$\(INSTALL\S*\)/
1397       || $line =~ /^\s*(\@.*\@)*\s*(-?rm.*) \S*$/)
1398   {
1399     $line =~ s/^(.*) ([^\s]+)\s*$/$1 \$(DESTDIR)$2/ if ($line !~ /\$\(DESTDIR\)/);
1400   }
1401
1402   if ($line ne $_[0]) {
1403     $_[0] = quotemeta $_[0];
1404     substituteLine($_[0], $line);
1405   }
1406 }
1407
1408 #---------------------------------------------------------------------------
1409 sub tag_CLOSURE () {
1410     return if ($program !~ /_la$/);
1411     
1412     my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n";
1413     $MakefileData =~ m/$lookup/;
1414     return if ($1 !~ /CXXLINK/);
1415
1416     if ($MakefileData !~ /\n$program\_LDFLAGS\s*=.*-no-undefined/ &&
1417         $MakefileData !~ /\n$program\_LDFLAGS\s*=.*KDE_PLUGIN/ ) {
1418         print STDERR "Report: $program contains undefined in $printname\n" if ($program =~ /^lib/ && $dryrun);
1419         return;
1420     }
1421     my $closure = $realname{$program} . ".closure";
1422     my $lines = "$closure: \$($program\_OBJECTS) \$($program\_DEPENDENCIES)\n";
1423     $lines .= "\t\@echo \"int main() {return 0;}\" > $program\_closure.$cxxsuffix\n";
1424     $lines .= "\t\@\$\(LTCXXCOMPILE\) -c $program\_closure.$cxxsuffix\n";
1425     $lines .= "\t\$\(CXXLINK\) $program\_closure.lo \$($program\_LDFLAGS) \$($program\_OBJECTS) \$($program\_LIBADD) \$(LIBS)\n";
1426     $lines .= "\t\@rm -f $program\_closure.* $closure\n";
1427     $lines .= "\t\@echo \"timestamp\" > $closure\n";
1428     $lines .= "\n";
1429     appendLines($lines);
1430     $lookup = $realname{$program} . ": (.*)";
1431     if ($MakefileData =~ /\n$lookup\n/) {
1432         $lines  = "\@KDE_USE_CLOSURE_TRUE@". $realname{$program} . ": $closure $1";
1433         $lines .= "\n\@KDE_USE_CLOSURE_FALSE@" . $realname{$program} . ": $1";
1434         substituteLine($lookup, $lines);
1435     }
1436     $closure_output .= " $closure";
1437 }
1438
1439 sub tag_DIST () {
1440     my %foundfiles = ();
1441     opendir (THISDIR, ".");
1442     foreach $entry (readdir(THISDIR)) {
1443         next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile$$/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/);
1444         next if (! -f $entry);
1445         next if ($entry =~ /\.moc/ || $entry =~ /\.lo$/ || $entry =~ /\.la$/ || $entry =~ /\.o/);
1446         next if ($entry =~ /.+meta_unload.$cppExt$/ || $entry =~ /\.all_$cppExt\.$cppExt$/);
1447         $foundfiles{$entry} = 1;
1448     }
1449     closedir (THISDIR);
1450
1451     my @marks = ("EXTRA_DIST", "DIST_COMMON", '\S*_SOURCES', '\S*_HEADERS', 'MAINTAINERCLEANFILES', 'CLEANFILES', 'DISTCLEANFILES', '\S*_OBJECTS');
1452     foreach $mark (@marks) {
1453         while ($MakefileData =~ /\n($mark)\s*=\s*([^\n]*)/g) {
1454             foreach $file (split('[\034\s]', $2)) {
1455                 $file =~ s/\.\///;
1456                 $foundfiles{$file} = 0 if (defined $foundfiles{$file});
1457             }
1458         }
1459     }
1460     my @files = ("Makefile", "config.cache", "config.log", "stamp-h",
1461                  "stamp-h1", "stamp-h1", "config.h", "Makefile", "config.status", "config.h", "libtool");
1462     foreach $file (@files) {
1463         $foundfiles{$file} = 0 if (defined $foundfiles{$file});
1464     }
1465
1466     my $KDE_DIST = "";
1467     foreach $file (keys %foundfiles) {
1468         if ($foundfiles{$file} == 1) {
1469             $KDE_DIST .= "$file ";
1470         }
1471     }
1472     if ($KDE_DIST) {
1473         print "KDE_DIST $printname $KDE_DIST\n" if ($verbose);
1474         
1475         my $lookup = "DISTFILES *=(.*)";
1476         if ($MakefileData =~ /\n$lookup\n/o) {
1477             substituteLine($lookup, "KDE_DIST=$KDE_DIST\n\nDISTFILES=$1 \$(KDE_DIST)\n");
1478         }
1479     }
1480 }
1481
1482 #-----------------------------------------------------------------------------
1483 # Returns 0 if the line was processed - 1 otherwise.
1484 # Errors are logged in the global $errorflags
1485 sub tag_DOCFILES ()
1486 {
1487 #    if ($MakefileData =~ /\nSUBDIRS\s*=/) { # subdirs
1488 #      $MakefileData =~ /\n(.*-recursive:\s*)\n/;
1489 #      my $orig_rules = $1;
1490 #      my $rules = $orig_rules;
1491 #      $rules =~ s/:\s*$//;
1492 #      substituteLine($orig_rules, "$rules docs-recursive:");
1493 #      appendLines("docs: docs-recursive docs-am\n");
1494 #    } else {
1495 #      appendLines("docs: docs-am\n");
1496 #    }
1497     $target_adds{"all"} .= "docs-am ";
1498
1499     my $lookup = 'KDE_DOCS\s*=\s*([^\n]*)';
1500     goto nodocs    if ($MakefileData !~ /\n$lookup/o);
1501     print STDOUT "KDE_DOCS processing <$1>\n"   if ($verbose);
1502
1503     my $tmp = $1;
1504
1505     # Either find the files in the directory (AUTO) or use
1506     # only the specified po files.
1507     my $files = "";
1508     my $appname = $tmp;
1509     $appname =~ s/^(\S*)\s*.*$/$1/;
1510     if ($appname =~ /AUTO/) {
1511       $appname = basename($makefileDir);
1512       if ("$appname" eq "en") {
1513           print STDERR "Error: KDE_DOCS = AUTO relies on the directory name. Yours is 'en' - you most likely want something else, e.g. KDE_DOCS = myapp\n";
1514           exit(1);
1515       }
1516     }
1517
1518     if ($tmp !~ / - /)
1519     {
1520         opendir (THISDIR, ".");
1521         foreach $entry (readdir(THISDIR)) {
1522           next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/);
1523           next if (! -f $entry);
1524           $files .= "$entry ";
1525         }
1526         closedir (THISDIR);
1527         print STDOUT "docfiles found = $files\n"   if ($verbose);
1528     }
1529     else
1530     {
1531         $tmp =~ s/\034/ /g;
1532         $tmp =~ s/^\S*\s*-\s*//;
1533         $files = $tmp;
1534     }
1535     goto nodocs if (!$files);        # Nothing to do
1536
1537     if ($files =~ /(^| )index\.docbook($| )/) {
1538       
1539       my $lines = "";
1540       my $lookup = 'MEINPROC\s*=';
1541       if ($MakefileData !~ /\n($lookup)/) {
1542         $lines = "MEINPROC=/\$(kde_bindir)/meinproc\n";
1543       }
1544       $lookup = 'KDE_XSL_STYLESHEET\s*=';
1545       if ($MakefileData !~ /\n($lookup)/) {
1546         $lines .= "KDE_XSL_STYLESHEET=/\$(kde_datadir)/ksgmltools2/customization/kde-chunk.xsl\n";
1547       }
1548       $lookup = '\nindex.cache.bz2:';
1549       if ($MakefileData !~ /\n($lookup)/) {
1550          $lines .= "index.cache.bz2: \$(srcdir)/index.docbook \$(KDE_XSL_STYLESHEET) $files\n";
1551          $lines .= "\t-\@if test -n \"\$(MEINPROC)\"; then echo \$(MEINPROC) --check --cache index.cache.bz2 \$(srcdir)/index.docbook; \$(MEINPROC) --check --cache index.cache.bz2 \$(srcdir)/index.docbook; fi\n";
1552          $lines .= "\n";
1553       }
1554  
1555       $lines .= "docs-am: index.cache.bz2\n";  
1556       $lines .= "\n";
1557       $lines .= "install-docs: docs-am install-nls\n";
1558       $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n";
1559       $lines .= "\t\@if test -f index.cache.bz2; then \\\n";
1560       $lines .= "\techo \$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
1561       $lines .= "\t\$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
1562       $lines .= "\tfi\n";
1563       $lines .= "\t-rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n";
1564       $lines .= "\t\$(LN_S) \$(kde_libs_htmldir)/$kdelang/common \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n";
1565
1566       $lines .= "\n";
1567       $lines .= "uninstall-docs:\n";
1568       $lines .= "\t-rm -rf \$(kde_htmldir)/$kdelang/$appname\n";
1569       $lines .= "\n";
1570       $lines .= "clean-docs:\n";
1571       $lines .= "\t-rm -f index.cache.bz2\n";
1572       $lines .= "\n";
1573       $target_adds{"install-data-am"} .= "install-docs ";
1574       $target_adds{"uninstall"} .= "uninstall-docs ";
1575       $target_adds{"clean-am"} .= "clean-docs ";
1576       appendLines ($lines);
1577     } else {
1578       appendLines("docs-am: $files\n");
1579     }
1580
1581     $target_adds{"install-data-am"} .= "install-nls";
1582     $target_adds{"uninstall"} .= "uninstall-nls ";
1583
1584     $tmp = "install-nls:\n";
1585     $tmp .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n";
1586     $tmp .= "\t\@for base in $files; do \\\n";
1587     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
1588     $tmp .= "\t  \$(INSTALL_DATA) \$(srcdir)/\$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
1589     $tmp .= "\tdone\n";
1590     if ($appname eq 'common') {
1591       $tmp .= "\t\@echo \"merging common and language specific dir\" ;\\\n";
1592       $tmp .= "\tif test ! -e \$(kde_htmldir)/en/common/kde-common.css; then echo 'no english docs found in \$(kde_htmldir)/en/common/'; exit 1; fi \n";
1593       $tmp .= "\t\@com_files=`cd \$(kde_htmldir)/en/common && echo *` ;\\\n";
1594       $tmp .= "\tcd \$(DESTDIR)\$(kde_htmldir)/$kdelang/common ;\\\n";
1595       $tmp .= "\tif test -n \"\$\$com_files\"; then for p in \$\$com_files ; do \\\n";
1596       $tmp .= "\t  case \" $files \" in \\\n";
1597       $tmp .= "\t    *\" \$\$p \"*) ;; \\\n";
1598       $tmp .= "\t    *) test ! -e \$\$p && echo \$(LN_S) ../../en/common/\$\$p \$(DESTDIR)\$(kde_htmldir)/$kdelang/common/\$\$p && \$(LN_S) ../../en/common/\$\$p \$\$p ;; \\\n";
1599       $tmp .= "\t  esac ; \\\n";
1600       $tmp .= "\tdone ; fi ; true\n";
1601     }
1602     $tmp .= "\n";
1603     $tmp .= "uninstall-nls:\n";
1604     $tmp .= "\tfor base in $files; do \\\n";
1605     $tmp .= "\t  rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
1606     $tmp .= "\tdone\n\n";
1607     appendLines ($tmp);
1608
1609     $target_adds{"distdir"} .= "distdir-nls ";
1610
1611     $tmp = "distdir-nls:\n";
1612     $tmp .= "\tfor file in $files; do \\\n";
1613     $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
1614     $tmp .= "\tdone\n";
1615
1616     appendLines ($tmp);
1617
1618     return 0;
1619
1620   nodocs:
1621     appendLines("docs-am:\n");
1622     return 1;
1623 }
1624
1625 #-----------------------------------------------------------------------------
1626 # Find headers in any of the source directories specified previously, that
1627 # are candidates for "moc-ing".
1628 sub findMocCandidates ()
1629 {
1630     foreach $dir (@headerdirs)
1631     {
1632         my @list = ();
1633         opendir (SRCDIR, "$dir");
1634         @hFiles = grep { /.+\.$hExt$/o && !/^\./ } readdir(SRCDIR);
1635         closedir SRCDIR;
1636         foreach $hf (@hFiles)
1637         {
1638             next if ($hf =~ /^\.\#/);
1639             $hf =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1640             next if ($uiFiles{$1});
1641             open (HFIN, "$dir/$hf") || die "Could not open $dir/$hf: $!\n";
1642             my $hfsize = 0;
1643             seek(HFIN, 0, 2);
1644             $hfsize = tell(HFIN);
1645             seek(HFIN, 0, 0);
1646             read HFIN, $hfData, $hfsize;
1647             close HFIN;
1648             # push (@list, $hf) if(index($hfData, "Q_OBJECT") >= 0); ### fast but doesn't handle //Q_OBJECT
1649             if ( $hfData =~ /{([^}]*)Q_OBJECT/s ) {              ## handle " { friend class blah; Q_OBJECT "
1650                 push (@list, $hf) unless $1 =~ m://[^\n]*Q_OBJECT[^\n]*$:s;  ## handle "// Q_OBJECT"
1651             }
1652         }
1653         # The assoc array of root of headerfile and header filename
1654         foreach $hFile (@list)
1655         {
1656             $hFile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1657             if ($mocFiles{$1})
1658             {
1659               print STDERR "Warning: Multiple header files found for $1\n";
1660               next;                           # Use the first one
1661             }
1662             $mocFiles{$1} = "$dir\035$hFile";   # Add relative dir
1663         }
1664     }
1665
1666     return 0;
1667 }
1668
1669 #-----------------------------------------------------------------------------
1670
1671 # The programmer has specified a moc list. Prune out the moc candidates
1672 # list that we found based on looking at the header files. This generates
1673 # a warning if the programmer gets the list wrong, but this doesn't have
1674 # to be fatal here.
1675 sub pruneMocCandidates ($)
1676 {
1677     my %prunedMoc = ();
1678     local @mocList = split(' ', $_[0]);
1679
1680     foreach $mocname (@mocList)
1681     {
1682         $mocname =~ s/\.moc$//;
1683         if ($mocFiles{$mocname})
1684         {
1685             $prunedMoc{$mocname} = $mocFiles{$mocname};
1686         }
1687         else
1688         {
1689             my $print = $makefileDir;
1690             $print =~ s/^\Q$topdir\E\\//;
1691             # They specified a moc file but we can't find a header that
1692             # will generate this moc file. That's possible fatal!
1693             print STDERR "Warning: No moc-able header file for $print/$mocname\n";
1694         }
1695     }
1696
1697     undef %mocFiles;
1698     %mocFiles = %prunedMoc;
1699 }
1700
1701 #-----------------------------------------------------------------------------
1702
1703 # Finds the cpp files (If they exist).
1704 # The cpp files get appended to the header file separated by \035
1705 sub checkMocCandidates ()
1706 {
1707     my @cppFiles;
1708     my $cpp2moc;  # which c++ file includes which .moc files
1709     my $moc2cpp;  # which moc file is included by which c++ files
1710
1711     return unless (keys %mocFiles);
1712     opendir(THISDIR, ".") || return;
1713     @cppFiles = grep { /.+\.$cppExt$/o  && !/.+\.moc\.$cppExt$/o
1714                          && !/.+\.all_$cppExt\.$cppExt$/o
1715                          && !/^\./  } readdir(THISDIR);
1716     closedir THISDIR;
1717     return unless (@cppFiles);
1718     my $files = join (" ", @cppFiles);
1719     $cpp2moc = {};
1720     $moc2cpp = {};
1721     foreach $cxxf (@cppFiles)
1722     {
1723       open (CXXFIN, $cxxf) || die "Could not open $cxxf: $!\n";
1724       seek(CXXFIN, 0, 2);
1725       my $cxxfsize = tell(CXXFIN);
1726       seek(CXXFIN, 0, 0);
1727       read CXXFIN, $cxxfData, $cxxfsize;
1728       close CXXFIN;
1729       while(($cxxfData =~ m/^[ \t]*\#include\s*[<\"](.*\.moc)[>\"]/gm)) {
1730         $cpp2moc->{$cxxf}->{$1} = 1;
1731         $moc2cpp->{$1}->{$cxxf} = 1;
1732       }
1733     }
1734     foreach my $mocFile (keys (%mocFiles))
1735     {
1736         @cppFiles = keys %{$moc2cpp->{"$mocFile.moc"}};
1737         if (@cppFiles == 1) {
1738             $mocFiles{$mocFile} .= "\035" . $cppFiles[0];
1739             push(@deped, $mocFile);
1740         } elsif (@cppFiles == 0) {
1741             push (@newObs, $mocFile);           # Produce new object file
1742             next    if ($haveAutomocTag);       # This is expected...
1743             # But this is an error we can deal with - let them know
1744             print STDERR
1745                 "Warning: No c++ file that includes $mocFile.moc\n";
1746         } else {
1747             # We can't decide which file to use, so it's fatal. Although as a
1748             # guess we could use the mocFile.cpp file if it's in the list???
1749             print STDERR
1750                 "Error: Multiple c++ files that include $mocFile.moc\n";
1751             print STDERR "\t",join ("\t", @cppFiles),"\n";
1752             $errorflag = 1;
1753             delete $mocFiles{$mocFile};
1754             # Let's continue and see what happens - They have been told!
1755         }
1756     }
1757 }
1758
1759 #-----------------------------------------------------------------------------
1760
1761 # Add the rules for generating moc source from header files
1762 # For Automoc output *.moc.cpp but normally we'll output *.moc
1763 # (We must compile *.moc.cpp separately. *.moc files are included
1764 # in the appropriate *.cpp file by the programmer)
1765 sub addMocRules ()
1766 {
1767     my $cppFile;
1768     my $hFile;
1769
1770     foreach $mocFile (keys (%mocFiles))
1771     {
1772         undef $cppFile;
1773         ($dir, $hFile, $cppFile) =  split ("\035", $mocFiles{$mocFile}, 3);
1774         $dir =~ s#^\.#\$(srcdir)#;
1775         if (defined ($cppFile))
1776         {
1777             $target_adds{"\$(srcdir)/$cppFile"} .= "$mocFile.moc ";
1778             appendLines ("$mocFile.moc: $dir/$hFile\n\t\$(MOC) $dir/$hFile -o $mocFile.moc\n");
1779             $cleanMoc .= " $mocFile.moc";
1780         }
1781         else
1782         {
1783             appendLines ("$mocFile$mocExt: $dir/$hFile\n\t\$(MOC) $dir/$hFile -o $mocFile$mocExt\n");
1784             $cleanMoc .= " $mocFile$mocExt";
1785         }
1786     }
1787 }
1788
1789 sub make_meta_classes ()
1790 {
1791     return if ($kdeopts{"qtonly"});
1792
1793     my $cppFile;
1794     my $hFile;
1795     my $moc_class_headers = "";
1796     foreach $program (@programs) {
1797         my $mocs = "";
1798         my @progsources = split(/[\s\034]+/, $sources{$program});
1799         my @depmocs = split(' ', $depedmocs{$program});
1800         my %shash = (), %mhash = ();
1801         @shash{@progsources} = 1;  # we are only interested in the existence
1802         @mhash{@depmocs} = 1;
1803
1804         print STDOUT "program=$program\n" if ($verbose);
1805         print STDOUT "psources=[".join(' ', keys %shash)."]\n" if ($verbose);
1806         print STDOUT "depmocs=[".join(' ', keys %mhash)."]\n" if ($verbose);
1807         print STDOUT "globalmocs=[".join(' ', keys(%globalmocs))."]\n" if ($verbose);
1808         foreach my $mocFile (keys (%globalmocs))
1809         {
1810             undef $cppFile;
1811             ($dir, $hFile, $cppFile) = split ("\035", $globalmocs{$mocFile}, 3);
1812             $dir =~ s#^\.#\$(srcdir)#;
1813             if (defined ($cppFile))
1814             {
1815                 $mocs .= " $mocFile.moc" if exists $shash{$cppFile};
1816             }
1817             else
1818             {
1819                 # Bah. This is the case, if no C++ file includes the .moc
1820                 # file. We make a .moc.cpp file for that. Unfortunately this
1821                 # is not included in the %sources hash, but rather is mentioned
1822                 # in %depedmocs. If the user wants to use AUTO he can't just
1823                 # use an unspecific METAINCLUDES. Instead he must use
1824                 # program_METAINCLUDES. Anyway, it's not working real nicely.
1825                 # E.g. Its not clear what happens if user specifies two
1826                 # METAINCLUDES=AUTO in the same Makefile.am.
1827                 $mocs .= " $mocFile.moc.$cxxsuffix"
1828                     if exists $mhash{$mocFile.".moc.$cxxsuffix"};
1829             }
1830         }
1831         if ($mocs) {
1832             print STDOUT "==> mocs=[".$mocs."]\n" if ($verbose);
1833             my $sourcename = $program."_meta_unload";
1834             my $ext = ($program =~ /_la$/) ? ".lo" : ".o";
1835             my $srcfile = $sourcename.".$cxxsuffix";
1836             my $objfile = $sourcename.$ext;
1837             $moc_class_headers .= " $srcfile";
1838             my $appl;
1839             $appl  = "$srcfile: $mocs\n";
1840             $appl .= "\t\@echo 'creating $srcfile'\n";
1841             $appl .= "\t\@-rm -f $srcfile\n";
1842             $appl .= "\t\@if test \${kde_qtver} = 2; then \\\n";
1843             $appl .= "\t\techo 'static const char * _metalist_$program\[\] = {' > $srcfile ;\\\n";
1844             $appl .= "\t\tcat $mocs | grep 'char.*className' | ";
1845             $appl .=  "sed -e 's/.*[^A-Za-z0-9_:]\\([A-Za-z0-9_:]*\\)::className.*\$\$/\\\"\\1\\\",/' | sort | uniq >> $srcfile ;\\\n";
1846             $appl .= "\t\techo '0};' >> $srcfile ;\\\n";
1847             $appl .= "\t\techo '#include <kunload.h>' >> $srcfile ;\\\n";
1848             $appl .= "\t\techo '_UNLOAD($program)' >> $srcfile ;\\\n";
1849             $appl .= "\telse echo > $srcfile; fi\n";
1850             $appl .= "\n";
1851             
1852             $realObjs{$program} .= " \034" . $objfile . " ";
1853             $sources{$program} .= " $srcfile";
1854             $sources_changed{$program} = 1;
1855             $dep_files .= " \$(DEPDIR)/$sourcename.P" if($dep_files !~/$sourcename.P/);
1856             appendLines ($appl);
1857         }
1858         print STDOUT "\n" if $verbose;
1859     }
1860     if ($moc_class_headers) {
1861         appendLines ("$cleantarget-moc-classes:\n\t-rm -f $moc_class_headers\n");
1862         $target_adds{"$cleantarget-am"} .= "$cleantarget-moc-classes ";
1863     }
1864 }
1865
1866 #-----------------------------------------------------------------------------
1867
1868 sub updateMakefile ()
1869 {
1870     return if ($dryrun);
1871
1872     open (FILEOUT, "> $makefile")
1873                         || die "Could not create $makefile: $!\n";
1874
1875     print FILEOUT "\# $progId - " . '$Revision$ '  . "\n";
1876     $MakefileData =~ s/\034/\\\n\t/g;    # Restore continuation lines
1877     print FILEOUT $MakefileData;
1878     close FILEOUT;
1879 }
1880
1881 #-----------------------------------------------------------------------------
1882
1883 # The given line needs to be removed from the makefile
1884 # Do this by adding the special "removed line" comment at the line start.
1885 sub removeLine ($$)
1886 {
1887     my ($lookup, $old) = @_;
1888
1889     $old =~ s/\034/\\\n#>- /g;          # Fix continuation lines
1890     $MakefileData =~ s/\n$lookup/\n#>\- $old/;
1891 }
1892
1893 #-----------------------------------------------------------------------------
1894
1895 # Replaces the old line with the new line
1896 # old line(s) are retained but tagged as removed. The new line(s) have the
1897 # "added" tag placed before it.
1898 sub substituteLine ($$)
1899 {
1900     my ($lookup, $new) = @_;
1901
1902     if ($MakefileData =~ /\n($lookup)/) {
1903       $old = $1;
1904       $old =~ s/\034/\\\n#>\- /g;         # Fix continuation lines
1905       $new =~ s/\034/\\\n\t/g;
1906       my $newCount = ($new =~ tr/\n//) + 1;
1907       $MakefileData =~ s/\n$lookup/\n#>- $old\n#>\+ $newCount\n$new/;
1908     } else {
1909       print STDERR "Warning: substitution of \"$lookup\" in $printname failed\n";
1910     }
1911 }
1912
1913 #-----------------------------------------------------------------------------
1914
1915 # Slap new lines on the back of the file.
1916 sub appendLines ($)
1917 {
1918   my ($new) = @_;
1919   $new =~ s/\034/\\\n\t/g;        # Fix continuation lines
1920   my $newCount = ($new =~ tr/\n//) + 1;
1921   $MakefileData .= "\n#>\+ $newCount\n$new";
1922 }
1923
1924 #-----------------------------------------------------------------------------
1925
1926 # Restore the Makefile.in to the state it was before we fiddled with it
1927 sub restoreMakefile ()
1928 {
1929     $MakefileData =~ s/# $progId[^\n\034]*[\n\034]*//g;
1930     # Restore removed lines
1931     $MakefileData =~ s/([\n\034])#>\- /$1/g;
1932     # Remove added lines
1933     while ($MakefileData =~ /[\n\034]#>\+ ([^\n\034]*)/)
1934     {
1935         my $newCount = $1;
1936         my $removeLines = "";
1937         while ($newCount--) {
1938             $removeLines .= "[^\n\034]*([\n\034]|)";
1939         }
1940         $MakefileData =~ s/[\n\034]#>\+.*[\n\034]$removeLines/\n/;
1941     }
1942 }
1943
1944 #-----------------------------------------------------------------------------