ReactOS 0.4.16-dev-292-gbbdcc14
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
 
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 77 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 79 of file spec2def.c.

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

◆ anonymous enum

anonymous enum
Enumerator
CC_STDCALL 
CC_CDECL 
CC_FASTCALL 
CC_THISCALL 
CC_EXTERN 
CC_STUB 

Definition at line 91 of file spec2def.c.

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

◆ anonymous enum

anonymous enum
Enumerator
ARG_LONG 
ARG_PTR 
ARG_STR 
ARG_WSTR 
ARG_DBL 
ARG_INT64 
ARG_INT128 
ARG_FLOAT 

Definition at line 101 of file spec2def.c.

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

◆ _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 1435 of file spec2def.c.

1436{
1437 unsigned short i, j;
1438 char* used;
1439 unsigned short firstOrdinal = 0xFFFF, firstIndex = 0;
1440
1441 /* Allocate a table to mark used ordinals */
1442 used = malloc(65536);
1443 if (used == NULL)
1444 {
1445 fprintf(stderr, "Failed to allocate memory for ordinal use table\n");
1446 return -1;
1447 }
1448 memset(used, 0, 65536);
1449
1450 /* Pass 1: mark the ordinals that are already used */
1451 for (i = 0; i < cExports; i++)
1452 {
1453 if (pexports[i].uFlags & FL_ORDINAL)
1454 {
1455 if (used[pexports[i].nOrdinal] != 0)
1456 {
1457 fprintf(stderr, "Found duplicate ordinal: %u\n", pexports[i].nOrdinal);
1458 return -1;
1459 }
1460 used[pexports[i].nOrdinal] = 1;
1461 if (pexports[i].nOrdinal < firstOrdinal)
1462 {
1463 firstOrdinal = pexports[i].nOrdinal;
1464 firstIndex = i;
1465 }
1466 }
1467 }
1468
1469 /* Check if we found an ordinal and it's larger than it's index */
1470 if ((firstOrdinal != 0xFFFF) && (firstOrdinal > firstIndex))
1471 {
1472 /* We did. Calculate an appropriate starting ordinal. */
1473 firstOrdinal -= firstIndex;
1474 }
1475 else
1476 {
1477 /* We didn't, so start with 1 */
1478 firstOrdinal = 1;
1479 }
1480
1481 /* Pass 2: apply available ordinals */
1482 for (i = 0, j = firstOrdinal; i < cExports; i++)
1483 {
1484 if ((pexports[i].uFlags & FL_ORDINAL) == 0 && pexports[i].bVersionIncluded)
1485 {
1486 while (used[j] != 0)
1487 j++;
1488
1489 pexports[i].nOrdinal = j;
1490 used[j] = 1;
1491 }
1492 }
1493
1494 free(used);
1495 return 0;
1496}
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 155 of file spec2def.c.

156{
157 while (*comparand)
158 {
159 if (*token != *comparand) return 0;
160 token++;
161 comparand++;
162 }
163 if (IsSeparator(comparand[-1])) return 1;
164 if (!IsSeparator(*token)) return 0;
165 return 1;
166}
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:148

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 909 of file spec2def.c.

917{
918 va_list argptr;
919
920 va_start(argptr, format);
921 Fatalv(filename, nLine, pcLine, pc, errorlen, format, argptr);
922 va_end(argptr);
923}
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:859
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 859 of file spec2def.c.

867{
868 unsigned i, errorpos, len;
869 const char* pcLineEnd;
870
871 /* Get the length of the line */
872 pcLineEnd = strpbrk(pcLine, "\r\n");
873 len = (unsigned)(pcLineEnd - pcLine);
874
875 if (pc == NULL)
876 {
877 pc = pcLine + len - 1;
878 errorlen = 1;
879 }
880
881 errorpos = (unsigned)(pc - pcLine);
882
883 /* Output the error message */
884 fprintf(stderr, "ERROR: (%s:%u:%u): ", filename, nLine, errorpos);
885 vfprintf(stderr, format, argptr);
886 fprintf(stderr, "\n");
887
888 /* Output the line with the error */
889 fprintf(stderr, "> %.*s\n", len, pcLine);
890
891 if (errorlen == 0)
892 {
893 errorlen = TokenLength(pc);
894 }
895
896 for (i = 0; i < errorpos + 2; i++)
897 {
898 fprintf(stderr, " ");
899 }
900 for (i = 0; i < errorlen; i++)
901 {
902 fprintf(stderr, "~");
903 }
904 fprintf(stderr, "\n");
905 exit(-1);
906}
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:192

