[SPEC2DEF]
[reactos.git] / reactos / tools / spec2def / spec2def.c
index f0f2db3..e5cee3c 100644 (file)
@@ -10,7 +10,7 @@
 typedef struct
 {
     char *pcName;
-    size_t nNameLength;
+    int nNameLength;
     char *pcRedirection;
     int nRedirectionLength;
     int nCallingConvention;
@@ -19,6 +19,7 @@ typedef struct
     int nArgCount;
     int anArgs[30];
     unsigned int uFlags;
+    int nNumber;
 } EXPORT;
 
 enum _ARCH
@@ -32,13 +33,14 @@ enum _ARCH
 
 typedef int (*PFNOUTLINE)(FILE *, EXPORT *);
 int gbKillAt = 0;
-int gbUseDeco = 0;
 int gbMSComp = 0;
+int gbImportLib = 0;
 int no_redirections = 0;
 int giArch = ARCH_X86;
 char *pszArchString = "i386";
 char *pszArchString2;
 char *pszDllName = 0;
+char *gpszUnderscore = "";
 
 enum
 {
@@ -52,6 +54,7 @@ enum
     CC_STDCALL,
     CC_CDECL,
     CC_FASTCALL,
+    CC_THISCALL,
     CC_EXTERN,
     CC_STUB,
 };
@@ -63,7 +66,9 @@ enum
     ARG_STR,
     ARG_WSTR,
     ARG_DBL,
-    ARG_INT64
+    ARG_INT64,
+    ARG_INT128,
+    ARG_FLOAT
 };
 
 char* astrCallingConventions[] =
@@ -71,6 +76,7 @@ char* astrCallingConventions[] =
     "STDCALL",
     "CDECL",
     "FASTCALL",
+    "THISCALL",
     "EXTERN"
 };
 
@@ -167,7 +173,15 @@ OutputLine_stub(FILE *file, EXPORT *pexp)
         fprintf(file, "__stdcall ");
     }
 
-    fprintf(file, "%.*s(", pexp->nNameLength, pexp->pcName);
+    /* Check for C++ */
+    if (pexp->pcName[0] == '?')
+    {
+        fprintf(file, "stub_function%d(", pexp->nNumber);
+    }
+    else
+    {
+        fprintf(file, "%.*s(", pexp->nNameLength, pexp->pcName);
+    }
 
     for (i = 0; i < pexp->nArgCount; i++)
     {
@@ -178,7 +192,10 @@ OutputLine_stub(FILE *file, EXPORT *pexp)
             case ARG_PTR:  fprintf(file, "void*"); break;
             case ARG_STR:  fprintf(file, "char*"); break;
             case ARG_WSTR: fprintf(file, "wchar_t*"); break;
-            case ARG_DBL: case ARG_INT64 :  fprintf(file, "__int64"); break;
+            case ARG_DBL:
+            case ARG_INT64 :  fprintf(file, "__int64"); break;
+            case ARG_INT128 :  fprintf(file, "__int128"); break;
+            case ARG_FLOAT: fprintf(file, "float"); break;
         }
         fprintf(file, " a%d", i);
     }
@@ -196,6 +213,8 @@ OutputLine_stub(FILE *file, EXPORT *pexp)
             case ARG_WSTR: fprintf(file, "'%%ws'"); break;
             case ARG_DBL:  fprintf(file, "%%f"); break;
             case ARG_INT64: fprintf(file, "%%\"PRix64\""); break;
+            case ARG_INT128: fprintf(file, "%%\"PRix128\""); break;
+            case ARG_FLOAT: fprintf(file, "%%f"); break;
         }
     }
     fprintf(file, ")\\n\"");
@@ -211,6 +230,8 @@ OutputLine_stub(FILE *file, EXPORT *pexp)
             case ARG_WSTR: fprintf(file, "(wchar_t*)a%d", i); break;
             case ARG_DBL:  fprintf(file, "(double)a%d", i); break;
             case ARG_INT64: fprintf(file, "(__int64)a%d", i); break;
+            case ARG_INT128: fprintf(file, "(__int128)a%d", i); break;
+            case ARG_FLOAT: fprintf(file, "(float)a%d", i); break;
         }
     }
     fprintf(file, ");\n");
@@ -242,37 +263,37 @@ OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
     /* Handle autoname */
     if (pexp->nNameLength == 1 && pexp->pcName[0] == '@')
     {
-        fprintf(fileDest, "PUBLIC ordinal%d\nordinal%d: nop\n",
-                pexp->nOrdinal, pexp->nOrdinal);
+        fprintf(fileDest, "PUBLIC %sordinal%d\n%sordinal%d: nop\n",
+                gpszUnderscore, pexp->nOrdinal, gpszUnderscore, pexp->nOrdinal);
     }
