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";
13 #if defined(__NetBSD__) || defined(__FreeBSD__)
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
23 #define FUNCTYPE_PASCAL 16
25 #define FUNCTYPE_REG 19
27 #define EQUATETYPE_ABS 18
28 #define TYPE_RETURN 20
30 #define MAX_ORDINALS 1024
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"
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"
68 char **context_strings;
70 int n_context_strings;
72 typedef struct ordinal_definition_s
77 void *additional_data;
80 typedef struct ordinal_variable_definition_s
86 typedef struct ordinal_function_definition_s
90 int arg_16_offsets[16];
92 char internal_name[80];
94 int arg_indices_32[16];
97 typedef struct ordinal_return_definition_s
103 ORDDEF OrdinalDefinitions[MAX_ORDINALS];
105 char LowerDLLName[80];
106 char UpperDLLName[80];
111 char *ParseBuffer = NULL;
116 int IsNumberString(char *s)
125 char *strlower(char *s)
129 for(p = s; *p != '\0'; p++)
135 char *strupper(char *s)
139 for(p = s; *p != '\0'; p++)
145 int stricmp(char *s1, char *s2)
147 if (strlen(s1) != strlen(s2))
163 if (ParseNext != ParseBuffer)
165 if (ParseSaveChar == '\0')
167 *ParseNext = ParseSaveChar;
171 * Remove initial white space.
173 for (p = ParseNext; isspace(*p); p++)
183 if (*token != '(' && *token != ')')
184 while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
199 if (ParseBuffer == NULL)
201 ParseBuffer = malloc(512);
202 ParseNext = ParseBuffer;
206 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
208 if (ParseBuffer[0] != '#')
213 while ((token = GetTokenInLine()) == NULL)
215 ParseNext = ParseBuffer;
219 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
221 if (ParseBuffer[0] != '#')
230 ParseVariable(int ordinal, int type)
234 char export_name[80];
239 int value_array_size;
241 strcpy(export_name, GetToken());
246 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
251 value_array_size = 25;
252 value_array = malloc(sizeof(*value_array) * value_array_size);
254 while ((token = GetToken()) != NULL)
259 value_array[n_values++] = strtol(token, &endptr, 0);
260 if (n_values == value_array_size)
262 value_array_size += 25;
263 value_array = realloc(value_array,
264 sizeof(*value_array) * value_array_size);
267 if (endptr == NULL || *endptr != '\0')
269 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
277 fprintf(stderr, "%d: End of file in variable declaration\n", Line);
281 if (ordinal >= MAX_ORDINALS)
283 fprintf(stderr, "%d: Ordinal number too large\n", Line);
287 odp = &OrdinalDefinitions[ordinal];
290 strcpy(odp->export_name, export_name);
292 vdp = malloc(sizeof(*vdp));
293 odp->additional_data = vdp;
295 vdp->n_values = n_values;
296 vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
302 ParseExportFunction(int ordinal, int type)
314 if (ordinal >= MAX_ORDINALS)
316 fprintf(stderr, "%d: Ordinal number too large\n", Line);
320 odp = &OrdinalDefinitions[ordinal];
321 strcpy(odp->export_name, GetToken());
324 fdp = malloc(sizeof(*fdp));
325 odp->additional_data = fdp;
330 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
334 fdp->arg_16_size = 0;
335 for (i = 0; i < 16; i++)
341 if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
343 fdp->arg_types_16[i] = VARTYPE_WORD;
344 fdp->arg_16_size += 2;
345 fdp->arg_16_offsets[i] = 2;
347 else if (stricmp(token, "s_byte") == 0 ||
348 stricmp(token, "s_word") == 0)
350 fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
351 fdp->arg_16_size += 2;
352 fdp->arg_16_offsets[i] = 2;
354 else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
356 fdp->arg_types_16[i] = VARTYPE_LONG;
357 fdp->arg_16_size += 4;
358 fdp->arg_16_offsets[i] = 4;
360 else if (stricmp(token, "ptr") == 0)
362 fdp->arg_types_16[i] = VARTYPE_FARPTR;
363 fdp->arg_16_size += 4;
364 fdp->arg_16_offsets[i] = 4;
368 fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
374 if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
377 for (i--; i >= 0; i--)
379 arg_size = fdp->arg_16_offsets[i];
380 fdp->arg_16_offsets[i] = current_offset;
381 current_offset += arg_size;
387 for (i = 0; i < fdp->n_args_16; i++)
389 arg_size = fdp->arg_16_offsets[i];
390 fdp->arg_16_offsets[i] = current_offset;
391 current_offset += arg_size;
395 strcpy(fdp->internal_name, GetToken());
399 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
402 for (i = 0; i < 16; i++)
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)
412 fprintf(stderr, "%d: Bad argument index %d\n", Line,
413 fdp->arg_indices_32[i]);
423 ParseEquate(int ordinal)
430 if (ordinal >= MAX_ORDINALS)
432 fprintf(stderr, "%d: Ordinal number too large\n", Line);
436 odp = &OrdinalDefinitions[ordinal];
437 strcpy(odp->export_name, GetToken());
440 value = strtol(token, &endptr, 0);
441 if (endptr == NULL || *endptr != '\0')
443 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
449 odp->type = EQUATETYPE_ABS;
450 odp->additional_data = (void *) value;
456 ParseReturn(int ordinal)
464 if (ordinal >= MAX_ORDINALS)
466 fprintf(stderr, "%d: Ordinal number too large\n", Line);
470 rdp = malloc(sizeof(*rdp));
472 odp = &OrdinalDefinitions[ordinal];
473 strcpy(odp->export_name, GetToken());
475 odp->type = TYPE_RETURN;
476 odp->additional_data = rdp;
479 rdp->arg_size = strtol(token, &endptr, 0);
480 if (endptr == NULL || *endptr != '\0')
482 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
488 rdp->ret_value = strtol(token, &endptr, 0);
489 if (endptr == NULL || *endptr != '\0')
491 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
500 ParseOrdinal(int ordinal)
507 fprintf(stderr, "%d: Expected type after ordinal\n", Line);
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);
532 "%d: Expected type after ordinal, found '%s' instead\n",
543 while ((token = GetToken()) != NULL)
545 if (stricmp(token, "name") == 0)
547 strcpy(LowerDLLName, GetToken());
548 strlower(LowerDLLName);
550 strcpy(UpperDLLName, LowerDLLName);
551 strupper(UpperDLLName);
553 else if (stricmp(token, "id") == 0)
556 if (!IsNumberString(token))
558 fprintf(stderr, "%d: Expected number after id\n", Line);
564 else if (stricmp(token, "length") == 0)
567 if (!IsNumberString(token))
569 fprintf(stderr, "%d: Expected number after length\n", Line);
575 else if (IsNumberString(token))
580 ordinal = atoi(token);
581 if ((rv = ParseOrdinal(ordinal)) < 0)
587 "%d: Expected name, id, length or ordinal\n", Line);
597 struct sigcontext_struct context;
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++)
606 context_strings[i] = PUSH_0;
607 pop_strings[i] = POP_0;
610 i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esp) / 4;
611 context_strings[i] = PUSH_ESP;
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;
617 i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eip) / 4;
618 context_strings[i] = PUSH_EIP;
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;
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;
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;
632 i = n_context_strings - 1 + ((int) &context - (int) &context.sc_cs) / 4;
633 context_strings[i] = PUSH_CS;
635 i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ss) / 4;
636 context_strings[i] = PUSH_SS;
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;
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;
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;
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;
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;
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;
664 OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
669 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
671 vdp = odp->additional_data;
672 for (i = 0; i < vdp->n_values; i++)
675 fprintf(fp, "\t%s\t", storage);
677 fprintf(fp, "%d", vdp->values[i]);
679 if ((i & 7) == 7 || i == vdp->n_values - 1)
687 main(int argc, char **argv)
701 fprintf(stderr, "usage: build SPECNAME\n build -p\n");
707 if (strcmp("-p", argv[1]) == 0)
709 fp = fopen("pop.h", "w");
711 for (i = 0; i < n_context_strings; i++)
713 if (strncmp(pop_strings[i], "\tadd\t", 5) == 0)
715 add_count += atoi(pop_strings[i] + 6);
721 fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
725 fprintf(fp, pop_strings[i]);
730 fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
732 fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
738 SpecFp = fopen(argv[1], "r");
741 fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
747 sprintf(filename, "dll_%s.S", LowerDLLName);
748 fp = fopen(filename, "w");
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");
757 odp = OrdinalDefinitions;
758 for (i = 0; i <= Limit; i++, odp++)
760 fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
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);
771 fdp = odp->additional_data;
772 rdp = odp->additional_data;
777 fprintf(fp, "_%s_Ordinal_%d = %d\n\n",
778 UpperDLLName, i, (int) odp->additional_data);
782 OutputVariableCode(fp, ".byte", odp);
786 OutputVariableCode(fp, ".word", odp);
790 OutputVariableCode(fp, ".long", odp);
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);
802 fprintf(fp, "\tlret\n");
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");
810 for (ci = 0; ci < n_context_strings; ci++)
811 fprintf(fp, context_strings[ci]);
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);
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);
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);
845 sprintf(filename, "dll_%s_tab.c", LowerDLLName);
847 sprintf(filename, "dtb_%s.c", LowerDLLName);
849 fp = fopen(filename, "w");
851 fprintf(fp, "#include <stdio.h>\n");
852 fprintf(fp, "#include <stdlib.h>\n");
853 fprintf(fp, "#include \042dlls.h\042\n\n");
855 for (i = 0; i <= Limit; i++)
857 fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
860 odp = OrdinalDefinitions;
861 for (i = 0; i <= Limit; i++, odp++)
864 (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
865 odp->type == FUNCTYPE_REG))
867 fdp = odp->additional_data;
868 fprintf(fp, "extern int %s();\n", fdp->internal_name);
872 fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n",
873 UpperDLLName, Limit + 1);
875 odp = OrdinalDefinitions;
876 for (i = 0; i <= Limit; i++, odp++)
878 fdp = odp->additional_data;
885 case FUNCTYPE_PASCAL:
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);
893 fprintf(fp, "%d, ", fdp->n_args_32);
894 if (fdp->n_args_32 > 0)
898 fprintf(fp, "\n {\n");
899 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
901 fprintf(fp, " { %d, %d },\n",
902 fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
903 fdp->arg_types_16[argnum]);
905 fprintf(fp, " }\n ");
907 fprintf(fp, "}, \n");
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);
917 fprintf(fp, "%d, ", fdp->n_args_32);
918 if (fdp->n_args_32 > 0)
922 fprintf(fp, "\n {\n");
923 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
925 fprintf(fp, " { %d, %d },\n",
926 fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
927 fdp->arg_types_16[argnum]);
929 fprintf(fp, " }\n ");
931 fprintf(fp, "}, \n");
935 fprintf(fp, " { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n",
936 UTEXTSEL, UpperDLLName, i);