ReactOS 0.4.16-dev-753-g705a985
spec2def.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
Include dependency graph for spec2def.c:

Go to the source code of this file.

Classes

struct  _STRING
 
struct  EXPORT
 

Macros

#define ARRAYSIZE(a)   (sizeof(a) / sizeof((a)[0]))
 
#define DbgPrint(...)   (!gbDebug || fprintf(stderr, __VA_ARGS__))
 

Typedefs

typedef struct _STRING STRING
 
typedef struct _STRINGPSTRING
 
typedef int(* PFNOUTLINE) (FILE *, EXPORT *)
 

Enumerations

enum  _ARCH {
  ARCH_X86 , ARCH_AMD64 , ARCH_IA64 , ARCH_ARM ,
  ARCH_ARM64 , ARCH_PPC
}
 
enum  {
  FL_PRIVATE = 1 , FL_STUB = 2 , FL_NONAME = 4 , FL_ORDINAL = 8 ,
  FL_NORELAY = 16 , FL_RET64 = 32 , FL_REGISTER = 64 , FL_IMPSYM = 128
}
 
enum  {
  CC_STDCALL , CC_CDECL , CC_FASTCALL , CC_THISCALL ,
  CC_EXTERN , CC_STUB
}
 
enum  {
  ARG_LONG , ARG_PTR , ARG_STR , ARG_WSTR ,
  ARG_DBL , ARG_INT64 , ARG_INT128 , ARG_FLOAT
}
 

Functions

static int IsSeparator (char chr)
 
int CompareToken (const char *token, const char *comparand)
 
const charScanToken (const char *token, char chr)
 
const charNextLine (const char *pc)
 
int TokenLength (const char *pc)
 
const charNextToken (const char *pc)
 
void OutputHeader_stub (FILE *file)
 
int OutputLine_stub (FILE *file, EXPORT *pexp)
 
void OutputHeader_asmstub (FILE *file, char *libname)
 
void Output_stublabel (FILE *fileDest, char *pszSymbolName)
 
int OutputLine_asmstub (FILE *fileDest, EXPORT *pexp)
 
void OutputHeader_def (FILE *file, char *libname)
 
