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