Fixed winelauncher for new dll files layout.
[wine] / tools / winemaker
1 #!/usr/bin/perl -w
2
3 # Copyright 2000 Francois Gouget for CodeWeavers
4 # fgouget@codeweavers.com
5 #
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 #
20
21 my $version="0.5.8";
22
23 use Cwd;
24 use File::Basename;
25 use File::Copy;
26
27
28
29 #####
30 #
31 # Options
32 #
33 #####
34
35 # The following constants define what we do with the case of filenames
36
37 ##
38 # Never rename a file to lowercase
39 my $OPT_LOWER_NONE=0;
40
41 ##
42 # Rename all files to lowercase
43 my $OPT_LOWER_ALL=1;
44
45 ##
46 # Rename only files that are all uppercase to lowercase
47 my $OPT_LOWER_UPPERCASE=2;
48
49
50 # The following constants define whether to ask questions or not
51
52 ##
53 # No (synonym of never)
54 my $OPT_ASK_NO=0;
55
56 ##
57 # Yes (always)
58 my $OPT_ASK_YES=1;
59
60 ##
61 # Skip the questions till the end of this scope
62 my $OPT_ASK_SKIP=-1;
63
64
65 # General options
66
67 ##
68 # This is the directory in which winemaker will operate.
69 my $opt_work_dir;
70
71 ##
72 # Make a backup of the files
73 my $opt_backup;
74
75 ##
76 # Defines which files to rename
77 my $opt_lower;
78
79 ##
80 # If we don't find the file referenced by an include, lower it
81 my $opt_lower_include;
82
83 ##
84 # If true then winemaker should not attempt to fix the source.  This is
85 # useful if the source is known to be already in a suitable form and is
86 # readonly
87 my $opt_no_source_fix;
88
89 # Options for the 'Source' method
90
91 ##
92 # Specifies that we have only one target so that all sources relate 
93 # to this target. By default this variable is left undefined which 
94 # means winemaker should try to find out by itself what the targets 
95 # are. If not undefined then this contains the name of the default 
96 # target (without the extension).
97 my $opt_single_target;
98
99 ##
100 # If '$opt_single_target' has been specified then this is the type of 
101 # that target. Otherwise it specifies whether the default target type 
102 # is guiexe or cuiexe.
103 my $opt_target_type;
104
105 ##
106 # Contains the default set of flags to be used when creating a new target.
107 my $opt_flags;
108
109 ##
110 # If true then winemaker should ask questions to the user as it goes 
111 # along.
112 my $opt_is_interactive;
113 my $opt_ask_project_options;
114 my $opt_ask_target_options;
115
116 ##
117 # If false then winemaker should not generate any file, i.e. 
118 # no makefiles, but also no .spec files, no configure.in, etc.
119 my $opt_no_generated_files;
120
121 ##
122 # If true then winemaker should not generate the spec files.
123 # This is useful if winemaker is being used to create a build environment
124 my $opt_no_generated_specs;
125
126 ##
127 # Specifies not to print the banner if set.
128 my $opt_no_banner;
129
130
131
132 #####
133 #
134 # Target modelization
135 #
136 #####
137
138 # The description of a target is stored in an array. The constants 
139 # below identify what is stored at each index of the array.
140
141 ##
142 # This is the name of the target.
143 my $T_NAME=0;
144
145 ##
146 # Defines the type of target we want to build. See the TT_xxx
147 # constants below
148 my $T_TYPE=1;
149
150 ##
151 # Defines the target's enty point, i.e. the function that is called
152 # on startup.
153 my $T_INIT=2;
154
155 ##
156 # This is a bitfield containing flags refining the way the target 
157 # should be handled. See the TF_xxx constants below
158 my $T_FLAGS=3;
159
160 ##
161 # This is a reference to an array containing the list of the 
162 # resp. C, C++, RC, other (.h, .hxx, etc.) source files.
163 my $T_SOURCES_C=4;
164 my $T_SOURCES_CXX=5;
165 my $T_SOURCES_RC=6;
166 my $T_SOURCES_MISC=7;
167
168 ##
169 # This is a reference to an array containing the list of macro 
170 # definitions
171 my $T_DEFINES=8;
172
173 ##
174 # This is a reference to an array containing the list of directory 
175 # names that constitute the include path
176 my $T_INCLUDE_PATH=9;
177
178 ##
179 # Same as T_INCLUDE_PATH but for the dll search path
180 my $T_DLL_PATH=10;
181
182 ##
183 # The list of Windows dlls to import
184 my $T_DLLS=11;
185
186 ##
187 # Same as T_INCLUDE_PATH but for the library search path
188 my $T_LIBRARY_PATH=12;
189
190 ##
191 # The list of Unix libraries to link with
192 my $T_LIBRARIES=13;
193
194 ##
195 # The list of dependencies between targets
196 my $T_DEPENDS=14;
197
198
199 # The following constants define the recognized types of target
200
201 ##
202 # This is not a real target. This type of target is used to collect 
203 # the sources that don't seem to belong to any other target. Thus no
204 # real target is generated for them, we just put the sources of the 
205 # fake target in the global source list.
206 my $TT_SETTINGS=0;
207
208 ##
209 # For executables in the windows subsystem
210 my $TT_GUIEXE=1;
211
212 ##
213 # For executables in the console subsystem
214 my $TT_CUIEXE=2;
215
216 ##
217 # For dynamically linked libraries
218 my $TT_DLL=3;
219
220
221 # The following constants further refine how the target should be handled
222
223 ##
224 # This target needs a wrapper
225 my $TF_WRAP=1;
226
227 ##
228 # This target is a wrapper
229 my $TF_WRAPPER=2;
230
231 ##
232 # This target is an MFC-based target
233 my $TF_MFC=4;
234
235 ##
236 # Initialize a target:
237 # - set the target type to TT_SETTINGS, i.e. no real target will 
238 #   be generated. 
239 sub target_init
240 {
241   my $target=$_[0];
242
243   @$target[$T_TYPE]=$TT_SETTINGS;
244   # leaving $T_INIT undefined
245   @$target[$T_FLAGS]=$opt_flags;
246   @$target[$T_SOURCES_C]=[];
247   @$target[$T_SOURCES_CXX]=[];
248   @$target[$T_SOURCES_RC]=[];
249   @$target[$T_SOURCES_MISC]=[];
250   @$target[$T_DEFINES]=[];
251   @$target[$T_INCLUDE_PATH]=[];
252   @$target[$T_DLL_PATH]=[];
253   @$target[$T_DLLS]=[];
254   @$target[$T_LIBRARY_PATH]=[];
255   @$target[$T_LIBRARIES]=[];
256   @$target[$T_DEPENDS]=[];
257 }
258
259 sub get_default_init
260 {
261   my $type=$_[0];
262   if ($type == $TT_GUIEXE) {
263     return "WinMain";
264   } elsif ($type == $TT_CUIEXE) {
265     return "main";
266   } elsif ($type == $TT_DLL) {
267     return "DllMain";
268   }
269 }
270
271
272
273 #####
274 #
275 # Project modelization
276 #
277 #####
278
279 # First we have the notion of project. A project is described by an 
280 # array (since we don't have structs in perl). The constants below 
281 # identify what is stored at each index of the array.
282
283 ##
284 # This is the path in which this project is located. In other 
285 # words, this is the path to  the Makefile.
286 my $P_PATH=0;
287
288 ##
289 # This index contains a reference to an array containing the project-wide 
290 # settings. The structure of that arrray is actually identical to that of 
291 # a regular target since it can also contain extra sources.
292 my $P_SETTINGS=1;
293
294 ##
295 # This index contains a reference to an array of targets for this 
296 # project. Each target describes how an executable or library is to 
297 # be built. For each target this description takes the same form as 
298 # that of the project: an array. So this entry is an array of arrays.
299 my $P_TARGETS=2;
300
301 ##
302 # Initialize a project:
303 # - set the project's path
304 # - initialize the target list
305 # - create a default target (will be removed later if unnecessary)
306 sub project_init
307 {
308   my $project=$_[0];
309   my $path=$_[1];
310
311   my $project_settings=[];
312   target_init($project_settings);
313
314   @$project[$P_PATH]=$path;
315   @$project[$P_SETTINGS]=$project_settings;
316   @$project[$P_TARGETS]=[];
317 }
318
319
320
321 #####
322 #
323 # Global variables
324 #
325 #####
326
327 my %warnings;
328
329 my %templates;
330
331 ##
332 # Contains the list of all projects. This list tells us what are 
333 # the subprojects of the main Makefile and where we have to generate 
334 # Makefiles.
335 my @projects=();
336
337 ##
338 # This is the main project, i.e. the one in the "." directory. 
339 # It may well be empty in which case the main Makefile will only 
340 # call out subprojects.
341 my @main_project;
342
343 ##
344 # Contains the defaults for the include path, etc.
345 # We store the defaults as if this were a target except that we only 
346 # exploit the defines, include path, library path, library list and misc
347 # sources fields.
348 my @global_settings;
349
350 ##
351 # If one of the projects requires the MFc then we set this global variable 
352 # to true so that configure asks the user to provide a path tothe MFC
353 my $needs_mfc=0;
354
355
356
357 #####
358 #
359 # Utility functions
360 #
361 #####
362
363 ##
364 # Cleans up a name to make it an acceptable Makefile 
365 # variable name.
366 sub canonize
367 {
368   my $name=$_[0];
369
370   $name =~ tr/a-zA-Z0-9_/_/c;
371   return $name;
372 }
373
374 ##
375 # Returns true is the specified pathname is absolute.
376 # Note: pathnames that start with a variable '$' or 
377 # '~' are considered absolute.
378 sub is_absolute
379 {
380   my $path=$_[0];
381
382   return ($path =~ /^[\/~\$]/);
383 }
384
385 ##
386 # Performs a binary search looking for the specified item
387 sub bsearch
388 {
389   my $array=$_[0];
390   my $item=$_[1];
391   my $last=@{$array}-1;
392   my $first=0;
393
394   while ($first<=$last) {
395     my $index=int(($first+$last)/2);
396     my $cmp=@$array[$index] cmp $item;
397     if ($cmp<0) {
398       $first=$index+1;
399     } elsif ($cmp>0) {
400       $last=$index-1;
401     } else {
402       return $index;
403     }
404   }
405 }
406
407
408
409 #####
410 #
411 # 'Source'-based Project analysis
412 #
413 #####
414
415 ##
416 # Allows the user to specify makefile and target specific options
417 # - target: the structure in which to store the results
418 # - options: the string containing the options
419 sub source_set_options
420 {
421   my $target=$_[0];
422   my $options=$_[1];
423
424   #FIXME: we must deal with escaping of stuff and all
425   foreach $option (split / /,$options) {
426     if (@$target[$T_TYPE] == $TT_SETTINGS and $option =~ /^-D/) {
427       push @{@$target[$T_DEFINES]},$option;
428     } elsif (@$target[$T_TYPE] == $TT_SETTINGS and $option =~ /^-I/) {
429       push @{@$target[$T_INCLUDE_PATH]},$option;
430     } elsif ($option =~ /^-P/) {
431       push @{@$target[$T_DLL_PATH]},"-L$'";
432     } elsif ($option =~ /^-i/) {
433       push @{@$target[$T_DLLS]},"$'";
434     } elsif ($option =~ /^-L/) {
435       push @{@$target[$T_LIBRARY_PATH]},$option;
436     } elsif ($option =~ /^-l/) {
437       push @{@$target[$T_LIBRARIES]},"$'";
438     } elsif (@$target[$T_TYPE] != $TT_DLL and $option =~ /^--wrap/) {
439       @$target[$T_FLAGS]|=$TF_WRAP;
440     } elsif (@$target[$T_TYPE] != $TT_DLL and $option =~ /^--nowrap/) {
441       @$target[$T_FLAGS]&=~$TF_WRAP;
442     } elsif ($option =~ /^--mfc/) {
443       @$target[$T_FLAGS]|=$TF_MFC;
444       if (@$target[$T_TYPE] != $TT_DLL) {
445         @$target[$T_FLAGS]|=$TF_WRAP;
446       }
447     } elsif ($option =~ /^--nomfc/) {
448       @$target[$T_FLAGS]&=~$TF_MFC;
449       @$target[$T_FLAGS]&=~($TF_MFC|$TF_WRAP);
450     } else {
451       print STDERR "error: unknown option \"$option\"\n";
452       return 0;
453     }
454   }
455   return 1;
456 }
457
458 ##
459 # Scans the specified directory to:
460 # - see if we should create a Makefile in this directory. We normally do 
461 #   so if we find a project file and sources
462 # - get a list of targets for this directory
463 # - get the list of source files
464 sub source_scan_directory
465 {
466   # a reference to the parent's project
467   my $parent_project=$_[0];
468   # the full relative path to the current directory, including a 
469   # trailing '/', or an empty string if this is the top level directory
470   my $path=$_[1];
471   # the name of this directory, including a trailing '/', or an empty
472   # string if this is the top level directory
473   my $dirname=$_[2];
474   # if set then no targets will be looked for and the sources will all 
475   # end up in the parent_project's 'misc' bucket
476   my $no_target=$_[3];
477
478   # reference to the project for this directory. May not be used
479   my $project;
480   # list of targets found in the 'current' directory
481   my %targets;
482   # list of sources found in the current directory
483   my @sources_c=();
484   my @sources_cxx=();
485   my @sources_rc=();
486   my @sources_misc=();
487   # true if this directory contains a Windows project
488   my $has_win_project=0;
489   # If we don't find any executable/library then we might make up targets 
490   # from the list of .dsp/.mak files we find since they usually have the 
491   # same name as their target.
492   my @dsp_files=();
493   my @mak_files=();
494
495   if (defined $opt_single_target or $dirname eq "") {
496     # Either there is a single target and thus a single project, 
497     # or we are in the top level directory for which a project 
498     # already exists
499     $project=$parent_project;
500   } else {
501     $project=[];
502     project_init($project,$path);
503   }
504   my $project_settings=@$project[$P_SETTINGS];
505
506   # First find out what this directory contains:
507   # collect all sources, targets and subdirectories
508   my $directory=get_directory_contents($path);
509   foreach $dentry (@$directory) {
510     if ($dentry =~ /^\./) {
511       next;
512     }
513     my $fullentry="$path$dentry";
514     if (-d "$fullentry") {
515       if ($dentry =~ /^(Release|Debug)/i) {
516         # These directories are often used to store the object files and the 
517         # resulting executable/library. They should not contain anything else.
518         my @candidates=grep /\.(exe|dll)$/i, @{get_directory_contents("$fullentry")};
519         foreach $candidate (@candidates) {
520           if ($candidate =~ s/\.exe$//i) {
521             $targets{$candidate}=1;
522           } elsif ($candidate =~ s/^(.*)\.dll$/lib$1.so/i) {
523             $targets{$candidate}=1;
524           }
525         }
526       } elsif ($dentry =~ /^include/i) {
527         # This directory must contain headers we're going to need
528         push @{@$project_settings[$T_INCLUDE_PATH]},"-I$dentry";
529         source_scan_directory($project,"$fullentry/","$dentry/",1);
530       } else {
531         # Recursively scan this directory. Any source file that cannot be 
532         # attributed to a project in one of the subdirectories will be 
533         # attributed to this project.
534         source_scan_directory($project,"$fullentry/","$dentry/",$no_target);
535       }
536     } elsif (-f "$fullentry") {
537       if ($dentry =~ s/\.exe$//i) {
538         $targets{$dentry}=1;
539       } elsif ($dentry =~ s/^(.*)\.dll$/lib$1.so/i) {
540         $targets{$dentry}=1;
541       } elsif ($dentry =~ /\.c$/i and $dentry !~ /\.spec\.c$/) {
542         push @sources_c,"$dentry";
543       } elsif ($dentry =~ /\.(cpp|cxx)$/i) {
544         if ($dentry =~ /^stdafx.cpp$/i) {
545           push @sources_misc,"$dentry";
546           @$project_settings[$T_FLAGS]|=$TF_MFC;
547         } else {
548           push @sources_cxx,"$dentry";
549         }
550       } elsif ($dentry =~ /\.rc$/i) {
551         push @sources_rc,"$dentry";
552       } elsif ($dentry =~ /\.(h|hxx|hpp|inl|rc2|dlg)$/i) {
553         push @sources_misc,"$dentry";
554         if ($dentry =~ /^stdafx.h$/i) {
555           @$project_settings[$T_FLAGS]|=$TF_MFC;
556         }
557       } elsif ($dentry =~ /\.dsp$/i) {
558         push @dsp_files,"$dentry";
559         $has_win_project=1;
560       } elsif ($dentry =~ /\.mak$/i) {
561         push @mak_files,"$dentry";
562         $has_win_project=1;
563       } elsif ($dentry =~ /^makefile/i) {
564         $has_win_project=1;
565       }
566     }
567   }
568   closedir(DIRECTORY);
569
570   # If we have a single target then all we have to do is assign 
571   # all the sources to it and we're done
572   # FIXME: does this play well with the --interactive mode?
573   if ($opt_single_target) {
574     my $target=@{@$project[$P_TARGETS]}[0];
575     push @{@$target[$T_SOURCES_C]},map "$path$_",@sources_c;
576     push @{@$target[$T_SOURCES_CXX]},map "$path$_",@sources_cxx;
577     push @{@$target[$T_SOURCES_RC]},map "$path$_",@sources_rc;
578     push @{@$target[$T_SOURCES_MISC]},map "$path$_",@sources_misc;
579     return;
580   }
581   if ($no_target) {
582     my $parent_settings=@$parent_project[$P_SETTINGS];
583     push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_c;
584     push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_cxx;
585     push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_rc;
586     push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc;
587     push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]};
588     return;
589   }
590
591   my $source_count=@sources_c+@sources_cxx+@sources_rc+
592                    @{@$project_settings[$T_SOURCES_C]}+
593                    @{@$project_settings[$T_SOURCES_CXX]}+
594                    @{@$project_settings[$T_SOURCES_RC]};
595   if ($source_count == 0) {
596     # A project without real sources is not a project, get out!
597     if ($project!=$parent_project) {
598       my $parent_settings=@$parent_project[$P_SETTINGS];
599       push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc;
600       push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]};
601     }
602     return;
603   }
604   #print "targets=",%targets,"\n";
605   #print "target_count=$target_count\n";
606   #print "has_win_project=$has_win_project\n";
607   #print "dirname=$dirname\n";
608
609   my $target_count;
610   if (($has_win_project != 0) or ($dirname eq "")) {
611     # Deal with cases where we could not find any executable/library, and 
612     # thus have no target, although we did find some sort of windows project.
613     $target_count=keys %targets;
614     if ($target_count == 0) {
615       # Try to come up with a target list based on .dsp/.mak files
616       my $prj_list;
617       if (@dsp_files > 0) {
618         $prj_list=\@dsp_files;
619       } else {
620         $prj_list=\@mak_files;
621       }
622       foreach $filename (@$prj_list) {
623         $filename =~ s/\.(dsp|mak)$//i;
624         if ($opt_target_type == $TT_DLL) {
625           $filename = "lib$filename.so";
626         }
627         $targets{$filename}=1;
628       }
629       $target_count=keys %targets;
630       if ($target_count == 0) {
631         # Still nothing, try the name of the directory
632         my $name;
633         if ($dirname eq "") {
634           # Bad luck, this is the top level directory!
635           $name=(split /\//, cwd)[-1];
636         } else {
637           $name=$dirname;
638           # Remove the trailing '/'. Also eliminate whatever is after the last 
639           # '.' as it is likely to be meaningless (.orig, .new, ...)
640           $name =~ s+(/|\.[^.]*)$++;
641           if ($name eq "src") {
642             # 'src' is probably a subdirectory of the real project directory.
643             # Try again with the parent (if any).
644             my $parent=$path;
645             if ($parent =~ s+([^/]*)/[^/]*/$+$1+) {
646               $name=$parent;
647             } else {
648               $name=(split /\//, cwd)[-1];
649             }
650           }
651         }
652         $name =~ s+(/|\.[^.]*)$++;
653         if ($opt_target_type == $TT_DLL) {
654           $name = "lib$name.so";
655         }
656         $targets{$name}=1;
657       }
658     }
659
660     # Ask confirmation to the user if he wishes so
661     if ($opt_is_interactive == $OPT_ASK_YES) {
662       my $target_list=join " ",keys %targets;
663       print "\n*** In ",($path?$path:"./"),"\n";
664       print "* winemaker found the following list of (potential) targets\n";
665       print "*   $target_list\n";
666       print "* Type enter to use it as is, your own comma-separated list of\n";
667       print "* targets, 'none' to assign the source files to a parent directory,\n";
668       print "* or 'ignore' to ignore everything in this directory tree.\n";
669       print "* Target list:\n";
670       $target_list=<STDIN>;
671       chomp $target_list;
672       if ($target_list eq "") {
673         # Keep the target list as is, i.e. do nothing
674       } elsif ($target_list eq "none") {
675         # Empty the target list
676         undef %targets;
677       } elsif ($target_list eq "ignore") {
678         # Ignore this subtree altogether
679         return;
680       } else {
681         undef %targets;
682         foreach $target (split /,/,$target_list) {
683           $target =~ s+^\s*++;
684           $target =~ s+\s*$++;
685           # Also accept .exe and .dll as a courtesy
686           $target =~ s+(.*)\.dll$+lib$1.so+;
687           $target =~ s+\.exe$++;
688           $targets{$target}=1;
689         }
690       }
691     }
692   }
693
694   # If we have no project at this level, then transfer all 
695   # the sources to the parent project
696   $target_count=keys %targets;
697   if ($target_count == 0) {
698     if ($project!=$parent_project) {
699       my $parent_settings=@$parent_project[$P_SETTINGS];
700       push @{@$parent_settings[$T_SOURCES_C]},map "$dirname$_",@sources_c;
701       push @{@$parent_settings[$T_SOURCES_CXX]},map "$dirname$_",@sources_cxx;
702       push @{@$parent_settings[$T_SOURCES_RC]},map "$dirname$_",@sources_rc;
703       push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc;
704       push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]};
705     }
706     return;
707   }
708
709   # Otherwise add this project to the project list, except for 
710   # the main project which is already in the list.
711   if ($dirname ne "") {
712     push @projects,$project;
713   }
714
715   # Ask for project-wide options
716   if ($opt_ask_project_options == $OPT_ASK_YES) {
717     my $flag_desc="";
718     if ((@$project_settings[$T_FLAGS] & $TF_MFC)!=0) {
719       $flag_desc="mfc";
720     }
721     if ((@$project_settings[$T_FLAGS] & $TF_WRAP)!=0) {
722       if ($flag_desc ne "") {
723         $flag_desc.=", ";
724       }
725       $flag_desc.="wrapped";
726     }
727     print "* Type any project-wide options (-D/-I/-P/-i/-L/-l/--mfc/--wrap),\n";
728     if (defined $flag_desc) {
729       print "* (currently $flag_desc)\n";
730     }
731     print "* or 'skip' to skip the target specific options,\n";
732     print "* or 'never' to not be asked this question again:\n";
733     while (1) {
734       my $options=<STDIN>;
735       chomp $options;
736       if ($options eq "skip") {
737         $opt_ask_target_options=$OPT_ASK_SKIP;
738         last;
739       } elsif ($options eq "never") {
740         $opt_ask_project_options=$OPT_ASK_NO;
741         last;
742       } elsif (source_set_options($project_settings,$options)) {
743         last;
744       }
745       print "Please re-enter the options:\n";
746     }
747   }
748
749   # - Create the targets
750   # - Check if we have both libraries and programs
751   # - Match each target with source files (sort in reverse 
752   #   alphabetical order to get the longest matches first)
753   my @local_dlls=();
754   my @local_depends=();
755   my @exe_list=();
756   foreach $target_name (sort { $b cmp $a } keys %targets) {
757     # Create the target...
758     my $basename;
759     my $target=[];
760     target_init($target);
761     @$target[$T_NAME]=$target_name;
762     @$target[$T_FLAGS]|=@$project_settings[$T_FLAGS];
763     if ($target_name =~ /^lib(.*)\.so$/) {
764       @$target[$T_TYPE]=$TT_DLL;
765       @$target[$T_INIT]=get_default_init($TT_DLL);
766       @$target[$T_FLAGS]&=~$TF_WRAP;
767       $basename=$1;
768       push @local_depends,$target_name;
769       push @local_dlls,$basename;
770     } else {
771       @$target[$T_TYPE]=$opt_target_type;
772       @$target[$T_INIT]=get_default_init($opt_target_type);
773       $basename=$target_name;
774       push @exe_list,$target;
775     }
776     # This is the default link list of Visual Studio, except odbccp32 
777     # which we don't have in Wine. Also I add ntdll which seems 
778     # necessary for Winelib.
779     my @std_dlls=qw(advapi32.dll comdlg32.dll gdi32.dll kernel32.dll ntdll.dll odbc32.dll ole32.dll oleaut32.dll shell32.dll user32.dll winspool.drv);
780     @$target[$T_DLLS]=\@std_dlls;
781     push @{@$project[$P_TARGETS]},$target;
782
783     # Ask for target-specific options
784     if ($opt_ask_target_options == $OPT_ASK_YES) {
785       my $flag_desc="";
786       if ((@$target[$T_FLAGS] & $TF_MFC)!=0) {
787         $flag_desc=" (mfc";
788       }
789       if ((@$target[$T_FLAGS] & $TF_WRAP)!=0) {
790         if ($flag_desc ne "") {
791           $flag_desc.=", ";
792         } else {
793           $flag_desc=" (";
794         }
795         $flag_desc.="wrapped";
796       }
797       if ($flag_desc ne "") {
798         $flag_desc.=")";
799       }
800       print "* Specify any link option (-P/-i/-L/-l/--mfc/--wrap) specific to the target\n";
801       print "* \"$target_name\"$flag_desc or 'never' to not be asked this question again:\n";
802       while (1) {
803         my $options=<STDIN>;
804         chomp $options;
805         if ($options eq "never") {
806           $opt_ask_target_options=$OPT_ASK_NO;
807           last;
808         } elsif (source_set_options($target,$options)) {
809           last;
810         }
811         print "Please re-enter the options:\n";
812       }
813     }
814     if (@$target[$T_FLAGS] & $TF_MFC) {
815       @$project_settings[$T_FLAGS]|=$TF_MFC;
816       push @{@$target[$T_DLL_PATH]},"\$(MFC_LIBRARY_PATH)";
817       push @{@$target[$T_DLLS]},"mfc.dll";
818       # FIXME: Link with the MFC in the Unix sense, until we 
819       # start exporting the functions properly.
820       push @{@$target[$T_LIBRARY_PATH]},"\$(MFC_LIBRARY_PATH)";
821       push @{@$target[$T_LIBRARIES]},"mfc";
822     }
823
824     # Match sources...
825     if ($target_count == 1) {
826       push @{@$target[$T_SOURCES_C]},@{@$project_settings[$T_SOURCES_C]},@sources_c;
827       @$project_settings[$T_SOURCES_C]=[];
828       @sources_c=();
829
830       push @{@$target[$T_SOURCES_CXX]},@{@$project_settings[$T_SOURCES_CXX]},@sources_cxx;
831       @$project_settings[$T_SOURCES_CXX]=[];
832       @sources_cxx=();
833
834       push @{@$target[$T_SOURCES_RC]},@{@$project_settings[$T_SOURCES_RC]},@sources_rc;
835       @$project_settings[$T_SOURCES_RC]=[];
836       @sources_rc=();
837
838       push @{@$target[$T_SOURCES_MISC]},@{@$project_settings[$T_SOURCES_MISC]},@sources_misc;
839       # No need for sorting these sources
840       @$project_settings[$T_SOURCES_MISC]=[];
841       @sources_misc=();
842     } else {
843       foreach $source (@sources_c) {
844         if ($source =~ /^$basename/i) {
845           push @{@$target[$T_SOURCES_C]},$source;
846           $source="";
847         }
848       }
849       foreach $source (@sources_cxx) {
850         if ($source =~ /^$basename/i) {
851           push @{@$target[$T_SOURCES_CXX]},$source;
852           $source="";
853         }
854       }
855       foreach $source (@sources_rc) {
856         if ($source =~ /^$basename/i) {
857           push @{@$target[$T_SOURCES_RC]},$source;
858           $source="";
859         }
860       }
861       foreach $source (@sources_misc) {
862         if ($source =~ /^$basename/i) {
863           push @{@$target[$T_SOURCES_MISC]},$source;
864           $source="";
865         }
866       }
867     }
868     @$target[$T_SOURCES_C]=[sort @{@$target[$T_SOURCES_C]}];
869     @$target[$T_SOURCES_CXX]=[sort @{@$target[$T_SOURCES_CXX]}];
870     @$target[$T_SOURCES_RC]=[sort @{@$target[$T_SOURCES_RC]}];
871     @$target[$T_SOURCES_MISC]=[sort @{@$target[$T_SOURCES_MISC]}];
872   }
873   if ($opt_ask_target_options == $OPT_ASK_SKIP) {
874     $opt_ask_target_options=$OPT_ASK_YES;
875   }
876
877   if (@$project_settings[$T_FLAGS] & $TF_MFC) {
878     push @{@$project_settings[$T_INCLUDE_PATH]},"\$(MFC_INCLUDE_PATH)";
879   }
880   # The sources that did not match, if any, go to the extra 
881   # source list of the project settings
882   foreach $source (@sources_c) {
883     if ($source ne "") {
884       push @{@$project_settings[$T_SOURCES_C]},$source;
885     }
886   }
887   @$project_settings[$T_SOURCES_C]=[sort @{@$project_settings[$T_SOURCES_C]}];
888   foreach $source (@sources_cxx) {
889     if ($source ne "") {
890       push @{@$project_settings[$T_SOURCES_CXX]},$source;
891     }
892   }
893   @$project_settings[$T_SOURCES_CXX]=[sort @{@$project_settings[$T_SOURCES_CXX]}];
894   foreach $source (@sources_rc) {
895     if ($source ne "") {
896       push @{@$project_settings[$T_SOURCES_RC]},$source;
897     }
898   }
899   @$project_settings[$T_SOURCES_RC]=[sort @{@$project_settings[$T_SOURCES_RC]}];
900   foreach $source (@sources_misc) {
901     if ($source ne "") {
902       push @{@$project_settings[$T_SOURCES_MISC]},$source;
903     }
904   }
905   @$project_settings[$T_SOURCES_MISC]=[sort @{@$project_settings[$T_SOURCES_MISC]}];
906
907   # Finally if we are building both libraries and programs in 
908   # this directory, then the programs should be linked with all 
909   # the libraries
910   if (@local_dlls > 0 and @exe_list > 0) {
911     foreach $target (@exe_list) {
912       push @{@$target[$T_DLL_PATH]},"-L.";
913       push @{@$target[$T_DLLS]},map { "$_.dll" } @local_dlls;
914       # Also link in the Unix sense since none of the functions 
915       # will be exported.
916       push @{@$target[$T_LIBRARY_PATH]},"-L.";
917       push @{@$target[$T_LIBRARIES]},@local_dlls;
918       push @{@$target[$T_DEPENDS]},@local_depends;
919     }
920   }
921 }
922
923 ##
924 # Scan the source directories in search of things to build
925 sub source_scan
926 {
927   # If there's a single target then this is going to be the default target
928   if (defined $opt_single_target) {
929     # Create the main target
930     my $main_target=[];
931     target_init($main_target);
932     if ($opt_target_type == $TT_DLL) {
933       @$main_target[$T_NAME]="lib$opt_single_target.so";
934     } else {
935       @$main_target[$T_NAME]="$opt_single_target";
936     }
937     @$main_target[$T_TYPE]=$opt_target_type;
938
939     # Add it to the list
940     push @{$main_project[$P_TARGETS]},$main_target;
941   }
942
943   # The main directory is always going to be there
944   push @projects,\@main_project;
945
946   # Now scan the directory tree looking for source files and, maybe, targets
947   print "Scanning the source directories...\n";
948   source_scan_directory(\@main_project,"","",0);
949
950   @projects=sort { @$a[$P_PATH] cmp @$b[$P_PATH] } @projects;
951 }
952
953
954
955 #####
956 #
957 # 'vc.dsp'-based Project analysis
958 #
959 #####
960
961 #sub analyze_vc_dsp
962 #{
963 #  
964 #}
965
966
967
968 #####
969 #
970 # Creating the wrapper targets
971 #
972 #####
973
974 sub postprocess_targets
975 {
976   foreach $project (@projects) {
977     foreach $target (@{@$project[$P_TARGETS]}) {
978       if ((@$target[$T_FLAGS] & $TF_WRAP) != 0) {
979         my $wrapper=[];
980         target_init($wrapper);
981         @$wrapper[$T_NAME]=@$target[$T_NAME];
982         @$wrapper[$T_TYPE]=@$target[$T_TYPE];
983         @$wrapper[$T_INIT]=get_default_init(@$target[$T_TYPE]);
984         @$wrapper[$T_FLAGS]=$TF_WRAPPER | (@$target[$T_FLAGS] & $TF_MFC);
985         @$wrapper[$T_DLLS]=[ "kernel32.dll", "ntdll.dll", "user32.dll" ];
986         push @{@$wrapper[$T_SOURCES_C]},"@$wrapper[$T_NAME]_wrapper.c";
987
988         my $index=bsearch(@$target[$T_SOURCES_C],"@$wrapper[$T_NAME]_wrapper.c");
989         if (defined $index) {
990           splice(@{@$target[$T_SOURCES_C]},$index,1);
991         }
992         @$target[$T_NAME]="lib@$target[$T_NAME].so";
993         @$target[$T_TYPE]=$TT_DLL;
994
995         push @{@$project[$P_TARGETS]},$wrapper;
996       }
997       if ((@$target[$T_FLAGS] & $TF_MFC) != 0) {
998         @{@$project[$P_SETTINGS]}[$T_FLAGS]|=$TF_MFC;
999         $needs_mfc=1;
1000       }
1001     }
1002   }
1003 }
1004
1005
1006
1007 #####
1008 #
1009 # Source search
1010 #
1011 #####
1012
1013 ##
1014 # Performs a directory traversal and renames the files so that:
1015 # - they have the case desired by the user
1016 # - their extension is of the appropriate case
1017 # - they don't contain annoying characters like ' ', '$', '#', ...
1018 sub fix_file_and_directory_names
1019 {
1020   my $dirname=$_[0];
1021
1022   if (opendir(DIRECTORY, "$dirname")) {
1023     foreach $dentry (readdir DIRECTORY) {
1024       if ($dentry =~ /^\./ or $dentry eq "CVS") {
1025         next;
1026       }
1027       # Set $warn to 1 if the user should be warned of the renaming
1028       my $warn=0;
1029
1030       # autoconf and make don't support these characters well
1031       my $new_name=$dentry;
1032       $new_name =~ s/[ \$]/_/g;
1033
1034       # Only all lowercase extensions are supported (because of the 
1035       # transformations ':.c=.o') .
1036       if (-f "$dirname/$new_name") {
1037         if ($new_name =~ /\.C$/) {
1038           $new_name =~ s/\.C$/.c/;
1039         }
1040         if ($new_name =~ /\.cpp$/i) {
1041           $new_name =~ s/\.cpp$/.cpp/i;
1042         }
1043         if ($new_name =~ s/\.cxx$/.cpp/i) {
1044           $warn=1;
1045         }
1046         if ($new_name =~ /\.rc$/i) {
1047           $new_name =~ s/\.rc$/.rc/i;
1048         }
1049         # And this last one is to avoid confusion then running make
1050         if ($new_name =~ s/^makefile$/makefile.win/) {
1051           $warn=1;
1052         }
1053       }
1054
1055       # Adjust the case to the user's preferences
1056       if (($opt_lower == $OPT_LOWER_ALL and $dentry =~ /[A-Z]/) or 
1057           ($opt_lower == $OPT_LOWER_UPPERCASE and $dentry !~ /[a-z]/)
1058          ) {
1059         $new_name=lc $new_name;
1060       }
1061
1062       # And finally, perform the renaming
1063       if ($new_name ne $dentry) {
1064         if ($warn) {
1065           print STDERR "warning: in \"$dirname\", renaming \"$dentry\" to \"$new_name\"\n";
1066         }
1067         if (!rename("$dirname/$dentry","$dirname/$new_name")) {
1068           print STDERR "error: in \"$dirname\", unable to rename \"$dentry\" to \"$new_name\"\n";
1069           print STDERR "       $!\n";
1070           $new_name=$dentry;
1071         }
1072       }
1073       if (-d "$dirname/$new_name") {
1074         fix_file_and_directory_names("$dirname/$new_name");
1075       }
1076     }
1077     closedir(DIRECTORY);
1078   }
1079 }
1080
1081
1082
1083 #####
1084 #
1085 # Source fixup
1086 #
1087 #####
1088
1089 ##
1090 # This maps a directory name to a reference to an array listing 
1091 # its contents (files and directories)
1092 my %directories;
1093
1094 ##
1095 # Retrieves the contents of the specified directory.
1096 # We either get it from the directories hashtable which acts as a 
1097 # cache, or use opendir, readdir, closedir and store the result 
1098 # in the hashtable.
1099 sub get_directory_contents
1100 {
1101   my $dirname=$_[0];
1102   my $directory;
1103
1104   #print "getting the contents of $dirname\n";
1105
1106   # check for a cached version
1107   $dirname =~ s+/$++;
1108   if ($dirname eq "") {
1109     $dirname=cwd;
1110   }
1111   $directory=$directories{$dirname};
1112   if (defined $directory) {
1113     #print "->@$directory\n";
1114     return $directory;
1115   }
1116   
1117   # Read this directory
1118   if (opendir(DIRECTORY, "$dirname")) {
1119     my @files=readdir DIRECTORY;
1120     closedir(DIRECTORY);
1121     $directory=\@files;
1122   } else {
1123     # Return an empty list
1124     #print "error: cannot open $dirname\n";
1125     my @files;
1126     $directory=\@files;
1127   }
1128   #print "->@$directory\n";
1129   $directories{$dirname}=$directory;
1130   return $directory;
1131 }
1132
1133 ##
1134 # Try to find a file for the specified filename. The attempt is 
1135 # case-insensitive which is why it's not trivial. If a match is 
1136 # found then we return the pathname with the correct case.
1137 sub search_from
1138 {
1139   my $dirname=$_[0];
1140   my $path=$_[1];
1141   my $real_path="";
1142
1143   if ($dirname eq "" or $dirname eq ".") {
1144     $dirname=cwd;
1145   } elsif ($dirname =~ m+^[^/]+) {
1146     $dirname=cwd . "/" . $dirname;
1147   }
1148   if ($dirname !~ m+/$+) {
1149     $dirname.="/";
1150   }
1151
1152   foreach $component (@$path) {
1153     #print "    looking for $component in \"$dirname\"\n";
1154     if ($component eq ".") {
1155       # Pass it as is
1156       $real_path.="./";
1157     } elsif ($component eq "..") {
1158       # Go up one level
1159       $dirname=dirname($dirname) . "/";
1160       $real_path.="../";
1161     } else {
1162       # The file/directory may have been renamed before. Also try to 
1163       # match the renamed file.
1164       my $renamed=$component;
1165       $renamed =~ s/[ \$]/_/g;
1166       if ($renamed eq $component) {
1167         undef $renamed;
1168       }
1169
1170       my $directory=get_directory_contents $dirname;
1171       my $found;
1172       foreach $dentry (@$directory) {
1173         if ($dentry =~ /^$component$/i or
1174             (defined $renamed and $dentry =~ /^$renamed$/i)
1175            ) {
1176           $dirname.="$dentry/";
1177           $real_path.="$dentry/";
1178           $found=1;
1179           last;
1180         }
1181       }
1182       if (!defined $found) {
1183         # Give up
1184         #print "    could not find $component in $dirname\n";
1185         return;
1186       }
1187     }
1188   }
1189   $real_path=~ s+/$++;
1190   #print "    -> found $real_path\n";
1191   return $real_path;
1192 }
1193
1194 ##
1195 # Performs a case-insensitive search for the specified file in the 
1196 # include path.
1197 # $line is the line number that should be referenced when an error occurs
1198 # $filename is the file we are looking for
1199 # $dirname is the directory of the file containing the '#include' directive
1200 #    if '"' was used, it is an empty string otherwise
1201 # $project and $target specify part of the include path
1202 sub get_real_include_name
1203 {
1204   my $line=$_[0];
1205   my $filename=$_[1];
1206   my $dirname=$_[2];
1207   my $project=$_[3];
1208   my $target=$_[4];
1209
1210   if ($filename =~ /^([a-zA-Z]:)?[\/]/ or $filename =~ /^[a-zA-Z]:[\/]?/) {
1211     # This is not a relative path, we cannot make any check
1212     my $warning="path:$filename";
1213     if (!defined $warnings{$warning}) {
1214       $warnings{$warning}="1";
1215       print STDERR "warning: cannot check the case of absolute pathnames:\n";
1216       print STDERR "$line:   $filename\n";
1217     }
1218   } else {
1219     # Here's how we proceed:
1220     # - split the filename we look for into its components
1221     # - then for each directory in the include path
1222     #   - trace the directory components starting from that directory
1223     #   - if we fail to find a match at any point then continue with 
1224     #     the next directory in the include path
1225     #   - otherwise, rejoice, our quest is over.
1226     my @file_components=split /[\/\\]+/, $filename;
1227     #print "  Searching for $filename from @$project[$P_PATH]\n";
1228
1229     my $real_filename;
1230     if ($dirname ne "") {
1231       # This is an 'include ""' -> look in dirname first.
1232       #print "    in $dirname (include \"\")\n";
1233       $real_filename=search_from($dirname,\@file_components);
1234       if (defined $real_filename) {
1235         return $real_filename;
1236       }
1237     }
1238     my $project_settings=@$project[$P_SETTINGS];
1239     foreach $include (@{@$target[$T_INCLUDE_PATH]}, @{@$project_settings[$T_INCLUDE_PATH]}) {
1240       my $dirname=$include;
1241       $dirname=~ s+^-I++;
1242       if (!is_absolute($dirname)) {
1243         $dirname="@$project[$P_PATH]$dirname";
1244       } else {
1245         $dirname=~ s+^\$\(TOPSRCDIR\)/++;
1246         $dirname=~ s+^\$\(SRCDIR\)/+@$project[$P_PATH]+;
1247       }
1248       #print "    in $dirname\n";
1249       $real_filename=search_from("$dirname",\@file_components);
1250       if (defined $real_filename) {
1251         return $real_filename;
1252       }
1253     }
1254     my $dotdotpath=@$project[$P_PATH];
1255     $dotdotpath =~ s/[^\/]+/../g;
1256     foreach $include (@{$global_settings[$T_INCLUDE_PATH]}) {
1257       my $dirname=$include;
1258       $dirname=~ s+^-I++;
1259       $dirname=~ s+^\$\(TOPSRCDIR\)\/++;
1260       $dirname=~ s+^\$\(SRCDIR\)\/+@$project[$P_PATH]+;
1261       #print "    in $dirname  (global setting)\n";
1262       $real_filename=search_from("$dirname",\@file_components);
1263       if (defined $real_filename) {
1264         return $real_filename;
1265       }
1266     }
1267   }
1268   $filename =~ s+\\\\+/+g; # in include ""
1269   $filename =~ s+\\+/+g; # in include <> !
1270   if ($opt_lower_include) {
1271     return lc "$filename";
1272   }
1273   return $filename;
1274 }
1275
1276 sub print_pack
1277 {
1278   my $indent=$_[0];
1279   my $size=$_[1];
1280   my $trailer=$_[2];
1281
1282   if ($size =~ /^(1|2|4|8)$/) {
1283     print FILEO "$indent#include <pshpack$size.h>$trailer";
1284   } else {
1285     print FILEO "$indent/* winemaker:warning: Unknown size \"$size\". Defaulting to 4 */\n";
1286     print FILEO "$indent#include <pshpack4.h>$trailer";
1287   }
1288 }
1289
1290 ##
1291 # 'Parses' a source file and fixes constructs that would not work with 
1292 # Winelib. The parsing is rather simple and not all non-portable features 
1293 # are corrected. The most important feature that is corrected is the case 
1294 # and path separator of '#include' directives. This requires that each 
1295 # source file be associated to a project & target so that the proper 
1296 # include path is used.
1297 # Also note that the include path is relative to the directory in which the 
1298 # compiler is run, i.e. that of the project, not to that of the file.
1299 sub fix_file
1300 {
1301   my $filename=$_[0];
1302   my $project=$_[1];
1303   my $target=$_[2];
1304   $filename="@$project[$P_PATH]$filename";
1305   if (! -e $filename) {
1306     return;
1307   }
1308
1309   my $is_rc=($filename =~ /\.(rc2?|dlg)$/i);
1310   my $dirname=dirname($filename);
1311   my $is_mfc=0;
1312   if (defined $target and (@$target[$T_FLAGS] & $TF_MFC)) {
1313     $is_mfc=1;
1314   }
1315
1316   print "  $filename\n";
1317   #FIXME:assuming that because there is a .bak file, this is what we want is 
1318   #probably flawed. Or is it???
1319   if (! -e "$filename.bak") {
1320     if (!copy("$filename","$filename.bak")) {
1321       print STDERR "error: unable to make a backup of $filename:\n";
1322       print STDERR "       $!\n";
1323       return;
1324     }
1325   }
1326   if (!open(FILEI,"$filename.bak")) {
1327     print STDERR "error: unable to open $filename.bak for reading:\n";
1328     print STDERR "       $!\n";
1329     return;
1330   }
1331   if (!open(FILEO,">$filename")) {
1332     print STDERR "error: unable to open $filename for writing:\n";
1333     print STDERR "       $!\n";
1334     return;
1335   }
1336   my $line=0;
1337   my $modified=0;
1338   my $rc_block_depth=0;
1339   my $rc_textinclude_state=0;
1340   my @pack_stack;
1341   while (<FILEI>) {
1342     # Remove any trailing CtrlZ, which isn't strictly in the file
1343     if (/\x1A/) {
1344       s/\x1A//;
1345       last if (/^$/)
1346     }
1347     $line++;
1348     s/\r\n$/\n/;
1349     if (!/\n$/) {
1350       # Make sure all files are '\n' terminated
1351       $_ .= "\n";
1352     }
1353     if ($is_rc and !$is_mfc and /^(\s*)(\#\s*include\s*)\"afxres\.h\"/) {
1354       # VC6 automatically includes 'afxres.h', an MFC specific header, in 
1355       # the RC files it generates (even in non-MFC projects). So we replace 
1356       # it with 'winres.h' its very close standard cousin so that non MFC 
1357       # projects can compile in Wine without the MFC sources.
1358       my $warning="mfc:afxres.h";
1359       if (!defined $warnings{$warning}) {
1360         $warnings{$warning}="1";
1361         print STDERR "warning: In non-MFC projects, winemaker replaces the MFC specific header 'afxres.h' with 'winres.h'\n";
1362         print STDERR "warning: the above warning is issued only once\n";
1363       }
1364       print FILEO "$1/* winemaker: $2\"afxres.h\" */\n";
1365       print FILEO "$1/* winemaker:warning: 'afxres.h' is an MFC specific header. Replacing it with 'winres.h' */\n";
1366       print FILEO "$1$2\"winres.h\"$'";
1367       $modified=1;
1368
1369     } elsif (/^(\s*\#\s*include\s*)([\"<])([^\"]+)([\">])/) {
1370       my $from_file=($2 eq "<"?"":$dirname);
1371       my $real_include_name=get_real_include_name($line,$3,$from_file,$project,$target);
1372       print FILEO "$1$2$real_include_name$4$'";
1373       $modified|=($real_include_name ne $3);
1374
1375     } elsif (s/^(\s*)(\#\s*pragma\s+pack\s*\(\s*)//) {
1376       # Pragma pack handling
1377       #
1378       # pack_stack is an array of references describing the stack of 
1379       # pack directives currently in effect. Each directive if described 
1380       # by a reference to an array containing:
1381       # - "push" for pack(push,...) directives, "" otherwise
1382       # - the directive's identifier at index 1
1383       # - the directive's alignement value at index 2
1384       #
1385       # Don't believe a word of what the documentation says: it's all wrong.
1386       # The code below is based on the actual behavior of Visual C/C++ 6.
1387       my $pack_indent=$1;
1388       my $pack_header=$2;
1389       if (/^(\))/) {
1390         # pragma pack()
1391         # Pushes the default stack alignment
1392         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1393         print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n";
1394         print_pack($pack_indent,4,$');
1395         push @pack_stack, [ "", "", 4 ];
1396
1397       } elsif (/^(pop\s*(,\s*\d+\s*)?\))/) {
1398         # pragma pack(pop)
1399         # pragma pack(pop,n)
1400         # Goes up the stack until it finds a pack(push,...), and pops it
1401         # Ignores any pack(n) entry
1402         # Issues a warning if the pack is of the form pack(push,label)
1403         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1404         my $pack_comment=$';
1405         $pack_comment =~ s/^\s*//;
1406         if ($pack_comment ne "") {
1407           print FILEO "$pack_indent$pack_comment";
1408         }
1409         while (1) {
1410           my $alignment=pop @pack_stack;
1411           if (!defined $alignment) {
1412             print FILEO "$pack_indent/* winemaker:warning: No pack(push,...) found. All the stack has been popped */\n";
1413             last;
1414           }
1415           if (@$alignment[1]) {
1416             print FILEO "$pack_indent/* winemaker:warning: Anonymous pop of pack(push,@$alignment[1]) (@$alignment[2]) */\n";
1417           }
1418           print FILEO "$pack_indent#include <poppack.h>\n";
1419           if (@$alignment[0]) {
1420             last;
1421           }
1422         }
1423
1424       } elsif (/^(pop\s*,\s*(\w+)\s*(,\s*\d+\s*)?\))/) {
1425         # pragma pack(pop,label[,n])
1426         # Goes up the stack until finding a pack(push,...) and pops it.
1427         # 'n', if specified, is ignored.
1428         # Ignores any pack(n) entry
1429         # Issues a warning if the label of the pack does not match,
1430         # or if it is in fact a pack(push,n)
1431         my $label=$2;
1432         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1433         my $pack_comment=$';
1434         $pack_comment =~ s/^\s*//;
1435         if ($pack_comment ne "") {
1436           print FILEO "$pack_indent$pack_comment";
1437         }
1438         while (1) {
1439           my $alignment=pop @pack_stack;
1440           if (!defined $alignment) {
1441             print FILEO "$pack_indent/* winemaker:warning: No pack(push,$label) found. All the stack has been popped */\n";
1442             last;
1443           }
1444           if (@$alignment[1] and @$alignment[1] ne $label) {
1445             print FILEO "$pack_indent/* winemaker:warning: Push/pop mismatch: \"@$alignment[1]\" (@$alignment[2]) != \"$label\" */\n";
1446           }
1447           print FILEO "$pack_indent#include <poppack.h>\n";
1448           if (@$alignment[0]) {
1449             last;
1450           }
1451         }
1452
1453       } elsif (/^(push\s*\))/) {
1454         # pragma pack(push)
1455         # Push the current alignment
1456         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1457         if (@pack_stack > 0) {
1458           my $alignment=$pack_stack[$#pack_stack];
1459           print_pack($pack_indent,@$alignment[2],$');
1460           push @pack_stack, [ "push", "", @$alignment[2] ];
1461         } else {
1462           print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n";
1463           print_pack($pack_indent,4,$');
1464           push @pack_stack, [ "push", "", 4 ];
1465         }
1466
1467       } elsif (/^((push\s*,\s*)?(\d+)\s*\))/) {
1468         # pragma pack([push,]n)
1469         # Push new alignment n
1470         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1471         print_pack($pack_indent,$3,"$'");
1472         push @pack_stack, [ ($2 ? "push" : ""), "", $3 ];
1473
1474       } elsif (/^((\w+)\s*\))/) {
1475         # pragma pack(label)
1476         # label must in fact be a macro that resolves to an integer
1477         # Then behaves like 'pragma pack(n)'
1478         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1479         print FILEO "$pack_indent/* winemaker:warning: Assuming $2 == 4 */\n";
1480         print_pack($pack_indent,4,$');
1481         push @pack_stack, [ "", "", 4 ];
1482
1483       } elsif (/^(push\s*,\s*(\w+)\s*(,\s*(\d+)\s*)?\))/) {
1484         # pragma pack(push,label[,n])
1485         # Pushes a new label on the stack. It is possible to push the same
1486         # label multiple times. If 'n' is omitted then the alignment is 
1487         # unchanged. Otherwise it becomes 'n'.
1488         print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n";
1489         my $size;
1490         if (defined $4) {
1491           $size=$4;
1492         } elsif (@pack_stack > 0) {
1493           my $alignment=$pack_stack[$#pack_stack];
1494           $size=@$alignment[2];
1495         } else {
1496           print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n";
1497           $size=4;
1498         }
1499         print_pack($pack_indent,$size,$');
1500         push @pack_stack, [ "push", $2, $size ];
1501
1502       } else {
1503         # pragma pack(???               -> What's that?
1504         print FILEO "$pack_indent/* winemaker:warning: Unknown type of pragma pack directive */\n";
1505         print FILEO "$pack_indent$pack_header$_";
1506
1507       }
1508       $modified=1;
1509
1510     } elsif ($is_rc) {
1511       if ($rc_block_depth == 0 and /^(\w+\s+(BITMAP|CURSOR|FONT|FONTDIR|ICON|MESSAGETABLE|TEXT|RTF)\s+((DISCARDABLE|FIXED|IMPURE|LOADONCALL|MOVEABLE|PRELOAD|PURE)\s+)*)([\"<]?)([^\">\r\n]+)([\">]?)/) {
1512         my $from_file=($5 eq "<"?"":$dirname);
1513         my $real_include_name=get_real_include_name($line,$6,$from_file,$project,$target);
1514         print FILEO "$1$5$real_include_name$7$'";
1515         $modified|=($real_include_name ne $6);
1516
1517       } elsif (/^(\s*RCINCLUDE\s*)([\"<]?)([^\">\r\n]+)([\">]?)/) {
1518         my $from_file=($2 eq "<"?"":$dirname);
1519         my $real_include_name=get_real_include_name($line,$3,$from_file,$project,$target);
1520         print FILEO "$1$2$real_include_name$4$'";
1521         $modified|=($real_include_name ne $3);
1522
1523       } elsif ($is_rc and !$is_mfc and $rc_block_depth == 0 and /^\s*\d+\s+TEXTINCLUDE\s*/) {
1524         $rc_textinclude_state=1;
1525         print FILEO;
1526
1527       } elsif ($rc_textinclude_state == 3 and /^(\s*\"\#\s*include\s*\"\")afxres\.h(\"\"\\r\\n\")/) {
1528         print FILEO "$1winres.h$2$'";
1529         $modified=1;
1530
1531       } elsif (/^\s*BEGIN(\W.*)?$/) {
1532         $rc_textinclude_state|=2;
1533         $rc_block_depth++;
1534         print FILEO;
1535
1536       } elsif (/^\s*END(\W.*)?$/) {
1537         $rc_textinclude_state=0;
1538         if ($rc_block_depth>0) {
1539           $rc_block_depth--;
1540         }
1541         print FILEO;
1542
1543       } else {
1544         print FILEO;
1545       }
1546
1547     } else {
1548       print FILEO;
1549     }
1550   }
1551
1552   close(FILEI);
1553   close(FILEO);
1554   if ($opt_backup == 0 or $modified == 0) {
1555     if (!unlink("$filename.bak")) {
1556       print STDERR "error: unable to delete $filename.bak:\n";
1557       print STDERR "       $!\n";
1558     }
1559   }
1560 }
1561
1562 ##
1563 # Analyzes each source file in turn to find and correct issues 
1564 # that would cause it not to compile.
1565 sub fix_source
1566 {
1567   print "Fixing the source files...\n";
1568   foreach $project (@projects) {
1569     foreach $target (@$project[$P_SETTINGS],@{@$project[$P_TARGETS]}) {
1570       if (@$target[$T_FLAGS] & $TF_WRAPPER) {
1571         next;
1572       }
1573       foreach $source (@{@$target[$T_SOURCES_C]}, @{@$target[$T_SOURCES_CXX]}, @{@$target[$T_SOURCES_RC]}, @{@$target[$T_SOURCES_MISC]}) {
1574         fix_file($source,$project,$target);
1575       }
1576     }
1577   }
1578 }
1579
1580
1581
1582 #####
1583 #
1584 # File generation
1585 #
1586 #####
1587
1588 ##
1589 # Generates a target's .spec file
1590 sub generate_spec_file
1591 {
1592   if ($opt_no_generated_specs) {
1593     return;
1594   }
1595   my $path=$_[0];
1596   my $target=$_[1];
1597   my $project_settings=$_[2];
1598
1599   my $basename=@$target[$T_NAME];
1600   $basename =~ s+\.so$++;
1601   if (@$target[$T_FLAGS] & $TF_WRAP) {
1602     $basename =~ s+^lib++;
1603   } elsif (@$target[$T_FLAGS] & $TF_WRAPPER) {
1604     $basename.="_wrapper";
1605   }
1606
1607   if (!open(FILEO,">$path$basename.spec")) {
1608     print STDERR "error: could not open \"$path$basename.spec\" for writing\n";
1609     print STDERR "       $!\n";
1610     return;
1611   }
1612
1613   my $module=$basename;
1614   $module =~ s+^lib++;
1615   $module=canonize($module);
1616   print FILEO "name    $module\n";
1617   print FILEO "type    win32\n";
1618   if (@$target[$T_TYPE] == $TT_GUIEXE) {
1619     print FILEO "mode    guiexe\n";
1620   } elsif (@$target[$T_TYPE] == $TT_CUIEXE) {
1621     print FILEO "mode    cuiexe\n";
1622   } else {
1623     print FILEO "mode    dll\n";
1624   }
1625   if (defined @$target[$T_INIT] and ((@$target[$T_FLAGS] & $TF_WRAP) == 0)) {
1626     print FILEO "init    @$target[$T_INIT]\n";
1627   }
1628   if (@{@$target[$T_SOURCES_RC]} > 0) {
1629     if (@{@$target[$T_SOURCES_RC]} > 1) {
1630       print STDERR "warning: the target $basename has more than one RC file. Modify the Makefile.in to remove redundant RC files, and fix the spec file\n";
1631     }
1632     my $rcname=@{@$target[$T_SOURCES_RC]}[0];
1633     $rcname =~ s+\.rc$++i;
1634     $rcname =~ s+([^/\w])+\\$1+g;
1635     print FILEO "rsrc    $rcname.res\n";
1636   }
1637   print FILEO "\n";
1638   my %dlls;
1639   foreach $dll (@{$global_settings[$T_DLLS]}) {
1640     if (!defined $dlls{$dll}) {
1641       print FILEO "import $dll\n";
1642       $dlls{$dll}=1;
1643     }
1644   }
1645   if (defined $project_settings) {
1646     foreach $dll (@{@$project_settings[$T_DLLS]}) {
1647       if (!defined $dlls{$dll}) {
1648         print FILEO "import $dll\n";
1649         $dlls{$dll}=1;
1650       }
1651     }
1652   }
1653   foreach $dll (@{@$target[$T_DLLS]}) {
1654     if (!defined $dlls{$dll}) {
1655       print FILEO "import $dll\n";
1656       $dlls{$dll}=1;
1657     }
1658   }
1659
1660   # Don't forget to export the 'Main' function for wrapped executables, 
1661   # except for MFC ones!
1662   if (@$target[$T_FLAGS] == $TF_WRAP) {
1663     if (@$target[$T_TYPE] == $TT_GUIEXE) {
1664       print FILEO "\n@ stdcall @$target[$T_INIT](long long ptr long) @$target[$T_INIT]\n";
1665     } elsif (@$target[$T_TYPE] == $TT_CUIEXE) {
1666       print FILEO "\n@ stdcall @$target[$T_INIT](long ptr ptr) @$target[$T_INIT]\n";
1667     } else {
1668       print FILEO "\n@ stdcall @$target[$T_INIT](ptr long ptr) @$target[$T_INIT]\n";
1669     }
1670   }
1671
1672   close(FILEO);
1673 }
1674
1675 ##
1676 # Generates a target's wrapper file
1677 sub generate_wrapper_file
1678 {
1679   my $path=$_[0];
1680   my $target=$_[1];
1681
1682   if (!defined $templates{"wrapper.c"}) {
1683     print STDERR "winemaker: internal error: No template called 'wrapper.c'\n";
1684     return;
1685   }
1686
1687   if (!open(FILEO,">$path@$target[$T_NAME]_wrapper.c")) {
1688     print STDERR "error: unable to open \"$path$basename.c\" for writing:\n";
1689     print STDERR "       $!\n";
1690     return;
1691   }
1692   my $app_name="\"@$target[$T_NAME]\"";
1693   my $app_type=(@$target[$T_TYPE]==$TT_GUIEXE?"GUIEXE":"CUIEXE");
1694   my $app_init=(@$target[$T_TYPE]==$TT_GUIEXE?"\"WinMain\"":"\"main\"");
1695   my $app_mfc=(@$target[$T_FLAGS] & $TF_MFC?"\"mfc\"":NULL);
1696   foreach $line (@{$templates{"wrapper.c"}}) {
1697     my $l=$line;
1698     $l =~ s/\#\#WINEMAKER_APP_NAME\#\#/$app_name/;
1699     $l =~ s/\#\#WINEMAKER_APP_TYPE\#\#/$app_type/;
1700     $l =~ s/\#\#WINEMAKER_APP_INIT\#\#/$app_init/;
1701     $l =~ s/\#\#WINEMAKER_APP_MFC\#\#/$app_mfc/;
1702     print FILEO $l;
1703   }
1704   close(FILEO);
1705 }
1706
1707 ##
1708 # A convenience function to generate all the lists (defines, 
1709 # C sources, C++ source, etc.) in the Makefile
1710 sub generate_list
1711 {
1712   my $name=$_[0];
1713   my $last=$_[1];
1714   my $list=$_[2];
1715   my $data=$_[3];
1716   my $first=$name;
1717
1718   if ($name) {
1719     printf FILEO "%-22s=",$name;
1720   }
1721   if (defined $list) {
1722     foreach $item (@$list) {
1723       my $value;
1724       if (defined $data) {
1725         $value=&$data($item);
1726       } else {
1727         $value=$item;
1728       }
1729       if ($value ne "") {
1730         if ($first) {
1731           print FILEO " $value";
1732           $first=0;
1733         } else {
1734           print FILEO " \\\n\t\t\t$value";
1735         }
1736       }
1737     }
1738   }
1739   if ($last) {
1740     print FILEO "\n";
1741   }
1742 }
1743
1744 ##
1745 # Generates a project's Makefile.in and all the target files
1746 sub generate_project_files
1747 {
1748   my $project=$_[0];
1749   my $project_settings=@$project[$P_SETTINGS];
1750   my @dll_list=();
1751   my @exe_list=();
1752
1753   # Then sort the targets and separate the libraries from the programs
1754   foreach $target (sort { @$a[$T_NAME] cmp @$b[$T_NAME] } @{@$project[$P_TARGETS]}) {
1755     if (@$target[$T_TYPE] == $TT_DLL) {
1756       push @dll_list,$target;
1757     } else {
1758       push @exe_list,$target;
1759     }
1760   }
1761   @$project[$P_TARGETS]=[];
1762   push @{@$project[$P_TARGETS]}, @dll_list;
1763   push @{@$project[$P_TARGETS]}, @exe_list;
1764
1765   if (!open(FILEO,">@$project[$P_PATH]Makefile.in")) {
1766     print STDERR "error: could not open \"@$project[$P_PATH]/Makefile.in\" for writing\n";
1767     print STDERR "       $!\n";
1768     return;
1769   }
1770
1771   print FILEO "### Generated by Winemaker\n";
1772   print FILEO "\n\n";
1773
1774   print FILEO "### Generic autoconf variables\n\n";
1775   generate_list("TOPSRCDIR",1,[ "\@top_srcdir\@" ]);
1776   generate_list("TOPOBJDIR",1,[ "." ]);
1777   generate_list("SRCDIR",1,[ "\@srcdir\@" ]);
1778   generate_list("VPATH",1,[ "\@srcdir\@" ]);
1779   print FILEO "\n";
1780   if (@$project[$P_PATH] eq "") {
1781     # This is the main project. It is also responsible for recursively 
1782     # calling the other projects
1783     generate_list("SUBDIRS",1,\@projects,sub 
1784                   {
1785                     if ($_[0] != \@main_project) {
1786                       my $subdir=@{$_[0]}[$P_PATH];
1787                       $subdir =~ s+/$++;
1788                       return $subdir;
1789                     }
1790                     # Eliminating the main project by returning undefined!
1791                   });
1792   }
1793   if (@{@$project[$P_TARGETS]} > 0) {
1794     generate_list("DLLS",1,\@dll_list,sub
1795                   {
1796                     return @{$_[0]}[$T_NAME];
1797                   });
1798     generate_list("EXES",1,\@exe_list,sub
1799                   {
1800                     return "@{$_[0]}[$T_NAME]";
1801                   });
1802     print FILEO "\n\n\n";
1803
1804     print FILEO "### Global settings\n\n";
1805     # Make it so that the project-wide settings override the global settings
1806     generate_list("DEFINES",0,@$project_settings[$T_DEFINES]);
1807     generate_list("",1,$global_settings[$T_DEFINES]);
1808     generate_list("INCLUDE_PATH",$no_extra,@$project_settings[$T_INCLUDE_PATH]);
1809     generate_list("",1,$global_settings[$T_INCLUDE_PATH],sub
1810                   {
1811                     if ($_[0] !~ /^-I/ or is_absolute($')) {
1812                       return "$_[0]";
1813                     }
1814                     return "-I\$(TOPSRCDIR)/$'";
1815                   });
1816     generate_list("DLL_PATH",$no_extra,@$project_settings[$T_DLL_PATH]);
1817     generate_list("",1,$global_settings[$T_DLL_PATH],sub
1818                   {
1819                     if ($_[0] !~ /^-L/ or is_absolute($')) {
1820                       return "$_[0]";
1821                     }
1822                     return "-L\$(TOPSRCDIR)/$'";
1823                   });
1824     generate_list("LIBRARY_PATH",$no_extra,@$project_settings[$T_LIBRARY_PATH]);
1825     generate_list("",1,$global_settings[$T_LIBRARY_PATH],sub
1826                   {
1827                     if ($_[0] !~ /^-L/ or is_absolute($')) {
1828                       return "$_[0]";
1829                     }
1830                     return "-L\$(TOPSRCDIR)/$'";
1831                   });
1832     generate_list("LIBRARIES",$no_extra,@$project_settings[$T_LIBRARIES]);
1833     generate_list("",1,$global_settings[$T_LIBRARIES]);
1834     print FILEO "\n\n";
1835
1836     my $extra_source_count=@{@$project_settings[$T_SOURCES_C]}+
1837                            @{@$project_settings[$T_SOURCES_CXX]}+
1838                            @{@$project_settings[$T_SOURCES_RC]};
1839     my $no_extra=($extra_source_count == 0);
1840     if (!$no_extra) {
1841       print FILEO "### Extra source lists\n\n";
1842       generate_list("EXTRA_C_SRCS",1,@$project_settings[$T_SOURCES_C]);
1843       generate_list("EXTRA_CXX_SRCS",1,@$project_settings[$T_SOURCES_CXX]);
1844       generate_list("EXTRA_RC_SRCS",1,@$project_settings[$T_SOURCES_RC]);
1845       print FILEO "\n";
1846       generate_list("EXTRA_OBJS",1,["\$(EXTRA_C_SRCS:.c=.o)","\$(EXTRA_CXX_SRCS:.cpp=.o)"]);
1847       print FILEO "\n\n\n";
1848     }
1849
1850     # Iterate over all the targets...
1851     foreach $target (@{@$project[$P_TARGETS]}) {
1852       print FILEO "### @$target[$T_NAME] sources and settings\n\n";
1853       my $canon=canonize("@$target[$T_NAME]");
1854       $canon =~ s+_so$++;
1855       generate_list("${canon}_C_SRCS",1,@$target[$T_SOURCES_C]);
1856       generate_list("${canon}_CXX_SRCS",1,@$target[$T_SOURCES_CXX]);
1857       generate_list("${canon}_RC_SRCS",1,@$target[$T_SOURCES_RC]);
1858       my $basename=@$target[$T_NAME];
1859       $basename =~ s+\.so$++;
1860       if (@$target[$T_FLAGS] & $TF_WRAP) {
1861         $basename =~ s+^lib++;
1862       } elsif (@$target[$T_FLAGS] & $TF_WRAPPER) {
1863         $basename.="_wrapper";
1864       }
1865       generate_list("${canon}_SPEC_SRCS",1,[ "$basename.spec" ]);
1866       generate_list("${canon}_DLL_PATH",1,@$target[$T_DLL_PATH]);
1867       generate_list("${canon}_LIBRARY_PATH",1,@$target[$T_LIBRARY_PATH]);
1868       generate_list("${canon}_LIBRARIES",1,@$target[$T_LIBRARIES]);
1869       generate_list("${canon}_DEPENDS",1,@$target[$T_DEPENDS]);
1870       print FILEO "\n";
1871       generate_list("${canon}_OBJS",1,["\$(${canon}_C_SRCS:.c=.o)","\$(${canon}_CXX_SRCS:.cpp=.o)","\$(EXTRA_OBJS)"]);
1872       print FILEO "\n\n\n";
1873     }
1874     print FILEO "### Global source lists\n\n";
1875     generate_list("C_SRCS",$no_extra,@$project[$P_TARGETS],sub
1876                   {
1877                     my $canon=canonize(@{$_[0]}[$T_NAME]);
1878                     $canon =~ s+_so$++;
1879                     return "\$(${canon}_C_SRCS)";
1880                   });
1881     if (!$no_extra) {
1882       generate_list("",1,[ "\$(EXTRA_C_SRCS)" ]);
1883     }
1884     generate_list("CXX_SRCS",$no_extra,@$project[$P_TARGETS],sub
1885                   {
1886                     my $canon=canonize(@{$_[0]}[$T_NAME]);
1887                     $canon =~ s+_so$++;
1888                     return "\$(${canon}_CXX_SRCS)";
1889                   });
1890     if (!$no_extra) {
1891       generate_list("",1,[ "\$(EXTRA_CXX_SRCS)" ]);
1892     }
1893     generate_list("RC_SRCS",$no_extra,@$project[$P_TARGETS],sub
1894                   {
1895                     my $canon=canonize(@{$_[0]}[$T_NAME]);
1896                     $canon =~ s+_so$++;
1897                     return "\$(${canon}_RC_SRCS)";
1898                   });
1899     if (!$no_extra) {
1900       generate_list("",1,[ "\$(EXTRA_RC_SRCS)" ]);
1901     }
1902     generate_list("SPEC_SRCS",1,@$project[$P_TARGETS],sub
1903                   {
1904                     my $canon=canonize(@{$_[0]}[$T_NAME]);
1905                     $canon =~ s+_so$++;
1906                     return "\$(${canon}_SPEC_SRCS)";
1907                   });
1908   }
1909   print FILEO "\n\n\n";
1910
1911   print FILEO "### Generic autoconf targets\n\n";
1912   print FILEO "all:";
1913   if (@$project[$P_PATH] eq "") {
1914     print FILEO " \$(SUBDIRS)";
1915   }
1916   if (@{@$project[$P_TARGETS]} > 0) {
1917     print FILEO " \$(DLLS) \$(EXES:%=%.so)";
1918   }
1919   print FILEO "\n\n";
1920   print FILEO "\@MAKE_RULES\@\n";
1921   print FILEO "\n";
1922   print FILEO "install::\n";
1923   if (@$project[$P_PATH] eq "") {
1924     # This is the main project. It is also responsible for recursively 
1925     # calling the other projects
1926     print FILEO "\t_list=\"\$(SUBDIRS)\"; for i in \$\$_list; do (cd \$\$i; \$(MAKE) install) || exit 1; done\n";
1927   }
1928   if (@{@$project[$P_TARGETS]} > 0) {
1929     print FILEO "\t_list=\"\$(EXES) \$(EXES:%=%.so)\"; for i in \$\$_list; do \$(INSTALL_PROGRAM) \$\$i \$(bindir); done\n";
1930     print FILEO "\t_list=\"\$(DLLS)\"; for i in \$\$_list; do \$(INSTALL_PROGRAM) \$\$i \$(libdir); done\n";
1931   }
1932   print FILEO "\n";
1933   print FILEO "uninstall::\n";
1934   if (@$project[$P_PATH] eq "") {
1935     # This is the main project. It is also responsible for recursively 
1936     # calling the other projects
1937     print FILEO "\t_list=\"\$(SUBDIRS)\"; for i in \$\$_list; do (cd \$\$i; \$(MAKE) uninstall) || exit 1; done\n";
1938   }
1939   if (@{@$project[$P_TARGETS]} > 0) {
1940     print FILEO "\t_list=\"\$(EXES) \$(EXES:%=%.so)\"; for i in \$\$_list; do \$(RM) \$(bindir)/\$\$i;done\n";
1941     print FILEO "\t_list=\"\$(DLLS)\"; for i in \$\$_list; do \$(RM) \$(libdir)/\$\$i;done\n";
1942   }
1943   print FILEO "\n\n\n";
1944
1945   if (@{@$project[$P_TARGETS]} > 0) {
1946     print FILEO "### Target specific build rules\n\n";
1947     foreach $target (@{@$project[$P_TARGETS]}) {
1948       my $canon=canonize("@$target[$T_NAME]");
1949       $canon =~ s/_so$//;
1950       print FILEO "\$(${canon}_SPEC_SRCS:.spec=.tmp.o): \$(${canon}_OBJS)\n";
1951       print FILEO "\t\$(LDCOMBINE) \$(${canon}_OBJS) -o \$\@\n";
1952       print FILEO "\t-\$(STRIP) \$(STRIPFLAGS) \$\@\n";
1953       print FILEO "\n";
1954       print FILEO "\$(${canon}_SPEC_SRCS:.spec=.spec.c): \$(${canon}_SPEC_SRCS) \$(${canon}_SPEC_SRCS:.spec=.tmp.o) \$(${canon}_RC_SRCS:.rc=.res)\n";
1955       print FILEO "\t\$(LD_PATH) \$(WINEBUILD) -fPIC \$(${canon}_DLL_PATH) \$(WINE_DLL_PATH) -sym \$(${canon}_SPEC_SRCS:.spec=.tmp.o) -o \$\@ -spec \$(SRCDIR)/\$(${canon}_SPEC_SRCS)\n";
1956       print FILEO "\n";
1957       my $t_name=@$target[$T_NAME];
1958       if (@$target[$T_TYPE]!=$TT_DLL) {
1959         $t_name.=".so";
1960       }
1961       print FILEO "$t_name: \$(${canon}_SPEC_SRCS:.spec=.spec.o) \$(${canon}_OBJS) \$(${canon}_DEPENDS) \n";
1962       if (@{@$target[$T_SOURCES_CXX]} > 0 or @{@$project_settings[$T_SOURCES_CXX]} > 0) {
1963         print FILEO "\t\$(LDXXSHARED)";
1964       } else {
1965         print FILEO "\t\$(LDSHARED)";
1966       }
1967       print FILEO " \$(LDDLLFLAGS) -o \$\@ \$(${canon}_OBJS) \$(${canon}_SPEC_SRCS:.spec=.spec.o) \$(${canon}_LIBRARY_PATH) \$(${canon}_LIBRARIES:%=-l%) \$(DLL_LINK) \$(LIBS)\n";
1968       if (@$target[$T_TYPE] ne $TT_DLL) {
1969         print FILEO "\ttest -f @$target[$T_NAME] || \$(LN_S) \$(WINE) @$target[$T_NAME]\n";
1970       }
1971       print FILEO "\n\n";
1972     }
1973   }
1974   close(FILEO);
1975
1976   foreach $target (@{@$project[$P_TARGETS]}) {
1977     generate_spec_file(@$project[$P_PATH],$target,$project_settings);
1978     if (@$target[$T_FLAGS] & $TF_WRAPPER) {
1979       generate_wrapper_file(@$project[$P_PATH],$target);
1980     }
1981   }
1982 }
1983
1984 ##
1985 # Perform the replacements in the template configure files
1986 # Return 1 for success, 0 for failure
1987 sub generate_configure
1988 {
1989   my $filename=$_[0];
1990   my $a_source_file=$_[1];
1991
1992   if (!defined $templates{$filename}) {
1993     if ($filename ne "configure") {
1994       print STDERR "winemaker: internal error: No template called '$filename'\n";
1995     }
1996     return 0;
1997   }
1998
1999   if (!open(FILEO,">$filename")) {
2000     print STDERR "error: unable to open \"$filename\" for writing:\n";
2001     print STDERR "       $!\n";
2002     return 0;
2003   }
2004   foreach $line (@{$templates{$filename}}) {
2005     if ($line =~ /^\#\#WINEMAKER_PROJECTS\#\#$/) {
2006       foreach $project (@projects) {
2007         print FILEO "@$project[$P_PATH]Makefile\n";
2008       }
2009     } else {
2010       $line =~ s+\#\#WINEMAKER_SOURCE\#\#+$a_source_file+;
2011       $line =~ s+\#\#WINEMAKER_NEEDS_MFC\#\#+$needs_mfc+;
2012       print FILEO $line;
2013     }
2014   }
2015   close(FILEO);
2016   return 1;
2017 }
2018
2019 sub generate_generic
2020 {
2021   my $filename=$_[0];
2022
2023   if (!defined $templates{$filename}) {
2024     print STDERR "winemaker: internal error: No template called '$filename'\n";
2025     return;
2026   }
2027   if (!open(FILEO,">$filename")) {
2028     print STDERR "error: unable to open \"$filename\" for writing:\n";
2029     print STDERR "       $!\n";
2030     return;
2031   }
2032   foreach $line (@{$templates{$filename}}) {
2033     print FILEO $line;
2034   }
2035   close(FILEO);
2036 }
2037
2038 ##
2039 # Generates the global files:
2040 # configure
2041 # configure.in
2042 # Make.rules.in
2043 sub generate_global_files
2044 {
2045   generate_generic("Make.rules.in");
2046
2047   # Get the name of a source file for configure.in
2048   my $a_source_file;
2049   search_a_file: foreach $project (@projects) {
2050     foreach $target (@{@$project[$P_TARGETS]}, @$project[$P_SETTINGS]) {
2051       $a_source_file=@{@$target[$T_SOURCES_C]}[0];
2052       if (!defined $a_source_file) {
2053         $a_source_file=@{@$target[$T_SOURCES_CXX]}[0];
2054       }
2055       if (!defined $a_source_file) {
2056         $a_source_file=@{@$target[$T_SOURCES_RC]}[0];
2057       }
2058       if (defined $a_source_file) {
2059         $a_source_file="@$project[$P_PATH]$a_source_file";
2060         last search_a_file;
2061       }
2062     }
2063   }
2064   if (!defined $a_source_file) {
2065     $a_source_file="Makefile.in";
2066   }
2067
2068   generate_configure("configure.in",$a_source_file);
2069   unlink("configure");
2070   if (generate_configure("configure",$a_source_file) == 0) {
2071     system("autoconf");
2072   }
2073   # Add execute permission to configure for whoever has the right to read it
2074   my @st=stat("configure");
2075   if (@st) {
2076     my $mode=$st[2];
2077     $mode|=($mode & 0444) >>2;
2078     chmod($mode,"configure");
2079   } else {
2080     print "warning: could not generate the configure script. You need to run autoconf\n";
2081   }
2082 }
2083
2084 ##
2085
2086 sub generate_read_templates
2087 {
2088   my $file;
2089
2090   while (<DATA>) {
2091     if (/^--- ((\w\.?)+) ---$/) {
2092       my $filename=$1;
2093       if (defined $templates{$filename}) {
2094         print STDERR "winemaker: internal error: There is more than one template for $filename\n";
2095         undef $file;
2096       } else {
2097         $file=[];
2098         $templates{$filename}=$file;
2099       }
2100     } elsif (defined $file) {
2101       push @$file, $_;
2102     }
2103   }
2104 }
2105
2106 ##
2107 # This is where we finally generate files. In fact this method does not 
2108 # do anything itself but calls the methods that do the actual work.
2109 sub generate
2110 {
2111   print "Generating project files...\n";
2112   generate_read_templates();
2113   generate_global_files();
2114
2115   foreach $project (@projects) {
2116     my $path=@$project[$P_PATH];
2117     if ($path eq "") {
2118       $path=".";
2119     } else {
2120       $path =~ s+/$++;
2121     }
2122     print "  $path\n";
2123     generate_project_files($project);
2124   }
2125 }
2126
2127
2128
2129 #####
2130 #
2131 # Option defaults
2132 #
2133 #####
2134
2135 $opt_backup=1;
2136 $opt_lower=$OPT_LOWER_UPPERCASE;
2137 $opt_lower_include=1;
2138
2139 # $opt_work_dir=<undefined>
2140 # $opt_single_target=<undefined>
2141 $opt_target_type=$TT_GUIEXE;
2142 $opt_flags=0;
2143 $opt_is_interactive=$OPT_ASK_NO;
2144 $opt_ask_project_options=$OPT_ASK_NO;
2145 $opt_ask_target_options=$OPT_ASK_NO;
2146 $opt_no_generated_files=0;
2147 $opt_no_generated_specs=0;
2148 $opt_no_source_fix=0;
2149 $opt_no_banner=0;
2150
2151
2152
2153 #####
2154 #
2155 # Main
2156 #
2157 #####
2158
2159 sub print_banner
2160 {
2161   print "Winemaker $version\n";
2162   print "Copyright 2000 Francois Gouget <fgouget\@codeweavers.com> for CodeWeavers\n";
2163 }
2164
2165 sub usage
2166 {
2167   print_banner();
2168   print STDERR "Usage: winemaker [--nobanner] [--backup|--nobackup] [--nosource-fix]\n";
2169   print STDERR "                 [--lower-none|--lower-all|--lower-uppercase]\n";
2170   print STDERR "                 [--lower-include|--nolower-include]\n";
2171   print STDERR "                 [--guiexe|--windows|--cuiexe|--console|--dll]\n";
2172   print STDERR "                 [--wrap|--nowrap] [--mfc|--nomfc]\n";
2173   print STDERR "                 [-Dmacro[=defn]] [-Idir] [-Pdir] [-idll] [-Ldir] [-llibrary]\n";
2174   print STDERR "                 [--interactive] [--single-target name]\n";
2175   print STDERR "                 [--generated-files|--nogenerated-files] [--nogenerated-specs]\n";
2176   print STDERR "                 work_directory\n";
2177   print STDERR "\nWinemaker is designed to recursively convert all the Windows sources found in\n";
2178   print STDERR "the specified directory so that they can be compiled with Winelib. During this\n";
2179   print STDERR "process it will modify and rename some of the files in that directory.\n";
2180   print STDERR "\tPlease read the manual page before use.\n";
2181   exit (2);
2182 }
2183
2184
2185 project_init(\@main_project,"");
2186
2187 while (@ARGV>0) {
2188   my $arg=shift @ARGV;
2189   # General options
2190   if ($arg eq "--nobanner") {
2191     $opt_no_banner=1;
2192   } elsif ($arg eq "--backup") {
2193     $opt_backup=1;
2194   } elsif ($arg eq "--nobackup") {
2195     $opt_backup=0;
2196   } elsif ($arg eq "--single-target") {
2197     $opt_single_target=shift @ARGV;
2198   } elsif ($arg eq "--lower-none") {
2199     $opt_lower=$OPT_LOWER_NONE;
2200   } elsif ($arg eq "--lower-all") {
2201     $opt_lower=$OPT_LOWER_ALL;
2202   } elsif ($arg eq "--lower-uppercase") {
2203     $opt_lower=$OPT_LOWER_UPPERCASE;
2204   } elsif ($arg eq "--lower-include") {
2205     $opt_lower_include=1;
2206   } elsif ($arg eq "--nolower-include") {
2207     $opt_lower_include=0;
2208   } elsif ($arg eq "--nosource-fix") {
2209     $opt_no_source_fix=1;
2210   } elsif ($arg eq "--generated-files") {
2211     $opt_no_generated_files=0;
2212   } elsif ($arg eq "--nogenerated-files") {
2213     $opt_no_generated_files=1;
2214   } elsif ($arg eq "--nogenerated-specs") {
2215     $opt_no_generated_specs=1;
2216
2217   } elsif ($arg =~ /^-D/) {
2218     push @{$global_settings[$T_DEFINES]},$arg;
2219   } elsif ($arg =~ /^-I/) {
2220     push @{$global_settings[$T_INCLUDE_PATH]},$arg;
2221   } elsif ($arg =~ /^-P/) {
2222     push @{$global_settings[$T_DLL_PATH]},"-L$'";
2223   } elsif ($arg =~ /^-i/) {
2224     push @{$global_settings[$T_DLLS]},$';
2225   } elsif ($arg =~ /^-L/) {
2226     push @{$global_settings[$T_LIBRARY_PATH]},$arg;
2227   } elsif ($arg =~ /^-l/) {
2228     push @{$global_settings[$T_LIBRARIES]},$';
2229
2230   # 'Source'-based method options
2231   } elsif ($arg eq "--dll") {
2232     $opt_target_type=$TT_DLL;
2233   } elsif ($arg eq "--guiexe" or $arg eq "--windows") {
2234     $opt_target_type=$TT_GUIEXE;
2235   } elsif ($arg eq "--cuiexe" or $arg eq "--console") {
2236     $opt_target_type=$TT_CUIEXE;
2237   } elsif ($arg eq "--interactive") {
2238     $opt_is_interactive=$OPT_ASK_YES;
2239     $opt_ask_project_options=$OPT_ASK_YES;
2240     $opt_ask_target_options=$OPT_ASK_YES;
2241   } elsif ($arg eq "--wrap") {
2242     $opt_flags|=$TF_WRAP;
2243   } elsif ($arg eq "--nowrap") {
2244     $opt_flags&=~$TF_WRAP;
2245   } elsif ($arg eq "--mfc") {
2246     $opt_flags|=$TF_MFC;
2247     $opt_flags|=$TF_MFC|$TF_WRAP;
2248     $needs_mfc=1;
2249   } elsif ($arg eq "--nomfc") {
2250     $opt_flags&=~($TF_MFC|$TF_WRAP);
2251     $needs_mfc=0;
2252
2253   # Catch errors
2254   } else {
2255     if ($arg ne "--help" and $arg ne "-h" and $arg ne "-?") {
2256       if (!defined $opt_work_dir) {
2257         $opt_work_dir=$arg;
2258       } else {
2259         print STDERR "error: the work directory, \"$arg\", has already been specified (was \"$opt_work_dir\")\n";
2260         usage();
2261       }
2262     } else {
2263       usage();
2264     }
2265   }
2266 }
2267
2268 if (!defined $opt_work_dir) {
2269   print STDERR "error: you must specify the directory containing the sources to be converted\n";
2270   usage();
2271 } elsif (!chdir $opt_work_dir) {
2272   print STDERR "error: could not chdir to the work directory\n";
2273   print STDERR "       $!\n";
2274   usage();
2275 }
2276
2277 if ($opt_no_banner == 0) {
2278   print_banner();
2279 }
2280
2281 # Fix the file and directory names
2282 fix_file_and_directory_names(".");
2283
2284 # Scan the sources to identify the projects and targets
2285 source_scan();
2286
2287 # Create targets for wrappers, etc.
2288 postprocess_targets();
2289
2290 # Fix the source files
2291 if (! $opt_no_source_fix) {
2292   fix_source();
2293 }
2294
2295 # Generate the Makefile and the spec file
2296 if (! $opt_no_generated_files) {
2297   generate();
2298 }
2299
2300
2301 __DATA__
2302 --- configure.in ---
2303 dnl Process this file with autoconf to produce a configure script.
2304 dnl Author: Michael Patra   <micky@marie.physik.tu-berlin.de>
2305 dnl                         <patra@itp1.physik.tu-berlin.de>
2306 dnl         Francois Gouget <fgouget@codeweavers.com> for CodeWeavers
2307
2308 AC_REVISION([configure.in 1.00])
2309 AC_INIT(##WINEMAKER_SOURCE##)
2310
2311 NEEDS_MFC=##WINEMAKER_NEEDS_MFC##
2312
2313 dnl **** Command-line arguments ****
2314
2315 AC_SUBST(OPTIONS)
2316
2317 dnl **** Check for some programs ****
2318
2319 AC_PROG_MAKE_SET
2320 AC_PROG_CC
2321 AC_PROG_CXX
2322 AC_PROG_CPP
2323 AC_PROG_LN_S
2324
2325 dnl **** Check for some libraries ****
2326
2327 dnl Check for -lm for BeOS
2328 AC_CHECK_LIB(m,sqrt)
2329 dnl Check for -lw for Solaris
2330 AC_CHECK_LIB(w,iswalnum)
2331 dnl Check for -lnsl for Solaris
2332 AC_CHECK_FUNCS(gethostbyname,, AC_CHECK_LIB(nsl, gethostbyname, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl", AC_CHECK_LIB(socket, gethostbyname, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl", , -lnsl), -lsocket))
2333 dnl Check for -lsocket for Solaris
2334 AC_CHECK_FUNCS(connect,,AC_CHECK_LIB(socket,connect))
2335
2336 dnl **** If ln -s doesn't work, use cp instead ****
2337 if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
2338
2339 dnl **** Check for gcc strength-reduce bug ****
2340
2341 if test "x${GCC}" = "xyes"
2342 then
2343   AC_CACHE_CHECK( "for gcc strength-reduce bug", ac_cv_c_gcc_strength_bug,
2344                   AC_TRY_RUN([
2345 int main(void) {
2346   static int Array[[3]];
2347   unsigned int B = 3;
2348   int i;
2349   for(i=0; i<B; i++) Array[[i]] = i - 3;
2350   exit( Array[[1]] != -2 );
2351 }],
2352     ac_cv_c_gcc_strength_bug="no",
2353     ac_cv_c_gcc_strength_bug="yes",
2354     ac_cv_c_gcc_strength_bug="yes") )
2355   if test "$ac_cv_c_gcc_strength_bug" = "yes"
2356   then
2357     CFLAGS="$CFLAGS -fno-strength-reduce"
2358   fi
2359 fi
2360
2361 dnl **** Check for underscore on external symbols ****
2362
2363 AC_CACHE_CHECK("whether external symbols need an underscore prefix",
2364                ac_cv_c_extern_prefix,
2365 [saved_libs=$LIBS
2366 LIBS="conftest_asm.s $LIBS"
2367 cat > conftest_asm.s <<EOF
2368         .globl _ac_test
2369 _ac_test:
2370         .long 0
2371 EOF
2372 AC_TRY_LINK([extern int ac_test;],[if (ac_test) return 1],
2373             ac_cv_c_extern_prefix="yes",ac_cv_c_extern_prefix="no")
2374 LIBS=$saved_libs])
2375 if test "$ac_cv_c_extern_prefix" = "yes"
2376 then
2377   AC_DEFINE(NEED_UNDERSCORE_PREFIX)
2378 fi
2379
2380 dnl **** Check for working dll ****
2381
2382 LDSHARED=""
2383 LDXXSHARED=""
2384 LDDLLFLAGS=""
2385 AC_CACHE_CHECK("whether we can build a Linux dll",
2386                ac_cv_c_dll_linux,
2387 [saved_cflags=$CFLAGS
2388 CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0,-Bsymbolic"
2389 AC_TRY_LINK(,[return 1],ac_cv_c_dll_linux="yes",ac_cv_c_dll_linux="no")
2390 CFLAGS=$saved_cflags
2391 ])
2392 if test "$ac_cv_c_dll_linux" = "yes"
2393 then
2394   LDSHARED="\$(CC) -shared -Wl,-rpath,\$(libdir)"
2395   LDXXSHARED="\$(CXX) -shared -Wl,-rpath,\$(libdir)"
2396   LDDLLFLAGS="-Wl,-Bsymbolic"
2397 else
2398   AC_CACHE_CHECK(whether we can build a UnixWare (Solaris) dll,
2399                 ac_cv_c_dll_unixware,
2400   [saved_cflags=$CFLAGS
2401   CFLAGS="$CFLAGS -fPIC -Wl,-G,-h,conftest.so.1.0,-B,symbolic"
2402   AC_TRY_LINK(,[return 1],ac_cv_c_dll_unixware="yes",ac_cv_c_dll_unixware="no")
2403   CFLAGS=$saved_cflags
2404   ])
2405   if test "$ac_cv_c_dll_unixware" = "yes"
2406   then
2407     LDSHARED="\$(CC) -Wl,-G"
2408     LDXXSHARED="\$(CXX) -Wl,-G"
2409     LDDLLFLAGS="-Wl,-B,symbolic"
2410   else
2411     AC_CACHE_CHECK("whether we can build a NetBSD dll",
2412                    ac_cv_c_dll_netbsd,
2413     [saved_cflags=$CFLAGS
2414     CFLAGS="$CFLAGS -fPIC -Wl,-Bshareable,-Bforcearchive"
2415     AC_TRY_LINK(,[return 1],ac_cv_c_dll_netbsd="yes",ac_cv_c_dll_netbsd="no")
2416     CFLAGS=$saved_cflags
2417     ])
2418     if test "$ac_cv_c_dll_netbsd" = "yes"
2419     then
2420       LDSHARED="\$(CC) -Wl,-Bshareable,-Bforcearchive"
2421       LDXXSHARED="\$(CXX) -Wl,-Bshareable,-Bforcearchive"
2422       LDDLLFLAGS="" #FIXME
2423     fi
2424   fi
2425 fi
2426 if test "$ac_cv_c_dll_linux" = "no" -a "$ac_cv_c_dll_unixware" = "no" -a "$ac_cv_c_dll_netbsd" = "no"
2427 then
2428   AC_MSG_ERROR([Could not find how to build a dynamically linked library])
2429 fi
2430
2431 CFLAGS="$CFLAGS -fPIC"
2432
2433 AC_SUBST(LDSHARED)
2434 AC_SUBST(LDXXSHARED)
2435 AC_SUBST(LDDLLFLAGS)
2436
2437 dnl *** check for the need to define __i386__
2438
2439 AC_CACHE_CHECK("whether we need to define __i386__",ac_cv_cpp_def_i386,
2440  AC_EGREP_CPP(yes,[#if (defined(i386) || defined(__i386)) && !defined(__i386__)
2441 yes
2442 #endif],
2443  ac_cv_cpp_def_i386="yes", ac_cv_cpp_def_i386="no"))
2444 if test "$ac_cv_cpp_def_i386" = "yes"
2445 then
2446     CFLAGS="$CFLAGS -D__i386__"
2447 fi
2448
2449 dnl $GCC is set by autoconf
2450 GCC_NO_BUILTIN=""
2451 if test "$GCC" = "yes"
2452 then
2453     GCC_NO_BUILTIN="-fno-builtin"
2454 fi
2455 AC_SUBST(GCC_NO_BUILTIN)
2456
2457 dnl **** Test Winelib-related features of the C++ compiler
2458 AC_LANG_CPLUSPLUS()
2459 if test "x${GCC}" = "xyes"
2460 then
2461   OLDCXXFLAGS="$CXXFLAGS";
2462   CXXFLAGS="-fpermissive";
2463   AC_CACHE_CHECK("for g++ -fpermissive option", has_gxx_permissive,
2464     AC_TRY_COMPILE(,[
2465         for (int i=0;i<2;i++);
2466         i=0;
2467       ],
2468       [has_gxx_permissive="yes"],
2469       [has_gxx_permissive="no"])
2470    )
2471   CXXFLAGS="-fno-for-scope";
2472   AC_CACHE_CHECK("for g++ -fno-for-scope option", has_gxx_no_for_scope,
2473     AC_TRY_COMPILE(,[
2474         for (int i=0;i<2;i++);
2475         i=0;
2476       ],
2477       [has_gxx_no_for_scope="yes"],
2478       [has_gxx_no_for_scope="no"])
2479    )
2480   CXXFLAGS="$OLDCXXFLAGS";
2481   if test "$has_gxx_permissive" = "yes"
2482   then
2483     CXXFLAGS="$CXXFLAGS -fpermissive"
2484   fi
2485   if test "$has_gxx_no_for_scope" = "yes"
2486   then
2487     CXXFLAGS="$CXXFLAGS -fno-for-scope"
2488   fi
2489 fi
2490 AC_LANG_C()
2491
2492 dnl **** Test Winelib-related features of the C compiler
2493 dnl none for now
2494
2495 dnl **** Macros for finding a headers/libraries in a collection of places
2496
2497 dnl AC_PATH_FILE(variable,file,action-if-not-found,default-locations)
2498 AC_DEFUN(AC_PATH_FILE,[
2499 AC_MSG_CHECKING([for $2])
2500 AC_CACHE_VAL(ac_cv_pfile_$1,
2501 [
2502   ac_found=
2503   ac_dummy="ifelse([$4], , , [$4])"
2504   IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
2505   for ac_dir in $ac_dummy; do
2506     IFS="$ac_save_ifs"
2507     if test -z "$ac_dir"
2508     then
2509       ac_file="$2"
2510     else
2511       ac_file="$ac_dir/$2"
2512     fi
2513     if test -f "$ac_file"
2514     then
2515       ac_found=1
2516       ac_cv_pfile_$1="$ac_dir"
2517       break
2518     fi
2519   done
2520   ifelse([$3],,,[if test -z "$ac_found"
2521     then
2522       $3
2523     fi
2524   ])
2525 ])
2526 $1="$ac_cv_pfile_$1"
2527 if test -n "$ac_found" -o -n "[$]$1"
2528 then
2529   AC_MSG_RESULT([$]$1)
2530 else
2531   AC_MSG_RESULT(no)
2532 fi
2533 AC_SUBST($1)
2534 ])
2535
2536 dnl AC_PATH_HEADER(variable,header,action-if-not-found,default-locations)
2537 dnl Note that the above may set variable to an empty value if the header is 
2538 dnl already in the include path
2539 AC_DEFUN(AC_PATH_HEADER,[
2540 AC_MSG_CHECKING([for $2 header])
2541 AC_CACHE_VAL(ac_cv_pheader_$1,
2542 [
2543   ac_found=
2544   ac_dummy="ifelse([$4], , :/usr/local/include, [$4])"
2545   save_CPPFLAGS="$CPPFLAGS"
2546   IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
2547   for ac_dir in $ac_dummy; do
2548     IFS="$ac_save_ifs"
2549     if test -z "$ac_dir"
2550     then
2551       CPPFLAGS="$save_CPPFLAGS"
2552     else
2553       CPPFLAGS="-I$ac_dir $save_CPPFLAGS"
2554     fi
2555     AC_TRY_COMPILE([#include <$2>],,ac_found=1;ac_cv_pheader_$1="$ac_dir";break)
2556   done
2557   CPPFLAGS="$save_CPPFLAGS"
2558   ifelse([$3],,,[if test -z "$ac_found"
2559     then
2560       $3
2561     fi
2562   ])
2563 ])
2564 $1="$ac_cv_pheader_$1"
2565 if test -n "$ac_found" -o -n "[$]$1"
2566 then
2567   AC_MSG_RESULT([$]$1)
2568 else
2569   AC_MSG_RESULT(no)
2570 fi
2571 AC_SUBST($1)
2572 ])
2573
2574 dnl AC_PATH_LIBRARY(variable,libraries,extra libs,action-if-not-found,default-locations)
2575 AC_DEFUN(AC_PATH_LIBRARY,[
2576 AC_MSG_CHECKING([for $2])
2577 AC_CACHE_VAL(ac_cv_plibrary_$1,
2578 [
2579   ac_found=
2580   ac_dummy="ifelse([$5], , :/usr/local/lib, [$5])"
2581   save_LIBS="$LIBS"
2582   IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
2583   for ac_dir in $ac_dummy; do
2584     IFS="$ac_save_ifs"
2585     if test -z "$ac_dir"
2586     then
2587       LIBS="$2 $3 $save_LIBS"
2588     else
2589       LIBS="-L$ac_dir $2 $3 $save_LIBS"
2590     fi
2591     AC_TRY_LINK(,,ac_found=1;ac_cv_plibrary_$1="$ac_dir";break)
2592   done
2593   LIBS="$save_LIBS"
2594   ifelse([$4],,,[if test -z "$ac_found"
2595     then
2596       $4
2597     fi
2598   ])
2599 ])
2600 $1="$ac_cv_plibrary_$1"
2601 if test -n "$ac_found" -o -n "[$]$1"
2602 then
2603   AC_MSG_RESULT([$]$1)
2604 else
2605   AC_MSG_RESULT(no)
2606 fi
2607 AC_SUBST($1)
2608 ])
2609
2610 dnl **** Try to find where winelib is located ****
2611
2612 LD_PATH=""
2613 WINE_INCLUDE_ROOT=""
2614 WINE_INCLUDE_PATH=""
2615 WINE_LIBRARY_ROOT=""
2616 WINE_LIBRARY_PATH=""
2617 WINE_DLL_ROOT=""
2618 WINE_DLL_PATH=""
2619 WINE_TOOL_PATH=""
2620 WINE=""
2621 WINEBUILD=""
2622 WRC=""
2623
2624 AC_ARG_WITH(wine,
2625 [  --with-wine=DIR           the Wine package (or sources) is in DIR],
2626 [if test "$withval" != "no"; then
2627   WINE_ROOT="$withval";
2628   WINE_INCLUDES="";
2629   WINE_LIBRARIES="";
2630   WINE_TOOLS="";
2631 else
2632   WINE_ROOT="";
2633 fi])
2634 if test -n "$WINE_ROOT"
2635 then
2636   WINE_INCLUDE_ROOT="$WINE_ROOT/include:$WINE_ROOT/include/wine"
2637   WINE_LIBRARY_ROOT="$WINE_ROOT:$WINE_ROOT/lib"
2638   WINE_TOOL_PATH="$WINE_ROOT:$WINE_ROOT/bin:$WINE_ROOT/tools/wrc:$WINE_ROOT/tools/winebuild"
2639 fi
2640
2641 AC_ARG_WITH(wine-includes,
2642 [  --with-wine-includes=DIR  the Wine includes are in DIR],
2643 [if test "$withval" != "no"; then
2644   WINE_INCLUDES="$withval";
2645 else
2646   WINE_INCLUDES="";
2647 fi])
2648 if test -n "$WINE_INCLUDES"
2649 then
2650   WINE_INCLUDE_ROOT="$WINE_INCLUDES"
2651 fi
2652
2653 AC_ARG_WITH(wine-libraries,
2654 [  --with-wine-libraries=DIR the Wine libraries are in DIR],
2655 [if test "$withval" != "no"; then
2656   WINE_LIBRARIES="$withval";
2657 else
2658   WINE_LIBRARIES="";
2659 fi])
2660 if test -n "$WINE_LIBRARIES"
2661 then
2662   WINE_LIBRARY_ROOT="$WINE_LIBRARIES"
2663 fi
2664
2665 AC_ARG_WITH(wine-dlls,
2666 [  --with-wine-dlls=DIR      the Wine dlls are in DIR],
2667 [if test "$withval" != "no"; then
2668   WINE_DLLS="$withval";
2669 else
2670   WINE_DLLS="";
2671 fi])
2672 if test -n "$WINE_DLLS"
2673 then
2674   WINE_DLL_ROOT="$WINE_DLLS"
2675 fi
2676
2677 AC_ARG_WITH(wine-tools,
2678 [  --with-wine-tools=DIR     the Wine tools are in DIR],
2679 [if test "$withval" != "no"; then
2680   WINE_TOOLS="$withval";
2681 else
2682   WINE_TOOLS="";
2683 fi])
2684 if test -n "$WINE_TOOLS"
2685 then
2686   WINE_TOOL_PATH="$WINE_TOOLS:$WINE_TOOLS/tools/wrc:$WINE_TOOLS/tools/winebuild"
2687 fi
2688
2689 if test -z "$WINE_INCLUDE_ROOT"
2690 then
2691   WINE_INCLUDE_ROOT=":/usr/include/wine:/usr/local/include/wine:/opt/wine/include:/opt/wine/include/wine";
2692 else
2693   AC_PATH_FILE(WINE_INCLUDE_ROOT,[windef.h],[
2694     AC_MSG_ERROR([Could not find the Wine headers (windef.h)])
2695   ],$WINE_INCLUDE_ROOT)
2696 fi
2697 AC_PATH_HEADER(WINE_INCLUDE_ROOT,[windef.h],[
2698   AC_MSG_ERROR([Could not include the Wine headers (windef.h)])
2699 ],$WINE_INCLUDE_ROOT)
2700 if test -n "$WINE_INCLUDE_ROOT"
2701 then
2702   WINE_INCLUDE_PATH="-I$WINE_INCLUDE_ROOT"
2703 else
2704   WINE_INCLUDE_PATH=""
2705 fi
2706
2707 if test -z "$WINE_LIBRARY_ROOT"
2708 then
2709   WINE_LIBRARY_ROOT=":/usr/lib/wine:/usr/local/lib:/usr/local/lib/wine:/opt/wine/lib"
2710 else
2711   AC_PATH_FILE(WINE_LIBRARY_ROOT,[libwine.so],[
2712     AC_MSG_ERROR([Could not find the Wine libraries (libwine.so)])
2713   ],$WINE_LIBRARY_ROOT)
2714 fi
2715 AC_PATH_LIBRARY(WINE_LIBRARY_ROOT,[-lwine],[],[
2716   AC_MSG_ERROR([Could not link with the Wine libraries (libwine.so)])
2717 ],$WINE_LIBRARY_ROOT)
2718 if test -n "$WINE_LIBRARY_ROOT"
2719 then
2720   WINE_LIBRARY_PATH="-L$WINE_LIBRARY_ROOT"
2721   LD_PATH="$WINE_LIBRARY_ROOT"
2722 else
2723   WINE_LIBRARY_PATH=""
2724 fi
2725
2726 if test -z "$WINE_DLL_ROOT"
2727 then
2728   if test -n "$WINE_LIBRARY_ROOT"
2729   then
2730     WINE_DLL_ROOT="$WINE_LIBRARY_ROOT:$WINE_LIBRARY_ROOT/dlls"
2731   else
2732     WINE_DLL_ROOT="/lib:/lib/dlls:/usr/lib:/usr/lib/dlls:/usr/local/lib:/usr/local/lib/dlls"
2733   fi
2734 fi
2735 AC_PATH_FILE(WINE_DLL_ROOT,[libntdll.so],[
2736   AC_MSG_ERROR([Could not find the Wine dlls (libntdll.so)])
2737 ],[$WINE_DLL_ROOT])
2738
2739 AC_PATH_LIBRARY(WINE_DLL_ROOT,[-lntdll],[$WINE_LIBRARY_PATH -lwine -lwine_unicode],[
2740   AC_MSG_ERROR([Could not link with the Wine dlls (libntdll.so)])
2741 ],[$WINE_DLL_ROOT])
2742 WINE_DLL_PATH="-L$WINE_DLL_ROOT"
2743
2744 if test -n "$LD_PATH"
2745 then
2746   LD_PATH="$LD_PATH:$WINE_DLL_ROOT"
2747 else
2748   LD_PATH="$WINE_DLL_ROOT"
2749 fi
2750 LD_PATH="LD_LIBRARY_PATH=\"$LD_PATH:\$\$LD_LIBRARY_PATH\""
2751
2752 if test -z "$WINE_TOOL_PATH"
2753 then
2754   WINE_TOOL_PATH="$PATH:/usr/local/bin:/opt/wine/bin"
2755 fi
2756 AC_PATH_PROG(WINE,wine,,$WINE_TOOL_PATH)
2757 if test -z "$WINE"
2758 then
2759   AC_MSG_ERROR([Could not find Wine's wine tool])
2760 fi
2761 AC_PATH_PROG(WINEBUILD,winebuild,,$WINE_TOOL_PATH)
2762 if test -z "$WINEBUILD"
2763 then
2764   AC_MSG_ERROR([Could not find Wine's winebuild tool])
2765 fi
2766 AC_PATH_PROG(WRC,wrc,,$WINE_TOOL_PATH)
2767 if test -z "$WRC"
2768 then
2769   AC_MSG_ERROR([Could not find Wine's wrc tool])
2770 fi
2771
2772 AC_SUBST(LD_PATH)
2773 AC_SUBST(WINE_INCLUDE_PATH)
2774 AC_SUBST(WINE_LIBRARY_PATH)
2775 AC_SUBST(WINE_DLL_PATH)
2776
2777 dnl **** Try to find where the MFC are located ****
2778 AC_LANG_CPLUSPLUS()
2779
2780 if test "x$NEEDS_MFC" = "x1"
2781 then
2782   ATL_INCLUDE_ROOT="";
2783   ATL_INCLUDE_PATH="";
2784   MFC_INCLUDE_ROOT="";
2785   MFC_INCLUDE_PATH="";
2786   MFC_LIBRARY_ROOT="";
2787   MFC_LIBRARY_PATH="";
2788
2789   AC_ARG_WITH(mfc,
2790   [  --with-mfc=DIR            the MFC package (or sources) is in DIR],
2791   [if test "$withval" != "no"; then
2792     MFC_ROOT="$withval";
2793     ATL_INCLUDES="";
2794     MFC_INCLUDES="";
2795     MFC_LIBRARIES="";
2796   else
2797     MFC_ROOT="";
2798   fi])
2799   if test -n "$MFC_ROOT"
2800   then
2801     ATL_INCLUDE_ROOT="$MFC_ROOT";
2802     MFC_INCLUDE_ROOT="$MFC_ROOT";
2803     MFC_LIBRARY_ROOT="$MFC_ROOT";
2804   fi
2805
2806   AC_ARG_WITH(atl-includes,
2807   [  --with-atl-includes=DIR   the ATL includes are in DIR],
2808   [if test "$withval" != "no"; then
2809     ATL_INCLUDES="$withval";
2810   else
2811     ATL_INCLUDES="";
2812   fi])
2813   if test -n "$ATL_INCLUDES"
2814   then
2815     ATL_INCLUDE_ROOT="$ATL_INCLUDES";
2816   fi
2817
2818   AC_ARG_WITH(mfc-includes,
2819   [  --with-mfc-includes=DIR   the MFC includes are in DIR],
2820   [if test "$withval" != "no"; then
2821     MFC_INCLUDES="$withval";
2822   else
2823     MFC_INCLUDES="";
2824   fi])
2825   if test -n "$MFC_INCLUDES"
2826   then
2827     MFC_INCLUDE_ROOT="$MFC_INCLUDES";
2828   fi
2829
2830   AC_ARG_WITH(mfc-libraries,
2831   [  --with-mfc-libraries=DIR  the MFC libraries are in DIR],
2832   [if test "$withval" != "no"; then
2833     MFC_LIBRARIES="$withval";
2834   else
2835     MFC_LIBRARIES="";
2836   fi])
2837   if test -n "$MFC_LIBRARIES"
2838   then
2839     MFC_LIBRARY_ROOT="$MFC_LIBRARIES";
2840   fi
2841
2842   OLDCPPFLAGS="$CPPFLAGS"
2843   dnl FIXME: We should not have defines in any of the include paths
2844   CPPFLAGS="$WINE_INCLUDE_PATH -I$WINE_INCLUDE_ROOT/mixedcrt -D_DLL -D_MT $CPPFLAGS"
2845   ATL_INCLUDE_PATH="-I\$(WINE_INCLUDE_ROOT)/mixedcrt -D_DLL -D_MT"
2846   if test -z "$ATL_INCLUDE_ROOT"
2847   then
2848     ATL_INCLUDE_ROOT=":$WINE_INCLUDE_ROOT/atl:/usr/include/atl:/usr/local/include/atl:/opt/mfc/include/atl:/opt/atl/include"
2849   else
2850     ATL_INCLUDE_ROOT="$ATL_INCLUDE_ROOT:$ATL_INCLUDE_ROOT/atl:$ATL_INCLUDE_ROOT/atl/include"
2851   fi
2852   AC_PATH_HEADER(ATL_INCLUDE_ROOT,atldef.h,[
2853     AC_MSG_ERROR([Could not find the ATL includes])
2854   ],$ATL_INCLUDE_ROOT)
2855   if test -n "$ATL_INCLUDE_ROOT"
2856   then
2857     ATL_INCLUDE_PATH="$ATL_INCLUDE_PATH -I$ATL_INCLUDE_ROOT"
2858   fi
2859
2860   MFC_INCLUDE_PATH="$ATL_INCLUDE_PATH"
2861   if test -z "$MFC_INCLUDE_ROOT"
2862   then
2863     MFC_INCLUDE_ROOT=":$WINE_INCLUDE_ROOT/mfc:/usr/include/mfc:/usr/local/include/mfc:/opt/mfc/include/mfc:/opt/mfc/include"
2864   else
2865     MFC_INCLUDE_ROOT="$MFC_INCLUDE_ROOT:$MFC_INCLUDE_ROOT/mfc:$MFC_INCLUDE_ROOT/mfc/include"
2866   fi
2867   AC_PATH_HEADER(MFC_INCLUDE_ROOT,afx.h,[
2868     AC_MSG_ERROR([Could not find the MFC includes])
2869   ],$MFC_INCLUDE_ROOT)
2870   if test -n "$MFC_INCLUDE_ROOT" -a "$ATL_INCLUDE_ROOT" != "$MFC_INCLUDE_ROOT"
2871   then
2872     MFC_INCLUDE_PATH="$MFC_INCLUDE_PATH -I$MFC_INCLUDE_ROOT"
2873   fi
2874   CPPFLAGS="$OLDCPPFLAGS"
2875
2876   if test -z "$MFC_LIBRARY_ROOT"
2877   then
2878     MFC_LIBRARY_ROOT=":$WINE_LIBRARY_ROOT:/usr/lib/mfc:/usr/local/lib:/usr/local/lib/mfc:/opt/mfc/lib";
2879   else
2880     MFC_LIBRARY_ROOT="$MFC_LIBRARY_ROOT:$MFC_LIBRARY_ROOT/lib:$MFC_LIBRARY_ROOT/mfc/src";
2881   fi
2882   AC_PATH_LIBRARY(MFC_LIBRARY_ROOT,[-lmfc],[$WINE_LIBRARY_PATH -lwine -lwine_unicode],[
2883     AC_MSG_ERROR([Could not find the MFC library])
2884   ],$MFC_LIBRARY_ROOT)
2885   if test -n "$MFC_LIBRARY_ROOT" -a "$MFC_LIBRARY_ROOT" != "$WINE_LIBRARY_ROOT"
2886   then
2887     MFC_LIBRARY_PATH="-L$MFC_LIBRARY_ROOT"
2888   else
2889     MFC_LIBRARY_PATH=""
2890   fi
2891
2892   AC_SUBST(ATL_INCLUDE_PATH)
2893   AC_SUBST(MFC_INCLUDE_PATH)
2894   AC_SUBST(MFC_LIBRARY_PATH)
2895 fi
2896
2897 AC_LANG_C()
2898
2899 dnl **** Generate output files ****
2900
2901 MAKE_RULES=Make.rules
2902 AC_SUBST_FILE(MAKE_RULES)
2903
2904 AC_OUTPUT([
2905 Make.rules
2906 ##WINEMAKER_PROJECTS##
2907  ])
2908
2909 echo
2910 echo "Configure finished.  Do 'make' to build the project."
2911 echo
2912
2913 dnl Local Variables:
2914 dnl comment-start: "dnl "
2915 dnl comment-end: ""
2916 dnl comment-start-skip: "\\bdnl\\b\\s *"
2917 dnl compile-command: "autoconf"
2918 dnl End:
2919 --- Make.rules.in ---
2920 # Copyright 2000 Francois Gouget for CodeWeavers
2921 # fgouget@codeweavers.com
2922 #
2923 # Global rules shared by all makefiles     -*-Makefile-*-
2924 #
2925 # Each individual makefile must define the following variables:
2926 # TOPOBJDIR    : top-level object directory
2927 # SRCDIR       : source directory for this module
2928 #
2929 # Each individual makefile may define the following additional variables:
2930 #
2931 # SUBDIRS      : subdirectories that contain a Makefile
2932 # DLLS         : WineLib libraries to be built
2933 # EXES         : WineLib executables to be built
2934 #
2935 # CEXTRA       : extra c flags (e.g. '-Wall')
2936 # CXXEXTRA     : extra c++ flags (e.g. '-Wall')
2937 # WRCEXTRA     : extra wrc flags (e.g. '-p _SysRes')
2938 # DEFINES      : defines (e.g. -DSTRICT)
2939 # INCLUDE_PATH : additional include path
2940 # LIBRARY_PATH : additional library path
2941 # LIBRARIES    : additional Unix libraries to link with
2942 #
2943 # C_SRCS       : C sources for the module
2944 # CXX_SRCS     : C++ sources for the module
2945 # RC_SRCS      : resource source files
2946 # SPEC_SRCS    : interface definition files
2947
2948
2949 # Where is Wine
2950
2951 WINE_INCLUDE_ROOT = @WINE_INCLUDE_ROOT@
2952 WINE_INCLUDE_PATH = @WINE_INCLUDE_PATH@
2953 WINE_LIBRARY_ROOT = @WINE_LIBRARY_ROOT@
2954 WINE_LIBRARY_PATH = @WINE_LIBRARY_PATH@
2955 WINE_DLL_ROOT     = @WINE_DLL_ROOT@
2956 WINE_DLL_PATH     = @WINE_DLL_PATH@
2957
2958 LD_PATH           = @LD_PATH@
2959
2960 # Where are the MFC
2961
2962 ATL_INCLUDE_ROOT = @ATL_INCLUDE_ROOT@
2963 ATL_INCLUDE_PATH = @ATL_INCLUDE_PATH@
2964 MFC_INCLUDE_ROOT = @MFC_INCLUDE_ROOT@
2965 MFC_INCLUDE_PATH = @MFC_INCLUDE_PATH@
2966 MFC_LIBRARY_ROOT = @MFC_LIBRARY_ROOT@
2967 MFC_LIBRARY_PATH = @MFC_LIBRARY_PATH@
2968
2969 # First some useful definitions
2970
2971 SHELL     = /bin/sh
2972 CC        = @CC@
2973 CPP       = @CPP@
2974 CXX       = @CXX@
2975 WRC       = @WRC@
2976 CFLAGS    = @CFLAGS@
2977 CXXFLAGS  = @CXXFLAGS@
2978 WRCFLAGS  = -r -L
2979 OPTIONS   = @OPTIONS@ -D_REENTRANT -DWINELIB
2980 LIBS      = @LIBS@ $(LIBRARY_PATH)
2981 LN_S      = @LN_S@
2982 ALLFLAGS  = $(DEFINES) -I$(SRCDIR) $(INCLUDE_PATH) $(WINE_INCLUDE_PATH)
2983 ALLCFLAGS = $(CFLAGS) $(CEXTRA) $(OPTIONS) $(ALLFLAGS)
2984 ALLCXXFLAGS=$(CXXFLAGS) $(CXXEXTRA) $(OPTIONS) $(ALLFLAGS)
2985 ALLWRCFLAGS=$(WRCFLAGS) $(WRCEXTRA) $(OPTIONS) $(ALLFLAGS)
2986 DLL_LINK  = $(LIBRARY_PATH) $(LIBRARIES:%=-l%) $(WINE_LIBRARY_PATH) -lwine -lwine_unicode -lwine_uuid
2987 LDCOMBINE = ld -r
2988 LDSHARED  = @LDSHARED@
2989 LDXXSHARED= @LDXXSHARED@
2990 LDDLLFLAGS= @LDDLLFLAGS@
2991 STRIP     = strip
2992 STRIPFLAGS= --strip-unneeded
2993 RM        = rm -f
2994 MV        = mv
2995 MKDIR     = mkdir -p
2996 WINE      = @WINE@
2997 WINEBUILD = @WINEBUILD@
2998 @SET_MAKE@
2999
3000 # Installation infos
3001
3002 INSTALL         = install
3003 INSTALL_PROGRAM = $(INSTALL)
3004 INSTALL_DATA    = $(INSTALL) -m 644
3005 prefix          = @prefix@
3006 exec_prefix     = @exec_prefix@
3007 bindir          = @bindir@
3008 libdir          = @libdir@
3009 infodir         = @infodir@
3010 mandir          = @mandir@
3011 prog_manext     = 1
3012 conf_manext     = 5
3013
3014 OBJS            = $(C_SRCS:.c=.o) $(CXX_SRCS:.cpp=.o) \
3015                   $(SPEC_SRCS:.spec=.spec.o) 
3016 CLEAN_FILES     = *.spec.c y.tab.c y.tab.h lex.yy.c \
3017                   core *.orig *.rej \
3018                   \\\#*\\\# *~ *% .\\\#*
3019
3020 # Implicit rules
3021
3022 .SUFFIXES: .cpp .rc .res .tmp.o .spec .spec.c .spec.o
3023
3024 .c.o:
3025         $(CC) -c $(ALLCFLAGS) -o $@ $<
3026
3027 .cpp.o:
3028         $(CXX) -c $(ALLCXXFLAGS) -o $@ $<
3029
3030 .cxx.o:
3031         $(CXX) -c $(ALLCXXFLAGS) -o $@ $<
3032
3033 .rc.res:
3034         $(LD_PATH) $(WRC) $(ALLWRCFLAGS) -o $@ $<
3035
3036 .PHONY: all install uninstall clean distclean depend dummy
3037
3038 # 'all' target first in case the enclosing Makefile didn't define any target
3039
3040 all: Makefile
3041
3042 # Rules for makefile
3043
3044 Makefile: Makefile.in $(TOPSRCDIR)/configure
3045         @echo Makefile is older than $?, please rerun $(TOPSRCDIR)/configure
3046         @exit 1
3047
3048 # Rules for cleaning
3049
3050 $(SUBDIRS:%=%/__clean__): dummy
3051         cd `dirname $@` && $(MAKE) clean
3052
3053 $(EXTRASUBDIRS:%=%/__clean__): dummy
3054         -cd `dirname $@` && $(RM) $(CLEAN_FILES)
3055
3056 clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
3057         $(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(OBJS) $(SPEC_SRCS:.spec=.tmp.o) $(EXES) $(EXES:%=%.so) $(DLLS)
3058
3059 # Rules for installing
3060
3061 $(SUBDIRS:%=%/__install__): dummy
3062         cd `dirname $@` && $(MAKE) install
3063
3064 $(SUBDIRS:%=%/__uninstall__): dummy
3065         cd `dirname $@` && $(MAKE) uninstall
3066
3067 # Misc. rules
3068
3069 $(SUBDIRS): dummy
3070         @cd $@ && $(MAKE)
3071
3072 dummy:
3073
3074 # End of global rules
3075 --- wrapper.c ---
3076 /*
3077  * Copyright 2000 Francois Gouget <fgouget@codeweavers.com> for CodeWeavers
3078  */
3079
3080 #ifndef STRICT
3081 #define STRICT
3082 #endif
3083
3084 #include <dlfcn.h>
3085 #include <windows.h>
3086
3087
3088
3089 /*
3090  * Describe the wrapped application
3091  */
3092
3093 /**
3094  * This is either CUIEXE for a console based application or
3095  * GUIEXE for a regular windows application.
3096  */
3097 #define      APP_TYPE      ##WINEMAKER_APP_TYPE##
3098
3099 /**
3100  * This is the application library's base name, i.e. 'hello' if the 
3101  * library is called 'libhello.so'.
3102  */
3103 static char* appName     = ##WINEMAKER_APP_NAME##;
3104
3105 /**
3106  * This is the name of the application's Windows module. If left NULL 
3107  * then appName is used.
3108  */
3109 static char* appModule   = NULL;
3110
3111 /**
3112  * This is the application's entry point. This is usually "WinMain" for a 
3113  * GUIEXE and 'main' for a CUIEXE application.
3114  */
3115 static char* appInit     = ##WINEMAKER_APP_INIT##;
3116
3117 /**
3118  * This is either non-NULL for MFC-based applications and is the name of the 
3119  * MFC's module. This is the module in which we will take the 'WinMain' 
3120  * function.
3121  */
3122 static char* mfcModule   = ##WINEMAKER_APP_MFC##;
3123
3124
3125
3126 /*
3127  * Implement the main.
3128  */
3129
3130 #if APP_TYPE == GUIEXE
3131 typedef int WINAPI (*WinMainFunc)(HINSTANCE hInstance, HINSTANCE hPrevInstance,
3132                                   PSTR szCmdLine, int iCmdShow);
3133 #else
3134 typedef int WINAPI (*MainFunc)(int argc, char** argv, char** envp);
3135 #endif
3136
3137 #if APP_TYPE == GUIEXE
3138 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
3139                    PSTR szCmdLine, int iCmdShow)
3140 #else
3141 int WINAPI Main(int argc, char** argv, char** envp)
3142 #endif
3143 {
3144     void* appLibrary;
3145     HINSTANCE hApp,hMFC,hMain;
3146     void* appMain;
3147     char* libName;
3148     int retcode;
3149
3150     /* Load the application's library */
3151     libName=(char*)malloc(strlen(appName)+5+3+1);
3152     /* FIXME: we should get the wrapper's path and use that as the base for 
3153      * the library 
3154      */
3155     sprintf(libName,"./lib%s.so",appName);
3156     appLibrary=dlopen(libName,RTLD_NOW);
3157     if (appLibrary==NULL) {
3158         sprintf(libName,"lib%s.so",appName);
3159         appLibrary=dlopen(libName,RTLD_NOW);
3160     }
3161     if (appLibrary==NULL) {
3162         char format[]="Could not load the %s library:\r\n%s";
3163         char* error;
3164         char* msg;
3165
3166         error=dlerror();
3167         msg=(char*)malloc(strlen(format)+strlen(libName)+strlen(error));
3168         sprintf(msg,format,libName,error);
3169         MessageBox(NULL,msg,"dlopen error",MB_OK);
3170         free(msg);
3171         return 1;
3172     }
3173
3174     /* Then if this application is MFC based, load the MFC module */
3175     /* FIXME: I'm not sure this is really necessary */
3176     if (mfcModule!=NULL) {
3177         hMFC=LoadLibrary(mfcModule);
3178         if (hMFC==NULL) {
3179             char format[]="Could not load the MFC module %s (%d)";
3180             char* msg;
3181
3182             msg=(char*)malloc(strlen(format)+strlen(mfcModule)+11);
3183             sprintf(msg,format,mfcModule,GetLastError());
3184             MessageBox(NULL,msg,"LoadLibrary error",MB_OK);
3185             free(msg);
3186             return 1;
3187         }
3188         /* MFC is a special case: the WinMain is in the MFC library, 
3189          * instead of the application's library.
3190          */
3191         hMain=hMFC;
3192     } else {
3193         hMFC=NULL;
3194     }
3195
3196     /* Load the application's module */
3197     if (appModule==NULL) {
3198         appModule=appName;
3199     }
3200     hApp=LoadLibrary(appModule);
3201     if (hApp==NULL) {
3202         char format[]="Could not load the application's module %s (%d)";
3203         char* msg;
3204
3205         msg=(char*)malloc(strlen(format)+strlen(appModule)+11);
3206         sprintf(msg,format,appModule,GetLastError());
3207         MessageBox(NULL,msg,"LoadLibrary error",MB_OK);
3208         free(msg);
3209         return 1;
3210     } else if (hMain==NULL) {
3211         hMain=hApp;
3212     }
3213
3214     /* Get the address of the application's entry point */
3215     appMain=(WinMainFunc*)GetProcAddress(hMain, appInit);
3216     if (appMain==NULL) {
3217         char format[]="Could not get the address of %s (%d)";
3218         char* msg;
3219
3220         msg=(char*)malloc(strlen(format)+strlen(appInit)+11);
3221         sprintf(msg,format,appInit,GetLastError());
3222         MessageBox(NULL,msg,"GetProcAddress error",MB_OK);
3223         free(msg);
3224         return 1;
3225     }
3226
3227     /* And finally invoke the application's entry point */
3228 #if APP_TYPE == GUIEXE
3229     retcode=(*((WinMainFunc)appMain))(hApp,hPrevInstance,szCmdLine,iCmdShow);
3230 #else
3231     retcode=(*((MainFunc)appMain))(argc,argv,envp);
3232 #endif
3233
3234     /* Cleanup and done */
3235     FreeLibrary(hApp);
3236     if (hMFC!=NULL) {
3237         FreeLibrary(hMFC);
3238     }
3239     dlclose(appLibrary);
3240     free(libName);
3241
3242     return retcode;
3243 }