Added support for creating an implib from a list of comma seperated files master
authorRobert Pengelly <robertapengelly@hotmail.com>
Fri, 22 May 2026 04:49:51 +0000 (05:49 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Fri, 22 May 2026 04:49:51 +0000 (05:49 +0100)
Makefile.unix
Makefile.w32
Makefile.wat
lib.c
lib.h
ll.c [new file with mode: 0644]
ll.h [new file with mode: 0644]
pe.c

index 7778788ae3b08f8c1aa73e174133640e40765b35..5c707740703d1fa635957c440e72fbdd7e7427c1 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
 
-CSRC                :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC                :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c ll.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
 
 ifeq ($(OS), Windows_NT)
 all: slink.exe
index 5cccc57f41f23f90a26569b658a1f99db5a466b8..9c3381c244a8c0e1c1ddce94b747fd5ea21e7c69 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra
 
-CSRC                :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC                :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c ll.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
 
 all: slink.exe
 
index 0a87a546116bd7e0e80ab11ffd662edfd33a5f4a..375bea585e21cf8ac49b81e93b17e0252f95ab8b 100644 (file)
@@ -4,7 +4,7 @@
 SRCDIR              ?=  $(CURDIR)
 VPATH               :=  $(SRCDIR)
 
-SRC                 :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+SRC                 :=  aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c ll.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
 
 all: slink.exe
 
diff --git a/lib.c b/lib.c
index 4d26833d7acf731d2b9b8be8f350d8126009685f..aabed802be44e207211164c4c2dc2be30c426c27 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -33,7 +33,7 @@ static struct options_with_use emulation_table[] = {
     {   0,                      0,                      0                   },
     {   0,                      0,                      0                   },
     {   &pe_print_help,         &pe_check_option,       &pe_use_option      },
-    {   &macho_print_help,      &macho_check_option,    &macho_use_option   },
+    {   &macho_print_help,      &macho_check_option,    &macho_use_option   }
 
 };
 
@@ -544,6 +544,16 @@ void integer_to_array (uint64_t value, unsigned char *dest, int size, int big_en
 
 }
 
+char *skip_whitespace (char *p) {
+
+    while (isspace ((int) *p)) {
+        p++;
+    }
+    
+    return p;
+
+}
+
 char *xstrdup (const char *__p) {
 
     char *p = xmalloc (strlen (__p) + 1);
@@ -637,8 +647,8 @@ void dynarray_add (void *ptab, long *nb_ptr, void *data) {
 
 void parse_args (int argc, char **argv, int optind) {
 
-    struct options_with_use *options_with_use;
-    struct ld_option *popt;
+    struct options_with_use *options_with_use = { 0 };
+    struct ld_option *popt = { 0 };
     
     const char *optarg, *r;
     
diff --git a/lib.h b/lib.h
index f741eb1649723ef90614d677665e01774d81d0d1..c32f6d05601f6b79d706ad0b64b8a8d2f5125ff0 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -25,8 +25,9 @@ uint64_t array_to_integer (unsigned char *arr, int size, int big_endian);
 void integer_to_array (uint64_t value, unsigned char *dest, int size, int big_endian);
 
 int xstrcasecmp (const char *__s1, const char *__s2);
-
 int strstart (const char *val, const char **str);
+
+char *skip_whitespace (char *p);
 void dynarray_add (void *ptab, long *nb_ptr, void *data);
 
 char *xstrdup (const char *__p);
diff --git a/ll.c b/ll.c
new file mode 100644 (file)
index 0000000..c59fab3
--- /dev/null
+++ b/ll.c
@@ -0,0 +1,303 @@
+/******************************************************************************
+ * @file            ll.c
+ *****************************************************************************/
+#include    <stddef.h>
+#include    <stdio.h>
+#include    <stdlib.h>
+#include    <string.h>
+
+#include    "ll.h"
+#include    "report.h"
+
+struct load_line_data {
+
+    char *line, *real_line;
+    
+    unsigned long capacity, read_size;
+    unsigned long end_of_prev_real_line;
+    
+    unsigned long *new_line_number_p;
+
+};
+
+#define     CAPACITY_INCREMENT          256
+extern void get_filename_and_line_number (const char **__filename_p, unsigned long *__line_number_p);
+
+extern void *xmalloc (unsigned long __size);
+extern void *xrealloc (void *__ptr, unsigned long __size);
+
+int load_line (char **line_p, char **line_end_p, char **real_line_p, unsigned long *real_line_len_p, unsigned long *newlines_p, FILE *ifp, void **load_line_internal_data_p) {
+
+    struct load_line_data *ll_data = *load_line_internal_data_p;
+    unsigned long pos_in_line = 0, pos_in_real_line = 0, newlines = 0;
+    
+    int in_escape = 0, in_double_quote = 0, in_single_quote = 0;
+    int in_line_comment = 0, skipping_spaces = 0;
+    
+    if (ll_data->end_of_prev_real_line) {
+    
+        memmove (ll_data->real_line, ll_data->real_line + ll_data->end_of_prev_real_line, ll_data->read_size - ll_data->end_of_prev_real_line);
+        ll_data->read_size -= ll_data->end_of_prev_real_line;
+    
+    }
+    
+    while (1) {
+    
+        if (pos_in_line >= ll_data->capacity || pos_in_real_line >= ll_data->capacity) {
+        
+            ll_data->capacity += CAPACITY_INCREMENT;
+            
+            ll_data->line = xrealloc (ll_data->line, ll_data->capacity + 2);
+            ll_data->real_line = xrealloc (ll_data->real_line, ll_data->capacity + 1);
+        
+        }
+        
+        if (pos_in_real_line >= ll_data->read_size) {
+        
+            ll_data->read_size = fread (ll_data->real_line + pos_in_real_line, 1, ll_data->capacity - pos_in_real_line, ifp) + pos_in_real_line;
+            
+            if (ferror (ifp)) {
+                return 4;
+            }
+            
+            ll_data->real_line[ll_data->read_size] = '\0';
+        
+        }
+        
+    copying:
+        
+        if (in_line_comment) {
+        
+            while (pos_in_real_line < ll_data->read_size) {
+            
+                if (ll_data->real_line[pos_in_real_line] == '\n') {
+                
+                    in_line_comment = 0;
+                    break;
+                
+                }
+                
+                pos_in_real_line++;
+            
+            }
+        
+        }
+        
+        if (skipping_spaces) {
+        
+            while (pos_in_real_line < ll_data->read_size) {
+            
+                if (ll_data->real_line[pos_in_real_line] != ' ' && ll_data->real_line[pos_in_real_line] != '\t') {
+                
+                    skipping_spaces = 0;
+                    break;
+                
+                }
+                
+                pos_in_real_line++;
+            
+            }
+        
+        }
+        
+        while (pos_in_real_line < ll_data->read_size && pos_in_line < ll_data->capacity) {
+        
+            ll_data->line[pos_in_line] = ll_data->real_line[pos_in_real_line++];
+            
+            if (in_double_quote || in_single_quote) {
+            
+                if (in_escape) {
+                    in_escape = 0;
+                } else if (in_double_quote && ll_data->line[pos_in_line] == '"') {
+                    in_double_quote = 0;
+                } else if (in_single_quote && ll_data->line[pos_in_line] == '\'') {
+                    in_single_quote = 0;
+                } else if (ll_data->line[pos_in_line] == '\\') {
+                    in_escape = 1;
+                }
+                
+                if (ll_data->line[pos_in_line] == '\n') {
+                
+                    int pos = pos_in_line;
+                    
+                    if (pos > 0 && ll_data->line[pos - 1] == '\r') {
+                        ll_data->line[--pos] = '\n';
+                    }
+                    
+                    if (pos > 0) {
+                    
+                        if (ll_data->line[pos - 1] != '\\') {
+                    
+                            ll_data->line[pos + 1] = '\0';
+                            ll_data->end_of_prev_real_line = pos_in_real_line;
+                            
+                            *line_p = ll_data->line;
+                            *line_end_p = ll_data->line + pos;
+                            
+                            *real_line_p = ll_data->real_line;
+                            *real_line_len_p = pos_in_real_line;
+                            
+                            *newlines_p = newlines;
+                            return 0;
+                        
+                        } else {
+                        
+                            pos_in_line = pos - 1;
+                            
+                            newlines++;
+                            goto copying;
+                        
+                        }
+                    
+                    }
+                
+                }
+            
+            } else {
+            
+                if (ll_data->line[pos_in_line] == ' ' || ll_data->line[pos_in_line] == '\t') {
+                
+                    /*ll_data->line[pos_in_line++] = ' ';*/
+                    
+                    /*skipping_spaces = 1;
+                    goto copying;*/
+                    
+                    if (ll_data->line[pos_in_line] == '\t') {
+                    
+                        int cnt = 4 - (pos_in_line % 4);
+                        int i = 0;
+                        
+                        ll_data->capacity += CAPACITY_INCREMENT;
+                        
+                        ll_data->line = xrealloc (ll_data->line, ll_data->capacity + 2);
+                        ll_data->real_line = xrealloc (ll_data->real_line, ll_data->capacity + 1);
+                        
+                        for (; i < cnt; i++) {
+                            ll_data->line[pos_in_line++] = ' ';
+                        }
+                        
+                        continue;
+                    
+                    }
+                
+                } else if (ll_data->line[pos_in_line] == '\n') {
+                
+                    if (pos_in_line > 0 && ll_data->line[pos_in_line - 1] == '\r') {
+                        ll_data->line[--pos_in_line] = '\n';
+                    }
+                    
+                    ll_data->line[pos_in_line + 1] = '\0';
+                    ll_data->end_of_prev_real_line = pos_in_real_line;
+                    
+                    *line_p = ll_data->line;
+                    *line_end_p = ll_data->line + pos_in_line;
+                    
+                    *real_line_p = ll_data->real_line;
+                    *real_line_len_p = pos_in_real_line;
+                    
+                    *newlines_p = newlines;
+                    return 0;
+                
+                } else if (ll_data->line[pos_in_line] == '\\') {
+                
+                    /*ll_data->line[pos_in_line] = ' ';*/
+                    pos_in_line--;
+                    
+                    while (pos_in_real_line < ll_data->read_size) {
+                    
+                        if (ll_data->real_line[pos_in_real_line] == '\r' || ll_data->real_line[pos_in_real_line] == '\n') {
+                        
+                            if (ll_data->real_line[pos_in_real_line] == '\r') {
+                                pos_in_real_line++;
+                            }
+                            
+                            if (ll_data->real_line[pos_in_real_line] == '\n') {
+                                pos_in_real_line++;
+                            }
+                            
+                            break;
+                        
+                        }
+                        
+                        pos_in_real_line++;
+                    
+                    }
+                    
+                    newlines++;
+                    continue;
+                
+                } else if (ll_data->line[pos_in_line] == '"') {
+                    in_double_quote = 1;
+                } else if (ll_data->line[pos_in_line] == '\'') {
+                    in_single_quote = 1;
+                } else if (ll_data->line[pos_in_line] == '#') {
+                
+                    in_line_comment = 1;
+                    goto copying;
+                
+                }
+            
+            }
+            
+            pos_in_line++;
+        
+        }
+        
+        if (feof (ifp)) {
+        
+            if (ll_data->read_size == 0) {
+                return 1;
+            }
+            
+            ll_data->line[pos_in_line] = '\n';
+            ll_data->line[pos_in_line + 1] = '\0';
+            
+            ll_data->end_of_prev_real_line = 0;
+            ll_data->read_size = 0;
+            
+            *line_p = ll_data->line;
+            *line_end_p = ll_data->line + pos_in_line;
+            
+            *real_line_p = ll_data->real_line;
+            *real_line_len_p = pos_in_real_line;
+            
+            *newlines_p = newlines;
+            return 0;
+        
+        }
+    
+    }
+
+}
+
+void load_line_destroy_internal_data (void *load_line_internal_data) {
+
+    struct load_line_data *ll_data;
+    
+    if (load_line_internal_data) {
+    
+        ll_data = load_line_internal_data;
+        
+        free (ll_data->line);
+        free (ll_data->real_line);
+        free (ll_data);
+    
+    }
+
+}
+
+void *load_line_create_internal_data (unsigned long *new_line_number_p) {
+
+    struct load_line_data *ll_data = xmalloc (sizeof (*ll_data));;
+    
+    ll_data->capacity = 0;
+    ll_data->line = NULL;
+    ll_data->real_line = NULL;
+    
+    ll_data->read_size = 0;
+    ll_data->end_of_prev_real_line = 0;
+    
+    ll_data->new_line_number_p = new_line_number_p;
+    return ll_data;
+
+}
diff --git a/ll.h b/ll.h
new file mode 100644 (file)
index 0000000..b6754ef
--- /dev/null
+++ b/ll.h
@@ -0,0 +1,13 @@
+/******************************************************************************
+ * @file            ll.h
+ *****************************************************************************/
+#ifndef     _LL_H
+#define     _LL_H
+
+#include    <stdio.h>
+int load_line (char **line_p, char **line_end_p, char **real_line_p, unsigned long *real_line_len_p, unsigned long *newlines_p, FILE *ifp, void **load_line_internal_data_p);
+
+void load_line_destroy_internal_data (void *load_line_internal_data);
+void *load_line_create_internal_data (unsigned long *new_line_number_p);
+
+#endif      /* _LL_H */
diff --git a/pe.c b/pe.c
index ecf5748d79b1148e9c1ad459aeba2f5bcb532dca..7e2f0a48784014c2500f04aed3adf9c410d7c45f 100644 (file)
--- a/pe.c
+++ b/pe.c
 #include    "ar.h"
 #include    "ld.h"
 #include    "lib.h"
+#include    "ll.h"
 #include    "pe.h"
 #include    "report.h"
 #include    "section.h"
 #include    "write7x.h"
 
 static char *output_implib_filename = 0;
-static int kill_at = 0;
+static int kill_at = 0, leading_underscore = 1;
 
 static unsigned short subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
 
 static unsigned long section_alignment = DEFAULT_SECTION_ALIGNMENT;
 static unsigned long file_alignment = DEFAULT_FILE_ALIGNMENT;
 
+static const char **def_list = 0;
+long nb_def_list = 0;
+
 struct exclude_symbol {
 
     char *name;
@@ -36,19 +40,21 @@ struct exclude_symbol {
 static struct exclude_symbol *exclude_symbols = 0;
 
 #define     LD_OPTION_IGNORED                               0
-#define     LD_OPTION_FILE_ALIGNMENT                        1
-#define     LD_OPTION_KILL_AT                               2
-#define     LD_OPTION_OUT_IMPLIB                            3
-#define     LD_OPTION_SECTION_ALIGNMENT                     4
-#define     LD_OPTION_SHARED                                5
-#define     LD_OPTION_STACK                                 6
-#define     LD_OPTION_SUBSYSTEM                             7
+#define     LD_OPTION_DEF_LIST                              1
+#define     LD_OPTION_FILE_ALIGNMENT                        2
+#define     LD_OPTION_KILL_AT                               3
+#define     LD_OPTION_OUT_IMPLIB                            4
+#define     LD_OPTION_SECTION_ALIGNMENT                     5
+#define     LD_OPTION_SHARED                                6
+#define     LD_OPTION_STACK                                 7
+#define     LD_OPTION_SUBSYSTEM                             8
 
 static struct ld_option opts[] = {
 
     {   "--file-alignment",         LD_OPTION_TYPE_LONG,        LD_OPTION_FILE_ALIGNMENT,       LD_OPTION_HAS_ARG   },
     {   "--section-alignment",      LD_OPTION_TYPE_LONG,        LD_OPTION_SECTION_ALIGNMENT,    LD_OPTION_HAS_ARG   },
     
+    {   "--def-list",               LD_OPTION_TYPE_LONG,        LD_OPTION_DEF_LIST,             LD_OPTION_HAS_ARG   },
     {   "--subsystem",              LD_OPTION_TYPE_LONG,        LD_OPTION_SUBSYSTEM,            LD_OPTION_HAS_ARG   },
     
     {   "--shared",                 LD_OPTION_TYPE_LONG,        LD_OPTION_SHARED,               LD_OPTION_NO_ARG    },
@@ -134,6 +140,39 @@ void pe_use_option (const char *cmd_arg, int idx, const char *optarg) {
         
         }
         
+        case LD_OPTION_DEF_LIST: {
+        
+            const char *fn = optarg, *arg, *p;
+            
+            for (;;) {
+            
+                fn = skip_whitespace ((char *) fn);
+                
+                if ((p = strchr (fn, ','))) {
+                
+                    arg = p;
+                    
+                    while (isspace ((int) *arg)) {
+                        arg--;
+                    }
+                    
+                    dynarray_add (&def_list, &nb_def_list, xstrndup (fn, arg - fn));
+                    fn = p + 1;
+                    
+                    continue;
+                
+                }
+                
+                dynarray_add (&def_list, &nb_def_list, xstrdup (fn));
+                break;
+            
+            }
+            
+            leading_underscore = 0;
+            break;
+        
+        }
+        
         case LD_OPTION_FILE_ALIGNMENT: {
         
             long conversion;
@@ -271,6 +310,104 @@ struct name_list {
 static struct name_list *export_name_list = 0;
 static struct name_list **last_export_name_list_p = &export_name_list;
 
+static void export_symbol_callback (struct symbol *symbol) {
+
+    struct name_list *name_list;
+    
+    if (symbol_is_undefined (symbol)) {
+        return;
+    }
+    
+    name_list = xmalloc (sizeof (*name_list));
+    
+    if (leading_underscore && symbol->name[0] == '_') {
+        name_list->name = xstrdup (symbol->name + 1);
+    } else {
+        name_list->name = xstrdup (symbol->name);
+    }
+    
+    name_list->info = (symbol->part->section->flags & SECTION_FLAG_CODE) ? 0 : 1;
+    name_list->next = NULL;
+    
+    *last_export_name_list_p = name_list;
+    last_export_name_list_p = &name_list->next;
+
+}
+
+static char is_end_of_line[256] = {
+    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 /* '\0' and '\n' */
+};
+
+static void parse_def (const char *ifile) {
+
+    char *line, *line_end, *real_line, *caret;
+    unsigned long real_line_len;
+    
+    unsigned long new_line_number = 1;
+    unsigned long newlines;
+    
+    int has_exports = 0;
+    void *load_line_internal_data = NULL;
+    
+    struct symbol *symbol;
+    FILE *fp;
+    
+    if (!(fp = fopen (ifile, "r"))) {
+    
+        report_at (program_name, 0, REPORT_FATAL_ERROR, "Failed to open '%s' for reading", ifile);
+        return;
+    
+    }
+    
+    load_line_internal_data = load_line_create_internal_data (&new_line_number);
+    
+    while (!load_line (&line, &line_end, &real_line, &real_line_len, &newlines, fp, &load_line_internal_data)) {
+    
+        caret = (line = skip_whitespace (line));
+        
+        if (line < line_end) {
+        
+            if (!isalnum ((int) *line) && *line != '_') {
+            
+                report_at (ifile, 0, REPORT_ERROR, "expected ident");
+                continue;
+            
+            }
+            
+            while (!is_end_of_line[(int) *line]) {
+                line++;
+            }
+            
+            *line = '\0';
+            
+            if (!has_exports) {
+            
+                if (strcmp (caret, "EXPORTS")) {
+                
+                    report_at (ifile, 0, REPORT_ERROR, "invalid command");
+                    continue;
+                
+                }
+                
+                has_exports = 1;
+                continue;
+            
+            }
+            
+            *line = '\0';
+            
+            if ((symbol = symbol_find (caret))) {
+                export_symbol_callback (symbol);
+            }
+        
+        }
+    
+    }
+    
+    load_line_destroy_internal_data (load_line_internal_data);
+
+}
+
 void pe_interpret_dot_drectve_section (/*const char *filename, unsigned char *data, unsigned long data_size, */unsigned char *pos, unsigned long size) {
 
     char *temp_buf = xmalloc (size + 1), *p;
@@ -816,7 +953,12 @@ struct symbol_info *create_symbol_list (struct export_name *export_name, unsigne
         symbol_info = xmalloc (sizeof (*symbol_info));
         
         symbol_info->name = xmalloc (7 + strlen (export_name[i].name) + 1);
-        sprintf (symbol_info->name, "__imp__%s", export_name[i].name);
+        
+        if (leading_underscore) {
+            sprintf (symbol_info->name, "__imp__%s", export_name[i].name);
+        } else {
+            sprintf (symbol_info->name, "__imp_%s", export_name[i].name);
+        }
         
         symbol_info->name_length = strlen (symbol_info->name);
         symbol_info->offset_index = j;
@@ -965,7 +1107,7 @@ struct data_entry {
 
 static void write_implib (struct export_name *export_names, unsigned long num_names, unsigned long ordinal_base) {
 
-    struct symbol_info *info_list, *info, *next_info;
+    struct symbol_info *info_list, *info;
     unsigned long *offsets, offset_count, symbol_count, length, i;
     
     unsigned long module_name_length;
@@ -1407,12 +1549,23 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
         
         offsets[4 + i] = offset2;
         
-        offset2 += write_file_header (outfile, header_name, bHeaderName, sizeof (import_hdr) + 1 + strlen (export_names[i].name) + 1 + module_name_length + 1, 0);
+        if (leading_underscore) {
+            offset2 += write_file_header (outfile, header_name, bHeaderName, sizeof (import_hdr) + 1 + strlen (export_names[i].name) + 1 + module_name_length + 1, 0);
+        } else {
+            offset2 += write_file_header (outfile, header_name, bHeaderName, sizeof (import_hdr) + strlen (export_names[i].name) + 1 + module_name_length + 1, 0);
+        }
+        
         memset (&import_hdr, 0, sizeof (import_hdr));
         
         integer_to_array (0xFFFF, import_hdr.Magic2, 2, 0);
         integer_to_array (IMAGE_FILE_MACHINE_I386, import_hdr.Machine, 2, 0);
-        integer_to_array (1 + strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0);
+        
+        if (leading_underscore) {
+            integer_to_array (1 + strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0);
+        } else {
+            integer_to_array (strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0);
+        }
+        
         integer_to_array (ordinal_base + i, import_hdr.OrdinalHint, 2, 0);
         
         switch (export_names[i].export_type) {
@@ -1439,8 +1592,17 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
         integer_to_array (type, import_hdr.Type, 2, 0);
         offset2 += write_data (outfile, &import_hdr, sizeof (import_hdr));
         
-        name = xmalloc (1 + strlen (export_names[i].name) + 1);
-        sprintf (name, "_%s", export_names[i].name);
+        if (leading_underscore) {
+        
+            name = xmalloc (1 + strlen (export_names[i].name) + 1);
+            sprintf (name, "_%s", export_names[i].name);
+        
+        } else {
+        
+            name = xmalloc (strlen (export_names[i].name) + 1);
+            sprintf (name, "%s", export_names[i].name);
+        
+        }
         
         offset2 += write_data (outfile, name, strlen (name) + 1);
         offset2 += write_data (outfile, module_name, module_name_length + 1);
@@ -1472,18 +1634,6 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
     }
     
     fclose (outfile);
-    
-    for (info = info_list; info; info = next_info) {
-    
-        next_info = info->next;
-        
-        free (info->name);
-        free (info);
-    
-    }
-    
-    free (header_name);
-    free (module_name);
 
 }
 
@@ -1607,8 +1757,17 @@ static void generate_edata (void) {
     
     for (i = 0; i < num_names; i++) {
     
-        symbol->name = xmalloc (1 + strlen (export_names[i].name) + 1);
-        sprintf (symbol->name, "_%s", export_names[i].name);
+        if (leading_underscore) {
+        
+            symbol->name = xmalloc (1 + strlen (export_names[i].name) + 1);
+            sprintf (symbol->name, "_%s", export_names[i].name);
+        
+        } else {
+        
+            symbol->name = xmalloc (strlen (export_names[i].name) + 1);
+            sprintf (symbol->name, "%s", export_names[i].name);
+        
+        }
         
         symbol->value = 0;
         symbol->part = 0;
@@ -1729,6 +1888,16 @@ void pe_before_link (void) {
         report_at (program_name, 0, REPORT_WARNING, "base address must be a multiple of 64 KiB (0x10000) according to the specification");
     }
     
+    if (nb_def_list > 0) {
+    
+        long i;
+        
+        for (i = 0; i < nb_def_list; i++) {
+            parse_def (def_list[i]);
+        }
+    
+    }
+    
     exclude_symbols_free ();
     
     if (export_name_list) {
@@ -2062,7 +2231,9 @@ void pe_print_help (void) {
     fprintf (stderr, "    --subsystem <name>                Set required OS subsystem.\n");
     
     fprintf (stderr, "\n");
-    fprintf (stderr, "    -shared, -Bshareable              Create a shared library\n");
+    fprintf (stderr, "    --def-list LIST                   Create implib from a comma seperated\n");
+    fprintf (stderr, "                                          list of files.\n");
+    fprintf (stderr, "    -shared, -Bshareable              Create a shared library.\n");
 
 }
 
@@ -2229,11 +2400,17 @@ static void import_generate_import (const char *import_name, short ordinal_hint,
     }
     
     symbol->name = xmalloc (6 + strlen (import_name) + 1);
-    sprintf (symbol->name, "__imp_%s", import_name);
+    
+    if (leading_underscore) {
+        sprintf (symbol->name, "__imp_%s", import_name);
+    } else {
+        sprintf (symbol->name, "__imp%s", import_name);
+    }
     
     symbol->value = 0;
     symbol->part = dot_idata5_part;
     symbol->section_number = 2;
+    
     symbol_record_external_symbol (symbol);
 
 }