Use a better location than HKCU\Wine for saving the temporary
[wine] / tools / winebuild / spec32.c
1 /*
2  * 32-bit spec files
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Martin von Loewis
6  * Copyright 1995, 1996, 1997 Alexandre Julliard
7  * Copyright 1997 Eric Youngdale
8  * Copyright 1999 Ulrich Weigand
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <assert.h>
29 #include <ctype.h>
30 #include <stdarg.h>
31 #include <string.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wine/exception.h"
36 #include "build.h"
37
38
39 #ifdef __APPLE__
40 # define __ASM_SKIP ".space"
41 #else
42 # define __ASM_SKIP ".skip"
43 #endif
44
45 static int string_compare( const void *ptr1, const void *ptr2 )
46 {
47     const char * const *str1 = ptr1;
48     const char * const *str2 = ptr2;
49     return strcmp( *str1, *str2 );
50 }
51
52
53 /*******************************************************************
54  *         make_internal_name
55  *
56  * Generate an internal name for an entry point. Used for stubs etc.
57  */
58 static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix )
59 {
60     static char buffer[256];
61     if (odp->name || odp->export_name)
62     {
63         char *p;
64         sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name,
65                  odp->name ? odp->name : odp->export_name );
66         /* make sure name is a legal C identifier */
67         for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
68         if (!*p) return buffer;
69     }
70     sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal );
71     return buffer;
72 }
73
74 /*******************************************************************
75  *         declare_weak_function
76  *
77  * Output a prototype for a weak function.
78  */
79 static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
80 {
81     fprintf( outfile, "#ifdef __GNUC__\n" );
82     fprintf( outfile, "# ifdef __APPLE__\n" );
83     fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params );
84     fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name );
85     fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name );
86     fprintf( outfile, "# else\n" );
87     fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
88     fprintf( outfile, "# endif\n" );
89     fprintf( outfile, "#else\n" );
90     fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
91     fprintf( outfile, "static void __asm__dummy_%s(void)", name );
92     fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name );
93     fprintf( outfile, "#endif\n\n" );
94 }
95
96
97 /*******************************************************************
98  *         output_debug
99  *
100  * Output the debug channels.
101  */
102 static int output_debug( FILE *outfile )
103 {
104     int i;
105
106     if (!nb_debug_channels) return 0;
107     qsort( debug_channels, nb_debug_channels, sizeof(debug_channels[0]), string_compare );
108
109     for (i = 0; i < nb_debug_channels; i++)
110         fprintf( outfile, "char __wine_dbch_%s[] = \"\\003%s\";\n",
111                  debug_channels[i], debug_channels[i] );
112
113     fprintf( outfile, "\nstatic char * const debug_channels[%d] =\n{\n", nb_debug_channels );
114     for (i = 0; i < nb_debug_channels; i++)
115     {
116         fprintf( outfile, "    __wine_dbch_%s", debug_channels[i] );
117         if (i < nb_debug_channels - 1) fprintf( outfile, ",\n" );
118     }
119     fprintf( outfile, "\n};\n\n" );
120     fprintf( outfile, "static void *debug_registration;\n\n" );
121
122     return nb_debug_channels;
123 }
124
125
126 /*******************************************************************
127  *         get_exports_size
128  *
129  * Compute the size of the export table.
130  */
131 static int get_exports_size( DLLSPEC *spec )
132 {
133     int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
134     int i, fwd_size = 0, total_size;
135
136     if (!nr_exports) return 0;
137
138     /* export directory header */
139     total_size = 10 * sizeof(int);
140
141     /* function pointers */
142     total_size += nr_exports * sizeof(int);
143
144     /* function name pointers */
145     total_size += spec->nb_names * sizeof(int);
146
147     /* function ordinals */
148     total_size += spec->nb_names * sizeof(short);
149     if (spec->nb_names % 2) total_size += sizeof(short);
150
151     /* forward strings */
152     for (i = spec->base; i <= spec->limit; i++)
153     {
154         ORDDEF *odp = spec->ordinals[i];
155         if (odp && odp->flags & FLAG_FORWARD) fwd_size += strlen(odp->link_name) + 1;
156     }
157     total_size += (fwd_size + 3) & ~3;
158
159     return total_size;
160 }
161
162
163 /*******************************************************************
164  *         output_exports
165  *
166  * Output the export table for a Win32 module.
167  */
168 static void output_exports( FILE *outfile, DLLSPEC *spec )
169 {
170     int i, fwd_size = 0;
171     int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
172
173     if (!nr_exports) return;
174
175     fprintf( outfile, "/* export table */\n" );
176     fprintf( outfile, "asm(\".data\\n\"\n" );
177     fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
178     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_exports") ":\\n\"\n" );
179
180     /* export directory header */
181
182     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* Characteristics */
183     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* TimeDateStamp */
184     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* MajorVersion/MinorVersion */
185     fprintf( outfile, "    \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
186     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->base );        /* Base */
187     fprintf( outfile, "    \"\\t.long %d\\n\"\n", nr_exports );        /* NumberOfFunctions */
188     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->nb_names );    /* NumberOfNames */
189     fprintf( outfile, "    \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */
190     if (spec->nb_names)
191     {
192         fprintf( outfile, "    \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" );     /* AddressOfNames */
193         fprintf( outfile, "    \"\\t.long __wine_spec_exp_ordinals\\n\"\n" );  /* AddressOfNameOrdinals */
194     }
195     else
196     {
197         fprintf( outfile, "    \"\\t.long 0\\n\"\n" );  /* AddressOfNames */
198         fprintf( outfile, "    \"\\t.long 0\\n\"\n" );  /* AddressOfNameOrdinals */
199     }
200
201     /* output the function pointers */
202
203     fprintf( outfile, "    \"__wine_spec_exports_funcs:\\n\"\n" );
204     for (i = spec->base; i <= spec->limit; i++)
205     {
206         ORDDEF *odp = spec->ordinals[i];
207         if (!odp) fprintf( outfile, "    \"\\t.long 0\\n\"\n" );
208         else switch(odp->type)
209         {
210         case TYPE_EXTERN:
211         case TYPE_STDCALL:
212         case TYPE_VARARGS:
213         case TYPE_CDECL:
214             if (!(odp->flags & FLAG_FORWARD))
215             {
216                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
217             }
218             else
219             {
220                 fprintf( outfile, "    \"\\t.long __wine_spec_forwards+%d\\n\"\n", fwd_size );
221                 fwd_size += strlen(odp->link_name) + 1;
222             }
223             break;
224         case TYPE_STUB:
225             fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
226                      make_internal_name( odp, spec, "stub" ) );
227             break;
228         default:
229             assert(0);
230         }
231     }
232
233     if (spec->nb_names)
234     {
235         /* output the function name pointers */
236
237         int namepos = strlen(spec->file_name) + 1;
238
239         fprintf( outfile, "    \"__wine_spec_exp_name_ptrs:\\n\"\n" );
240         for (i = 0; i < spec->nb_names; i++)
241         {
242             fprintf( outfile, "    \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
243             namepos += strlen(spec->names[i]->name) + 1;
244         }
245     }
246
247     /* output the function names */
248
249     fprintf( outfile, "    \"\\t.text\\n\"\n" );
250     fprintf( outfile, "    \"__wine_spec_exp_names:\\n\"\n" );
251     fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
252     for (i = 0; i < spec->nb_names; i++)
253         fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
254     fprintf( outfile, "    \"\\t.data\\n\"\n" );
255
256     if (spec->nb_names)
257     {
258         /* output the function ordinals */
259
260         fprintf( outfile, "    \"__wine_spec_exp_ordinals:\\n\"\n" );
261         for (i = 0; i < spec->nb_names; i++)
262         {
263             fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n",
264                      spec->names[i]->ordinal - spec->base );
265         }
266         if (spec->nb_names % 2)
267         {
268             fprintf( outfile, "    \"\\t" __ASM_SHORT " 0\\n\"\n" );
269         }
270     }
271
272     /* output forward strings */
273
274     if (fwd_size)
275     {
276         fprintf( outfile, "    \"__wine_spec_forwards:\\n\"\n" );
277         for (i = spec->base; i <= spec->limit; i++)
278         {
279             ORDDEF *odp = spec->ordinals[i];
280             if (odp && (odp->flags & FLAG_FORWARD))
281                 fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
282         }
283         fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
284     }
285
286     /* output relays */
287
288     if (debugging)
289     {
290         for (i = spec->base; i <= spec->limit; i++)
291         {
292             ORDDEF *odp = spec->ordinals[i];
293             unsigned int j, args, mask = 0;
294
295             /* skip nonexistent entry points */
296             if (!odp) goto ignore;
297             /* skip non-functions */
298             if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) goto ignore;
299             /* skip norelay and forward entry points */
300             if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) goto ignore;
301
302             for (j = 0; odp->u.func.arg_types[j]; j++)
303             {
304                 if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
305                 if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
306             }
307             if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
308
309             args = strlen(odp->u.func.arg_types) * sizeof(int);
310
311             switch(odp->type)
312             {
313             case TYPE_STDCALL:
314                 fprintf( outfile, "    \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
315                 fprintf( outfile, "    \"\\tret $%d\\n\"\n", args );
316                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", odp->link_name, mask );
317                 break;
318             case TYPE_CDECL:
319                 fprintf( outfile, "    \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", odp->link_name );
320                 fprintf( outfile, "    \"\\tret\\n\"\n" );
321                 fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n", args );
322                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", odp->link_name, mask );
323                 break;
324             default:
325                 assert(0);
326             }
327             continue;
328
329         ignore:
330             fprintf( outfile, "    \"\\t.long 0,0,0,0\\n\"\n" );
331         }
332     }
333     fprintf( outfile, ");\n" );
334 }
335
336
337 /*******************************************************************
338  *         output_stub_funcs
339  *
340  * Output the functions for stub entry points
341 */
342 static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
343 {
344     int i;
345
346     for (i = 0; i < spec->nb_entry_points; i++)
347     {
348         ORDDEF *odp = &spec->entry_points[i];
349         if (odp->type != TYPE_STUB) continue;
350         fprintf( outfile, "#ifdef __GNUC__\n" );
351         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
352         fprintf( outfile, "#endif\n\n" );
353         fprintf( outfile, "struct exc_record {\n" );
354         fprintf( outfile, "  unsigned int code, flags;\n" );
355         fprintf( outfile, "  void *rec, *addr;\n" );
356         fprintf( outfile, "  unsigned int params;\n" );
357         fprintf( outfile, "  const void *info[15];\n" );
358         fprintf( outfile, "};\n\n" );
359         fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
360         fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
361         fprintf( outfile, "  struct exc_record rec;\n" );
362         fprintf( outfile, "  rec.code    = 0x%08x;\n", EXCEPTION_WINE_STUB );
363         fprintf( outfile, "  rec.flags   = %d;\n", EH_NONCONTINUABLE );
364         fprintf( outfile, "  rec.rec     = 0;\n" );
365         fprintf( outfile, "  rec.params  = 2;\n" );
366         fprintf( outfile, "  rec.info[0] = \"%s\";\n", spec->file_name );
367         fprintf( outfile, "  rec.info[1] = func;\n" );
368         fprintf( outfile, "#ifdef __GNUC__\n" );
369         fprintf( outfile, "  rec.addr = __builtin_return_address(1);\n" );
370         fprintf( outfile, "#else\n" );
371         fprintf( outfile, "  rec.addr = 0;\n" );
372         fprintf( outfile, "#endif\n" );
373         fprintf( outfile, "  for (;;) RtlRaiseException( &rec );\n}\n\n" );
374         break;
375     }
376
377     for (i = 0; i < spec->nb_entry_points; i++)
378     {
379         const ORDDEF *odp = &spec->entry_points[i];
380         if (odp->type != TYPE_STUB) continue;
381         fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
382         if (odp->name)
383             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
384         else if (odp->export_name)
385             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->export_name );
386         else
387             fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
388     }
389 }
390
391
392 /*******************************************************************
393  *         output_dll_init
394  *
395  * Output code for calling a dll constructor and destructor.
396  */
397 void output_dll_init( FILE *outfile, const char *constructor, const char *destructor )
398 {
399 #ifdef __APPLE__
400 /* Mach-O doesn't have an init section */
401     if (constructor)
402     {
403         fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
404         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
405         fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", constructor );
406         fprintf( outfile, "    \"\\t.text\\n\");\n" );
407     }
408     if (destructor)
409     {
410         fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
411         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
412         fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", destructor );
413         fprintf( outfile, "    \"\\t.text\\n\");\n" );
414     }
415 #elif defined(__i386__)
416     if (constructor)
417     {
418         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
419         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
420         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
421     }
422     if (destructor)
423     {
424         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
425         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
426         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
427     }
428 #elif defined(__sparc__)
429     if (constructor)
430     {
431         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
432         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
433         fprintf( outfile, "    \"\\tnop\\n\"\n" );
434         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
435     }
436     if (destructor)
437     {
438         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
439         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
440         fprintf( outfile, "    \"\\tnop\\n\"\n" );
441         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
442     }
443 #elif defined(__powerpc__)
444     if (constructor)
445     {
446         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
447         fprintf( outfile, "    \"\\tbl " __ASM_NAME("%s") "\\n\"\n", constructor );
448         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
449     }
450     if (destructor)
451     {
452         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
453         fprintf( outfile, "    \"\\tbl " __ASM_NAME("%s") "\\n\"\n", destructor );
454         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
455     }
456 #elif defined(__ALPHA__)
457     if (constructor)
458     {
459         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
460         fprintf( outfile, "    \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", constructor );
461         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
462     }
463     if (destructor)
464     {
465         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
466         fprintf( outfile, "    \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", destructor );
467         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
468     }
469 #else
470 #error You need to define the DLL constructor for your architecture
471 #endif
472 }
473
474
475 /*******************************************************************
476  *         BuildSpec32File
477  *
478  * Build a Win32 C file from a spec file.
479  */
480 void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
481 {
482     int exports_size = 0;
483     int nr_exports, nr_imports, nr_delayed;
484     DWORD page_size;
485     const char *init_func = spec->init_func;
486
487 #ifdef HAVE_GETPAGESIZE
488     page_size = getpagesize();
489 #elif defined(__svr4__)
490     page_size = sysconf(_SC_PAGESIZE);
491 #elif defined(_WINDOWS)
492     {
493         SYSTEM_INFO si;
494         GetSystemInfo(&si);
495         page_size = si.dwPageSize;
496     }
497 #else
498 #   error Cannot get the page size on this platform
499 #endif
500
501     nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
502     resolve_imports( spec );
503     exports_size = get_exports_size( spec );
504     output_standard_file_header( outfile );
505
506     /* Reserve some space for the PE header */
507
508     fprintf( outfile, "extern char __wine_spec_pe_header[];\n" );
509     fprintf( outfile, "#ifndef __GNUC__\n" );
510     fprintf( outfile, "static void __asm__dummy_header(void) {\n" );
511     fprintf( outfile, "#endif\n" );
512     fprintf( outfile, "asm(\".text\\n\\t\"\n" );
513     fprintf( outfile, "    \".align %d\\n\"\n", get_alignment(page_size) );
514     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_pe_header") ":\\t" __ASM_SKIP " 65536\\n\\t\"\n" );
515     fprintf( outfile, "    \".data\\n\\t\"\n" );
516     fprintf( outfile, "    \".align %d\\n\"\n", get_alignment(4) );
517     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_data_start") ":\\t.long 1\");\n" );
518     fprintf( outfile, "#ifndef __GNUC__\n" );
519     fprintf( outfile, "}\n" );
520     fprintf( outfile, "#endif\n" );
521
522 #ifdef __APPLE__
523     fprintf( outfile, "static char _end[4];\n" );
524 #else
525     fprintf( outfile, "extern char _end[];\n" );
526 #endif
527     
528     fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
529
530 #ifdef __i386__
531     fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
532 #else
533     fprintf( outfile, "#define __stdcall\n\n" );
534 #endif
535
536     output_stub_funcs( outfile, spec );
537
538     /* Output the DLL imports */
539
540     nr_imports = output_imports( outfile, spec, &nr_delayed );
541
542     /* Output the resources */
543
544     output_resources( outfile, spec );
545
546     /* Output the entry point function */
547
548     fprintf( outfile, "static int __wine_spec_init_state;\n" );
549     fprintf( outfile, "extern int __wine_main_argc;\n" );
550     fprintf( outfile, "extern char **__wine_main_argv;\n" );
551     fprintf( outfile, "extern char **__wine_main_environ;\n" );
552     fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
553 #ifdef __APPLE__
554     fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" );
555     fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" );
556     fprintf( outfile, "{\n" );
557     fprintf( outfile, "    void (*init)(void);\n" );
558     fprintf( outfile, "    _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
559     fprintf( outfile, "    init();\n" );
560     fprintf( outfile, "}\n" );
561     fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
562     fprintf( outfile, "{\n" );
563     fprintf( outfile, "    void (*fini)(void);\n" );
564     fprintf( outfile, "    _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
565     fprintf( outfile, "    fini();\n" );
566     fprintf( outfile, "}\n" );
567     fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
568     fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
569 #else
570     fprintf( outfile, "extern void _init(int, char**, char**);\n" );
571     fprintf( outfile, "extern void _fini();\n" );
572 #endif
573
574     if (spec->characteristics & IMAGE_FILE_DLL)
575     {
576         if (init_func)
577             fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
578         else
579         {
580             declare_weak_function( outfile, "int __stdcall", "DllMain", "void*, unsigned int, void*" );
581             init_func = "DllMain";
582         }
583         fprintf( outfile,
584                  "static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n"
585                  "{\n"
586                  "    int ret;\n"
587                  "    if (reason == %d && __wine_spec_init_state == 1)\n"
588                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
589                  "    ret = %s ? %s( inst, reason, reserved ) : 1;\n"
590                  "    if (reason == %d && __wine_spec_init_state == 1)\n",
591                  DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
592         if (!nr_delayed)
593             fprintf( outfile, "        _fini();\n" );
594         else
595             fprintf( outfile,
596                      "    {\n"
597                      "        extern int __stdcall FreeLibrary(void *);\n"
598                      "        unsigned int i;\n"
599                      "        _fini();\n"
600                      "        for (i = 0; i < sizeof(__wine_delay_imp_hmod)/sizeof(__wine_delay_imp_hmod[0]); i++)\n"
601                      "            if (__wine_delay_imp_hmod[i]) FreeLibrary( __wine_delay_imp_hmod[i] );\n"
602                      "    }\n" );
603         fprintf( outfile, "    return ret;\n}\n" );
604         init_func = "__wine_dll_main";
605     }
606     else switch(spec->subsystem)
607     {
608     case IMAGE_SUBSYSTEM_NATIVE:
609         if (init_func)
610             fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
611         else
612         {
613             declare_weak_function( outfile, "int __stdcall", "DriverEntry", "void*, void*");
614             init_func = "DriverEntry";
615         }
616         fprintf( outfile,
617                  "static int __stdcall __wine_driver_entry( void *obj, void *path )\n"
618                  "{\n"
619                  "    int ret;\n"
620                  "    if (__wine_spec_init_state == 1)\n"
621                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
622                  "    ret = %s ? %s( obj, path ) : 0;\n"
623                  "    if (__wine_spec_init_state == 1) _fini();\n"
624                  "    return ret;\n"
625                  "}\n",
626                  init_func, init_func );
627         init_func = "__wine_driver_entry";
628         break;
629     case IMAGE_SUBSYSTEM_WINDOWS_GUI:
630     case IMAGE_SUBSYSTEM_WINDOWS_CUI:
631         if (init_func)
632             fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
633         else
634         {
635             declare_weak_function( outfile, "int", "main", "int argc, char *argv[]" );
636             declare_weak_function( outfile, "int", "wmain", "int argc, unsigned short *argv[]" );
637             declare_weak_function( outfile, "int __stdcall", "WinMain", "void *,void *,char *,int" );
638         }
639         fprintf( outfile,
640                  "\ntypedef struct {\n"
641                  "    unsigned int cb;\n"
642                  "    char *lpReserved, *lpDesktop, *lpTitle;\n"
643                  "    unsigned int dwX, dwY, dwXSize, dwYSize;\n"
644                  "    unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n"
645                  "    unsigned short wShowWindow, cbReserved2;\n"
646                  "    char *lpReserved2;\n"
647                  "    void *hStdInput, *hStdOutput, *hStdError;\n"
648                  "} STARTUPINFOA;\n"
649                  "extern char * __stdcall GetCommandLineA(void);\n"
650                  "extern void * __stdcall GetModuleHandleA(char *);\n"
651                  "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
652                  "extern void __stdcall ExitProcess(unsigned int);\n"
653                  "static void __wine_exe_main(void)\n"
654                  "{\n"
655                  "    int ret;\n"
656                  "    if (__wine_spec_init_state == 1)\n"
657                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" );
658         if (init_func)
659             fprintf( outfile,
660                      "    ret = %s( __wine_main_argc, __wine_main_argv );\n", init_func );
661         else
662             fprintf( outfile,
663                      "    if (WinMain) {\n"
664                      "        STARTUPINFOA info;\n"
665                      "        char *cmdline = GetCommandLineA();\n"
666                      "        int bcount=0, in_quotes=0;\n"
667                      "        while (*cmdline) {\n"
668                      "            if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
669                      "            else if (*cmdline=='\\\\') bcount++;\n"
670                      "            else if (*cmdline=='\\\"') {\n"
671                      "                if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
672                      "                bcount=0;\n"
673                      "            }\n"
674                      "            else bcount=0;\n"
675                      "            cmdline++;\n"
676                      "        }\n"
677                      "        while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
678                      "        GetStartupInfoA( &info );\n"
679                      "        if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
680                      "        ret = WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
681                      "    }\n"
682                      "    else if (wmain) ret = wmain( __wine_main_argc, __wine_main_wargv );\n"
683                      "    else ret = main( __wine_main_argc, __wine_main_argv );\n" );
684         fprintf( outfile,
685                  "    if (__wine_spec_init_state == 1) _fini();\n"
686                  "    ExitProcess( ret );\n"
687                  "}\n\n" );
688         init_func = "__wine_exe_main";
689         break;
690     }
691
692     /* Output the NT header */
693
694     /* this is the IMAGE_NT_HEADERS structure, but we cannot include winnt.h here */
695     fprintf( outfile, "static const struct image_nt_headers\n{\n" );
696     fprintf( outfile, "  int Signature;\n" );
697     fprintf( outfile, "  struct file_header {\n" );
698     fprintf( outfile, "    short Machine;\n" );
699     fprintf( outfile, "    short NumberOfSections;\n" );
700     fprintf( outfile, "    int   TimeDateStamp;\n" );
701     fprintf( outfile, "    void *PointerToSymbolTable;\n" );
702     fprintf( outfile, "    int   NumberOfSymbols;\n" );
703     fprintf( outfile, "    short SizeOfOptionalHeader;\n" );
704     fprintf( outfile, "    short Characteristics;\n" );
705     fprintf( outfile, "  } FileHeader;\n" );
706     fprintf( outfile, "  struct opt_header {\n" );
707     fprintf( outfile, "    short Magic;\n" );
708     fprintf( outfile, "    char  MajorLinkerVersion, MinorLinkerVersion;\n" );
709     fprintf( outfile, "    int   SizeOfCode;\n" );
710     fprintf( outfile, "    int   SizeOfInitializedData;\n" );
711     fprintf( outfile, "    int   SizeOfUninitializedData;\n" );
712     fprintf( outfile, "    void *AddressOfEntryPoint;\n" );
713     fprintf( outfile, "    void *BaseOfCode;\n" );
714     fprintf( outfile, "    void *BaseOfData;\n" );
715     fprintf( outfile, "    void *ImageBase;\n" );
716     fprintf( outfile, "    int   SectionAlignment;\n" );
717     fprintf( outfile, "    int   FileAlignment;\n" );
718     fprintf( outfile, "    short MajorOperatingSystemVersion;\n" );
719     fprintf( outfile, "    short MinorOperatingSystemVersion;\n" );
720     fprintf( outfile, "    short MajorImageVersion;\n" );
721     fprintf( outfile, "    short MinorImageVersion;\n" );
722     fprintf( outfile, "    short MajorSubsystemVersion;\n" );
723     fprintf( outfile, "    short MinorSubsystemVersion;\n" );
724     fprintf( outfile, "    int   Win32VersionValue;\n" );
725     fprintf( outfile, "    void *SizeOfImage;\n" );
726     fprintf( outfile, "    int   SizeOfHeaders;\n" );
727     fprintf( outfile, "    int   CheckSum;\n" );
728     fprintf( outfile, "    short Subsystem;\n" );
729     fprintf( outfile, "    short DllCharacteristics;\n" );
730     fprintf( outfile, "    int   SizeOfStackReserve;\n" );
731     fprintf( outfile, "    int   SizeOfStackCommit;\n" );
732     fprintf( outfile, "    int   SizeOfHeapReserve;\n" );
733     fprintf( outfile, "    int   SizeOfHeapCommit;\n" );
734     fprintf( outfile, "    int   LoaderFlags;\n" );
735     fprintf( outfile, "    int   NumberOfRvaAndSizes;\n" );
736     fprintf( outfile, "    struct { const void *VirtualAddress; int Size; } DataDirectory[%d];\n",
737              IMAGE_NUMBEROF_DIRECTORY_ENTRIES );
738     fprintf( outfile, "  } OptionalHeader;\n" );
739     fprintf( outfile, "} nt_header = {\n" );
740     fprintf( outfile, "  0x%04x,\n", IMAGE_NT_SIGNATURE );   /* Signature */
741 #ifdef __i386__
742     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 );  /* Machine */
743 #elif defined(__powerpc__)
744     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_POWERPC ); /* Machine */
745 #elif defined(__ALPHA__)
746     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_ALPHA ); /* Machine */
747 #else
748     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_UNKNOWN );  /* Machine */
749 #endif
750     fprintf( outfile, "    0, 0, 0, 0,\n" );
751     fprintf( outfile, "    sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
752     fprintf( outfile, "    0x%04x },\n", spec->characteristics );  /* Characteristics */
753
754     fprintf( outfile, "  { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC );  /* Magic */
755     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorLinkerVersion */
756     fprintf( outfile, "    0, 0, 0,\n" );                /* SizeOfCode/Data */
757     fprintf( outfile, "    %s,\n", init_func );          /* AddressOfEntryPoint */
758     fprintf( outfile, "    0, __wine_spec_data_start,\n" );              /* BaseOfCode/Data */
759     fprintf( outfile, "    __wine_spec_pe_header,\n" );  /* ImageBase */
760     fprintf( outfile, "    %ld,\n", page_size );         /* SectionAlignment */
761     fprintf( outfile, "    %ld,\n", page_size );         /* FileAlignment */
762     fprintf( outfile, "    1, 0,\n" );                   /* Major/MinorOperatingSystemVersion */
763     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorImageVersion */
764     fprintf( outfile, "    %d,\n", spec->subsystem_major );             /* MajorSubsystemVersion */
765     fprintf( outfile, "    %d,\n", spec->subsystem_minor );             /* MinorSubsystemVersion */
766     fprintf( outfile, "    0,\n" );                      /* Win32VersionValue */
767     fprintf( outfile, "    _end,\n" );                   /* SizeOfImage */
768     fprintf( outfile, "    %ld,\n", page_size );         /* SizeOfHeaders */
769     fprintf( outfile, "    0,\n" );                      /* CheckSum */
770     fprintf( outfile, "    0x%04x,\n", spec->subsystem );/* Subsystem */
771     fprintf( outfile, "    0,\n" );                      /* DllCharacteristics */
772     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfStackReserve/Commit */
773              (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
774     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfHeapReserve/Commit */
775              (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
776     fprintf( outfile, "    0,\n" );                      /* LoaderFlags */
777     fprintf( outfile, "    %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES );  /* NumberOfRvaAndSizes */
778     fprintf( outfile, "    {\n" );
779     fprintf( outfile, "      { %s, %d },\n",  /* IMAGE_DIRECTORY_ENTRY_EXPORT */
780              exports_size ? "__wine_spec_exports" : "0", exports_size );
781     fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
782              nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
783     fprintf( outfile, "      { %s, %s },\n",   /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
784              spec->nb_resources ? "&__wine_spec_resources" : "0",
785              spec->nb_resources ? "sizeof(__wine_spec_resources)" : "0" );
786     fprintf( outfile, "    }\n  }\n};\n\n" );
787
788     /* Output the DLL constructor */
789
790     fprintf( outfile,
791              "void __wine_spec_init(void)\n"
792              "{\n"
793              "    extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
794              "    __wine_spec_init_state = 1;\n"
795              "    __wine_dll_register( &nt_header, \"%s\" );\n"
796              "}\n\n",
797              spec->file_name );
798
799     fprintf( outfile,
800              "void __wine_spec_init_ctor(void)\n"
801              "{\n"
802              "    if (__wine_spec_init_state) return;\n"
803              "    __wine_spec_init();\n"
804              "    __wine_spec_init_state = 2;\n"
805              "}\n" );
806
807     fprintf( outfile, "#ifndef __GNUC__\n" );
808     fprintf( outfile, "static void __asm__dummy(void) {\n" );
809     fprintf( outfile, "#endif\n" );
810
811     output_exports( outfile, spec );
812     output_import_thunks( outfile, spec );
813     output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
814
815     fprintf( outfile, "#ifndef __GNUC__\n" );
816     fprintf( outfile, "}\n" );
817     fprintf( outfile, "#endif\n" );
818 }
819
820
821 /*******************************************************************
822  *         BuildDef32File
823  *
824  * Build a Win32 def file from a spec file.
825  */
826 void BuildDef32File( FILE *outfile, DLLSPEC *spec )
827 {
828     const char *name;
829     int i;
830
831     if (spec_file_name)
832         fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n",
833                  spec_file_name );
834     else
835         fprintf( outfile, "; File generated automatically; do not edit!\n\n" );
836
837     fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
838
839     fprintf(outfile, "EXPORTS\n");
840
841     /* Output the exports and relay entry points */
842
843     for(i = 0; i < spec->nb_entry_points; i++)
844     {
845         const ORDDEF *odp = &spec->entry_points[i];
846         int is_data = 0;
847
848         if (!odp) continue;
849         if (odp->type == TYPE_STUB) continue;
850
851         if (odp->name) name = odp->name;
852         else if (odp->export_name) name = odp->export_name;
853         else continue;
854
855         fprintf(outfile, "  %s", name);
856
857         switch(odp->type)
858         {
859         case TYPE_EXTERN:
860             is_data = 1;
861             /* fall through */
862         case TYPE_VARARGS:
863         case TYPE_CDECL:
864             /* try to reduce output */
865             if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
866                 fprintf(outfile, "=%s", odp->link_name);
867             break;
868         case TYPE_STDCALL:
869         {
870             int at_param = strlen(odp->u.func.arg_types) * sizeof(int);
871             if (!kill_at) fprintf(outfile, "@%d", at_param);
872             if  (odp->flags & FLAG_FORWARD)
873             {
874                 fprintf(outfile, "=%s", odp->link_name);
875             }
876             else if (strcmp(name, odp->link_name)) /* try to reduce output */
877             {
878                 fprintf(outfile, "=%s", odp->link_name);
879                 if (!kill_at) fprintf(outfile, "@%d", at_param);
880             }
881             break;
882         }
883         default:
884             assert(0);
885         }
886         fprintf( outfile, " @%d", odp->ordinal );
887         if (!odp->name) fprintf( outfile, " NONAME" );
888         if (is_data) fprintf( outfile, " DATA" );
889         if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
890         fprintf( outfile, "\n" );
891     }
892 }
893
894
895 /*******************************************************************
896  *         BuildDebugFile
897  *
898  * Build the debugging channels source file.
899  */
900 void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
901 {
902     int nr_debug;
903     char *prefix, *p, *constructor, *destructor;
904
905     while (*argv)
906     {
907         if (!parse_debug_channels( srcdir, *argv++ )) exit(1);
908     }
909
910     output_standard_file_header( outfile );
911     nr_debug = output_debug( outfile );
912     if (!nr_debug)
913     {
914         fprintf( outfile, "/* no debug channels found for this module */\n" );
915         return;
916     }
917
918     if (output_file_name)
919     {
920         if ((p = strrchr( output_file_name, '/' ))) p++;
921         prefix = xstrdup( p ? p : output_file_name );
922         if ((p = strchr( prefix, '.' ))) *p = 0;
923         strcpy( p, make_c_identifier(p) );
924     }
925     else prefix = xstrdup( "_" );
926
927     /* Output the DLL constructor */
928
929     constructor = xmalloc( strlen(prefix) + 17 );
930     destructor = xmalloc( strlen(prefix) + 17 );
931     sprintf( constructor, "__wine_dbg_%s_init", prefix );
932     sprintf( destructor, "__wine_dbg_%s_fini", prefix );
933     fprintf( outfile,
934              "#ifdef __GNUC__\n"
935              "void %s(void) __attribute__((constructor));\n"
936              "void %s(void) __attribute__((destructor));\n"
937              "#else\n"
938              "static void __asm__dummy_dll_init(void) {\n",
939              constructor, destructor );
940     output_dll_init( outfile, constructor, destructor );
941     fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
942
943     fprintf( outfile,
944              "void %s(void)\n"
945              "{\n"
946              "    extern void *__wine_dbg_register( char * const *, int );\n"
947              "    if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
948              "}\n\n", constructor, nr_debug );
949     fprintf( outfile,
950              "void %s(void)\n"
951              "{\n"
952              "    extern void __wine_dbg_unregister( void* );\n"
953              "    __wine_dbg_unregister( debug_registration );\n"
954              "}\n", destructor );
955
956     free( constructor );
957     free( destructor );
958     free( prefix );
959 }