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