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";
10 #define VARTYPE_SIGNEDWORD 0
11 #define VARTYPE_WORD 1
12 #define VARTYPE_LONG 2
13 #define VARTYPE_FARPTR 3
15 #define FUNCTYPE_PASCAL 16
17 #define FUNCTYPE_REG 19
19 #define EQUATETYPE_ABS 18
20 #define TYPE_RETURN 20
22 #define MAX_ORDINALS 1024
24 typedef struct ordinal_definition_s
29 void *additional_data;
32 typedef struct ordinal_variable_definition_s
38 typedef struct ordinal_function_definition_s
42 int arg_16_offsets[16];
44 char internal_name[80];
46 int arg_indices_32[16];
49 typedef struct ordinal_return_definition_s
55 ORDDEF OrdinalDefinitions[MAX_ORDINALS];
57 char LowerDLLName[80];
58 char UpperDLLName[80];
63 char *ParseBuffer = NULL;
68 int IsNumberString(char *s)
77 char *strlower(char *s)
81 for(p = s; *p != '\0'; p++)
87 char *strupper(char *s)
91 for(p = s; *p != '\0'; p++)
97 int stricmp(char *s1, char *s2)
99 if (strlen(s1) != strlen(s2))
115 if (ParseNext != ParseBuffer)
117 if (ParseSaveChar == '\0')
119 *ParseNext = ParseSaveChar;
123 * Remove initial white space.
125 for (p = ParseNext; isspace(*p); p++)
135 if (*token != '(' && *token != ')')
136 while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
151 if (ParseBuffer == NULL)
153 ParseBuffer = malloc(512);
154 ParseNext = ParseBuffer;
158 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
160 if (ParseBuffer[0] != '#')
165 while ((token = GetTokenInLine()) == NULL)
167 ParseNext = ParseBuffer;
171 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
173 if (ParseBuffer[0] != '#')
182 ParseVariable(int ordinal, int type)
186 char export_name[80];
191 int value_array_size;
193 strcpy(export_name, GetToken());
198 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
203 value_array_size = 25;
204 value_array = malloc(sizeof(*value_array) * value_array_size);
206 while ((token = GetToken()) != NULL)
211 value_array[n_values++] = strtol(token, &endptr, 0);
212 if (n_values == value_array_size)
214 value_array_size += 25;
215 value_array = realloc(value_array,
216 sizeof(*value_array) * value_array_size);
219 if (endptr == NULL || *endptr != '\0')
221 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
229 fprintf(stderr, "%d: End of file in variable declaration\n", Line);
233 if (ordinal >= MAX_ORDINALS)
235 fprintf(stderr, "%d: Ordinal number too large\n", Line);
239 odp = &OrdinalDefinitions[ordinal];
242 strcpy(odp->export_name, export_name);
244 vdp = malloc(sizeof(*vdp));
245 odp->additional_data = vdp;
247 vdp->n_values = n_values;
248 vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
254 ParseExportFunction(int ordinal, int type)
266 if (ordinal >= MAX_ORDINALS)
268 fprintf(stderr, "%d: Ordinal number too large\n", Line);
272 odp = &OrdinalDefinitions[ordinal];
273 strcpy(odp->export_name, GetToken());
276 fdp = malloc(sizeof(*fdp));
277 odp->additional_data = fdp;
282 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
286 fdp->arg_16_size = 0;
287 for (i = 0; i < 16; i++)
293 if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
295 fdp->arg_types_16[i] = VARTYPE_WORD;
296 fdp->arg_16_size += 2;
297 fdp->arg_16_offsets[i] = 2;
299 else if (stricmp(token, "s_byte") == 0 ||
300 stricmp(token, "s_word") == 0)
302 fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
303 fdp->arg_16_size += 2;
304 fdp->arg_16_offsets[i] = 2;
306 else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
308 fdp->arg_types_16[i] = VARTYPE_LONG;
309 fdp->arg_16_size += 4;
310 fdp->arg_16_offsets[i] = 4;
312 else if (stricmp(token, "ptr") == 0)
314 fdp->arg_types_16[i] = VARTYPE_FARPTR;
315 fdp->arg_16_size += 4;
316 fdp->arg_16_offsets[i] = 4;
320 fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
326 if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
329 for (i--; i >= 0; i--)
331 arg_size = fdp->arg_16_offsets[i];
332 fdp->arg_16_offsets[i] = current_offset;
333 current_offset += arg_size;
339 for (i = 0; i < fdp->n_args_16; i++)
341 arg_size = fdp->arg_16_offsets[i];
342 fdp->arg_16_offsets[i] = current_offset;
343 current_offset += arg_size;
347 strcpy(fdp->internal_name, GetToken());
351 fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
354 for (i = 0; i < 16; i++)
360 fdp->arg_indices_32[i] = atoi(token);
361 if (fdp->arg_indices_32[i] < 1 ||
362 fdp->arg_indices_32[i] > fdp->n_args_16)
364 fprintf(stderr, "%d: Bad argument index %d\n", Line,
365 fdp->arg_indices_32[i]);
375 ParseEquate(int ordinal)
382 if (ordinal >= MAX_ORDINALS)
384 fprintf(stderr, "%d: Ordinal number too large\n", Line);
388 odp = &OrdinalDefinitions[ordinal];
389 strcpy(odp->export_name, GetToken());
392 value = strtol(token, &endptr, 0);
393 if (endptr == NULL || *endptr != '\0')
395 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
401 odp->type = EQUATETYPE_ABS;
402 odp->additional_data = (void *) value;
408 ParseReturn(int ordinal)
416 if (ordinal >= MAX_ORDINALS)
418 fprintf(stderr, "%d: Ordinal number too large\n", Line);
422 rdp = malloc(sizeof(*rdp));
424 odp = &OrdinalDefinitions[ordinal];
425 strcpy(odp->export_name, GetToken());
427 odp->type = TYPE_RETURN;
428 odp->additional_data = rdp;
431 rdp->arg_size = strtol(token, &endptr, 0);
432 if (endptr == NULL || *endptr != '\0')
434 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
440 rdp->ret_value = strtol(token, &endptr, 0);
441 if (endptr == NULL || *endptr != '\0')
443 fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
452 ParseOrdinal(int ordinal)
459 fprintf(stderr, "%d: Expected type after ordinal\n", Line);
463 if (stricmp(token, "byte") == 0)
464 return ParseVariable(ordinal, VARTYPE_BYTE);
465 else if (stricmp(token, "word") == 0)
466 return ParseVariable(ordinal, VARTYPE_WORD);
467 else if (stricmp(token, "long") == 0)
468 return ParseVariable(ordinal, VARTYPE_LONG);
469 else if (stricmp(token, "c") == 0)
470 return ParseExportFunction(ordinal, FUNCTYPE_C);
471 else if (stricmp(token, "p") == 0)
472 return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
473 else if (stricmp(token, "pascal") == 0)
474 return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
475 else if (stricmp(token, "register") == 0)
476 return ParseExportFunction(ordinal, FUNCTYPE_REG);
477 else if (stricmp(token, "equate") == 0)
478 return ParseEquate(ordinal);
479 else if (stricmp(token, "return") == 0)
480 return ParseReturn(ordinal);
484 "%d: Expected type after ordinal, found '%s' instead\n",
495 while ((token = GetToken()) != NULL)
497 if (stricmp(token, "name") == 0)
499 strcpy(LowerDLLName, GetToken());
500 strlower(LowerDLLName);
502 strcpy(UpperDLLName, LowerDLLName);
503 strupper(UpperDLLName);
505 else if (stricmp(token, "id") == 0)
508 if (!IsNumberString(token))
510 fprintf(stderr, "%d: Expected number after id\n", Line);
516 else if (stricmp(token, "length") == 0)
519 if (!IsNumberString(token))
521 fprintf(stderr, "%d: Expected number after length\n", Line);
527 else if (IsNumberString(token))
532 ordinal = atoi(token);
533 if ((rv = ParseOrdinal(ordinal)) < 0)
539 "%d: Expected name, id, length or ordinal\n", Line);
548 OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
553 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
555 vdp = odp->additional_data;
556 for (i = 0; i < vdp->n_values; i++)
559 fprintf(fp, "\t%s\t", storage);
561 fprintf(fp, "%d", vdp->values[i]);
563 if ((i & 7) == 7 || i == vdp->n_values - 1)
571 main(int argc, char **argv)
584 fprintf(stderr, "usage: build SPECNAME\n");
588 SpecFp = fopen(argv[1], "r");
591 fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
597 sprintf(filename, "dll_%s.S", LowerDLLName);
598 fp = fopen(filename, "w");
600 fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
601 fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
602 fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
603 fprintf(fp, "\tjmp\t_CallTo32\n\n");
605 odp = OrdinalDefinitions;
606 for (i = 0; i <= Limit; i++, odp++)
608 fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
612 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
613 fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
614 fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
615 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
616 fprintf(fp, "\tpushw\t$0\n");
617 fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
621 fdp = odp->additional_data;
622 rdp = odp->additional_data;
627 fprintf(fp, "_%s_Ordinal_%d = %d\n\n",
628 UpperDLLName, i, (int) odp->additional_data);
632 OutputVariableCode(fp, ".byte", odp);
636 OutputVariableCode(fp, ".word", odp);
640 OutputVariableCode(fp, ".long", odp);
644 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
645 fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
646 fprintf(fp, "\tmovw\t$%d,%%dx\n",
647 (rdp->ret_value >> 16) & 0xffff);
648 fprintf(fp, "\t.byte\t0x66\n");
649 if (rdp->arg_size != 0)
650 fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
652 fprintf(fp, "\tlret\n");
656 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
657 fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
658 fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
659 fprintf(fp, "\tpushw\t%%ax\n");
660 fprintf(fp, "\tpushw\t%%cx\n");
661 fprintf(fp, "\tpushw\t%%dx\n");
662 fprintf(fp, "\tpushw\t%%bx\n");
663 fprintf(fp, "\tpushw\t%%sp\n");
664 fprintf(fp, "\tpushw\t%%bp\n");
665 fprintf(fp, "\tpushw\t%%si\n");
666 fprintf(fp, "\tpushw\t%%di\n");
667 fprintf(fp, "\tpushw\t%%ds\n");
668 fprintf(fp, "\tpushw\t%%es\n");
669 fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
670 fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
671 fprintf(fp, "\tpushl\t20(%%ebp)\n");
672 fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
673 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
674 fprintf(fp, "\tpushw\t$24\n");
675 fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
678 case FUNCTYPE_PASCAL:
679 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
680 fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
681 fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
682 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
683 fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
684 fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
689 fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
690 fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
691 fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
692 fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
693 fprintf(fp, "\tpushw\t$0\n");
694 fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
702 sprintf(filename, "dll_%s_tab.c", LowerDLLName);
703 fp = fopen(filename, "w");
705 fprintf(fp, "#include <stdio.h>\n");
706 fprintf(fp, "#include <stdlib.h>\n");
707 fprintf(fp, "#include \042dlls.h\042\n\n");
709 for (i = 0; i <= Limit; i++)
711 fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
714 odp = OrdinalDefinitions;
715 for (i = 0; i <= Limit; i++, odp++)
718 (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
719 odp->type == FUNCTYPE_REG))
721 fdp = odp->additional_data;
722 fprintf(fp, "extern int %s();\n", fdp->internal_name);
726 fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n",
727 UpperDLLName, Limit + 1);
729 odp = OrdinalDefinitions;
730 for (i = 0; i <= Limit; i++, odp++)
732 fdp = odp->additional_data;
739 case FUNCTYPE_PASCAL:
741 fprintf(fp, " { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
742 fprintf(fp, "\042%s\042, ", odp->export_name);
743 fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
744 fprintf(fp, "%d, ", fdp->n_args_32);
745 if (fdp->n_args_32 > 0)
749 fprintf(fp, "\n {\n");
750 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
752 fprintf(fp, " { %d, %d },\n",
753 fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
754 fdp->arg_types_16[argnum]);
756 fprintf(fp, " }\n ");
758 fprintf(fp, "}, \n");
762 fprintf(fp, " { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
763 fprintf(fp, "\042%s\042, ", odp->export_name);
764 fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
765 fprintf(fp, "%d, ", fdp->n_args_32);
766 if (fdp->n_args_32 > 0)
770 fprintf(fp, "\n {\n");
771 for (argnum = 0; argnum < fdp->n_args_32; argnum++)
773 fprintf(fp, " { %d, %d },\n",
774 fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
775 fdp->arg_types_16[argnum]);
777 fprintf(fp, " }\n ");
779 fprintf(fp, "}, \n");
783 fprintf(fp, " { 0x23, %s_Ordinal_%d, \042\042, NULL },\n",