-    else if (giArch == ARCH_AMD64)
+    else if (giArch != ARCH_X86)
     {
-        fprintf(fileDest, "PUBLIC %.*s\n%.*s: nop\n",
+        fprintf(fileDest, "PUBLIC _stub_%.*s\n_stub_%.*s: nop\n",
                 pexp->nNameLength, pexp->pcName,
                 pexp->nNameLength, pexp->pcName);
     }
     else if (pexp->nCallingConvention == CC_STDCALL)
     {
-        fprintf(fileDest, "PUBLIC _%.*s@%d\n_%.*s@%d: nop\n",
+        fprintf(fileDest, "PUBLIC __stub_%.*s@%d\n__stub_%.*s@%d: nop\n",
                 pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
                 pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
     }
     else if (pexp->nCallingConvention == CC_FASTCALL)
     {
-        fprintf(fileDest, "PUBLIC @%.*s@%d\n@%.*s@%d: nop\n",
+        fprintf(fileDest, "PUBLIC @_stub_%.*s@%d\n@_stub_%.*s@%d: nop\n",
                 pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
                 pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
     }
     else if (pexp->nCallingConvention == CC_CDECL ||
              pexp->nCallingConvention == CC_STUB)
     {
-        fprintf(fileDest, "PUBLIC _%.*s\n_%.*s: nop\n",
+        fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s: nop\n",
                 pexp->nNameLength, pexp->pcName,
                 pexp->nNameLength, pexp->pcName);
     }
     else if (pexp->nCallingConvention == CC_EXTERN)
     {
-        fprintf(fileDest, "PUBLIC _%.*s\n_%.*s:\n",
+        fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s:\n",
                 pexp->nNameLength, pexp->pcName,
                 pexp->nNameLength, pexp->pcName);
     }
@@ -291,18 +312,26 @@ OutputHeader_def(FILE *file, char *libname)
 }
 
 void
-PrintName(FILE *fileDest, EXPORT *pexp, int fRedir, int fDeco)
+PrintName(FILE *fileDest, EXPORT *pexp, char *pszPrefix, int fRedir, int fDeco)
 {
     char *pcName = fRedir ? pexp->pcRedirection : pexp->pcName;
-    size_t nNameLength = fRedir ? pexp->nRedirectionLength : pexp->nNameLength;
+    int nNameLength = fRedir ? pexp->nRedirectionLength : pexp->nNameLength;
 
-    if (fDeco && pexp->nCallingConvention == CC_FASTCALL)
-         fprintf(fileDest, "@");
-    fprintf(fileDest, "%.*s", nNameLength, pcName);
-    if ((pexp->nCallingConvention == CC_STDCALL ||
-        pexp->nCallingConvention == CC_FASTCALL) && fDeco)
+    /* Handle autoname */
+    if (nNameLength == 1 && pcName[0] == '@')
     {
-        fprintf(fileDest, "@%d", pexp->nStackBytes);
+        fprintf(fileDest, "ordinal%d", pexp->nOrdinal);
+    }
+    else
+    {
+        if (fDeco && pexp->nCallingConvention == CC_FASTCALL)
+             fprintf(fileDest, "@");
+        fprintf(fileDest, "%s%.*s", pszPrefix, nNameLength, pcName);
+        if ((pexp->nCallingConvention == CC_STDCALL ||
+            pexp->nCallingConvention == CC_FASTCALL) && fDeco)
+        {
+            fprintf(fileDest, "@%d", pexp->nStackBytes);
+        }
     }
 }
 
@@ -311,29 +340,41 @@ OutputLine_def(FILE *fileDest, EXPORT *pexp)
 {
     fprintf(fileDest, " ");
 
-    /* Handle autoname */
-    if (pexp->nNameLength == 1 && pexp->pcName[0] == '@')
+    PrintName(fileDest, pexp, "", 0, (giArch == ARCH_X86) && !gbKillAt);
+
+    if (gbImportLib)
     {
-        fprintf(fileDest, "ordinal%d", pexp->nOrdinal);
+        fprintf(fileDest, "=");
+        PrintName(fileDest, pexp, "_stub_", 0, 0);
     }
-    else
+    else if (pexp->pcRedirection)
     {
-        PrintName(fileDest, pexp, 0, gbUseDeco && !gbKillAt);
-    }
+        if (gbMSComp && (pexp->pcName[0] == '?'))
+        {
+            /* ignore c++ redirection, since link doesn't like that! */
+        }
+        else
+        {
+            int fDeco;
 
-    if (pexp->pcRedirection && !no_redirections)
+            fDeco = ((giArch == ARCH_X86) && !ScanToken(pexp->pcRedirection, '.'));
+            fprintf(fileDest, "=");
+            PrintName(fileDest, pexp, "", 1, fDeco && !gbMSComp);
+        }
+    }
+    else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
+             (pexp->pcName[0] == '?'))
     {
-        int fDeco = (gbUseDeco && !ScanToken(pexp->pcRedirection, '.'));
-
+        /* C++ stubs are forwarded to C stubs */
         fprintf(fileDest, "=");
-        PrintName(fileDest, pexp, 1, fDeco && !gbMSComp);
+        fprintf(fileDest, "stub_function%d", pexp->nNumber);
     }
-    else if (gbUseDeco && gbKillAt && !gbMSComp &&
+    else if ((giArch == ARCH_X86) && gbKillAt && !gbMSComp &&
              (pexp->nCallingConvention == CC_STDCALL ||
               pexp->nCallingConvention == CC_FASTCALL))
     {
         fprintf(fileDest, "=");
-        PrintName(fileDest, pexp, 0, 1);
+        PrintName(fileDest, pexp, "", 0, 1);
     }
 
     if (pexp->nOrdinal != -1)
@@ -373,12 +414,14 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
 
     /* Loop all lines */
     nLine = 1;
+    exp.nNumber = 0;
     for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
     {
         pc = pcLine;
 
         exp.nArgCount = 0;
         exp.uFlags = 0;
+        exp.nNumber++;
 
         //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
         //        nLine, TokenLength(pcLine), pcLine);
@@ -420,6 +463,10 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
         {
             exp.nCallingConvention = CC_FASTCALL;
         }
+        else if (CompareToken(pc, "thiscall"))
+        {
+            exp.nCallingConvention = CC_THISCALL;
+        }
         else if (CompareToken(pc, "extern"))
         {
             exp.nCallingConvention = CC_EXTERN;
@@ -558,6 +605,16 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
                     exp.nStackBytes += 8;
                     exp.anArgs[exp.nArgCount] = ARG_INT64;
                 }
+                else if (CompareToken(pc, "int128"))
+                {
+                    exp.nStackBytes += 16;
+                    exp.anArgs[exp.nArgCount] = ARG_INT128;
+                }
+                else if (CompareToken(pc, "float"))
+                {
+                    exp.nStackBytes += 4;
+                    exp.anArgs[exp.nArgCount] = ARG_FLOAT;
+                }
                 else
                     fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc);
 
@@ -585,17 +642,17 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
             /* Check for c++ mangled name */
             if (pc[0] == '?')
             {
-                printf("Found c++ mangled name...\n");
+                //printf("Found c++ mangled name...\n");
                 //
             }
             else
             {
                 /* Check for stdcall name */
                 char *p = strchr(pc, '@');
-                if (p && ((size_t)(p - pc) < exp.nNameLength))
+                if (p && (p - pc < exp.nNameLength))
                 {
                     int i;
-                    exp.nNameLength = p - pc;
+                    exp.nNameLength = (int)(p - pc);
                     if (exp.nNameLength < 1)
                     {
                         fprintf(stderr, "error, @ in line %d\n", nLine);
@@ -612,7 +669,8 @@ ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
         }
 
         /* Get optional redirection */
-        if ((pc = NextToken(pc)))
+        pc = NextToken(pc);
+        if (pc)
         {
             exp.pcRedirection = pc;
             exp.nRedirectionLength = TokenLength(pc);
@@ -658,7 +716,7 @@ int main(int argc, char *argv[])
     char *pszSource, *pszDefFileName = 0, *pszStubFileName = 0, *pszLibStubName = 0;
     char achDllName[40];
     FILE *file;
-    int result, i;
+    int result = 0, i;
 
     if (argc < 2)
     {
@@ -691,6 +749,11 @@ int main(int argc, char *argv[])
         {
             pszDllName = argv[i] + 3;
         }
+        else if ((strcasecmp(argv[i], "--implib") == 0))
+        {
+            no_redirections = 1;
+            gbImportLib = 1;
+        }
         else if ((strcasecmp(argv[i], "--kill-at") == 0))
         {
             gbKillAt = 1;
@@ -714,7 +777,11 @@ int main(int argc, char *argv[])
         }
     }
 
-    if (strcasecmp(pszArchString, "i386") == 0) giArch = ARCH_X86;
+    if (strcasecmp(pszArchString, "i386") == 0)
+    {
+        giArch = ARCH_X86;
+        gpszUnderscore = "_";
+    }
     else if (strcasecmp(pszArchString, "x86_64") == 0) giArch = ARCH_AMD64;
     else if (strcasecmp(pszArchString, "ia64") == 0) giArch = ARCH_IA64;
     else if (strcasecmp(pszArchString, "arm") == 0) giArch = ARCH_ARM;
@@ -727,11 +794,6 @@ int main(int argc, char *argv[])
     else
         pszArchString2 = "win32";
 
-    if (giArch == ARCH_X86)
-    {
-        gbUseDeco = 1;
-    }
-
     /* Set a default dll name */
     if (!pszDllName)
     {
@@ -771,7 +833,11 @@ int main(int argc, char *argv[])
 
     /* Allocate memory buffer */
     pszSource = malloc(nFileSize + 1);
-    if (!pszSource) return -4;
+    if (!pszSource)
+    {
+        fclose(file);
+        return -4;
+    }
 
     /* Load input file into memory */
     nFileSize = fread(pszSource, 1, nFileSize, file);