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