void PrintName (FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
 
void OutputLine_def_MS (FILE *fileDest, EXPORT *pexp)
 
void OutputLine_def_GCC (FILE *fileDest, EXPORT *pexp)
 
int OutputLine_def (FILE *fileDest, EXPORT *pexp)
 
void PrintNameOrImpName (FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco, int fImp)
 
void OutputAlias (FILE *fileDest, EXPORT *pexp, int fImp)
 
int OutputLine_implib_asm (FILE *fileDest, EXPORT *pexp)
 
void Fatalv (const char *filename, unsigned nLine, const char *pcLine, const char *pc, size_t errorlen, const char *format, va_list argptr)
 
void Fatal (const char *filename, unsigned nLine, const char *pcLine, const char *pc, size_t errorlen, const char *format,...)
 
EXPORTParseFile (char *pcStart, FILE *fileDest, unsigned *cExports)
 
int ApplyOrdinals (EXPORT *pexports, unsigned cExports)
 
void usage (void)
 
int main (int argc, char *argv[])
 

Variables

int gbMSComp = 0
 
int gbImportLib = 0
 
int gbNotPrivateNoWarn = 0
 
int gbTracing = 0
 
int giArch = ARCH_X86
 
int gbDbgExports = 0
 
charpszArchString = "i386"
 
charpszArchString2
 
charpszSourceFileName = NULL
 
charpszDllName = NULL
 
chargpszUnderscore = ""
 
int gbDebug
 
unsigned guOsVersion = 0x502
 
const charastrCallingConventions []
 
static const charastrOlePrivateExports []
 

Macro Definition Documentation

◆ ARRAYSIZE

#define ARRAYSIZE (   a)    (sizeof(a) / sizeof((a)[0]))

Definition at line 12 of file spec2def.c.

◆ DbgPrint

#define DbgPrint (   ...)    (!gbDebug || fprintf(stderr, __VA_ARGS__))

Definition at line 78 of file spec2def.c.

Typedef Documentation

◆ PFNOUTLINE

typedef int(* PFNOUTLINE) (FILE *, EXPORT *)

Definition at line 64 of file spec2def.c.

◆ PSTRING

typedef struct _STRING * PSTRING

◆ STRING

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
FL_PRIVATE 
FL_STUB 
FL_NONAME 
FL_ORDINAL 
FL_NORELAY 
FL_RET64 
FL_REGISTER 
FL_IMPSYM 

Definition at line 80 of file spec2def.c.

81{
82 FL_PRIVATE = 1,
83 FL_STUB = 2,
84 FL_NONAME = 4,
85 FL_ORDINAL = 8,
86 FL_NORELAY = 16,
87 FL_RET64 = 32,
88 FL_REGISTER = 64,
89 FL_IMPSYM = 128,
90};
@ FL_PRIVATE
Definition: spec2def.c:82
@ FL_REGISTER
Definition: spec2def.c:88
@ FL_NONAME
Definition: spec2def.c:84
@ FL_IMPSYM
Definition: spec2def.c:89
@ FL_ORDINAL
Definition: spec2def.c:85
@ FL_RET64
Definition: spec2def.c:87
@ FL_NORELAY
Definition: spec2def.c:86
@ FL_STUB
Definition: spec2def.c:83

◆ anonymous enum

anonymous enum
Enumerator
CC_STDCALL 
CC_CDECL 
CC_FASTCALL 
CC_THISCALL 
CC_EXTERN 
CC_STUB 

Definition at line 92 of file spec2def.c.

93{
99 CC_STUB,
100};
@ CC_STUB
Definition: spec2def.c:99
@ CC_CDECL
Definition: spec2def.c:95
@ CC_STDCALL
Definition: spec2def.c:94
@ CC_FASTCALL
Definition: spec2def.c:96
@ CC_THISCALL
Definition: spec2def.c:97
@ CC_EXTERN
Definition: spec2def.c:98

◆ anonymous enum

anonymous enum
Enumerator
ARG_LONG 
ARG_PTR 
ARG_STR 
ARG_WSTR 
ARG_DBL 
ARG_INT64 
ARG_INT128 
ARG_FLOAT 

Definition at line 102 of file spec2def.c.

103{
104 ARG_LONG,
105 ARG_PTR,
106 ARG_STR,
107 ARG_WSTR,
108 ARG_DBL,
109 ARG_INT64,
112};
@ ARG_DBL
Definition: spec2def.c:108
@ ARG_FLOAT
Definition: spec2def.c:111
@ ARG_LONG
Definition: spec2def.c:104
@ ARG_PTR
Definition: spec2def.c:105
@ ARG_INT64
Definition: spec2def.c:109
@ ARG_STR
Definition: spec2def.c:106
@ ARG_WSTR
Definition: spec2def.c:107
@ ARG_INT128
Definition: spec2def.c:110

◆ _ARCH

Enumerator
ARCH_X86 
ARCH_AMD64 
ARCH_IA64 
ARCH_ARM 
ARCH_ARM64 
ARCH_PPC 

Definition at line 54 of file spec2def.c.

55{
62};
@ ARCH_IA64
Definition: spec2def.c:58
@ ARCH_AMD64
Definition: spec2def.c:57
@ ARCH_X86
Definition: spec2def.c:56
@ ARCH_ARM64
Definition: spec2def.c:60
@ ARCH_ARM
Definition: spec2def.c:59
@ ARCH_PPC
Definition: spec2def.c:61

Function Documentation

◆ ApplyOrdinals()

int ApplyOrdinals ( EXPORT pexports,
unsigned  cExports 
)

Definition at line 1443 of file spec2def.c.

1444{
1445 unsigned short i, j;
1446 char* used;
1447 unsigned short firstOrdinal = 0xFFFF, firstIndex = 0;
1448
1449 /* Allocate a table to mark used ordinals */
1450 used = malloc(65536);
1451 if (used == NULL)
1452 {
1453 fprintf(stderr, "Failed to allocate memory for ordinal use table\n");
1454 return -1;
1455 }
1456 memset(used, 0, 65536);
1457
1458 /* Pass 1: mark the ordinals that are already used */
1459 for (i = 0; i < cExports; i++)
1460 {
1461 if (pexports[i].uFlags & FL_ORDINAL)
1462 {
1463 if (used[pexports[i].nOrdinal] != 0)
1464 {
1465 fprintf(stderr, "Found duplicate ordinal: %u\n", pexports[i].nOrdinal);
1466 return -1;
1467 }
1468 used[pexports[i].nOrdinal] = 1;
1469 if (pexports[i].nOrdinal < firstOrdinal)
1470 {
1471 firstOrdinal = pexports[i].nOrdinal;
1472 firstIndex = i;
1473 }
1474 }
1475 }
1476
1477 /* Check if we found an ordinal and it's larger than it's index */
1478 if ((firstOrdinal != 0xFFFF) && (firstOrdinal > firstIndex))
1479 {
1480 /* We did. Calculate an appropriate starting ordinal. */
1481 firstOrdinal -= firstIndex;
1482 }
1483 else
1484 {
1485 /* We didn't, so start with 1 */
1486 firstOrdinal = 1;
1487 }
1488
1489 /* Pass 2: apply available ordinals */
1490 for (i = 0, j = firstOrdinal; i < cExports; i++)
1491 {
1492 if ((pexports[i].uFlags & FL_ORDINAL) == 0 && pexports[i].bVersionIncluded)
1493 {
1494 while (used[j] != 0)
1495 j++;
1496
1497 pexports[i].nOrdinal = j;
1498 used[j] = 1;
1499 }
1500 }
1501
1502 free(used);
1503 return 0;
1504}
static int used
Definition: adh-main.c:39
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
UINT uFlags
Definition: api.c:59
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define memset(x, y, z)
Definition: compat.h:39
int nOrdinal
Definition: spec2def.c:25

Referenced by main().

◆ CompareToken()

int CompareToken ( const char token,
const char comparand 
)

Definition at line 156 of file spec2def.c.

157{
158 while (*comparand)
159 {
160 if (*token != *comparand) return 0;
161 token++;
162 comparand++;
163 }
164 if (IsSeparator(comparand[-1])) return 1;
165 if (!IsSeparator(*token)) return 0;
166 return 1;
167}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
static int IsSeparator(char chr)
Definition: spec2def.c:149

Referenced by ParseFile().

◆ Fatal()

void Fatal ( const char filename,
unsigned  nLine,
const char pcLine,
const char pc,
size_t  errorlen,
const char format,
  ... 
)

Definition at line 910 of file spec2def.c.

918{
919 va_list argptr;
920
921 va_start(argptr, format);
922 Fatalv(filename, nLine, pcLine, pc, errorlen, format, argptr);
923 va_end(argptr);
924}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
const char * filename
Definition: ioapi.h:137
void Fatalv(const char *filename, unsigned nLine, const char *pcLine, const char *pc, size_t errorlen, const char *format, va_list argptr)
Definition: spec2def.c:860
Definition: format.c:58

Referenced by AcpiExOpcode_3A_0T_0R(), and ParseFile().

◆ Fatalv()

void Fatalv ( const char filename,
unsigned  nLine,
const char pcLine,
const char pc,
size_t  errorlen,
const char format,
va_list  argptr 
)

Definition at line 860 of file spec2def.c.

868{
869 unsigned i, errorpos, len;
870 const char* pcLineEnd;
871
872 /* Get the length of the line */
873 pcLineEnd = strpbrk(pcLine, "\r\n");
874 len = (unsigned)(pcLineEnd - pcLine);
875
876 if (pc == NULL)
877 {
878 pc = pcLine + len - 1;
879 errorlen = 1;
880 }
881
882 errorpos = (unsigned)(pc - pcLine);
883
884 /* Output the error message */
885 fprintf(stderr, "ERROR: (%s:%u:%u): ", filename, nLine, errorpos);
886 vfprintf(stderr, format, argptr);
887 fprintf(stderr, "\n");
888
889 /* Output the line with the error */
890 fprintf(stderr, "> %.*s\n", len, pcLine);
891
892 if (errorlen == 0)
893 {
894 errorlen = TokenLength(pc);
895 }
896
897 for (i = 0; i < errorpos + 2; i++)
898 {
899 fprintf(stderr, " ");
900 }
901 for (i = 0; i < errorlen; i++)
902 {
903 fprintf(stderr, "~");
904 }
905 fprintf(stderr, "\n");
906 exit(-1);
907}
char * strpbrk(const char *String, const char *Delimiters)
Definition: utclib.c:302
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define exit(n)
Definition: config.h:202
int TokenLength(const char *pc)
Definition: spec2def.c:193

Referenced by Fatal().

◆ IsSeparator()

static int IsSeparator ( char  chr)
static

Definition at line 149 of file spec2def.c.

150{
151 return ((chr <= ',' && chr != '$' && chr != '#') ||
152 (chr >= ':' && chr < '?') );
153}

Referenced by CompareToken(), NextToken(), ScanToken(), and TokenLength().

◆ main()

int main ( int argc  ,
char argv[] 
)

Definition at line 1525 of file spec2def.c.

1526{
1527 size_t nFileSize;
1528 char *pszSource, *pszDefFileName = NULL, *pszStubFileName = NULL, *pszLibStubName = NULL;
1529 char *pszImpLibAliasFileName = NULL;
1530 const char* pszVersionOption = "--version=0x";
1531 char achDllName[40];
1532 FILE *file;
1533 unsigned cExports = 0, i;
1534 EXPORT *pexports;
1535
1536 if (argc < 2)
1537 {
1538 usage();
1539 return -1;
1540 }
1541
1542 /* Read options */
1543 for (i = 1; i < (unsigned)argc && *argv[i] == '-'; i++)
1544 {
1545 if ((strcasecmp(argv[i], "--help") == 0) ||
1546 (strcasecmp(argv[i], "-h") == 0))
1547 {
1548 usage();
1549 return 0;
1550 }
1551 else if (argv[i][1] == 'd' && argv[i][2] == '=')
1552 {
1553 pszDefFileName = argv[i] + 3;
1554 }
1555 else if (argv[i][1] == 'l' && argv[i][2] == '=')
1556 {
1557 pszLibStubName = argv[i] + 3;
1558 }
1559 else if (argv[i][1] == 's' && argv[i][2] == '=')
1560 {
1561 pszStubFileName = argv[i] + 3;
1562 }
1563 else if (argv[i][1] == 'i' && argv[i][2] == '=')
1564 {
1565 pszImpLibAliasFileName = argv[i] + 3;
1566 }
1567 else if (argv[i][1] == 'n' && argv[i][2] == '=')
1568 {
1569 pszDllName = argv[i] + 3;
1570 }
1571 else if (strncasecmp(argv[i], pszVersionOption, strlen(pszVersionOption)) == 0)
1572 {
1573 guOsVersion = strtoul(argv[i] + strlen(pszVersionOption), NULL, 16);
1574 }
1575 else if (strcasecmp(argv[i], "--implib") == 0)
1576 {
1577 gbImportLib = 1;
1578 }
1579 else if (strcasecmp(argv[i], "--ms") == 0)
1580 {
1581 gbMSComp = 1;
1582 }
1583 else if (strcasecmp(argv[i], "--dbg") == 0)
1584 {
1585 gbDbgExports = 1;
1586 }
1587 else if (strcasecmp(argv[i], "--no-private-warnings") == 0)
1588 {
1590 }
1591 else if (strcasecmp(argv[i], "--with-tracing") == 0)
1592 {
1593 if (!pszStubFileName)
1594 {
1595 fprintf(stderr, "Error: cannot use --with-tracing without -s option.\n");
1596 return -1;
1597 }
1598 gbTracing = 1;
1599 }
1600 else if (argv[i][1] == 'a' && argv[i][2] == '=')
1601 {
1602 pszArchString = argv[i] + 3;
1603 }
1604 else
1605 {
1606 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
1607 return -1;
1608 }
1609 }
1610
1611 if (strcasecmp(pszArchString, "i386") == 0)
1612 {
1613 giArch = ARCH_X86;
1614 gpszUnderscore = "_";
1615 }
1616 else if (strcasecmp(pszArchString, "x86_64") == 0) giArch = ARCH_AMD64;
1617 else if (strcasecmp(pszArchString, "ia64") == 0) giArch = ARCH_IA64;
1618 else if (strcasecmp(pszArchString, "arm") == 0) giArch = ARCH_ARM;
1619 else if (strcasecmp(pszArchString, "arm64") == 0) giArch = ARCH_ARM64;
1620 else if (strcasecmp(pszArchString, "ppc") == 0) giArch = ARCH_PPC;
1621
1622 if ((giArch == ARCH_AMD64) || (giArch == ARCH_IA64))
1623 {
1624 pszArchString2 = "win64";
1625 }
1626 else
1627 pszArchString2 = "win32";
1628
1629 /* Set a default dll name */
1630 if (!pszDllName)
1631 {
1632 char *p1, *p2;
1633 size_t len;
1634
1635 p1 = strrchr(argv[i], '\\');
1636 if (!p1) p1 = strrchr(argv[i], '/');
1637 p2 = p1 = p1 ? p1 + 1 : argv[i];
1638
1639 /* walk up to '.' */
1640 while (*p2 != '.' && *p2 != 0) p2++;
1641 len = p2 - p1;
1642 if (len >= sizeof(achDllName) - 5)
1643 {
1644 fprintf(stderr, "name too long: %s\n", p1);
1645 return -2;
1646 }
1647
1648 strncpy(achDllName, p1, len);
1649 strncpy(achDllName + len, ".dll", sizeof(achDllName) - len);
1650 pszDllName = achDllName;
1651 }
1652
1653 /* Open input file */
1656 if (!file)
1657 {
1658 fprintf(stderr, "error: could not open file %s\n", pszSourceFileName);
1659 return -3;
1660 }
1661
1662 /* Get file size */
1663 fseek(file, 0, SEEK_END);
1664 nFileSize = ftell(file);
1665 rewind(file);
1666
1667 /* Allocate memory buffer */
1668 pszSource = malloc(nFileSize + 1);
1669 if (!pszSource)
1670 {
1671 fclose(file);
1672 return -4;
1673 }
1674
1675 /* Load input file into memory */
1676 nFileSize = fread(pszSource, 1, nFileSize, file);
1677 fclose(file);
1678
1679 /* Zero terminate the source */
1680 pszSource[nFileSize] = '\0';
1681
1682 pexports = ParseFile(pszSource, file, &cExports);
1683 if (pexports == NULL)
1684 {
1685 fprintf(stderr, "error: could not parse file!\n");
1686 return -1;
1687 }
1688
1689 if (ApplyOrdinals(pexports, cExports) < 0)
1690 {
1691 fprintf(stderr, "error: could not apply ordinals!\n");
1692 return -1;
1693 }
1694
1695 if (pszDefFileName)
1696 {
1697 /* Open output file */
1698 file = fopen(pszDefFileName, "w");
1699 if (!file)
1700 {
1701 fprintf(stderr, "error: could not open output file %s\n", pszDefFileName);
1702 return -5;
1703 }
1704
1706
1707 for (i = 0; i < cExports; i++)
1708 {
1709 if (pexports[i].bVersionIncluded)
1710 OutputLine_def(file, &pexports[i]);
1711 }
1712
1713 fclose(file);
1714 }
1715
1716 if (pszStubFileName)
1717 {
1718 /* Open output file */
1719 file = fopen(pszStubFileName, "w");
1720 if (!file)
1721 {
1722 fprintf(stderr, "error: could not open output file %s\n", pszStubFileName);
1723 return -5;
1724 }
1725
1727
1728 for (i = 0; i < cExports; i++)
1729 {
1730 if (pexports[i].bVersionIncluded)
1731 OutputLine_stub(file, &pexports[i]);
1732 }
1733
1734 fclose(file);
1735 }
1736
1737 if (pszLibStubName)
1738 {
1739 /* Open output file */
1740 file = fopen(pszLibStubName, "w");
1741 if (!file)
1742 {
1743 fprintf(stderr, "error: could not open output file %s\n", pszLibStubName);
1744 return -5;
1745 }
1746
1748
1749 for (i = 0; i < cExports; i++)
1750 {
1751 if (pexports[i].bVersionIncluded)
1752 OutputLine_asmstub(file, &pexports[i]);
1753 }
1754
1755 fprintf(file, "\n END\n");
1756 fclose(file);
1757 }
1758
1759 if (pszImpLibAliasFileName)
1760 {
1761 /* Open output file */
1762 file = fopen(pszImpLibAliasFileName, "w");
1763 if (!file)
1764 {
1765 fprintf(stderr, "error: could not open output file %s\n", pszImpLibAliasFileName);
1766 return -5;
1767 }
1768
1770
1771 for (i = 0; i < cExports; i++)
1772 {
1773 if (pexports[i].bVersionIncluded)
1774 OutputLine_implib_asm(file, &pexports[i]);
1775 }
1776
1777 fprintf(file, "\n END\n");
1778 fclose(file);
1779 }
1780
1781 free(pexports);
1782
1783 return 0;
1784}
static int argc
Definition: ServiceArgs.c:12
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define SEEK_END
Definition: cabinet.c:29
#define strncasecmp
Definition: fake.h:10
#define strcasecmp
Definition: fake.h:9
_CRTIMP void __cdecl rewind(_Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP size_t __cdecl fread(_Out_writes_bytes_(_ElementSize *_Count) void *_DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fseek(_Inout_ FILE *_File, _In_ long _Offset, _In_ int _Origin)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP long __cdecl ftell(_Inout_ FILE *_File)
#define argv
Definition: mplay32.c:18
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
strncpy
Definition: string.h:335
unsigned guOsVersion
Definition: spec2def.c:77
void OutputHeader_stub(FILE *file)
Definition: spec2def.c:221
int OutputLine_stub(FILE *file, EXPORT *pexp)
Definition: spec2def.c:237
char * pszArchString2
Definition: spec2def.c:72
void OutputHeader_def(FILE *file, char *libname)
Definition: spec2def.c:532
char * pszSourceFileName
Definition: spec2def.c:73
int gbNotPrivateNoWarn
Definition: spec2def.c:67
char * pszDllName
Definition: spec2def.c:74
int giArch
Definition: spec2def.c:69
int gbMSComp
Definition: spec2def.c:65
void OutputHeader_asmstub(FILE *file, char *libname)
Definition: spec2def.c:436
int OutputLine_implib_asm(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:846
int gbDbgExports
Definition: spec2def.c:70
int ApplyOrdinals(EXPORT *pexports, unsigned cExports)
Definition: spec2def.c:1443
int gbImportLib
Definition: spec2def.c:66
char * pszArchString
Definition: spec2def.c:71
int OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:474
void usage(void)
Definition: spec2def.c:1506
int OutputLine_def(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:748
int gbTracing
Definition: spec2def.c:68
EXPORT * ParseFile(char *pcStart, FILE *fileDest, unsigned *cExports)
Definition: spec2def.c:927
char * gpszUnderscore
Definition: spec2def.c:75
Definition: fci.c:127

◆ NextLine()

const char * NextLine ( const char pc)

Definition at line 181 of file spec2def.c.

182{
183 while (*pc != 0)
184 {
185 if (pc[0] == '\n' && pc[1] == '\r') return pc + 2;
186 else if (pc[0] == '\n') return pc + 1;
187 pc++;
188 }
189 return pc;
190}

Referenced by ParseFile().

◆ NextToken()

const char * NextToken ( const char pc)

Definition at line 203 of file spec2def.c.

204{
205 /* Skip token */
206 while (!IsSeparator(*pc)) pc++;
207
208 /* Skip white spaces */
209 while (*pc == ' ' || *pc == '\t') pc++;
210
211 /* Check for end of line */
212 if (*pc == '\n' || *pc == '\r' || *pc == 0) return 0;
213
214 /* Check for comment */
215 if (*pc == '#' || *pc == ';') return 0;
216
217 return pc;
218}

Referenced by ParseFile().

◆ Output_stublabel()

void Output_stublabel ( FILE fileDest,
char pszSymbolName 
)

Definition at line 455 of file spec2def.c.

456{
457 if (giArch == ARCH_ARM || giArch == ARCH_ARM64)
458 {
459 fprintf(fileDest,
460 "\tEXPORT |%s| [FUNC]\n|%s|\n",
461 pszSymbolName,
462 pszSymbolName);
463 }
464 else
465 {
466 fprintf(fileDest,
467 "PUBLIC %s\n%s: nop\n",
468 pszSymbolName,
469 pszSymbolName);
470 }
471}

Referenced by OutputLine_asmstub().

◆ OutputAlias()

void OutputAlias ( FILE fileDest,
EXPORT pexp,
int  fImp 
)

Definition at line 823 of file spec2def.c.

824{
825 if ((giArch == ARCH_ARM) || (giArch == ARCH_ARM64))
826 {
827 fprintf(fileDest, " IMPORT ");
828 PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp);
829 fprintf(fileDest, ", WEAK ");
830 PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
831 fprintf(fileDest, "\n");
832 }
833 else
834 {
835 fprintf(fileDest, " EXTERN ");
836 PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
837 fprintf(fileDest, ":PROC\n ALIAS <");
838 PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp);
839 fprintf(fileDest, "> = <");
840 PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
841 fprintf(fileDest, ">\n");
842 }
843}
void PrintNameOrImpName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco, int fImp)
Definition: spec2def.c:812
STRING strName
Definition: spec2def.c:22
STRING strTarget
Definition: spec2def.c:23

Referenced by OutputLine_implib_asm().

◆ OutputHeader_asmstub()

void OutputHeader_asmstub ( FILE file,
char libname 
)

Definition at line 436 of file spec2def.c.

437{
438 fprintf(file, "; File generated automatically, do not edit!\n\n");
439
440 if (giArch == ARCH_X86)
441 {
442 fprintf(file, ".586\n.model flat\n.code\n");
443 }
444 else if (giArch == ARCH_AMD64)
445 {
446 fprintf(file, ".code\n");
447 }
448 else if (giArch == ARCH_ARM || giArch == ARCH_ARM64)
449 {
450 fprintf(file, " AREA |.text|,ALIGN=2,CODE,READONLY\n\n");
451 }
452}

Referenced by main().

◆ OutputHeader_def()

void OutputHeader_def ( FILE file,
char libname 
)

Definition at line 532 of file spec2def.c.

533{
535 "; File generated automatically, do not edit!\n\n"
536 "NAME %s\n\n"
537 "EXPORTS\n",
538 libname);
539}

Referenced by main().

◆ OutputHeader_stub()

void OutputHeader_stub ( FILE file)

Definition at line 221 of file spec2def.c.

222{
223 fprintf(file, "/* This file is autogenerated, do not edit. */\n\n"
224 "#include <stubs.h>\n");
225
226 if (gbTracing)
227 {
228 fprintf(file, "#include <wine/debug.h>\n");
229 fprintf(file, "#include <inttypes.h>\n");
230 fprintf(file, "WINE_DECLARE_DEBUG_CHANNEL(relay);\n");
231 }
232
233 fprintf(file, "\n");
234}

Referenced by main().

◆ OutputLine_asmstub()

int OutputLine_asmstub ( FILE fileDest,
EXPORT pexp 
)

Definition at line 474 of file spec2def.c.

475{
476 char szNameBuffer[128];
477
478 /* Handle autoname */
479 if (pexp->strName.len == 1 && pexp->strName.buf[0] == '@')
480 {
481 sprintf(szNameBuffer, "%s_stub_ordinal%d",
482 gpszUnderscore, pexp->nOrdinal);
483 }
484 else if (giArch != ARCH_X86)
485 {
486 /* Does the string already have stdcall decoration? */
487 const char *pcAt = ScanToken(pexp->strName.buf, '@');
488 if (pcAt && (pcAt < (pexp->strName.buf + pexp->strName.len)) &&
489 (pexp->strName.buf[0] == '_'))
490 {
491 /* Skip leading underscore and remove trailing decoration */
492 sprintf(szNameBuffer, "_stub_%.*s",
493 (int)(pcAt - pexp->strName.buf - 1),
494 pexp->strName.buf + 1);
495 }
496 else
497 {
498 sprintf(szNameBuffer, "_stub_%.*s",
499 pexp->strName.len, pexp->strName.buf);
500 }
501 }
502 else if (pexp->nCallingConvention == CC_STDCALL)
503 {
504 sprintf(szNameBuffer, "__stub_%.*s@%d",
505 pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
506 }
507 else if (pexp->nCallingConvention == CC_FASTCALL)
508 {
509 sprintf(szNameBuffer, "@_stub_%.*s@%d",
510 pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
511 }
512 else if ((pexp->nCallingConvention == CC_CDECL) ||
513 (pexp->nCallingConvention == CC_THISCALL) ||
514 (pexp->nCallingConvention == CC_EXTERN) ||
515 (pexp->nCallingConvention == CC_STUB))
516 {
517 sprintf(szNameBuffer, "__stub_%.*s",
518 pexp->strName.len, pexp->strName.buf);
519 }
520 else
521 {
522 fprintf(stderr, "Invalid calling convention");
523 return 0;
524 }
525
526 Output_stublabel(fileDest, szNameBuffer);
527
528 return 1;
529}
#define sprintf(buf, format,...)
Definition: sprintf.c:55
const char * ScanToken(const char *token, char chr)
Definition: spec2def.c:170
void Output_stublabel(FILE *fileDest, char *pszSymbolName)
Definition: spec2def.c:455
int nCallingConvention
Definition: spec2def.c:24
int nStackBytes
Definition: spec2def.c:26
const char * buf
Definition: spec2def.c:16
int len
Definition: spec2def.c:17

Referenced by main().

◆ OutputLine_def()

int OutputLine_def ( FILE fileDest,
EXPORT pexp 
)

Definition at line 748 of file spec2def.c.

749{
750 /* Don't add private exports to the import lib */
751 if (gbImportLib && (pexp->uFlags & FL_PRIVATE))
752 {
753 DbgPrint("OutputLine_def: skipping private export '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
754 return 1;
755 }
756
757 /* Handle import symbols */
758 if (pexp->uFlags & FL_IMPSYM)
759 {
760 /* Skip these, if we are not creating an import lib, or if this is MS */
761 if (!gbImportLib || gbMSComp)
762 {
763 DbgPrint("OutputLine_def: skipping import symbol '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
764 return 1;
765 }
766 }
767
768 /* For MS linker, forwarded externs are managed via #pragma comment(linker,"/export:_data=org.data,DATA") */
769 if (gbMSComp && !gbImportLib && (pexp->nCallingConvention == CC_EXTERN) &&
770 (pexp->strTarget.buf != NULL) && !!ScanToken(pexp->strTarget.buf, '.'))
771 {
772 DbgPrint("OutputLine_def: skipping forwarded extern export '%.*s' ->'%.*s'...\n",
773 pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
774 return 1;
775 }
776
777 DbgPrint("OutputLine_def: '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
778 fprintf(fileDest, " ");
779
780 if (gbMSComp)
781 OutputLine_def_MS(fileDest, pexp);
782 else
783 OutputLine_def_GCC(fileDest, pexp);
784
785 /* If it is not an import lib, we force ordinals */
786 if ((pexp->uFlags & FL_ORDINAL) || !gbImportLib)
787 {
788 fprintf(fileDest, " @%d", pexp->nOrdinal);
789 }
790
791 if (pexp->uFlags & FL_NONAME)
792 {
793 fprintf(fileDest, " NONAME");
794 }
795
796 /* Either PRIVATE or DATA */
797 if (pexp->uFlags & FL_PRIVATE)
798 {
799 fprintf(fileDest, " PRIVATE");
800 }
801 else if (pexp->nCallingConvention == CC_EXTERN)
802 {
803 fprintf(fileDest, " DATA");
804 }
805
806 fprintf(fileDest, "\n");
807
808 return 1;
809}
#define DbgPrint(...)
Definition: spec2def.c:78
void OutputLine_def_MS(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:630
void OutputLine_def_GCC(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:681
unsigned int uFlags
Definition: spec2def.c:29

Referenced by main().

◆ OutputLine_def_GCC()

void OutputLine_def_GCC ( FILE fileDest,
EXPORT pexp 
)

Definition at line 681 of file spec2def.c.

682{
683 int bTracing = 0;
684 /* Print the function name, with decoration for export libs */
685 PrintName(fileDest, pexp, &pexp->strName, gbImportLib);
686 DbgPrint("Generating def line for '%.*s'\n", pexp->strName.len, pexp->strName.buf);
687
688 /* Check if this is a forwarded export */
689 if (pexp->strTarget.buf)
690 {
691 int fIsExternal = !!ScanToken(pexp->strTarget.buf, '.');
692 DbgPrint("Got redirect '%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf);
693
694 /* print the target name, don't decorate if it is external */
695 fprintf(fileDest, pexp->uFlags & FL_IMPSYM ? "==" : "=");
696 PrintName(fileDest, pexp, &pexp->strTarget, !fIsExternal);
697 }
698 else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
699 (pexp->strName.buf[0] == '?'))
700 {
701 /* C++ stubs are forwarded to C stubs */
702 fprintf(fileDest, "=stub_function%d", pexp->nNumber);
703 }
704 else if (gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) &&
705 (pexp->nCallingConvention == CC_STDCALL) &&
706 (pexp->strName.buf[0] != '?'))
707 {
708 /* Redirect it to the relay-tracing trampoline */
709 char buf[256];
710 STRING strTarget;
711 fprintf(fileDest, "=");
712 sprintf(buf, "$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
713 strTarget.buf = buf;
714 strTarget.len = pexp->strName.len + 12;
715 PrintName(fileDest, pexp, &strTarget, 1);
716 bTracing = 1;
717 }
718
719 /* Special handling for stdcall and fastcall, but not C++ exports*/
720 if ((giArch == ARCH_X86) &&
721 (pexp->strName.buf[0] != '?') &&
722 ((pexp->nCallingConvention == CC_STDCALL) ||
724 {
725 /* Is this the import lib? */
726 if (gbImportLib)
727 {
728 /* Is the name in the spec file decorated? */
729 const char* pcDeco = ScanToken(pexp->strName.buf, '@');
730 if (pcDeco &&
731 (pexp->strName.len > 1) &&
732 (pcDeco < pexp->strName.buf + pexp->strName.len))
733 {
734 /* Write the name including the leading @ */
735 fprintf(fileDest, "==%.*s", pexp->strName.len, pexp->strName.buf);
736 }
737 }
738 else if ((!pexp->strTarget.buf) && !(bTracing))
739 {
740 /* Write a forwarder to the actual decorated symbol */
741 fprintf(fileDest, "=");
742 PrintName(fileDest, pexp, &pexp->strName, 1);
743 }
744 }
745}
std::wstring STRING
Definition: fontsub.cpp:33
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
void PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
Definition: spec2def.c:542
int nNumber
Definition: spec2def.c:30

Referenced by OutputLine_def().

◆ OutputLine_def_MS()

void OutputLine_def_MS ( FILE fileDest,
EXPORT pexp 
)

Definition at line 630 of file spec2def.c.

631{
632 PrintName(fileDest, pexp, &pexp->strName, 0);
633
634 if (gbImportLib)
635 {
636 /* Redirect to a stub function, to get the right decoration in the lib */
637 fprintf(fileDest, "=_stub_");
638 PrintName(fileDest, pexp, &pexp->strName, 0);
639 }
640 else if (pexp->strTarget.buf)
641 {
642 if (pexp->strName.buf[0] == '?')
643 {
644 //fprintf(stderr, "warning: ignoring C++ redirection %.*s -> %.*s\n",
645 // pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
646 }
647 else
648 {
649 fprintf(fileDest, "=");
650
651 /* If the original name was decorated, use decoration in the forwarder as well */
652 if ((giArch == ARCH_X86) && ScanToken(pexp->strName.buf, '@') &&
653 !ScanToken(pexp->strTarget.buf, '@') &&
654 ((pexp->nCallingConvention == CC_STDCALL) ||
655 (pexp->nCallingConvention == CC_FASTCALL)) )
656 {
657 PrintName(fileDest, pexp, &pexp->strTarget, 1);
658 }
659 else
660 {
661 /* Write the undecorated redirection name */
662 fprintf(fileDest, "%.*s", pexp->strTarget.len, pexp->strTarget.buf);
663 }
664 }
665 }
666 else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
667 (pexp->strName.buf[0] == '?'))
668 {
669 /* C++ stubs are forwarded to C stubs */
670 fprintf(fileDest, "=stub_function%d", pexp->nNumber);
671 }
672 else if (gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CC_STDCALL) &&
673 (pexp->strName.buf[0] != '?'))
674 {
675 /* Redirect it to the relay-tracing trampoline */
676 fprintf(fileDest, "=$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
677 }
678}

Referenced by OutputLine_def().

◆ OutputLine_implib_asm()

int OutputLine_implib_asm ( FILE fileDest,
EXPORT pexp 
)

Definition at line 846 of file spec2def.c.

847{
848 if ((pexp->uFlags & FL_IMPSYM) == 0)
849 {
850 return 1;
851 }
852
853 OutputAlias(fileDest, pexp, 0);
854 OutputAlias(fileDest, pexp, 1);
855
856 return 1;
857}
void OutputAlias(FILE *fileDest, EXPORT *pexp, int fImp)
Definition: spec2def.c:823

Referenced by main().

◆ OutputLine_stub()

int OutputLine_stub ( FILE file,
EXPORT pexp 
)

Definition at line 237 of file spec2def.c.

238{
239 int i;
240 int bRelay = 0;
241 int bInPrototype = 0;
242
243 /* Workaround for forwarded externs. See here for an explanation:
244 * https://stackoverflow.com/questions/4060143/forwarding-data-in-a-dll */
245 if (gbMSComp &&
246 (pexp->nCallingConvention == CC_EXTERN) &&
247 (pexp->strTarget.buf != NULL) &&
248 (!!ScanToken(pexp->strTarget.buf, '.')))
249 {
250 fprintf(file, "#pragma comment(linker,\"/export:%s%.*s=%.*s,DATA\")\n\n",
251 gpszUnderscore, pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
252 return 0;
253 }
254
255 if (pexp->nCallingConvention != CC_STUB &&
256 (pexp->uFlags & FL_STUB) == 0)
257 {
258 /* Only relay trace stdcall C functions */
259 if (!gbTracing || (pexp->nCallingConvention != CC_STDCALL)
260 || (pexp->uFlags & FL_NORELAY)
261 || (pexp->strName.buf[0] == '?'))
262 {
263 return 0;
264 }
265 bRelay = 1;
266 }
267
268 /* Declare the "real" function */
269 if (bRelay)
270 {
271 fprintf(file, "extern ");
272 bInPrototype = 1;
273 }
274
275 do
276 {
277 if (pexp->uFlags & FL_REGISTER)
278 {
279 /* FIXME: Not sure this is right */
280 fprintf(file, "void ");
281 }
282 else if (pexp->uFlags & FL_RET64)
283 {
284 fprintf(file, "__int64 ");
285 }
286 else
287 {
288 fprintf(file, "int ");
289 }
290
291 if ((giArch == ARCH_X86) &&
293 {
294 fprintf(file, "__stdcall ");
295 }
296
297 /* Check for C++ */
298 if (pexp->strName.buf[0] == '?')
299 {
300 fprintf(file, "stub_function%d(", pexp->nNumber);
301 }
302 else
303 {
304 if (!bRelay || bInPrototype)
305 fprintf(file, "%.*s(", pexp->strName.len, pexp->strName.buf);
306 else
307 fprintf(file, "$relaytrace$%.*s(", pexp->strName.len, pexp->strName.buf);
308 }
309
310 for (i = 0; i < pexp->nArgCount; i++)
311 {
312 if (i != 0) fprintf(file, ", ");
313 switch (pexp->anArgs[i])
314 {
315 case ARG_LONG: fprintf(file, "long"); break;
316 case ARG_PTR: fprintf(file, "void*"); break;
317 case ARG_STR: fprintf(file, "char*"); break;
318 case ARG_WSTR: fprintf(file, "wchar_t*"); break;
319 case ARG_DBL: fprintf(file, "double"); break;
320 case ARG_INT64: fprintf(file, "__int64"); break;
321 /* __int128 is not supported on x86, so use a custom type */
322 case ARG_INT128: fprintf(file, "MyInt128"); break;
323 case ARG_FLOAT: fprintf(file, "float"); break;
324 }
325 fprintf(file, " a%d", i);
326 }
327
328 if (bInPrototype)
329 {
330 fprintf(file, ");\n\n");
331 }
332 } while (bInPrototype--);
333
334 if (!bRelay)
335 {
336 fprintf(file, ")\n{\n\tDbgPrint(\"WARNING: calling stub %.*s(",
337 pexp->strName.len, pexp->strName.buf);
338 }
339 else
340 {
341 fprintf(file, ")\n{\n");
342 if (pexp->uFlags & FL_REGISTER)
343 {
344 /* No return value */
345 }
346 else if (pexp->uFlags & FL_RET64)
347 {
348 fprintf(file, "\t__int64 retval;\n");
349 }
350 else
351 {
352 fprintf(file, "\tint retval;\n");
353 }
354 fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s(",
355 pszDllName, pexp->strName.len, pexp->strName.buf);
356 }
357
358 for (i = 0; i < pexp->nArgCount; i++)
359 {
360 if (i != 0) fprintf(file, ",");
361 switch (pexp->anArgs[i])
362 {
363 case ARG_LONG: fprintf(file, "0x%%lx"); break;
364 case ARG_PTR: fprintf(file, "0x%%p"); break;
365 case ARG_STR: fprintf(file, "'%%s'"); break;
366 case ARG_WSTR: fprintf(file, "'%%ws'"); break;
367 case ARG_DBL: fprintf(file, "%%f"); break;
368 case ARG_INT64: fprintf(file, "0x%%\"PRIx64\""); break;
369 case ARG_INT128: fprintf(file, "0x%%\"PRIx64\"-0x%%\"PRIx64\""); break;
370 case ARG_FLOAT: fprintf(file, "%%f"); break;
371 }
372 }
373 fprintf(file, ")\\n\"");
374
375 for (i = 0; i < pexp->nArgCount; i++)
376 {
377 fprintf(file, ", ");
378 switch (pexp->anArgs[i])
379 {
380 case ARG_LONG: case ARG_PTR: case ARG_STR:
381 case ARG_WSTR: case ARG_DBL: case ARG_INT64:
382 fprintf(file, "a%d", i); break;
383 case ARG_INT128:
384 fprintf(file, "a%d.lower, a%d.upper", i, i); break;
385 case ARG_FLOAT:
386 fprintf(file, "a%d", i); break;
387 }
388 }
389 fprintf(file, ");\n");
390
391 if (pexp->nCallingConvention == CC_STUB)
392 {
393 fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName);
394 }
395 else if (bRelay)
396 {
397 if (pexp->uFlags & FL_REGISTER)
398 {
399 fprintf(file,"\t");
400 }
401 else
402 {
403 fprintf(file, "\tretval = ");
404 }
405 fprintf(file, "%.*s(", pexp->strName.len, pexp->strName.buf);
406
407 for (i = 0; i < pexp->nArgCount; i++)
408 {
409 if (i != 0) fprintf(file, ", ");
410 fprintf(file, "a%d", i);
411 }
412 fprintf(file, ");\n");
413 }
414
415 if (!bRelay)
416 fprintf(file, "\treturn 0;\n}\n\n");
417 else if ((pexp->uFlags & FL_REGISTER) == 0)
418 {
419 if (pexp->uFlags & FL_RET64)
420 {
421 fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s: retval = 0x%%\"PRIx64\"\\n\", retval);\n",
422 pszDllName, pexp->strName.len, pexp->strName.buf);
423 }
424 else
425 {
426 fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s: retval = 0x%%lx\\n\", retval);\n",
427 pszDllName, pexp->strName.len, pexp->strName.buf);
428 }
429 fprintf(file, "\treturn retval;\n}\n\n");
430 }
431
432 return 1;
433}
int anArgs[30]
Definition: spec2def.c:28
int nArgCount
Definition: spec2def.c:27

Referenced by main().

◆ ParseFile()

EXPORT * ParseFile ( char pcStart,
FILE fileDest,
unsigned cExports 
)

Definition at line 927 of file spec2def.c.

928{
929 EXPORT *pexports;
930 const char *pc, *pcLine;
931 int cLines, nLine;
932 EXPORT exp;
933 int included;
934 unsigned int i;
935
936 *cExports = 0;
937
938 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
939
940 /* Count the lines */
941 for (cLines = 1, pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), cLines++)
942 {
943 /* Nothing */
944 }
945
946 /* Allocate an array of EXPORT structures */
947 pexports = malloc(cLines * sizeof(EXPORT));
948 if (pexports == NULL)
949 {
950 fprintf(stderr, "ERROR: %s: failed to allocate EXPORT array of %u elements\n", pszSourceFileName, cLines);
951 return NULL;
952 }
953
954 /* Loop all lines */
955 nLine = 1;
956 exp.nNumber = 0;
957 for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
958 {
959 pc = pcLine;
960
961 exp.strName.buf = NULL;
962 exp.strName.len = 0;
963 exp.strTarget.buf = NULL;
964 exp.strTarget.len = 0;
965 exp.nArgCount = 0;
966 exp.uFlags = 0;
967 exp.nNumber++;
968 exp.nStartVersion = 0;
969 exp.nEndVersion = 0xFFFFFFFF;
970 exp.bVersionIncluded = 1;
971
972 /* Skip white spaces */
973 while (*pc == ' ' || *pc == '\t') pc++;
974
975 /* Check for line break or comment */
976 if ((*pc == '\r') || (*pc == '\n') ||
977 (*pc == ';') || (*pc == '#'))
978 {
979 continue;
980 }
981
982 /* On EOF we are done */
983 if (*pc == 0)
984 {
985 return pexports;
986 }
987
988 /* Now we should get either an ordinal or @ */
989 if (*pc == '@')
990 {
991 exp.nOrdinal = -1;
992 }
993 else if ((*pc >= '0') && (*pc <= '9'))
994 {
995 char* end;
996 long int number = strtol(pc, &end, 10);
997 if ((*end != ' ') && (*end != '\t'))
998 {
999 Fatal(pszSourceFileName, nLine, pcLine, end, 0, "Unexpected character(s) after ordinal");
1000 }
1001
1002 if ((number < 0) || (number > 0xFFFE))
1003 {
1004 Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Invalid value for ordinal");
1005 }
1006
1007 exp.nOrdinal = number;
1008
1009 /* The import lib should contain the ordinal only if -ordinal was specified */
1010 if (!gbImportLib)
1011 exp.uFlags |= FL_ORDINAL;
1012 }
1013 else
1014 {
1015 Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Expected '@' or ordinal");
1016 }
1017
1018 /* Go to next token (type) */
1019 if (!(pc = NextToken(pc)))
1020 {
1021 Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1022 }
1023
1024 //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
1025
1026 /* Now we should get the type */
1027 if (CompareToken(pc, "stdcall"))
1028 {
1029 exp.nCallingConvention = CC_STDCALL;
1030 }
1031 else if (CompareToken(pc, "cdecl") ||
1032 CompareToken(pc, "varargs"))
1033 {
1034 exp.nCallingConvention = CC_CDECL;
1035 }
1036 else if (CompareToken(pc, "fastcall"))
1037 {
1038 exp.nCallingConvention = CC_FASTCALL;
1039 }
1040 else if (CompareToken(pc, "thiscall"))
1041 {
1042 exp.nCallingConvention = CC_THISCALL;
1043 }
1044 else if (CompareToken(pc, "extern"))
1045 {
1046 exp.nCallingConvention = CC_EXTERN;
1047 }
1048 else if (CompareToken(pc, "stub"))
1049 {
1050 exp.nCallingConvention = CC_STUB;
1051 }
1052 else
1053 {
1054 Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Invalid calling convention");
1055 }
1056
1057 /* Go to next token (options or name) */
1058 if (!(pc = NextToken(pc)))
1059 {
1060 Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1061 }
1062
1063 /* Handle options */
1064 included = 1;
1065 while (*pc == '-')
1066 {
1067 if (CompareToken(pc, "-arch="))
1068 {
1069 /* Default to not included */
1070 included = 0;
1071 pc += 5;
1072
1073 /* Look if we are included */
1074 do
1075 {
1076 int negated = 0, match = 0;
1077
1078 pc++;
1079
1080 /* Check for negated case */
1081 if (*pc == '!')
1082 {
1083 negated = 1;
1084 pc++;
1085 }
1086
1087 if (CompareToken(pc, pszArchString) ||
1089 {
1090 match = 1;
1091 }
1092
1093 if (match != negated)
1094 {
1095 included = 1;
1096 }
1097
1098 /* Skip to next arch or end */
1099 while (*pc > ',') pc++;
1100 } while (*pc == ',');
1101 }
1102 else if (CompareToken(pc, "-i386"))
1103 {
1104 if (giArch != ARCH_X86) included = 0;
1105 }
1106 else if (CompareToken(pc, "-version="))
1107 {
1108 const char *pcVersionStart = pc + 9;
1109
1110 /* Default to not included */
1111 exp.bVersionIncluded = 0;
1112 pc += 8;
1113
1114 /* Look if we are included */
1115 do
1116 {
1117 unsigned version, endversion;
1118
1119 /* Optionally skip leading '0x' */
1120 pc++;
1121 if ((pc[0] == '0') && (pc[1] == 'x')) pc += 2;
1122
1123 /* Now get the version number */
1124 endversion = version = strtoul(pc, (char**)&pc, 16);
1125
1126 /* Check if it's a range */
1127 if (pc[0] == '+')
1128 {
1129 endversion = 0xFFF;
1130 pc++;
1131 }
1132 else if (pc[0] == '-')
1133 {
1134 /* Optionally skip leading '0x' */
1135 pc++;
1136 if ((pc[0] == '0') && (pc[1] == 'x')) pc += 2;
1137 endversion = strtoul(pc, (char**)&pc, 16);
1138 }
1139
1140 /* Check for degenerate range */
1141 if (version > endversion)
1142 {
1144 nLine,
1145 pcLine,
1146 pcVersionStart,
1147 pc - pcVersionStart,
1148 "Invalid version range");
1149 }
1150
1151 exp.nStartVersion = version;
1152 exp.nEndVersion = endversion;
1153
1154 /* Now compare the range with our version */
1155 if ((guOsVersion >= version) &&
1156 (guOsVersion <= endversion))
1157 {
1158 exp.bVersionIncluded = 1;
1159 }
1160
1161 /* Skip to next arch or end */
1162 while (*pc > ',') pc++;
1163
1164 } while (*pc == ',');
1165 }
1166 else if (CompareToken(pc, "-dbg"))
1167 {
1168 if (!gbDbgExports)
1169 {
1170 included = 0;
1171 }
1172 }
1173 else if (CompareToken(pc, "-private"))
1174 {
1175 exp.uFlags |= FL_PRIVATE;
1176 }
1177 else if (CompareToken(pc, "-noname"))
1178 {
1179 exp.uFlags |= FL_ORDINAL | FL_NONAME;
1180 }
1181 else if (CompareToken(pc, "-impsym"))
1182 {
1183 exp.uFlags |= FL_IMPSYM;
1184 }
1185 else if (CompareToken(pc, "-ordinal"))
1186 {
1187 exp.uFlags |= FL_ORDINAL;
1188 /* GCC doesn't automatically import by ordinal if an ordinal
1189 * is found in the def file. Force it. */
1190 if (gbImportLib && !gbMSComp)
1191 exp.uFlags |= FL_NONAME;
1192 }
1193 else if (CompareToken(pc, "-stub"))
1194 {
1195 exp.uFlags |= FL_STUB;
1196 }
1197 else if (CompareToken(pc, "-norelay"))
1198 {
1199 exp.uFlags |= FL_NORELAY;
1200 }
1201 else if (CompareToken(pc, "-ret64"))
1202 {
1203 exp.uFlags |= FL_RET64;
1204 }
1205 else if (CompareToken(pc, "-register"))
1206 {
1207 exp.uFlags |= FL_REGISTER;
1208 }
1209 else
1210 {
1212 "INFO: %s line %d: Ignored option: '%.*s'\n",
1214 nLine,
1215 TokenLength(pc),
1216 pc);
1217 }
1218
1219 /* Go to next token */
1220 pc = NextToken(pc);
1221 }
1222
1223 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
1224
1225 /* If arch didn't match ours, skip this entry */
1226 if (!included) continue;
1227
1228 /* Get name */
1229 exp.strName.buf = pc;
1230 exp.strName.len = TokenLength(pc);
1231 //DbgPrint("Got name: '%.*s'\n", exp.strName.len, exp.strName.buf);
1232
1233 /* Check for autoname */
1234 if ((exp.strName.len == 1) && (exp.strName.buf[0] == '@'))
1235 {
1236 exp.uFlags |= FL_ORDINAL | FL_NONAME;
1237 }
1238
1239 /* Handle parameters */
1240 exp.nStackBytes = 0;
1241 pc = NextToken(pc);
1242 /* Extern can't have parameters, and it's optional to provide ones for stubs. All other exports must have them */
1243 if (!pc && (exp.nCallingConvention != CC_EXTERN && exp.nCallingConvention != CC_STUB))
1244 {
1245 Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1246 }
1247
1248 if (pc && (exp.nCallingConvention != CC_EXTERN))
1249 {
1250 /* Verify syntax */
1251 if (*pc++ != '(')
1252 {
1253 Fatal(pszSourceFileName, nLine, pcLine, pc - 1, 0, "Expected '('");
1254 }
1255
1256 /* Skip whitespaces */
1257 while (*pc == ' ' || *pc == '\t') pc++;
1258
1259 exp.nStackBytes = 0;
1260 while (*pc >= '0')
1261 {
1262 if (CompareToken(pc, "long"))
1263 {
1264 exp.nStackBytes += 4;
1265 exp.anArgs[exp.nArgCount] = ARG_LONG;
1266 }
1267 else if (CompareToken(pc, "double"))
1268 {
1269 exp.nStackBytes += 8;
1270 exp.anArgs[exp.nArgCount] = ARG_DBL;
1271 }
1272 else if (CompareToken(pc, "ptr"))
1273 {
1274 exp.nStackBytes += 4; // sizeof(void*) on x86
1275 exp.anArgs[exp.nArgCount] = ARG_PTR;
1276 }
1277 else if (CompareToken(pc, "str"))
1278 {
1279 exp.nStackBytes += 4; // sizeof(void*) on x86
1280 exp.anArgs[exp.nArgCount] = ARG_STR;
1281 }
1282 else if (CompareToken(pc, "wstr"))
1283 {
1284 exp.nStackBytes += 4; // sizeof(void*) on x86
1285 exp.anArgs[exp.nArgCount] = ARG_WSTR;
1286 }
1287 else if (CompareToken(pc, "int64"))
1288 {
1289 exp.nStackBytes += 8;
1290 exp.anArgs[exp.nArgCount] = ARG_INT64;
1291 }
1292 else if (CompareToken(pc, "int128"))
1293 {
1294 exp.nStackBytes += 16;
1295 exp.anArgs[exp.nArgCount] = ARG_INT128;
1296 }
1297 else if (CompareToken(pc, "float"))
1298 {
1299 exp.nStackBytes += 4;
1300 exp.anArgs[exp.nArgCount] = ARG_FLOAT;
1301 }
1302 else
1303 {
1304 Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Unrecognized type");
1305 }
1306
1307 exp.nArgCount++;
1308
1309 /* Go to next parameter */
1310 if (!(pc = NextToken(pc)))
1311 {
1312 Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1313 }
1314 }
1315
1316 /* Check syntax */
1317 if (*pc++ != ')')
1318 {
1319 Fatal(pszSourceFileName, nLine, pcLine, pc - 1, 0, "Expected ')'");
1320 }
1321
1322 /* Go to next token */
1323 pc = NextToken(pc);
1324 }
1325
1326 /* Handle special stub cases */
1327 if (exp.nCallingConvention == CC_STUB)
1328 {
1329 /* If we got parameters, assume STDCALL */
1330 if (exp.nArgCount != 0)
1331 {
1332 exp.nCallingConvention = CC_STDCALL;
1333 exp.uFlags |= FL_STUB;
1334 }
1335
1336 /* Check for c++ mangled name */
1337 if (exp.strName.buf[0] == '?')
1338 {
1339 //printf("Found c++ mangled name...\n");
1340 //
1341 }
1342 else
1343 {
1344 /* Check for stdcall name */
1345 const char *p = ScanToken(exp.strName.buf, '@');
1346 if (p && (p - exp.strName.buf < exp.strName.len))
1347 {
1348 int i;
1349
1350 /* Truncate the name to before the @ */
1351 exp.strName.len = (int)(p - exp.strName.buf);
1352 if (exp.strName.len < 1)
1353 {
1354 Fatal(pszSourceFileName, nLine, pcLine, p, 1, "Unexpected @");
1355 }
1356 exp.nStackBytes = atoi(p + 1);
1357 exp.nArgCount = exp.nStackBytes / 4;
1358 exp.nCallingConvention = CC_STDCALL;
1359 exp.uFlags |= FL_STUB;
1360 for (i = 0; i < exp.nArgCount; i++)
1361 exp.anArgs[i] = ARG_LONG;
1362 }
1363 }
1364 }
1365
1366 /* Check optional redirection */
1367 if (pc)
1368 {
1369 exp.strTarget.buf = pc;
1370 exp.strTarget.len = TokenLength(pc);
1371
1372 /* Check syntax (end of line) */
1373 if (NextToken(pc))
1374 {
1375 Fatal(pszSourceFileName, nLine, pcLine, NextToken(pc), 0, "Excess token(s) at end of definition");
1376 }
1377
1378 /* Don't relay-trace forwarded functions */
1379 exp.uFlags |= FL_NORELAY;
1380 }
1381 else
1382 {
1383 exp.strTarget.buf = NULL;
1384 exp.strTarget.len = 0;
1385 }
1386
1387 /* Check for no-name without ordinal */
1388 if ((exp.uFlags & FL_ORDINAL) && (exp.nOrdinal == -1))
1389 {
1390 Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Ordinal export without ordinal");
1391 }
1392
1393 /* Check for import symbol without target */
1394 if ((exp.uFlags & FL_IMPSYM) && (exp.strTarget.buf == NULL))
1395 {
1396 Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Import symbol without target");
1397 }
1398
1399 /*
1400 * Check for special handling of OLE exports, only when MSVC
1401 * is not used, since otherwise this is handled by MS LINK.EXE.
1402 */
1403 if (!gbMSComp)
1404 {
1405 /* Check whether the current export is not PRIVATE, or has an ordinal */
1406 int bIsNotPrivate = (!gbNotPrivateNoWarn && /*gbImportLib &&*/ !(exp.uFlags & FL_PRIVATE));
1407 int bHasOrdinal = (exp.uFlags & FL_ORDINAL);
1408
1409 /* Check whether the current export is an OLE export, in case any of these tests pass */
1410 if (bIsNotPrivate || bHasOrdinal)
1411 {
1412 for (i = 0; i < ARRAYSIZE(astrOlePrivateExports); ++i)
1413 {
1414 if (strlen(astrOlePrivateExports[i]) == exp.strName.len &&
1415 strncmp(exp.strName.buf, astrOlePrivateExports[i], exp.strName.len) == 0)
1416 {
1417 /* The current export is an OLE export: display the corresponding warning */
1418 if (bIsNotPrivate)
1419 {
1420 fprintf(stderr, "WARNING: %s line %d: Exported symbol '%.*s' should be PRIVATE\n",
1421 pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
1422 }
1423 if (bHasOrdinal)
1424 {
1425 fprintf(stderr, "WARNING: %s line %d: exported symbol '%.*s' should not be assigned an ordinal\n",
1426 pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
1427 }
1428 break;
1429 }
1430 }
1431 }
1432 }
1433
1434 pexports[*cExports] = exp;
1435 (*cExports)++;
1436 gbDebug = 0;
1437 }
1438
1439 return pexports;
1440}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static const WCHAR version[]
Definition: asmname.c:66
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
GLuint GLuint end
Definition: gl.h:1545
GLfloat GLfloat p
Definition: glext.h:8902
#define stdout
Definition: stdio.h:99
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
static unsigned int number
Definition: dsound.c:1479
DWORD exp
Definition: msg.c:16058
const char * NextLine(const char *pc)
Definition: spec2def.c:181
int gbDebug
Definition: spec2def.c:76
const char * NextToken(const char *pc)
Definition: spec2def.c:203
void Fatal(const char *filename, unsigned nLine, const char *pcLine, const char *pc, size_t errorlen, const char *format,...)
Definition: spec2def.c:910
int CompareToken(const char *token, const char *comparand)
Definition: spec2def.c:156
static const char * astrOlePrivateExports[]
Definition: spec2def.c:128
#define ARRAYSIZE(a)
Definition: spec2def.c:12
Definition: match.c:28

Referenced by main().

◆ PrintName()

void PrintName ( FILE fileDest,
EXPORT pexp,
PSTRING  pstr,
int  fDeco 
)

Definition at line 542 of file spec2def.c.

543{
544 const char *pcName = pstr->buf;
545 int nNameLength = pstr->len;
546 const char* pcDot, *pcAt;
547 char namebuffer[19];
548
549 if ((nNameLength == 1) && (pcName[0] == '@'))
550 {
551 sprintf(namebuffer, "ordinal%d", pexp->nOrdinal);
552 pcName = namebuffer;
553 nNameLength = strlen(namebuffer);
554 }
555
556 /* Check for non-x86 first */
557 if (giArch != ARCH_X86)
558 {
559 /* Does the string already have stdcall decoration? */
560 pcAt = ScanToken(pcName, '@');
561 if (pcAt && (pcAt < (pcName + nNameLength)) && (pcName[0] == '_'))
562 {
563 /* Skip leading underscore and remove trailing decoration */
564 pcName++;
565 nNameLength = (int)(pcAt - pcName);
566 }
567
568 /* Print the undecorated function name */
569 fprintf(fileDest, "%.*s", nNameLength, pcName);
570 }
571 else if (fDeco &&
572 ((pexp->nCallingConvention == CC_STDCALL) ||
574 {
575 /* Beware with C++ exports */
576 int is_cpp = pcName[0] == '?';
577
578 /* Scan for a dll forwarding dot */
579 pcDot = ScanToken(pcName, '.');
580 if (pcDot)
581 {
582 /* First print the dll name, followed by a dot */
583 nNameLength = (int)(pcDot - pcName);
584 fprintf(fileDest, "%.*s.", nNameLength, pcName);
585
586 /* Now the actual function name */
587 pcName = pcDot + 1;
588 nNameLength = pexp->strTarget.len - nNameLength - 1;
589 }
590
591 /* Does the string already have decoration? */
592 pcAt = ScanToken(pcName, '@');
593 if (pcAt && (pcAt < (pcName + nNameLength)))
594 {
595 /* On GCC, we need to remove the leading stdcall underscore, but not for C++ exports */
596 if (!gbMSComp && !is_cpp && (pexp->nCallingConvention == CC_STDCALL))
597 {
598 pcName++;
599 nNameLength--;
600 }
601
602 /* Print the already decorated function name */
603 fprintf(fileDest, "%.*s", nNameLength, pcName);
604 }
605 else
606 {
607 /* Print the prefix, but skip it for (GCC && stdcall) */
608 if (gbMSComp || (pexp->nCallingConvention != CC_STDCALL))
609 {
610 fprintf(fileDest, "%c", pexp->nCallingConvention == CC_FASTCALL ? '@' : '_');
611 }
612
613 /* Print the name with trailing decoration */
614 fprintf(fileDest, "%.*s@%d", nNameLength, pcName, pexp->nStackBytes);
615 }
616 }
617 else if (fDeco && (pexp->nCallingConvention == CC_CDECL) && gbMSComp)
618 {
619 /* Print with cdecl decoration */
620 fprintf(fileDest, "_%.*s", nNameLength, pcName);
621 }
622 else
623 {
624 /* Print the undecorated function name */
625 fprintf(fileDest, "%.*s", nNameLength, pcName);
626 }
627}

Referenced by OutputLine_def_GCC(), OutputLine_def_MS(), PrintNameOrImpName(), and Defragment::Start().

◆ PrintNameOrImpName()

void PrintNameOrImpName ( FILE fileDest,
EXPORT pexp,
PSTRING  pstr,
int  fDeco,
int  fImp 
)

Definition at line 812 of file spec2def.c.

813{
814 if (fImp)
815 {
816 fprintf(fileDest, "__imp_");
817 }
818
819 PrintName(fileDest, pexp, pstr, fDeco);
820}

Referenced by OutputAlias().

◆ ScanToken()

const char * ScanToken ( const char token,
char  chr 
)

Definition at line 170 of file spec2def.c.

171{
172 while (!IsSeparator(*token))
173 {
174 if (*token == chr) return token;
175 token++;
176 }
177 return 0;
178}

Referenced by OutputLine_asmstub(), OutputLine_def(), OutputLine_def_GCC(), OutputLine_def_MS(), OutputLine_stub(), ParseFile(), and PrintName().

◆ TokenLength()

int TokenLength ( const char pc)

Definition at line 193 of file spec2def.c.

194{
195 int length = 0;
196
197 while (!IsSeparator(*pc++)) length++;
198
199 return length;
200}
GLuint GLsizei GLsizei * length
Definition: glext.h:6040

Referenced by Fatalv(), ParseFile(), and SmpParseToken().

◆ usage()

void usage ( void  )

Definition at line 1506 of file spec2def.c.

1507{
1508 printf("syntax: spec2def [<options> ...] <spec file>\n"
1509 "Possible options:\n"
1510 " -h --help print this help screen\n"
1511 " -l=<file> generate an asm lib stub\n"
1512 " -d=<file> generate a def file\n"
1513 " -s=<file> generate a stub file\n"
1514 " -i=<file> generate an import alias file\n"
1515 " --ms MSVC compatibility\n"
1516 " --dbg Enable debug exports\n"
1517 " -n=<name> name of the dll\n"
1518 " --version=<version> Sets the version to create exports for\n"
1519 " --implib generate a def file for an import library\n"
1520 " --no-private-warnings suppress warnings about symbols that should be -private\n"
1521 " -a=<arch> set architecture to <arch> (i386, x86_64, arm, arm64)\n"
1522 " --with-tracing generate wine-like \"+relay\" trace trampolines (needs -s)\n");
1523}
#define printf
Definition: freeldr.h:97

Referenced by main().

Variable Documentation

◆ astrCallingConventions

const char* astrCallingConventions[]
Initial value:
=
{
"STDCALL",
"CDECL",
"FASTCALL",
"THISCALL",
"EXTERN"
}

Definition at line 114 of file spec2def.c.

◆ astrOlePrivateExports

const char* astrOlePrivateExports[]
static
Initial value:
=
{
"DllCanUnloadNow",
"DllGetClassObject",
"DllGetClassFactoryFromClassString",
"DllGetDocumentation",
"DllInitialize",
"DllInstall",
"DllRegisterServer",
"DllRegisterServerEx",
"DllRegisterServerExW",
"DllUnload",
"DllUnregisterServer",
"RasCustomDeleteEntryNotify",
"RasCustomDial",
"RasCustomDialDlg",
"RasCustomEntryDlg",
}

Definition at line 128 of file spec2def.c.

Referenced by ParseFile().

◆ gbDbgExports

int gbDbgExports = 0

Definition at line 70 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ gbDebug

int gbDebug

Definition at line 76 of file spec2def.c.

Referenced by ParseFile().

◆ gbImportLib

int gbImportLib = 0

Definition at line 66 of file spec2def.c.

Referenced by main(), OutputLine_def(), OutputLine_def_GCC(), OutputLine_def_MS(), and ParseFile().

◆ gbMSComp

int gbMSComp = 0

Definition at line 65 of file spec2def.c.

Referenced by main(), OutputLine_def(), OutputLine_stub(), ParseFile(), and PrintName().

◆ gbNotPrivateNoWarn

int gbNotPrivateNoWarn = 0

Definition at line 67 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ gbTracing

int gbTracing = 0

◆ giArch

◆ gpszUnderscore

char* gpszUnderscore = ""

Definition at line 75 of file spec2def.c.

Referenced by main(), OutputLine_asmstub(), and OutputLine_stub().

◆ guOsVersion

unsigned guOsVersion = 0x502

Definition at line 77 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszArchString

char* pszArchString = "i386"

Definition at line 71 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszArchString2

char* pszArchString2

Definition at line 72 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszDllName

char* pszDllName = NULL

Definition at line 74 of file spec2def.c.

Referenced by Imm32GetFn(), LoadHelperDll(), main(), and OutputLine_stub().

◆ pszSourceFileName

char* pszSourceFileName = NULL

Definition at line 73 of file spec2def.c.

Referenced by main(), and ParseFile().