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
18 static int name_compare( const void *name1
, const void *name2
)
20 ORDDEF
*odp1
= *(ORDDEF
**)name1
;
21 ORDDEF
*odp2
= *(ORDDEF
**)name2
;
22 return strcmp( odp1
->name
, odp2
->name
);
25 /*******************************************************************
28 * Assign ordinals to all entry points.
30 static void AssignOrdinals(void)
34 if ( !nb_names
) return;
36 /* sort the list of names */
37 qsort( Names
, nb_names
, sizeof(Names
[0]), name_compare
);
39 /* check for duplicate names */
40 for (i
= 0; i
< nb_names
- 1; i
++)
42 if (!strcmp( Names
[i
]->name
, Names
[i
+1]->name
))
44 current_line
= max( Names
[i
]->lineno
, Names
[i
+1]->lineno
);
45 fatal_error( "'%s' redefined (previous definition at line %d)\n",
46 Names
[i
]->name
, min( Names
[i
]->lineno
, Names
[i
+1]->lineno
) );
50 /* start assigning from Base, or from 1 if no ordinal defined yet */
51 if (Base
== MAX_ORDINALS
) Base
= 1;
52 for (i
= 0, ordinal
= Base
; i
< nb_names
; i
++)
54 if (Names
[i
]->ordinal
!= -1) continue; /* already has an ordinal */
55 while (Ordinals
[ordinal
]) ordinal
++;
56 if (ordinal
>= MAX_ORDINALS
)
58 current_line
= Names
[i
]->lineno
;
59 fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS
);
61 Names
[i
]->ordinal
= ordinal
;
62 Ordinals
[ordinal
] = Names
[i
];
64 if (ordinal
> Limit
) Limit
= ordinal
;
68 /*******************************************************************
71 * Output the export table for a Win32 module.
73 static void output_exports( FILE *outfile
, int nr_exports
, int nr_names
, int fwd_size
)
77 if (!nr_exports
) return;
79 fprintf( outfile
, "\n\n/* exports */\n\n" );
80 fprintf( outfile
, "typedef void (*func_ptr)();\n" );
81 fprintf( outfile
, "static struct {\n" );
82 fprintf( outfile
, " struct {\n" );
83 fprintf( outfile
, " unsigned int Characteristics;\n" );
84 fprintf( outfile
, " unsigned int TimeDateStamp;\n" );
85 fprintf( outfile
, " unsigned short MajorVersion;\n" );
86 fprintf( outfile
, " unsigned short MinorVersion;\n" );
87 fprintf( outfile
, " const char *Name;\n" );
88 fprintf( outfile
, " unsigned int Base;\n" );
89 fprintf( outfile
, " unsigned int NumberOfFunctions;\n" );
90 fprintf( outfile
, " unsigned int NumberOfNames;\n" );
91 fprintf( outfile
, " func_ptr *AddressOfFunctions;\n" );
92 fprintf( outfile
, " const char **AddressOfNames;\n" );
93 fprintf( outfile
, " unsigned short *AddressOfNameOrdinals;\n" );
94 fprintf( outfile
, " func_ptr functions[%d];\n", nr_exports
);
97 fprintf( outfile
, " const char *names[%d];\n", nb_names
);
98 fprintf( outfile
, " unsigned short ordinals[%d];\n", nb_names
);
99 if (nb_names
% 2) fprintf( outfile
, " unsigned short pad1;\n" );
103 fprintf( outfile
, " char forwards[%d];\n", (fwd_size
+ 3) & ~3 );
105 fprintf( outfile
, " } exp;\n" );
108 fprintf( outfile
, " struct {\n" );
109 fprintf( outfile
, " unsigned char jmp;\n" );
110 fprintf( outfile
, " unsigned char addr[4];\n" );
111 fprintf( outfile
, " unsigned char ret;\n" );
112 fprintf( outfile
, " unsigned short args;\n" );
113 fprintf( outfile
, " func_ptr orig;\n" );
114 fprintf( outfile
, " unsigned int argtypes;\n" );
115 fprintf( outfile
, " } relay[%d];\n", nr_exports
);
116 #endif /* __i386__ */
118 fprintf( outfile
, "} exports = {\n {\n" );
119 fprintf( outfile
, " 0,\n" ); /* Characteristics */
120 fprintf( outfile
, " 0,\n" ); /* TimeDateStamp */
121 fprintf( outfile
, " 0,\n" ); /* MajorVersion */
122 fprintf( outfile
, " 0,\n" ); /* MinorVersion */
123 fprintf( outfile
, " dllname,\n" ); /* Name */
124 fprintf( outfile
, " %d,\n", Base
); /* Base */
125 fprintf( outfile
, " %d,\n", nr_exports
); /* NumberOfFunctions */
126 fprintf( outfile
, " %d,\n", nb_names
); /* NumberOfNames */
127 fprintf( outfile
, " exports.exp.functions,\n" ); /* AddressOfFunctions */
130 fprintf( outfile
, " exports.exp.names,\n" ); /* AddressOfNames */
131 fprintf( outfile
, " exports.exp.ordinals,\n" ); /* AddressOfNameOrdinals */
135 fprintf( outfile
, " 0,\n" ); /* AddressOfNames */
136 fprintf( outfile
, " 0,\n" ); /* AddressOfNameOrdinals */
139 /* output the function addresses */
141 fprintf( outfile
, " {\n " );
142 for (i
= Base
; i
<= Limit
; i
++)
144 ORDDEF
*odp
= Ordinals
[i
];
145 if (!odp
) fprintf( outfile
, "0" );
146 else switch(odp
->type
)
149 fprintf( outfile
, "%s", odp
->u
.ext
.link_name
);
154 fprintf( outfile
, "%s", odp
->u
.func
.link_name
);
157 fprintf( outfile
, "__stub_%d", i
);
160 fprintf( outfile
, "__regs_%d", i
);
163 fprintf( outfile
, "(func_ptr)&exports.exp.forwards[%d] /* %s */",
164 fwd_pos
, odp
->u
.fwd
.link_name
);
165 fwd_pos
+= strlen(odp
->u
.fwd
.link_name
) + 1;
170 if (i
< Limit
) fprintf( outfile
, ",\n " );
171 else fprintf( outfile
, "\n },\n" );
176 /* output the function names */
178 fprintf( outfile
, " {\n" );
179 for (i
= 0; i
< nb_names
; i
++)
181 if (i
) fprintf( outfile
, ",\n" );
182 fprintf( outfile
, " \"%s\"", Names
[i
]->name
);
184 fprintf( outfile
, "\n },\n" );
186 /* output the function ordinals */
188 fprintf( outfile
, " {\n " );
189 for (i
= 0; i
< nb_names
; i
++)
191 fprintf( outfile
, "%4d", Names
[i
]->ordinal
- Base
);
194 fputc( ',', outfile
);
195 if ((i
% 8) == 7) fprintf( outfile
, "\n " );
198 fprintf( outfile
, "\n },\n" );
199 if (nb_names
% 2) fprintf( outfile
, " 0,\n" );
202 /* output forwards */
206 for (i
= Base
; i
<= Limit
; i
++)
208 ORDDEF
*odp
= Ordinals
[i
];
209 if (odp
&& odp
->type
== TYPE_FORWARD
)
210 fprintf( outfile
, " \"%s\\0\"\n", odp
->u
.fwd
.link_name
);
217 fprintf( outfile
, " },\n {\n" );
218 for (i
= Base
; i
<= Limit
; i
++)
220 ORDDEF
*odp
= Ordinals
[i
];
222 if (odp
&& ((odp
->type
== TYPE_STDCALL
) ||
223 (odp
->type
== TYPE_CDECL
) ||
224 (odp
->type
== TYPE_REGISTER
)))
226 unsigned int j
, mask
= 0;
227 for (j
= 0; odp
->u
.func
.arg_types
[j
]; j
++)
229 if (odp
->u
.func
.arg_types
[j
] == 't') mask
|= 1<< (j
*2);
230 if (odp
->u
.func
.arg_types
[j
] == 'W') mask
|= 2<< (j
*2);
236 fprintf( outfile
, " { 0xe9, { 0,0,0,0 }, 0xc2, 0x%04x, %s, 0x%08x }",
237 strlen(odp
->u
.func
.arg_types
) * sizeof(int),
238 odp
->u
.func
.link_name
, mask
);
241 fprintf( outfile
, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, %s, 0x%08x }",
242 strlen(odp
->u
.func
.arg_types
) * sizeof(int),
243 odp
->u
.func
.link_name
, mask
);
246 fprintf( outfile
, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, __regs_%d, 0x%08x }",
247 0x8000 | (strlen(odp
->u
.func
.arg_types
) * sizeof(int)), i
, mask
);
253 else fprintf( outfile
, " { 0, }" );
255 if (i
< Limit
) fprintf( outfile
, ",\n" );
257 #endif /* __i386__ */
259 fprintf( outfile
, " }\n};\n" );
263 /*******************************************************************
266 * Build a Win32 C file from a spec file.
268 void BuildSpec32File( FILE *outfile
)
271 int i
, fwd_size
= 0, have_regs
= FALSE
;
273 const char *init_func
;
276 #ifdef HAVE_GETPAGESIZE
277 page_size
= getpagesize();
280 page_size
= sysconf(_SC_PAGESIZE
);
282 # error Cannot get the page size on this platform
287 nr_exports
= Base
<= Limit
? Limit
- Base
+ 1 : 0;
289 fprintf( outfile
, "/* File generated automatically from %s; do not edit! */\n\n",
291 fprintf( outfile
, "#include \"builtin32.h\"\n\n" );
293 /* Reserve some space for the PE header */
295 fprintf( outfile
, "extern char pe_header[];\n" );
296 fprintf( outfile
, "asm(\".section .text\\n\\t\"\n" );
297 fprintf( outfile
, " \".align %ld\\n\"\n", page_size
);
298 fprintf( outfile
, " \"pe_header:\\t.fill %ld,1,0\\n\\t\");\n", page_size
);
300 fprintf( outfile
, "static const char dllname[] = \"%s\";\n", DLLName
);
302 /* Output the DLL functions prototypes */
304 for (i
= 0, odp
= EntryPoints
; i
< nb_entry_points
; i
++, odp
++)
309 fprintf( outfile
, "extern void %s();\n", odp
->u
.ext
.link_name
);
314 fprintf( outfile
, "extern void %s();\n", odp
->u
.func
.link_name
);
317 fwd_size
+= strlen(odp
->u
.fwd
.link_name
) + 1;
320 fprintf( outfile
, "extern void __regs_%d();\n", odp
->ordinal
);
326 "static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n",
327 odp
->ordinal
, odp
->name
);
330 "static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n",
331 odp
->ordinal
, odp
->ordinal
);
335 fprintf(stderr
,"build: function type %d not available for Win32\n",
341 /* Output code for all register functions */
345 fprintf( outfile
, "#ifndef __GNUC__\n" );
346 fprintf( outfile
, "static void __asm__dummy(void) {\n" );
347 fprintf( outfile
, "#endif /* !defined(__GNUC__) */\n" );
348 for (i
= 0, odp
= EntryPoints
; i
< nb_entry_points
; i
++, odp
++)
350 if (odp
->type
!= TYPE_REGISTER
) continue;
352 "asm(\".align 4\\n\\t\"\n"
353 " \".type " PREFIX
"__regs_%d,@function\\n\\t\"\n"
354 " \"" PREFIX
"__regs_%d:\\n\\t\"\n"
355 " \"call " PREFIX
"CALL32_Regs\\n\\t\"\n"
356 " \".long " PREFIX
"%s\\n\\t\"\n"
357 " \".byte %d,%d\");\n",
358 odp
->ordinal
, odp
->ordinal
, odp
->u
.func
.link_name
,
359 4 * strlen(odp
->u
.func
.arg_types
),
360 4 * strlen(odp
->u
.func
.arg_types
) );
362 fprintf( outfile
, "#ifndef __GNUC__\n" );
363 fprintf( outfile
, "}\n" );
364 fprintf( outfile
, "#endif /* !defined(__GNUC__) */\n" );
367 /* Output the exports and relay entry points */
369 output_exports( outfile
, nr_exports
, nb_names
, fwd_size
);
371 /* Output the DLL imports */
375 fprintf( outfile
, "static const char * const Imports[%d] =\n{\n", nb_imports
);
376 for (i
= 0; i
< nb_imports
; i
++)
378 fprintf( outfile
, " \"%s\"", DLLImports
[i
] );
379 if (i
< nb_imports
-1) fprintf( outfile
, ",\n" );
381 fprintf( outfile
, "\n};\n\n" );
384 /* Output LibMain function */
386 init_func
= DLLInitFunc
[0] ? DLLInitFunc
: NULL
;
390 if (init_func
) fprintf( outfile
, "extern void %s();\n", init_func
);
392 case SPEC_MODE_GUIEXE
:
393 if (!init_func
) init_func
= "WinMain";
395 "\n#include <winbase.h>\n"
396 "static void exe_main(void)\n"
398 " extern int PASCAL %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n"
399 " STARTUPINFOA info;\n"
400 " LPSTR cmdline = GetCommandLineA();\n"
401 " while (*cmdline && *cmdline != ' ') cmdline++;\n"
402 " if (*cmdline) cmdline++;\n"
403 " GetStartupInfoA( &info );\n"
404 " if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;\n"
405 " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
406 "}\n\n", init_func
, init_func
);
408 "int main( int argc, char *argv[] )\n"
410 " extern void PROCESS_InitWinelib( int, char ** );\n"
411 " PROCESS_InitWinelib( argc, argv );\n"
414 init_func
= "exe_main";
416 case SPEC_MODE_CUIEXE
:
417 if (!init_func
) init_func
= "wine_main";
419 "\n#include <winbase.h>\n"
420 "static void exe_main(void)\n"
422 " extern int %s( int argc, char *argv[] );\n"
423 " extern int _ARGC;\n"
424 " extern char **_ARGV;\n"
425 " ExitProcess( %s( _ARGC, _ARGV ) );\n"
426 "}\n\n", init_func
, init_func
);
428 "int main( int argc, char *argv[] )\n"
430 " extern void PROCESS_InitWinelib( int, char ** );\n"
431 " PROCESS_InitWinelib( argc, argv );\n"
434 init_func
= "exe_main";
438 /* Output the DLL descriptor */
440 if (rsrc_name
[0]) fprintf( outfile
, "extern char %s[];\n\n", rsrc_name
);
442 fprintf( outfile
, "static const BUILTIN32_DESCRIPTOR descriptor =\n{\n" );
443 fprintf( outfile
, " \"%s\",\n", DLLFileName
);
444 fprintf( outfile
, " %d,\n", nb_imports
);
445 fprintf( outfile
, " pe_header,\n" );
446 fprintf( outfile
, " %s,\n", nr_exports
? "&exports" : "0" );
447 fprintf( outfile
, " %s,\n", nr_exports
? "sizeof(exports.exp)" : "0" );
448 fprintf( outfile
, " %s,\n", nb_imports
? "Imports" : "0" );
449 fprintf( outfile
, " %s,\n", init_func
? init_func
: "0" );
450 fprintf( outfile
, " %d,\n", SpecMode
== SPEC_MODE_DLL
? IMAGE_FILE_DLL
: 0 );
451 fprintf( outfile
, " %s\n", rsrc_name
[0] ? rsrc_name
: "0" );
452 fprintf( outfile
, "};\n" );
454 /* Output the DLL constructor */
456 fprintf( outfile
, "#ifdef __GNUC__\n" );
457 fprintf( outfile
, "static void %s_init(void) __attribute__((constructor));\n", DLLName
);
458 fprintf( outfile
, "#else /* defined(__GNUC__) */\n" );
459 fprintf( outfile
, "static void __asm__dummy_dll_init(void) {\n" );
460 fprintf( outfile
, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
461 fprintf( outfile
, " \"\\tcall %s_init\\n\"\n", DLLName
);
462 fprintf( outfile
, " \"\\t.previous\\n\");\n" );
463 fprintf( outfile
, "}\n" );
464 fprintf( outfile
, "#endif /* defined(__GNUC__) */\n" );
465 fprintf( outfile
, "static void %s_init(void) { BUILTIN32_RegisterDLL( &descriptor ); }\n",