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