Moved the generated code segment for 16-bit builtins inside the module
[wine] / tools / winebuild / spec16.c
1 /*
2  * 16-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
31 #include "wine/exception.h"
32 #include "wine/winbase16.h"
33
34 #include "build.h"
35
36
37 /*******************************************************************
38  *         get_cs
39  */
40 #ifdef __i386__
41 static inline unsigned short get_cs(void)
42 {
43     unsigned short res;
44 #ifdef __GNUC__
45     __asm__("movw %%cs,%w0" : "=r"(res));
46 #elif defined(_MSC_VER)
47     __asm { mov res, cs }
48 #else
49     res = 0;
50 #endif
51     return res;
52 }
53 #endif /* __i386__ */
54
55
56 /*******************************************************************
57  *         output_file_header
58  *
59  * Output a file header with the common declarations we need.
60  */
61 static void output_file_header( FILE *outfile )
62 {
63     output_standard_file_header( outfile );
64     fprintf( outfile, "extern struct\n{\n" );
65     fprintf( outfile, "  void *base[8192];\n" );
66     fprintf( outfile, "  unsigned long limit[8192];\n" );
67     fprintf( outfile, "  unsigned char flags[8192];\n" );
68     fprintf( outfile, "} wine_ldt_copy;\n\n" );
69 #ifdef __i386__
70     fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
71 #else
72     fprintf( outfile, "#define __stdcall\n\n" );
73 #endif
74 }
75
76
77 /*******************************************************************
78  *         output_entry_table
79  */
80 static int output_entry_table( unsigned char **ret_buff, DLLSPEC *spec )
81 {
82     int i, prev = 0, prev_sel = -1;
83     unsigned char *pstr, *buffer;
84     unsigned char *bundle = NULL;
85
86     buffer = xmalloc( spec->limit * 5 );  /* we use at most 5 bytes per entry-point */
87     pstr = buffer;
88
89     for (i = 1; i <= spec->limit; i++)
90     {
91         int selector = 0;
92         WORD offset;
93         ORDDEF *odp = spec->ordinals[i];
94         if (!odp) continue;
95
96         switch (odp->type)
97         {
98         case TYPE_CDECL:
99         case TYPE_PASCAL:
100         case TYPE_VARARGS:
101         case TYPE_STUB:
102             selector = 1;  /* Code selector */
103             break;
104         case TYPE_VARIABLE:
105             selector = 2;  /* Data selector */
106             break;
107         case TYPE_ABS:
108             selector = 0xfe;  /* Constant selector */
109             break;
110         default:
111             continue;
112         }
113
114         if (!bundle || prev + 1 != i || prev_sel != selector || *bundle == 255)
115         {
116             /* need to start a new bundle */
117
118             if (prev + 1 != i)
119             {
120                 int skip = i - (prev + 1);
121                 while (skip > 255)
122                 {
123                     *pstr++ = 255;
124                     *pstr++ = 0;
125                     skip -= 255;
126                 }
127                 *pstr++ = skip;
128                 *pstr++ = 0;
129             }
130
131             bundle = pstr;
132             *pstr++ = 0;
133             *pstr++ = selector;
134             prev_sel = selector;
135         }
136         /* output the entry */
137         *pstr++ = 3;  /* flags: exported & public data */
138         offset = odp->offset;
139         memcpy( pstr, &offset, sizeof(WORD) );
140         pstr += sizeof(WORD);
141         (*bundle)++;  /* increment bundle entry count */
142         prev = i;
143     }
144     *pstr++ = 0;
145     if ((pstr - buffer) & 1) *pstr++ = 0;
146     *ret_buff = xrealloc( buffer, pstr - buffer );
147     return pstr - buffer;
148 }
149
150
151 /*******************************************************************
152  *         output_bytes
153  */
154 static void output_bytes( FILE *outfile, const void *buffer, unsigned int size )
155 {
156     unsigned int i;
157     const unsigned char *ptr = buffer;
158
159     fprintf( outfile, "  {" );
160     for (i = 0; i < size; i++)
161     {
162         if (!(i & 7)) fprintf( outfile, "\n   " );
163         fprintf( outfile, " 0x%02x", *ptr++ );
164         if (i < size - 1) fprintf( outfile, "," );
165     }
166     fprintf( outfile, "\n  },\n" );
167 }
168
169
170 #ifdef __i386__
171 /*******************************************************************
172  *         BuildCallFrom16Func
173  *
174  * Build a 16-bit-to-Wine callback glue function.
175  *
176  * The generated routines are intended to be used as argument conversion
177  * routines to be called by the CallFrom16... core. Thus, the prototypes of
178  * the generated routines are (see also CallFrom16):
179  *
180  *  extern WORD WINAPI PREFIX_CallFrom16_C_word_xxx( FARPROC func, LPBYTE args );
181  *  extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args );
182  *  extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args,
183  *                                                   CONTEXT86 *context );
184  *
185  * where 'C' is the calling convention ('p' for pascal or 'c' for cdecl),
186  * and each 'x' is an argument  ('w'=word, 's'=signed word, 'l'=long,
187  * 'p'=linear pointer, 't'=linear pointer to null-terminated string,
188  * 'T'=segmented pointer to null-terminated string).
189  *
190  * The generated routines fetch the arguments from the 16-bit stack (pointed
191  * to by 'args'); the offsets of the single argument values are computed
192  * according to the calling convention and the argument types.  Then, the
193  * 32-bit entry point is called with these arguments.
194  *
195  * For register functions, the arguments (if present) are converted just
196  * the same as for normal functions, but in addition the CONTEXT86 pointer
197  * filled with the current register values is passed to the 32-bit routine.
198  */
199 static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char *prefix )
200 {
201     int i, pos, argsize = 0;
202     int short_ret = 0;
203     int reg_func = 0;
204     int usecdecl = 0;
205     int varargs = 0;
206     const char *args = profile + 7;
207     const char *ret_type;
208
209     /* Parse function type */
210
211     if (!strncmp( "c_", profile, 2 )) usecdecl = 1;
212     else if (!strncmp( "v_", profile, 2 )) varargs = usecdecl = 1;
213     else if (strncmp( "p_", profile, 2 ))
214     {
215         fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
216         return;
217     }
218
219     if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
220     else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
221     else if (strncmp( "long_", profile + 2, 5 ))
222     {
223         fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
224         return;
225     }
226
227     for ( i = 0; args[i]; i++ )
228         switch ( args[i] )
229         {
230         case 'w':  /* word */
231         case 's':  /* s_word */
232             argsize += 2;
233             break;
234         case 'l':  /* long or segmented pointer */
235         case 'T':  /* segmented pointer to null-terminated string */
236         case 'p':  /* linear pointer */
237         case 't':  /* linear pointer to null-terminated string */
238             argsize += 4;
239             break;
240         }
241
242     ret_type = reg_func? "void" : short_ret ? "unsigned short" : "unsigned int";
243
244     fprintf( outfile, "typedef %s (%s*proc_%s_t)( ",
245              ret_type, usecdecl ? "" : "__stdcall ", profile );
246     args = profile + 7;
247     for ( i = 0; args[i]; i++ )
248     {
249         if ( i ) fprintf( outfile, ", " );
250         switch (args[i])
251         {
252         case 'w':           fprintf( outfile, "unsigned short" ); break;
253         case 's':           fprintf( outfile, "short" ); break;
254         case 'l': case 'T': fprintf( outfile, "unsigned int" ); break;
255         case 'p': case 't': fprintf( outfile, "void *" ); break;
256         }
257     }
258     if (reg_func || varargs)
259         fprintf( outfile, "%svoid *", i? ", " : "" );
260     else if ( !i )
261         fprintf( outfile, "void" );
262     fprintf( outfile, " );\n" );
263
264     fprintf( outfile, "static %s __stdcall __wine_%s_CallFrom16_%s( proc_%s_t proc, unsigned char *args%s )\n",
265              ret_type, make_c_identifier(prefix), profile, profile,
266              reg_func? ", void *context" : "" );
267
268     fprintf( outfile, "{\n    %sproc(\n", reg_func ? "" : "return " );
269     args = profile + 7;
270     pos = !usecdecl? argsize : 0;
271     for ( i = 0; args[i]; i++ )
272     {
273         if ( i ) fprintf( outfile, ",\n" );
274         fprintf( outfile, "        " );
275         switch (args[i])
276         {
277         case 'w':  /* word */
278             if ( !usecdecl ) pos -= 2;
279             fprintf( outfile, "*(unsigned short *)(args+%d)", pos );
280             if (  usecdecl ) pos += 2;
281             break;
282
283         case 's':  /* s_word */
284             if ( !usecdecl ) pos -= 2;
285             fprintf( outfile, "*(short *)(args+%d)", pos );
286             if (  usecdecl ) pos += 2;
287             break;
288
289         case 'l':  /* long or segmented pointer */
290         case 'T':  /* segmented pointer to null-terminated string */
291             if ( !usecdecl ) pos -= 4;
292             fprintf( outfile, "*(unsigned int *)(args+%d)", pos );
293             if (  usecdecl ) pos += 4;
294             break;
295
296         case 'p':  /* linear pointer */
297         case 't':  /* linear pointer to null-terminated string */
298             if ( !usecdecl ) pos -= 4;
299             fprintf( outfile, "((char*)wine_ldt_copy.base[*(unsigned short*)(args+%d) >> 3] + *(unsigned short*)(args+%d))",
300                      pos + 2, pos );
301             if (  usecdecl ) pos += 4;
302             break;
303
304         default:
305             fprintf( stderr, "Unknown arg type '%c'\n", args[i] );
306         }
307     }
308     if ( reg_func )
309         fprintf( outfile, "%s        context", i? ",\n" : "" );
310     else if (varargs)
311         fprintf( outfile, "%s        args + %d", i? ",\n" : "", argsize );
312     fprintf( outfile, " );\n}\n\n" );
313 }
314 #endif
315
316
317 /*******************************************************************
318  *         get_function_name
319  */
320 static const char *get_function_name( const ORDDEF *odp )
321 {
322     static char buffer[80];
323
324     sprintf( buffer, "%s_%s_%s",
325              (odp->type == TYPE_PASCAL) ? "p" :
326              (odp->type == TYPE_VARARGS) ? "v" : "c",
327              (odp->flags & FLAG_REGISTER) ? "regs" :
328              (odp->flags & FLAG_RET16) ? "word" : "long",
329              odp->u.func.arg_types );
330     return buffer;
331 }
332
333
334 /*******************************************************************
335  *         Spec16TypeCompare
336  */
337 static int Spec16TypeCompare( const void *e1, const void *e2 )
338 {
339     const ORDDEF *odp1 = *(const ORDDEF * const *)e1;
340     const ORDDEF *odp2 = *(const ORDDEF * const *)e2;
341     int retval;
342     int type1 = odp1->type;
343     int type2 = odp2->type;
344
345     if (type1 == TYPE_STUB) type1 = TYPE_CDECL;
346     if (type2 == TYPE_STUB) type2 = TYPE_CDECL;
347
348     if ((retval = type1 - type2) != 0) return retval;
349
350     type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER);
351     type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER);
352
353     if ((retval = type1 - type2) != 0) return retval;
354
355     return strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
356 }
357
358
359 /*******************************************************************
360  *         output_stub_funcs
361  *
362  * Output the functions for stub entry points
363 */
364 static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
365 {
366     int i;
367     char *p;
368
369     for (i = 0; i <= spec->limit; i++)
370     {
371         ORDDEF *odp = spec->ordinals[i];
372         if (!odp || odp->type != TYPE_STUB) continue;
373         fprintf( outfile, "#ifdef __GNUC__\n" );
374         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
375         fprintf( outfile, "#endif\n" );
376         fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
377         fprintf( outfile, "  extern void __stdcall RaiseException( unsigned int, unsigned int, unsigned int, const void ** );\n" );
378         fprintf( outfile, "  const void *args[2];\n" );
379         fprintf( outfile, "  args[0] = \"%s\";\n", spec->file_name );
380         fprintf( outfile, "  args[1] = func;\n" );
381         fprintf( outfile, "  for (;;) RaiseException( 0x%08x, %d, 2, args );\n}\n\n",
382                  EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
383         break;
384     }
385     for (i = 0; i <= spec->limit; i++)
386     {
387         ORDDEF *odp = spec->ordinals[i];
388         if (!odp || odp->type != TYPE_STUB) continue;
389         odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 );
390         strcpy( odp->link_name, "__wine_stub_" );
391         strcat( odp->link_name, odp->name );
392         for (p = odp->link_name; *p; p++) if (!isalnum(*p)) *p = '_';
393         fprintf( outfile, "static void %s(void) { __wine_unimplemented(\"%s\"); }\n",
394                  odp->link_name, odp->name );
395     }
396 }
397
398
399 /*******************************************************************
400  *         BuildSpec16File
401  *
402  * Build a Win16 assembly file from a spec file.
403  */
404 void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
405 {
406     ORDDEF **type, **typelist;
407     int i, nFuncs, nTypes;
408     unsigned char *resdir_buffer, *resdata_buffer, *et_buffer, *data_buffer;
409     unsigned char string[256];
410     unsigned int ne_offset, segtable_offset, impnames_offset;
411     unsigned int entrypoint_size, callfrom_size;
412     unsigned int code_size, code_offset;
413     unsigned int data_size, data_offset;
414     unsigned int resnames_size, resnames_offset;
415     unsigned int resdir_size, resdir_offset;
416     unsigned int resdata_size, resdata_offset, resdata_align;
417     unsigned int et_size, et_offset;
418
419     char constructor[100], destructor[100];
420 #ifdef __i386__
421     unsigned short code_selector = get_cs();
422 #endif
423
424     /* File header */
425
426     output_file_header( outfile );
427     fprintf( outfile, "extern unsigned short __wine_call_from_16_word();\n" );
428     fprintf( outfile, "extern unsigned int __wine_call_from_16_long();\n" );
429     fprintf( outfile, "extern void __wine_call_from_16_regs();\n" );
430     fprintf( outfile, "extern void __wine_call_from_16_thunk();\n" );
431
432     data_buffer = xmalloc( 0x10000 );
433     memset( data_buffer, 0, 16 );
434     data_size = 16;
435
436     if (!spec->dll_name)  /* set default name from file name */
437     {
438         char *p;
439         spec->dll_name = xstrdup( spec->file_name );
440         if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
441     }
442
443     output_stub_funcs( outfile, spec );
444
445     /* Build sorted list of all argument types, without duplicates */
446
447     typelist = (ORDDEF **)calloc( spec->limit+1, sizeof(ORDDEF *) );
448
449     for (i = nFuncs = 0; i <= spec->limit; i++)
450     {
451         ORDDEF *odp = spec->ordinals[i];
452         if (!odp) continue;
453         switch (odp->type)
454         {
455           case TYPE_CDECL:
456           case TYPE_PASCAL:
457           case TYPE_VARARGS:
458           case TYPE_STUB:
459             typelist[nFuncs++] = odp;
460
461           default:
462             break;
463         }
464     }
465
466     qsort( typelist, nFuncs, sizeof(ORDDEF *), Spec16TypeCompare );
467
468     i = nTypes = 0;
469     while ( i < nFuncs )
470     {
471         typelist[nTypes++] = typelist[i++];
472         while ( i < nFuncs && Spec16TypeCompare( typelist + i, typelist + nTypes-1 ) == 0 )
473             i++;
474     }
475
476     /* Output CallFrom16 routines needed by this .spec file */
477 #ifdef __i386__
478     for ( i = 0; i < nTypes; i++ )
479     {
480         char profile[101];
481
482         strcpy( profile, get_function_name( typelist[i] ));
483         BuildCallFrom16Func( outfile, profile, spec->file_name );
484     }
485 #endif
486
487     /* compute code and data sizes, set offsets, and output prototypes */
488
489 #ifdef __i386__
490     entrypoint_size = 2 + 5 + 4;    /* pushw bp + pushl target + call */
491     callfrom_size = 5 + 7 + 4 + 8;  /* pushl relay + lcall cs:glue + lret n + args */
492 #else
493     entrypoint_size = 4 + 4;  /* target + call */
494     callfrom_size = 4 + 8;    /* lret n + args */
495 #endif
496     code_size = nTypes * callfrom_size;
497
498     for (i = 0; i <= spec->limit; i++)
499     {
500         ORDDEF *odp = spec->ordinals[i];
501         if (!odp) continue;
502         switch (odp->type)
503         {
504         case TYPE_ABS:
505             odp->offset = LOWORD(odp->u.abs.value);
506             break;
507         case TYPE_VARIABLE:
508             odp->offset = data_size;
509             memcpy( data_buffer + data_size, odp->u.var.values, odp->u.var.n_values * sizeof(int) );
510             data_size += odp->u.var.n_values * sizeof(int);
511             break;
512         case TYPE_CDECL:
513         case TYPE_PASCAL:
514         case TYPE_VARARGS:
515             fprintf( outfile, "extern void %s();\n", odp->link_name );
516             /* fall through */
517         case TYPE_STUB:
518             odp->offset = code_size;
519             code_size += entrypoint_size;
520             break;
521         default:
522             assert(0);
523             break;
524         }
525     }
526     data_buffer = xrealloc( data_buffer, data_size );  /* free unneeded data */
527
528     /* Output the module structure */
529
530     /* DOS header */
531
532     fprintf( outfile, "\n#include \"pshpack1.h\"\n" );
533     fprintf( outfile, "static const struct module_data\n{\n" );
534     fprintf( outfile, "  struct\n  {\n" );
535     fprintf( outfile, "    unsigned short e_magic;\n" );
536     fprintf( outfile, "    unsigned short e_cblp;\n" );
537     fprintf( outfile, "    unsigned short e_cp;\n" );
538     fprintf( outfile, "    unsigned short e_crlc;\n" );
539     fprintf( outfile, "    unsigned short e_cparhdr;\n" );
540     fprintf( outfile, "    unsigned short e_minalloc;\n" );
541     fprintf( outfile, "    unsigned short e_maxalloc;\n" );
542     fprintf( outfile, "    unsigned short e_ss;\n" );
543     fprintf( outfile, "    unsigned short e_sp;\n" );
544     fprintf( outfile, "    unsigned short e_csum;\n" );
545     fprintf( outfile, "    unsigned short e_ip;\n" );
546     fprintf( outfile, "    unsigned short e_cs;\n" );
547     fprintf( outfile, "    unsigned short e_lfarlc;\n" );
548     fprintf( outfile, "    unsigned short e_ovno;\n" );
549     fprintf( outfile, "    unsigned short e_res[4];\n" );
550     fprintf( outfile, "    unsigned short e_oemid;\n" );
551     fprintf( outfile, "    unsigned short e_oeminfo;\n" );
552     fprintf( outfile, "    unsigned short e_res2[10];\n" );
553     fprintf( outfile, "    unsigned int   e_lfanew;\n" );
554     fprintf( outfile, "  } dos_header;\n" );
555
556     /* NE header */
557
558     ne_offset = 64;
559     fprintf( outfile, "  struct\n  {\n" );
560     fprintf( outfile, "    unsigned short  ne_magic;\n" );
561     fprintf( outfile, "    unsigned char   ne_ver;\n" );
562     fprintf( outfile, "    unsigned char   ne_rev;\n" );
563     fprintf( outfile, "    unsigned short  ne_enttab;\n" );
564     fprintf( outfile, "    unsigned short  ne_cbenttab;\n" );
565     fprintf( outfile, "    int             ne_crc;\n" );
566     fprintf( outfile, "    unsigned short  ne_flags;\n" );
567     fprintf( outfile, "    unsigned short  ne_autodata;\n" );
568     fprintf( outfile, "    unsigned short  ne_heap;\n" );
569     fprintf( outfile, "    unsigned short  ne_stack;\n" );
570     fprintf( outfile, "    unsigned int    ne_csip;\n" );
571     fprintf( outfile, "    unsigned int    ne_sssp;\n" );
572     fprintf( outfile, "    unsigned short  ne_cseg;\n" );
573     fprintf( outfile, "    unsigned short  ne_cmod;\n" );
574     fprintf( outfile, "    unsigned short  ne_cbnrestab;\n" );
575     fprintf( outfile, "    unsigned short  ne_segtab;\n" );
576     fprintf( outfile, "    unsigned short  ne_rsrctab;\n" );
577     fprintf( outfile, "    unsigned short  ne_restab;\n" );
578     fprintf( outfile, "    unsigned short  ne_modtab;\n" );
579     fprintf( outfile, "    unsigned short  ne_imptab;\n" );
580     fprintf( outfile, "    unsigned int    ne_nrestab;\n" );
581     fprintf( outfile, "    unsigned short  ne_cmovent;\n" );
582     fprintf( outfile, "    unsigned short  ne_align;\n" );
583     fprintf( outfile, "    unsigned short  ne_cres;\n" );
584     fprintf( outfile, "    unsigned char   ne_exetyp;\n" );
585     fprintf( outfile, "    unsigned char   ne_flagsothers;\n" );
586     fprintf( outfile, "    unsigned short  ne_pretthunks;\n" );
587     fprintf( outfile, "    unsigned short  ne_psegrefbytes;\n" );
588     fprintf( outfile, "    unsigned short  ne_swaparea;\n" );
589     fprintf( outfile, "    unsigned short  ne_expver;\n" );
590     fprintf( outfile, "  } os2_header;\n" );
591
592     /* segment table */
593
594     segtable_offset = 64;
595     fprintf( outfile, "  struct\n  {\n" );
596     fprintf( outfile, "    unsigned short filepos;\n" );
597     fprintf( outfile, "    unsigned short size;\n" );
598     fprintf( outfile, "    unsigned short flags;\n" );
599     fprintf( outfile, "    unsigned short minsize;\n" );
600     fprintf( outfile, "  } segtable[2];\n" );
601
602     /* resource directory */
603
604     resdir_offset = segtable_offset + 2 * 8;
605     resdir_size = get_res16_directory_size( spec );
606     fprintf( outfile, "  unsigned char resdir[%d];\n", resdir_size );
607
608     /* resident names table */
609
610     resnames_offset = resdir_offset + resdir_size;
611     fprintf( outfile, "  struct\n  {\n" );
612     fprintf( outfile, "    struct { unsigned char len; char name[%d]; unsigned short ord; } name_0;\n",
613              strlen( spec->dll_name ) );
614     resnames_size = 3 + strlen( spec->dll_name );
615     for (i = 1; i <= spec->limit; i++)
616     {
617         ORDDEF *odp = spec->ordinals[i];
618         if (!odp || !odp->name[0]) continue;
619         fprintf( outfile, "    struct { unsigned char len; char name[%d]; unsigned short ord; } name_%d;\n",
620                  strlen(odp->name), i );
621         resnames_size += 3 + strlen( odp->name );
622     }
623     fprintf( outfile, "    unsigned char name_last[%d];\n", 2 - (resnames_size & 1) );
624     resnames_size = (resnames_size + 2) & ~1;
625     fprintf( outfile, "  } resnames;\n" );
626
627     /* imported names table */
628
629     impnames_offset = resnames_offset + resnames_size;
630     fprintf( outfile, "  unsigned char impnames[2];\n" );
631
632     /* entry table */
633
634     et_offset = impnames_offset + 2;
635     et_size = output_entry_table( &et_buffer, spec );
636     fprintf( outfile, "  unsigned char entry_table[%d];\n", et_size );
637
638     /* code segment */
639
640     code_offset = et_offset + et_size;
641     fprintf( outfile, "  struct {\n" );
642 #ifdef __i386__
643     fprintf( outfile, "    unsigned char pushl;\n" );      /* pushl $relay */
644     fprintf( outfile, "    void *relay;\n" );
645     fprintf( outfile, "    unsigned char lcall;\n" );      /* lcall __FLATCS__:glue */
646     fprintf( outfile, "    void *glue;\n" );
647     fprintf( outfile, "    unsigned short flatcs;\n" );
648 #endif
649     fprintf( outfile, "    unsigned short lret;\n" );      /* lret $args */
650     fprintf( outfile, "    unsigned short args;\n" );
651     fprintf( outfile, "    unsigned int arg_types[2];\n" );
652     fprintf( outfile, "  } call[%d];\n", nTypes );
653     fprintf( outfile, "  struct {\n" );
654 #ifdef __i386__
655     fprintf( outfile, "    unsigned short pushw_bp;\n" );  /* pushw %bp */
656     fprintf( outfile, "    unsigned char pushl;\n" );      /* pushl $target */
657 #endif
658     fprintf( outfile, "    void (*target)();\n" );
659     fprintf( outfile, "    unsigned short call;\n" );      /* call CALLFROM16 */
660     fprintf( outfile, "    short callfrom16;\n" );
661     fprintf( outfile, "  } entry[%d];\n", nFuncs );
662
663     /* data segment */
664
665     data_offset = code_offset + code_size;
666     fprintf( outfile, "  unsigned char data_segment[%d];\n", data_size );
667     if (data_offset + data_size >= 0x10000)
668         fatal_error( "Not supported yet: 16-bit module data larger than 64K\n" );
669
670     /* resource data */
671
672     resdata_offset = ne_offset + data_offset + data_size;
673     for (resdata_align = 0; resdata_align < 16; resdata_align++)
674     {
675         unsigned int size = get_res16_data_size( spec, resdata_offset, resdata_align );
676         if ((resdata_offset + size) >> resdata_align <= 0xffff) break;
677     }
678     output_res16_directory( &resdir_buffer, spec, resdata_offset, resdata_align );
679     resdata_size = output_res16_data( &resdata_buffer, spec, resdata_offset, resdata_align );
680     if (resdata_size) fprintf( outfile, "  unsigned char resources[%d];\n", resdata_size );
681
682     /* Output the module data */
683
684     /* DOS header */
685
686     fprintf( outfile, "} module =\n{\n  {\n" );
687     fprintf( outfile, "    0x%04x,\n", IMAGE_DOS_SIGNATURE );  /* e_magic */
688     fprintf( outfile, "    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n" );
689     fprintf( outfile, "    { 0, 0, 0, 0, }, 0, 0,\n" );
690     fprintf( outfile, "    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n" );
691     fprintf( outfile, "    sizeof(module.dos_header)\n" );  /* e_lfanew */
692
693     /* NE header */
694
695     fprintf( outfile, "  },\n  {\n" );
696     fprintf( outfile, "    0x%04x,\n", IMAGE_OS2_SIGNATURE ); /* ne_magic */
697     fprintf( outfile, "    0, 0,\n" );
698     fprintf( outfile, "    %d,\n", et_offset );               /* ne_enttab */
699     fprintf( outfile, "    sizeof(module.entry_table),\n" );  /* ne_cbenttab */
700     fprintf( outfile, "    0,\n" );                           /* ne_crc */
701     fprintf( outfile, "    0x%04x,\n",                        /* ne_flags */
702              NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE );
703     fprintf( outfile, "    2,\n" );                           /* ne_autodata */
704     fprintf( outfile, "    %d,\n", spec->heap_size );         /* ne_heap */
705     fprintf( outfile, "    0, 0, 0,\n" );
706     fprintf( outfile, "    2,\n" );                           /* ne_cseg */
707     fprintf( outfile, "    0,\n" );                           /* ne_cmod */
708     fprintf( outfile, "    0,\n" );                           /* ne_cbnrestab */
709     fprintf( outfile, "    %d,\n", segtable_offset );         /* ne_segtab */
710     fprintf( outfile, "    %d,\n", resdir_offset );           /* ne_rsrctab */
711     fprintf( outfile, "    %d,\n", resnames_offset );         /* ne_restab */
712     fprintf( outfile, "    %d,\n", impnames_offset );         /* ne_modtab */
713     fprintf( outfile, "    %d,\n", impnames_offset );         /* ne_imptab */
714     fprintf( outfile, "    0,\n" );                           /* ne_nrestab */
715     fprintf( outfile, "    0,\n" );                           /* ne_cmovent */
716     fprintf( outfile, "    0,\n" );                           /* ne_align */
717     fprintf( outfile, "    0,\n" );                           /* ne_cres */
718     fprintf( outfile, "    0x%04x,\n", NE_OSFLAGS_WINDOWS );  /* ne_exetyp */
719     fprintf( outfile, "    0x%04x,\n", NE_AFLAGS_FASTLOAD );  /* ne_flagsothers */
720     fprintf( outfile, "    0,\n" );                           /* ne_pretthunks */
721     fprintf( outfile, "    0,\n" );                           /* ne_psegrefbytes */
722     fprintf( outfile, "    0,\n" );                           /* ne_swaparea */
723     fprintf( outfile, "    0\n" );                            /* ne_expver */
724     fprintf( outfile, "  },\n" );
725
726     /* segment table */
727
728     fprintf( outfile, "  {\n" );
729     fprintf( outfile, "    { %d, %d, 0x%04x, %d },\n",
730              ne_offset + code_offset, code_size, NE_SEGFLAGS_32BIT, code_size );
731     fprintf( outfile, "    { %d, %d, 0x%04x, %d },\n",
732              ne_offset + data_offset, data_size, NE_SEGFLAGS_DATA, data_size );
733     fprintf( outfile, "  },\n" );
734
735     /* resource directory */
736
737     output_bytes( outfile, resdir_buffer, resdir_size );
738     free( resdir_buffer );
739
740     /* resident names table */
741
742     fprintf( outfile, "  {\n" );
743     strcpy( string, spec->dll_name );
744     fprintf( outfile, "    { %d, \"%s\", 0 },\n", strlen(string), strupper(string) );
745     for (i = 1; i <= spec->limit; i++)
746     {
747         ORDDEF *odp = spec->ordinals[i];
748         if (!odp || !odp->name[0]) continue;
749         strcpy( string, odp->name );
750         fprintf( outfile, "    { %d, \"%s\", %d },\n", strlen(string), strupper(string), i );
751     }
752     fprintf( outfile, "    { 0 }\n  },\n" );
753
754     /* imported names table */
755
756     fprintf( outfile, "  { 0, 0 },\n" );
757
758     /* entry table */
759
760     output_bytes( outfile, et_buffer, et_size );
761     free( et_buffer );
762
763     /* code segment */
764
765     fprintf( outfile, "  {\n" );
766     for ( i = 0; i < nTypes; i++ )
767     {
768         char profile[101], *arg;
769         unsigned int arg_types[2];
770         int j, argsize = 0;
771
772         strcpy( profile, get_function_name( typelist[i] ));
773         if ( typelist[i]->type == TYPE_PASCAL )
774             for ( arg = typelist[i]->u.func.arg_types; *arg; arg++ )
775                 switch ( *arg )
776                 {
777                 case 'w':  /* word */
778                 case 's':  /* s_word */
779                     argsize += 2;
780                     break;
781                 case 'l':  /* long or segmented pointer */
782                 case 'T':  /* segmented pointer to null-terminated string */
783                 case 'p':  /* linear pointer */
784                 case 't':  /* linear pointer to null-terminated string */
785                     argsize += 4;
786                     break;
787                 }
788
789         /* build the arg types bit fields */
790         arg_types[0] = arg_types[1] = 0;
791         for (j = 0; typelist[i]->u.func.arg_types[j]; j++)
792         {
793             int type = 0;
794             switch(typelist[i]->u.func.arg_types[j])
795             {
796             case 'w': type = ARG_WORD; break;
797             case 's': type = ARG_SWORD; break;
798             case 'l': type = ARG_LONG; break;
799             case 'p': type = ARG_PTR; break;
800             case 't': type = ARG_STR; break;
801             case 'T': type = ARG_SEGSTR; break;
802             }
803             arg_types[j / 10] |= type << (3 * (j % 10));
804         }
805         if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
806         if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
807
808 #ifdef __i386__
809         fprintf( outfile, "    { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
810                  make_c_identifier(spec->file_name), profile,
811                  (typelist[i]->flags & FLAG_REGISTER) ? "regs":
812                  (typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
813         if (argsize)
814             fprintf( outfile, "      0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n",
815                      code_selector, argsize, arg_types[0], arg_types[1] );
816         else
817             fprintf( outfile, "      0x%04x, 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
818                      code_selector, arg_types[0], arg_types[1] );
819 #else
820         if (argsize)
821             fprintf( outfile, "    { 0xca66, %d, { 0x%08x, 0x%08x } },\n",
822                      argsize, arg_types[0], arg_types[1] );
823         else
824             fprintf( outfile, "     { 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
825                      arg_types[0], arg_types[1] );
826 #endif
827     }
828     fprintf( outfile, "  },\n  {\n" );
829
830     for (i = 0; i <= spec->limit; i++)
831     {
832         ORDDEF *odp = spec->ordinals[i];
833         if (!odp) continue;
834         switch (odp->type)
835         {
836           case TYPE_CDECL:
837           case TYPE_PASCAL:
838           case TYPE_VARARGS:
839           case TYPE_STUB:
840             type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
841             assert( type );
842
843             fprintf( outfile, "    /* %s.%d */ ", spec->dll_name, i );
844             fprintf( outfile,
845 #ifdef __i386__
846                      "{ 0x5566, 0x68, %s, 0xe866, %d  /* %s */ },\n",
847 #else
848                      "{ %s, 0xe866, %d, /* %s */ },\n",
849 #endif
850                      odp->link_name,
851                      (type - typelist) * callfrom_size - (odp->offset + entrypoint_size),
852                      get_function_name( odp ) );
853             break;
854         default:
855             break;
856         }
857     }
858     fprintf( outfile, "  },\n" );
859
860
861     /* data_segment */
862
863     output_bytes( outfile, data_buffer, data_size );
864     free( data_buffer );
865
866     /* resource data */
867
868     if (resdata_size)
869     {
870         output_bytes( outfile, resdata_buffer, resdata_size );
871         free( resdata_buffer );
872     }
873
874     fprintf( outfile, "};\n" );
875     fprintf( outfile, "#include \"poppack.h\"\n\n" );
876
877     /* Output the DLL constructor */
878
879     sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
880     sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
881     output_dll_init( outfile, constructor, destructor );
882
883     fprintf( outfile,
884              "void %s(void)\n"
885              "{\n"
886              "    extern void __wine_dll_register_16( const struct module_data *, const char * );\n"
887              "    __wine_dll_register_16( &module, \"%s\" );\n"
888              "}\n", constructor, spec->file_name );
889     fprintf( outfile,
890              "void %s(void)\n"
891              "{\n"
892              "    extern void __wine_dll_unregister_16( const struct module_data * );\n"
893              "    __wine_dll_unregister_16( &module );\n"
894              "}\n", destructor );
895 }