Release 950109
[wine] / tools / build.c
1 /* static char Copyright[] = "Copyright  Robert J. Amstadt, 1993"; */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include "wine.h"
8
9 #ifdef linux
10 #define UTEXTSEL 0x23
11 #endif
12 #if defined(__NetBSD__) || defined(__FreeBSD__)
13 #define UTEXTSEL 0x1f
14 #endif
15
16 /* ELF symbols do not have an underscore in front */
17 #ifdef __ELF__
18 #define PREFIX
19 #else
20 #define PREFIX "_"
21 #endif
22
23 #define VARTYPE_BYTE    0
24 #define VARTYPE_SIGNEDWORD      0
25 #define VARTYPE_WORD    1
26 #define VARTYPE_LONG    2
27 #define VARTYPE_FARPTR  3
28
29 #define FUNCTYPE_PASCAL_16      15
30 #define FUNCTYPE_PASCAL         16
31 #define FUNCTYPE_C              17
32 #define FUNCTYPE_REG            19
33
34 #define EQUATETYPE_ABS  18
35 #define TYPE_RETURN     20
36
37 /*#define MAX_ORDINALS  1024*/
38 #define MAX_ORDINALS    1299
39
40 #define PUSH_0          "\tpushl\t$0\n"
41 #define PUSH_SS         "\tpushw\t$0\n\tpushw\t%%ss\n"
42 #define PUSH_ESP        "\tpushl\t%%esp\n"
43 #define PUSH_EFL        "\tpushfl\n"
44 #define PUSH_CS         "\tpushw\t$0\n\tpushw\t%%cs\n"
45 #define PUSH_EIP        "\tpushl\t$0\n"
46 #define PUSH_DS         "\tpushw\t$0\n\tpushw\t%%ds\n"
47 #define PUSH_ES         "\tpushw\t$0\n\tpushw\t%%es\n"
48 #define PUSH_FS         "\tpushw\t$0\n\tpushw\t%%fs\n"
49 #define PUSH_GS         "\tpushw\t$0\n\tpushw\t%%gs\n"
50 #define PUSH_EAX        "\tpushl\t%%eax\n"
51 #define PUSH_ECX        "\tpushl\t%%ecx\n"
52 #define PUSH_EDX        "\tpushl\t%%edx\n"
53 #define PUSH_EBX        "\tpushl\t%%ebx\n"
54 #define PUSH_EBP        "\tpushl\t%%ebp\n"
55 #define PUSH_ESI        "\tpushl\t%%esi\n"
56 #define PUSH_EDI        "\tpushl\t%%edi\n"
57
58 #define POP_0           "\tadd\t$4,%%esp\n"
59 #define POP_SS          "\tpopw\t%%ss\n\tadd\t$2,%%esp\n"
60 #define POP_ESP         "\tpopl\t%%esp\n"
61 #define POP_EFL         "\tpopl\t%%gs:return_value\n"
62 #define POP_CS          "\tpopw\t%%cs\n\tadd\t$2,%%esp\n"
63 #define POP_EIP         "\tpopl\t$0\n"
64 #define POP_DS          "\tpopw\t%%ds\n\tadd\t$2,%%esp\n"
65 #define POP_ES          "\tpopw\t%%es\n\tadd\t$2,%%esp\n"
66 #define POP_FS          "\tpopw\t%%fs\n\tadd\t$2,%%esp\n"
67 #define POP_GS          "\tpopw\t%%gs\n\tadd\t$2,%%esp\n"
68 #define POP_EAX         "\tpopl\t%%eax\n"
69 #define POP_ECX         "\tpopl\t%%ecx\n"
70 #define POP_EDX         "\tpopl\t%%edx\n"
71 #define POP_EBX         "\tpopl\t%%ebx\n"
72 #define POP_EBP         "\tpopl\t%%ebp\n"
73 #define POP_ESI         "\tpopl\t%%esi\n"
74 #define POP_EDI         "\tpopl\t%%edi\n"
75
76 char **context_strings;
77 char **pop_strings;
78 int    n_context_strings;
79
80 typedef struct ordinal_definition_s
81 {
82     int valid;
83     int type;
84     char export_name[80];
85     void *additional_data;
86 } ORDDEF;
87
88 typedef struct ordinal_variable_definition_s
89 {
90     int n_values;
91     int *values;
92 } ORDVARDEF;
93
94 typedef struct ordinal_function_definition_s
95 {
96     int n_args_16;
97     int arg_types_16[16];
98     int arg_16_offsets[16];
99     int arg_16_size;
100     char internal_name[80];
101     int n_args_32;
102     int arg_indices_32[16];
103 } ORDFUNCDEF;
104
105 typedef struct ordinal_return_definition_s
106 {
107     int arg_size;
108     int ret_value;
109 } ORDRETDEF;
110
111 ORDDEF OrdinalDefinitions[MAX_ORDINALS];
112
113 char LowerDLLName[80];
114 char UpperDLLName[80];
115 int Limit;
116 int DLLId;
117 FILE *SpecFp;
118
119 char *ParseBuffer = NULL;
120 char *ParseNext;
121 char ParseSaveChar;
122 int Line;
123
124 int IsNumberString(char *s)
125 {
126     while (*s != '\0')
127         if (!isdigit(*s++))
128             return 0;
129
130     return 1;
131 }
132
133 char *strlower(char *s)
134 {
135     char *p;
136     
137     for(p = s; *p != '\0'; p++)
138         *p = tolower(*p);
139
140     return s;
141 }
142
143 char *strupper(char *s)
144 {
145     char *p;
146     
147     for(p = s; *p != '\0'; p++)
148         *p = toupper(*p);
149
150     return s;
151 }
152
153 int stricmp(char *s1, char *s2)
154 {
155     if (strlen(s1) != strlen(s2))
156         return -1;
157     
158     while (*s1 != '\0')
159         if (*s1++ != *s2++)
160             return -1;
161     
162     return 0;
163 }
164
165 char *
166 GetTokenInLine(void)
167 {
168     char *p;
169     char *token;
170
171     if (ParseNext != ParseBuffer)
172     {
173         if (ParseSaveChar == '\0')
174             return NULL;
175         *ParseNext = ParseSaveChar;
176     }
177     
178     /*
179      * Remove initial white space.
180      */
181     for (p = ParseNext; isspace(*p); p++)
182         ;
183     
184     if (*p == '\0')
185         return NULL;
186     
187     /*
188      * Find end of token.
189      */
190     token = p++;
191     if (*token != '(' && *token != ')')
192         while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
193             p++;
194     
195     ParseSaveChar = *p;
196     ParseNext = p;
197     *p = '\0';
198
199     return token;
200 }
201
202 char *
203 GetToken(void)
204 {
205     char *token;
206
207     if (ParseBuffer == NULL)
208     {
209         ParseBuffer = malloc(512);
210         ParseNext = ParseBuffer;
211         Line++;
212         while (1)
213         {
214             if (fgets(ParseBuffer, 511, SpecFp) == NULL)
215                 return NULL;
216             if (ParseBuffer[0] != '#')
217                 break;
218         }
219     }
220
221     while ((token = GetTokenInLine()) == NULL)
222     {
223         ParseNext = ParseBuffer;
224         Line++;
225         while (1)
226         {
227             if (fgets(ParseBuffer, 511, SpecFp) == NULL)
228                 return NULL;
229             if (ParseBuffer[0] != '#')
230                 break;
231         }
232     }
233
234     return token;
235 }
236
237 int
238 ParseVariable(int ordinal, int type)
239 {
240     ORDDEF *odp;
241     ORDVARDEF *vdp;
242     char export_name[80];
243     char *token;
244     char *endptr;
245     int *value_array;
246     int n_values;
247     int value_array_size;
248     
249     strcpy(export_name, GetToken());
250
251     token = GetToken();
252     if (*token != '(')
253     {
254         fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
255         exit(1);
256     }
257
258     n_values = 0;
259     value_array_size = 25;
260     value_array = malloc(sizeof(*value_array) * value_array_size);
261     
262     while ((token = GetToken()) != NULL)
263     {
264         if (*token == ')')
265             break;
266
267         value_array[n_values++] = strtol(token, &endptr, 0);
268         if (n_values == value_array_size)
269         {
270             value_array_size += 25;
271             value_array = realloc(value_array, 
272                                   sizeof(*value_array) * value_array_size);
273         }
274         
275         if (endptr == NULL || *endptr != '\0')
276         {
277             fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
278                     token);
279             exit(1);
280         }
281     }
282     
283     if (token == NULL)
284     {
285         fprintf(stderr, "%d: End of file in variable declaration\n", Line);
286         exit(1);
287     }
288
289     if (ordinal >= MAX_ORDINALS)
290     {
291         fprintf(stderr, "%d: Ordinal number too large\n", Line);
292         exit(1);
293     }
294     
295     odp = &OrdinalDefinitions[ordinal];
296     odp->valid = 1;
297     odp->type = type;
298     strcpy(odp->export_name, export_name);
299     
300     vdp = malloc(sizeof(*vdp));
301     odp->additional_data = vdp;
302     
303     vdp->n_values = n_values;
304     vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
305
306     return 0;
307 }
308
309 int
310 ParseExportFunction(int ordinal, int type)
311 {
312     char *token;
313     ORDDEF *odp;
314     ORDFUNCDEF *fdp;
315     int i;
316     int current_offset;
317     int arg_size;
318         
319     
320     if (ordinal >= MAX_ORDINALS)
321     {
322         fprintf(stderr, "%d: Ordinal number too large\n", Line);
323         exit(1);
324     }
325     
326     odp = &OrdinalDefinitions[ordinal];
327     strcpy(odp->export_name, GetToken());
328     odp->valid = 1;
329     odp->type = type;
330     fdp = malloc(sizeof(*fdp));
331     odp->additional_data = fdp;
332
333     token = GetToken();
334     if (*token != '(')
335     {
336         fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
337         exit(1);
338     }
339
340     fdp->arg_16_size = 0;
341     for (i = 0; i < 16; i++)
342     {
343         token = GetToken();
344         if (*token == ')')
345             break;
346
347         if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
348         {
349             fdp->arg_types_16[i] = VARTYPE_WORD;
350             fdp->arg_16_size += 2;
351             fdp->arg_16_offsets[i] = 2;
352         }
353         else if (stricmp(token, "s_byte") == 0 || 
354                  stricmp(token, "s_word") == 0)
355         {
356             fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
357             fdp->arg_16_size += 2;
358             fdp->arg_16_offsets[i] = 2;
359         }
360         else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
361         {
362             fdp->arg_types_16[i] = VARTYPE_LONG;
363             fdp->arg_16_size += 4;
364             fdp->arg_16_offsets[i] = 4;
365         }
366         else if (stricmp(token, "ptr") == 0)
367         {
368             fdp->arg_types_16[i] = VARTYPE_FARPTR;
369             fdp->arg_16_size += 4;
370             fdp->arg_16_offsets[i] = 4;
371         }
372         else
373         {
374             fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
375             exit(1);
376         }
377     }
378     fdp->n_args_16 = i;
379
380     if (type == FUNCTYPE_PASCAL_16 || type == FUNCTYPE_PASCAL ||
381         type == FUNCTYPE_REG )
382     {
383         current_offset = 0;
384         for (i--; i >= 0; i--)
385         {
386             arg_size = fdp->arg_16_offsets[i];
387             fdp->arg_16_offsets[i] = current_offset;
388             current_offset += arg_size;
389         }
390     }
391     else
392     {
393         current_offset = 0;
394         for (i = 0; i < fdp->n_args_16; i++)
395         {
396             arg_size = fdp->arg_16_offsets[i];
397             fdp->arg_16_offsets[i] = current_offset;
398             current_offset += arg_size;
399         }
400     }
401
402     strcpy(fdp->internal_name, GetToken());
403     token = GetToken();
404     if (*token != '(')
405     {
406         fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
407         exit(1);
408     }
409     for (i = 0; i < 16; i++)
410     {
411         token = GetToken();
412         if (*token == ')')
413             break;
414
415         fdp->arg_indices_32[i] = atoi(token);
416         if (fdp->arg_indices_32[i] < 1 || 
417             fdp->arg_indices_32[i] > fdp->n_args_16)
418         {
419             fprintf(stderr, "%d: Bad argument index %d\n", Line,
420                     fdp->arg_indices_32[i]);
421             exit(1);
422         }
423     }
424     fdp->n_args_32 = i;
425
426     return 0;
427 }
428
429 int
430 ParseEquate(int ordinal)
431 {
432     ORDDEF *odp;
433     char *token;
434     char *endptr;
435     int value;
436     
437     if (ordinal >= MAX_ORDINALS)
438     {
439         fprintf(stderr, "%d: Ordinal number too large\n", Line);
440         exit(1);
441     }
442     
443     odp = &OrdinalDefinitions[ordinal];
444     strcpy(odp->export_name, GetToken());
445
446     token = GetToken();
447     value = strtol(token, &endptr, 0);
448     if (endptr == NULL || *endptr != '\0')
449     {
450         fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
451                 token);
452         exit(1);
453     }
454
455     odp->valid = 1;
456     odp->type = EQUATETYPE_ABS;
457     odp->additional_data = (void *) value;
458
459     return 0;
460 }
461
462 int
463 ParseReturn(int ordinal)
464 {
465     ORDDEF *odp;
466     ORDRETDEF *rdp;
467     char *token;
468     char *endptr;
469     
470     if (ordinal >= MAX_ORDINALS)
471     {
472         fprintf(stderr, "%d: Ordinal number too large\n", Line);
473         exit(1);
474     }
475
476     rdp = malloc(sizeof(*rdp));
477     
478     odp = &OrdinalDefinitions[ordinal];
479     strcpy(odp->export_name, GetToken());
480     odp->valid = 1;
481     odp->type = TYPE_RETURN;
482     odp->additional_data = rdp;
483
484     token = GetToken();
485     rdp->arg_size = strtol(token, &endptr, 0);
486     if (endptr == NULL || *endptr != '\0')
487     {
488         fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
489                 token);
490         exit(1);
491     }
492
493     token = GetToken();
494     rdp->ret_value = strtol(token, &endptr, 0);
495     if (endptr == NULL || *endptr != '\0')
496     {
497         fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
498                 token);
499         exit(1);
500     }
501
502     return 0;
503 }
504
505 int
506 ParseOrdinal(int ordinal)
507 {
508     char *token;
509     
510     token = GetToken();
511     if (token == NULL)
512     {
513         fprintf(stderr, "%d: Expected type after ordinal\n", Line);
514         exit(1);
515     }
516
517     if (stricmp(token, "byte") == 0)
518         return ParseVariable(ordinal, VARTYPE_BYTE);
519     else if (stricmp(token, "word") == 0)
520         return ParseVariable(ordinal, VARTYPE_WORD);
521     else if (stricmp(token, "long") == 0)
522         return ParseVariable(ordinal, VARTYPE_LONG);
523     else if (stricmp(token, "c") == 0)
524         return ParseExportFunction(ordinal, FUNCTYPE_C);
525     else if (stricmp(token, "p") == 0)
526         return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
527     else if (stricmp(token, "pascal") == 0)
528         return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
529     else if (stricmp(token, "pascal16") == 0)
530         return ParseExportFunction(ordinal, FUNCTYPE_PASCAL_16);
531     else if (stricmp(token, "register") == 0)
532         return ParseExportFunction(ordinal, FUNCTYPE_REG);
533     else if (stricmp(token, "equate") == 0)
534         return ParseEquate(ordinal);
535     else if (stricmp(token, "return") == 0)
536         return ParseReturn(ordinal);
537     else
538     {
539         fprintf(stderr, 
540                 "%d: Expected type after ordinal, found '%s' instead\n",
541                 Line, token);
542         exit(1);
543     }
544 }
545
546 int
547 ParseTopLevel(void)
548 {
549     char *token;
550     
551     while ((token = GetToken()) != NULL)
552     {
553         if (stricmp(token, "name") == 0)
554         {
555             strcpy(LowerDLLName, GetToken());
556             strlower(LowerDLLName);
557
558             strcpy(UpperDLLName, LowerDLLName);
559             strupper(UpperDLLName);
560         }
561         else if (stricmp(token, "id") == 0)
562         {
563             token = GetToken();
564             if (!IsNumberString(token))
565             {
566                 fprintf(stderr, "%d: Expected number after id\n", Line);
567                 exit(1);
568             }
569             
570             DLLId = atoi(token);
571         }
572         else if (stricmp(token, "length") == 0)
573         {
574             token = GetToken();
575             if (!IsNumberString(token))
576             {
577                 fprintf(stderr, "%d: Expected number after length\n", Line);
578                 exit(1);
579             }
580
581             Limit = atoi(token);
582         }
583         else if (IsNumberString(token))
584         {
585             int ordinal;
586             int rv;
587             
588             ordinal = atoi(token);
589             if ((rv = ParseOrdinal(ordinal)) < 0)
590                 return rv;
591         }
592         else
593         {
594             fprintf(stderr, 
595                     "%d: Expected name, id, length or ordinal\n", Line);
596             exit(1);
597         }
598     }
599
600     return 0;
601 }
602
603 void
604 InitContext(void)
605 {
606     struct sigcontext_struct context;
607     int i;
608     
609     n_context_strings = sizeof(context) / 4;
610     context_strings   = (char **) malloc(n_context_strings * sizeof(char **));
611     pop_strings       = (char **) malloc(n_context_strings * sizeof(char **));
612     for (i = 0; i < n_context_strings; i++)
613     {
614         context_strings[i] = PUSH_0;
615         pop_strings[i]     = POP_0;
616     }
617
618     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esp) / 4;
619     context_strings[i] = PUSH_ESP;
620
621     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebp) / 4;
622     context_strings[i] = PUSH_EBP;
623     pop_strings[n_context_strings - 1 - i] = POP_EBP;
624
625     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eip) / 4;
626     context_strings[i] = PUSH_EIP;
627
628 #ifndef __FreeBSD__
629     i = n_context_strings - 1 + ((int) &context - (int)&context.sc_eflags) / 4;
630 #else
631     i = n_context_strings - 1 + ((int) &context - (int)&context.sc_efl) / 4;
632 #endif
633     context_strings[i] = PUSH_EFL;
634     pop_strings[n_context_strings - 1 - i] = POP_EFL;
635
636     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_es) / 4;
637     context_strings[i] = PUSH_ES;
638     pop_strings[n_context_strings - 1 - i] = POP_ES;
639
640     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ds) / 4;
641     context_strings[i] = PUSH_DS;
642     pop_strings[n_context_strings - 1 - i] = POP_DS;
643
644     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_cs) / 4;
645     context_strings[i] = PUSH_CS;
646
647     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ss) / 4;
648     context_strings[i] = PUSH_SS;
649
650     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edi) / 4;
651     context_strings[i] = PUSH_EDI;
652     pop_strings[n_context_strings - 1 - i] = POP_EDI;
653
654     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esi) / 4;
655     context_strings[i] = PUSH_ESI;
656     pop_strings[n_context_strings - 1 - i] = POP_ESI;
657
658     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebx) / 4;
659     context_strings[i] = PUSH_EBX;
660     pop_strings[n_context_strings - 1 - i] = POP_EBX;
661
662     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edx) / 4;
663     context_strings[i] = PUSH_EDX;
664     pop_strings[n_context_strings - 1 - i] = POP_EDX;
665
666     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ecx) / 4;
667     context_strings[i] = PUSH_ECX;
668     pop_strings[n_context_strings - 1 - i] = POP_ECX;
669
670     i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eax) / 4;
671     context_strings[i] = PUSH_EAX;
672     pop_strings[n_context_strings - 1 - i] = POP_EAX;
673 }
674
675 void
676 OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
677 {
678     ORDVARDEF *vdp;
679     int i;
680
681     vdp = odp->additional_data;
682     for (i = 0; i < vdp->n_values; i++)
683     {
684         if ((i & 7) == 0)
685             fprintf(fp, "\t%s\t", storage);
686             
687         fprintf(fp, "%d", vdp->values[i]);
688         
689         if ((i & 7) == 7 || i == vdp->n_values - 1)
690             fprintf(fp, "\n");
691         else
692             fprintf(fp, ", ");
693     }
694     fprintf(fp, "\n");
695 }
696
697 int main(int argc, char **argv)
698 {
699     ORDDEF *odp;
700     ORDFUNCDEF *fdp;
701     ORDRETDEF *rdp;
702     FILE *fp;
703     char filename[80];
704     int i, ci, add_count;
705     
706     if (argc < 2)
707     {
708         fprintf(stderr, "usage: build SPECNAME\n       build -p\n");
709         exit(1);
710     }
711
712     InitContext();
713
714     if (strcmp("-p", argv[1]) == 0)
715     {
716         fp = fopen("pop.h", "w");
717         add_count = 0;
718         for (i = 0; i < n_context_strings; i++)
719         {
720             if (strncmp(pop_strings[i], "\tadd\t", 5) == 0)
721             {
722                 add_count += atoi(pop_strings[i] + 6);
723             }
724             else
725             {
726                 if (add_count > 0)
727                 {
728                     fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
729                     add_count = 0;
730                 }
731                 
732                 fprintf(fp, pop_strings[i]);
733             }
734         }
735     
736         if (add_count > 0)
737             fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
738
739         fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
740                 
741         fclose(fp);
742         exit(0);
743     }
744
745     SpecFp = fopen(argv[1], "r");
746     if (SpecFp == NULL)
747     {
748         fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
749         exit(1);
750     }
751
752     ParseTopLevel();
753
754     sprintf(filename, "dll_%s.S", LowerDLLName);
755     fp = fopen(filename, "w");
756
757     fprintf(fp, "\t.globl " PREFIX "%s_Dispatch\n", UpperDLLName);
758     fprintf(fp, PREFIX "%s_Dispatch:\n", UpperDLLName);
759     fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
760     fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
761     fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
762     fprintf(fp, "\tjmp\t" PREFIX "CallTo32\n\n");
763
764     fprintf(fp, "\t.globl " PREFIX "%s_Dispatch_16\n", UpperDLLName);
765     fprintf(fp, PREFIX "%s_Dispatch_16:\n", UpperDLLName);
766     fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
767     fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
768     fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
769     fprintf(fp, "\tjmp\t" PREFIX "CallTo32_16\n\n");
770
771     odp = OrdinalDefinitions;
772     for (i = 0; i <= Limit; i++, odp++)
773     {
774         fprintf(fp, "\t.globl " PREFIX "%s_Ordinal_%d\n", UpperDLLName, i);
775
776         if (!odp->valid)
777         {
778             fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
779             fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
780             fprintf(fp, "\tpushw\t$0\n");
781             fprintf(fp, "\tjmp\t" PREFIX "%s_Dispatch\n\n", UpperDLLName);
782         }
783         else
784         {
785             fdp = odp->additional_data;
786             rdp = odp->additional_data;
787             
788             switch (odp->type)
789             {
790               case EQUATETYPE_ABS:
791                 fprintf(fp, PREFIX "%s_Ordinal_%d = %d\n\n", 
792                         UpperDLLName, i, (int) odp->additional_data);
793                 break;
794
795               case VARTYPE_BYTE:
796                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
797                 OutputVariableCode(fp, ".byte", odp);
798                 break;
799
800               case VARTYPE_WORD:
801                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
802                 OutputVariableCode(fp, ".word", odp);
803                 break;
804
805               case VARTYPE_LONG:
806                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
807                 OutputVariableCode(fp, ".long", odp);
808                 break;
809
810               case TYPE_RETURN:
811                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
812                 fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
813                 fprintf(fp, "\tmovw\t$%d,%%dx\n", 
814                         (rdp->ret_value >> 16) & 0xffff);
815                 fprintf(fp, "\t.byte\t0x66\n");
816                 if (rdp->arg_size != 0)
817                     fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
818                 else
819                     fprintf(fp, "\tlret\n");
820                 break;
821
822               case FUNCTYPE_REG:
823                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
824                 fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
825                 fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
826
827                 for (ci = 0; ci < n_context_strings; ci++)
828                     fprintf(fp, context_strings[ci]);
829
830                 fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
831                 fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
832                 fprintf(fp, "\tpushl\t%d(%%ebp)\n",
833                         sizeof(struct sigcontext_struct));
834                 fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
835                 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
836                 fprintf(fp, "\tpushw\t$%d\n", 
837                         sizeof(struct sigcontext_struct) + 4);
838                 fprintf(fp, "\tjmp\t" PREFIX "%s_Dispatch\n\n", UpperDLLName);
839                 break;
840
841               case FUNCTYPE_PASCAL:
842                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
843                 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
844                 fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
845                 fprintf(fp, "\tjmp\t" PREFIX "%s_Dispatch\n\n", UpperDLLName);
846                 break;
847                 
848               case FUNCTYPE_PASCAL_16:
849                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
850                 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
851                 fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
852                 fprintf(fp, "\tjmp\t" PREFIX "%s_Dispatch_16\n\n", UpperDLLName);
853                 break;
854                 
855               case FUNCTYPE_C:
856               default:
857                 fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
858                 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
859                 fprintf(fp, "\tpushw\t$0\n");
860                 fprintf(fp, "\tjmp\t" PREFIX "%s_Dispatch\n\n", UpperDLLName);
861                 break;
862             }
863         }
864     }
865
866     fclose(fp);
867
868 #ifndef SHORTNAMES
869     sprintf(filename, "dll_%s_tab.c", LowerDLLName);
870 #else
871     sprintf(filename, "dtb_%s.c", LowerDLLName);
872 #endif
873     fp = fopen(filename, "w");
874
875     fprintf(fp, "#include <stdio.h>\n");
876     fprintf(fp, "#include <stdlib.h>\n");
877     fprintf(fp, "#include \042dlls.h\042\n\n");
878
879     for (i = 0; i <= Limit; i++)
880     {
881         fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
882     }
883     
884     odp = OrdinalDefinitions;
885     for (i = 0; i <= Limit; i++, odp++)
886     {
887         if (odp->valid && 
888             (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_PASCAL_16 ||
889              odp->type == FUNCTYPE_REG || odp->type == FUNCTYPE_C ))
890         {
891             fdp = odp->additional_data;
892             fprintf(fp, "extern int %s();\n", fdp->internal_name);
893         }
894     }
895     
896     fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
897             UpperDLLName, Limit + 1);
898     fprintf(fp, "{\n");
899     odp = OrdinalDefinitions;
900     for (i = 0; i <= Limit; i++, odp++)
901     {
902         fdp = odp->additional_data;
903
904         if (!odp->valid)
905             odp->type = -1;
906         
907         switch (odp->type)
908         {
909           case FUNCTYPE_PASCAL:
910           case FUNCTYPE_PASCAL_16:
911           case FUNCTYPE_REG:
912             fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
913             fprintf(fp, "\042%s\042, ", odp->export_name);
914             fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
915 #ifdef WINESTAT
916             fprintf(fp, "0, ");
917 #endif      
918             fprintf(fp, "%d, ", fdp->n_args_32);
919             if (fdp->n_args_32 > 0)
920             {
921                 int argnum;
922                 
923                 fprintf(fp, "\n      {\n");
924                 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
925                 {
926                     fprintf(fp, "        { %d, %d },\n",
927                             fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
928                             fdp->arg_types_16[argnum]);
929                 }
930                 fprintf(fp, "      }\n    ");
931             }
932             fprintf(fp, "}, \n");
933             break;
934                 
935           case FUNCTYPE_C:
936             fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
937             fprintf(fp, "\042%s\042, ", odp->export_name);
938             fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
939 #ifdef WINESTAT
940             fprintf(fp, "0, ");
941 #endif      
942             fprintf(fp, "%d, ", fdp->n_args_32);
943             if (fdp->n_args_32 > 0)
944             {
945                 int argnum;
946                 
947                 fprintf(fp, "\n      {\n");
948                 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
949                 {
950                     fprintf(fp, "        { %d, %d },\n",
951                             fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
952                             fdp->arg_types_16[argnum]);
953                 }
954                 fprintf(fp, "      }\n    ");
955             }
956             fprintf(fp, "}, \n");
957             break;
958             
959           default:
960             fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
961                     UTEXTSEL, UpperDLLName, i);
962             break;
963         }
964     }
965     fprintf(fp, "};\n");
966
967     fclose(fp);
968     return 0;
969 }
970