From 49edd1965004e9ca1124f638152c4eece3a29f3a Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 18 Mar 2003 05:30:54 +0000 Subject: [PATCH] Handle end of line as a syntactic element in the spec file parser; backslashes can be used to continue lines. This allows us to skip over errors to continue parsing, and also to make specification of an entry point link name optional. --- tools/winebuild/build.h | 6 +- tools/winebuild/import.c | 49 ++++- tools/winebuild/main.c | 6 +- tools/winebuild/parser.c | 325 ++++++++++++++++++++++--------- tools/winebuild/spec16.c | 12 +- tools/winebuild/spec32.c | 5 +- tools/winebuild/utils.c | 16 ++ tools/winebuild/winebuild.man.in | 41 ++-- 8 files changed, 335 insertions(+), 125 deletions(-) diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index aca8939f970..9a9b6286c28 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -136,6 +136,7 @@ extern char *xstrdup( const char *str ); extern char *strupper(char *s); extern void fatal_error( const char *msg, ... ); extern void fatal_perror( const char *msg, ... ); +extern void error( const char *msg, ... ); extern void warning( const char *msg, ... ); extern void output_standard_file_header( FILE *outfile ); extern FILE *open_input_file( const char *srcdir, const char *name ); @@ -156,7 +157,7 @@ extern void load_res16_file( const char *name ); extern int output_res16_data( FILE *outfile ); extern int output_res16_directory( unsigned char *buffer ); extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor ); -extern void parse_debug_channels( const char *srcdir, const char *filename ); +extern int parse_debug_channels( const char *srcdir, const char *filename ); extern void BuildGlue( FILE *outfile, const char *srcdir, char **argv ); extern void BuildRelays16( FILE *outfile ); @@ -165,7 +166,7 @@ extern void BuildSpec16File( FILE *outfile ); extern void BuildSpec32File( FILE *outfile ); extern void BuildDef32File( FILE *outfile ); extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ); -extern void ParseTopLevel( FILE *file ); +extern int ParseTopLevel( FILE *file ); /* global variables */ @@ -180,6 +181,7 @@ extern int debugging; extern int stack_size; extern int nb_debug_channels; extern int nb_lib_paths; +extern int nb_errors; extern int display_warnings; extern int kill_at; diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 06dbf98dca9..2927d8e83e1 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -281,10 +281,18 @@ static int read_import_lib( const char *name, struct import *imp ) if (!strcmp( name, "LIBRARY" )) { - if (!p) fatal_error( "Expected name after LIBRARY\n" ); + if (!p) + { + error( "Expected name after LIBRARY\n" ); + goto next; + } name = p; p = next_token( name ); - if (p) fatal_error( "Garbage after LIBRARY statement\n" ); + if (p) + { + error( "Garbage after LIBRARY statement\n" ); + goto next; + } if (is_already_imported( name )) { close_input_file( f ); @@ -297,11 +305,22 @@ static int read_import_lib( const char *name, struct import *imp ) if (!strcmp( name, "EXPORTS" )) goto next; /* check for ordinal */ - if (!p) fatal_error( "Expected ordinal after function name\n" ); + if (!p) + { + error( "Expected ordinal after function name\n" ); + goto next; + } if (*p != '@' || !isdigit(p[1])) - fatal_error( "Expected ordinal after function name '%s'\n", name ); + { + error( "Expected ordinal after function name '%s'\n", name ); + goto next; + } ordinal = strtol( p+1, &p, 10 ); - if (ordinal >= MAX_ORDINALS) fatal_error( "Invalid ordinal number %d\n", ordinal ); + if (ordinal >= MAX_ORDINALS) + { + error( "Invalid ordinal number %d\n", ordinal ); + goto next; + } /* check for optional flags */ while (p && (p = skip_whitespace(p))) @@ -311,14 +330,22 @@ static int read_import_lib( const char *name, struct import *imp ) if (!strcmp( flags, "NONAME" )) { ord_only = 1; - if (!ordinal) fatal_error( "Invalid ordinal number %d\n", ordinal ); + if (!ordinal) + { + error( "Invalid ordinal number %d\n", ordinal ); + goto next; + } } else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" )) { /* we don't support importing non-function entry points */ goto next; } - else fatal_error( "Garbage after ordinal declaration\n" ); + else + { + error( "Garbage after ordinal declaration\n" ); + goto next; + } } if (imp->nb_exports == size) @@ -338,7 +365,7 @@ static int read_import_lib( const char *name, struct import *imp ) close_input_file( f ); if (imp->nb_exports) qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp ); - return 1; + return !nb_errors; } /* add a dll to the list of imports */ @@ -371,7 +398,11 @@ void add_import_dll( const char *name, int delay ) dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) ); dll_imports[nb_imports++] = imp; } - else free_imports( imp ); + else + { + free_imports( imp ); + if (nb_errors) exit(1); + } } /* remove an imported dll, based on its index in the dll_imports array */ diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index bda87fe9780..b58c27c933a 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -49,6 +49,7 @@ int nb_entry_points = 0; int nb_names = 0; int nb_debug_channels = 0; int nb_lib_paths = 0; +int nb_errors = 0; int display_warnings = 0; int kill_at = 0; @@ -467,7 +468,7 @@ int main(int argc, char **argv) { case MODE_SPEC: load_resources( argv + 1 ); - ParseTopLevel( input_file ); + if (!ParseTopLevel( input_file )) break; switch (SpecType) { case SPEC_WIN16: @@ -491,7 +492,7 @@ int main(int argc, char **argv) case MODE_DEF: if (argv[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[1] ); if (SpecType == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); - ParseTopLevel( input_file ); + if (!ParseTopLevel( input_file )) break; BuildDef32File( output_file ); break; case MODE_DEBUG: @@ -512,6 +513,7 @@ int main(int argc, char **argv) do_usage(); break; } + if (nb_errors) exit(1); if (output_file_name) { fclose( output_file ); diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 67af7a40bef..3f8c34692d1 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -76,17 +76,41 @@ inline static int is_token_separator( char ch ) return (ch == '(' || ch == ')' || ch == '-'); } -static const char * GetTokenInLine(void) +/* get the next line from the input file, or return 0 if at eof */ +static int get_next_line(void) +{ + ParseNext = ParseBuffer; + current_line++; + return (fgets(ParseBuffer, sizeof(ParseBuffer), input_file) != NULL); +} + +static const char * GetToken( int allow_eol ) { char *p = ParseNext; char *token = TokenBuffer; - /* - * Remove initial white space. - */ - while (isspace(*p)) p++; + for (;;) + { + /* remove initial white space */ + p = ParseNext; + while (isspace(*p)) p++; - if ((*p == '\0') || (*p == '#')) return NULL; + if (*p == '\\' && p[1] == '\n') /* line continuation */ + { + if (!get_next_line()) + { + if (!allow_eol) error( "Unexpected end of file\n" ); + return NULL; + } + } + else break; + } + + if ((*p == '\0') || (*p == '#')) + { + if (!allow_eol) error( "Declaration not terminated properly\n" ); + return NULL; + } /* * Find end of token. @@ -106,30 +130,13 @@ static const char * GetTokenInLine(void) return TokenBuffer; } -static const char * GetToken( int allow_eof ) -{ - const char *token; - - while ((token = GetTokenInLine()) == NULL) - { - ParseNext = ParseBuffer; - current_line++; - if (fgets(ParseBuffer, sizeof(ParseBuffer), input_file) == NULL) - { - if (!allow_eof) fatal_error( "Unexpected end of file\n" ); - return NULL; - } - } - return token; -} - /******************************************************************* * ParseVariable * * Parse a variable definition. */ -static void ParseVariable( ORDDEF *odp ) +static int ParseVariable( ORDDEF *odp ) { char *endptr; int *value_array; @@ -138,10 +145,17 @@ static void ParseVariable( ORDDEF *odp ) const char *token; if (SpecType == SPEC_WIN32) - fatal_error( "'variable' not supported in Win32, use 'extern' instead\n" ); + { + error( "'variable' not supported in Win32, use 'extern' instead\n" ); + return 0; + } - token = GetToken(0); - if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token ); + if (!(token = GetToken(0))) return 0; + if (*token != '(') + { + error( "Expected '(' got '%s'\n", token ); + return 0; + } n_values = 0; value_array_size = 25; @@ -149,7 +163,11 @@ static void ParseVariable( ORDDEF *odp ) for (;;) { - token = GetToken(0); + if (!(token = GetToken(0))) + { + free( value_array ); + return 0; + } if (*token == ')') break; @@ -162,11 +180,16 @@ static void ParseVariable( ORDDEF *odp ) } if (endptr == NULL || *endptr != '\0') - fatal_error( "Expected number value, got '%s'\n", token ); + { + error( "Expected number value, got '%s'\n", token ); + free( value_array ); + return 0; + } } odp->u.var.n_values = n_values; odp->u.var.values = xrealloc(value_array, sizeof(*value_array) * n_values); + return 1; } @@ -175,7 +198,7 @@ static void ParseVariable( ORDDEF *odp ) * * Parse a function definition. */ -static void ParseExportFunction( ORDDEF *odp ) +static int ParseExportFunction( ORDDEF *odp ) { const char *token; unsigned int i; @@ -184,26 +207,42 @@ static void ParseExportFunction( ORDDEF *odp ) { case SPEC_WIN16: if (odp->type == TYPE_STDCALL) - fatal_error( "'stdcall' not supported for Win16\n" ); + { + error( "'stdcall' not supported for Win16\n" ); + return 0; + } if (odp->type == TYPE_VARARGS) - fatal_error( "'varargs' not supported for Win16\n" ); + { + error( "'varargs' not supported for Win16\n" ); + return 0; + } break; case SPEC_WIN32: if ((odp->type == TYPE_PASCAL) || (odp->type == TYPE_PASCAL_16)) - fatal_error( "'pascal' not supported for Win32\n" ); + { + error( "'pascal' not supported for Win32\n" ); + return 0; + } if (odp->flags & FLAG_INTERRUPT) - fatal_error( "'interrupt' not supported for Win32\n" ); + { + error( "'interrupt' not supported for Win32\n" ); + return 0; + } break; default: break; } - token = GetToken(0); - if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token ); + if (!(token = GetToken(0))) return 0; + if (*token != '(') + { + error( "Expected '(' got '%s'\n", token ); + return 0; + } for (i = 0; i < sizeof(odp->u.func.arg_types); i++) { - token = GetToken(0); + if (!(token = GetToken(0))) return 0; if (*token == ')') break; @@ -226,7 +265,11 @@ static void ParseExportFunction( ORDDEF *odp ) odp->u.func.arg_types[i++] = 'l'; if (i < sizeof(odp->u.func.arg_types)) odp->u.func.arg_types[i] = 'l'; } - else fatal_error( "Unknown variable type '%s'\n", token ); + else + { + error( "Unknown argument type '%s'\n", token ); + return 0; + } if (SpecType == SPEC_WIN32) { @@ -236,22 +279,44 @@ static void ParseExportFunction( ORDDEF *odp ) strcmp(token, "wstr") && strcmp(token, "double")) { - fatal_error( "Type '%s' not supported for Win32\n", token ); + error( "Type '%s' not supported for Win32\n", token ); + return 0; } } } if ((*token != ')') || (i >= sizeof(odp->u.func.arg_types))) - fatal_error( "Too many arguments\n" ); + { + error( "Too many arguments\n" ); + return 0; + } odp->u.func.arg_types[i] = '\0'; if (odp->type == TYPE_VARARGS) odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */ - odp->link_name = xstrdup( GetToken(0) ); - if (strchr( odp->link_name, '.' )) + + if (!(token = GetToken(1))) { - if (SpecType == SPEC_WIN16) fatal_error( "Forwarded functions not supported for Win16\n" ); - odp->flags |= FLAG_FORWARD; + if (!strcmp( odp->name, "@" )) + { + error( "Missing handler name for anonymous function\n" ); + return 0; + } + odp->link_name = xstrdup( odp->name ); } + else + { + odp->link_name = xstrdup( token ); + if (strchr( odp->link_name, '.' )) + { + if (SpecType == SPEC_WIN16) + { + error( "Forwarded functions not supported for Win16\n" ); + return 0; + } + odp->flags |= FLAG_FORWARD; + } + } + return 1; } @@ -260,17 +325,26 @@ static void ParseExportFunction( ORDDEF *odp ) * * Parse an 'equate' definition. */ -static void ParseEquate( ORDDEF *odp ) +static int ParseEquate( ORDDEF *odp ) { char *endptr; + int value; + const char *token; - const char *token = GetToken(0); - int value = strtol(token, &endptr, 0); - if (endptr == NULL || *endptr != '\0') - fatal_error( "Expected number value, got '%s'\n", token ); if (SpecType == SPEC_WIN32) - fatal_error( "'equate' not supported for Win32\n" ); + { + error( "'equate' not supported for Win32\n" ); + return 0; + } + if (!(token = GetToken(0))) return 0; + value = strtol(token, &endptr, 0); + if (endptr == NULL || *endptr != '\0') + { + error( "Expected number value, got '%s'\n", token ); + return 0; + } odp->u.abs.value = value; + return 1; } @@ -279,10 +353,11 @@ static void ParseEquate( ORDDEF *odp ) * * Parse a 'stub' definition. */ -static void ParseStub( ORDDEF *odp ) +static int ParseStub( ORDDEF *odp ) { odp->u.func.arg_types[0] = '\0'; odp->link_name = xstrdup(""); + return 1; } @@ -291,12 +366,30 @@ static void ParseStub( ORDDEF *odp ) * * Parse an 'extern' definition. */ -static void ParseExtern( ORDDEF *odp ) +static int ParseExtern( ORDDEF *odp ) { + const char *token; + if (SpecType == SPEC_WIN16) - fatal_error( "'extern' not supported for Win16, use 'variable' instead\n" ); - odp->link_name = xstrdup( GetToken(0) ); - if (strchr( odp->link_name, '.' )) odp->flags |= FLAG_FORWARD; + { + error( "'extern' not supported for Win16, use 'variable' instead\n" ); + return 0; + } + if (!(token = GetToken(1))) + { + if (!strcmp( odp->name, "@" )) + { + error( "Missing handler name for anonymous extern\n" ); + return 0; + } + odp->link_name = xstrdup( odp->name ); + } + else + { + odp->link_name = xstrdup( token ); + if (strchr( odp->link_name, '.' )) odp->flags |= FLAG_FORWARD; + } + return 1; } @@ -312,13 +405,17 @@ static const char *ParseFlags( ORDDEF *odp ) do { - token = GetToken(0); + if (!(token = GetToken(0))) break; for (i = 0; FlagNames[i]; i++) if (!strcmp( FlagNames[i], token )) break; - if (!FlagNames[i]) fatal_error( "Unknown flag '%s'\n", token ); + if (!FlagNames[i]) + { + error( "Unknown flag '%s'\n", token ); + return NULL; + } odp->flags |= 1 << i; token = GetToken(0); - } while (*token == '-'); + } while (token && *token == '-'); return token; } @@ -342,7 +439,7 @@ static void fix_export_name( char *name ) * * Parse an ordinal definition. */ -static void ParseOrdinal(int ordinal) +static int ParseOrdinal(int ordinal) { const char *token; @@ -350,17 +447,20 @@ static void ParseOrdinal(int ordinal) memset( odp, 0, sizeof(*odp) ); EntryPoints[nb_entry_points++] = odp; - token = GetToken(0); + if (!(token = GetToken(0))) goto error; for (odp->type = 0; odp->type < TYPE_NBTYPES; odp->type++) if (TypeNames[odp->type] && !strcmp( token, TypeNames[odp->type] )) break; if (odp->type >= TYPE_NBTYPES) - fatal_error( "Expected type after ordinal, found '%s' instead\n", token ); + { + error( "Expected type after ordinal, found '%s' instead\n", token ); + goto error; + } - token = GetToken(0); - if (*token == '-') token = ParseFlags( odp ); + if (!(token = GetToken(0))) goto error; + if (*token == '-' && !(token = ParseFlags( odp ))) goto error; odp->name = xstrdup( token ); fix_export_name( odp->name ); @@ -370,23 +470,23 @@ static void ParseOrdinal(int ordinal) switch(odp->type) { case TYPE_VARIABLE: - ParseVariable( odp ); + if (!ParseVariable( odp )) goto error; break; case TYPE_PASCAL_16: case TYPE_PASCAL: case TYPE_STDCALL: case TYPE_VARARGS: case TYPE_CDECL: - ParseExportFunction( odp ); + if (!ParseExportFunction( odp )) goto error; break; case TYPE_ABS: - ParseEquate( odp ); + if (!ParseEquate( odp )) goto error; break; case TYPE_STUB: - ParseStub( odp ); + if (!ParseStub( odp )) goto error; break; case TYPE_EXTERN: - ParseExtern( odp ); + if (!ParseExtern( odp )) goto error; break; default: assert( 0 ); @@ -398,14 +498,22 @@ static void ParseOrdinal(int ordinal) /* ignore this entry point on non-Intel archs */ EntryPoints[--nb_entry_points] = NULL; free( odp ); - return; + return 1; } #endif if (ordinal != -1) { - if (!ordinal) fatal_error( "Ordinal 0 is not valid\n" ); - if (ordinal >= MAX_ORDINALS) fatal_error( "Ordinal number %d too large\n", ordinal ); + 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 > Limit) Limit = ordinal; if (ordinal < Base) Base = ordinal; odp->ordinal = ordinal; @@ -415,14 +523,27 @@ static void ParseOrdinal(int ordinal) if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME) { if (ordinal == -1) - fatal_error( "Nameless function needs an explicit ordinal number\n" ); + { + error( "Nameless function needs an explicit ordinal number\n" ); + goto error; + } if (SpecType != SPEC_WIN32) - fatal_error( "Nameless functions not supported for Win16\n" ); + { + error( "Nameless functions not supported for Win16\n" ); + goto error; + } if (!strcmp( odp->name, "@" )) free( odp->name ); else odp->export_name = odp->name; odp->name = NULL; } else Names[nb_names++] = odp; + return 1; + +error: + EntryPoints[--nb_entry_points] = NULL; + free( odp->name ); + free( odp ); + return 0; } @@ -453,9 +574,9 @@ static void sort_names(void) if (!strcmp( Names[i]->name, Names[i+1]->name )) { current_line = max( Names[i]->lineno, Names[i+1]->lineno ); - fatal_error( "'%s' redefined\n%s:%d: First defined here\n", - Names[i]->name, input_file_name, - min( Names[i]->lineno, Names[i+1]->lineno ) ); + error( "'%s' redefined\n%s:%d: First defined here\n", + Names[i]->name, input_file_name, + min( Names[i]->lineno, Names[i+1]->lineno ) ); } } } @@ -466,31 +587,40 @@ static void sort_names(void) * * Parse a spec file. */ -void ParseTopLevel( FILE *file ) +int ParseTopLevel( FILE *file ) { const char *token; input_file = file; current_line = 0; - while ((token = GetToken(1)) != NULL) + while (get_next_line()) { + if (!(token = GetToken(1))) continue; if (strcmp(token, "@") == 0) - { + { if (SpecType != SPEC_WIN32) - fatal_error( "'@' ordinals not supported for Win16\n" ); - ParseOrdinal( -1 ); - } - else if (IsNumberString(token)) - { - ParseOrdinal( atoi(token) ); - } - else - fatal_error( "Expected ordinal declaration\n" ); + { + error( "'@' ordinals not supported for Win16\n" ); + continue; + } + if (!ParseOrdinal( -1 )) continue; + } + else if (IsNumberString(token)) + { + if (!ParseOrdinal( atoi(token) )) continue; + } + else + { + error( "Expected ordinal declaration, got '%s'\n", token ); + continue; + } + if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token ); } current_line = 0; /* no longer parsing the input file */ sort_names(); + return !nb_errors; } @@ -514,7 +644,7 @@ static void add_debug_channel( const char *name ) * * Parse a source file and extract the debug channel definitions. */ -void parse_debug_channels( const char *srcdir, const char *filename ) +int parse_debug_channels( const char *srcdir, const char *filename ) { FILE *file; int eol_seen = 1; @@ -540,21 +670,32 @@ void parse_debug_channels( const char *srcdir, const char *filename ) p += 26; while (isspace(*p)) p++; if (*p != '(') - fatal_error( "invalid debug channel specification '%s'\n", ParseBuffer ); + { + error( "invalid debug channel specification '%s'\n", ParseBuffer ); + goto next; + } p++; while (isspace(*p)) p++; if (!isalpha(*p)) - fatal_error( "invalid debug channel specification '%s'\n", ParseBuffer ); + { + error( "invalid debug channel specification '%s'\n", ParseBuffer ); + goto next; + } channel = p; while (isalnum(*p) || *p == '_') p++; end = p; while (isspace(*p)) p++; if (*p != ')') - fatal_error( "invalid debug channel specification '%s'\n", ParseBuffer ); + { + error( "invalid debug channel specification '%s'\n", ParseBuffer ); + goto next; + } *end = 0; add_debug_channel( channel ); } + next: current_line++; } close_input_file( file ); + return !nb_errors; } diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 54da5cd6581..9b78c241fe3 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -451,14 +451,17 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char * routines by yourself. * */ -static void BuildCallTo16Func( FILE *outfile, const char *profile, const char *prefix ) +static int BuildCallTo16Func( FILE *outfile, const char *profile, const char *prefix ) { const char *args = profile + 5; int i, argsize = 0, short_ret = 0; if (!strncmp( "word_", profile, 5 )) short_ret = 1; else if (strncmp( "long_", profile, 5 )) - fatal_error( "Invalid function name '%s'\n", profile ); + { + error( "Invalid function name '%s'\n", profile ); + return 0; + } fprintf( outfile, "unsigned %s __stdcall %s_CallTo16_%s( void (*proc)()", short_ret? "short" : "int", prefix, profile ); @@ -470,7 +473,9 @@ static void BuildCallTo16Func( FILE *outfile, const char *profile, const char *p { case 'w': fprintf( outfile, "unsigned short" ); argsize += 2; break; case 'l': fprintf( outfile, "unsigned int" ); argsize += 4; break; - default: fatal_error( "Invalid letter '%c' in function name '%s'\n", args[i], profile ); + default: + error( "Invalid letter '%c' in function name '%s'\n", args[i], profile ); + return 0; } fprintf( outfile, " arg%d", i+1 ); } @@ -509,6 +514,7 @@ static void BuildCallTo16Func( FILE *outfile, const char *profile, const char *p #else /* __i386__ */ fprintf( outfile, " assert(0);\n}\n\n" ); #endif /* __i386__ */ + return 1; } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 14994c35909..ce9b25e8592 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -868,7 +868,10 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ) int nr_debug; char *prefix, *p; - while (*argv) parse_debug_channels( srcdir, *argv++ ); + while (*argv) + { + if (!parse_debug_channels( srcdir, *argv++ )) exit(1); + } output_standard_file_header( outfile ); nr_debug = output_debug( outfile ); diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index cbc8e51a597..7722bf6d28c 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -104,6 +104,22 @@ void fatal_perror( const char *msg, ... ) exit(1); } +void error( const char *msg, ... ) +{ + va_list valist; + va_start( valist, msg ); + if (input_file_name) + { + fprintf( stderr, "%s:", input_file_name ); + if (current_line) + fprintf( stderr, "%d:", current_line ); + fputc( ' ', stderr ); + } + vfprintf( stderr, msg, valist ); + va_end( valist ); + nb_errors++; +} + void warning( const char *msg, ... ) { va_list valist; diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index f4a7a838098..dd38ba15b6b 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -191,13 +191,13 @@ A spec file should contain a list of ordinal declarations. The general syntax is the following: .PP .I ordinal functype -.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB)\fI\ handler +.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB) \ [ handler ] .br .IB ordinal\ variable .RI [ flags ]\ exportname \ \fB(\fR\ [ data... ] \ \fB) .br .IB ordinal\ extern -.RI [ flags ]\ exportname\ symbolname +.RI [ flags ]\ exportname \ [ symbolname ] .br .IB ordinal\ stub .RI [ flags ]\ exportname @@ -207,9 +207,11 @@ syntax is the following: .br .BI #\ comments .PP -Lines whose first character is a +Declarations must fit on a single line, except if the end of line is +escaped using a backslash character. The .B # -will be ignored as comments. +character anywhere in a line causes the rest of the line to be ignored +as a comment. .PP .I ordinal specifies the ordinal number corresponding to the entry point, or '@' @@ -242,7 +244,7 @@ The function is an interrupt handler routine. Syntax: .br .I ordinal functype -.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB)\fI\ handler +.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB) \ [ handler ] .br This declaration defines a function entry point. The prototype defined by @@ -312,25 +314,30 @@ is the name of the actual C function that will implement that entry point in 32-bit mode. The handler can also be specified as .IB dllname . function to define a forwarded function (one whose implementation is in another -dll). +dll). If +.I handler +is not specified, it is assumed to be identical to +.I exportname. .PP -This first example defines an entry point for the 16-bit -CreateWindow() call (the ordinal 100 is just an example): -.IP -100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word word word word ptr) WIN_CreateWindow -.PP -This second example defines an entry point for the 32-bit GetFocus() +This first example defines an entry point for the 32-bit GetFocus() call: .IP @ stdcall GetFocus() GetFocus .PP +This second example defines an entry point for the 16-bit +CreateWindow() call (the ordinal 100 is just an example); it also +shows how long lines can be split using a backslash: +.IP +100 pascal CreateWindow(ptr ptr long s_word s_word s_word \\ + s_word word word word ptr) WIN_CreateWindow +.PP To declare a function using a variable number of arguments in Win16, specify the function as taking no arguments. The arguments are then available with CURRENT_STACK16->args. In Win32, specify the function as .B varargs and declare it with a '...' parameter in the C file. See the -wsprintf* functions in user.spec and user32.spec for an example. +wsprintf* functions in user.exe.spec and user32.spec for an example. .SS "Variable ordinals" Syntax: .br @@ -357,7 +364,7 @@ instead (see below). Syntax: .br .IB ordinal\ extern -.RI [ flags ]\ exportname\ symbolname +.RI [ flags ]\ exportname \ [ symbolname ] .PP This declaration defines an entry that simply maps to a C symbol (variable or function). It only works in Win32 spec files. @@ -368,8 +375,10 @@ that must be defined in the C code. Alternatively, it can be of the form .IB dllname . symbolname to define a forwarded symbol (one whose implementation is in another -dll). - +dll). If +.I symbolname +is not specified, it is assumed to be identical to +.I exportname. .SS "Stub ordinals" Syntax: .br