Added __dllexport support, a .def file will be created with the function names under...
authorRobert Pengelly <robertapengelly@hotmail.com>
Fri, 22 May 2026 04:47:57 +0000 (05:47 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Fri, 22 May 2026 04:47:57 +0000 (05:47 +0100)
parse.c
token.c
token.h

diff --git a/parse.c b/parse.c
index d6b67fb1934144e25eeb25b1bac6c150e2449095..78483ea82c476dc35970893429e3341fc9d2fdca 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -12,6 +12,9 @@
 #include    "report.h"
 #include    "token.h"
 
+static struct vector vec_dllexports = { 0 };
+static int parsed_dllexport = 0;
+
 #define     SECTION_NONE                0
 #define     SECTION_TEXT                1
 #define     SECTION_DATA                2
@@ -6169,7 +6172,7 @@ static int is_type_start (enum token_kind k) {
     switch (k) {
     
         case TOK_AUTO:          case TOK_REGISTER:      case TOK_STATIC:
-        case TOK_EXTERN:        case TOK_TYPEDEF:       case TOK_INLINE:
+        case TOK_DLLEXPORT:     case TOK_EXTERN:        case TOK_TYPEDEF:       case TOK_INLINE:
         case TOK_CONST:         case TOK_VOLATILE:      case TOK_RESTRICT:
         case TOK_SIGNED:        case TOK_UNSIGNED:
         case TOK_SHORT:         case TOK_LONG:
@@ -6756,7 +6759,7 @@ static void parse_type_spec (void) {
            tok.kind == TOK_SHORT || tok.kind == TOK_LONG || tok.kind == TOK_CHAR ||
            tok.kind == TOK_INT || tok.kind == TOK_VOID || tok.kind == TOK_FLOAT ||
            tok.kind == TOK_DOUBLE || tok.kind == TOK_INLINE || tok.kind == TOK_RESTRICT ||
-           token_is_ms_int_type_name ()) {
+           tok.kind == TOK_DLLEXPORT || token_is_ms_int_type_name ()) {
         
         saw = 1;
         
@@ -6767,7 +6770,15 @@ static void parse_type_spec (void) {
             saw_real_type = 1;
         }
         
-        if (tok.kind == TOK_EXTERN) {
+        if (tok.kind == TOK_DLLEXPORT) {
+        
+            if (parsed_dllexport) {
+                report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.start, tok.caret, "duplicate '__dllexport'");
+            } else {
+                parsed_dllexport = 1;
+            }
+        
+        } else if (tok.kind == TOK_EXTERN) {
         
             if (parsed_storage_class == STORAGE_EXTERN) {
                 report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.start, tok.caret, "duplicate 'extern'");
@@ -32515,6 +32526,13 @@ static int parse_possible_knr_function (void) {
     
         parse_function_body (name, STORAGE_NONE, 0, 0, 0, 0, DATA_INT & 0x1f, name_line, name_start, name_caret);
         
+        if (parsed_dllexport) {
+        
+            vec_push (&vec_dllexports, xstrdup (name));
+            parsed_dllexport = 0;
+        
+        }
+        
         free (name);
         return 1;
     
@@ -33848,6 +33866,13 @@ static void parse_external_after_type (void) {
         
         if (name && tok.kind == TOK_LBRACE) {
         
+            if (parsed_dllexport) {
+            
+                vec_push (&vec_dllexports, xstrdup (name));
+                parsed_dllexport = 0;
+            
+            }
+            
             parse_function_body (name, declaration_storage, declaration_is_inline,
                 (parsed_type_is_void && !declarator_is_pointer),
                     (declarator_is_pointer ? 0 : parsed_type_is_floating),
@@ -34107,6 +34132,36 @@ void compile_translation_unit (void) {
     
     emit_pending_extern_symbols ();
     
+    if (vec_dllexports.length) {
+    
+        char *p = strrchr (state->ofile, '.'), *tmp;
+        
+        const char *name;
+        long i;
+        
+        FILE *fp;
+        
+        tmp = xmalloc (p - state->ofile + 4);
+        sprintf (tmp, "%.*s.def", (int) (p - state->ofile), state->ofile);
+        
+        if ((fp = fopen (tmp, "w"))) {
+        
+            fprintf (fp, "EXPORTS\n");
+            
+            for (i = 0; i < vec_dllexports.length; i++) {
+            
+                if ((name = asm_global_symbol_name (vec_dllexports.data[i]))) {
+                    fprintf (fp, "    %s\n", name);
+                }
+            
+            }
+            
+            fclose (fp);
+            
+        }
+    
+    }
+    
     if (state->ofp) {
     
         if (state->syntax & ASM_SYNTAX_MASM) {
diff --git a/token.c b/token.c
index 8e8335ee73b801e7a5acbcf573e346bfa74b2909..abf19ceb39034b730693c731ffcfc05c2c09af5c 100755 (executable)
--- a/token.c
+++ b/token.c
@@ -1065,6 +1065,8 @@ static int find_kind (const char *start, const char *caret, const char *p) {
     static struct keyword kws[] = {
     
         /* Compiler Specific keywords */
+        {   "__dllexport",      0,          VERSION,    TOK_DLLEXPORT   },
+        
         {   "__asm__",          0,          VERSION,    TOK_ASM         },
         {   "__inline__",       0,          VERSION,    TOK_INLINE      },
         {   "__restrict__",     0,          VERSION,    TOK_RESTRICT    },
diff --git a/token.h b/token.h
index cbf67e406398e6a98a055452cb5ee767fff2fb65..38037b59c865a13605e00cb5362f34f09cf956bd 100755 (executable)
--- a/token.h
+++ b/token.h
@@ -74,6 +74,7 @@ enum token_kind {
     TOK_CONST,
     TOK_CONTINUE,
     TOK_DEFAULT,
+    TOK_DLLEXPORT,
     TOK_DO,
     TOK_DOUBLE,
     TOK_ELSE,