946 lines
21 KiB
C
946 lines
21 KiB
C
static char RCSId[] = "$Id: build.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
|
|
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "wine.h"
|
|
|
|
#ifdef linux
|
|
#define UTEXTSEL 0x23
|
|
#endif
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__)
|
|
#define UTEXTSEL 0x1f
|
|
#endif
|
|
|
|
#define VARTYPE_BYTE 0
|
|
#define VARTYPE_SIGNEDWORD 0
|
|
#define VARTYPE_WORD 1
|
|
#define VARTYPE_LONG 2
|
|
#define VARTYPE_FARPTR 3
|
|
|
|
#define FUNCTYPE_PASCAL 16
|
|
#define FUNCTYPE_C 17
|
|
#define FUNCTYPE_REG 19
|
|
|
|
#define EQUATETYPE_ABS 18
|
|
#define TYPE_RETURN 20
|
|
|
|
/*#define MAX_ORDINALS 1024*/
|
|
#define MAX_ORDINALS 1299
|
|
|
|
#define PUSH_0 "\tpushl\t$0\n"
|
|
#define PUSH_SS "\tpushw\t$0\n\tpushw\t%%ss\n"
|
|
#define PUSH_ESP "\tpushl\t%%esp\n"
|
|
#define PUSH_EFL "\tpushfl\n"
|
|
#define PUSH_CS "\tpushw\t$0\n\tpushw\t%%cs\n"
|
|
#define PUSH_EIP "\tpushl\t$0\n"
|
|
#define PUSH_DS "\tpushw\t$0\n\tpushw\t%%ds\n"
|
|
#define PUSH_ES "\tpushw\t$0\n\tpushw\t%%es\n"
|
|
#define PUSH_FS "\tpushw\t$0\n\tpushw\t%%fs\n"
|
|
#define PUSH_GS "\tpushw\t$0\n\tpushw\t%%gs\n"
|
|
#define PUSH_EAX "\tpushl\t%%eax\n"
|
|
#define PUSH_ECX "\tpushl\t%%ecx\n"
|
|
#define PUSH_EDX "\tpushl\t%%edx\n"
|
|
#define PUSH_EBX "\tpushl\t%%ebx\n"
|
|
#define PUSH_EBP "\tpushl\t%%ebp\n"
|
|
#define PUSH_ESI "\tpushl\t%%esi\n"
|
|
#define PUSH_EDI "\tpushl\t%%edi\n"
|
|
|
|
#define POP_0 "\tadd\t$4,%%esp\n"
|
|
#define POP_SS "\tpopw\t%%ss\n\tadd\t$2,%%esp\n"
|
|
#define POP_ESP "\tpopl\t%%esp\n"
|
|
#define POP_EFL "\tpopl\t%%gs:return_value\n"
|
|
#define POP_CS "\tpopw\t%%cs\n\tadd\t$2,%%esp\n"
|
|
#define POP_EIP "\tpopl\t$0\n"
|
|
#define POP_DS "\tpopw\t%%ds\n\tadd\t$2,%%esp\n"
|
|
#define POP_ES "\tpopw\t%%es\n\tadd\t$2,%%esp\n"
|
|
#define POP_FS "\tpopw\t%%fs\n\tadd\t$2,%%esp\n"
|
|
#define POP_GS "\tpopw\t%%gs\n\tadd\t$2,%%esp\n"
|
|
#define POP_EAX "\tpopl\t%%eax\n"
|
|
#define POP_ECX "\tpopl\t%%ecx\n"
|
|
#define POP_EDX "\tpopl\t%%edx\n"
|
|
#define POP_EBX "\tpopl\t%%ebx\n"
|
|
#define POP_EBP "\tpopl\t%%ebp\n"
|
|
#define POP_ESI "\tpopl\t%%esi\n"
|
|
#define POP_EDI "\tpopl\t%%edi\n"
|
|
|
|
char **context_strings;
|
|
char **pop_strings;
|
|
int n_context_strings;
|
|
|
|
typedef struct ordinal_definition_s
|
|
{
|
|
int valid;
|
|
int type;
|
|
char export_name[80];
|
|
void *additional_data;
|
|
} ORDDEF;
|
|
|
|
typedef struct ordinal_variable_definition_s
|
|
{
|
|
int n_values;
|
|
int *values;
|
|
} ORDVARDEF;
|
|
|
|
typedef struct ordinal_function_definition_s
|
|
{
|
|
int n_args_16;
|
|
int arg_types_16[16];
|
|
int arg_16_offsets[16];
|
|
int arg_16_size;
|
|
char internal_name[80];
|
|
int n_args_32;
|
|
int arg_indices_32[16];
|
|
} ORDFUNCDEF;
|
|
|
|
typedef struct ordinal_return_definition_s
|
|
{
|
|
int arg_size;
|
|
int ret_value;
|
|
} ORDRETDEF;
|
|
|
|
ORDDEF OrdinalDefinitions[MAX_ORDINALS];
|
|
|
|
char LowerDLLName[80];
|
|
char UpperDLLName[80];
|
|
int Limit;
|
|
int DLLId;
|
|
FILE *SpecFp;
|
|
|
|
char *ParseBuffer = NULL;
|
|
char *ParseNext;
|
|
char ParseSaveChar;
|
|
int Line;
|
|
|
|
int IsNumberString(char *s)
|
|
{
|
|
while (*s != '\0')
|
|
if (!isdigit(*s++))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
char *strlower(char *s)
|
|
{
|
|
char *p;
|
|
|
|
for(p = s; *p != '\0'; p++)
|
|
*p = tolower(*p);
|
|
|
|
return s;
|
|
}
|
|
|
|
char *strupper(char *s)
|
|
{
|
|
char *p;
|
|
|
|
for(p = s; *p != '\0'; p++)
|
|
*p = toupper(*p);
|
|
|
|
return s;
|
|
}
|
|
|
|
int stricmp(char *s1, char *s2)
|
|
{
|
|
if (strlen(s1) != strlen(s2))
|
|
return -1;
|
|
|
|
while (*s1 != '\0')
|
|
if (*s1++ != *s2++)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
GetTokenInLine(void)
|
|
{
|
|
char *p;
|
|
char *token;
|
|
|
|
if (ParseNext != ParseBuffer)
|
|
{
|
|
if (ParseSaveChar == '\0')
|
|
return NULL;
|
|
*ParseNext = ParseSaveChar;
|
|
}
|
|
|
|
/*
|
|
* Remove initial white space.
|
|
*/
|
|
for (p = ParseNext; isspace(*p); p++)
|
|
;
|
|
|
|
if (*p == '\0')
|
|
return NULL;
|
|
|
|
/*
|
|
* Find end of token.
|
|
*/
|
|
token = p++;
|
|
if (*token != '(' && *token != ')')
|
|
while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
|
|
p++;
|
|
|
|
ParseSaveChar = *p;
|
|
ParseNext = p;
|
|
*p = '\0';
|
|
|
|
return token;
|
|
}
|
|
|
|
char *
|
|
GetToken(void)
|
|
{
|
|
char *token;
|
|
|
|
if (ParseBuffer == NULL)
|
|
{
|
|
ParseBuffer = malloc(512);
|
|
ParseNext = ParseBuffer;
|
|
Line++;
|
|
while (1)
|
|
{
|
|
if (fgets(ParseBuffer, 511, SpecFp) == NULL)
|
|
return NULL;
|
|
if (ParseBuffer[0] != '#')
|
|
break;
|
|
}
|
|
}
|
|
|
|
while ((token = GetTokenInLine()) == NULL)
|
|
{
|
|
ParseNext = ParseBuffer;
|
|
Line++;
|
|
while (1)
|
|
{
|
|
if (fgets(ParseBuffer, 511, SpecFp) == NULL)
|
|
return NULL;
|
|
if (ParseBuffer[0] != '#')
|
|
break;
|
|
}
|
|
}
|
|
|
|
return token;
|
|
}
|
|
|
|
int
|
|
ParseVariable(int ordinal, int type)
|
|
{
|
|
ORDDEF *odp;
|
|
ORDVARDEF *vdp;
|
|
char export_name[80];
|
|
char *token;
|
|
char *endptr;
|
|
int *value_array;
|
|
int n_values;
|
|
int value_array_size;
|
|
|
|
strcpy(export_name, GetToken());
|
|
|
|
token = GetToken();
|
|
if (*token != '(')
|
|
{
|
|
fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
|
|
exit(1);
|
|
}
|
|
|
|
n_values = 0;
|
|
value_array_size = 25;
|
|
value_array = malloc(sizeof(*value_array) * value_array_size);
|
|
|
|
while ((token = GetToken()) != NULL)
|
|
{
|
|
if (*token == ')')
|
|
break;
|
|
|
|
value_array[n_values++] = strtol(token, &endptr, 0);
|
|
if (n_values == value_array_size)
|
|
{
|
|
value_array_size += 25;
|
|
value_array = realloc(value_array,
|
|
sizeof(*value_array) * value_array_size);
|
|
}
|
|
|
|
if (endptr == NULL || *endptr != '\0')
|
|
{
|
|
fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
|
|
token);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (token == NULL)
|
|
{
|
|
fprintf(stderr, "%d: End of file in variable declaration\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
if (ordinal >= MAX_ORDINALS)
|
|
{
|
|
fprintf(stderr, "%d: Ordinal number too large\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
odp = &OrdinalDefinitions[ordinal];
|
|
odp->valid = 1;
|
|
odp->type = type;
|
|
strcpy(odp->export_name, export_name);
|
|
|
|
vdp = malloc(sizeof(*vdp));
|
|
odp->additional_data = vdp;
|
|
|
|
vdp->n_values = n_values;
|
|
vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ParseExportFunction(int ordinal, int type)
|
|
{
|
|
char *token;
|
|
ORDDEF *odp;
|
|
ORDFUNCDEF *fdp;
|
|
int arg_types[16];
|
|
int i;
|
|
int arg_num;
|
|
int current_offset;
|
|
int arg_size;
|
|
|
|
|
|
if (ordinal >= MAX_ORDINALS)
|
|
{
|
|
fprintf(stderr, "%d: Ordinal number too large\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
odp = &OrdinalDefinitions[ordinal];
|
|
strcpy(odp->export_name, GetToken());
|
|
odp->valid = 1;
|
|
odp->type = type;
|
|
fdp = malloc(sizeof(*fdp));
|
|
odp->additional_data = fdp;
|
|
|
|
token = GetToken();
|
|
if (*token != '(')
|
|
{
|
|
fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
|
|
exit(1);
|
|
}
|
|
|
|
fdp->arg_16_size = 0;
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
token = GetToken();
|
|
if (*token == ')')
|
|
break;
|
|
|
|
if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
|
|
{
|
|
fdp->arg_types_16[i] = VARTYPE_WORD;
|
|
fdp->arg_16_size += 2;
|
|
fdp->arg_16_offsets[i] = 2;
|
|
}
|
|
else if (stricmp(token, "s_byte") == 0 ||
|
|
stricmp(token, "s_word") == 0)
|
|
{
|
|
fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
|
|
fdp->arg_16_size += 2;
|
|
fdp->arg_16_offsets[i] = 2;
|
|
}
|
|
else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
|
|
{
|
|
fdp->arg_types_16[i] = VARTYPE_LONG;
|
|
fdp->arg_16_size += 4;
|
|
fdp->arg_16_offsets[i] = 4;
|
|
}
|
|
else if (stricmp(token, "ptr") == 0)
|
|
{
|
|
fdp->arg_types_16[i] = VARTYPE_FARPTR;
|
|
fdp->arg_16_size += 4;
|
|
fdp->arg_16_offsets[i] = 4;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
|
|
exit(1);
|
|
}
|
|
}
|
|
fdp->n_args_16 = i;
|
|
|
|
if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
|
|
{
|
|
current_offset = 0;
|
|
for (i--; i >= 0; i--)
|
|
{
|
|
arg_size = fdp->arg_16_offsets[i];
|
|
fdp->arg_16_offsets[i] = current_offset;
|
|
current_offset += arg_size;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
current_offset = 0;
|
|
for (i = 0; i < fdp->n_args_16; i++)
|
|
{
|
|
arg_size = fdp->arg_16_offsets[i];
|
|
fdp->arg_16_offsets[i] = current_offset;
|
|
current_offset += arg_size;
|
|
}
|
|
}
|
|
|
|
strcpy(fdp->internal_name, GetToken());
|
|
token = GetToken();
|
|
if (*token != '(')
|
|
{
|
|
fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
token = GetToken();
|
|
if (*token == ')')
|
|
break;
|
|
|
|
fdp->arg_indices_32[i] = atoi(token);
|
|
if (fdp->arg_indices_32[i] < 1 ||
|
|
fdp->arg_indices_32[i] > fdp->n_args_16)
|
|
{
|
|
fprintf(stderr, "%d: Bad argument index %d\n", Line,
|
|
fdp->arg_indices_32[i]);
|
|
exit(1);
|
|
}
|
|
}
|
|
fdp->n_args_32 = i;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ParseEquate(int ordinal)
|
|
{
|
|
ORDDEF *odp;
|
|
char *token;
|
|
char *endptr;
|
|
int value;
|
|
|
|
if (ordinal >= MAX_ORDINALS)
|
|
{
|
|
fprintf(stderr, "%d: Ordinal number too large\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
odp = &OrdinalDefinitions[ordinal];
|
|
strcpy(odp->export_name, GetToken());
|
|
|
|
token = GetToken();
|
|
value = strtol(token, &endptr, 0);
|
|
if (endptr == NULL || *endptr != '\0')
|
|
{
|
|
fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
|
|
token);
|
|
exit(1);
|
|
}
|
|
|
|
odp->valid = 1;
|
|
odp->type = EQUATETYPE_ABS;
|
|
odp->additional_data = (void *) value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ParseReturn(int ordinal)
|
|
{
|
|
ORDDEF *odp;
|
|
ORDRETDEF *rdp;
|
|
char *token;
|
|
char *endptr;
|
|
int value;
|
|
|
|
if (ordinal >= MAX_ORDINALS)
|
|
{
|
|
fprintf(stderr, "%d: Ordinal number too large\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
rdp = malloc(sizeof(*rdp));
|
|
|
|
odp = &OrdinalDefinitions[ordinal];
|
|
strcpy(odp->export_name, GetToken());
|
|
odp->valid = 1;
|
|
odp->type = TYPE_RETURN;
|
|
odp->additional_data = rdp;
|
|
|
|
token = GetToken();
|
|
rdp->arg_size = strtol(token, &endptr, 0);
|
|
if (endptr == NULL || *endptr != '\0')
|
|
{
|
|
fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
|
|
token);
|
|
exit(1);
|
|
}
|
|
|
|
token = GetToken();
|
|
rdp->ret_value = strtol(token, &endptr, 0);
|
|
if (endptr == NULL || *endptr != '\0')
|
|
{
|
|
fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
|
|
token);
|
|
exit(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ParseOrdinal(int ordinal)
|
|
{
|
|
char *token;
|
|
|
|
token = GetToken();
|
|
if (token == NULL)
|
|
{
|
|
fprintf(stderr, "%d: Expected type after ordinal\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
if (stricmp(token, "byte") == 0)
|
|
return ParseVariable(ordinal, VARTYPE_BYTE);
|
|
else if (stricmp(token, "word") == 0)
|
|
return ParseVariable(ordinal, VARTYPE_WORD);
|
|
else if (stricmp(token, "long") == 0)
|
|
return ParseVariable(ordinal, VARTYPE_LONG);
|
|
else if (stricmp(token, "c") == 0)
|
|
return ParseExportFunction(ordinal, FUNCTYPE_C);
|
|
else if (stricmp(token, "p") == 0)
|
|
return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
|
|
else if (stricmp(token, "pascal") == 0)
|
|
return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
|
|
else if (stricmp(token, "register") == 0)
|
|
return ParseExportFunction(ordinal, FUNCTYPE_REG);
|
|
else if (stricmp(token, "equate") == 0)
|
|
return ParseEquate(ordinal);
|
|
else if (stricmp(token, "return") == 0)
|
|
return ParseReturn(ordinal);
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"%d: Expected type after ordinal, found '%s' instead\n",
|
|
Line, token);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
int
|
|
ParseTopLevel(void)
|
|
{
|
|
char *token;
|
|
|
|
while ((token = GetToken()) != NULL)
|
|
{
|
|
if (stricmp(token, "name") == 0)
|
|
{
|
|
strcpy(LowerDLLName, GetToken());
|
|
strlower(LowerDLLName);
|
|
|
|
strcpy(UpperDLLName, LowerDLLName);
|
|
strupper(UpperDLLName);
|
|
}
|
|
else if (stricmp(token, "id") == 0)
|
|
{
|
|
token = GetToken();
|
|
if (!IsNumberString(token))
|
|
{
|
|
fprintf(stderr, "%d: Expected number after id\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
DLLId = atoi(token);
|
|
}
|
|
else if (stricmp(token, "length") == 0)
|
|
{
|
|
token = GetToken();
|
|
if (!IsNumberString(token))
|
|
{
|
|
fprintf(stderr, "%d: Expected number after length\n", Line);
|
|
exit(1);
|
|
}
|
|
|
|
Limit = atoi(token);
|
|
}
|
|
else if (IsNumberString(token))
|
|
{
|
|
int ordinal;
|
|
int rv;
|
|
|
|
ordinal = atoi(token);
|
|
if ((rv = ParseOrdinal(ordinal)) < 0)
|
|
return rv;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"%d: Expected name, id, length or ordinal\n", Line);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
InitContext()
|
|
{
|
|
struct sigcontext_struct context;
|
|
int i;
|
|
int j;
|
|
|
|
n_context_strings = sizeof(context) / 4;
|
|
context_strings = (char **) malloc(n_context_strings * sizeof(char **));
|
|
pop_strings = (char **) malloc(n_context_strings * sizeof(char **));
|
|
for (i = 0; i < n_context_strings; i++)
|
|
{
|
|
context_strings[i] = PUSH_0;
|
|
pop_strings[i] = POP_0;
|
|
}
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esp) / 4;
|
|
context_strings[i] = PUSH_ESP;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebp) / 4;
|
|
context_strings[i] = PUSH_EBP;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EBP;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eip) / 4;
|
|
context_strings[i] = PUSH_EIP;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_efl) / 4;
|
|
context_strings[i] = PUSH_EFL;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EFL;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_es) / 4;
|
|
context_strings[i] = PUSH_ES;
|
|
pop_strings[n_context_strings - 1 - i] = POP_ES;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ds) / 4;
|
|
context_strings[i] = PUSH_DS;
|
|
pop_strings[n_context_strings - 1 - i] = POP_DS;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_cs) / 4;
|
|
context_strings[i] = PUSH_CS;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ss) / 4;
|
|
context_strings[i] = PUSH_SS;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edi) / 4;
|
|
context_strings[i] = PUSH_EDI;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EDI;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esi) / 4;
|
|
context_strings[i] = PUSH_ESI;
|
|
pop_strings[n_context_strings - 1 - i] = POP_ESI;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebx) / 4;
|
|
context_strings[i] = PUSH_EBX;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EBX;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edx) / 4;
|
|
context_strings[i] = PUSH_EDX;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EDX;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ecx) / 4;
|
|
context_strings[i] = PUSH_ECX;
|
|
pop_strings[n_context_strings - 1 - i] = POP_ECX;
|
|
|
|
i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eax) / 4;
|
|
context_strings[i] = PUSH_EAX;
|
|
pop_strings[n_context_strings - 1 - i] = POP_EAX;
|
|
}
|
|
|
|
void
|
|
OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
|
|
{
|
|
ORDVARDEF *vdp;
|
|
int i;
|
|
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
|
|
vdp = odp->additional_data;
|
|
for (i = 0; i < vdp->n_values; i++)
|
|
{
|
|
if ((i & 7) == 0)
|
|
fprintf(fp, "\t%s\t", storage);
|
|
|
|
fprintf(fp, "%d", vdp->values[i]);
|
|
|
|
if ((i & 7) == 7 || i == vdp->n_values - 1)
|
|
fprintf(fp, "\n");
|
|
else
|
|
fprintf(fp, ", ");
|
|
}
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
main(int argc, char **argv)
|
|
{
|
|
ORDDEF *odp;
|
|
ORDFUNCDEF *fdp;
|
|
ORDRETDEF *rdp;
|
|
FILE *fp;
|
|
char filename[80];
|
|
char buffer[80];
|
|
char *p;
|
|
int i, ci;
|
|
int add_count;
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf(stderr, "usage: build SPECNAME\n build -p\n");
|
|
exit(1);
|
|
}
|
|
|
|
InitContext();
|
|
|
|
if (strcmp("-p", argv[1]) == 0)
|
|
{
|
|
fp = fopen("pop.h", "w");
|
|
add_count = 0;
|
|
for (i = 0; i < n_context_strings; i++)
|
|
{
|
|
if (strncmp(pop_strings[i], "\tadd\t", 5) == 0)
|
|
{
|
|
add_count += atoi(pop_strings[i] + 6);
|
|
}
|
|
else
|
|
{
|
|
if (add_count > 0)
|
|
{
|
|
fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
|
|
add_count = 0;
|
|
}
|
|
|
|
fprintf(fp, pop_strings[i]);
|
|
}
|
|
}
|
|
|
|
if (add_count > 0)
|
|
fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
|
|
|
|
fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
|
|
|
|
fclose(fp);
|
|
exit(0);
|
|
}
|
|
|
|
SpecFp = fopen(argv[1], "r");
|
|
if (SpecFp == NULL)
|
|
{
|
|
fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
|
|
exit(1);
|
|
}
|
|
|
|
ParseTopLevel();
|
|
|
|
sprintf(filename, "dll_%s.S", LowerDLLName);
|
|
fp = fopen(filename, "w");
|
|
|
|
fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
|
|
fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
|
|
fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
|
|
fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
|
|
fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
|
|
fprintf(fp, "\tjmp\t_CallTo32\n\n");
|
|
|
|
odp = OrdinalDefinitions;
|
|
for (i = 0; i <= Limit; i++, odp++)
|
|
{
|
|
fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
|
|
|
|
if (!odp->valid)
|
|
{
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
|
|
fprintf(fp, "\tpushw\t$0\n");
|
|
fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
|
|
}
|
|
else
|
|
{
|
|
fdp = odp->additional_data;
|
|
rdp = odp->additional_data;
|
|
|
|
switch (odp->type)
|
|
{
|
|
case EQUATETYPE_ABS:
|
|
fprintf(fp, "_%s_Ordinal_%d = %d\n\n",
|
|
UpperDLLName, i, (int) odp->additional_data);
|
|
break;
|
|
|
|
case VARTYPE_BYTE:
|
|
OutputVariableCode(fp, ".byte", odp);
|
|
break;
|
|
|
|
case VARTYPE_WORD:
|
|
OutputVariableCode(fp, ".word", odp);
|
|
break;
|
|
|
|
case VARTYPE_LONG:
|
|
OutputVariableCode(fp, ".long", odp);
|
|
break;
|
|
|
|
case TYPE_RETURN:
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
|
|
fprintf(fp, "\tmovw\t$%d,%%dx\n",
|
|
(rdp->ret_value >> 16) & 0xffff);
|
|
fprintf(fp, "\t.byte\t0x66\n");
|
|
if (rdp->arg_size != 0)
|
|
fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
|
|
else
|
|
fprintf(fp, "\tlret\n");
|
|
break;
|
|
|
|
case FUNCTYPE_REG:
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
|
|
fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
|
|
|
|
for (ci = 0; ci < n_context_strings; ci++)
|
|
fprintf(fp, context_strings[ci]);
|
|
|
|
fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
|
|
fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
|
|
fprintf(fp, "\tpushl\t%d(%%ebp)\n",
|
|
sizeof(struct sigcontext_struct));
|
|
fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
|
|
fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
|
|
fprintf(fp, "\tpushw\t$%d\n",
|
|
sizeof(struct sigcontext_struct) + 4);
|
|
fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
|
|
break;
|
|
|
|
case FUNCTYPE_PASCAL:
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
|
|
fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
|
|
fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
|
|
break;
|
|
|
|
case FUNCTYPE_C:
|
|
default:
|
|
fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
|
|
fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
|
|
fprintf(fp, "\tpushw\t$0\n");
|
|
fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
#ifndef SHORTNAMES
|
|
sprintf(filename, "dll_%s_tab.c", LowerDLLName);
|
|
#else
|
|
sprintf(filename, "dtb_%s.c", LowerDLLName);
|
|
#endif
|
|
fp = fopen(filename, "w");
|
|
|
|
fprintf(fp, "#include <stdio.h>\n");
|
|
fprintf(fp, "#include <stdlib.h>\n");
|
|
fprintf(fp, "#include \042dlls.h\042\n\n");
|
|
|
|
for (i = 0; i <= Limit; i++)
|
|
{
|
|
fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
|
|
}
|
|
|
|
odp = OrdinalDefinitions;
|
|
for (i = 0; i <= Limit; i++, odp++)
|
|
{
|
|
if (odp->valid &&
|
|
(odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
|
|
odp->type == FUNCTYPE_REG))
|
|
{
|
|
fdp = odp->additional_data;
|
|
fprintf(fp, "extern int %s();\n", fdp->internal_name);
|
|
}
|
|
}
|
|
|
|
fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n",
|
|
UpperDLLName, Limit + 1);
|
|
fprintf(fp, "{\n");
|
|
odp = OrdinalDefinitions;
|
|
for (i = 0; i <= Limit; i++, odp++)
|
|
{
|
|
fdp = odp->additional_data;
|
|
|
|
if (!odp->valid)
|
|
odp->type = -1;
|
|
|
|
switch (odp->type)
|
|
{
|
|
case FUNCTYPE_PASCAL:
|
|
case FUNCTYPE_REG:
|
|
fprintf(fp, " { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
|
|
fprintf(fp, "\042%s\042, ", odp->export_name);
|
|
fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
|
|
#ifdef WINESTAT
|
|
fprintf(fp, "0, ");
|
|
#endif
|
|
fprintf(fp, "%d, ", fdp->n_args_32);
|
|
if (fdp->n_args_32 > 0)
|
|
{
|
|
int argnum;
|
|
|
|
fprintf(fp, "\n {\n");
|
|
for (argnum = 0; argnum < fdp->n_args_32; argnum++)
|
|
{
|
|
fprintf(fp, " { %d, %d },\n",
|
|
fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
|
|
fdp->arg_types_16[argnum]);
|
|
}
|
|
fprintf(fp, " }\n ");
|
|
}
|
|
fprintf(fp, "}, \n");
|
|
break;
|
|
|
|
case FUNCTYPE_C:
|
|
fprintf(fp, " { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
|
|
fprintf(fp, "\042%s\042, ", odp->export_name);
|
|
fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
|
|
#ifdef WINESTAT
|
|
fprintf(fp, "0, ");
|
|
#endif
|
|
fprintf(fp, "%d, ", fdp->n_args_32);
|
|
if (fdp->n_args_32 > 0)
|
|
{
|
|
int argnum;
|
|
|
|
fprintf(fp, "\n {\n");
|
|
for (argnum = 0; argnum < fdp->n_args_32; argnum++)
|
|
{
|
|
fprintf(fp, " { %d, %d },\n",
|
|
fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
|
|
fdp->arg_types_16[argnum]);
|
|
}
|
|
fprintf(fp, " }\n ");
|
|
}
|
|
fprintf(fp, "}, \n");
|
|
break;
|
|
|
|
default:
|
|
fprintf(fp, " { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n",
|
|
UTEXTSEL, UpperDLLName, i);
|
|
break;
|
|
}
|
|
}
|
|
fprintf(fp, "};\n");
|
|
|
|
fclose(fp);
|
|
}
|
|
|