| /* 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); | |
| } | |
| /**********************************************************************/ |