Split the build program in several files.
[wine.git] / tools / winebuild / spec32.c
blob65c2ba7bc9b787a56dafd547c826009f105ad78a
1 /*
2 * 32-bit spec files
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 */
11 #include <assert.h>
12 #include <unistd.h>
14 #include "winbase.h"
15 #include "build.h"
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 /*******************************************************************
26 * AssignOrdinals
28 * Assign ordinals to all entry points.
30 static void AssignOrdinals(void)
32 int i, ordinal;
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 /*******************************************************************
69 * output_exports
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 )
75 int i, fwd_pos = 0;
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 );
95 if (nb_names)
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" );
101 if (fwd_size)
103 fprintf( outfile, " char forwards[%d];\n", (fwd_size + 3) & ~3 );
105 fprintf( outfile, " } exp;\n" );
107 #ifdef __i386__
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 */
128 if (nb_names)
130 fprintf( outfile, " exports.exp.names,\n" ); /* AddressOfNames */
131 fprintf( outfile, " exports.exp.ordinals,\n" ); /* AddressOfNameOrdinals */
133 else
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)
148 case TYPE_EXTERN:
149 fprintf( outfile, "%s", odp->u.ext.link_name );
150 break;
151 case TYPE_STDCALL:
152 case TYPE_VARARGS:
153 case TYPE_CDECL:
154 fprintf( outfile, "%s", odp->u.func.link_name);
155 break;
156 case TYPE_STUB:
157 fprintf( outfile, "__stub_%d", i );
158 break;
159 case TYPE_REGISTER:
160 fprintf( outfile, "__regs_%d", i );
161 break;
162 case TYPE_FORWARD:
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;
166 break;
167 default:
168 assert(0);
170 if (i < Limit) fprintf( outfile, ",\n " );
171 else fprintf( outfile, "\n },\n" );
174 if (nb_names)
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 );
192 if (i < nb_names-1)
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 */
204 if (fwd_size)
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 );
214 /* output relays */
216 #ifdef __i386__
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);
233 switch(odp->type)
235 case TYPE_STDCALL:
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 );
239 break;
240 case TYPE_CDECL:
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 );
244 break;
245 case TYPE_REGISTER:
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 );
248 break;
249 default:
250 assert(0);
253 else fprintf( outfile, " { 0, }" );
255 if (i < Limit) fprintf( outfile, ",\n" );
257 #endif /* __i386__ */
259 fprintf( outfile, " }\n};\n" );
263 /*******************************************************************
264 * BuildSpec32File
266 * Build a Win32 C file from a spec file.
268 void BuildSpec32File( FILE *outfile )
270 ORDDEF *odp;
271 int i, fwd_size = 0, have_regs = FALSE;
272 int nr_exports;
273 const char *init_func;
274 DWORD page_size;
276 #ifdef HAVE_GETPAGESIZE
277 page_size = getpagesize();
278 #else
279 # ifdef __svr4__
280 page_size = sysconf(_SC_PAGESIZE);
281 # else
282 # error Cannot get the page size on this platform
283 # endif
284 #endif
286 AssignOrdinals();
287 nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
289 fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
290 input_file_name );
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++)
306 switch(odp->type)
308 case TYPE_EXTERN:
309 fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name );
310 break;
311 case TYPE_STDCALL:
312 case TYPE_VARARGS:
313 case TYPE_CDECL:
314 fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
315 break;
316 case TYPE_FORWARD:
317 fwd_size += strlen(odp->u.fwd.link_name) + 1;
318 break;
319 case TYPE_REGISTER:
320 fprintf( outfile, "extern void __regs_%d();\n", odp->ordinal );
321 have_regs = TRUE;
322 break;
323 case TYPE_STUB:
324 if (odp->name[0])
325 fprintf( outfile,
326 "static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n",
327 odp->ordinal, odp->name );
328 else
329 fprintf( outfile,
330 "static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n",
331 odp->ordinal, odp->ordinal );
333 break;
334 default:
335 fprintf(stderr,"build: function type %d not available for Win32\n",
336 odp->type);
337 exit(1);
341 /* Output code for all register functions */
343 if ( have_regs )
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;
351 fprintf( outfile,
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 */
373 if (nb_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;
387 switch(SpecMode)
389 case SPEC_MODE_DLL:
390 if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
391 break;
392 case SPEC_MODE_GUIEXE:
393 if (!init_func) init_func = "WinMain";
394 fprintf( outfile,
395 "\n#include <winbase.h>\n"
396 "static void exe_main(void)\n"
397 "{\n"
398 " extern int PASCAL %s(HINSTANCE,HINSTANCE,LPCSTR,INT);\n"
399 " STARTUPINFOA info;\n"
400 " const char *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 );
407 fprintf( outfile,
408 "int main( int argc, char *argv[] )\n"
409 "{\n"
410 " extern void PROCESS_InitWinelib( int, char ** );\n"
411 " PROCESS_InitWinelib( argc, argv );\n"
412 " return 1;\n"
413 "}\n\n" );
414 init_func = "exe_main";
415 break;
416 case SPEC_MODE_CUIEXE:
417 if (!init_func) init_func = "wine_main";
418 fprintf( outfile,
419 "\n#include <winbase.h>\n"
420 "static void exe_main(void)\n"
421 "{\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 );
427 fprintf( outfile,
428 "int main( int argc, char *argv[] )\n"
429 "{\n"
430 " extern void PROCESS_InitWinelib( int, char ** );\n"
431 " PROCESS_InitWinelib( argc, argv );\n"
432 " return 1;\n"
433 "}\n\n" );
434 init_func = "exe_main";
435 break;
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",
466 DLLName );