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