Fix the case of product and company names.
[wine] / tools / winebuild / import.c
1 /*
2  * DLL imports support
3  *
4  * Copyright 2000 Alexandre Julliard
5  *           2000 Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32
33 #include "build.h"
34
35 struct func
36 {
37     char       *name;         /* function name */
38     int         ordinal;      /* function ordinal */
39     int         ord_only;     /* non-zero if function is imported by ordinal */
40 };
41
42 struct import
43 {
44     char        *dll;         /* dll name */
45     int          delay;       /* delay or not dll loading ? */
46     struct func *exports;     /* functions exported from this dll */
47     int          nb_exports;  /* number of exported functions */
48     struct func *imports;     /* functions we want to import from this dll */
49     int          nb_imports;  /* number of imported functions */
50 };
51
52 static char **undef_symbols;  /* list of undefined symbols */
53 static int nb_undef_symbols = -1;
54 static int undef_size;
55
56 static char **ignore_symbols; /* list of symbols to ignore */
57 static int nb_ignore_symbols;
58 static int ignore_size;
59
60 static char *ld_tmp_file;  /* ld temp file name */
61
62 static struct import **dll_imports = NULL;
63 static int nb_imports = 0;      /* number of imported dlls (delayed or not) */
64 static int nb_delayed = 0;      /* number of delayed dlls */
65 static int total_imports = 0;   /* total number of imported functions */
66 static int total_delayed = 0;   /* total number of imported functions in delayed DLLs */
67
68 /* list of symbols that are ignored by default */
69 static const char * const default_ignored_symbols[] =
70 {
71     "abs",
72     "acos",
73     "asin",
74     "atan",
75     "atan2",
76     "atof",
77     "atoi",
78     "atol",
79     "bsearch",
80     "ceil",
81     "cos",
82     "cosh",
83     "div",
84     "exp",
85     "fabs",
86     "floor",
87     "fmod",
88     "frexp",
89     "labs",
90     "ldiv",
91     "log",
92     "log10",
93     "memchr",
94     "memcmp",
95     "memcpy",
96     "memmove",
97     "memset",
98     "modf",
99     "pow",
100     "qsort",
101     "sin",
102     "sinh",
103     "sqrt",
104     "strcat",
105     "strchr",
106     "strcmp",
107     "strcpy",
108     "strcspn",
109     "strlen",
110     "strncat",
111     "strncmp",
112     "strncpy",
113     "strpbrk",
114     "strrchr",
115     "strspn",
116     "strstr",
117     "tan",
118     "tanh"
119 };
120
121 #ifdef __powerpc__
122 # ifdef __APPLE__
123 # define ppc_high(mem) "ha16(" mem ")"
124 # define ppc_low(mem)  "lo16(" mem ")"
125 static const char * const ppc_reg[32] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
126                                           "r8", "r9", "r10","r11","r12","r13","r14","r15",
127                                           "r16","r17","r18","r19","r20","r21","r22","r23",
128                                           "r24","r25","r26","r27","r28","r29","r30","r31" };
129 # else  /* __APPLE__ */
130 # define ppc_high(mem) "(" mem ")@hi"
131 # define ppc_low(mem)  "(" mem ")@l"
132 static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7",
133                                           "8", "9", "10","11","12","13","14","15",
134                                           "16","17","18","19","20","21","22","23",
135                                           "24","25","26","27","28","29","30","31" };
136 # endif  /* __APPLE__ */
137 #endif  /* __powerpc__ */
138
139 /* compare function names; helper for resolve_imports */
140 static int name_cmp( const void *name, const void *entry )
141 {
142     return strcmp( *(char **)name, *(char **)entry );
143 }
144
145 /* compare function names; helper for resolve_imports */
146 static int func_cmp( const void *func1, const void *func2 )
147 {
148     return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name );
149 }
150
151 /* locate a symbol in a (sorted) list */
152 inline static const char *find_symbol( const char *name, char **table, int size )
153 {
154     char **res = NULL;
155
156     if (table) {
157         res = bsearch( &name, table, size, sizeof(*table), name_cmp );
158     }
159
160     return res ? *res : NULL;
161 }
162
163 /* locate an export in a (sorted) export list */
164 inline static struct func *find_export( const char *name, struct func *table, int size )
165 {
166     struct func func, *res = NULL;
167
168     func.name = (char *)name;
169     func.ordinal = -1;
170     if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp );
171     return res;
172 }
173
174 /* sort a symbol table */
175 inline static void sort_symbols( char **table, int size )
176 {
177     if (table )
178         qsort( table, size, sizeof(*table), name_cmp );
179 }
180
181 /* free an import structure */
182 static void free_imports( struct import *imp )
183 {
184     int i;
185
186     for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name );
187     for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name );
188     free( imp->exports );
189     free( imp->imports );
190     free( imp->dll );
191     free( imp );
192 }
193
194 /* remove the temp file at exit */
195 static void remove_ld_tmp_file(void)
196 {
197     if (ld_tmp_file) unlink( ld_tmp_file );
198 }
199
200 /* check whether a given dll has already been imported */
201 static int is_already_imported( const char *name )
202 {
203     int i;
204
205     for (i = 0; i < nb_imports; i++)
206     {
207         if (!strcmp( dll_imports[i]->dll, name )) return 1;
208     }
209     return 0;
210 }
211
212 /* open the .so library for a given dll in a specified path */
213 static char *try_library_path( const char *path, const char *name )
214 {
215     char *buffer;
216     int fd;
217
218     buffer = xmalloc( strlen(path) + strlen(name) + 9 );
219     sprintf( buffer, "%s/lib%s.def", path, name );
220
221     /* check if the file exists */
222     if ((fd = open( buffer, O_RDONLY )) != -1)
223     {
224         close( fd );
225         return buffer;
226     }
227     free( buffer );
228     return NULL;
229 }
230
231 /* open the .so library for a given dll */
232 static char *open_library( const char *name )
233 {
234     char *fullname;
235     int i;
236
237     for (i = 0; i < nb_lib_paths; i++)
238     {
239         if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
240     }
241     if (!(fullname = try_library_path( ".", name )))
242         fatal_error( "could not open .def file for %s\n", name );
243     return fullname;
244 }
245
246 /* skip whitespace until the next token */
247 static char *skip_whitespace( char *p )
248 {
249     while (*p && isspace(*p)) p++;
250     if (!*p || *p == ';') p = NULL;
251     return p;
252 }
253
254 /* skip to the start of the next token, null terminating the current one */
255 static char *next_token( char *p )
256 {
257     while (*p && !isspace(*p)) p++;
258     if (*p) *p++ = 0;
259     return skip_whitespace( p );
260 }
261
262 /* remove the @nn suffix from stdcall names */
263 static char *remove_stdcall_decoration( char *buffer )
264 {
265     char *p = buffer + strlen(buffer) - 1;
266     while (p > buffer && isdigit(*p)) p--;
267     if (p > buffer && *p == '@') *p = 0;
268     return buffer;
269 }
270
271 /* read in the list of exported symbols of an import library */
272 static int read_import_lib( const char *name, struct import *imp )
273 {
274     FILE *f;
275     char buffer[1024];
276     char *fullname;
277     int size;
278
279     imp->exports    = NULL;
280     imp->nb_exports = size = 0;
281
282     fullname = open_library( name );
283     f = open_input_file( NULL, fullname );
284     free( fullname );
285
286     while (fgets( buffer, sizeof(buffer), f ))
287     {
288         char *name, *flags;
289         int ordinal = 0, ord_only = 0;
290
291         char *p = buffer + strlen(buffer) - 1;
292         if (p < buffer) goto next;
293         if (*p == '\n') *p-- = 0;
294
295         p = buffer;
296         if (!(p = skip_whitespace(p))) goto next;
297         name = p;
298         p = next_token( name );
299
300         if (!strcmp( name, "LIBRARY" ))
301         {
302             if (!p)
303             {
304                 error( "Expected name after LIBRARY\n" );
305                 goto next;
306             }
307             name = p;
308             p = next_token( name );
309             if (p)
310             {
311                 error( "Garbage after LIBRARY statement\n" );
312                 goto next;
313             }
314             if (is_already_imported( name ))
315             {
316                 close_input_file( f );
317                 return 0;  /* ignore this dll */
318             }
319             free( imp->dll );
320             imp->dll = xstrdup( name );
321             goto next;
322         }
323         if (!strcmp( name, "EXPORTS" )) goto next;
324
325         /* check for ordinal */
326         if (!p)
327         {
328             error( "Expected ordinal after function name\n" );
329             goto next;
330         }
331         if (*p != '@' || !isdigit(p[1]))
332         {
333             error( "Expected ordinal after function name '%s'\n", name );
334             goto next;
335         }
336         ordinal = strtol( p+1, &p, 10 );
337         if (ordinal >= MAX_ORDINALS)
338         {
339             error( "Invalid ordinal number %d\n", ordinal );
340             goto next;
341         }
342
343         /* check for optional flags */
344         while (p && (p = skip_whitespace(p)))
345         {
346             flags = p;
347             p = next_token( flags );
348             if (!strcmp( flags, "NONAME" ))
349             {
350                 ord_only = 1;
351                 if (!ordinal)
352                 {
353                     error( "Invalid ordinal number %d\n", ordinal );
354                     goto next;
355                 }
356             }
357             else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" ))
358             {
359                 /* we don't support importing non-function entry points */
360                 goto next;
361             }
362             else if (!strcmp( flags, "PRIVATE" ))
363             {
364                 /* function must not be imported */
365                 goto next;
366             }
367             else
368             {
369                 error( "Garbage after ordinal declaration\n" );
370                 goto next;
371             }
372         }
373
374         if (imp->nb_exports == size)
375         {
376             size += 128;
377             imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) );
378         }
379         if ((p = strchr( name, '=' ))) *p = 0;
380         remove_stdcall_decoration( name );
381         imp->exports[imp->nb_exports].name     = xstrdup( name );
382         imp->exports[imp->nb_exports].ordinal  = ordinal;
383         imp->exports[imp->nb_exports].ord_only = ord_only;
384         imp->nb_exports++;
385     next:
386         current_line++;
387     }
388     close_input_file( f );
389     if (imp->nb_exports)
390         qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
391     return !nb_errors;
392 }
393
394 /* add a dll to the list of imports */
395 void add_import_dll( const char *name, int delay )
396 {
397     struct import *imp;
398     char *fullname;
399
400     fullname = xmalloc( strlen(name) + 5 );
401     strcpy( fullname, name );
402     if (!strchr( fullname, '.' )) strcat( fullname, ".dll" );
403
404     /* check if we already imported it */
405     if (is_already_imported( fullname ))
406     {
407         free( fullname );
408         return;
409     }
410
411     imp = xmalloc( sizeof(*imp) );
412     imp->dll        = fullname;
413     imp->delay      = delay;
414     imp->imports    = NULL;
415     imp->nb_imports = 0;
416
417     if (delay) nb_delayed++;
418
419     if (read_import_lib( name, imp ))
420     {
421         dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
422         dll_imports[nb_imports++] = imp;
423     }
424     else
425     {
426         free_imports( imp );
427         if (nb_errors) exit(1);
428     }
429 }
430
431 /* remove an imported dll, based on its index in the dll_imports array */
432 static void remove_import_dll( int index )
433 {
434     struct import *imp = dll_imports[index];
435
436     memmove( &dll_imports[index], &dll_imports[index+1], sizeof(imp) * (nb_imports - index - 1) );
437     nb_imports--;
438     if (imp->delay) nb_delayed--;
439     free_imports( imp );
440 }
441
442 /* initialize the list of ignored symbols */
443 static void init_ignored_symbols(void)
444 {
445     int i;
446
447     nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
448     ignore_size = nb_ignore_symbols + 32;
449     ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
450     for (i = 0; i < nb_ignore_symbols; i++)
451         ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
452 }
453
454 /* add a symbol to the ignored symbol list */
455 /* if the name starts with '-' the symbol is removed instead */
456 void add_ignore_symbol( const char *name )
457 {
458     int i;
459
460     if (!ignore_symbols) init_ignored_symbols();  /* first time around, fill list with defaults */
461
462     if (name[0] == '-')  /* remove it */
463     {
464         if (!name[1])  /* remove everything */
465         {
466             for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
467             nb_ignore_symbols = 0;
468         }
469         else
470         {
471             for (i = 0; i < nb_ignore_symbols; i++)
472             {
473                 if (!strcmp( ignore_symbols[i], name+1 ))
474                 {
475                     free( ignore_symbols[i] );
476                     memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
477                     nb_ignore_symbols--;
478                 }
479             }
480         }
481     }
482     else
483     {
484         if (nb_ignore_symbols == ignore_size)
485         {
486             ignore_size += 32;
487             ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
488         }
489         ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
490     }
491 }
492
493 /* add a function to the list of imports from a given dll */
494 static void add_import_func( struct import *imp, const struct func *func )
495 {
496     imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
497     imp->imports[imp->nb_imports].name     = xstrdup( func->name );
498     imp->imports[imp->nb_imports].ordinal  = func->ordinal;
499     imp->imports[imp->nb_imports].ord_only = func->ord_only;
500     imp->nb_imports++;
501     total_imports++;
502     if (imp->delay) total_delayed++;
503 }
504
505 /* add a symbol to the undef list */
506 inline static void add_undef_symbol( const char *name )
507 {
508     if (nb_undef_symbols == undef_size)
509     {
510         undef_size += 128;
511         undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
512     }
513     undef_symbols[nb_undef_symbols++] = xstrdup( name );
514 }
515
516 /* remove all the holes in the undefined symbol list; return the number of removed symbols */
517 static int remove_symbol_holes(void)
518 {
519     int i, off;
520     for (i = off = 0; i < nb_undef_symbols; i++)
521     {
522         if (!undef_symbols[i]) off++;
523         else undef_symbols[i - off] = undef_symbols[i];
524     }
525     nb_undef_symbols -= off;
526     return off;
527 }
528
529 /* add a symbol to the extra list, but only if needed */
530 static int add_extra_symbol( const char **extras, int *count, const char *name )
531 {
532     int i;
533
534     if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
535     {
536         /* check if the symbol is being exported by this dll */
537         for (i = 0; i < nb_entry_points; i++)
538         {
539             ORDDEF *odp = EntryPoints[i];
540             if (odp->type == TYPE_STDCALL ||
541                 odp->type == TYPE_CDECL ||
542                 odp->type == TYPE_VARARGS ||
543                 odp->type == TYPE_EXTERN)
544             {
545                 if (odp->name && !strcmp( odp->name, name )) return 0;
546             }
547         }
548         extras[*count] = name;
549         (*count)++;
550     }
551     return 1;
552 }
553
554 /* add the extra undefined symbols that will be contained in the generated spec file itself */
555 static void add_extra_undef_symbols(void)
556 {
557     const char *extras[10];
558     int i, count = 0, nb_stubs = 0, nb_regs = 0;
559     int kernel_imports = 0, ntdll_imports = 0;
560
561     sort_symbols( undef_symbols, nb_undef_symbols );
562
563     for (i = 0; i < nb_entry_points; i++)
564     {
565         ORDDEF *odp = EntryPoints[i];
566         if (odp->type == TYPE_STUB) nb_stubs++;
567         if (odp->flags & FLAG_REGISTER) nb_regs++;
568     }
569
570     /* add symbols that will be contained in the spec file itself */
571     switch (SpecMode)
572     {
573     case SPEC_MODE_DLL:
574         break;
575     case SPEC_MODE_GUIEXE:
576         kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
577         kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
578         kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
579         /* fall through */
580     case SPEC_MODE_CUIEXE:
581         kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
582         break;
583     case SPEC_MODE_GUIEXE_UNICODE:
584         kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
585         kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
586         kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
587         /* fall through */
588     case SPEC_MODE_CUIEXE_UNICODE:
589         kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
590         break;
591     }
592     if (nb_delayed)
593     {
594         kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" );
595         kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" );
596     }
597     if (nb_regs)
598         ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" );
599     if (nb_delayed || nb_stubs)
600         ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" );
601
602     /* make sure we import the dlls that contain these functions */
603     if (kernel_imports) add_import_dll( "kernel32", 0 );
604     if (ntdll_imports) add_import_dll( "ntdll", 0 );
605
606     if (count)
607     {
608         for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
609         sort_symbols( undef_symbols, nb_undef_symbols );
610     }
611 }
612
613 /* check if a given imported dll is not needed, taking forwards into account */
614 static int check_unused( const struct import* imp )
615 {
616     int i;
617     size_t len = strlen(imp->dll);
618     const char *p = strchr( imp->dll, '.' );
619     if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
620
621     for (i = Base; i <= Limit; i++)
622     {
623         ORDDEF *odp = Ordinals[i];
624         if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
625         if (!strncasecmp( odp->link_name, imp->dll, len ) &&
626             odp->link_name[len] == '.')
627             return 0;  /* found a forward, it is used */
628     }
629     return 1;
630 }
631
632 /* combine a list of object files with ld into a single object file */
633 /* returns the name of the combined file */
634 static const char *ldcombine_files( char **argv )
635 {
636     int i, len = 0;
637     char *cmd;
638     int fd, err;
639
640     if (output_file_name && output_file_name[0])
641     {
642         ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
643         strcpy( ld_tmp_file, output_file_name );
644         strcat( ld_tmp_file, ".XXXXXX.o" );
645     }
646     else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
647
648     if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
649     close( fd );
650     atexit( remove_ld_tmp_file );
651
652     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
653     cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
654     sprintf( cmd, "ld -r -o %s", ld_tmp_file );
655     for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
656     err = system( cmd );
657     if (err) fatal_error( "ld -r failed with status %d\n", err );
658     free( cmd );
659     return ld_tmp_file;
660 }
661
662 /* read in the list of undefined symbols */
663 void read_undef_symbols( char **argv )
664 {
665     FILE *f;
666     char buffer[1024];
667     int err;
668     const char *name;
669
670     if (!argv[0]) return;
671
672     undef_size = nb_undef_symbols = 0;
673
674     /* if we have multiple object files, link them together */
675     if (argv[1]) name = ldcombine_files( argv );
676     else name = argv[0];
677
678     sprintf( buffer, "nm -u %s", name );
679     if (!(f = popen( buffer, "r" )))
680         fatal_error( "Cannot execute '%s'\n", buffer );
681
682     while (fgets( buffer, sizeof(buffer), f ))
683     {
684         char *p = buffer + strlen(buffer) - 1;
685         if (p < buffer) continue;
686         if (*p == '\n') *p-- = 0;
687         p = buffer;
688         while (*p == ' ') p++;
689         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
690         add_undef_symbol( p );
691     }
692     if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
693 }
694
695 static void remove_ignored_symbols(void)
696 {
697     int i;
698
699     if (!ignore_symbols) init_ignored_symbols();
700     sort_symbols( ignore_symbols, nb_ignore_symbols );
701     for (i = 0; i < nb_undef_symbols; i++)
702     {
703         if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
704         {
705             free( undef_symbols[i] );
706             undef_symbols[i] = NULL;
707         }
708     }
709     remove_symbol_holes();
710 }
711
712 /* resolve the imports for a Win32 module */
713 int resolve_imports( void )
714 {
715     int i, j;
716
717     if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
718
719     add_extra_undef_symbols();
720     remove_ignored_symbols();
721
722     for (i = 0; i < nb_imports; i++)
723     {
724         struct import *imp = dll_imports[i];
725
726         for (j = 0; j < nb_undef_symbols; j++)
727         {
728             struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
729             if (func)
730             {
731                 add_import_func( imp, func );
732                 free( undef_symbols[j] );
733                 undef_symbols[j] = NULL;
734             }
735         }
736         /* remove all the holes in the undef symbols list */
737         if (!remove_symbol_holes() && check_unused( imp ))
738         {
739             /* the dll is not used, get rid of it */
740             warning( "%s imported but no symbols used\n", imp->dll );
741             remove_import_dll( i );
742             i--;
743         }
744     }
745     return 1;
746 }
747
748 /* output the import table of a Win32 module */
749 static int output_immediate_imports( FILE *outfile )
750 {
751     int i, j, pos;
752     int nb_imm = nb_imports - nb_delayed;
753
754     if (!nb_imm) goto done;
755
756     /* main import header */
757
758     fprintf( outfile, "\nstatic struct {\n" );
759     fprintf( outfile, "  struct {\n" );
760     fprintf( outfile, "    void        *OriginalFirstThunk;\n" );
761     fprintf( outfile, "    unsigned int TimeDateStamp;\n" );
762     fprintf( outfile, "    unsigned int ForwarderChain;\n" );
763     fprintf( outfile, "    const char  *Name;\n" );
764     fprintf( outfile, "    void        *FirstThunk;\n" );
765     fprintf( outfile, "  } imp[%d];\n", nb_imm+1 );
766     fprintf( outfile, "  const char *data[%d];\n",
767              total_imports - total_delayed + nb_imm );
768     fprintf( outfile, "} imports = {\n  {\n" );
769
770     /* list of dlls */
771
772     for (i = j = 0; i < nb_imports; i++)
773     {
774         if (dll_imports[i]->delay) continue;
775         fprintf( outfile, "    { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
776                  dll_imports[i]->dll, j );
777         j += dll_imports[i]->nb_imports + 1;
778     }
779
780     fprintf( outfile, "    { 0, 0, 0, 0, 0 },\n" );
781     fprintf( outfile, "  },\n  {\n" );
782
783     /* list of imported functions */
784
785     for (i = 0; i < nb_imports; i++)
786     {
787         if (dll_imports[i]->delay) continue;
788         fprintf( outfile, "    /* %s */\n", dll_imports[i]->dll );
789         for (j = 0; j < dll_imports[i]->nb_imports; j++)
790         {
791             struct func *import = &dll_imports[i]->imports[j];
792             if (!import->ord_only)
793             {
794                 unsigned short ord = import->ordinal;
795                 fprintf( outfile, "    \"\\%03o\\%03o%s\",\n",
796                          *(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
797             }
798             else
799                 fprintf( outfile, "    (char *)%d,\n", import->ordinal );
800         }
801         fprintf( outfile, "    0,\n" );
802     }
803     fprintf( outfile, "  }\n};\n\n" );
804
805     /* thunks for imported functions */
806
807     fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
808     pos = 20 * (nb_imm + 1);  /* offset of imports.data from start of imports */
809     fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
810     for (i = 0; i < nb_imports; i++)
811     {
812         if (dll_imports[i]->delay) continue;
813         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
814         {
815             struct func *import = &dll_imports[i]->imports[j];
816             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
817             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
818             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t", import->name);
819
820 #if defined(__i386__)
821             if (strstr( import->name, "__wine_call_from_16" ))
822                 fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
823             else
824                 fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
825 #elif defined(__sparc__)
826             if ( !UsePIC )
827             {
828                 fprintf( outfile, "sethi %%hi(imports+%d), %%g1\\n\\t", pos );
829                 fprintf( outfile, "ld [%%g1+%%lo(imports+%d)], %%g1\\n\\t", pos );
830                 fprintf( outfile, "jmp %%g1\\n\\tnop\\n" );
831             }
832             else
833             {
834                 /* Hmpf.  Stupid sparc assembler always interprets global variable
835                    names as GOT offsets, so we have to do it the long way ... */
836                 fprintf( outfile, "save %%sp, -96, %%sp\\n" );
837                 fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" );
838                 fprintf( outfile, "1:\\tsethi %%hi(imports+%d-0b), %%g1\\n\\t", pos );
839                 fprintf( outfile, "or %%g1, %%lo(imports+%d-0b), %%g1\\n\\t", pos );
840                 fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
841                 fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
842             }
843
844 #elif defined(__powerpc__)
845             fprintf(outfile, "\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
846             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
847             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
848             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
849             fprintf(outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
850             fprintf(outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
851
852             fprintf(outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d")  "\\n\"\n", ppc_reg[9], pos);
853             fprintf(outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
854             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
855             fprintf(outfile, "\t\"\\tmctr %s\\n\"\n", ppc_reg[7]);
856
857             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
858             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
859             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
860             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
861             fprintf(outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
862             fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
863             fprintf(outfile, "\t\"\\tbctr\\n");
864 #else
865 #error You need to define import thunks for your architecture!
866 #endif
867             fprintf( outfile, "\"\n" );
868         }
869         pos += 4;
870     }
871     fprintf( outfile, "\".section\\t\\\".text\\\"\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
872
873  done:
874     return nb_imm;
875 }
876
877 /* output the delayed import table of a Win32 module */
878 static int output_delayed_imports( FILE *outfile )
879 {
880     int i, idx, j, pos;
881
882     if (!nb_delayed) goto done;
883
884     for (i = 0; i < nb_imports; i++)
885     {
886         if (!dll_imports[i]->delay) continue;
887         fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
888         for (j = 0; j < dll_imports[i]->nb_imports; j++)
889         {
890             fprintf( outfile, "void __wine_delay_imp_%d_%s();\n",
891                      i, dll_imports[i]->imports[j].name );
892         }
893     }
894     fprintf( outfile, "\n" );
895     fprintf( outfile, "static struct {\n" );
896     fprintf( outfile, "  struct ImgDelayDescr {\n" );
897     fprintf( outfile, "    unsigned int  grAttrs;\n" );
898     fprintf( outfile, "    const char   *szName;\n" );
899     fprintf( outfile, "    void        **phmod;\n" );
900     fprintf( outfile, "    void        **pIAT;\n" );
901     fprintf( outfile, "    const char  **pINT;\n" );
902     fprintf( outfile, "    void*         pBoundIAT;\n" );
903     fprintf( outfile, "    void*         pUnloadIAT;\n" );
904     fprintf( outfile, "    unsigned long dwTimeStamp;\n" );
905     fprintf( outfile, "  } imp[%d];\n", nb_delayed );
906     fprintf( outfile, "  void         *IAT[%d];\n", total_delayed );
907     fprintf( outfile, "  const char   *INT[%d];\n", total_delayed );
908     fprintf( outfile, "} delay_imports = {\n" );
909     fprintf( outfile, "  {\n" );
910     for (i = j = 0; i < nb_imports; i++)
911     {
912         if (!dll_imports[i]->delay) continue;
913         fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
914                  dll_imports[i]->dll, i, j, j );
915         j += dll_imports[i]->nb_imports;
916     }
917     fprintf( outfile, "  },\n  {\n" );
918     for (i = 0; i < nb_imports; i++)
919     {
920         if (!dll_imports[i]->delay) continue;
921         fprintf( outfile, "    /* %s */\n", dll_imports[i]->dll );
922         for (j = 0; j < dll_imports[i]->nb_imports; j++)
923         {
924             fprintf( outfile, "    &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name);
925         }
926     }
927     fprintf( outfile, "  },\n  {\n" );
928     for (i = 0; i < nb_imports; i++)
929     {
930         if (!dll_imports[i]->delay) continue;
931         fprintf( outfile, "    /* %s */\n", dll_imports[i]->dll );
932         for (j = 0; j < dll_imports[i]->nb_imports; j++)
933         {
934             struct func *import = &dll_imports[i]->imports[j];
935             if (import->ord_only)
936                 fprintf( outfile, "    (char *)%d,\n", import->ordinal );
937             else
938                 fprintf( outfile, "    \"%s\",\n", import->name );
939         }
940     }
941     fprintf( outfile, "  }\n};\n\n" );
942
943     /* check if there's some stub defined. if so, exception struct
944      *  is already defined, so don't emit it twice
945      */
946     for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break;
947
948     if (i == nb_entry_points) {
949        fprintf( outfile, "struct exc_record {\n" );
950        fprintf( outfile, "  unsigned int code, flags;\n" );
951        fprintf( outfile, "  void *rec, *addr;\n" );
952        fprintf( outfile, "  unsigned int params;\n" );
953        fprintf( outfile, "  const void *info[15];\n" );
954        fprintf( outfile, "};\n\n" );
955        fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
956     }
957
958     fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
959     fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
960     fprintf( outfile, "\n" );
961
962     fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
963     fprintf( outfile, "{\n" );
964     fprintf( outfile, "  int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
965     fprintf( outfile, "  struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
966     fprintf( outfile, "  void **pIAT = imd->pIAT + nr;\n" );
967     fprintf( outfile, "  const char** pINT = imd->pINT + nr;\n" );
968     fprintf( outfile, "  void *fn;\n\n" );
969
970     fprintf( outfile, "  if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
971     fprintf( outfile, "  if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
972     fprintf( outfile, "    /* patch IAT with final value */\n" );
973     fprintf( outfile, "    return *pIAT = fn;\n" );
974     fprintf( outfile, "  else {\n");
975     fprintf( outfile, "    struct exc_record rec;\n" );
976     fprintf( outfile, "    rec.code    = 0x80000100;\n" );
977     fprintf( outfile, "    rec.flags   = 1;\n" );
978     fprintf( outfile, "    rec.rec     = 0;\n" );
979     fprintf( outfile, "    rec.params  = 2;\n" );
980     fprintf( outfile, "    rec.info[0] = imd->szName;\n" );
981     fprintf( outfile, "    rec.info[1] = *pINT + 2;\n" );
982     fprintf( outfile, "#ifdef __GNUC__\n" );
983     fprintf( outfile, "    rec.addr = __builtin_return_address(1);\n" );
984     fprintf( outfile, "#else\n" );
985     fprintf( outfile, "    rec.addr = 0;\n" );
986     fprintf( outfile, "#endif\n" );
987     fprintf( outfile, "    for (;;) RtlRaiseException( &rec );\n" );
988     fprintf( outfile, "    return 0; /* shouldn't go here */\n" );
989     fprintf( outfile, "  }\n}\n\n" );
990
991     fprintf( outfile, "#ifndef __GNUC__\n" );
992     fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
993     fprintf( outfile, "#endif\n" );
994
995     fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
996     fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
997     fprintf( outfile, "    \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
998 #if defined(__i386__)
999     fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
1000     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
1001     fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
1002 #elif defined(__sparc__)
1003     fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
1004     fprintf( outfile, "    \"\\tcall __wine_delay_load\\n\"\n" );
1005     fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
1006     fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
1007 #elif defined(__powerpc__)
1008     /* Save all callee saved registers into a stackframe. */
1009     fprintf( outfile, "    \"\\tstwu %s, -48, %s\\n\"\n", ppc_reg[1], ppc_reg[1]);
1010     fprintf( outfile, "    \"\\tstw  %s,   4, %s\\n\"\n", ppc_reg[3], ppc_reg[1]);
1011     fprintf( outfile, "    \"\\tstw  %s,   8, %s\\n\"\n", ppc_reg[4], ppc_reg[1]);
1012     fprintf( outfile, "    \"\\tstw  %s,  12, %s\\n\"\n", ppc_reg[5], ppc_reg[1]);
1013     fprintf( outfile, "    \"\\tstw  %s,  16, %s\\n\"\n", ppc_reg[6], ppc_reg[1]);
1014     fprintf( outfile, "    \"\\tstw  %s,  20, %s\\n\"\n", ppc_reg[7], ppc_reg[1]);
1015     fprintf( outfile, "    \"\\tstw  %s,  24, %s\\n\"\n", ppc_reg[8], ppc_reg[1]);
1016     fprintf( outfile, "    \"\\tstw  %s,  28, %s\\n\"\n", ppc_reg[9], ppc_reg[1]);
1017     fprintf( outfile, "    \"\\tstw  %s,  32, %s\\n\"\n", ppc_reg[10], ppc_reg[1]);
1018     fprintf( outfile, "    \"\\tstw  %s,  36, %s\\n\"\n", ppc_reg[11], ppc_reg[1]);
1019     fprintf( outfile, "    \"\\tstw  %s,  40, %s\\n\"\n", ppc_reg[12], ppc_reg[1]);
1020
1021     /* r0 -> r3 (arg1) */
1022     fprintf( outfile, "    \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
1023
1024     /* save return address */
1025     fprintf( outfile, "    \"\\tmflr %s\\n\"\n", ppc_reg[0]);
1026     fprintf( outfile, "    \"\\tstw  %s, 44, %s\\n\"\n", ppc_reg[0], ppc_reg[1]);
1027
1028     /* Call the __wine_delay_load function, arg1 is arg1. */
1029     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
1030
1031     /* Load return value from call into ctr register */
1032     fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
1033
1034     /* restore all saved registers and drop stackframe. */
1035     fprintf( outfile, "    \"\\tlwz  %s,   4, %s\\n\"\n", ppc_reg[3], ppc_reg[1]);
1036     fprintf( outfile, "    \"\\tlwz  %s,   8, %s\\n\"\n", ppc_reg[4], ppc_reg[1]);
1037     fprintf( outfile, "    \"\\tlwz  %s,  12, %s\\n\"\n", ppc_reg[5], ppc_reg[1]);
1038     fprintf( outfile, "    \"\\tlwz  %s,  16, %s\\n\"\n", ppc_reg[6], ppc_reg[1]);
1039     fprintf( outfile, "    \"\\tlwz  %s,  20, %s\\n\"\n", ppc_reg[7], ppc_reg[1]);
1040     fprintf( outfile, "    \"\\tlwz  %s,  24, %s\\n\"\n", ppc_reg[8], ppc_reg[1]);
1041     fprintf( outfile, "    \"\\tlwz  %s,  28, %s\\n\"\n", ppc_reg[9], ppc_reg[1]);
1042     fprintf( outfile, "    \"\\tlwz  %s,  32, %s\\n\"\n", ppc_reg[10], ppc_reg[1]);
1043     fprintf( outfile, "    \"\\tlwz  %s,  36, %s\\n\"\n", ppc_reg[11], ppc_reg[1]);
1044     fprintf( outfile, "    \"\\tlwz  %s,  40, %s\\n\"\n", ppc_reg[12], ppc_reg[1]);
1045
1046     /* Load return value from call into return register */
1047     fprintf( outfile, "    \"\\tlwz  %s,  44, %s\\n\"\n", ppc_reg[0], ppc_reg[1]);
1048     fprintf( outfile, "    \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
1049     fprintf( outfile, "    \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]);
1050
1051     /* branch to ctr register. */
1052     fprintf( outfile, "\"bctr\\n\"\n");
1053 #else
1054 #error You need to defined delayed import thunks for your architecture!
1055 #endif
1056
1057     for (i = idx = 0; i < nb_imports; i++)
1058     {
1059         if (!dll_imports[i]->delay) continue;
1060         for (j = 0; j < dll_imports[i]->nb_imports; j++)
1061         {
1062             char buffer[128];
1063             sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name );
1064             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
1065             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
1066 #if defined(__i386__)
1067             fprintf( outfile, "    \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j );
1068             fprintf( outfile, "    \"\\tjmp __wine_delay_load_asm\\n\"\n" );
1069 #elif defined(__sparc__)
1070             fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
1071             fprintf( outfile, "    \"\\tb,a __wine_delay_load_asm\\n\"\n" );
1072 #elif defined(__powerpc__)
1073             /* g0 is a function scratch register or so I understand. */
1074             /* First load the upper half-word, and then the lower part */
1075             fprintf( outfile, "    \"\\lis %s, %d\\n\"\n", ppc_reg[0], idx);
1076             fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[0], j);
1077             fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
1078 #else
1079 #error You need to defined delayed import thunks for your architecture!
1080 #endif
1081         }
1082         idx++;
1083     }
1084
1085     fprintf( outfile, "\n    \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
1086     pos = nb_delayed * 32;
1087     for (i = 0; i < nb_imports; i++)
1088     {
1089         if (!dll_imports[i]->delay) continue;
1090         for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
1091         {
1092             struct func *import = &dll_imports[i]->imports[j];
1093             fprintf( outfile, "    \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
1094             fprintf( outfile, "    \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
1095             fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\\t\"", import->name);
1096 #if defined(__i386__)
1097             if (strstr( import->name, "__wine_call_from_16" ))
1098                 fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
1099             else
1100                 fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
1101 #elif defined(__sparc__)
1102             if ( !UsePIC )
1103             {
1104                 fprintf( outfile, "\"sethi %%hi(delay_imports+%d), %%g1\\n\\t\"", pos );
1105                 fprintf( outfile, "\"ld [%%g1+%%lo(delay_imports+%d)], %%g1\\n\\t\"", pos );
1106                 fprintf( outfile, "\"jmp %%g1\\n\\tnop\\n\"" );
1107             }
1108             else
1109             {
1110                 /* Hmpf.  Stupid sparc assembler always interprets global variable
1111                    names as GOT offsets, so we have to do it the long way ... */
1112                 fprintf( outfile, "\"save %%sp, -96, %%sp\\n\"" );
1113                 fprintf( outfile, "\"0:\\tcall 1f\\n\\tnop\\n\"" );
1114                 fprintf( outfile, "\"1:\\tsethi %%hi(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1115                 fprintf( outfile, "\"or %%g1, %%lo(delay_imports+%d-0b), %%g1\\n\\t\"", pos );
1116                 fprintf( outfile, "\"ld [%%g1+%%o7], %%g1\\n\\t\"" );
1117                 fprintf( outfile, "\"jmp %%g1\\n\\trestore\\n\"" );
1118             }
1119
1120 #elif defined(__powerpc__)
1121             fprintf( outfile, "\t addi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1122             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[9], ppc_reg[1]);
1123             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1124             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
1125             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1126             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
1127             fprintf( outfile, "\t\"\\tlis %s " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
1128             fprintf( outfile, "\t\"\\tla  %s " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
1129             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
1130             fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
1131
1132             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[7], ppc_reg[1]);
1133             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1134             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[8], ppc_reg[1]);
1135             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1136             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg[9], ppc_reg[1]);
1137             fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
1138             fprintf( outfile, "\t\"\\tbctr\\n");
1139 #else
1140 #error You need to define delayed import thunks for your architecture!
1141 #endif
1142             fprintf( outfile, "\n" );
1143         }
1144     }
1145     fprintf( outfile, "\".section \\\".text\\\"\");\n" );
1146     fprintf( outfile, "#ifndef __GNUC__\n" );
1147     fprintf( outfile, "}\n" );
1148     fprintf( outfile, "#endif\n" );
1149     fprintf( outfile, "\n" );
1150
1151  done:
1152     return nb_delayed;
1153 }
1154
1155 /* output the import and delayed import tables of a Win32 module
1156  * returns number of DLLs exported in 'immediate' mode
1157  */
1158 int output_imports( FILE *outfile )
1159 {
1160    output_delayed_imports( outfile );
1161    return output_immediate_imports( outfile );
1162 }