Referenced by Fatal().

◆ IsSeparator()

static int IsSeparator ( char  chr)
static

Definition at line 148 of file spec2def.c.

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

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

◆ main()

int main ( int argc  ,
char argv[] 
)

Definition at line 1516 of file spec2def.c.

1517{
1518 size_t nFileSize;
1519 char *pszSource, *pszDefFileName = NULL, *pszStubFileName = NULL, *pszLibStubName = NULL;
1520 char *pszImpLibAliasFileName = NULL;
1521 const char* pszVersionOption = "--version=0x";
1522 char achDllName[40];
1523 FILE *file;
1524 unsigned cExports = 0, i;
1525 EXPORT *pexports;
1526
1527 if (argc < 2)
1528 {
1529 usage();
1530 return -1;
1531 }
1532
1533 /* Read options */
1534 for (i = 1; i < (unsigned)argc && *argv[i] == '-'; i++)
1535 {
1536 if ((strcasecmp(argv[i], "--help") == 0) ||
1537 (strcasecmp(argv[i], "-h") == 0))
1538 {
1539 usage();
1540 return 0;
1541 }
1542 else if (argv[i][1] == 'd' && argv[i][2] == '=')
1543 {
1544 pszDefFileName = argv[i] + 3;
1545 }
1546 else if (argv[i][1] == 'l' && argv[i][2] == '=')
1547 {
1548 pszLibStubName = argv[i] + 3;
1549 }
1550 else if (argv[i][1] == 's' && argv[i][2] == '=')
1551 {
1552 pszStubFileName = argv[i] + 3;
1553 }
1554 else if (argv[i][1] == 'i' && argv[i][2] == '=')
1555 {
1556 pszImpLibAliasFileName = argv[i] + 3;
1557 }
1558 else if (argv[i][1] == 'n' && argv[i][2] == '=')
1559 {
1560 pszDllName = argv[i] + 3;
1561 }
1562 else if (strncasecmp(argv[i], pszVersionOption, strlen(pszVersionOption)) == 0)
1563 {
1564 guOsVersion = strtoul(argv[i] + strlen(pszVersionOption), NULL, 16);
1565 }
1566 else if (strcasecmp(argv[i], "--implib") == 0)
1567 {
1568 gbImportLib = 1;
1569 }
1570 else if (strcasecmp(argv[i], "--ms") == 0)
1571 {
1572 gbMSComp = 1;
1573 }
1574 else if (strcasecmp(argv[i], "--no-private-warnings") == 0)
1575 {
1577 }
1578 else if (strcasecmp(argv[i], "--with-tracing") == 0)
1579 {
1580 if (!pszStubFileName)
1581 {
1582 fprintf(stderr, "Error: cannot use --with-tracing without -s option.\n");
1583 return -1;
1584 }
1585 gbTracing = 1;
1586 }
1587 else if (argv[i][1] == 'a' && argv[i][2] == '=')
1588 {
1589 pszArchString = argv[i] + 3;
1590 }
1591 else
1592 {
1593 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
1594 return -1;
1595 }
1596 }
1597
1598 if (strcasecmp(pszArchString, "i386") == 0)
1599 {
1600 giArch = ARCH_X86;
1601 gpszUnderscore = "_";
1602 }
1603 else if (strcasecmp(pszArchString, "x86_64") == 0) giArch = ARCH_AMD64;
1604 else if (strcasecmp(pszArchString, "ia64") == 0) giArch = ARCH_IA64;
1605 else if (strcasecmp(pszArchString, "arm") == 0) giArch = ARCH_ARM;
1606 else if (strcasecmp(pszArchString, "arm64") == 0) giArch = ARCH_ARM64;
1607 else if (strcasecmp(pszArchString, "ppc") == 0) giArch = ARCH_PPC;
1608
1609 if ((giArch == ARCH_AMD64) || (giArch == ARCH_IA64))
1610 {
1611 pszArchString2 = "win64";
1612 }
1613 else
1614 pszArchString2 = "win32";
1615
1616 /* Set a default dll name */
1617 if (!pszDllName)
1618 {
1619 char *p1, *p2;
1620 size_t len;
1621
1622 p1 = strrchr(argv[i], '\\');
1623 if (!p1) p1 = strrchr(argv[i], '/');
1624 p2 = p1 = p1 ? p1 + 1 : argv[i];
1625
1626 /* walk up to '.' */
1627 while (*p2 != '.' && *p2 != 0) p2++;
1628 len = p2 - p1;
1629 if (len >= sizeof(achDllName) - 5)
1630 {
1631 fprintf(stderr, "name too long: %s\n", p1);
1632 return -2;
1633 }
1634
1635 strncpy(achDllName, p1, len);
1636 strncpy(achDllName + len, ".dll", sizeof(achDllName) - len);
1637 pszDllName = achDllName;
1638 }
1639
1640 /* Open input file */
1643 if (!file)
1644 {
1645 fprintf(stderr, "error: could not open file %s\n", pszSourceFileName);
1646 return -3;
1647 }
1648
1649 /* Get file size */
1650 fseek(file, 0, SEEK_END);
1651 nFileSize = ftell(file);
1652 rewind(file);
1653
1654 /* Allocate memory buffer */
1655 pszSource = malloc(nFileSize + 1);
1656 if (!pszSource)
1657 {
1658 fclose(file);
1659 return -4;
1660 }
1661
1662 /* Load input file into memory */
1663 nFileSize = fread(pszSource, 1, nFileSize, file);
1664 fclose(file);
1665
1666 /* Zero terminate the source */
1667 pszSource[nFileSize] = '\0';
1668
1669 pexports = ParseFile(pszSource, file, &cExports);
1670 if (pexports == NULL)
1671 {
1672 fprintf(stderr, "error: could not parse file!\n");
1673 return -1;
1674 }
1675
1676 if (ApplyOrdinals(pexports, cExports) < 0)
1677 {
1678 fprintf(stderr, "error: could not apply ordinals!\n");
1679 return -1;
1680 }
1681
1682 if (pszDefFileName)
1683 {
1684 /* Open output file */
1685 file = fopen(pszDefFileName, "w");
1686 if (!file)
1687 {
1688 fprintf(stderr, "error: could not open output file %s\n", pszDefFileName);
1689 return -5;
1690 }
1691
1693
1694 for (i = 0; i < cExports; i++)
1695 {
1696 if (pexports[i].bVersionIncluded)
1697 OutputLine_def(file, &pexports[i]);
1698 }
1699
1700 fclose(file);
1701 }
1702
1703 if (pszStubFileName)
1704 {
1705 /* Open output file */
1706 file = fopen(pszStubFileName, "w");
1707 if (!file)
1708 {
1709 fprintf(stderr, "error: could not open output file %s\n", pszStubFileName);
1710 return -5;
1711 }
1712
1714
1715 for (i = 0; i < cExports; i++)
1716 {
1717 if (pexports[i].bVersionIncluded)
1718 OutputLine_stub(file, &pexports[i]);
1719 }
1720
1721 fclose(file);
1722 }
1723
1724 if (pszLibStubName)
1725 {
1726 /* Open output file */
1727 file = fopen(pszLibStubName, "w");
1728 if (!file)
1729 {
1730 fprintf(stderr, "error: could not open output file %s\n", pszLibStubName);
1731 return -5;
1732 }
1733
1735
1736 for (i = 0; i < cExports; i++)
1737 {
1738 if (pexports[i].bVersionIncluded)
1739 OutputLine_asmstub(file, &pexports[i]);
1740 }
1741
1742 fprintf(file, "\n END\n");
1743 fclose(file);
1744 }
1745
1746 if (pszImpLibAliasFileName)
1747 {
1748 /* Open output file */
1749 file = fopen(pszImpLibAliasFileName, "w");
1750 if (!file)
1751 {
1752 fprintf(stderr, "error: could not open output file %s\n", pszImpLibAliasFileName);
1753 return -5;
1754 }
1755
1757
1758 for (i = 0; i < cExports; i++)
1759 {
1760 if (pexports[i].bVersionIncluded)
1761 OutputLine_implib_asm(file, &pexports[i]);
1762 }
1763
1764 fprintf(file, "\n END\n");
1765 fclose(file);
1766 }
1767
1768 free(pexports);
1769
1770 return 0;
1771}
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
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#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)
unsigned guOsVersion
Definition: spec2def.c:76
void OutputHeader_stub(FILE *file)
Definition: spec2def.c:220
int OutputLine_stub(FILE *file, EXPORT *pexp)
Definition: spec2def.c:236
char * pszArchString2
Definition: spec2def.c:71
void OutputHeader_def(FILE *file, char *libname)
Definition: spec2def.c:531
char * pszSourceFileName
Definition: spec2def.c:72
int gbNotPrivateNoWarn
Definition: spec2def.c:67
char * pszDllName
Definition: spec2def.c:73
int giArch
Definition: spec2def.c:69
int gbMSComp
Definition: spec2def.c:65
void OutputHeader_asmstub(FILE *file, char *libname)
Definition: spec2def.c:435
int OutputLine_implib_asm(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:845
int ApplyOrdinals(EXPORT *pexports, unsigned cExports)
Definition: spec2def.c:1435
int gbImportLib
Definition: spec2def.c:66
char * pszArchString
Definition: spec2def.c:70
int OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:473
void usage(void)
Definition: spec2def.c:1498
int OutputLine_def(FILE *fileDest, EXPORT *pexp)
Definition: spec2def.c:747
int gbTracing
Definition: spec2def.c:68
EXPORT * ParseFile(char *pcStart, FILE *fileDest, unsigned *cExports)
Definition: spec2def.c:926
char * gpszUnderscore
Definition: spec2def.c:74
Definition: fci.c:127

◆ NextLine()

const char * NextLine ( const char pc)

Definition at line 180 of file spec2def.c.

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

Referenced by ParseFile().

◆ NextToken()

const char * NextToken ( const char pc)

Definition at line 202 of file spec2def.c.

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

Referenced by ParseFile().

◆ Output_stublabel()

void Output_stublabel ( FILE fileDest,
char pszSymbolName 
)

Definition at line 454 of file spec2def.c.

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

Referenced by OutputLine_asmstub().

◆ OutputAlias()

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

Definition at line 822 of file spec2def.c.

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

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

Referenced by main().

◆ OutputHeader_def()

void OutputHeader_def ( FILE file,
char libname 
)

Definition at line 531 of file spec2def.c.

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

Referenced by main().

◆ OutputHeader_stub()

void OutputHeader_stub ( FILE file)

Definition at line 220 of file spec2def.c.

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

Referenced by main().

◆ OutputLine_asmstub()

int OutputLine_asmstub ( FILE fileDest,
EXPORT pexp 
)

Definition at line 473 of file spec2def.c.

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

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

Referenced by main().

◆ OutputLine_def_GCC()

void OutputLine_def_GCC ( FILE fileDest,
EXPORT pexp 
)

Definition at line 680 of file spec2def.c.

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

Referenced by OutputLine_def().

◆ OutputLine_def_MS()

void OutputLine_def_MS ( FILE fileDest,
EXPORT pexp 
)

Definition at line 629 of file spec2def.c.

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

Referenced by OutputLine_def().

◆ OutputLine_implib_asm()

int OutputLine_implib_asm ( FILE fileDest,
EXPORT pexp 
)

Definition at line 845 of file spec2def.c.

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

Referenced by main().

◆ OutputLine_stub()

int OutputLine_stub ( FILE file,
EXPORT pexp 
)

Definition at line 236 of file spec2def.c.

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

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

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

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 811 of file spec2def.c.

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

Referenced by OutputAlias().

◆ ScanToken()

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

Definition at line 169 of file spec2def.c.

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

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 192 of file spec2def.c.

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

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

◆ usage()

void usage ( void  )

Definition at line 1498 of file spec2def.c.

1499{
1500 printf("syntax: spec2def [<options> ...] <spec file>\n"
1501 "Possible options:\n"
1502 " -h --help print this help screen\n"
1503 " -l=<file> generate an asm lib stub\n"
1504 " -d=<file> generate a def file\n"
1505 " -s=<file> generate a stub file\n"
1506 " -i=<file> generate an import alias file\n"
1507 " --ms MSVC compatibility\n"
1508 " -n=<name> name of the dll\n"
1509 " --version=<version> Sets the version to create exports for\n"
1510 " --implib generate a def file for an import library\n"
1511 " --no-private-warnings suppress warnings about symbols that should be -private\n"
1512 " -a=<arch> set architecture to <arch> (i386, x86_64, arm, arm64)\n"
1513 " --with-tracing generate wine-like \"+relay\" trace trampolines (needs -s)\n");
1514}
#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 113 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 127 of file spec2def.c.

Referenced by ParseFile().

◆ gbDebug

int gbDebug

Definition at line 75 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 74 of file spec2def.c.

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

◆ guOsVersion

unsigned guOsVersion = 0x502

Definition at line 76 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszArchString

char* pszArchString = "i386"

Definition at line 70 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszArchString2

char* pszArchString2

Definition at line 71 of file spec2def.c.

Referenced by main(), and ParseFile().

◆ pszDllName

char* pszDllName = NULL

Definition at line 73 of file spec2def.c.

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

◆ pszSourceFileName

char* pszSourceFileName = NULL

Definition at line 72 of file spec2def.c.

Referenced by main(), and ParseFile().