tagging KDE 3.5.8
[kdevelop:kdevelop.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 #    http://developer.kde.org/documentation/other/developer-faq.html
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 # Dirk Mueller <mueller@kde.org>
35
36 use Cwd;
37 use File::Find;
38 use File::Basename;
39
40 # Prototype the functions
41 sub initialise ();
42 sub processMakefile ($);
43 sub updateMakefile ();
44 sub restoreMakefile ();
45
46 sub removeLine ($$);
47 sub appendLines ($);
48 sub substituteLine ($$);
49
50 sub findMocCandidates ();
51 sub pruneMocCandidates ($);
52 sub checkMocCandidates ();
53 sub addMocRules ();
54 sub findKcfgFile($);
55
56 sub tag_AUTOMAKE ();
57 sub tag_META_INCLUDES ();
58 sub tag_METASOURCES ();
59 sub tag_POFILES ();
60 sub tag_DOCFILES ();
61 sub tag_LOCALINSTALL();
62 sub tag_IDLFILES();
63 sub tag_UIFILES();
64 sub tag_KCFGFILES();
65 sub tag_SUBDIRS();
66 sub tag_ICON();
67 sub tag_CLOSURE();
68 sub tag_NO_UNDEFINED();
69 sub tag_NMCHECK();
70 sub tag_DIST();
71 sub tag_KDEINIT();
72
73 # Some global globals...
74 $verbose    = 0;        # a debug flag
75 $thisProg   = "$0";     # This programs name
76 $topdir     = cwd();    # The current directory
77 @makefiles  = ();       # Contains all the files we'll process
78 @foreignfiles = ();
79 $start      = (times)[0]; # some stats for testing - comment out for release
80 $version    = "v0.2";
81 $errorflag  = 0;
82 $cppExt     = "(cpp|cc|cxx|C|c\\+\\+)";
83 $hExt       = "(h|H|hh|hxx|hpp|h\\+\\+)";
84 $progId     = "KDE tags expanded automatically by " . basename($thisProg);
85 $automkCall = "\n";
86 $printname  = "";  # used to display the directory the Makefile is in
87 $use_final  = 1;        # create code for --enable-final
88 $cleantarget = "clean";
89 $dryrun     = 0;
90 $pathoption = 0;
91 $foreign_libtool = 0;
92
93 while (defined ($ARGV[0]))
94 {
95     $_ = shift;
96     if (/^--version$/)
97     {
98         print STDOUT "\n";
99         print STDOUT basename($thisProg), " $version\n",
100                 "This is really free software, unencumbered by the GPL.\n",
101                 "You can do anything you like with it except sueing me.\n",
102                 "Copyright 1998 Kalle Dalheimer <kalle\@kde.org>\n",
103                 "Concept, design and unnecessary questions about perl\n",
104                 "       by Matthias Ettrich <ettrich\@kde.org>\n\n",
105                 "Making it useful by Stephan Kulow <coolo\@kde.org> and\n",
106                 "Harri Porten <porten\@kde.org>\n",
107                 "Updated (Feb-1999), John Birch <jb.nz\@writeme.com>\n",
108                 "Fixes and Improvements by Dirk Mueller <mueller\@kde.org>\n",
109                 "Current Maintainer Stephan Kulow\n\n";
110         exit 0;
111     }
112     elsif (/^--verbose$|^-v$/)
113     {
114         $verbose = 1;       # Oh is there a problem...?
115     }
116     elsif (/^(?:-p|--path=)(.+)$/)
117     {
118         my $p = $1;
119         $thisProg = $p . "/". basename($thisProg);
120         warn ("$thisProg doesn't exist\n")      if (!(-f $thisProg));
121         $thisProg .= " -p".$p;
122         $pathoption=1;
123     }
124     elsif (/^--help$|^-h$/)
125     {
126         print STDOUT "Usage $thisProg [OPTION] ... [dir/Makefile.in]...\n",
127                 "\n",
128                 "Patches dir/Makefile.in generated by automake\n",
129                 "(where dir can be an absolute or relative directory name)\n",
130                 "\n",
131                 "  -v, --verbose      verbosely list files processed\n",
132                 "  -h, --help         print this help, then exit\n",
133                 "  --version          print version number, then exit\n",
134                 "  -p, --path=        use the path to am_edit if the path\n",
135                 "                     called from is not the one to be used\n",
136                 "  --no-final         don't patch for --enable-final\n";
137         
138         exit 0;
139     }
140     elsif (/^--no-final$/)
141     {
142         $use_final = 0;
143         $thisProg .= " --no-final";
144     }
145     elsif (/^--foreign-libtool$/)
146     {
147         $foreign_libtool = 1;
148         $thisProg .= " --foreign-libtool";
149     }
150     elsif (/^-n$/)
151     {
152         $dryrun = 1;
153     }
154     else
155     {
156         # user selects what input files to check
157         # add full path if relative path is given
158         $_ = cwd()."/".$_   if (! /^\//);
159         print "User wants $_\n" if ($verbose);
160         push (@makefiles, $_);
161     }
162 }
163
164 if ($thisProg =~ /^\// && !$pathoption )
165 {
166   print STDERR "Illegal full pathname call performed...\n",
167       "The call to \"$thisProg\"\nwould be inserted in some Makefile.in.\n",
168       "Please use option --path.\n";
169   exit 1;
170 }
171
172 # Only scan for files when the user hasn't entered data
173 if (!@makefiles)
174 {
175     print STDOUT "Scanning for Makefile.in\n"       if ($verbose);
176     find (\&add_makefile, cwd());
177     #chdir('$topdir');
178 } else {
179     print STDOUT "Using input files specified by user\n"   if ($verbose);
180 }
181
182 foreach $makefile (sort(@makefiles))
183 {
184     processMakefile ($makefile);
185     last            if ($errorflag);
186 }
187
188 # Just some debug statistics - comment out for release as it uses printf.
189 printf STDOUT "Time %.2f CPU sec\n", (times)[0] - $start     if ($verbose);
190
191 exit $errorflag;        # causes make to fail if erroflag is set
192
193 #-----------------------------------------------------------------------------
194
195 # In conjunction with the "find" call, this builds the list of input files
196 sub add_makefile ()
197 {
198   push (@makefiles, $File::Find::name) if (/Makefile.in$/);
199 }
200
201 #-----------------------------------------------------------------------------
202
203 # Processes a single make file
204 # The parameter contains the full path name of the Makefile.in to use
205 sub processMakefile ($)
206 {
207     # some useful globals for the subroutines called here
208     local ($makefile)       = @_;
209     local @headerdirs       = ('.');
210     local $haveAutomocTag   = 0;
211     local $MakefileData     = "";
212
213     local $cxxsuffix  = "KKK";
214
215     local @programs = ();  # lists the names of programs and libraries
216     local $program = "";
217
218     local @kdeinits = (); # lists the kdeinit targets
219
220     local %realObjs = ();  # lists the objects compiled into $program
221     local %sources = ();   # lists the sources used for $program
222     local %finalObjs = (); # lists the objects compiled when final
223     local %realname = ();  # the binary name of program variable
224     local %idlfiles = ();  # lists the idl files used for $program
225     local %globalmocs = ();# list of all mocfiles (in %mocFiles format)
226     local %important = (); # list of files to be generated asap
227     local %uiFiles = ();
228     local %kcfgFiles = ();
229
230     local $allidls = "";
231     local $idl_output = "";# lists all idl generated files for cleantarget
232     local $ui_output = "";# lists all uic generated files for cleantarget
233     local $kcfg_output = "";# lists all kcfg generated files for cleantarget
234
235     local %dependmocs = ();
236     
237     local $metasourceTags = 0;
238     local $dep_files      = "";
239     local $dep_finals     = "";
240     local %target_adds    = (); # the targets to add
241     local %rule_adds      = ();
242     local $kdelang        = "";
243     local @cleanfiles     = ();
244     local $cleanMoc       = "";
245     local $closure_output = "";
246
247     local %varcontent     = ();
248
249     $makefileDir = dirname($makefile);
250     chdir ($makefileDir);
251     $printname = $makefile;
252     $printname =~ s/^\Q$topdir\E\///;
253     $makefile = basename($makefile);
254
255     print STDOUT "Processing makefile $printname\n"   if ($verbose);
256
257     # Setup and see if we need to do this.
258     return      if (!initialise());
259
260     tag_AUTOMAKE ();            # Allows a "make" to redo the Makefile.in
261     tag_META_INCLUDES ();       # Supplies directories for src locations
262
263     foreach $program (@programs) {
264         $sources_changed{$program} = 0;
265         $dependmocs{$program} = "";
266         $important{$program} = "";
267         tag_IDLFILES();             # Sorts out idl rules
268         tag_NO_UNDEFINED();
269         tag_CLOSURE();
270         tag_NMCHECK();
271         tag_UIFILES();              # Sorts out ui rules
272         tag_KCFGFILES();            # Sorts out kcfg rules
273         tag_METASOURCES ();         # Sorts out the moc rules
274         if ($sources_changed{$program}) {
275             my $lookup = $program . '_SOURCES\s*=[ \t]*(.*)';
276
277             if($program =~ /libkdeinit_(.*)/) {
278                 my $prog = $1;
279                 substituteLine($prog . '_SOURCES\s*=[ \t]*(.*)', 
280                     "${prog}_SOURCES = ${prog}_dummy.$cxxsuffix\n" .
281                     "libkdeinit_${prog}_SOURCES = " . $sources{$program});
282                 $sources{$prog} = "${prog}_dummy.$cxxsuffix";
283             }
284             else {
285                 substituteLine($lookup, "$program\_SOURCES=" . $sources{$program});
286             }
287         }
288         if ($important{$program}) {
289             local %source_dict = ();
290             for $source (split(/[\034\s]+/, $sources{$program})) {
291                 $source_dict{$source} = 1;
292             }
293             for $source (@cleanfiles) {
294                 $source_dict{$source} = 0;
295             }
296             for $source (keys %source_dict) {
297                 next if (!$source);
298                 if ($source_dict{$source}) {
299                     # sanity check
300                     if (! -f $source) {
301                         print STDERR "Error: $source is listed in a _SOURCE line in $printname, but doesn't exist yet. Put it in DISTCLEANFILES!\n";
302                     } else {
303                         $target_adds{"\$(srcdir)/$source"} .= $important{$program};
304                     }
305                 }
306             }
307         }
308     }
309     if ($cleanMoc) {
310         # Always add dist clean tag
311         # Add extra *.moc.cpp files created for USE_AUTOMOC because they
312         # aren't included in the normal *.moc clean rules.
313         appendLines ("$cleantarget-metasources:\n\t-rm -f $cleanMoc\n");
314         $target_adds{"$cleantarget-am"} .= "$cleantarget-metasources ";
315     }
316     
317     tag_DIST() unless ($kdeopts{"noautodist"});
318
319     if ($idl_output) {
320         appendLines ("$cleantarget-idl:\n\t-rm -f $idl_output\n");
321         $target_adds{"$cleantarget-am"} .= "$cleantarget-idl ";
322     }
323
324     if ($ui_output) {
325         appendLines ("$cleantarget-ui:\n\t-rm -f $ui_output\n");
326         $target_adds{"$cleantarget-am"} .= "$cleantarget-ui ";
327     }
328
329     if ($kcfg_output) {
330         appendLines ("$cleantarget-kcfg:\n\t-rm -f $kcfg_output\n");
331         $target_adds{"$cleantarget-am"} .= "$cleantarget-kcfg ";
332     }
333
334     if ($closure_output) {
335         appendLines ("$cleantarget-closures:\n\t-rm -f $closure_output\n");
336         $target_adds{"$cleantarget-am"} .= "$cleantarget-closures ";
337     }
338
339     if ($MakefileData =~ /\nKDE_LANG\s*=\s*(\S*)\s*\n/) {
340         $kdelang = '$(KDE_LANG)'
341     } else {
342         $kdelang = '';
343     }
344
345     tag_POFILES ();             # language rules for po directory
346     tag_DOCFILES ();            # language rules for doc directories
347     tag_LOCALINSTALL();         # add $(DESTDIR) before all kde_ dirs
348     tag_ICON();
349     tag_SUBDIRS();
350
351     my $tmp = "force-reedit:\n";
352     $tmp   .= "\t$automkCall\n\tcd \$(top_srcdir) && perl $thisProg $printname\n\n";
353     appendLines($tmp);
354
355     make_bcheck_target();
356     make_meta_classes();
357     tag_COMPILE_FIRST();
358     tag_FINAL() if (!$kdeopts{"nofinal"});
359
360     my $final_lines = "final:\n\t\$(MAKE) ";
361     my $final_install_lines = "final-install:\n\t\$(MAKE) ";
362     my $nofinal_lines = "no-final:\n\t\$(MAKE) ";
363     my $nofinal_install_lines = "no-final-install:\n\t\$(MAKE) ";
364
365     foreach $program (@programs) {
366         my $lookup = $program . '_OBJECTS\s*=[ \t]*.*';
367         my $new = "";
368         my @list = split(/[\034\s]+/, $realObjs{$program});
369         if (!$kdeopts{"nofinal"} && @list > 1 && $finalObjs{$program}) {
370             $new .= "$program\_final\_OBJECTS = " . $finalObjs{$program};
371             $new .= "\n$program\_nofinal\_OBJECTS = " . $realObjs{$program};
372             $new .= "\n\@KDE_USE_FINAL_FALSE\@$program\_OBJECTS = \$($program\_nofinal\_OBJECTS)";
373             $new .= "\n\@KDE_USE_FINAL_TRUE\@$program\_OBJECTS = \$($program\_final\_OBJECTS)";
374
375             $final_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" ";
376             $final_install_lines .= "$program\_OBJECTS=\"\$($program\_final_OBJECTS)\" ";
377             $nofinal_lines .= "$program\_OBJECTS=\"\$($program\_nofinal\_OBJECTS)\" ";
378             $nofinal_install_lines .= "$program\_OBJECTS=\"\$($program\_nofinal_OBJECTS)\" ";
379         } else {
380             $new = "$program\_OBJECTS = " . $realObjs{$program};
381         }
382         if($MakefileData =~ m/\n$lookup/) {
383             substituteLine ($lookup, $new);
384         }
385         else {
386             appendLines("$new\n");
387         }
388     }
389     appendLines($final_lines . "all-am\n");
390     appendLines($final_install_lines . "install-am\n");
391     appendLines($nofinal_lines . "all-am\n");
392     appendLines($nofinal_install_lines . "install-am\n");
393
394     my $lookup = '(\@\S+\@)?DEP_FILES\s*=[ \t]*(.*)';
395     if ($MakefileData =~ /\n$lookup/) {
396         my $condition = $1;
397         my $depfiles = $2;
398         my $workfiles;
399
400         if ($dep_finals) {
401             # Add the conditions on every line, since
402             # there may be line continuations in the list.
403             $workfiles = "$dep_files $dep_finals $depfiles";
404             $workfiles =~ s/\034/\034$condition\@KDE_USE_FINAL_TRUE\@\t/g;
405             $lines  = "$condition\@KDE_USE_FINAL_TRUE\@DEP_FILES = $workfiles\n";
406             $workfiles = "$dep_files $depfiles";
407             $workfiles =~ s/\034/\034$condition\@KDE_USE_FINAL_FALSE\@\t/g;
408             $lines .= "$condition\@KDE_USE_FINAL_FALSE\@DEP_FILES = $workfiles";
409         } else {
410             $workfiles = "$dep_files $depfiles";
411             $workfiles =~ s/\034/\034$condition\t/g;
412             $lines = $condition . "DEP_FILES = $workfiles";
413         }
414         substituteLine($lookup, $lines);
415     }
416
417     # new recursive targets
418     $target_adds{ "nmcheck" } .= ""; # always create nmcheck target
419     $target_adds{ "nmcheck-am" } .= "nmcheck";
420     $lookup = 'RECURSIVE_TARGETS\s*=[ \t]*(.*)';
421     if ($MakefileData =~ /\n$lookup/) {
422       substituteLine($lookup, "RECURSIVE_TARGETS = $1 nmcheck-recursive bcheck-recursive");
423     }
424
425     $cvs_lines  = "kde-rpo-clean:\n";
426     $cvs_lines .= "\t-rm -f *.rpo\n";
427     appendLines($cvs_lines);
428     $target_adds{"clean"} .= "kde-rpo-clean ";
429
430     my %target_dels = ("install-data-am" => "");
431
432     # some strange people like to do a install-exec, and expect that also
433     # all modules are installed.  automake doesn't know this, so we need to move
434     # this here from install-data to install-exec.
435     if ($MakefileData =~ m/\nkde_module_LTLIBRARIES\s*=/) {
436 #      $target_adds{"install-exec-am"} .= "install-kde_moduleLTLIBRARIES ";
437 #      don't use $target_adds here because we need to append the dependency, not
438 #      prepend it. Fixes #44342 , when a module depends on a lib in the same dir
439 #      and libtool needs it during relinking upon install (Simon)
440       my $lookup = "install-exec-am:([^\n]*)";
441       if($MakefileData =~ /\n$lookup\n/) {
442         substituteLine("$lookup", "install-exec-am: $1 install-kde_moduleLTLIBRARIES");
443       }
444       $target_dels{"install-data-am"} .= "install-kde_moduleLTLIBRARIES ";
445       $target_adds{"install-data-am"} .= " ";
446     }
447
448     my $lines = "";
449
450     foreach $add (keys %target_adds) {
451         my $lookup = quotemeta($add) . ':([^\n]*)';
452         if ($MakefileData =~ /\n$lookup\n/) {
453           my $newlines = $1;
454           my $oldlines = $lookup;
455           if (defined $target_dels{$add}) {
456             foreach $del (split(' ', $target_dels{$add})) {
457               $newlines =~ s/\s*$del\s*/ /g;
458             }
459           }
460           substituteLine($oldlines, "$add: " . $target_adds{$add} . $newlines);
461         } else {
462           $lines .= "$add: " . $target_adds{$add} . "\n";
463         }
464     }
465
466     appendLines($lines) if ($lines);
467
468     $lines = join("\n", values %rule_adds);
469     appendLines($lines) if ($lines);
470
471     my $found = 1;
472
473     while ($found) {
474         if ($MakefileData =~ m/\n(.*)\$\(CXXFLAGS\)(.*)\n/) {
475             my $stuff_before = $1;
476             my $stuff_after = $2;
477             my $lookup = quotemeta("$1\$(CXXFLAGS)$2");
478             my $replacement = "$1\$(KCXXFLAGS)$2";
479             $MakefileData =~ s/$lookup/$replacement/;
480             $lookup =~ s/\\\$\\\(CXXFLAGS\\\)/\\\$\\\(KCXXFLAGS\\\)/;
481             $replacement = "$stuff_before\$(KCXXFLAGS) \$(KDE_CXXFLAGS)$stuff_after";
482             next if ($stuff_before =~ /\$\(KDE_CXXFLAGS\)/ or $stuff_after =~ /\$\(KDE_CXXFLAGS\)/);
483             substituteLine($lookup, $replacement);
484         } else {
485             $found = 0;
486         }
487     }
488
489     if($foreign_libtool == 0) {
490         $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=link) (\$\(CXXLD\).*\$\(KCXXFLAGS\))';
491
492         if ($MakefileData =~ m/$lookup/ ) {
493             $MakefileData =~ s/$lookup/$1 --tag=CXX $2/;
494         }
495
496         $lookup = '(\n[^#].*\$\(LIBTOOL\) --mode=compile)\s+(\$\(CXX\)\s+)';
497         if ($MakefileData =~ m/$lookup/ ) {
498             $MakefileData =~ s/$lookup/$1 --tag=CXX $2/;
499         }
500     }
501
502     $MakefileData =~ s/\$\(KCXXFLAGS\)/\$\(CXXFLAGS\)/g;
503
504     $lookup = '(.*)cp -pr \$\$/\$\$file \$\(distdir\)/\$\$file(.*)';
505     if ($MakefileData =~ m/\n$lookup\n/) {
506         substituteLine($lookup, "$1cp -pr \$\$d/\$\$file \$(distdir)/\$\$file$2");
507     }
508
509     # Always update the Makefile.in
510     updateMakefile ();
511     return;
512 }
513
514 #-----------------------------------------------------------------------------
515
516 # Beware: This procedure is not complete.  E.g. it also parses lines
517 # containing a '=' in rules (for instance setting shell vars).  For our
518 # usage this us enough, though.
519 sub read_variables ()
520 {
521     while ($MakefileData =~ /\n\s*(\S+)\s*=([^\n]*)/g) {
522         $varcontent{$1} = $2;
523     }
524 }
525
526 # Check to see whether we should process this make file.
527 # This is where we look for tags that we need to process.
528 # A small amount of initialising on the tags is also done here.
529 # And of course we open and/or create the needed make files.
530 sub initialise ()
531 {
532     if (! -r "Makefile.am") {
533         print STDOUT "found Makefile.in without Makefile.am\n" if ($verbose);
534         return 0;
535     }
536
537     # Checking for files to process...
538
539     open (FILEIN, $makefile) || die "Can't open $makefileDir/$makefile: $!\n";
540     # perl bug in 5.8.0: in utf8 mode it badly screws up
541     binmode(FILEIN, ":bytes") if ($] >= 5.008);
542     # Read the file
543     # stat(FILEIN)[7] might look more elegant, but is slower as it 
544     # requires stat'ing the file
545     seek(FILEIN, 0, 2);
546     my $fsize = tell(FILEIN);
547     seek(FILEIN, 0, 0);
548     read FILEIN, $MakefileData, $fsize;
549     close FILEIN;
550     print "DOS CRLF within $makefileDir/$makefile!\n" if($MakefileData =~ y/\r//d);
551
552     # Remove the line continuations, but keep them marked
553     # Note: we lose the trailing spaces but that's ok.
554     # Don't mangle line-leading spaces (usually tabs)
555     # since they're important.
556     $MakefileData =~ s/\\\s*\n/\034/g;
557
558     # If we've processed the file before...
559     restoreMakefile ()      if ($MakefileData =~ /$progId/);
560
561     foreach $dir (@foreignfiles) {
562       if (substr($makefileDir,0,length($dir)) eq $dir) {
563         return 0;
564       }
565     }
566
567     %kdeopts = ();
568     $kdeopts{"foreign"} = 0;
569     $kdeopts{"qtonly"} = 0;
570     $kdeopts{"noautodist"} = 0;
571     $kdeopts{"foreign-libtool"} = $foreign_libtool;
572     $kdeopts{"nofinal"} = !$use_final; # default
573
574     read_variables();
575
576     if ($MakefileData =~ /\nKDE_OPTIONS\s*=[ \t]*([^\n]*)\n/) {
577         my $kde_options_str = $1;
578         local @kde_options = split(/[\034\s]+/, $kde_options_str);
579         if (grep(/^foreign$/, @kde_options)) {
580             push(@foreignfiles, $makefileDir . "/");
581             return 0; # don't touch me
582         }
583         for $opt (@kde_options) {
584             if (!defined $kdeopts{$opt}) {
585                 print STDERR "Warning: unknown option $opt in $printname\n";
586             } else {
587                 $kdeopts{$opt} = 1;
588             }
589         }
590     }
591
592     # Look for the tags that mean we should process this file.
593     $metasourceTags = 0;
594     $metasourceTags++    while ($MakefileData =~ /\n[^=\#]*METASOURCES\s*=/g);
595
596     my $pofileTag = 0;
597     $pofileTag++    while ($MakefileData =~ /\nPOFILES\s*=/g);
598     if ($pofileTag > 1)
599       {
600           print STDERR "Error: Only one POFILES tag allowed\n";
601           $errorflag = 1;
602       }
603
604     while ($MakefileData =~ /\n\.SUFFIXES:([^\n]+)\n/g) {
605         my $suffixes_str = $1;
606         my @list=split(' ', $suffixes_str);
607         foreach $ext (@list) {
608             if ($ext =~ /^\.$cppExt$/) {
609                 $cxxsuffix = $ext;
610                 $cxxsuffix =~ s/\.//g;
611                 print STDOUT "will use suffix $cxxsuffix\n" if ($verbose);
612                 last;
613             }
614         }
615     }
616
617     tag_KDEINIT();
618
619     while ($MakefileData =~ /\n(\S*)_OBJECTS\s*=[\034 \t]*([^\n]*)\n/g) {
620
621         my $program = $1;
622         my $objs = $2; # safe them
623
624         my $ocv = 0;
625
626         my @objlist = split(/[\034\s]+/, $objs);
627         foreach $obj (@objlist) {
628             if ($obj =~ /(\S*)\$\((\S+)\)/ ) {
629                 my $pre = $1;
630                 my $variable = $2;
631                 if ($pre eq '' && exists($varcontent{$variable})) {
632                     my @addlist = split(/[\034\s]+/, $varcontent{$variable});
633                     push(@objlist, @addlist);
634                 } elsif ($variable !~ 'OBJEXT' && $variable !~ /am__objects_\d+/ ) {
635                     $ocv = 1;
636                 }
637             }
638         }
639
640         next if ($ocv);
641         next if ($program =~ /^am_libkdeinit_/);
642
643         $program =~ s/^am_// if ($program =~ /^am_/);
644
645         my $sourceprogram = $program;
646         $sourceprogram =~ s/\@am_/\@/ if($sourceprogram =~ /^.*\@am_.+/);
647
648         print STDOUT "found program $program\n" if ($verbose);
649         push(@programs, $program);
650
651         $realObjs{$program} = $objs;
652
653         if ($MakefileData =~ /\n$sourceprogram\_SOURCES\s*=[ \t]*(.*)\n/) {
654             $sources{$program} = $1;
655         } 
656         else {
657             $sources{$program} = "";
658             print STDERR "found program with no _SOURCES: $program\n";
659         }
660         
661         my $realprogram = $program;
662         $realprogram =~ s/_/./g; # unmask to regexp
663         if ($MakefileData =~ /\n($realprogram)(\$\(EXEEXT\)?)?:.*\$\($program\_OBJECTS\)/) {
664             $realname{$program} = $1;
665         } else {
666             # not standard Makefile - nothing to worry about
667             $realname{$program} = "";
668         }
669     }
670
671     my $lookup = 'DEPDIR\s*=.*';
672     if ($MakefileData !~ /\n$lookup/) {
673         $lookup = 'bindir\s*=[ \t]*.*';
674         substituteLine($lookup, "DEPDIR = .deps\n$1") if ($MakefileData =~ /\n($lookup)/);
675     }
676
677     my @marks = ('MAINTAINERCLEANFILES', 'CLEANFILES', 'DISTCLEANFILES');
678     foreach $mark (@marks) {
679         while ($MakefileData =~ /\n($mark)\s*=[ \t]*([^\n]*)/g) {
680             my $clean_str = $2; 
681             foreach $file (split('[\034\s]+', $clean_str)) {
682                 $file =~ s/\.\///;
683                 push(@cleanfiles, $file);
684             }
685         }
686     }
687
688     my $localTag = 0;
689     $localTag++ if ($MakefileData =~ /\ninstall-\S+-local:/);
690     
691     return (!$errorflag);
692 }
693
694 #-----------------------------------------------------------------------------
695
696 # Gets the list of user defined directories - relative to $srcdir - where
697 # header files could be located.
698 sub tag_META_INCLUDES ()
699 {
700     my $lookup = '[^=\n]*META_INCLUDES\s*=[ \t]*(.*)';
701     return 1    if ($MakefileData !~ /($lookup)\n/);
702     print STDOUT "META_INCLUDE processing <$1>\n"       if ($verbose);
703
704     my $headerStr = $2;
705     removeLine ($lookup, $1);
706
707     my @headerlist = split(/[\034\s]+/, $headerStr);
708
709     foreach $dir (@headerlist)
710     {
711         $dir =~ s#\$\(srcdir\)#.#;
712         if (! -d $dir)
713         {
714             print STDERR "Warning: $dir can't be found. ",
715                             "Must be a relative path to \$(srcdir)\n";
716         }
717         else
718         {
719             push (@headerdirs, $dir);
720         }
721     }
722
723     return 0;
724 }
725
726 #-----------------------------------------------------------------------------
727
728 sub tag_FINAL()
729 {
730     my @final_names = ();
731     
732     foreach $program (@programs) {
733         
734         if ($sources{$program} =~ /\(/) {
735             print STDOUT "found ( in $program\_SOURCES. skipping\n" if ($verbose);
736             next;
737         }
738
739         my $mocs = "";       # Moc files (in this program)
740         my $moc_cpp_added = 0;  # If we added some .moc.cpp files, due to
741                                 # no other .cpp file including the .moc one.
742         
743         my @progsources = split(/[\034\s]+/, $sources{$program});
744         my %shash = ();
745         @shash{@progsources} = 1;  # we are only interested in the existence
746         my %sourcelist = ();
747         my %extradeps = ();
748         
749         foreach $source (@progsources) {
750             my $suffix = $source;
751             $suffix =~ s/^.*\.([^\.]+)$/$1/;
752             
753             $sourcelist{$suffix} .= "$source ";
754         }
755         foreach my $mocFile (keys (%globalmocs))
756         {
757             my ($dir, $hFile, $cppFile) = split ("\035", $globalmocs{$mocFile}, 3);
758             if (defined ($cppFile)) {
759                 $mocs .= " $mocFile.moc" if exists $shash{$cppFile};
760             } else {
761                 $sourcelist{$cxxsuffix} .= "$mocFile.moc.$cxxsuffix ";
762                 $moc_cpp_added = 1;
763             }
764         }
765
766         # scan for extra given dependencies and add them to our target
767         while ($MakefileData =~ /\n\s*(\S+)\.(?:lo|o)\s*:([^\n]*)/g) {
768             $extradeps{$1} = $2;
769         }
770
771         foreach $suffix (keys %sourcelist) {
772             # See if this file contains c++ code. (i.e., just check the file's suffix against c++ extensions)
773             my $suffix_is_cxx = 0;
774             if($suffix =~ /($cppExt)$/) {
775               $cxxsuffix = $1;
776               $suffix_is_cxx = 1;
777             }
778             
779             my $mocfiles_in = ($suffix eq $cxxsuffix) && $moc_cpp_added;
780             
781             my @sourcelist = split(/[\034\s]+/, $sourcelist{$suffix});
782             
783             if ((@sourcelist == 1 && !$mocfiles_in) || $suffix_is_cxx != 1 ) {
784                 
785                 # we support IDL on our own
786                 if ($suffix eq "skel" || $suffix =~ /^stub/
787                     || $suffix =~ /^signals/ # obsolete, remove in KDE-4
788                     || $suffix eq "h" || $suffix eq "ui" 
789                     || $suffix eq "kcfgc" ) {
790                     next;
791                 }
792                 
793                 foreach $file (@sourcelist) {
794                     $file =~ s/\Q$suffix\E$//;
795                     
796                     $finalObjs{$program} .= $file;
797                     if ($program =~ /_la$/) {
798                         $finalObjs{$program} .= "lo ";
799                     } else {
800                         $finalObjs{$program} .= "o ";
801                     }
802                 }
803                 next; # suffix
804             }
805             
806             my $source_deps = "";
807             foreach $source (@sourcelist) {
808                 if (-f $source) {
809                     $source_deps .= " \$(srcdir)/$source";
810                 } else {
811                     $source_deps .= " $source";
812                 }
813                 my $plainsource = $source;
814                 $plainsource =~ s/\.$cppExt$//;
815                 $source_deps .= " " . $extradeps{$plainsource} if (exists($extradeps{$plainsource}));
816             }
817
818             $handling = "$program.all_$suffix.$suffix: \$(srcdir)/Makefile.in" . $source_deps . " " . join(' ', $mocs)  . "\n";
819             $handling .= "\t\@echo 'creating $program.all_$suffix.$suffix ...'; \\\n";
820             $handling .= "\trm -f $program.all_$suffix.files $program.all_$suffix.final; \\\n";
821             $handling .= "\techo \"#define KDE_USE_FINAL 1\" >> $program.all_$suffix.final; \\\n";
822             $handling .= "\tfor file in " . $sourcelist{$suffix} . "; do \\\n";
823             $handling .= "\t  echo \"#include \\\"\$\$file\\\"\" >> $program.all_$suffix.files; \\\n";
824             $handling .= "\t  test ! -f \$\(srcdir\)/\$\$file || egrep '^#pragma +implementation' \$\(srcdir\)/\$\$file >> $program.all_$suffix.final; \\\n";
825             $handling .= "\tdone; \\\n";
826             $handling .= "\tcat $program.all_$suffix.final $program.all_$suffix.files > $program.all_$suffix.$suffix; \\\n";
827             $handling .= "\trm -f $program.all_$suffix.final $program.all_$suffix.files\n";
828
829             appendLines($handling);
830
831             push(@final_names, "$program.all_$suffix.$suffix");
832             my $finalObj = "$program.all_$suffix.";
833             if ($program =~ /_la$/) {
834                 $finalObj .= "lo";
835             } else {
836                 $finalObj .= "o";
837             }
838             $finalObjs{$program} .= $finalObj . " ";
839         }
840     }
841     
842     if (!$kdeopts{"nofinal"} && @final_names >= 1) {
843         # add clean-final target
844         my $lines = "$cleantarget-final:\n";
845         $lines .= "\t-rm -f " . join(' ', @final_names) . "\n" if (@final_names);
846         appendLines($lines);
847         $target_adds{"$cleantarget-am"} .= "$cleantarget-final ";
848         
849         foreach $finalfile (@final_names) {
850             $finalfile =~ s/\.[^.]*$/.P/;
851             $dep_finals .= " \$(DEPDIR)/$finalfile";
852         }
853     }
854 }
855
856 sub tag_KDEINIT()
857 {
858     my @progs = ();
859     my $ltlibs = "";
860     my $lookup = 'kdeinit_LTLIBRARIES\s*=[ \t]*(.*)';
861
862     if ($MakefileData =~ m/\n$lookup/) {
863         @kdeinits = split(/[\034\s]+/, $1);
864         my $lines = "";
865         foreach my $kdeinit (@kdeinits) {
866             if ($kdeinit =~ m/\.la$/) {
867                 $kdeinit =~ s/\.la$//;
868                 push(@progs, $kdeinit);
869
870                 $lines .= "\n${kdeinit}.la.$cxxsuffix:\n";
871                 $lines .= "\techo 'extern \"C\" int kdemain(int argc, char* argv[]);' > ${kdeinit}.la.$cxxsuffix; \\\n";
872                 $lines .= "\techo 'int main(int argc, char* argv[]) { return kdemain(argc,argv); }' >> ${kdeinit}.la.$cxxsuffix\n";
873
874                 $lines .= "\n${kdeinit}_dummy.$cxxsuffix:\n";
875                 $lines .= "\techo '#include <kdemacros.h>' > ${kdeinit}_dummy.$cxxsuffix; \\\n";
876                 $lines .= "\techo 'extern \"C\" int kdemain(int argc, char* argv[]);' >> ${kdeinit}_dummy.$cxxsuffix; \\\n";
877                 $lines .= "\techo 'extern \"C\" KDE_EXPORT int kdeinitmain(int argc, char* argv[]) { return kdemain(argc,argv); }' >> ${kdeinit}_dummy.$cxxsuffix\n";
878
879                 push(@cleanfiles, "${kdeinit}.la.$cxxsuffix");
880                 push(@cleanfiles, "${kdeinit}_dummy.$cxxsuffix");
881
882                 # add dependency
883                 $dep_files .= " \$(DEPDIR)/${kdeinit}.la.Po" if($dep_files !~/${kdeinit}.la.Po/ );
884                 $dep_files .= " \$(DEPDIR)/${kdeinit}_dummy.Plo" if($dep_files !~/${kdeinit}_dummy.Plo/ );
885
886                 # make library
887                 $lookup = $kdeinit . '_la_LIBADD\s*=[ \t]*(.*)';
888                 if($MakefileData =~ m/\n$lookup/) {
889                     my $libadd = $1;
890                     substituteLine($lookup, "${kdeinit}_la_LIBADD = libkdeinit_${kdeinit}.la");
891                     appendLines("libkdeinit_${kdeinit}_la_LIBADD = $libadd\n");
892                 }
893                 appendLines("libkdeinit_${kdeinit}_la_LDFLAGS = -no-undefined -avoid-version \$(all_libraries)\n");
894
895                 # add library dependencies
896                 $lookup = $kdeinit . '_la_DEPENDENCIES\s*=[ \t]*(.*)';
897                 if($MakefileData =~ m/\n$lookup/) {
898                     my $libdeps = $1;
899                     substituteLine($lookup, "${kdeinit}_la_DEPENDENCIES = libkdeinit_${kdeinit}.la");
900                     appendLines("libkdeinit_${kdeinit}_la_DEPENDENCIES = $libdeps\n");
901                 }
902
903                 # make library objects
904                 $lookup = "am_${kdeinit}_la_OBJECTS" . '\s*=[ \t]*(.*)';
905                 if($MakefileData =~ m/\n$lookup/) {
906                     my $libobjects = $1;
907                     substituteLine($lookup, "am_${kdeinit}_la_OBJECTS = ${kdeinit}_dummy.lo");
908                     appendLines("am_libkdeinit_${kdeinit}_la_OBJECTS = $libobjects\n");
909                     my $prog = "libkdeinit_${kdeinit}_la";
910                     push(@programs, $prog);
911                     $realObjs{$prog} = $libobjects;
912                     $realname{$prog} = "libkdeinit_${kdeinit}.la";
913                 }
914                 $target_adds{"libkdeinit_${kdeinit}.la"} = "\$(libkdeinit_${kdeinit}_la_OBJECTS) \$(libkdeinit_${kdeinit}_la_DEPENDENCIES)\n" .
915                         "\t\$(CXXLINK) -rpath \$(libdir) \$(libkdeinit_${kdeinit}_la_LDFLAGS) ".
916                            "\$(libkdeinit_${kdeinit}_la_OBJECTS) " .
917                            "\$(libkdeinit_${kdeinit}_la_LIBADD) " .
918                            "\$(LIBS)\n";
919
920                 # make libkdeinit sources
921                 $lookup = $kdeinit . '_la_SOURCES\s*=[ \t]*(.*)';
922                 if($MakefileData =~ m/\n$lookup/) {
923                     my $srces = $1;
924                     $sources_changed{"libkdeinit_${kdeinit}_la"} = 1;
925                     $sources{"libkdeinit_${kdeinit}_la"} = $srces;
926                 }
927
928                 # make libkdeinit metasources
929                 $lookup = $kdeinit . '_la_METASOURCES\s*=[ \t]*(.*)';
930                 substituteLine($lookup, "libkdeinit_${kdeinit}_la_METASOURCES = $1")
931                     if($MakefileData =~ m/\n$lookup/);
932
933 =cut
934                 # make binary sources
935                 $lookup = $kdeinit. '_SOURCES\s*=[ \t]*(.*)';
936                 if($MakefileData =~ m/\n$lookup/) {
937                     substituteLine($lookup, "${kdeinit}_SOURCES = ${kdeinit}.la.$cxxsuffix");
938                     $lookup = 'SOURCES\s*=[ \t]*(.*)';
939                     if($MakefileData =~ m/\n$lookup/) {
940                         my $srces = $1;
941                         $srces =~ s/\b$kdeinit\.c\b/\$(${kdeinit}_SOURCES)/;
942                         $srces =~ s/\$\(${kdeinit}_la_SOURCES\)/\$(libkdeinit_${kdeinit}_la_SOURCES)/;
943                         substituteLine($lookup, "SOURCES = $srces");
944                     }
945                     $lookup = 'DIST_SOURCES\s*=[ \t](.*)';
946                     if($MakefileData =~ m/\n$lookup/) {
947                         my $srces = $1;
948                         $srces =~ s/\b$kdeinit\.c\b/\$(${kdeinit}_SOURCES)/;
949                         $srces =~ s/\$\(${kdeinit}_la_SOURCES\)/\$(libkdeinit_${kdeinit}_la_SOURCES)/;
950                         substituteLine($lookup, "DIST_SOURCES = $srces");
951                     }
952                 }
953
954                 # make binary objects / libs
955                 $lookup = $kdeinit . '_OBJECTS\s*=[ \t]*.*';
956                 if($MakefileData =~ m/\n$lookup/) {
957                     $realObjs{$kdeinit} = "${kdeinit}.la.\$(OBJEXT)";
958                     substituteLine("${kdeinit}_LDFLAGS\\s*=.*", "${kdeinit}_LDFLAGS = \$(all_libraries)");
959                     substituteLine("${kdeinit}_LDADD\\s*=.*", "${kdeinit}_LDADD = libkdeinit_${kdeinit}.la");
960                     substituteLine("${kdeinit}_DEPENDENCIES\\s*=.*", "${kdeinit}_DEPENDENCIES = libkdeinit_${kdeinit}.la");
961                 }
962 =cut
963                 # add binary
964                 push(@programs, $kdeinit);
965                 $realObjs{$kdeinit} = "${kdeinit}.la.\$(OBJEXT)";
966                 $realname{$kdeinit} = $kdeinit;
967                 $sources{$kdeinit} = "${kdeinit}.la.$cxxsuffix";
968
969                 $lines .= "${kdeinit}_LDFLAGS = \$(KDE_RPATH) -no-undefined \$(all_libraries)\n";
970                 $lines .= "${kdeinit}_LDADD = libkdeinit_${kdeinit}.la\n";
971                 $lines .= "${kdeinit}_DEPENDENCIES = libkdeinit_${kdeinit}.la\n";
972
973                 $target_adds{"${kdeinit}\$(EXEEXT)"} =
974                           "\$(${kdeinit}_OBJECTS) \$(${kdeinit}_DEPENDENCIES)\n" .
975                           "\t\@rm -f ${kdeinit}\$(EXEEXT)\n" .
976                           "\t\$(CXXLINK) \$(${kdeinit}_LDFLAGS) \$(${kdeinit}_OBJECTS) \$(${kdeinit}_LDADD) \$(LIBS)\n";
977
978                 $ltlibs .= " libkdeinit_${kdeinit}.la";
979             }
980         }
981         appendLines($lines);
982
983         # add libkdeinit target
984         $lookup = 'lib_LTLIBRARIES\s*=[ \t]*(.*)';
985         if($MakefileData =~ m/\n$lookup/) {
986             substituteLine($lookup, "lib_LTLIBRARIES = $1 $ltlibs");
987         }
988         else {
989             print STDERR
990                 "Error: lib_LTLIBRARIES missing in $printname (required for kdeinit_LTLIBRARIES).\n";
991             $errorflag = 1;
992         }
993     }
994
995     if($#progs >= 0) {
996         if($MakefileData !~ m/\nbin_PROGRAMS\s*=/) {
997             print STDERR "Error: bin_PROGRAMS missing in $printname (required for kdeinit_LTLIBRARIES).\n";
998             $errorflag = 1;
999         }
1000         else {
1001             # add our new progs to SOURCES, DIST_SOURCES and bin_PROGRAMS
1002             my $progsources = "";
1003             my $progexes = "";
1004             foreach my $p (@progs) {
1005                 $progsources .= "\$(${p}_SOURCES) ";
1006                 $progexes .= "${p}\$(EXEEXT) ";
1007             }
1008             $lookup = 'SOURCES\s*=[ \t]*(.*)';
1009             if($MakefileData =~ /\n$lookup/) {
1010                 substituteLine($lookup, "SOURCES = $1 $progsources");
1011             }
1012             $lookup = 'DIST_SOURCES\s*=[ \t]*(.*)';
1013             if($MakefileData =~ /\n$lookup/) {
1014                 substituteLine($lookup, "DIST_SOURCES = $1 $progsources");
1015             }
1016             # bin_PROGRAMS is complicated, as it exists twice, so we do a little
1017             # magic trick here
1018             $lookup = 'PROGRAMS\s*=[ \t]*(.*)';
1019             if ($MakefileData =~ /\n$lookup/) {
1020                 substituteLine($lookup, "bin_PROGRAMS += $progexes\nPROGRAMS = $1");
1021             }
1022         }
1023     }
1024 }
1025
1026 #-----------------------------------------------------------------------------
1027
1028 sub tag_COMPILE_FIRST()
1029 {
1030   foreach $program (@programs) {
1031     my $lookup = "$program" . '_COMPILE_FIRST\s*=[ \t]*(.*)';
1032     if ($MakefileData =~ m/\n$lookup\n/) {
1033       my $compilefirst_str = $1;
1034       my @compilefirst = split(/[\034\s]+/, $compilefirst_str);
1035       my @progsources = split(/[\034\s]+/, $sources{$program});
1036       my %donesources = ();
1037       foreach $source (@progsources) {
1038         my @deps  = ();
1039         my $sdeps = "";
1040         if (-f $source) {
1041           $sdeps = "\$(srcdir)/$source";
1042         } else {
1043           $sdeps = "$source";
1044         }
1045         foreach $depend (@compilefirst) {
1046           next if ($source eq $depend);
1047           # avoid cyclic dependencies
1048           next if defined($donesources{$depend});
1049           push @deps, $depend;
1050         }
1051         $target_adds{$sdeps} .= join(' ', @deps) . ' ' if (@deps);
1052         $donesources{$source} = 1;
1053       }
1054     }
1055   }
1056 }
1057
1058 #-----------------------------------------------------------------------------
1059
1060
1061 # Organises the list of headers that we'll use to produce moc files
1062 # from.
1063 sub tag_METASOURCES ()
1064 {
1065     local @newObs           = ();  # here we add to create object files
1066     local @depend           = ();  # here we add to create moc files
1067     local $mocExt           = ".moc";
1068     local %mocFiles         = ();
1069
1070     my $line = "";
1071     my $postEqual = "";
1072
1073     my $lookup;
1074     my $found = "";
1075     if ($metasourceTags > 1) {
1076         $lookup = $program . '_METASOURCES\s*=\s*(.*)';
1077         return 1    if ($MakefileData !~ /\n($lookup)\n/);
1078         $found = $1;
1079     } else {
1080         $lookup = $program . '_METASOURCES\s*=\s*(.*)';
1081         if ($MakefileData !~ /\n($lookup)\n/) {
1082             $lookup = 'METASOURCES\s*=\s*(.*)';
1083             return 1    if ($MakefileData !~ /\n($lookup)\n/);
1084             $found = $1;
1085             $metasourceTags = 0; # we can use the general target only once
1086         } else {
1087             $found = $1;
1088         }
1089     }
1090     print STDOUT "METASOURCE processing <$found>)\n"      if ($verbose);
1091     
1092     $postEqual = $found;
1093     $postEqual =~ s/[^=]*=//;
1094     
1095     removeLine ($lookup, $found);
1096     
1097     # Always find the header files that could be used to "moc"
1098     return 1    if (findMocCandidates ());
1099     
1100     if ($postEqual =~ /AUTO\s*(\S*)|USE_AUTOMOC\s*(\S*)/)
1101     {
1102         print STDERR "$printname: the argument for AUTO|USE_AUTOMOC is obsolete" if ($+);
1103         $mocExt = ".moc.$cxxsuffix";
1104         $haveAutomocTag = 1;
1105     }
1106     else
1107     {
1108         # Not automoc so read the list of files supplied which
1109         # should be .moc files.
1110
1111         $postEqual =~ tr/\034/ /;
1112
1113         # prune out extra headers - This also checks to make sure that
1114         # the list is valid.
1115         pruneMocCandidates ($postEqual);
1116     }
1117
1118     checkMocCandidates ();
1119     
1120     if (@newObs) {
1121         my $ext =  ($program =~ /_la$/) ? ".moc.lo " : ".moc.o ";
1122         $realObjs{$program} .= "\034" . join ($ext, @newObs) . $ext;
1123         $dependmocs{$program} = join (".moc.$cxxsuffix " , @newObs) . ".moc.$cxxsuffix";
1124         foreach $file (@newObs) {
1125             $dep_files .= " \$(DEPDIR)/$file.moc.P" if($dep_files !~/$file.moc.P/);
1126         }
1127     }
1128     if (@depend) {
1129         $dependmocs{$program} .= " ";
1130         $dependmocs{$program} .= join('.moc ', @depend) . ".moc";
1131         $dependmocs{$program} .= " ";
1132     }
1133     addMocRules ();
1134     @globalmocs{keys %mocFiles}=values %mocFiles;
1135 }
1136
1137 #-----------------------------------------------------------------------------
1138
1139 # Returns 0 if the line was processed - 1 otherwise.
1140 # Errors are logged in the global $errorflags
1141 sub tag_AUTOMAKE ()
1142 {
1143     my $lookup = '.*cd \$\(top_srcdir\)\s+&&[\034\s]+\$\(AUTOMAKE\)(.*)';
1144     return 1    if ($MakefileData !~ /\n($lookup)\n/);
1145     print STDOUT "AUTOMAKE processing <$1>\n"        if ($verbose);
1146
1147     my $newLine = $1."\n\tcd \$(top_srcdir) && perl $thisProg $printname";
1148
1149     # automake 1.8.x adds another automake call. *sigh*
1150     $newLine =~ s/;([\034\s]+cd\s+\$\(srcdir\)\s+&&[\034\s]+\$\(AUTOMAKE\).*)[\034\s]+\&\&[\034\s]+exit[\034\s]+0;([\034\s]+exit\s+1)/; \034 ( $1 ) || exit 1; echo \' cd \$(top_srcdir) && perl $thisProg \'; cd \$(top_srcdir) && perl $thisProg && exit 0; $2/;
1151     substituteLine ($lookup, $newLine);
1152     $automkCall = $1;
1153
1154     $lookup = '.*cd \$\(srcdir\)\s+&&[\034\s]+\$\(AUTOCONF\)(.*)';
1155     if ($MakefileData =~ /\n($lookup)\n/) {
1156       $newLine  = "\tcd \$(srcdir) && rm -f configure\n";
1157       $newLine .= "\tcd \$(top_srcdir) && \$(MAKE) -f admin/Makefile.common configure";
1158       substituteLine ($lookup, $newLine);
1159     }
1160
1161     return 0;
1162 }
1163
1164 #-----------------------------------------------------------------------------
1165
1166 sub handle_TOPLEVEL()
1167 {
1168     my $pofiles = "";
1169     my @restfiles = ();
1170     opendir (THISDIR, ".");
1171     foreach $entry (readdir(THISDIR)) {
1172         next if (-d $entry);
1173         
1174         next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/ || $entry =~ /.gmo$/);
1175                  
1176         if ($entry =~ /\.po$/) {
1177              next;
1178         }
1179         push(@restfiles, $entry);
1180     }
1181     closedir (THISDIR);
1182             
1183     if (@restfiles) {
1184         $target_adds{"install-data-am"} .= "install-nls-files ";
1185         $lines = "install-nls-files:\n";
1186         $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$kdelang\n";
1187         for $file (@restfiles) {
1188             $lines .= "\t\$(INSTALL_DATA) \$\(srcdir\)/$file \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n";
1189         }
1190         $target_adds{"uninstall"} .= "uninstall-nls-files ";
1191         $lines .= "uninstall-nls-files:\n";
1192         for $file (@restfiles) {
1193             $lines .= "\t-rm -f \$(DESTDIR)\$(kde_locale)/$kdelang/$file\n";
1194         }
1195         appendLines($lines);
1196     }
1197     
1198     return 0;
1199 }
1200
1201 #-----------------------------------------------------------------------------
1202
1203 sub tag_SUBDIRS ()
1204 {
1205   if ($MakefileData !~ /\nSUBDIRS\s*=\s*\$\(AUTODIRS\)\s*\n/) {
1206     return 1;
1207   }
1208
1209   my $subdirs = ".";
1210
1211   opendir (THISDIR, ".");
1212   foreach $entry (readdir(THISDIR)) {
1213     next if ($entry eq "CVS" || $entry =~ /^\./);
1214     if (-d $entry && -f $entry . "/Makefile.am") {
1215       $subdirs .= " $entry";
1216       next;
1217     }
1218   }
1219   closedir (THISDIR);
1220
1221   substituteLine('SUBDIRS\s*=.*', "SUBDIRS =$subdirs");
1222   return 0;
1223 }
1224
1225 sub tag_IDLFILES ()
1226 {
1227     my @psources = split(/[\034\s]+/, $sources{$program});
1228     my $dep_lines = "";
1229     my @cppFiles = ();
1230     
1231     foreach $source (@psources) {
1232         my $skel = ($source =~ m/\.skel$/);
1233         my $stub = ($source =~ m/\.stub$/);
1234         my $signals = ($source =~ m/\.signals$/); # obsolete, remove in KDE-4
1235         
1236         if ($stub || $skel || $signals) {
1237
1238             my $qs = quotemeta($source);
1239             $sources{$program} =~ s/$qs//;
1240             $sources_changed{$program} = 1;
1241
1242             $source =~ s/\.(stub|skel|signals)$//;
1243             my $sourcename;
1244
1245             if ($skel) {
1246                 $sourcename = "$source\_skel";
1247             } elsif ($stub) {
1248                 $sourcename = "$source\_stub";
1249             } else {
1250                 $sourcename = "$source\_signals";
1251             }
1252             
1253             my $sourcedir = '';
1254             if (-f "$makefileDir/$source.h") {
1255                 $sourcedir = '$(srcdir)/';
1256             } else {
1257                 if ($MakefileData =~ /\n$source\_DIR\s*=\s*(\S+)\n/) {
1258                     $sourcedir = $1;
1259                     $sourcedir .= "/" if ($sourcedir !~ /\/$/);
1260                 }
1261             }
1262             
1263             if ($allidls !~ /$source\_kidl/) {
1264                 
1265                 $use_ng = ($MakefileData =~ /\n$source\_DCOPIDLNG\s*=\s*(\S+)\n/);
1266                 $dcopidl =  $use_ng ? "KDECONFIG=\"\$(KDECONFIG)\" \$(DCOPIDLNG)" : "\$(DCOPIDL)";
1267
1268                 $dep_lines .= "$source.kidl: $sourcedir$source.h \$(DCOP_DEPENDENCIES)\n";
1269                 $dep_lines .= "\t$dcopidl $sourcedir$source.h > $source.kidl || ( rm -f $source.kidl ; false )\n";
1270                 
1271                 $allidls .= $source . "_kidl ";
1272             }
1273             
1274             if ($allidls !~ /$sourcename/) {
1275                 
1276                 $dep_lines_tmp = "";
1277
1278                 if ($skel) {
1279                     $dep_lines .= "$sourcename.$cxxsuffix: $source.kidl\n";
1280                     $dep_lines .= "\t\$(DCOPIDL2CPP) --c++-suffix $cxxsuffix --no-signals --no-stub $source.kidl\n";
1281                 } elsif ($stub) {
1282                     $dep_lines_tmp = "\t\$(DCOPIDL2CPP) --c++-suffix $cxxsuffix --no-signals --no-skel $source.kidl\n";
1283                 } else { # signals - obsolete, remove in KDE 4
1284                     $dep_lines_tmp = "\t\$(DCOPIDL2CPP) --c++-suffix $cxxsuffix --no-stub --no-skel $source.kidl\n";
1285                 }
1286
1287                 if ($stub || $signals) {
1288                     $target_adds{"$sourcename.$cxxsuffix"} .= "$sourcename.h ";
1289                     $dep_lines .= "$sourcename.h: $source.kidl\n";
1290                     $dep_lines .= $dep_lines_tmp;
1291                 }
1292                 
1293                 $allidls .= $sourcename . " ";
1294             }
1295             
1296             $idlfiles{$program} .= $sourcename . " ";
1297             
1298             if ($program =~ /_la$/) {
1299                 $realObjs{$program} .= " $sourcename.lo";
1300             } else {
1301                 $realObjs{$program} .= " $sourcename.\$(OBJEXT)";
1302             }
1303             $sources{$program} .= " $sourcename.$cxxsuffix";
1304             $sources_changed{$program} = 1;
1305             $important{$program} .= "$sourcename.h " if (!$skel);
1306             $idl_output .= "\\\n\t$sourcename.$cxxsuffix $sourcename.h $source.kidl ";
1307             push(@cleanfiles, "$sourcename.$cxxsuffix");
1308             push(@cleanfiles, "$sourcename.h");
1309             push(@cleanfiles, "$sourcename.kidl");
1310             $dep_files .= " \$(DEPDIR)/$sourcename.P" if ($dep_files !~/$sourcename.P/);
1311         }
1312     }
1313     if ($dep_lines) {
1314         appendLines($dep_lines);
1315     }
1316     
1317     if (0) {
1318         my $lookup = "($program)";
1319         $lookup .= '(|\$\(EXEEXT\))';
1320         $lookup =~ s/\_/./g;
1321         $lookup .= ":(.*..$program\_OBJECTS..*)";
1322         #    $lookup = quotemeta($lookup);
1323         if ($MakefileData =~ /\n$lookup\n/) {
1324             
1325             my $line = "$1$2: ";
1326             foreach $file (split(' ', $idlfiles{$program})) {
1327                 $line .= "$file.$cxxsuffix ";
1328             }
1329             $line .= $3;
1330             substituteLine($lookup, $line);
1331         } else {
1332             print STDERR "no built dependency found $lookup\n";
1333         }
1334     }
1335 }
1336
1337 sub tag_UIFILES ()
1338 {
1339     my @psources = split(/[\034\s]+/, $sources{$program});
1340     my @depFiles = ();
1341     
1342     foreach $source (@psources) {
1343
1344         if ($source =~ m/\.ui$/) {
1345
1346             print STDERR "adding UI file $source\n" if ($verbose);
1347
1348             my $qs = quotemeta($source);
1349             $sources{$program} =~ s/$qs//;
1350             $sources_changed{$program} = 1;
1351       
1352             $source =~ s/\.ui$//;
1353
1354             my $sourcedir = '';
1355             if (-f "$makefileDir/$source.ui") {
1356                 $sourcedir = '$(srcdir)/';
1357             }
1358
1359             if (!$uiFiles{$source}) {
1360
1361                 my $dep_lines = "$source.$cxxsuffix: $sourcedir$source.ui $source.h $source.moc\n";
1362                 $dep_lines .= "\trm -f $source.$cxxsuffix\n";
1363                 if (!$kdeopts{"qtonly"}) {
1364                     $dep_lines .= "\techo '#include <kdialog.h>' > $source.$cxxsuffix\n";
1365                     $dep_lines .= "\techo '#include <klocale.h>' >> $source.$cxxsuffix\n";
1366                     my ($mangled_source) = $source;
1367                     $mangled_source =~ s/[^A-Za-z0-9]/_/g;  # get rid of garbage
1368                     $dep_lines .= "\t\$(UIC) -tr \${UIC_TR} -i $source.h $sourcedir$source.ui > $source.$cxxsuffix.temp ; ret=\$\$?; \\\n";
1369                     $dep_lines .= "\t\$(PERL) -pe \"s,\${UIC_TR}( \\\"\\\" ),QString::null,g\" $source.$cxxsuffix.temp | \$(PERL) -pe \"s,\${UIC_TR}( \\\"\\\"\\, \\\"\\\" ),QString::null,g\" | \$(PERL) -pe \"s,image([0-9][0-9]*)_data,img\\\$\$1_" . $mangled_source . ",g\" | \$(PERL) -pe \"s,: QWizard\\(,: KWizard(,g\" >> $source.$cxxsuffix ;\\\n";
1370                     $dep_lines .= "\trm -f $source.$cxxsuffix.temp ;\\\n";
1371                 } else {
1372                     $dep_lines .= "\t\$(UIC) -i $source.h $sourcedir$source.ui > $source.$cxxsuffix; ret=\$\$?; \\\n";
1373                 }
1374                 $dep_lines .= "\tif test \"\$\$ret\" = 0; then echo '#include \"$source.moc\"' >> $source.$cxxsuffix; else rm -f $source.$cxxsuffix ; exit \$\$ret ; fi\n\n";
1375                 $dep_lines .= "$source.h: $sourcedir$source.ui\n";
1376                 $dep_lines .= "\trm -rf $source.h;\n";
1377                 if (!$kdeopts{"qtonly"}) {
1378                     $dep_lines .= "\t\$(UIC) $sourcedir$source.ui | \$(PERL) -pi -e \"s,public QWizard,public KWizard,g; s,#include <qwizard.h>,#include <kwizard.h>,g\" >> $source.h ;\n";
1379                 } else {
1380                     $dep_lines .= "\t\$(UIC) -o $source.h $sourcedir$source.ui\n";
1381                 }
1382                 $dep_lines .= "$source.moc: $source.h\n";
1383                 $dep_lines .= "\t\$(MOC) $source.h -o $source.moc\n";
1384
1385                 $rule_adds{"$source.$cxxsuffix"} = $dep_lines;
1386
1387                 $uiFiles{$source} = 1;
1388                 $dependmocs{$program} .= " $source.moc";
1389                 $globalmocs{$source} = "\035$source.h\035$source.cpp";
1390             }
1391             
1392             if ($program =~ /_la$/) {
1393                 $realObjs{$program} .= " $source.lo";
1394             } else {
1395                 $realObjs{$program} .= " $source.\$(OBJEXT)";
1396             }
1397             $sources{$program} .= " $source.$cxxsuffix";
1398             $sources_changed{$program} = 1;
1399             $important{$program} .= "$source.h ";
1400             $ui_output .= "\\\n\t$source.$cxxsuffix $source.h $source.moc ";
1401             push(@cleanfiles, "$source.$cxxsuffix");
1402             push(@cleanfiles, "$source.h");
1403             push(@cleanfiles, "$source.moc");
1404             $dep_files .= " \$(DEPDIR)/$source.P" if($dep_files !~/$source.P/ );
1405         }
1406     }
1407 }
1408
1409 sub tag_KCFGFILES ()
1410 {
1411     my @psources = split(/[\034\s]+/, $sources{$program});
1412     my @depFiles = ();
1413     
1414     foreach $source (@psources) {
1415
1416         if ($source =~ m/\.kcfgc$/) {
1417
1418             print STDERR "adding KCFG file $source\n" if ($verbose);
1419
1420             my $qs = quotemeta($source);
1421             $sources{$program} =~ s/$qs//;
1422             $sources_changed{$program} = 1;
1423       
1424             $source =~ s/\.kcfgc$//;
1425
1426             my $sourcedir = '';
1427             if (-f "$makefileDir/$source.kcfgc") {
1428                 $sourcedir = '$(srcdir)/';
1429             }
1430
1431             if (!$kcfgFiles{$source}) {
1432                 $kcfg = "$program.kcfg";
1433                 findKcfgFile("$source.kcfgc");
1434
1435                 my $fixsuffix = "";
1436                 $fixsuffix = "else mv $source.cpp $source.$cxxsuffix ; " 
1437                     unless "cpp" eq $cxxsuffix;
1438
1439                 my $dep_lines = "$source.$cxxsuffix: $source.h\n";
1440                 $dep_lines .= "$source.h: $sourcedir$kcfg $sourcedir$source.kcfgc \$(KCFG_DEPENDENCIES)\n";
1441                 $dep_lines .= "\t\$(KCONFIG_COMPILER) $sourcedir$kcfg $sourcedir$source.kcfgc; ret=\$\$?; \\\n";
1442                 $dep_lines .= "\tif test \"\$\$ret\" != 0; then rm -f $source.h ; exit \$\$ret ; $fixsuffix fi\n\n";
1443
1444                 $rule_adds{"$source.$cxxsuffix"} = $dep_lines;
1445
1446                 $kcfgFiles{$source} = 1;
1447             }
1448             
1449             if ($program =~ /_la$/) {
1450                 $realObjs{$program} .= " $source.lo";
1451             } else {
1452                 $realObjs{$program} .= " $source.\$(OBJEXT)";
1453             }
1454             $sources{$program} .= " $source.$cxxsuffix";
1455             $sources_changed{$program} = 1;
1456             $important{$program} .= "$source.h ";
1457             $kcfg_output .= "\\\n\t$source.$cxxsuffix $source.h ";
1458             push(@cleanfiles, "$source.$cxxsuffix");
1459             push(@cleanfiles, "$source.h");
1460             $dep_files .= " \$(DEPDIR)/$source.P" if($dep_files !~/$source.P/ );
1461         }
1462     }
1463 }
1464
1465 sub tag_ICON()
1466 {
1467     my $lookup = '([^\s]*)_ICON\s*=[ \t]*(.*)';
1468     my $install = "";
1469     my $uninstall = "";
1470
1471     while ($MakefileData =~ /\n$lookup/g) {
1472         my $destdir;
1473         if ($1 eq "KDE") {
1474             $destdir = "kde_icondir";
1475         } else {
1476             $destdir = $1 . "dir";
1477         }
1478         my $iconauto = ($2 =~ /AUTO\s*$/);
1479         my @appnames = ();
1480         if ( ! $iconauto ) {
1481             my $appicon_str = $2;
1482             my @_appnames = split(" ", $appicon_str);
1483             print STDOUT "KDE_ICON processing <@_appnames>\n"   if ($verbose);
1484             foreach $appname (@_appnames) {
1485                 push(@appnames, quotemeta($appname));
1486             }
1487         } else {
1488             print STDOUT "KDE_ICON processing <AUTO>\n"   if ($verbose);
1489         }
1490
1491         my @files = ();
1492         opendir (THISDIR, ".");
1493         foreach $entry (readdir(THISDIR)) {
1494             next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/);
1495             next if (! -f $entry);
1496             if ( $iconauto )
1497               {
1498                   push(@files, $entry)
1499                     if ($entry =~ /\.xpm/ || $entry =~ /\.png/ || $entry =~ /\.mng/ || $entry =~ /\.svg/);
1500               } else {
1501                   foreach $appname (@appnames) {
1502                       push(@files, $entry)
1503                         if ($entry =~ /-$appname\.xpm/ || $entry =~ /-$appname\.png/ || $entry =~ /-$appname\.mng/ || $entry =~ /-$appname\.svg/);
1504                   }
1505               }
1506         }
1507         closedir (THISDIR);
1508         
1509         my %directories = ();
1510         
1511         foreach $file (@files) {
1512             my $newfile = $file;
1513             my $prefix = $file;
1514             $prefix =~ s/\.(png|xpm|mng|svg|svgz)$//;
1515             my $appname = $prefix;
1516             $appname =~ s/^[^-]+-// if ($appname =~ /-/) ;
1517             $appname =~ s/^[^-]+-// if ($appname =~ /-/) ;
1518             $appname = quotemeta($appname);
1519             $prefix =~ s/$appname$//;
1520             $prefix =~ s/-$//;
1521             
1522             $prefix = 'lo16-app' if ($prefix eq 'mini');
1523             $prefix = 'lo32-app' if ($prefix eq 'lo');
1524             $prefix = 'hi48-app' if ($prefix eq 'large');
1525             $prefix .= '-app' if ($prefix =~ m/^...$/);
1526             
1527             my $type = $prefix;
1528             $type =~ s/^.*-([^-]+)$/$1/;
1529             $prefix =~ s/^(.*)-[^-]+$/$1/;
1530             
1531             my %type_hash =
1532               (
1533                'action' => 'actions',
1534                'app' => 'apps',
1535                'device' => 'devices',
1536                'filesys' => 'filesystems',
1537                'mime' => 'mimetypes'
1538               );
1539
1540             if (! defined $type_hash{$type} ) {
1541                 print STDERR "unknown icon type $type in $printname ($file)\n";
1542                 next;
1543             }
1544
1545             my %dir_hash =
1546               (
1547                'los' => 'locolor/16x16',
1548                'lom' => 'locolor/32x32',
1549                'him' => 'hicolor/32x32',
1550                'hil' => 'hicolor/48x48',
1551                'lo16' => 'locolor/16x16',
1552                'lo22' => 'locolor/22x22',
1553                'lo32' => 'locolor/32x32',
1554                'hi16' => 'hicolor/16x16',
1555                'hi22' => 'hicolor/22x22',
1556                'hi32' => 'hicolor/32x32',
1557                'hi48' => 'hicolor/48x48',
1558                'hi64' => 'hicolor/64x64',
1559                'hi128' => 'hicolor/128x128',
1560                'hisc' => 'hicolor/scalable',
1561                'cr16' => 'crystalsvg/16x16',
1562                'cr22' => 'crystalsvg/22x22',
1563                'cr32' => 'crystalsvg/32x32',
1564                'cr48' => 'crystalsvg/48x48',
1565                'cr64' => 'crystalsvg/64x64',
1566                'cr128' => 'crystalsvg/128x128',
1567                'crsc' => 'crystalsvg/scalable'
1568               );
1569             
1570             $newfile =~ s@.*-($appname\.(png|xpm|mng|svgz|svg?))@$1@;
1571             
1572             if (! defined $dir_hash{$prefix}) {
1573                 print STDERR "unknown icon prefix $prefix in $printname\n";
1574                 next;
1575             }
1576             
1577             my $dir = $dir_hash{$prefix} . "/" . $type_hash{$type};
1578             if ($newfile =~ /-[^\.]/) {
1579                 my $tmp = $newfile;
1580                 $tmp =~ s/^([^-]+)-.*$/$1/;
1581                 $dir = $dir . "/" . $tmp;
1582                 $newfile =~ s/^[^-]+-//;
1583             }
1584             
1585             if (!defined $directories{$dir}) {
1586                 $install .= "\t\$(mkinstalldirs) \$(DESTDIR)\$($destdir)/$dir\n";
1587                 $directories{$dir} = 1;
1588             }
1589             
1590             $install .= "\t\$(INSTALL_DATA) \$(srcdir)/$file \$(DESTDIR)\$($destdir)/$dir/$newfile\n";
1591             $uninstall .= "\t-rm -f \$(DESTDIR)\$($destdir)/$dir/$newfile\n";
1592             
1593         }
1594     }
1595
1596     if (length($install)) {
1597         $target_adds{"install-data-am"} .= "install-kde-icons ";
1598         $target_adds{"uninstall-am"} .= "uninstall-kde-icons ";
1599         appendLines("install-kde-icons:\n" . $install . "\nuninstall-kde-icons:\n" . $uninstall);
1600     }
1601 }
1602
1603 sub handle_POFILES($$)
1604 {
1605   my @pofiles = split(" ", $_[0]);
1606   my $lang = $_[1];
1607
1608   # Build rules for creating the gmo files
1609   my $tmp = "";
1610   my $allgmofiles     = "";
1611   my $pofileLine   = "POFILES =";
1612   foreach $pofile (@pofiles)
1613     {
1614         $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1615         $tmp .= "$1.gmo: $pofile\n";
1616         $tmp .= "\trm -f $1.gmo; \$(GMSGFMT) -o $1.gmo \$(srcdir)/$pofile\n";
1617         $tmp .= "\ttest ! -f $1.gmo || touch $1.gmo\n";
1618         $allgmofiles .= " $1.gmo";
1619         $pofileLine  .= " $1.po";
1620     }
1621   appendLines ($tmp);
1622   my $lookup = 'POFILES\s*=([^\n]*)';
1623   if ($MakefileData !~ /\n$lookup/) {
1624     appendLines("$pofileLine\nGMOFILES =$allgmofiles");
1625   } else {
1626     substituteLine ($lookup, "$pofileLine\nGMOFILES =$allgmofiles");
1627   }
1628
1629     if ($allgmofiles) {
1630
1631         # Add the "clean" rule so that the maintainer-clean does something
1632         appendLines ("clean-nls:\n\t-rm -f $allgmofiles\n");
1633
1634         $target_adds{"maintainer-clean"} .= "clean-nls ";
1635
1636         $lookup = 'DISTFILES\s*=[ \t]*(.*)';
1637         if ($MakefileData =~ /\n$lookup/) {
1638           $tmp = "DISTFILES = \$(GMOFILES) \$(POFILES) $1";
1639           substituteLine ($lookup, $tmp);
1640         }
1641     }
1642
1643   $target_adds{"install-data-am"} .= "install-nls ";
1644
1645   $tmp = "install-nls:\n";
1646   if ($lang) {
1647     $tmp  .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES\n";
1648   }
1649   $tmp .= "\t\@for base in ";
1650   foreach $pofile (@pofiles)
1651     {
1652       $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1653       $tmp .= "$1 ";
1654     }
1655
1656   $tmp .= "; do \\\n";
1657   if ($lang) {
1658     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n";
1659     $tmp .= "\t  if test -f \$\$base.gmo; then \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n";
1660     $tmp .= "\t  elif test -f \$(srcdir)/\$\$base.gmo; then \$(INSTALL_DATA) \$(srcdir)/\$\$base.gmo \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/\$\$base.mo ;\\\n";
1661     $tmp .= "\t  fi ;\\\n";
1662   } else {
1663     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n";
1664     $tmp .= "\t  \$(mkinstalldirs) \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES ; \\\n";
1665     $tmp .= "\t  if test -f \$\$base.gmo; then \$(INSTALL_DATA) \$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n";
1666     $tmp .= "\t  elif test -f \$(srcdir)/\$\$base.gmo; then \$(INSTALL_DATA) \$(srcdir)/\$\$base.gmo \$(DESTDIR)\$(kde_locale)/\$\$base/LC_MESSAGES/\$(PACKAGE).mo ;\\\n";
1667     $tmp .= "\t  fi ;\\\n";
1668   }
1669   $tmp .= "\tdone\n\n";
1670   appendLines ($tmp);
1671
1672   $target_adds{"uninstall"} .= "uninstall-nls ";
1673
1674   $tmp = "uninstall-nls:\n";
1675   foreach $pofile (@pofiles)
1676     {
1677       $pofile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
1678       if ($lang) {
1679         $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$lang/LC_MESSAGES/$1.mo\n";
1680       } else {
1681         $tmp .= "\trm -f \$(DESTDIR)\$(kde_locale)/$1/LC_MESSAGES/\$(PACKAGE).mo\n";
1682       }
1683     }
1684   appendLines($tmp);
1685
1686   $target_adds{"all"} .= "all-nls ";
1687
1688   $tmp = "all-nls: \$(GMOFILES)\n";
1689
1690   appendLines($tmp);
1691
1692   $target_adds{"distdir"} .= "distdir-nls ";
1693
1694   $tmp = "distdir-nls:\$(GMOFILES)\n";
1695   $tmp .= "\tfor file in \$(POFILES); do \\\n";
1696   $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
1697   $tmp .= "\tdone\n";
1698   $tmp .= "\tfor file in \$(GMOFILES); do \\\n";
1699   $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
1700   $tmp .= "\tdone\n";
1701
1702   appendLines ($tmp);
1703
1704   if (!$lang) {
1705     appendLines("merge:\n\t\$(MAKE) -f \$(top_srcdir)/admin/Makefile.common package-merge POFILES=\"\${POFILES}\" PACKAGE=\${PACKAGE}\n\n");
1706   }
1707  
1708 }
1709
1710 #-----------------------------------------------------------------------------
1711
1712 # Returns 0 if the line was processed - 1 otherwise.
1713 # Errors are logged in the global $errorflags
1714 sub tag_POFILES ()
1715 {
1716     my $lookup = 'POFILES\s*=([^\n]*)';
1717     return 1    if ($MakefileData !~ /\n$lookup/);
1718     print STDOUT "POFILES processing <$1>\n"   if ($verbose);
1719
1720     my $tmp = $1;
1721
1722     # make sure these are all gone.
1723     if ($MakefileData =~ /\n\.po\.gmo:\n/)
1724     {
1725         print STDERR "Warning: Found old .po.gmo rules in $printname. New po rules not added\n";
1726         return 1;
1727     }
1728
1729     # Either find the pofiles in the directory (AUTO) or use
1730     # only the specified po files.
1731     my $pofiles = "";
1732     if ($tmp =~ /^\s*AUTO\s*$/)
1733     {
1734         opendir (THISDIR, ".");
1735         $pofiles =  join(" ", grep(/\.po$/, readdir(THISDIR)));
1736         closedir (THISDIR);
1737         print STDOUT "pofiles found = $pofiles\n"   if ($verbose);
1738         if (-f "charset" && -f "kdelibs/kdelibs.po") {
1739             handle_TOPLEVEL();
1740         }
1741     }
1742     else
1743     {
1744         $tmp =~ s/\034/ /g;
1745         $pofiles = $tmp;
1746     }
1747     return 1    if (!$pofiles);        # Nothing to do
1748
1749     handle_POFILES($pofiles, $kdelang);
1750
1751     return 0;
1752 }
1753
1754 sub helper_LOCALINSTALL($)
1755 {
1756   my $lookup = "\035" . $_[0] . " *:[^\035]*\035\t";
1757   my $copy = $MakefileData;
1758   $copy =~ s/\n/\035/g;
1759   if ($copy =~ /($lookup.*)$/) {
1760
1761     $install = $1;
1762     $install =~ s/\035$_[0] *:[^\035]*\035//;
1763     my $emptyline = 0;
1764     while (! $emptyline ) {
1765       if ($install =~ /([^\035]*)\035(.*)/) {
1766         local $line = $1;
1767         $install = $2;
1768         if ($line !~ /^\s*$/ && $line !~ /^(\@.*\@)*\t/) {
1769           $emptyline = 1;
1770         } else {
1771           replaceDestDir($line);
1772         }
1773       } else {
1774         $emptyline = 1;
1775       }
1776     }
1777   }
1778
1779 }
1780
1781 sub tag_LOCALINSTALL ()
1782 {
1783   helper_LOCALINSTALL('install-exec-local');
1784   helper_LOCALINSTALL('install-data-local');
1785   helper_LOCALINSTALL('uninstall-local');
1786
1787   return 0;
1788 }
1789
1790 sub replaceDestDir($) {
1791   local $line = $_[0];
1792
1793   if (   $line =~ /^\s*(\@.*\@)*\s*\$\(mkinstalldirs\)/
1794       || $line =~ /^\s*(\@.*\@)*\s*\$\(INSTALL\S*\)/
1795       || $line =~ /^\s*(\@.*\@)*\s*(-?rm.*) \S*$/)
1796   {
1797     $line =~ s/^(.*) ([^\s]+)\s*$/$1 \$(DESTDIR)$2/ if ($line !~ /\$\(DESTDIR\)/);
1798   }
1799
1800   if ($line ne $_[0]) {
1801     $_[0] = quotemeta $_[0];
1802     substituteLine($_[0], $line);
1803   }
1804 }
1805
1806 #---------------------------------------------------------------------------
1807 # libtool is very hard to persuade it could use -Wl,--no-undefined for making
1808 # -no-undefined actually work
1809 # append $(KDE_NO_UNFINED) after every -no-undefined in LDFLAGS
1810 # this may go away if libtool ever does this on its own
1811 sub tag_NO_UNDEFINED () {
1812     return if ($program !~ /_la$/);
1813
1814     my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n";
1815     $MakefileData =~ m/$lookup/;
1816     return if (!defined($1));
1817     return if ($1 !~ /CXXLINK/);
1818
1819     if ($MakefileData !~ /\n$program\_LDFLAGS\s*=.*-no-undefined/ ) {
1820         return;
1821     }
1822
1823     $lookup = $program . '\_LDFLAGS(\s*)=(.*)-no-undefined(.*)';
1824     if ($MakefileData =~ /\n$lookup\n/) {
1825         my $replace = $program . "\_LDFLAGS$1=$2-no-undefined \$(KDE_NO_UNDEFINED)$3";
1826         substituteLine($lookup, $replace);
1827     }
1828 }
1829
1830 sub tag_CLOSURE () {
1831     return if ($program !~ /_la$/);
1832
1833     my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n";
1834     $MakefileData =~ m/$lookup/;
1835     return if (!defined($1));
1836     return if ($1 !~ /CXXLINK/);
1837
1838     if ($MakefileData !~ /\n$program\_LDFLAGS\s*=.*-no-undefined/ &&
1839         $MakefileData !~ /\n$program\_LDFLAGS\s*=.*KDE_PLUGIN/ ) {
1840         print STDERR "Report: $program contains undefined in $printname\n" if ($program =~ /^lib/ && $dryrun);
1841         return;
1842     }
1843
1844     my $closure = $realname{$program} . ".closure";
1845     my $lines = "$closure: \$($program\_OBJECTS) \$($program\_DEPENDENCIES)\n";
1846     $lines .= "\t\@echo \"int main() {return 0;}\" > $program\_closure.$cxxsuffix\n";
1847     $lines .= "\t\@\$\(LTCXXCOMPILE\) -c $program\_closure.$cxxsuffix\n";
1848     $lines .= "\t\$\(CXXLINK\) $program\_closure.lo \$($program\_LDFLAGS) \$($program\_OBJECTS) \$($program\_LIBADD) \$(LIBS)\n";
1849     $lines .= "\t\@rm -f $program\_closure.* $closure\n";
1850     $lines .= "\t\@echo \"timestamp\" > $closure\n";
1851     $lines .= "\n";
1852     appendLines($lines);
1853     $lookup = $realname{$program} . ": (.*)";
1854     if ($MakefileData =~ /\n$lookup\n/) {
1855         $lines  = "\@KDE_USE_CLOSURE_TRUE@". $realname{$program} . ": $closure $1";
1856         $lines .= "\n\@KDE_USE_CLOSURE_FALSE@" . $realname{$program} . ": $1";
1857         substituteLine($lookup, $lines);
1858     }
1859     $closure_output .= " $closure";
1860 }
1861
1862 sub tag_NMCHECK () {
1863     return if ($program !~ /_la$/);
1864     my $lookup = quotemeta($realname{$program}) . ":.*?\n\t.*?\\((.*?)\\) .*\n";
1865     $MakefileData =~ m/$lookup/;
1866     my $linkcmd = $1;
1867     return if (!defined($1));
1868     return if ($linkcmd !~ /CXXLINK/ && $linkcmd !~ /LINK/);
1869
1870     $lookup = $program . '_NMCHECK\s*=([^\n]*)';
1871     if( $MakefileData !~ m/\n$lookup\n/ ) {
1872         return;
1873     }
1874     my $allowed = $1;
1875     $allowed =~ s/^ *//;
1876     $lookup = $program . '_NMCHECKWEAK\s*=([^\n]*)';
1877     my $weak = "";
1878     my $is_weak = 0;
1879     if( $MakefileData =~ m/\n$lookup\n/ ) {
1880         $weak = $1;
1881         $is_weak = 1;
1882     }
1883     $weak =~ s/^ *//;
1884
1885     if( $is_weak )
1886     {
1887         $weak = '--allowweak=\'' . $weak . '\' ';
1888     }
1889     my $nmline = "\@KDE_USE_NMCHECK_TRUE@\t\@\$(MAKE) \$(AM_MAKEFLAGS) nmcheck_$realname{$program} || ( rm -f $realname{$program}; exit 1 )";
1890     $lookup = '(\t\$\(CXXLINK\)[^\n]*' . $program . '_OBJECTS[^\n]*)';
1891     if( $MakefileData =~ /\n$lookup\n/ ) {
1892         my $oldstuff = $1;
1893         substituteLine( $lookup, $oldstuff . "\n" . $nmline );
1894     }
1895     $lookup = '(\t\$\(LINK\)[^\n]*' . $program . '_OBJECTS[^\n]*)';
1896     if( $MakefileData =~ /\n$lookup\n/ ) {
1897         my $oldstuff = $1;
1898         substituteLine( $lookup, $oldstuff . "\n" . $nmline );
1899     }
1900     $nmline = "\@\$(top_srcdir)/admin/nmcheck $realname{$program} \'$allowed\' $weak";
1901     appendLines( "\nnmcheck_$realname{$program}: $realname{$program} \n\t$nmline\n" );
1902     $target_adds{ "nmcheck" } .= "nmcheck_$realname{$program} ";
1903 }
1904
1905 sub tag_DIST () {
1906     my %foundfiles = ();
1907     opendir (THISDIR, ".");
1908     foreach $entry (readdir(THISDIR)) {
1909         next if ($entry eq "CVS" || $entry =~ /^\./  || $entry eq "Makefile" || $entry =~ /~$/ || $entry =~ /^\#.*\#$/);
1910         next if (! -f $entry);
1911         next if ($entry =~ /\.moc/ || $entry =~ /\.moc.$cppExt$/ || $entry =~ /\.lo$/ || $entry =~ /\.la$/ || $entry =~ /\.o/);
1912         next if ($entry =~ /\.all_$cppExt\.$cppExt$/);
1913         $foundfiles{$entry} = 1;
1914     }
1915     closedir (THISDIR);
1916
1917     # doing this for MAINTAINERCLEANFILES would be wrong
1918     my @marks = ("EXTRA_DIST", "DIST_COMMON", '\S*_SOURCES', '\S*_HEADERS', 'CLEANFILES', 'DISTCLEANFILES', '\S*_OBJECTS');
1919     foreach $mark (@marks) {
1920         while ($MakefileData =~ /\n($mark)\s*=[ \t]*([^\n]*)/g) {
1921             my $cleanfiles_str = $2;
1922             foreach $file (split('[\034\s]+', $cleanfiles_str)) {
1923                 $file =~ s/\.\///;
1924                 $foundfiles{$file} = 0 if (defined $foundfiles{$file});
1925             }
1926         }
1927     }
1928     my @files = ("Makefile", "config.cache", "config.log", "stamp-h",
1929                  "stamp-h1", "stamp-h1", "config.h", "Makefile", 
1930                  "config.status", "config.h", "libtool", "core" );
1931     foreach $file (@files) {
1932         $foundfiles{$file} = 0 if (defined $foundfiles{$file});
1933     }
1934
1935     my $KDE_DIST = "";
1936     foreach $file (keys %foundfiles) {
1937         if ($foundfiles{$file} == 1) {
1938             $KDE_DIST .= "$file ";
1939         }
1940     }
1941     if ($KDE_DIST) {
1942         print "KDE_DIST $printname $KDE_DIST\n" if ($verbose);
1943
1944         my $lookup = 'DISTFILES\s*=[ \t]*(.*)';
1945         if ($MakefileData =~ /\n$lookup/) {
1946             substituteLine($lookup, "DISTFILES = $1 \$(KDE_DIST)");
1947             appendLines("KDE_DIST=$KDE_DIST\n");
1948         }
1949     }
1950 }
1951
1952 #-----------------------------------------------------------------------------
1953 # Returns 0 if the line was processed - 1 otherwise.
1954 # Errors are logged in the global $errorflags
1955 sub tag_DOCFILES ()
1956 {
1957     $target_adds{"all"} .= "docs-am ";
1958
1959     my $lookup = 'KDE_DOCS\s*=[ \t]*([^\n]*)';
1960     goto nodocs    if ($MakefileData !~ /\n$lookup/);
1961     print STDOUT "KDE_DOCS processing <$1>\n"   if ($verbose);
1962
1963     my $tmp = $1;
1964
1965     # Either find the files in the directory (AUTO) or use
1966     # only the specified po files.
1967     my $files = "";
1968     my $appname = $tmp;
1969     $appname =~ s/^(\S*)\s*.*$/$1/;
1970     if ($appname =~ /AUTO/) {
1971       $appname = basename($makefileDir);
1972       if ("$appname" eq "en") {
1973           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";
1974           exit(1);
1975       }
1976     }
1977
1978     if ($tmp !~ / - /)
1979     {
1980         opendir (THISDIR, ".");
1981         foreach $entry (readdir(THISDIR)) {
1982           next if ($entry eq "CVS" || $entry =~ /^\./  || $entry =~ /^Makefile/ || $entry =~ /~$/ || $entry =~ /^\#.*\#$/ || $entry eq "core" || $entry eq "index.cache.bz2");
1983           next if (! -f $entry);
1984           $files .= "$entry ";
1985         }
1986         closedir (THISDIR);
1987         print STDOUT "docfiles found = $files\n"   if ($verbose);
1988     }
1989     else
1990     {
1991         $tmp =~ s/\034/ /g;
1992         $tmp =~ s/^\S*\s*-\s*//;
1993         $files = $tmp;
1994     }
1995     goto nodocs if (!$files);        # Nothing to do
1996
1997     if ($files =~ /(^| )index\.docbook($| )/) {
1998
1999       my $lines = "";
2000       my $lookup = 'MEINPROC\s*=';
2001       if ($MakefileData !~ /\n($lookup)/) {
2002         $lines = "MEINPROC=/\$(kde_bindir)/meinproc\n";
2003       }
2004       $lookup = 'KDE_XSL_STYLESHEET\s*=';
2005       if ($MakefileData !~ /\n($lookup)/) {
2006         $lines .= "KDE_XSL_STYLESHEET=/\$(kde_datadir)/ksgmltools2/customization/kde-chunk.xsl\n";
2007       }
2008       $lookup = '\nindex.cache.bz2:';
2009       if ($MakefileData !~ /\n($lookup)/) {
2010          $lines .= "index.cache.bz2: \$(srcdir)/index.docbook \$(KDE_XSL_STYLESHEET) $files\n";
2011          $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";
2012          $lines .= "\n";
2013       }
2014
2015       $lines .= "docs-am: index.cache.bz2\n";
2016       $lines .= "\n";
2017       $lines .= "install-docs: docs-am install-nls\n";
2018       $lines .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n";
2019       $lines .= "\t\@if test -f index.cache.bz2; then \\\n";
2020       $lines .= "\techo \$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
2021       $lines .= "\t\$(INSTALL_DATA) index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
2022       $lines .= "\telif test -f  \$(srcdir)/index.cache.bz2; then \\\n";
2023       $lines .= "\techo \$(INSTALL_DATA) \$(srcdir)/index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
2024       $lines .= "\t\$(INSTALL_DATA) \$(srcdir)/index.cache.bz2 \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/; \\\n";
2025       $lines .= "\tfi\n";
2026       $lines .= "\t-rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n";
2027       $lines .= "\t\$(LN_S) \$(kde_libs_htmldir)/$kdelang/common \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/common\n";
2028
2029       $lines .= "\n";
2030       $lines .= "uninstall-docs:\n";
2031       $lines .= "\t-rm -rf \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n";
2032       $lines .= "\n";
2033       $lines .= "clean-docs:\n";
2034       $lines .= "\t-rm -f index.cache.bz2\n";
2035       $lines .= "\n";
2036       $target_adds{"install-data-am"} .= "install-docs ";
2037       $target_adds{"uninstall"} .= "uninstall-docs ";
2038       $target_adds{"clean-am"} .= "clean-docs ";
2039       appendLines ($lines);
2040     } else {
2041       appendLines("docs-am: $files\n");
2042     }
2043
2044     $target_adds{"install-data-am"} .= "install-nls ";
2045     $target_adds{"uninstall"} .= "uninstall-nls ";
2046
2047     $tmp = "install-nls:\n";
2048     $tmp .= "\t\$(mkinstalldirs) \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname\n";
2049     $tmp .= "\t\@for base in $files; do \\\n";
2050     $tmp .= "\t  echo \$(INSTALL_DATA) \$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
2051     $tmp .= "\t  \$(INSTALL_DATA) \$(srcdir)/\$\$base \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
2052     $tmp .= "\tdone\n";
2053     if ($appname eq 'common') {
2054       $tmp .= "\t\@echo \"merging common and language specific dir\" ;\\\n";
2055       $tmp .= "\tif test ! -f \$(kde_htmldir)/en/common/kde-common.css; then echo 'no english docs found in \$(kde_htmldir)/en/common/'; exit 1; fi \n";
2056       $tmp .= "\t\@com_files=`cd \$(kde_htmldir)/en/common && echo *` ;\\\n";
2057       $tmp .= "\tcd \$(DESTDIR)\$(kde_htmldir)/$kdelang/common ;\\\n";
2058       $tmp .= "\tif test -n \"\$\$com_files\"; then for p in \$\$com_files ; do \\\n";
2059       $tmp .= "\t  case \" $files \" in \\\n";
2060       $tmp .= "\t    *\" \$\$p \"*) ;; \\\n";
2061       $tmp .= "\t    *) test ! -f \$\$p && echo \$(LN_S) ../../en/common/\$\$p \$(DESTDIR)\$(kde_htmldir)/$kdelang/common/\$\$p && \$(LN_S) ../../en/common/\$\$p \$\$p ;; \\\n";
2062       $tmp .= "\t  esac ; \\\n";
2063       $tmp .= "\tdone ; fi ; true\n";
2064     }
2065     $tmp .= "\n";
2066     $tmp .= "uninstall-nls:\n";
2067     $tmp .= "\tfor base in $files; do \\\n";
2068     $tmp .= "\t  rm -f \$(DESTDIR)\$(kde_htmldir)/$kdelang/$appname/\$\$base ;\\\n";
2069     $tmp .= "\tdone\n\n";
2070     appendLines ($tmp);
2071
2072     $target_adds{"distdir"} .= "distdir-nls ";
2073
2074     $tmp = "distdir-nls:\n";
2075     $tmp .= "\tfor file in $files; do \\\n";
2076     $tmp .= "\t  cp \$(srcdir)/\$\$file \$(distdir); \\\n";
2077     $tmp .= "\tdone\n";
2078
2079     appendLines ($tmp);
2080
2081     return 0;
2082
2083   nodocs:
2084     appendLines("docs-am:\n");
2085     return 1;
2086 }
2087
2088 #-----------------------------------------------------------------------------
2089 # Find headers in any of the source directories specified previously, that
2090 # are candidates for "moc-ing".
2091 sub findMocCandidates ()
2092 {
2093     foreach $dir (@headerdirs)
2094     {
2095         my @list = ();
2096         opendir (SRCDIR, "$dir");
2097         @hFiles = grep { /.+\.$hExt$/o && !/^\./ } readdir(SRCDIR);
2098         closedir SRCDIR;
2099         foreach $hf (@hFiles)
2100         {
2101             next if ($hf =~ /^\.\#/);
2102             $hf =~ /(.*)\.[^\.]*$/;          # Find name minus extension
2103             next if ($uiFiles{$1});
2104             open (HFIN, "$dir/$hf") || die "Could not open $dir/$hf: $!\n";
2105             my $hfsize = 0;
2106             seek(HFIN, 0, 2);
2107             $hfsize = tell(HFIN);
2108             seek(HFIN, 0, 0);
2109             read HFIN, $hfData, $hfsize;
2110             close HFIN;
2111             # push (@list, $hf) if(index($hfData, "Q_OBJECT") >= 0); ### fast but doesn't handle //Q_OBJECT
2112             # handle " { friend class blah; Q_OBJECT ", but don't match antlarr_Q_OBJECT (\b).
2113             if ( $hfData =~ /{([^}]*)\bQ_OBJECT/s ) {
2114                 push (@list, $hf) unless $1 =~ m://[^\n]*Q_OBJECT[^\n]*$:s;  ## reject "// Q_OBJECT"
2115             }
2116         }
2117         # The assoc array of root of headerfile and header filename
2118         foreach $hFile (@list)
2119         {
2120             $hFile =~ /(.*)\.[^\.]*$/;          # Find name minus extension
2121             if ($mocFiles{$1})
2122             {
2123               print STDERR "Warning: Multiple header files found for $1\n";
2124               next;                           # Use the first one
2125             }
2126             $mocFiles{$1} = "$dir\035$hFile";   # Add relative dir
2127         }
2128     }
2129
2130     return 0;
2131 }
2132
2133 #-----------------------------------------------------------------------------
2134
2135 # The programmer has specified a moc list. Prune out the moc candidates
2136 # list that we found based on looking at the header files. This generates
2137 # a warning if the programmer gets the list wrong, but this doesn't have
2138 # to be fatal here.
2139 sub pruneMocCandidates ($)
2140 {
2141     my %prunedMoc = ();
2142     local @mocList = split(' ', $_[0]);
2143
2144     foreach $mocname (@mocList)
2145     {
2146         $mocname =~ s/\.moc$//;
2147         if ($mocFiles{$mocname})
2148         {
2149             $prunedMoc{$mocname} = $mocFiles{$mocname};
2150         }
2151         else
2152         {
2153             my $print = $makefileDir;
2154             $print =~ s/^\Q$topdir\E\\//;
2155             # They specified a moc file but we can't find a header that
2156             # will generate this moc file. That's possible fatal!
2157             print STDERR "Warning: No moc-able header file for $print/$mocname\n";
2158         }
2159     }
2160
2161     undef %mocFiles;
2162     %mocFiles = %prunedMoc;
2163 }
2164
2165 #-----------------------------------------------------------------------------
2166
2167 # Finds the cpp files (If they exist).
2168 # The cpp files get appended to the header file separated by \035
2169 sub checkMocCandidates ()
2170 {
2171     my @cppFiles;
2172     my $cpp2moc;  # which c++ file includes which .moc files
2173     my $moc2cpp;  # which moc file is included by which c++ files
2174
2175     return unless (keys %mocFiles);
2176     opendir(THISDIR, ".") || return;
2177     @cppFiles = grep { /.+\.$cppExt$/o  && !/.+\.moc\.$cppExt$/o
2178                          && !/.+\.all_$cppExt\.$cppExt$/o
2179                          && !/^\./  } readdir(THISDIR);
2180     closedir THISDIR;
2181     return unless (@cppFiles);
2182     my $files = join (" ", @cppFiles);
2183     $cpp2moc = {};
2184     $moc2cpp = {};
2185     foreach $cxxf (@cppFiles)
2186     {
2187       open (CXXFIN, $cxxf) || die "Could not open $cxxf: $!\n";
2188       seek(CXXFIN, 0, 2);
2189       my $cxxfsize = tell(CXXFIN);
2190       seek(CXXFIN, 0, 0);
2191       read CXXFIN, $cxxfData, $cxxfsize;
2192       close CXXFIN;
2193       while(($cxxfData =~ m/^[ \t]*\#include\s*[<\"](.*\.moc)[>\"]/gm)) {
2194         $cpp2moc->{$cxxf}->{$1} = 1;
2195         $moc2cpp->{$1}->{$cxxf} = 1;
2196       }
2197     }
2198     foreach my $mocFile (keys (%mocFiles))
2199     {
2200         @cppFiles = keys %{$moc2cpp->{"$mocFile.moc"}};
2201         if (@cppFiles == 1) {
2202             $mocFiles{$mocFile} .= "\035" . $cppFiles[0];
2203             push(@depend, $mocFile);
2204         } elsif (@cppFiles == 0) {
2205             push (@newObs, $mocFile);           # Produce new object file
2206             next    if ($haveAutomocTag);       # This is expected...
2207             # But this is an error we can deal with - let them know
2208             print STDERR
2209                 "Warning: No c++ file that includes $mocFile.moc\n";
2210         } else {
2211             # We can't decide which file to use, so it's fatal. Although as a
2212             # guess we could use the mocFile.cpp file if it's in the list???
2213             print STDERR
2214                 "Error: Multiple c++ files that include $mocFile.moc\n";
2215             print STDERR "\t",join ("\t", @cppFiles),"\n";
2216             $errorflag = 1;
2217             delete $mocFiles{$mocFile};
2218             # Let's continue and see what happens - They have been told!
2219         }
2220     }
2221 }
2222
2223 #-----------------------------------------------------------------------------
2224
2225 # Add the rules for generating moc source from header files
2226 # For Automoc output *.moc.cpp but normally we'll output *.moc
2227 # (We must compile *.moc.cpp separately. *.moc files are included
2228 # in the appropriate *.cpp file by the programmer)
2229 sub addMocRules ()
2230 {
2231     my $cppFile;
2232     my $hFile;
2233
2234     foreach $mocFile (keys (%mocFiles))
2235     {
2236         undef $cppFile;
2237         ($dir, $hFile, $cppFile) =  split ("\035", $mocFiles{$mocFile}, 3);
2238         $dir =~ s#^\.#\$(srcdir)#;
2239         if (defined ($cppFile))
2240         {
2241           $cppFile =~ s,\.[^.]*$,,;
2242           $target_adds{"$cppFile.o"} .= "$mocFile.moc ";
2243           $target_adds{"$cppFile.lo"} .= "$mocFile.moc ";
2244           appendLines ("$mocFile.moc: $dir/$hFile\n\t\$(MOC) $dir/$hFile -o $mocFile.moc\n");
2245           $cleanMoc .= " $mocFile.moc";
2246           appendLines ("mocs: $mocFile.moc\n");
2247         }
2248         else
2249         {
2250             appendLines ("$mocFile$mocExt: $dir/$hFile\n\t\$(MOC) $dir/$hFile -o $mocFile$mocExt\n");
2251             $cleanMoc .= " $mocFile$mocExt";
2252             appendLines ("mocs: $mocFile$mocExt\n");
2253         }
2254     }
2255 }
2256
2257 sub make_bcheck_target()
2258 {
2259     my $lookup = 'RECURSIVE_TARGETS\s*=[ \t]*(.*)';
2260     my $bcheckdep = "bcheck-am";
2261     $bcheckdep = "bcheck-recursive" if ($MakefileData =~ /\n$lookup/);
2262
2263     my $headers= "";
2264     $headers = $1 if($MakefileData =~ /\nHEADERS\s*=[ \t]*(.+)/);
2265     $headers =~ s/\$\((?:noinst|EXTRA)_HEADERS\)//g;
2266
2267     $target_adds{"clean-am"} .= "clean-bcheck ";
2268
2269     my $t = "clean-bcheck: \n" .
2270             "\trm -f *.bchecktest.cc *.bchecktest.cc.class a.out\n\n" .
2271             "bcheck: $bcheckdep\n\n" .
2272             "bcheck-am:\n" .
2273            "\t\@for i in $headers; do \\\n" .
2274            "\t    if test \$(srcdir)/\$\$i -nt \$\$i.bchecktest.cc; then \\\n" . 
2275            "\t        echo \"int main() {return 0;}\" > \$\$i.bchecktest.cc ; \\\n" .
2276            "\t        echo \"#include \\\"\$\$i\\\"\" >> \$\$i.bchecktest.cc ; \\\n" .
2277            "\t        echo \"\$\$i\"; \\\n" . 
2278            "\t        if ! ";
2279     $t .=  $cxxsuffix eq "KKK" ?
2280            "\$(CXX) \$(DEFS) -I. -I\$(srcdir) -I\$(top_builddir) \$(INCLUDES) \$(AM_CPPFLAGS) \$(CPPFLAGS) \$(CXXFLAGS) \$(KDE_CXXFLAGS) " :
2281            "\$(CXXCOMPILE) ";
2282     $t .=  " --dump-class-hierarchy -c \$\$i.bchecktest.cc; then \\\n" .
2283            "\t            rm -f \$\$i.bchecktest.cc; exit 1; \\\n" .
2284            "\t        fi ; \\\n" .
2285            "\t        echo \"\" >> \$\$i.bchecktest.cc.class; \\\n" .
2286            "\t        perl \$(top_srcdir)/admin/bcheck.pl \$\$i.bchecktest.cc.class || { rm -f \$\$i.bchecktest.cc; exit 1; }; \\\n" .
2287            "\t        rm -f a.out; \\\n" .
2288            "\t    fi ; \\\n" .
2289            "\tdone\n";
2290     appendLines("$t\n");
2291 }
2292
2293 sub make_meta_classes ()
2294 {
2295     return if ($kdeopts{"qtonly"});
2296
2297     my $cppFile;
2298     my $hFile;
2299     my $moc_class_headers = "";
2300     foreach $program (@programs) {
2301         my $mocs = "";
2302         my @progsources = split(/[\034\s]+/, $sources{$program});
2303         my @depmocs = split(' ', $dependmocs{$program});
2304         my %shash = (), %mhash = ();
2305         @shash{@progsources} = 1;  # we are only interested in the existence
2306         @mhash{@depmocs} = 1;
2307
2308         print STDOUT "program=$program\n" if ($verbose);
2309         print STDOUT "psources=[".join(' ', keys %shash)."]\n" if ($verbose);
2310         print STDOUT "depmocs=[".join(' ', keys %mhash)."]\n" if ($verbose);
2311         print STDOUT "globalmocs=[".join(' ', keys(%globalmocs))."]\n" if ($verbose);
2312         foreach my $mocFile (keys (%globalmocs))
2313         {
2314             my ($dir, $hFile, $cppFile) = split ("\035", $globalmocs{$mocFile}, 3);
2315             if (defined ($cppFile))
2316             {
2317                 $mocs .= " $mocFile.moc" if exists $shash{$cppFile};
2318             }
2319             else
2320             {
2321                 # Bah. This is the case, if no C++ file includes the .moc
2322                 # file. We make a .moc.cpp file for that. Unfortunately this
2323                 # is not included in the %sources hash, but rather is mentioned
2324                 # in %dependmocs. If the user wants to use AUTO he can't just
2325                 # use an unspecific METAINCLUDES. Instead he must use
2326                 # program_METAINCLUDES. Anyway, it's not working real nicely.
2327                 # E.g. Its not clear what happens if user specifies two
2328                 # METAINCLUDES=AUTO in the same Makefile.am.
2329                 $mocs .= " $mocFile.moc.$cxxsuffix"
2330                     if exists $mhash{$mocFile.".moc.$cxxsuffix"};
2331             }
2332         }
2333         if ($mocs) {
2334             print STDOUT "==> mocs=[".$mocs."]\n" if ($verbose);
2335         }
2336         print STDOUT "\n" if $verbose;
2337     }
2338     if ($moc_class_headers) {
2339         appendLines ("$cleantarget-moc-classes:\n\t-rm -f $moc_class_headers\n");
2340         $target_adds{"$cleantarget-am"} .= "$cleantarget-moc-classes ";
2341     }
2342 }
2343
2344 #-----------------------------------------------------------------------------
2345
2346 sub updateMakefile ()
2347 {
2348     return if ($dryrun);
2349
2350     open (FILEOUT, "> $makefile")
2351                         || die "Could not create $makefile: $!\n";
2352
2353     $MakefileData =~ s/\034/\\\n/g;    # Restore continuation lines
2354     # Append our $progId line, _below_ the "generated by automake" line
2355     # because automake-1.6 relies on the first line to be his own.
2356     my $progIdLine = "\# $progId - " . '$Revision$ '."\n";
2357     if ( !( $MakefileData =~ s/^(.*generated .*by automake.*\n)/$1$progIdLine/ ) ) {
2358         warn "automake line not found in $makefile\n";
2359         # Fallback: first line
2360         print FILEOUT $progIdLine;
2361     };
2362     print FILEOUT $MakefileData;
2363     close FILEOUT;
2364 }
2365
2366 #-----------------------------------------------------------------------------
2367
2368 # The given line needs to be removed from the makefile
2369 # Do this by adding the special "removed line" comment at the line start.
2370 sub removeLine ($$)
2371 {
2372     my ($lookup, $old) = @_;
2373
2374     $old =~ s/\034/\\\n#>- /g;          # Fix continuation lines
2375     $MakefileData =~ s/\n$lookup/\n#>\- $old/;
2376 }
2377
2378 #-----------------------------------------------------------------------------
2379
2380 # Replaces the old line with the new line
2381 # old line(s) are retained but tagged as removed. The new line(s) have the
2382 # "added" tag placed before it.
2383 sub substituteLine ($$)
2384 {
2385     my ($lookup, $new) = @_;
2386
2387     if ($MakefileData =~ /\n($lookup)/) {
2388       $old = $1;
2389       $old =~ s/\034/\\\n#>\- /g;         # Fix continuation lines
2390       my $newCount = ($new =~ tr/\034//) + ($new =~ tr/\n//) + 1;
2391       $new =~ s/\\\n/\034/g;
2392       $MakefileData =~ s/\n$lookup/\n#>- $old\n#>\+ $newCount\n$new/;
2393     } else {
2394         warn "Warning: substitution of \"$lookup\" in $printname failed\n";
2395     }
2396 }
2397
2398 #-----------------------------------------------------------------------------
2399
2400 # Slap new lines on the back of the file.
2401 sub appendLines ($)
2402 {
2403   my ($new) = @_;
2404   my $copynew = $new;
2405   my $newCount = ($new =~ tr/\034//) + ($new =~ tr/\n//) + 1;
2406   $new =~ s/\\\n/\034/g;        # Fix continuation lines
2407   $MakefileData .= "\n#>\+ $newCount\n$new";
2408 }
2409
2410 #-----------------------------------------------------------------------------
2411
2412 # Restore the Makefile.in to the state it was before we fiddled with it
2413 sub restoreMakefile ()
2414 {
2415     $MakefileData =~ s/# $progId[^\n\034]*[\n\034]*//g;
2416     # Restore removed lines
2417     $MakefileData =~ s/([\n\034])#>\- /$1/g;
2418     # Remove added lines
2419     while ($MakefileData =~ /[\n\034]#>\+ ([^\n\034]*)/)
2420     {
2421         my $newCount = $1;
2422         my $removeLines = "";
2423         while ($newCount--) {
2424             $removeLines .= "[^\n\034]*([\n\034]|)";
2425         }
2426         $MakefileData =~ s/[\n\034]#>\+.*[\n\034]$removeLines/\n/;
2427     }
2428 }
2429
2430 #-----------------------------------------------------------------------------
2431
2432 # find the .kcfg file listed in the .kcfgc file
2433 sub findKcfgFile($)
2434 {
2435   my ($kcfgf) = @_;
2436   open (KCFGFIN, $kcfgf) || die "Could not open $kcfgf: $!\n";
2437   seek(KCFGFIN, 0, 2);
2438   my $kcfgfsize = tell(KCFGFIN);
2439   seek(KCFGFIN, 0, 0);
2440   read KCFGFIN, $kcfgfData, $kcfgfsize;
2441   close KCFGFIN;
2442   if(($kcfgfData =~ m/^File=(.*\.kcfg)/gm)) {
2443     $kcfg = $1;
2444   }
2445 }