Hide the _init and _fini wrappers on darwin.
[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 *name, const char *prototype )
80 {
81     fprintf( outfile, "#ifdef __GNUC__\n" );
82     fprintf( outfile, "# ifdef __APPLE__\n" );
83     fprintf( outfile, "extern %s __attribute__((weak_import));\n", prototype );
84     fprintf( outfile, "# else\n" );
85     fprintf( outfile, "extern %s __attribute__((weak));\n", prototype );
86     fprintf( outfile, "# endif\n" );
87     fprintf( outfile, "#else\n" );
88     fprintf( outfile, "extern %s;\n", prototype );
89     fprintf( outfile, "static void __asm__dummy_%s(void)", name );
90     fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name );
91     fprintf( outfile, "#endif\n\n" );
92 }
93
94
95 /*******************************************************************
96  *         output_debug
97  *
98  * Output the debug channels.
99  */
100 static int output_debug( FILE *outfile )
101 {
102     int i;
103
104     if (!nb_debug_channels) return 0;
105     qsort( debug_channels, nb_debug_channels, sizeof(debug_channels[0]), string_compare );
106
107     for (i = 0; i < nb_debug_channels; i++)
108         fprintf( outfile, "char __wine_dbch_%s[] = \"\\003%s\";\n",
109                  debug_channels[i], debug_channels[i] );
110
111     fprintf( outfile, "\nstatic char * const debug_channels[%d] =\n{\n", nb_debug_channels );
112     for (i = 0; i < nb_debug_channels; i++)
113     {
114         fprintf( outfile, "    __wine_dbch_%s", debug_channels[i] );
115         if (i < nb_debug_channels - 1) fprintf( outfile, ",\n" );
116     }
117     fprintf( outfile, "\n};\n\n" );
118     fprintf( outfile, "static void *debug_registration;\n\n" );
119
120     return nb_debug_channels;
121 }
122
123
124 /*******************************************************************
125  *         output_exports
126  *
127  * Output the export table for a Win32 module.
128  */
129 static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
130 {
131     int i, fwd_size = 0, total_size = 0;
132
133     if (!nr_exports) return 0;
134
135     fprintf( outfile, "asm(\".data\\n\"\n" );
136     fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
137     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_exports") ":\\n\"\n" );
138
139     /* export directory header */
140
141     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* Characteristics */
142     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* TimeDateStamp */
143     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* MajorVersion/MinorVersion */
144     fprintf( outfile, "    \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
145     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->base );        /* Base */
146     fprintf( outfile, "    \"\\t.long %d\\n\"\n", nr_exports );        /* NumberOfFunctions */
147     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->nb_names );    /* NumberOfNames */
148     fprintf( outfile, "    \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */
149     if (spec->nb_names)
150     {
151         fprintf( outfile, "    \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" );     /* AddressOfNames */
152         fprintf( outfile, "    \"\\t.long __wine_spec_exp_ordinals\\n\"\n" );  /* AddressOfNameOrdinals */
153     }
154     else
155     {
156         fprintf( outfile, "    \"\\t.long 0\\n\"\n" );  /* AddressOfNames */
157         fprintf( outfile, "    \"\\t.long 0\\n\"\n" );  /* AddressOfNameOrdinals */
158     }
159     total_size += 10 * sizeof(int);
160
161     /* output the function pointers */
162
163     fprintf( outfile, "    \"__wine_spec_exports_funcs:\\n\"\n" );
164     for (i = spec->base; i <= spec->limit; i++)
165     {
166         ORDDEF *odp = spec->ordinals[i];
167         if (!odp) fprintf( outfile, "    \"\\t.long 0\\n\"\n" );
168         else switch(odp->type)
169         {
170         case TYPE_EXTERN:
171         case TYPE_STDCALL:
172         case TYPE_VARARGS:
173         case TYPE_CDECL:
174             if (!(odp->flags & FLAG_FORWARD))
175             {
176                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
177                          (odp->flags & FLAG_REGISTER) ? make_internal_name( odp, spec, "regs" )
178                          : odp->link_name );
179             }
180             else
181             {
182                 fprintf( outfile, "    \"\\t.long __wine_spec_forwards+%d\\n\"\n", fwd_size );
183                 fwd_size += strlen(odp->link_name) + 1;
184             }
185             break;
186         case TYPE_STUB:
187             fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
188                      make_internal_name( odp, spec, "stub" ) );
189             break;
190         default:
191             assert(0);
192         }
193     }
194     total_size += (spec->limit - spec->base + 1) * sizeof(int);
195
196     if (spec->nb_names)
197     {
198         /* output the function name pointers */
199
200         int namepos = strlen(spec->file_name) + 1;
201
202         fprintf( outfile, "    \"__wine_spec_exp_name_ptrs:\\n\"\n" );
203         for (i = 0; i < spec->nb_names; i++)
204         {
205             fprintf( outfile, "    \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
206             namepos += strlen(spec->names[i]->name) + 1;
207         }
208         total_size += spec->nb_names * sizeof(int);
209     }
210
211     /* output the function names */
212
213     fprintf( outfile, "    \"\\t.text\\n\"\n" );
214     fprintf( outfile, "    \"__wine_spec_exp_names:\\n\"\n" );
215     fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
216     for (i = 0; i < spec->nb_names; i++)
217         fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
218     fprintf( outfile, "    \"\\t.data\\n\"\n" );
219
220     if (spec->nb_names)
221     {
222         /* output the function ordinals */
223
224         fprintf( outfile, "    \"__wine_spec_exp_ordinals:\\n\"\n" );
225         for (i = 0; i < spec->nb_names; i++)
226         {
227             fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n",
228                      spec->names[i]->ordinal - spec->base );
229         }
230         total_size += spec->nb_names * sizeof(short);
231         if (spec->nb_names % 2)
232         {
233             fprintf( outfile, "    \"\\t" __ASM_SHORT " 0\\n\"\n" );
234             total_size += sizeof(short);
235         }
236     }
237
238     /* output forward strings */
239
240     if (fwd_size)
241     {
242         fprintf( outfile, "    \"__wine_spec_forwards:\\n\"\n" );
243         for (i = spec->base; i <= spec->limit; i++)
244         {
245             ORDDEF *odp = spec->ordinals[i];
246             if (odp && (odp->flags & FLAG_FORWARD))
247                 fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
248         }
249         fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
250         total_size += (fwd_size + 3) & ~3;
251     }
252
253     /* output relays */
254
255     if (debugging)
256     {
257         for (i = spec->base; i <= spec->limit; i++)
258         {
259             ORDDEF *odp = spec->ordinals[i];
260             unsigned int j, args, mask = 0;
261             const char *name;
262
263             /* skip non-existent entry points */
264             if (!odp) goto ignore;
265             /* skip non-functions */
266             if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) goto ignore;
267             /* skip norelay and forward entry points */
268             if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) goto ignore;
269
270             for (j = 0; odp->u.func.arg_types[j]; j++)
271             {
272                 if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
273                 if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
274             }
275             if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
276
277             name = odp->link_name;
278             args = strlen(odp->u.func.arg_types) * sizeof(int);
279             if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, spec, "regs" );
280
281             switch(odp->type)
282             {
283             case TYPE_STDCALL:
284                 fprintf( outfile, "    \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name );
285                 fprintf( outfile, "    \"\\tret $%d\\n\"\n", args );
286                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask );
287                 break;
288             case TYPE_CDECL:
289                 fprintf( outfile, "    \"\\tjmp " __ASM_NAME("%s") "\\n\"\n", name );
290                 fprintf( outfile, "    \"\\tret\\n\"\n" );
291                 fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n", args );
292                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") ",0x%08x\\n\"\n", name, mask );
293                 break;
294             default:
295                 assert(0);
296             }
297             continue;
298
299         ignore:
300             fprintf( outfile, "    \"\\t.long 0,0,0,0\\n\"\n" );
301         }
302     }
303
304     fprintf( outfile, "    \"\\t.text\\n\"\n" );
305     fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
306     fprintf( outfile, ");\n\n" );
307
308     return total_size;
309 }
310
311
312 /*******************************************************************
313  *         output_stub_funcs
314  *
315  * Output the functions for stub entry points
316 */
317 static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
318 {
319     int i;
320
321     for (i = 0; i < spec->nb_entry_points; i++)
322     {
323         ORDDEF *odp = &spec->entry_points[i];
324         if (odp->type != TYPE_STUB) continue;
325         fprintf( outfile, "#ifdef __GNUC__\n" );
326         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
327         fprintf( outfile, "#endif\n\n" );
328         fprintf( outfile, "struct exc_record {\n" );
329         fprintf( outfile, "  unsigned int code, flags;\n" );
330         fprintf( outfile, "  void *rec, *addr;\n" );
331         fprintf( outfile, "  unsigned int params;\n" );
332         fprintf( outfile, "  const void *info[15];\n" );
333         fprintf( outfile, "};\n\n" );
334         fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
335         fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
336         fprintf( outfile, "  struct exc_record rec;\n" );
337         fprintf( outfile, "  rec.code    = 0x%08x;\n", EXCEPTION_WINE_STUB );
338         fprintf( outfile, "  rec.flags   = %d;\n", EH_NONCONTINUABLE );
339         fprintf( outfile, "  rec.rec     = 0;\n" );
340         fprintf( outfile, "  rec.params  = 2;\n" );
341         fprintf( outfile, "  rec.info[0] = \"%s\";\n", spec->file_name );
342         fprintf( outfile, "  rec.info[1] = func;\n" );
343         fprintf( outfile, "#ifdef __GNUC__\n" );
344         fprintf( outfile, "  rec.addr = __builtin_return_address(1);\n" );
345         fprintf( outfile, "#else\n" );
346         fprintf( outfile, "  rec.addr = 0;\n" );
347         fprintf( outfile, "#endif\n" );
348         fprintf( outfile, "  for (;;) RtlRaiseException( &rec );\n}\n\n" );
349         break;
350     }
351
352     for (i = 0; i < spec->nb_entry_points; i++)
353     {
354         const ORDDEF *odp = &spec->entry_points[i];
355         if (odp->type != TYPE_STUB) continue;
356         fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
357         if (odp->name)
358             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
359         else if (odp->export_name)
360             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->export_name );
361         else
362             fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
363     }
364 }
365
366
367 /*******************************************************************
368  *         output_register_funcs
369  *
370  * Output the functions for register entry points
371  */
372 static void output_register_funcs( FILE *outfile, DLLSPEC *spec )
373 {
374     const char *name;
375     int i;
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_STDCALL && odp->type != TYPE_CDECL) continue;
381         if (!(odp->flags & FLAG_REGISTER)) continue;
382         if (odp->flags & FLAG_FORWARD) continue;
383         name = make_internal_name( odp, spec, "regs" );
384         fprintf( outfile,
385                  "asm(\".align %d\\n\\t\"\n"
386                  "    \"" __ASM_FUNC("%s") "\\n\\t\"\n"
387                  "    \"" __ASM_NAME("%s") ":\\n\\t\"\n"
388                  "    \"call " __ASM_NAME("__wine_call_from_32_regs") "\\n\\t\"\n"
389                  "    \".long " __ASM_NAME("%s") "\\n\\t\"\n"
390                  "    \".byte %d,%d\");\n",
391                  get_alignment(4),
392                  name, name, odp->link_name,
393                  strlen(odp->u.func.arg_types) * sizeof(int),
394                  (odp->type == TYPE_CDECL) ? 0 : (strlen(odp->u.func.arg_types) * sizeof(int)) );
395     }
396 }
397
398
399 /*******************************************************************
400  *         output_dll_init
401  *
402  * Output code for calling a dll constructor and destructor.
403  */
404 void output_dll_init( FILE *outfile, const char *constructor, const char *destructor )
405 {
406     fprintf( outfile, "#ifndef __GNUC__\n" );
407     fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
408     fprintf( outfile, "#endif\n" );
409
410 #if defined(__i386__)
411     if (constructor)
412     {
413         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
414         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
415         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
416     }
417     if (destructor)
418     {
419         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
420         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
421         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
422     }
423 #elif defined(__sparc__)
424     if (constructor)
425     {
426         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
427         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", constructor );
428         fprintf( outfile, "    \"\\tnop\\n\"\n" );
429         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
430     }
431     if (destructor)
432     {
433         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
434         fprintf( outfile, "    \"\\tcall " __ASM_NAME("%s") "\\n\"\n", destructor );
435         fprintf( outfile, "    \"\\tnop\\n\"\n" );
436         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
437     }
438 #elif defined(__powerpc__)
439 # ifdef __APPLE__
440 /* Mach-O doesn't have an init section */
441     if (constructor)
442     {
443         fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
444         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
445         fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", constructor );
446         fprintf( outfile, "    \"\\t.text\\n\");\n" );
447     }
448     if (destructor)
449     {
450         fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
451         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
452         fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", destructor );
453         fprintf( outfile, "    \"\\t.text\\n\");\n" );
454     }
455 # else /* __APPLE__ */
456     if (constructor)
457     {
458         fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
459         fprintf( outfile, "    \"\\tbl " __ASM_NAME("%s") "\\n\"\n", constructor );
460         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
461     }
462     if (destructor)
463     {
464         fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
465         fprintf( outfile, "    \"\\tbl " __ASM_NAME("%s") "\\n\"\n", destructor );
466         fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
467     }
468 # endif /* __APPLE__ */
469 #else
470 #error You need to define the DLL constructor for your architecture
471 #endif
472     fprintf( outfile, "#ifndef __GNUC__\n" );
473     fprintf( outfile, "}\n" );
474     fprintf( outfile, "#endif\n" );
475 }
476
477
478 /*******************************************************************
479  *         BuildSpec32File
480  *
481  * Build a Win32 C file from a spec file.
482  */
483 void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
484 {
485     int exports_size = 0;
486     int nr_exports, nr_imports;
487     DWORD page_size;
488     const char *init_func = spec->init_func;
489
490 #ifdef HAVE_GETPAGESIZE
491     page_size = getpagesize();
492 #elif defined(__svr4__)
493     page_size = sysconf(_SC_PAGESIZE);
494 #elif defined(_WINDOWS)
495     {
496         SYSTEM_INFO si;
497         GetSystemInfo(&si);
498         page_size = si.dwPageSize;
499     }
500 #else
501 #   error Cannot get the page size on this platform
502 #endif
503
504     nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
505     resolve_imports( spec );
506     output_standard_file_header( outfile );
507
508     /* Reserve some space for the PE header */
509
510     fprintf( outfile, "extern char __wine_spec_pe_header[];\n" );
511     fprintf( outfile, "#ifndef __GNUC__\n" );
512     fprintf( outfile, "static void __asm__dummy_header(void) {\n" );
513     fprintf( outfile, "#endif\n" );
514     fprintf( outfile, "asm(\".text\\n\\t\"\n" );
515     fprintf( outfile, "    \".align %d\\n\"\n", get_alignment(page_size) );
516     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_pe_header") ":\\t" __ASM_SKIP " 65536\\n\\t\"\n" );
517     fprintf( outfile, "    \".data\\n\\t\"\n" );
518     fprintf( outfile, "    \".align %d\\n\"\n", get_alignment(4) );
519     fprintf( outfile, "    \"" __ASM_NAME("__wine_spec_data_start") ":\\t.long 1\");\n" );
520     fprintf( outfile, "#ifndef __GNUC__\n" );
521     fprintf( outfile, "}\n" );
522     fprintf( outfile, "#endif\n" );
523
524 #ifdef __APPLE__
525     fprintf( outfile, "static char _end[4];\n" );
526 #else
527     fprintf( outfile, "extern char _end[];\n" );
528 #endif
529     
530     fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
531
532 #ifdef __i386__
533     fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
534 #else
535     fprintf( outfile, "#define __stdcall\n\n" );
536 #endif
537
538     if (nr_exports)
539     {
540         /* Output the stub functions */
541
542         output_stub_funcs( outfile, spec );
543
544         fprintf( outfile, "#ifndef __GNUC__\n" );
545         fprintf( outfile, "static void __asm__dummy(void) {\n" );
546         fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
547
548         /* Output code for all register functions */
549
550         output_register_funcs( outfile, spec );
551
552         /* Output the exports and relay entry points */
553
554         exports_size = output_exports( outfile, nr_exports, spec );
555
556         fprintf( outfile, "#ifndef __GNUC__\n" );
557         fprintf( outfile, "}\n" );
558         fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
559     }
560
561     /* Output the DLL imports */
562
563     nr_imports = output_imports( outfile, spec );
564
565     /* Output the resources */
566
567     output_resources( outfile, spec );
568
569     /* Output the entry point function */
570
571     fprintf( outfile, "static int __wine_spec_init_state;\n" );
572     fprintf( outfile, "extern int __wine_main_argc;\n" );
573     fprintf( outfile, "extern char **__wine_main_argv;\n" );
574     fprintf( outfile, "extern char **__wine_main_environ;\n" );
575     fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
576 #ifdef __APPLE__
577     fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" );
578     fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" );
579     fprintf( outfile, "{\n" );
580     fprintf( outfile, "    void (*init)(void);\n" );
581     fprintf( outfile, "    _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
582     fprintf( outfile, "    init();\n" );
583     fprintf( outfile, "}\n" );
584     fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
585     fprintf( outfile, "{\n" );
586     fprintf( outfile, "    void (*fini)(void);\n" );
587     fprintf( outfile, "    _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
588     fprintf( outfile, "    fini();\n" );
589     fprintf( outfile, "}\n" );
590     fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
591     fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
592 #else
593     fprintf( outfile, "extern void _init(int, char**, char**);\n" );
594     fprintf( outfile, "extern void _fini();\n" );
595 #endif
596
597     if (spec->characteristics & IMAGE_FILE_DLL)
598     {
599         if (init_func)
600             fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
601         else
602         {
603             declare_weak_function( outfile, "DllMain",
604                                    "int __stdcall DllMain( void*, unsigned int, void* )" );
605             init_func = "DllMain";
606         }
607         fprintf( outfile,
608                  "static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n"
609                  "{\n"
610                  "    int ret;\n"
611                  "    if (reason == %d && __wine_spec_init_state == 1)\n"
612                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
613                  "    ret = %s ? %s( inst, reason, reserved ) : 1;\n"
614                  "    if (reason == %d && __wine_spec_init_state == 1) _fini();\n"
615                  "    return ret;\n"
616                  "}\n",
617                  DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
618         init_func = "__wine_dll_main";
619     }
620     else switch(spec->subsystem)
621     {
622     case IMAGE_SUBSYSTEM_NATIVE:
623         if (init_func)
624             fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
625         else
626         {
627             declare_weak_function( outfile, "DriverEntry",
628                                    "int __stdcall DriverEntry( void*, void* )" );
629             init_func = "DriverEntry";
630         }
631         fprintf( outfile,
632                  "static int __stdcall __wine_driver_entry( void *obj, void *path )\n"
633                  "{\n"
634                  "    int ret;\n"
635                  "    if (__wine_spec_init_state == 1)\n"
636                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
637                  "    ret = %s ? %s( obj, path ) : 0;\n"
638                  "    if (__wine_spec_init_state == 1) _fini();\n"
639                  "    return ret;\n"
640                  "}\n",
641                  init_func, init_func );
642         init_func = "__wine_driver_entry";
643         break;
644     case IMAGE_SUBSYSTEM_WINDOWS_GUI:
645     case IMAGE_SUBSYSTEM_WINDOWS_CUI:
646         if (init_func)
647             fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
648         else
649         {
650             declare_weak_function( outfile, "main", "int main( int argc, char *argv[] )" );
651             declare_weak_function( outfile, "wmain", "int wmain( int argc, unsigned short *argv[] )" );
652             declare_weak_function( outfile, "WinMain", "int __stdcall WinMain(void *,void *,char *,int)" );
653         }
654         fprintf( outfile,
655                  "\ntypedef struct {\n"
656                  "    unsigned int cb;\n"
657                  "    char *lpReserved, *lpDesktop, *lpTitle;\n"
658                  "    unsigned int dwX, dwY, dwXSize, dwYSize;\n"
659                  "    unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n"
660                  "    unsigned short wShowWindow, cbReserved2;\n"
661                  "    char *lpReserved2;\n"
662                  "    void *hStdInput, *hStdOutput, *hStdError;\n"
663                  "} STARTUPINFOA;\n"
664                  "extern char * __stdcall GetCommandLineA(void);\n"
665                  "extern void * __stdcall GetModuleHandleA(char *);\n"
666                  "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
667                  "extern void __stdcall ExitProcess(unsigned int);\n"
668                  "static void __wine_exe_main(void)\n"
669                  "{\n"
670                  "    int ret;\n"
671                  "    if (__wine_spec_init_state == 1)\n"
672                  "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" );
673         if (init_func)
674             fprintf( outfile,
675                      "    ret = %s( __wine_main_argc, __wine_main_argv );\n", init_func );
676         else
677             fprintf( outfile,
678                      "    if (WinMain) {\n"
679                      "        STARTUPINFOA info;\n"
680                      "        char *cmdline = GetCommandLineA();\n"
681                      "        int bcount=0, in_quotes=0;\n"
682                      "        while (*cmdline) {\n"
683                      "            if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
684                      "            else if (*cmdline=='\\\\') bcount++;\n"
685                      "            else if (*cmdline=='\\\"') {\n"
686                      "                if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
687                      "                bcount=0;\n"
688                      "            }\n"
689                      "            else bcount=0;\n"
690                      "            cmdline++;\n"
691                      "        }\n"
692                      "        while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
693                      "        GetStartupInfoA( &info );\n"
694                      "        if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
695                      "        ret = WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
696                      "    }\n"
697                      "    else if (wmain) ret = wmain( __wine_main_argc, __wine_main_wargv );\n"
698                      "    else ret = main( __wine_main_argc, __wine_main_argv );\n" );
699         fprintf( outfile,
700                  "    if (__wine_spec_init_state == 1) _fini();\n"
701                  "    ExitProcess( ret );\n"
702                  "}\n\n" );
703         init_func = "__wine_exe_main";
704         break;
705     }
706
707     /* Output the NT header */
708
709     /* this is the IMAGE_NT_HEADERS structure, but we cannot include winnt.h here */
710     fprintf( outfile, "static const struct image_nt_headers\n{\n" );
711     fprintf( outfile, "  int Signature;\n" );
712     fprintf( outfile, "  struct file_header {\n" );
713     fprintf( outfile, "    short Machine;\n" );
714     fprintf( outfile, "    short NumberOfSections;\n" );
715     fprintf( outfile, "    int   TimeDateStamp;\n" );
716     fprintf( outfile, "    void *PointerToSymbolTable;\n" );
717     fprintf( outfile, "    int   NumberOfSymbols;\n" );
718     fprintf( outfile, "    short SizeOfOptionalHeader;\n" );
719     fprintf( outfile, "    short Characteristics;\n" );
720     fprintf( outfile, "  } FileHeader;\n" );
721     fprintf( outfile, "  struct opt_header {\n" );
722     fprintf( outfile, "    short Magic;\n" );
723     fprintf( outfile, "    char  MajorLinkerVersion, MinorLinkerVersion;\n" );
724     fprintf( outfile, "    int   SizeOfCode;\n" );
725     fprintf( outfile, "    int   SizeOfInitializedData;\n" );
726     fprintf( outfile, "    int   SizeOfUninitializedData;\n" );
727     fprintf( outfile, "    void *AddressOfEntryPoint;\n" );
728     fprintf( outfile, "    void *BaseOfCode;\n" );
729     fprintf( outfile, "    void *BaseOfData;\n" );
730     fprintf( outfile, "    void *ImageBase;\n" );
731     fprintf( outfile, "    int   SectionAlignment;\n" );
732     fprintf( outfile, "    int   FileAlignment;\n" );
733     fprintf( outfile, "    short MajorOperatingSystemVersion;\n" );
734     fprintf( outfile, "    short MinorOperatingSystemVersion;\n" );
735     fprintf( outfile, "    short MajorImageVersion;\n" );
736     fprintf( outfile, "    short MinorImageVersion;\n" );
737     fprintf( outfile, "    short MajorSubsystemVersion;\n" );
738     fprintf( outfile, "    short MinorSubsystemVersion;\n" );
739     fprintf( outfile, "    int   Win32VersionValue;\n" );
740     fprintf( outfile, "    void *SizeOfImage;\n" );
741     fprintf( outfile, "    int   SizeOfHeaders;\n" );
742     fprintf( outfile, "    int   CheckSum;\n" );
743     fprintf( outfile, "    short Subsystem;\n" );
744     fprintf( outfile, "    short DllCharacteristics;\n" );
745     fprintf( outfile, "    int   SizeOfStackReserve;\n" );
746     fprintf( outfile, "    int   SizeOfStackCommit;\n" );
747     fprintf( outfile, "    int   SizeOfHeapReserve;\n" );
748     fprintf( outfile, "    int   SizeOfHeapCommit;\n" );
749     fprintf( outfile, "    int   LoaderFlags;\n" );
750     fprintf( outfile, "    int   NumberOfRvaAndSizes;\n" );
751     fprintf( outfile, "    struct { const void *VirtualAddress; int Size; } DataDirectory[%d];\n",
752              IMAGE_NUMBEROF_DIRECTORY_ENTRIES );
753     fprintf( outfile, "  } OptionalHeader;\n" );
754     fprintf( outfile, "} nt_header = {\n" );
755     fprintf( outfile, "  0x%04x,\n", IMAGE_NT_SIGNATURE );   /* Signature */
756 #ifdef __i386__
757     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 );  /* Machine */
758 #elif defined(__powerpc__)
759     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_POWERPC ); /* Machine */
760 #else
761     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_UNKNOWN );  /* Machine */
762 #endif
763     fprintf( outfile, "    0, 0, 0, 0,\n" );
764     fprintf( outfile, "    sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
765     fprintf( outfile, "    0x%04x },\n", spec->characteristics );  /* Characteristics */
766
767     fprintf( outfile, "  { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC );  /* Magic */
768     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorLinkerVersion */
769     fprintf( outfile, "    0, 0, 0,\n" );                /* SizeOfCode/Data */
770     fprintf( outfile, "    %s,\n", init_func );          /* AddressOfEntryPoint */
771     fprintf( outfile, "    0, __wine_spec_data_start,\n" );              /* BaseOfCode/Data */
772     fprintf( outfile, "    __wine_spec_pe_header,\n" );  /* ImageBase */
773     fprintf( outfile, "    %ld,\n", page_size );         /* SectionAlignment */
774     fprintf( outfile, "    %ld,\n", page_size );         /* FileAlignment */
775     fprintf( outfile, "    1, 0,\n" );                   /* Major/MinorOperatingSystemVersion */
776     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorImageVersion */
777     fprintf( outfile, "    %d,\n", spec->subsystem_major );             /* MajorSubsystemVersion */
778     fprintf( outfile, "    %d,\n", spec->subsystem_minor );             /* MinorSubsystemVersion */
779     fprintf( outfile, "    0,\n" );                      /* Win32VersionValue */
780     fprintf( outfile, "    _end,\n" );                   /* SizeOfImage */
781     fprintf( outfile, "    %ld,\n", page_size );         /* SizeOfHeaders */
782     fprintf( outfile, "    0,\n" );                      /* CheckSum */
783     fprintf( outfile, "    0x%04x,\n", spec->subsystem );/* Subsystem */
784     fprintf( outfile, "    0,\n" );                      /* DllCharacteristics */
785     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfStackReserve/Commit */
786              (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
787     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfHeapReserve/Commit */
788              (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
789     fprintf( outfile, "    0,\n" );                      /* LoaderFlags */
790     fprintf( outfile, "    %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES );  /* NumberOfRvaAndSizes */
791     fprintf( outfile, "    {\n" );
792     fprintf( outfile, "      { %s, %d },\n",  /* IMAGE_DIRECTORY_ENTRY_EXPORT */
793              exports_size ? "__wine_spec_exports" : "0", exports_size );
794     fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
795              nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
796     fprintf( outfile, "      { %s, %s },\n",   /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
797              spec->nb_resources ? "&resources" : "0",
798              spec->nb_resources ? "sizeof(resources)" : "0" );
799     fprintf( outfile, "    }\n  }\n};\n\n" );
800
801     /* Output the DLL constructor */
802
803     fprintf( outfile,
804              "void __wine_spec_init(void)\n"
805              "{\n"
806              "    extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
807              "    __wine_spec_init_state = 1;\n"
808              "    __wine_dll_register( &nt_header, \"%s\" );\n"
809              "}\n\n",
810              spec->file_name );
811
812     output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
813     fprintf( outfile,
814              "void __wine_spec_init_ctor(void)\n"
815              "{\n"
816              "    if (__wine_spec_init_state) return;\n"
817              "    __wine_spec_init();\n"
818              "    __wine_spec_init_state = 2;\n"
819              "}\n" );
820 }
821
822
823 /*******************************************************************
824  *         BuildDef32File
825  *
826  * Build a Win32 def file from a spec file.
827  */
828 void BuildDef32File( FILE *outfile, DLLSPEC *spec )
829 {
830     const char *name;
831     int i;
832
833     fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n",
834             input_file_name );
835
836     fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
837
838     fprintf(outfile, "EXPORTS\n");
839
840     /* Output the exports and relay entry points */
841
842     for(i = 0; i < spec->nb_entry_points; i++)
843     {
844         const ORDDEF *odp = &spec->entry_points[i];
845         int is_data = 0;
846
847         if (!odp) continue;
848         if (odp->flags & FLAG_REGISTER) 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;
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     fprintf( outfile,
930              "#ifdef __GNUC__\n"
931              "void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
932              "void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
933              "#else\n"
934              "static void __asm__dummy_dll_init(void) {\n",
935              prefix, prefix );
936
937 #if defined(__i386__)
938     fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
939     fprintf( outfile, "    \"\\tcall " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
940     fprintf( outfile, "    \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
941     fprintf( outfile, "    \"\\tcall " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
942     fprintf( outfile, "    \"\\t.section\\t\\\".text\\\"\\n\");\n" );
943 #elif defined(__sparc__)
944     fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
945     fprintf( outfile, "    \"\\tcall " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
946     fprintf( outfile, "    \"\\tnop\\n\"\n" );
947     fprintf( outfile, "    \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
948     fprintf( outfile, "    \"\\tcall " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
949     fprintf( outfile, "    \"\\tnop\\n\"\n" );
950     fprintf( outfile, "    \"\\t.section\t\\\".text\\\"\\n\");\n" );
951 #elif defined(__powerpc__)
952 # ifdef __APPLE__
953         fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
954         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
955         fprintf( outfile, "    \"\\t.long " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
956         fprintf( outfile, "    \"\\t.text\\n\");\n" );
957         fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
958         fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
959         fprintf( outfile, "    \"\\t.long " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
960         fprintf( outfile, "    \"\\t.text\\n\");\n" );
961 # else
962     fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
963     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
964     fprintf( outfile, "    \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
965     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
966     fprintf( outfile, "    \"\\t.text\\n\");\n" );
967 # endif
968 #else
969 #error You need to define the DLL constructor for your architecture
970 #endif
971     fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
972
973     fprintf( outfile,
974              "void __wine_dbg_%s_init(void)\n"
975              "{\n"
976              "    extern void *__wine_dbg_register( char * const *, int );\n"
977              "    if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
978              "}\n\n", prefix, nr_debug );
979     fprintf( outfile,
980              "void __wine_dbg_%s_fini(void)\n"
981              "{\n"
982              "    extern void __wine_dbg_unregister( void* );\n"
983              "    __wine_dbg_unregister( debug_registration );\n"
984              "}\n", prefix );
985
986     free( prefix );
987 }