Author: tkreuzer
Date: Sun Nov 17 22:11:04 2013
New Revision: 61024
URL:
http://svn.reactos.org/svn/reactos?rev=61024&view=rev
Log:
[SPEC2DEF]
Rewrite the code for generating def files. Remove useless switches. Seperate code for GCC
and MSVC for easier maintainability. Make use of the new dlltool feature implemented by
Kai Tietz, that allows to specify the name of an import/export. It is now possible to both
export stdcall and fastcall decorated symbols as well as import from them.
Modified:
trunk/reactos/cmake/gcc.cmake
trunk/reactos/cmake/msvc.cmake
trunk/reactos/tools/spec2def/spec2def.c
Modified: trunk/reactos/cmake/gcc.cmake
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/cmake/gcc.cmake?rev=61024&…
==============================================================================
--- trunk/reactos/cmake/gcc.cmake [iso-8859-1] (original)
+++ trunk/reactos/cmake/gcc.cmake [iso-8859-1] Sun Nov 17 22:11:04 2013
@@ -96,6 +96,7 @@
if(ARCH STREQUAL "i386")
add_compile_flags("-mpreferred-stack-boundary=3 -fno-set-stack-executable
-fno-optimize-sibling-calls -fno-omit-frame-pointer")
+ # FIXME: this doesn't work. CMAKE_BUILD_TYPE is always "Debug"
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_flags("-momit-leaf-frame-pointer")
endif()
@@ -241,7 +242,7 @@
# generate the def for the import lib
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_implib.def
- COMMAND native-spec2def -n=${_dllname} -a=${ARCH2}
-d=${CMAKE_CURRENT_BINARY_DIR}/${_libname}_implib.def
${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
+ COMMAND native-spec2def -n=${_dllname} -a=${ARCH2} --implib
-d=${CMAKE_CURRENT_BINARY_DIR}/${_libname}_implib.def
${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} native-spec2def)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_libname}_implib.def
PROPERTIES EXTERNAL_OBJECT TRUE)
Modified: trunk/reactos/cmake/msvc.cmake
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/cmake/msvc.cmake?rev=61024…
==============================================================================
--- trunk/reactos/cmake/msvc.cmake [iso-8859-1] (original)
+++ trunk/reactos/cmake/msvc.cmake [iso-8859-1] Sun Nov 17 22:11:04 2013
@@ -176,7 +176,7 @@
# Generate the asm stub file and the def file for import library
add_custom_command(
OUTPUT ${_asm_stubs_file} ${_def_file}
- COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} --implib
-n=${_dllname} -d=${_def_file} -l=${_asm_stubs_file}
${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
+ COMMAND native-spec2def --ms -a=${SPEC2DEF_ARCH} --implib -n=${_dllname}
-d=${_def_file} -l=${_asm_stubs_file} ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} native-spec2def)
if(MSVC_IDE)
@@ -233,7 +233,7 @@
#generate def for the DLL and C stubs file
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_file}.def
${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c
- COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} -n=${_dllname}
-d=${CMAKE_CURRENT_BINARY_DIR}/${_file}.def
-s=${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
+ COMMAND native-spec2def --ms -a=${SPEC2DEF_ARCH} -n=${_dllname}
-d=${CMAKE_CURRENT_BINARY_DIR}/${_file}.def
-s=${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} native-spec2def)
if(__add_importlib)
Modified: trunk/reactos/tools/spec2def/spec2def.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/spec2def/spec2def.c?…
==============================================================================
--- trunk/reactos/tools/spec2def/spec2def.c [iso-8859-1] (original)
+++ trunk/reactos/tools/spec2def/spec2def.c [iso-8859-1] Sun Nov 17 22:11:04 2013
@@ -7,12 +7,16 @@
#define strcasecmp _stricmp
#endif
+typedef struct _STRING
+{
+ const char *buf;
+ int len;
+} STRING, *PSTRING;
+
typedef struct
{
- char *pcName;
- int nNameLength;
- char *pcRedirection;
- int nRedirectionLength;
+ STRING strName;
+ STRING strTarget;
int nCallingConvention;
int nOrdinal;
int nStackBytes;
@@ -32,15 +36,15 @@
};
typedef int (*PFNOUTLINE)(FILE *, EXPORT *);
-int gbKillAt = 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 = "";
+int gbDebug;
+#define DbgPrint(...) (!gbDebug || fprintf(stderr, __VA_ARGS__))
enum
{
@@ -101,12 +105,13 @@
return 1;
}
-int
+const char *
ScanToken(const char *token, char chr)
{
while (!IsSeparator(*token))
{
- if (*token++ == chr) return 1;
+ if (*token == chr) return token;
+ token++;
}
return 0;
}
@@ -174,13 +179,13 @@
}
/* Check for C++ */
- if (pexp->pcName[0] == '?')
+ if (pexp->strName.buf[0] == '?')
{
fprintf(file, "stub_function%d(", pexp->nNumber);
}
else
{
- fprintf(file, "%.*s(", pexp->nNameLength, pexp->pcName);
+ fprintf(file, "%.*s(", pexp->strName.len, pexp->strName.buf);
}
for (i = 0; i < pexp->nArgCount; i++)
@@ -200,7 +205,7 @@
fprintf(file, " a%d", i);
}
fprintf(file, ")\n{\n\tDPRINT1(\"WARNING: calling stub %.*s(",
- pexp->nNameLength, pexp->pcName);
+ pexp->strName.len, pexp->strName.buf);
for (i = 0; i < pexp->nArgCount; i++)
{
@@ -261,7 +266,7 @@
OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
{
/* Handle autoname */
- if (pexp->nNameLength == 1 && pexp->pcName[0] == '@')
+ if (pexp->strName.len == 1 && pexp->strName.buf[0] == '@')
{
fprintf(fileDest, "PUBLIC %sordinal%d\n%sordinal%d: nop\n",
gpszUnderscore, pexp->nOrdinal, gpszUnderscore, pexp->nOrdinal);
@@ -269,33 +274,33 @@
else if (giArch != ARCH_X86)
{
fprintf(fileDest, "PUBLIC _stub_%.*s\n_stub_%.*s: nop\n",
- pexp->nNameLength, pexp->pcName,
- pexp->nNameLength, pexp->pcName);
+ pexp->strName.len, pexp->strName.buf,
+ pexp->strName.len, pexp->strName.buf);
}
else if (pexp->nCallingConvention == CC_STDCALL)
{
fprintf(fileDest, "PUBLIC __stub_%.*s@%d\n__stub_%.*s@%d: nop\n",
- pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
- pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
+ pexp->strName.len, pexp->strName.buf, pexp->nStackBytes,
+ pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
}
else if (pexp->nCallingConvention == CC_FASTCALL)
{
fprintf(fileDest, "PUBLIC @_stub_%.*s@%d\n@_stub_%.*s@%d: nop\n",
- pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
- pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
+ pexp->strName.len, pexp->strName.buf, pexp->nStackBytes,
+ pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
}
else if (pexp->nCallingConvention == CC_CDECL ||
pexp->nCallingConvention == CC_STUB)
{
fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s: nop\n",
- pexp->nNameLength, pexp->pcName,
- pexp->nNameLength, pexp->pcName);
+ pexp->strName.len, pexp->strName.buf,
+ pexp->strName.len, pexp->strName.buf);
}
else if (pexp->nCallingConvention == CC_EXTERN)
{
fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s:\n",
- pexp->nNameLength, pexp->pcName,
- pexp->nNameLength, pexp->pcName);
+ pexp->strName.len, pexp->strName.buf,
+ pexp->strName.len, pexp->strName.buf);
}
return 1;
@@ -312,25 +317,151 @@
}
void
-PrintName(FILE *fileDest, EXPORT *pexp, char *pszPrefix, int fRedir, int fDeco)
-{
- char *pcName = fRedir ? pexp->pcRedirection : pexp->pcName;
- int nNameLength = fRedir ? pexp->nRedirectionLength : pexp->nNameLength;
-
- /* Handle autoname */
- if (nNameLength == 1 && pcName[0] == '@')
- {
- fprintf(fileDest, "ordinal%d", pexp->nOrdinal);
+PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
+{
+ const char *pcName = pstr->buf;
+ int nNameLength = pstr->len;
+ const char* pcDot, *pcAt;
+
+ if ((giArch == ARCH_X86) && fDeco &&
+ ((pexp->nCallingConvention == CC_STDCALL) ||
+ (pexp->nCallingConvention == CC_FASTCALL)))
+ {
+ /* Scan for a dll forwarding dot */
+ pcDot = ScanToken(pcName, '.');
+ if (pcDot)
+ {
+ /* First print the dll name, followed by a dot */
+ nNameLength = pcDot - pcName;
+ fprintf(fileDest, "%.*s.", nNameLength, pcName);
+
+ /* Now the actual function name */
+ pcName = pcDot + 1;
+ nNameLength = pexp->strTarget.len - nNameLength - 1;
+ }
+
+ /* Does the string already have decoration? */
+ pcAt = ScanToken(pcName, '@');
+ if (pcAt && (pcAt < (pcName + nNameLength)))
+ {
+ /* On GCC, we need to remove the leading stdcall underscore */
+ if (!gbMSComp && (pexp->nCallingConvention == CC_STDCALL))
+ {
+ pcName++;
+ nNameLength--;
+ }
+
+ /* Print the already decorated function name */
+ fprintf(fileDest, "%.*s", nNameLength, pcName);
+ }
+ else
+ {
+ /* Print the prefix, but skip it for (GCC && stdcall) */
+ if (gbMSComp || (pexp->nCallingConvention != CC_STDCALL))
+ {
+ fprintf(fileDest, "%c%", pexp->nCallingConvention ==
CC_FASTCALL ? '@' : '_');
+ }
+
+ /* Print the name with trailing decoration */
+ fprintf(fileDest, "%.*s@%d", nNameLength, pcName,
pexp->nStackBytes);
+ }
}
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);
+ /* Print the undecorated function name */
+ fprintf(fileDest, "%.*s", nNameLength, pcName);
+ }
+}
+
+void
+OutputLine_def_MS(FILE *fileDest, EXPORT *pexp)
+{
+ PrintName(fileDest, pexp, &pexp->strName, 0);
+
+ if (gbImportLib)
+ {
+ /* Redirect to a stub function, to get the right decoration in the lib */
+ fprintf(fileDest, "=_stub_%.*s", pexp->strName.len,
pexp->strName.buf);
+ }
+ else if (pexp->strTarget.buf)
+ {
+ if (pexp->strName.buf[0] == '?')
+ {
+ fprintf(stderr, "warning: ignoring C++ redirection %.*s ->
%.*s\n",
+ pexp->strName.len, pexp->strName.buf, pexp->strTarget.len,
pexp->strTarget.buf);
+ }
+ else
+ {
+ fprintf(fileDest, "=");
+
+ /* If the original name was decorated, use decoration in the forwarder as
well */
+ if ((giArch == ARCH_X86) && ScanToken(pexp->strName.buf,
'@') &&
+ !ScanToken(pexp->strTarget.buf, '@') &&
+ ((pexp->nCallingConvention == CC_STDCALL) ||
+ (pexp->nCallingConvention == CC_FASTCALL)) )
+ {
+ PrintName(fileDest, pexp, &pexp->strTarget, 1);
+ }
+ else
+ {
+ /* Write the undecorated redirection name */
+ fprintf(fileDest, "%.*s", pexp->strTarget.len,
pexp->strTarget.buf);
+ }
+ }
+ }
+ else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention ==
CC_STUB)) &&
+ (pexp->strName.buf[0] == '?'))
+ {
+ /* C++ stubs are forwarded to C stubs */
+ fprintf(fileDest, "=stub_function%d", pexp->nNumber);
+ }
+}
+
+void
+OutputLine_def_GCC(FILE *fileDest, EXPORT *pexp)
+{
+ /* Print the function name, with decoration for export libs */
+ PrintName(fileDest, pexp, &pexp->strName, gbImportLib);
+ DbgPrint("Generating def line for '%.*s'\n", pexp->strName.len,
pexp->strName.buf);
+
+ /* Check if this is a forwarded export */
+ if (pexp->strTarget.buf)
+ {
+ DbgPrint("Got redirect '%.*s'\n", pexp->strTarget.len,
pexp->strTarget.buf);
+ int fIsExternal = !!ScanToken(pexp->strTarget.buf, '.');
+
+ /* print the target name, don't decorate if it is external */
+ fprintf(fileDest, "=");
+ PrintName(fileDest, pexp, &pexp->strTarget, !fIsExternal);
+ }
+ else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention ==
CC_STUB)) &&
+ (pexp->strName.buf[0] == '?'))
+ {
+ /* C++ stubs are forwarded to C stubs */
+ fprintf(fileDest, "=stub_function%d", pexp->nNumber);
+ }
+
+ /* Special handling for stdcall and fastcall */
+ if ((giArch == ARCH_X86) &&
+ ((pexp->nCallingConvention == CC_STDCALL) ||
+ (pexp->nCallingConvention == CC_FASTCALL)))
+ {
+ /* Is this the import lib? */
+ if (gbImportLib)
+ {
+ /* Is the name in the spec file decorated? */
+ const char* pcDeco = ScanToken(pexp->strName.buf, '@');
+ if (pcDeco && (pcDeco < pexp->strName.buf +
pexp->strName.len))
+ {
+ /* Write the name including the leading @ */
+ fprintf(fileDest, "==%.*s", pexp->strName.len,
pexp->strName.buf);
+ }
+ }
+ else if (!pexp->strTarget.buf)
+ {
+ /* Write a forwarder to the actual decorated symbol */
+ fprintf(fileDest, "=");
+ PrintName(fileDest, pexp, &pexp->strName, 1);
}
}
}
@@ -340,43 +471,10 @@
{
fprintf(fileDest, " ");
- PrintName(fileDest, pexp, "", 0, (giArch == ARCH_X86) &&
!gbKillAt);
-
- if (gbImportLib)
- {
- fprintf(fileDest, "=");
- PrintName(fileDest, pexp, "_stub_", 0, 0);
- }
- else if (pexp->pcRedirection)
- {
- if (gbMSComp && (pexp->pcName[0] == '?'))
- {
- fprintf(stderr, "warning: ignoring C++ redirection %.*s ->
%.*s\n",
- pexp->nNameLength, pexp->pcName, pexp->nRedirectionLength,
pexp->pcRedirection);
- }
- else
- {
- int fDeco;
-
- 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] == '?'))
- {
- /* C++ stubs are forwarded to C stubs */
- fprintf(fileDest, "=");
- fprintf(fileDest, "stub_function%d", pexp->nNumber);
- }
- else if ((giArch == ARCH_X86) && gbKillAt && !gbMSComp &&
- (pexp->nCallingConvention == CC_STDCALL ||
- pexp->nCallingConvention == CC_FASTCALL))
- {
- fprintf(fileDest, "=");
- PrintName(fileDest, pexp, "", 0, 1);
- }
+ if (gbMSComp)
+ OutputLine_def_MS(fileDest, pexp);
+ else
+ OutputLine_def_GCC(fileDest, pexp);
if (pexp->nOrdinal != -1)
{
@@ -410,6 +508,7 @@
int nLine;
EXPORT exp;
int included;
+ char namebuffer[16];
//fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine,
pcStart);
@@ -424,6 +523,10 @@
exp.uFlags = 0;
exp.nNumber++;
+
+ //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
+ // gbDebug = 1;
+
//fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
// nLine, TokenLength(pcLine), pcLine);
@@ -448,7 +551,7 @@
return -10;
}
- //fprintf(stderr, "info: Token:'%.10s'\n", pc);
+ //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc),
pc);
/* Now we should get the type */
if (CompareToken(pc, "stdcall"))
@@ -478,7 +581,7 @@
}
else
{
- fprintf(stderr, "error: line %d, expected type, got '%.*s'
%d\n",
+ fprintf(stderr, "error: line %d, expected callconv, got '%.*s'
%d\n",
nLine, TokenLength(pc), pc, *pc);
return -11;
}
@@ -555,8 +658,17 @@
if (!included) continue;
/* Get name */
- exp.pcName = pc;
- exp.nNameLength = TokenLength(pc);
+ exp.strName.buf = pc;
+ exp.strName.len = TokenLength(pc);
+
+ /* Check for autoname */
+ if ((exp.strName.len == 1) && (exp.strName.buf[0] == '@'))
+ {
+ sprintf(namebuffer, "ordinal%d", exp.nOrdinal);
+ exp.strName.len = strlen(namebuffer);
+ exp.strName.buf = namebuffer;
+ exp.uFlags |= FL_NONAME;
+ }
/* Handle parameters */
exp.nStackBytes = 0;
@@ -649,12 +761,14 @@
else
{
/* Check for stdcall name */
- char *p = strchr(pc, '@');
- if (p && (p - pc < exp.nNameLength))
+ const char *p = ScanToken(pc, '@');
+ if (p && (p - pc < exp.strName.len))
{
int i;
- exp.nNameLength = (int)(p - pc);
- if (exp.nNameLength < 1)
+
+ /* Truncate the name to before the @ */
+ exp.strName.len = (int)(p - pc);
+ if (exp.strName.len < 1)
{
fprintf(stderr, "error, @ in line %d\n", nLine);
return -1;
@@ -673,8 +787,8 @@
pc = NextToken(pc);
if (pc)
{
- exp.pcRedirection = pc;
- exp.nRedirectionLength = TokenLength(pc);
+ exp.strTarget.buf = pc;
+ exp.strTarget.len = TokenLength(pc);
/* Check syntax (end of line) */
if (NextToken(pc))
@@ -685,11 +799,18 @@
}
else
{
- exp.pcRedirection = 0;
- exp.nRedirectionLength = 0;
+ exp.strTarget.buf = 0;
+ exp.strTarget.len = 0;
+ }
+
+ /* Check for no-name without ordinal */
+ if ((exp.uFlags & FL_NONAME) && (exp.nOrdinal == -1))
+ {
+ fprintf(stderr, "error: line %d, noname export without ordinal!\n",
nLine);
}
OutputLine(fileDest, &exp);
+ gbDebug = 0;
}
return 0;
@@ -752,20 +873,11 @@
}
else if ((strcasecmp(argv[i], "--implib") == 0))
{
- no_redirections = 1;
gbImportLib = 1;
}
- else if ((strcasecmp(argv[i], "--kill-at") == 0))
- {
- gbKillAt = 1;
- }
else if ((strcasecmp(argv[i], "--ms") == 0))
{
gbMSComp = 1;
- }
- else if ((strcasecmp(argv[i], "-r") == 0))
- {
- no_redirections = 1;
}
else if (argv[i][1] == 'a' && argv[i][2] == '=')
{