/* Copyright (C) 1995-2015 Free Software Foundation, Inc. | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | |
MA 02110-1301, USA. */ | |
#include "deflex.h" | |
#include "genlib.h" | |
#include <string.h> | |
#include <libgen.h> | |
typedef struct ifunct | |
{ | |
char * name; /* Name of function being imported. */ | |
char * its_name; /* Optional import table symbol name. */ | |
int ord; /* Two-byte ordinal value associated with function. */ | |
struct ifunct *next; | |
} ifunctype; | |
typedef struct iheadt | |
{ | |
char * dllname; /* Name of dll file imported from. */ | |
long nfuncs; /* Number of functions in list. */ | |
struct ifunct *funchead; /* First function in list. */ | |
struct ifunct *functail; /* Last function in list. */ | |
struct iheadt *next; /* Next dll file in list. */ | |
} iheadtype; | |
/* Structure containing all import information as defined in .def file | |
(qv "ihead structure"). */ | |
static iheadtype *import_list = NULL; | |
typedef struct dlist | |
{ | |
char *text; | |
struct dlist *next; | |
}dlist_type; | |
typedef struct export | |
{ | |
const char *name; | |
const char *internal_name; | |
const char *import_name; | |
const char *its_name; | |
int ordinal; | |
int constant; | |
int noname; /* Don't put name in image file. */ | |
int private; /* Don't put reference in import lib. */ | |
int data; | |
int hint; | |
int forward; /* Number of forward label, 0 means no forward. */ | |
struct export *next; | |
}export_type; | |
char *def_file; | |
char *dll_name; | |
/**********************************************************************/ | |
/* Communications with the parser. */ | |
int d_nfuncs; /* Number of functions exported. */ | |
//static int d_named_nfuncs; /* Number of named functions exported. */ | |
//static int d_low_ord; /* Lowest ordinal index. */ | |
//static int d_high_ord; /* Highest ordinal index. */ | |
export_type *d_exports; /* List of exported functions. */ | |
//static export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */ | |
static dlist_type *d_list; /* Descriptions. */ | |
static dlist_type *a_list; /* Stuff to go in directives. */ | |
static int d_nforwards = 0; /* Number of forwarded exports. */ | |
static int d_is_dll; | |
static int d_is_exe; | |
int | |
yyerror (const char * err __attribute__ ((__unused__))) | |
{ | |
PRDEBUG("Syntax error in def file %s:%d", def_file, linenumber); | |
return 0; | |
} | |
void | |
def_exports (const char *name, const char *internal_name, int ordinal, | |
int noname, int constant, int data, int private, | |
const char *its_name) | |
{ | |
struct export *p = (struct export *) malloc (sizeof (*p)); | |
p->name = name; | |
p->internal_name = internal_name ? internal_name : name; | |
p->its_name = its_name; | |
p->import_name = name; | |
p->ordinal = ordinal; | |
p->constant = constant; | |
p->noname = noname; | |
p->private = private; | |
p->data = data; | |
p->next = d_exports; | |
d_exports = p; | |
d_nfuncs++; | |
if ((internal_name != NULL) | |
&& (strchr (internal_name, '.') != NULL)) | |
p->forward = ++d_nforwards; | |
else | |
p->forward = 0; /* no forward */ | |
} | |
static void | |
set_dll_name_from_def (const char *name, char is_dll) | |
{ | |
const char *image_basename = basename ((char*)name); | |
if (image_basename != name) | |
PRDEBUG("%s: Path components stripped from image name, '%s'\n", | |
def_file, name); | |
/* Append the default suffix, if none specified. */ | |
if (strchr (image_basename, '.') == 0) | |
{ | |
const char * suffix = is_dll ? ".dll" : ".exe"; | |
dll_name = malloc (strlen (image_basename) + strlen (suffix) + 1); | |
sprintf (dll_name, "%s%s", image_basename, suffix); | |
} | |
else | |
dll_name = strdup (image_basename); | |
} | |
void | |
def_name (const char *name, int base) | |
{ | |
PRDEBUG("NAME: %s base: %x", name, base); | |
/* If --dllname not provided, use the one in the DEF file. | |
FIXME: Is this appropriate for executables? */ | |
if (!dll_name) | |
set_dll_name_from_def (name, 0); | |
d_is_exe = 1; | |
} | |
void | |
def_library (const char *name, int base) | |
{ | |
PRDEBUG("LIBRARY: %s base: %x\n", name, base); | |
/* If --dllname not provided, use the one in the DEF file. */ | |
if (!dll_name) | |
set_dll_name_from_def (name, 1); | |
d_is_dll = 1; | |
} | |
void | |
def_description (const char *desc) | |
{ | |
dlist_type *d = (dlist_type *) malloc (sizeof (dlist_type)); | |
d->text = strdup (desc); | |
d->next = d_list; | |
d_list = d; | |
} | |
static void | |
new_directive (char *dir) | |
{ | |
dlist_type *d = (dlist_type *) malloc (sizeof (dlist_type)); | |
d->text = strdup (dir); | |
d->next = a_list; | |
a_list = d; | |
} | |
void | |
def_heapsize (int reserve, int commit) | |
{ | |
char b[200]; | |
if (commit > 0) | |
sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); | |
else | |
sprintf (b, "-heap 0x%x ", reserve); | |
new_directive (strdup (b)); | |
} | |
void | |
def_stacksize (int reserve, int commit) | |
{ | |
char b[200]; | |
if (commit > 0) | |
sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); | |
else | |
sprintf (b, "-stack 0x%x ", reserve); | |
new_directive (strdup (b)); | |
} | |
/* append_import simply adds the given import definition to the global | |
import_list. It is used by def_import. */ | |
static void | |
append_import (const char *symbol_name, const char *dllname, int func_ordinal, | |
const char *its_name) | |
{ | |
iheadtype **pq; | |
iheadtype *q; | |
for (pq = &import_list; *pq != NULL; pq = &(*pq)->next) | |
{ | |
if (strcmp ((*pq)->dllname, dllname) == 0) | |
{ | |
q = *pq; | |
q->functail->next = malloc (sizeof (ifunctype)); | |
q->functail = q->functail->next; | |
q->functail->ord = func_ordinal; | |
q->functail->name = strdup (symbol_name); | |
q->functail->its_name = (its_name ? strdup (its_name) : NULL); | |
q->functail->next = NULL; | |
q->nfuncs++; | |
return; | |
} | |
} | |
q = malloc (sizeof (iheadtype)); | |
q->dllname = strdup (dllname); | |
q->nfuncs = 1; | |
q->funchead = malloc (sizeof (ifunctype)); | |
q->functail = q->funchead; | |
q->next = NULL; | |
q->functail->name = strdup (symbol_name); | |
q->functail->its_name = (its_name ? strdup (its_name) : NULL); | |
q->functail->ord = func_ordinal; | |
q->functail->next = NULL; | |
*pq = q; | |
} | |
/* def_import is called from within defparse.y when an IMPORT | |
declaration is encountered. Depending on the form of the | |
declaration, the module name may or may not need ".dll" to be | |
appended to it, the name of the function may be stored in internal | |
or entry, and there may or may not be an ordinal value associated | |
with it. */ | |
/* A note regarding the parse modes: | |
In defparse.y we have to accept import declarations which follow | |
any one of the following forms: | |
<func_name_in_app> = <dll_name>.<func_name_in_dll> | |
<func_name_in_app> = <dll_name>.<number> | |
<dll_name>.<func_name_in_dll> | |
<dll_name>.<number> | |
Furthermore, the dll's name may or may not end with ".dll", which | |
complicates the parsing a little. Normally the dll's name is | |
passed to def_import() in the "module" parameter, but when it ends | |
with ".dll" it gets passed in "module" sans ".dll" and that needs | |
to be reappended. | |
def_import gets five parameters: | |
APP_NAME - the name of the function in the application, if | |
present, or NULL if not present. | |
MODULE - the name of the dll, possibly sans extension (ie, '.dll'). | |
DLLEXT - the extension of the dll, if present, NULL if not present. | |
ENTRY - the name of the function in the dll, if present, or NULL. | |
ORD_VAL - the numerical tag of the function in the dll, if present, | |
or NULL. Exactly one of <entry> or <ord_val> must be | |
present (i.e., not NULL). */ | |
void | |
def_import (const char *app_name, const char *module, const char *dllext, | |
const char *entry, int ord_val, const char *its_name) | |
{ | |
const char *application_name; | |
char *buf; | |
if (entry != NULL) | |
application_name = entry; | |
else | |
{ | |
if (app_name != NULL) | |
application_name = app_name; | |
else | |
application_name = ""; | |
} | |
if (dllext != NULL) | |
{ | |
buf = (char *) alloca (strlen (module) + strlen (dllext) + 2); | |
sprintf (buf, "%s.%s", module, dllext); | |
module = buf; | |
} | |
append_import (application_name, module, ord_val, its_name); | |
} | |
void | |
def_version (int major, int minor) | |
{ | |
PRDEBUG(("VERSION %d.%d\n"), major, minor); | |
} | |
void | |
def_section (const char *name, int attr) | |
{ | |
char buf[200]; | |
char atts[5]; | |
char *d = atts; | |
if (attr & 1) | |
*d++ = 'R'; | |
if (attr & 2) | |
*d++ = 'W'; | |
if (attr & 4) | |
*d++ = 'X'; | |
if (attr & 8) | |
*d++ = 'S'; | |
*d++ = 0; | |
sprintf (buf, "-attr %s %s", name, atts); | |
new_directive (strdup (buf)); | |
} | |
void | |
def_code (int attr) | |
{ | |
def_section ("CODE", attr); | |
} | |
void | |
def_data (int attr) | |
{ | |
def_section ("DATA", attr); | |
} | |
/**********************************************************************/ |