Added support for building a dll from a .def file for cases where we
don't want to write a full .spec.
Renamed --spec option to --dll for consistency.
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 49b42a9..652826f 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -3,7 +3,7 @@
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
- * Copyright 1995, 1996, 1997 Alexandre Julliard
+ * Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*
@@ -43,6 +43,9 @@
static char *ParseNext = ParseBuffer;
static FILE *input_file;
+static const char *separator_chars;
+static const char *comment_chars;
+
static const char * const TypeNames[TYPE_NBTYPES] =
{
"variable", /* TYPE_VARIABLE */
@@ -76,7 +79,12 @@
inline static int is_token_separator( char ch )
{
- return (ch == '(' || ch == ')' || ch == '-');
+ return strchr( separator_chars, ch ) != NULL;
+}
+
+inline static int is_token_comment( char ch )
+{
+ return strchr( comment_chars, ch ) != NULL;
}
/* get the next line from the input file, or return 0 if at eof */
@@ -109,7 +117,7 @@
else break;
}
- if ((*p == '\0') || (*p == '#'))
+ if ((*p == '\0') || is_token_comment(*p))
{
if (!allow_eol) error( "Declaration not terminated properly\n" );
return NULL;
@@ -146,11 +154,11 @@
}
/*******************************************************************
- * ParseVariable
+ * parse_spec_variable
*
- * Parse a variable definition.
+ * Parse a variable definition in a .spec file.
*/
-static int ParseVariable( ORDDEF *odp, DLLSPEC *spec )
+static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
{
char *endptr;
int *value_array;
@@ -208,11 +216,11 @@
/*******************************************************************
- * ParseExportFunction
+ * parse_spec_export
*
- * Parse a function definition.
+ * Parse an exported function definition in a .spec file.
*/
-static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec )
+static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
{
const char *token;
unsigned int i;
@@ -330,11 +338,11 @@
/*******************************************************************
- * ParseEquate
+ * parse_spec_equate
*
- * Parse an 'equate' definition.
+ * Parse an 'equate' definition in a .spec file.
*/
-static int ParseEquate( ORDDEF *odp, DLLSPEC *spec )
+static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
{
char *endptr;
int value;
@@ -358,11 +366,11 @@
/*******************************************************************
- * ParseStub
+ * parse_spec_stub
*
- * Parse a 'stub' definition.
+ * Parse a 'stub' definition in a .spec file
*/
-static int ParseStub( ORDDEF *odp, DLLSPEC *spec )
+static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
{
odp->u.func.arg_types[0] = '\0';
odp->link_name = xstrdup("");
@@ -371,11 +379,11 @@
/*******************************************************************
- * ParseExtern
+ * parse_spec_extern
*
- * Parse an 'extern' definition.
+ * Parse an 'extern' definition in a .spec file.
*/
-static int ParseExtern( ORDDEF *odp, DLLSPEC *spec )
+static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
{
const char *token;
@@ -403,11 +411,11 @@
/*******************************************************************
- * ParseFlags
+ * parse_spec_flags
*
- * Parse the optional flags for an entry point
+ * Parse the optional flags for an entry point in a .spec file.
*/
-static const char *ParseFlags( ORDDEF *odp )
+static const char *parse_spec_flags( ORDDEF *odp )
{
unsigned int i;
const char *token;
@@ -429,26 +437,13 @@
return token;
}
-/*******************************************************************
- * fix_export_name
- *
- * Fix an exported function name by removing a possible @xx suffix
- */
-static void fix_export_name( char *name )
-{
- char *p, *end = strrchr( name, '@' );
- if (!end || !end[1] || end == name) return;
- /* make sure all the rest is digits */
- for (p = end + 1; *p; p++) if (!isdigit(*p)) return;
- *end = 0;
-}
/*******************************************************************
- * ParseOrdinal
+ * parse_spec_ordinal
*
- * Parse an ordinal definition.
+ * Parse an ordinal definition in a .spec file.
*/
-static int ParseOrdinal( int ordinal, DLLSPEC *spec )
+static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
{
const char *token;
@@ -468,32 +463,32 @@
}
if (!(token = GetToken(0))) goto error;
- if (*token == '-' && !(token = ParseFlags( odp ))) goto error;
+ if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error;
odp->name = xstrdup( token );
- fix_export_name( odp->name );
+ remove_stdcall_decoration( odp->name );
odp->lineno = current_line;
odp->ordinal = ordinal;
switch(odp->type)
{
case TYPE_VARIABLE:
- if (!ParseVariable( odp, spec )) goto error;
+ if (!parse_spec_variable( odp, spec )) goto error;
break;
case TYPE_PASCAL:
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
- if (!ParseExportFunction( odp, spec )) goto error;
+ if (!parse_spec_export( odp, spec )) goto error;
break;
case TYPE_ABS:
- if (!ParseEquate( odp, spec )) goto error;
+ if (!parse_spec_equate( odp, spec )) goto error;
break;
case TYPE_STUB:
- if (!ParseStub( odp, spec )) goto error;
+ if (!parse_spec_stub( odp, spec )) goto error;
break;
case TYPE_EXTERN:
- if (!ParseExtern( odp, spec )) goto error;
+ if (!parse_spec_extern( odp, spec )) goto error;
break;
default:
assert( 0 );
@@ -641,17 +636,20 @@
/*******************************************************************
- * ParseTopLevel
+ * parse_spec_file
*
- * Parse a spec file.
+ * Parse a .spec file.
*/
-int ParseTopLevel( FILE *file, DLLSPEC *spec )
+int parse_spec_file( FILE *file, DLLSPEC *spec )
{
const char *token;
input_file = file;
current_line = 0;
+ comment_chars = "#;";
+ separator_chars = "()-";
+
while (get_next_line())
{
if (!(token = GetToken(1))) continue;
@@ -662,11 +660,11 @@
error( "'@' ordinals not supported for Win16\n" );
continue;
}
- if (!ParseOrdinal( -1, spec )) continue;
+ if (!parse_spec_ordinal( -1, spec )) continue;
}
else if (IsNumberString(token))
{
- if (!ParseOrdinal( atoi(token), spec )) continue;
+ if (!parse_spec_ordinal( atoi(token), spec )) continue;
}
else
{
@@ -684,6 +682,243 @@
/*******************************************************************
+ * parse_def_library
+ *
+ * Parse a LIBRARY declaration in a .def file.
+ */
+static int parse_def_library( DLLSPEC *spec )
+{
+ const char *token = GetToken(1);
+
+ if (!token) return 1;
+ if (strcmp( token, "BASE" ))
+ {
+ free( spec->file_name );
+ spec->file_name = xstrdup( token );
+ if (!(token = GetToken(1))) return 1;
+ }
+ if (strcmp( token, "BASE" ))
+ {
+ error( "Expected library name or BASE= declaration, got '%s'\n", token );
+ return 0;
+ }
+ if (!(token = GetToken(0))) return 0;
+ if (strcmp( token, "=" ))
+ {
+ error( "Expected '=' after BASE, got '%s'\n", token );
+ return 0;
+ }
+ if (!(token = GetToken(0))) return 0;
+ /* FIXME: do something with base address */
+
+ return 1;
+}
+
+
+/*******************************************************************
+ * parse_def_stack_heap_size
+ *
+ * Parse a STACKSIZE or HEAPSIZE declaration in a .def file.
+ */
+static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec )
+{
+ const char *token = GetToken(0);
+ char *end;
+ unsigned long size;
+
+ if (!token) return 0;
+ size = strtoul( token, &end, 0 );
+ if (*end)
+ {
+ error( "Invalid number '%s'\n", token );
+ return 0;
+ }
+ if (is_stack) spec->stack_size = size / 1024;
+ else spec->heap_size = size / 1024;
+ if (!(token = GetToken(1))) return 1;
+ if (strcmp( token, "," ))
+ {
+ error( "Expected ',' after size, got '%s'\n", token );
+ return 0;
+ }
+ if (!(token = GetToken(0))) return 0;
+ /* FIXME: do something with reserve size */
+ return 1;
+}
+
+
+/*******************************************************************
+ * parse_def_export
+ *
+ * Parse an export declaration in a .def file.
+ */
+static int parse_def_export( char *name, DLLSPEC *spec )
+{
+ int i, args;
+ const char *token = GetToken(1);
+
+ ORDDEF *odp = add_entry_point( spec );
+ memset( odp, 0, sizeof(*odp) );
+
+ odp->lineno = current_line;
+ odp->ordinal = -1;
+ odp->name = name;
+ args = remove_stdcall_decoration( odp->name );
+ if (args == -1) odp->type = TYPE_CDECL;
+ else
+ {
+ odp->type = TYPE_STDCALL;
+ args /= sizeof(int);
+ if (args >= sizeof(odp->u.func.arg_types))
+ {
+ error( "Too many arguments in stdcall function '%s'\n", odp->name );
+ return 0;
+ }
+ for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l';
+ }
+
+ /* check for optional internal name */
+
+ if (token && !strcmp( token, "=" ))
+ {
+ if (!(token = GetToken(0))) goto error;
+ odp->link_name = xstrdup( token );
+ remove_stdcall_decoration( odp->link_name );
+ token = GetToken(1);
+ }
+
+ /* check for optional ordinal */
+
+ if (token && token[0] == '@')
+ {
+ int ordinal;
+
+ if (!IsNumberString( token+1 ))
+ {
+ error( "Expected number after '@', got '%s'\n", token+1 );
+ goto error;
+ }
+ ordinal = atoi( token+1 );
+ if (!ordinal)
+ {
+ error( "Ordinal 0 is not valid\n" );
+ goto error;
+ }
+ if (ordinal >= MAX_ORDINALS)
+ {
+ error( "Ordinal number %d too large\n", ordinal );
+ goto error;
+ }
+ if (ordinal > spec->limit) spec->limit = ordinal;
+ if (ordinal < spec->base) spec->base = ordinal;
+ odp->ordinal = ordinal;
+ token = GetToken(1);
+ }
+
+ /* check for other optional keywords */
+
+ if (token && !strcmp( token, "NONAME" ))
+ {
+ if (odp->ordinal == -1)
+ {
+ error( "NONAME requires an ordinal\n" );
+ goto error;
+ }
+ odp->export_name = odp->name;
+ odp->name = NULL;
+ odp->flags |= FLAG_NONAME;
+ token = GetToken(1);
+ }
+ if (token && !strcmp( token, "PRIVATE" ))
+ {
+ odp->flags |= FLAG_PRIVATE;
+ token = GetToken(1);
+ }
+ if (token && !strcmp( token, "DATA" ))
+ {
+ odp->type = TYPE_EXTERN;
+ token = GetToken(1);
+ }
+ if (token)
+ {
+ error( "Garbage text '%s' found at end of export declaration\n", token );
+ goto error;
+ }
+ return 1;
+
+error:
+ spec->nb_entry_points--;
+ free( odp->name );
+ return 0;
+}
+
+
+/*******************************************************************
+ * parse_def_file
+ *
+ * Parse a .def file.
+ */
+int parse_def_file( FILE *file, DLLSPEC *spec )
+{
+ const char *token;
+ int in_exports = 0;
+
+ input_file = file;
+ current_line = 0;
+
+ comment_chars = ";";
+ separator_chars = ",=";
+
+ while (get_next_line())
+ {
+ if (!(token = GetToken(1))) continue;
+
+ if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" ))
+ {
+ if (!parse_def_library( spec )) continue;
+ goto end_of_line;
+ }
+ else if (!strcmp( token, "STACKSIZE" ))
+ {
+ if (!parse_def_stack_heap_size( 1, spec )) continue;
+ goto end_of_line;
+ }
+ else if (!strcmp( token, "HEAPSIZE" ))
+ {
+ if (!parse_def_stack_heap_size( 0, spec )) continue;
+ goto end_of_line;
+ }
+ else if (!strcmp( token, "EXPORTS" ))
+ {
+ in_exports = 1;
+ if (!(token = GetToken(1))) continue;
+ }
+ else if (!strcmp( token, "IMPORTS" ))
+ {
+ in_exports = 0;
+ if (!(token = GetToken(1))) continue;
+ }
+ else if (!strcmp( token, "SECTIONS" ))
+ {
+ in_exports = 0;
+ if (!(token = GetToken(1))) continue;
+ }
+
+ if (!in_exports) continue; /* ignore this line */
+ if (!parse_def_export( xstrdup(token), spec )) continue;
+
+ end_of_line:
+ if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
+ }
+
+ current_line = 0; /* no longer parsing the input file */
+ assign_names( spec );
+ assign_ordinals( spec );
+ return !nb_errors;
+}
+
+
+/*******************************************************************
* add_debug_channel
*/
static void add_debug_channel( const char *name )