diff --git a/src/engine/constants.cpp b/src/engine/constants.cpp index ce4e3d7e4..c64ea3b63 100644 --- a/src/engine/constants.cpp +++ b/src/engine/constants.cpp @@ -1,5 +1,6 @@ /* * Copyright 2011 Steven Watanabe + * Copyright 2020 René Ferdinand Rivera Morell * * This file is part of Jam - see jam.c for Copyright information. */ @@ -74,6 +75,8 @@ void constants_init( void ) constant_MAIN_PYTHON = object_new( "MAIN_PYTHON" ); constant_BUILTIN_GLOB_ARCHIVE_BACK= object_new( "BUILTIN_GLOB_ARCHIVE_BACK" ); constant_FILE_ARCHIVESCAN = object_new( "FILE_ARCHIVESCAN" ); + + constant_RESPONSE_FILE_SUB = object_new( "RESPONSE_FILE_SUB" ); } void constants_done( void ) @@ -133,6 +136,8 @@ void constants_done( void ) object_free( constant_MAIN_PYTHON ); object_free( constant_FILE_ARCHIVESCAN ); object_free( constant_BUILTIN_GLOB_ARCHIVE_BACK ); + + object_free( constant_RESPONSE_FILE_SUB ); } OBJECT * constant_empty; @@ -190,3 +195,5 @@ OBJECT * constant_extra_pythonpath; OBJECT * constant_MAIN_PYTHON; OBJECT * constant_FILE_ARCHIVESCAN; OBJECT * constant_BUILTIN_GLOB_ARCHIVE_BACK; + +OBJECT * constant_RESPONSE_FILE_SUB; diff --git a/src/engine/constants.h b/src/engine/constants.h index ec112080d..675b66579 100644 --- a/src/engine/constants.h +++ b/src/engine/constants.h @@ -73,4 +73,6 @@ extern OBJECT * constant_MAIN_PYTHON; /* "MAIN_PYTHON" */ extern OBJECT * constant_FILE_ARCHIVESCAN; /* "FILE_ARCHIVESCAN" */ extern OBJECT * constant_BUILTIN_GLOB_ARCHIVE_BACK; /* "BUILTIN_GLOB_ARCHIVE_BACK" */ +extern OBJECT * constant_RESPONSE_FILE_SUB; // "RESPONSE_FILE_SUB" + #endif diff --git a/src/engine/execcmd.h b/src/engine/execcmd.h index fa24e432d..293822b30 100644 --- a/src/engine/execcmd.h +++ b/src/engine/execcmd.h @@ -112,4 +112,8 @@ int is_raw_command_request( LIST * shell ); int check_cmd_for_too_long_lines( char const * command, int32_t max, int32_t * const error_length, int32_t * const error_max_length ); +/* Maximum shell command line length. + */ +int32_t shell_maxline(); + #endif diff --git a/src/engine/execnt.cpp b/src/engine/execnt.cpp index be0a57a9b..e365d7396 100644 --- a/src/engine/execnt.cpp +++ b/src/engine/execnt.cpp @@ -318,7 +318,7 @@ int32_t exec_check */ /* Check for too long command lines. */ - return check_cmd_for_too_long_lines( command->value, maxline(), + return check_cmd_for_too_long_lines( command->value, shell_maxline(), error_length, error_max_length ); } @@ -1376,5 +1376,10 @@ static void reportWindowsError( char const * const apiName, int32_t slot ) string_renew( cmdtab[ slot ].buffer_err ); } +int32_t shell_maxline() +{ + return maxline(); +} + #endif /* USE_EXECNT */ diff --git a/src/engine/execunix.cpp b/src/engine/execunix.cpp index 9b6ee0fc9..5cd5139ff 100644 --- a/src/engine/execunix.cpp +++ b/src/engine/execunix.cpp @@ -154,7 +154,7 @@ int exec_check return is_raw_cmd ? EXEC_CHECK_OK - : check_cmd_for_too_long_lines( command->value, MAXLINE, error_length, + : check_cmd_for_too_long_lines( command->value, shell_maxline(), error_length, error_max_length ); } @@ -603,4 +603,9 @@ static int get_free_cmdtab_slot() exit( EXITBAD ); } +int32_t shell_maxline() +{ + return MAXLINE; +} + # endif /* USE_EXECUNIX */ diff --git a/src/engine/execvms.cpp b/src/engine/execvms.cpp index e5a12bc62..2c516326c 100644 --- a/src/engine/execvms.cpp +++ b/src/engine/execvms.cpp @@ -89,7 +89,7 @@ int exec_check return is_raw_cmd ? EXEC_CHECK_OK - : check_cmd_for_too_long_lines( command->value, MAXLINE, error_length, + : check_cmd_for_too_long_lines( command->value, shell_maxline(), error_length, error_max_length ); } @@ -415,6 +415,11 @@ clock_t get_cpu_time() return result; } +int32_t shell_maxline() +{ + return MAXLINE; +} + # endif /* VMS */ diff --git a/src/engine/function.cpp b/src/engine/function.cpp index 357f331c3..101fd1a13 100644 --- a/src/engine/function.cpp +++ b/src/engine/function.cpp @@ -13,6 +13,7 @@ #include "compile.h" #include "constants.h" #include "debugger.h" +#include "execcmd.h" #include "filesys.h" #include "frames.h" #include "lists.h" @@ -29,6 +30,8 @@ #include #include +#include + /* #define FUNCTION_DEBUG_PROFILE */ @@ -628,9 +631,17 @@ typedef struct char to_windows; /* :W -- convert cygwin to native paths */ PATHPART empty; /* :E -- default for empties */ PATHPART join; /* :J -- join list with char */ + PATHPART prefix; /* :< */ + PATHPART postfix; /* :> */ } VAR_EDITS; -static LIST * apply_modifiers_impl( LIST * result, string * buf, +struct VAR_EXPANDED +{ + LIST * value = L0; + LIST * inner = L0; +}; + +static VAR_EXPANDED apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int32_t n, LISTITER iter, LISTITER end ); static void get_iters( subscript_t const subscript, LISTITER * const first, LISTITER * const last, int32_t const length ); @@ -693,6 +704,8 @@ static int32_t var_edit_parse( char const * mods, VAR_EDITS * edits, int32_t hav case 'M': fp = &edits->f.f_member; goto fileval; case 'T': edits->to_slashes = 1; continue; case 'W': edits->to_windows = 1; continue; + case '<': fp = &edits->prefix; goto strval; + case '>': fp = &edits->postfix; goto strval; default: continue; /* Should complain, but so what... */ } @@ -873,19 +886,37 @@ static int32_t expand_modifiers( STACK * s, int32_t n ) return total; } -static LIST * apply_modifiers( STACK * s, int32_t n ) +static VAR_EXPANDED apply_modifiers( STACK * s, int32_t n ) { LIST * value = stack_top( s ); - LIST * result = L0; + VAR_EXPANDED result; VAR_EDITS * const edits = (VAR_EDITS *)( (LIST * *)stack_get( s ) + 1 ); string buf[ 1 ]; string_new( buf ); - result = apply_modifiers_impl( result, buf, edits, n, list_begin( value ), + result = apply_modifiers_impl( L0, buf, edits, n, list_begin( value ), list_end( value ) ); string_free( buf ); return result; } +// STACK: LIST * modifiers[modifier_count] +static VAR_EXPANDED eval_modifiers( STACK * s, LIST * value, int32_t modifier_count ) +{ + // Convert modifiers to value edits. + int32_t edits = expand_modifiers( s, modifier_count ); + // Edit the value on the stack. + stack_push( s, value ); + VAR_EXPANDED result = apply_modifiers( s, edits ); + list_free( stack_pop( s ) ); + // Clean up the value edits on the stack. + stack_deallocate( s, edits * sizeof( VAR_EDITS ) ); + // Clean up the filename modifiers. + for ( int32_t i = 0; i < modifier_count; ++i ) + list_free( stack_pop( s ) ); + // Done. + return result; +} + /* * Parse a string of the form "1-2", "-2--1", "2-" and return the two @@ -1027,6 +1058,32 @@ static void get_iters( subscript_t const subscript, LISTITER * const first, *last = end; } +static LIST * apply_modifiers_prepost( LIST * result, string * buf, + VAR_EDITS * edits, int32_t n, LISTITER begin, LISTITER end ) +{ + for ( LISTITER iter = begin; iter != end; iter = list_next( iter ) ) + { + for ( int32_t i = 0; i < n; ++i ) + { + if ( edits[ i ].prefix.ptr ) + { + string_append( buf, edits[ i ].prefix.ptr ); + } + } + string_append( buf, object_str( list_item( iter ) ) ); + for ( int32_t i = 0; i < n; ++i ) + { + if ( edits[ i ].postfix.ptr ) + { + string_append( buf, edits[ i ].postfix.ptr ); + } + } + result = list_push_back( result, object_new( buf->value ) ); + string_truncate( buf, 0 ); + } + return result; +} + static LIST * apply_modifiers_empty( LIST * result, string * buf, VAR_EDITS * edits, int32_t n ) { @@ -1083,12 +1140,17 @@ static LIST * apply_modifiers_non_empty( LIST * result, string * buf, return result; } -static LIST * apply_modifiers_impl( LIST * result, string * buf, +static VAR_EXPANDED apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int32_t n, LISTITER iter, LISTITER end ) { - return iter == end + LIST * modified = iter == end ? apply_modifiers_empty( result, buf, edits, n ) : apply_modifiers_non_empty( result, buf, edits, n, iter, end ); + VAR_EXPANDED expanded; + expanded.value = apply_modifiers_prepost( + L0, buf, edits, n, list_begin( modified ), list_end( modified ) ); + expanded.inner = modified; + return expanded; } static LIST * apply_subscript_and_modifiers( STACK * s, int32_t n ) @@ -1110,7 +1172,10 @@ static LIST * apply_subscript_and_modifiers( STACK * s, int32_t n ) subscript_t const sub = parse_subscript( object_str( list_item( indices_iter ) ) ); get_iters( sub, &iter, &end, length ); - result = apply_modifiers_impl( result, buf, edits, n, iter, end ); + VAR_EXPANDED modified + = apply_modifiers_impl( result, buf, edits, n, iter, end ); + result = modified.value; + list_free( modified.inner ); } string_free( buf ); return result; @@ -1256,6 +1321,7 @@ struct dynamic_array { int32_t size; int32_t capacity; + int32_t unit_size; void * data; }; @@ -1263,6 +1329,7 @@ static void dynamic_array_init( struct dynamic_array * array ) { array->size = 0; array->capacity = 0; + array->unit_size = 0; array->data = 0; } @@ -1274,6 +1341,14 @@ static void dynamic_array_free( struct dynamic_array * array ) static void dynamic_array_push_impl( struct dynamic_array * const array, void const * const value, int32_t const unit_size ) { + if ( array->unit_size == 0 ) + { + array->unit_size = unit_size; + } + else + { + assert( array->unit_size == unit_size ); + } if ( array->capacity == 0 ) { array->capacity = 2; @@ -1293,7 +1368,7 @@ static void dynamic_array_push_impl( struct dynamic_array * const array, } #define dynamic_array_push( array, value ) (dynamic_array_push_impl(array, &value, sizeof(value))) -#define dynamic_array_at( type, array, idx ) (((type *)(array)->data)[idx]) +#define dynamic_array_at( type, array, idx ) ( (assert( array->unit_size == sizeof(type) )) , (((type *)(array)->data)[idx]) ) #define dynamic_array_pop( array ) (--(array)->size) /* @@ -1611,15 +1686,51 @@ typedef struct OBJECT * s; } VAR_PARSE_STRING; -typedef struct -{ - VAR_PARSE base; - struct dynamic_array filename[ 1 ]; - struct dynamic_array contents[ 1 ]; -} VAR_PARSE_FILE; - static void var_parse_free( VAR_PARSE * ); +static std::string var_parse_to_string( VAR_PARSE_STRING * string, bool debug = false ); +static std::string var_parse_to_string( VAR_PARSE_GROUP * group, bool debug = false ); +static std::string var_parse_to_string( VAR_PARSE_VAR const * parse, bool debug = false ); + +static std::string var_parse_to_string( VAR_PARSE_STRING * string, bool debug ) +{ + std::string result; + if ( debug ) result += "'"; + result += object_str( string->s ) ? object_str( string->s ) : ""; + if ( debug ) result += "'"; + return result; +} +static std::string var_parse_to_string( VAR_PARSE_GROUP * group, bool debug ) +{ + std::string result; + if ( debug ) result += "["; + for ( int32_t i = 0; i < group->elems->size; ++i ) + { + switch ( dynamic_array_at( VAR_PARSE *, group->elems, i )->type ) + { + case VAR_PARSE_TYPE_VAR: + result += var_parse_to_string( dynamic_array_at( VAR_PARSE_VAR *, group->elems, i ), debug ); + break; + + case VAR_PARSE_TYPE_STRING: + result += var_parse_to_string( dynamic_array_at( VAR_PARSE_STRING *, group->elems, i ), debug ); + break; + } + } + if ( debug ) result += "["; + return result; +} +static std::string var_parse_to_string( VAR_PARSE_VAR const * parse, bool debug ) +{ + std::string result = "$("; + result += var_parse_to_string( parse->name, debug ); + for ( int32_t i = 0; i < parse->modifiers->size; ++i ) + { + result += ":" + var_parse_to_string( dynamic_array_at( VAR_PARSE_GROUP *, parse->modifiers, i ), debug ); + } + return result + ")"; +} + /* * VAR_PARSE_GROUP @@ -1732,6 +1843,21 @@ static VAR_PARSE_GROUP * var_parse_var_new_modifier( VAR_PARSE_VAR * var ) return result; } +static int32_t var_parse_var_mod_index( VAR_PARSE_VAR const * var , char m) +{ + for ( int32_t i = 0; i < var->modifiers->size; ++i ) + { + VAR_PARSE_GROUP * mod = dynamic_array_at( VAR_PARSE_GROUP *, var->modifiers, i ); + VAR_PARSE_STRING * mod_val = dynamic_array_at( VAR_PARSE_STRING *, mod->elems, 0 ); + const char * mod_str = object_str(mod_val->s); + if (mod_str && mod_str[0] == m) + { + return i; + } + } + return -1; +} + /* * VAR_PARSE_STRING @@ -1744,35 +1870,6 @@ static void var_parse_string_free( VAR_PARSE_STRING * string ) } -/* - * VAR_PARSE_FILE - */ - -static VAR_PARSE_FILE * var_parse_file_new( void ) -{ - VAR_PARSE_FILE * const result = (VAR_PARSE_FILE *)BJAM_MALLOC( sizeof( - VAR_PARSE_FILE ) ); - result->base.type = VAR_PARSE_TYPE_FILE; - dynamic_array_init( result->filename ); - dynamic_array_init( result->contents ); - return result; -} - -static void var_parse_file_free( VAR_PARSE_FILE * file ) -{ - int32_t i; - for ( i = 0; i < file->filename->size; ++i ) - var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, - file->filename, i ) ); - dynamic_array_free( file->filename ); - for ( i = 0; i < file->contents->size; ++i ) - var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, - file->contents, i ) ); - dynamic_array_free( file->contents ); - BJAM_FREE( file ); -} - - /* * VAR_PARSE */ @@ -1782,6 +1879,7 @@ static void var_parse_free( VAR_PARSE * parse ) switch ( parse->type ) { case VAR_PARSE_TYPE_VAR: + case VAR_PARSE_TYPE_FILE: var_parse_var_free( (VAR_PARSE_VAR *)parse ); break; @@ -1789,10 +1887,6 @@ static void var_parse_free( VAR_PARSE * parse ) var_parse_string_free( (VAR_PARSE_STRING *)parse ); break; - case VAR_PARSE_TYPE_FILE: - var_parse_file_free( (VAR_PARSE_FILE *)parse ); - break; - default: assert( !"Invalid type" ); } @@ -1898,17 +1992,53 @@ static void var_parse_string_compile( VAR_PARSE_STRING const * parse, ); } -static void var_parse_file_compile( VAR_PARSE_FILE const * parse, compiler * c ) +static void parse_var_string( char const * first, char const * last, + struct dynamic_array * out ); + +static void var_parse_file_compile( VAR_PARSE_VAR const * parse, compiler * c ) { - int32_t i; - for ( i = 0; i < parse->filename->size; ++i ) - var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, - parse->filename, parse->filename->size - i - 1 ), c ); - compile_emit( c, INSTR_APPEND_STRINGS, parse->filename->size ); - for ( i = 0; i < parse->contents->size; ++i ) - var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, - parse->contents, parse->contents->size - i - 1 ), c ); - compile_emit( c, INSTR_WRITE_FILE, parse->contents->size ); + std::string var = var_parse_to_string( parse, true ); + int32_t empty_mod_index = var_parse_var_mod_index( parse, 'E' ); + int32_t grist_mod_index = var_parse_var_mod_index( parse, 'G' ); + int32_t modifier_count = 0; + // Push the contents, aka the edit modifier value. + { + assert( empty_mod_index >= 0 ); + // We reparse the edit modifier as we do teh expansion differently than + // regular var expansion. + std::string contents_val = var_parse_to_string( + dynamic_array_at( + VAR_PARSE_GROUP *, parse->modifiers, empty_mod_index ), false ); + dynamic_array contents_dyn_array; + dynamic_array_init( &contents_dyn_array ); + parse_var_string( + contents_val.c_str() + 2, contents_val.c_str() + contents_val.size(), + &contents_dyn_array ); + for ( int32_t i = contents_dyn_array.size - 1; i >= 0; --i ) + { + var_parse_group_compile( dynamic_array_at( + VAR_PARSE_GROUP *, ( &contents_dyn_array ), i ), c ); + } + dynamic_array_free( &contents_dyn_array ); + compile_emit( c, INSTR_APPEND_STRINGS, contents_dyn_array.size ); + } + // If there are modifiers, emit them in reverse order. + if ( parse->modifiers->size > 0 ) + { + for ( int32_t i = parse->modifiers->size - 1; i >= 0; --i ) + { + // Skip special modifiers. + if ( i == empty_mod_index || i == grist_mod_index ) continue; + modifier_count += 1; + var_parse_group_compile( + dynamic_array_at( VAR_PARSE_GROUP *, parse->modifiers, i ), c ); + } + } + // Push the filename, aka var name. + var_parse_group_compile( parse->name, c ); + // This instruction applies the modifiers and writes out the file and fills + // in the file name. + compile_emit( c, INSTR_WRITE_FILE, modifier_count ); } static void var_parse_compile( VAR_PARSE const * parse, compiler * c ) @@ -1924,7 +2054,7 @@ static void var_parse_compile( VAR_PARSE const * parse, compiler * c ) break; case VAR_PARSE_TYPE_FILE: - var_parse_file_compile( (VAR_PARSE_FILE const *)parse, c ); + var_parse_file_compile( (VAR_PARSE_VAR const *)parse, c ); break; default: @@ -1964,8 +2094,6 @@ static void var_parse_actions_compile( VAR_PARSE_ACTIONS const * actions, * Parse VAR_PARSE_VAR */ -static VAR_PARSE * parse_at_file( char const * start, char const * mid, - char const * end ); static VAR_PARSE * parse_variable( char const * * string ); static int32_t try_parse_variable( char const * * s_, char const * * string, VAR_PARSE_GROUP * out ); @@ -2026,36 +2154,18 @@ static int32_t try_parse_variable( char const * * s_, char const * * string, } if ( s[ 0 ] == '@' && s[ 1 ] == '(' ) { - int32_t depth = 1; - char const * ine; - char const * split = 0; var_parse_group_maybe_add_constant( out, *string, s ); s += 2; - ine = s; - - /* Scan the content of the response file @() section. */ - while ( *ine && ( depth > 0 ) ) + VAR_PARSE_VAR *vp = (VAR_PARSE_VAR*)parse_variable( &s ); + /* We at least need the empty (:E) modifier. */ + if (var_parse_var_mod_index(vp, 'E') >= 0) { - switch ( *ine ) - { - case '(': ++depth; break; - case ')': --depth; break; - case ':': - if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' - ) ) - split = ine; - break; - } - ++ine; + vp->base.type = VAR_PARSE_TYPE_FILE; + var_parse_group_add( out, (VAR_PARSE*)vp ); + *string = s; + *s_ = s; + return 1; } - - if ( !split || depth ) - return 0; - - var_parse_group_add( out, parse_at_file( s, split, ine - 1 ) ); - *string = ine; - *s_ = ine; - return 1; } return 0; } @@ -2221,20 +2331,6 @@ static void parse_var_string( char const * first, char const * last, } } -/* - * start should point to the character immediately following the opening "@(", - * mid should point to the ":E=", and end should point to the closing ")". - */ - -static VAR_PARSE * parse_at_file( char const * start, char const * mid, - char const * end ) -{ - VAR_PARSE_FILE * result = var_parse_file_new(); - parse_var_string( start, mid, result->filename ); - parse_var_string( mid + 3, end, result->contents ); - return (VAR_PARSE *)result; -} - /* * Given that *s_ points to the character after a "(", parses up to the matching * ")". *string should point to the first unemitted character before *s_. @@ -3859,6 +3955,146 @@ void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, stack_deallocate( s, sizeof( string * ) ); } +// Result is either the filename or contents depending on: +// 1. If the RESPONSE_FILE_SUB == f or not set (it's filename) +// 2. If the RESPONSE_FILE_SUB == c (it's contents) +// 3. If the RESPONSE_FILE_SUB == a (depends on the length of contents) +// Note, returns a *copy* of the filename or contents. +LIST * function_execute_write_file( + JAM_FUNCTION * function, FRAME * frame, STACK * s, + VAR_EXPANDED filename, LIST * contents ) +{ + LIST * filename_or_contents_result = nullptr; + + LIST * response_file_sub = function_get_named_variable( + function, frame, constant_RESPONSE_FILE_SUB ); + char response_file_sub_c + = response_file_sub && list_front( response_file_sub ) + ? object_str( list_front( response_file_sub ) )[0] + : 'f'; + list_free( response_file_sub ); + const char * contents_str = object_str( list_front( contents ) ); + if ( response_file_sub_c == 'a' ) + { + if ( int32_t( strlen( contents_str ) + 256 ) > shell_maxline() ) + response_file_sub_c = 'f'; + else + response_file_sub_c = 'c'; + } + if ( response_file_sub_c == 'c' ) + { + filename_or_contents_result = list_copy( contents ); + } + else + { + char const * out = object_str( list_front( filename.inner ) ); + OBJECT * tmp_filename = nullptr; + FILE * out_file = nullptr; + bool out_debug = DEBUG_EXEC; + + /* For stdout/stderr we will create a temp file and generate a + * command that outputs the content as needed. + */ + if ( ( strcmp( "STDOUT", out ) == 0 ) || + ( strcmp( "STDERR", out ) == 0 ) ) + { + int32_t err_redir = strcmp( "STDERR", out ) == 0; + string result[ 1 ]; + + tmp_filename = path_tmpfile(); + + /* Construct os-specific cat command. */ + { + const char * command = "cat"; + const char * quote = "\""; + const char * redirect = "1>&2"; + + #ifdef OS_NT + command = "type"; + quote = "\""; + #elif defined( OS_VMS ) + command = "pipe type"; + quote = ""; + + /* Get tmp file name in os-format. */ + { + string os_filename[ 1 ]; + + string_new( os_filename ); + path_translate_to_os( object_str( tmp_filename ), os_filename ); + object_free( tmp_filename ); + tmp_filename = object_new( os_filename->value ); + string_free( os_filename ); + } + #endif + + string_new( result ); + string_append( result, command ); + string_append( result, " " ); + string_append( result, quote ); + string_append( result, object_str( tmp_filename ) ); + string_append( result, quote ); + if ( err_redir ) + { + string_append( result, " " ); + string_append( result, redirect ); + } + } + + /* Replace STDXXX with the temporary file. */ + filename_or_contents_result = list_new( object_new( result->value ) ); + out = object_str( tmp_filename ); + + string_free( result ); + + /* Make sure temp files created by this get nuked eventually. */ + file_remove_atexit( tmp_filename ); + } + else + { + filename_or_contents_result = list_copy( filename.value ); + } + + if ( !globs.noexec ) + { + string out_name[ 1 ]; + /* Handle "path to file" filenames. */ + if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) + ) + { + string_copy( out_name, out + 1 ); + string_truncate( out_name, out_name->size - 1 ); + } + else + string_copy( out_name, out ); + out_file = fopen( out_name->value, "w" ); + + if ( !out_file ) + { + err_printf( "[errno %d] failed to write output file '%s': %s", + errno, out_name->value, strerror(errno) ); + exit( EXITBAD ); + } + string_free( out_name ); + } + + if ( out_debug ) out_printf( "\nfile %s\n", out ); + if ( out_file ) fputs( object_str( list_front( contents ) ), out_file ); + if ( out_debug ) out_puts( object_str( list_front( contents ) ) ); + if ( out_file ) + { + fflush( out_file ); + fclose( out_file ); + } + if ( tmp_filename ) + object_free( tmp_filename ); + + if ( out_debug ) out_putc( '\n' ); + } + + return filename_or_contents_result; +} + /* * WARNING: The instruction set is tuned for Jam and is not really generic. Be * especially careful about stack push/pop. @@ -4660,7 +4896,9 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s ) l = stack_pop( s ); n = expand_modifiers( s, code->arg ); stack_push( s, l ); - l = apply_modifiers( s, n ); + VAR_EXPANDED m = apply_modifiers( s, n ); + l = m.value; + list_free( m.inner ); list_free( stack_pop( s ) ); stack_deallocate( s, n * sizeof( VAR_EDITS ) ); for ( i = 0; i < code->arg; ++i ) @@ -4715,7 +4953,9 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s ) { stack_push( s, function_get_named_variable( function, frame, list_item( iter ) ) ); - result = list_append( result, apply_modifiers( s, n ) ); + VAR_EXPANDED m = apply_modifiers( s, n ); + result = m.value; + list_free( m.inner ); list_free( stack_pop( s ) ); } list_free( vars ); @@ -4932,114 +5172,27 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s ) break; } + // WRITE_FILE( LIST*1 filename, LIST*1 modifiers[N], LIST*1 contents ) case INSTR_WRITE_FILE: { PROFILE_ENTER_LOCAL(function_run_INSTR_WRITE_FILE); - string buf[ 1 ]; - char const * out; - OBJECT * tmp_filename = 0; - int32_t out_debug = DEBUG_EXEC ? 1 : 0; - FILE * out_file = 0; - string_new( buf ); - combine_strings( s, code->arg, buf ); - out = object_str( list_front( stack_top( s ) ) ); - - /* For stdout/stderr we will create a temp file and generate a - * command that outputs the content as needed. - */ - if ( ( strcmp( "STDOUT", out ) == 0 ) || - ( strcmp( "STDERR", out ) == 0 ) ) + // Get expanded filename. + LIST * filename = nullptr; { - int32_t err_redir = strcmp( "STDERR", out ) == 0; - string result[ 1 ]; - - tmp_filename = path_tmpfile(); - - /* Construct os-specific cat command. */ - { - const char * command = "cat"; - const char * quote = "\""; - const char * redirect = "1>&2"; - - #ifdef OS_NT - command = "type"; - quote = "\""; - #elif defined( OS_VMS ) - command = "pipe type"; - quote = ""; - - /* Get tmp file name is os-format. */ - { - string os_filename[ 1 ]; - - string_new( os_filename ); - path_translate_to_os( object_str( tmp_filename ), os_filename ); - object_free( tmp_filename ); - tmp_filename = object_new( os_filename->value ); - string_free( os_filename ); - } - #endif - - string_new( result ); - string_append( result, command ); - string_append( result, " " ); - string_append( result, quote ); - string_append( result, object_str( tmp_filename ) ); - string_append( result, quote ); - if ( err_redir ) - { - string_append( result, " " ); - string_append( result, redirect ); - } - } - - /* Replace STDXXX with the temporary file. */ - list_free( stack_pop( s ) ); - stack_push( s, list_new( object_new( result->value ) ) ); - out = object_str( tmp_filename ); - - string_free( result ); - - /* Make sure temp files created by this get nuked eventually. */ - file_remove_atexit( tmp_filename ); + expansion_item ei = { stack_pop( s ) }; + filename = expand( &ei, 1 ); } - - if ( !globs.noexec ) - { - string out_name[ 1 ]; - /* Handle "path to file" filenames. */ - if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) - ) - { - string_copy( out_name, out + 1 ); - string_truncate( out_name, out_name->size - 1 ); - } - else - string_copy( out_name, out ); - out_file = fopen( out_name->value, "w" ); - - if ( !out_file ) - { - err_printf( "[errno %d] failed to write output file '%s': %s", - errno, out_name->value, strerror(errno) ); - exit( EXITBAD ); - } - string_free( out_name ); - } - - if ( out_debug ) out_printf( "\nfile %s\n", out ); - if ( out_file ) fputs( buf->value, out_file ); - if ( out_debug ) out_puts( buf->value ); - if ( out_file ) - { - fflush( out_file ); - fclose( out_file ); - } - string_free( buf ); - if ( tmp_filename ) - object_free( tmp_filename ); - - if ( out_debug ) out_putc( '\n' ); + // Apply modifiers to "raw" filename. + VAR_EXPANDED filename_mod = eval_modifiers( s, filename, code->arg ); + // Get contents. + LIST * contents = stack_pop( s ); + // Write out the contents file, or expand the contents, as needed. + LIST * filename_or_contents = function_execute_write_file( function, frame, s, filename_mod, contents ); + // The result that gets replaced into the @() space. + stack_push( s, filename_or_contents ); + list_free( filename_mod.value ); + list_free( filename_mod.inner ); + list_free( contents ); PROFILE_EXIT_LOCAL(function_run_INSTR_WRITE_FILE); break; } diff --git a/src/engine/jamgram.cpp b/src/engine/jamgram.cpp index 2f7382dfa..4f3de0615 100644 --- a/src/engine/jamgram.cpp +++ b/src/engine/jamgram.cpp @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.6.4. */ +/* A Bison parser, made by GNU Bison 3.7.2. */ /* Bison implementation for Yacc-like parsers in C @@ -49,7 +49,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.6.4" +#define YYBISON_VERSION "3.7.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -135,144 +135,7 @@ # endif # endif -/* Use api.header.include to #include this header - instead of duplicating it here. */ -#ifndef YY_YY_SRC_ENGINE_JAMGRAM_HPP_INCLUDED -# define YY_YY_SRC_ENGINE_JAMGRAM_HPP_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - _BANG_t = 258, /* _BANG_t */ - _BANG_EQUALS_t = 259, /* _BANG_EQUALS_t */ - _AMPER_t = 260, /* _AMPER_t */ - _AMPERAMPER_t = 261, /* _AMPERAMPER_t */ - _LPAREN_t = 262, /* _LPAREN_t */ - _RPAREN_t = 263, /* _RPAREN_t */ - _PLUS_EQUALS_t = 264, /* _PLUS_EQUALS_t */ - _COLON_t = 265, /* _COLON_t */ - _SEMIC_t = 266, /* _SEMIC_t */ - _LANGLE_t = 267, /* _LANGLE_t */ - _LANGLE_EQUALS_t = 268, /* _LANGLE_EQUALS_t */ - _EQUALS_t = 269, /* _EQUALS_t */ - _RANGLE_t = 270, /* _RANGLE_t */ - _RANGLE_EQUALS_t = 271, /* _RANGLE_EQUALS_t */ - _QUESTION_EQUALS_t = 272, /* _QUESTION_EQUALS_t */ - _LBRACKET_t = 273, /* _LBRACKET_t */ - _RBRACKET_t = 274, /* _RBRACKET_t */ - ACTIONS_t = 275, /* ACTIONS_t */ - BIND_t = 276, /* BIND_t */ - BREAK_t = 277, /* BREAK_t */ - CASE_t = 278, /* CASE_t */ - CLASS_t = 279, /* CLASS_t */ - CONTINUE_t = 280, /* CONTINUE_t */ - DEFAULT_t = 281, /* DEFAULT_t */ - ELSE_t = 282, /* ELSE_t */ - EXISTING_t = 283, /* EXISTING_t */ - FOR_t = 284, /* FOR_t */ - IF_t = 285, /* IF_t */ - IGNORE_t = 286, /* IGNORE_t */ - IN_t = 287, /* IN_t */ - INCLUDE_t = 288, /* INCLUDE_t */ - LOCAL_t = 289, /* LOCAL_t */ - MODULE_t = 290, /* MODULE_t */ - ON_t = 291, /* ON_t */ - PIECEMEAL_t = 292, /* PIECEMEAL_t */ - QUIETLY_t = 293, /* QUIETLY_t */ - RETURN_t = 294, /* RETURN_t */ - RULE_t = 295, /* RULE_t */ - SWITCH_t = 296, /* SWITCH_t */ - TOGETHER_t = 297, /* TOGETHER_t */ - UPDATED_t = 298, /* UPDATED_t */ - WHILE_t = 299, /* WHILE_t */ - _LBRACE_t = 300, /* _LBRACE_t */ - _BAR_t = 301, /* _BAR_t */ - _BARBAR_t = 302, /* _BARBAR_t */ - _RBRACE_t = 303, /* _RBRACE_t */ - ARG = 304, /* ARG */ - STRING = 305 /* STRING */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif -/* Token kinds. */ -#define YYEOF 0 -#define YYerror 256 -#define YYUNDEF 257 -#define _BANG_t 258 -#define _BANG_EQUALS_t 259 -#define _AMPER_t 260 -#define _AMPERAMPER_t 261 -#define _LPAREN_t 262 -#define _RPAREN_t 263 -#define _PLUS_EQUALS_t 264 -#define _COLON_t 265 -#define _SEMIC_t 266 -#define _LANGLE_t 267 -#define _LANGLE_EQUALS_t 268 -#define _EQUALS_t 269 -#define _RANGLE_t 270 -#define _RANGLE_EQUALS_t 271 -#define _QUESTION_EQUALS_t 272 -#define _LBRACKET_t 273 -#define _RBRACKET_t 274 -#define ACTIONS_t 275 -#define BIND_t 276 -#define BREAK_t 277 -#define CASE_t 278 -#define CLASS_t 279 -#define CONTINUE_t 280 -#define DEFAULT_t 281 -#define ELSE_t 282 -#define EXISTING_t 283 -#define FOR_t 284 -#define IF_t 285 -#define IGNORE_t 286 -#define IN_t 287 -#define INCLUDE_t 288 -#define LOCAL_t 289 -#define MODULE_t 290 -#define ON_t 291 -#define PIECEMEAL_t 292 -#define QUIETLY_t 293 -#define RETURN_t 294 -#define RULE_t 295 -#define SWITCH_t 296 -#define TOGETHER_t 297 -#define UPDATED_t 298 -#define WHILE_t 299 -#define _LBRACE_t 300 -#define _BAR_t 301 -#define _BARBAR_t 302 -#define _RBRACE_t 303 -#define ARG 304 -#define STRING 305 - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE yylval; - -int yyparse (void); - -#endif /* !YY_YY_SRC_ENGINE_JAMGRAM_HPP_INCLUDED */ +#include "jamgram.hpp" /* Symbol kind. */ enum yysymbol_kind_t { @@ -716,6 +579,7 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 207 +/* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 305 @@ -1258,7 +1122,7 @@ yydestruct (const char *yymsg, } -/* The lookahead symbol. */ +/* Lookahead token kind. */ int yychar; /* The semantic value of the lookahead symbol. */ @@ -1276,34 +1140,30 @@ int yynerrs; int yyparse (void) { - yy_state_fast_t yystate; + yy_state_fast_t yystate = 0; /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; + int yyerrstatus = 0; - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow + /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* Their size. */ - YYPTRDIFF_T yystacksize; + YYPTRDIFF_T yystacksize = YYINITDEPTH; - /* The state stack. */ + /* The state stack: array, bottom, top. */ yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss; - yy_state_t *yyssp; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; - /* The semantic value stack. */ + /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; int yyn; /* The return value of yyparse. */ int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Lookahead symbol kind. */ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ @@ -1317,15 +1177,6 @@ yyparse (void) Keep to zero when no symbol should be popped. */ int yylen = 0; - yynerrs = 0; - yystate = 0; - yyerrstatus = 0; - - yystacksize = YYINITDEPTH; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - - YYDPRINTF ((stderr, "Starting parse\n")); yychar = YYEMPTY; /* Cause a token to be read. */ @@ -1526,722 +1377,722 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 3: + case 3: /* run: rules */ #line 148 "src/engine/jamgram.y" { parse_save( yyvsp[0].parse ); } -#line 1533 "src/engine/jamgram.cpp" +#line 1384 "src/engine/jamgram.cpp" break; - case 4: + case 4: /* block: null */ #line 159 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 1539 "src/engine/jamgram.cpp" +#line 1390 "src/engine/jamgram.cpp" break; - case 5: + case 5: /* block: rules */ #line 161 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 1545 "src/engine/jamgram.cpp" +#line 1396 "src/engine/jamgram.cpp" break; - case 6: + case 6: /* rules: rule */ #line 165 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 1551 "src/engine/jamgram.cpp" +#line 1402 "src/engine/jamgram.cpp" break; - case 7: + case 7: /* rules: rule rules */ #line 167 "src/engine/jamgram.y" { yyval.parse = prules( yyvsp[-1].parse, yyvsp[0].parse ); } -#line 1557 "src/engine/jamgram.cpp" +#line 1408 "src/engine/jamgram.cpp" break; - case 8: + case 8: /* $@1: %empty */ #line 168 "src/engine/jamgram.y" { yymode( SCAN_ASSIGN ); } -#line 1563 "src/engine/jamgram.cpp" +#line 1414 "src/engine/jamgram.cpp" break; - case 9: + case 9: /* $@2: %empty */ #line 168 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1569 "src/engine/jamgram.cpp" +#line 1420 "src/engine/jamgram.cpp" break; - case 10: + case 10: /* rules: LOCAL_t $@1 list assign_list_opt _SEMIC_t $@2 block */ #line 169 "src/engine/jamgram.y" { yyval.parse = plocal( yyvsp[-4].parse, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1575 "src/engine/jamgram.cpp" +#line 1426 "src/engine/jamgram.cpp" break; - case 11: + case 11: /* null: %empty */ #line 173 "src/engine/jamgram.y" { yyval.parse = pnull(); } -#line 1581 "src/engine/jamgram.cpp" +#line 1432 "src/engine/jamgram.cpp" break; - case 12: + case 12: /* $@3: %empty */ #line 176 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1587 "src/engine/jamgram.cpp" +#line 1438 "src/engine/jamgram.cpp" break; - case 13: + case 13: /* assign_list_opt: _EQUALS_t $@3 list */ #line 177 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_SET; } -#line 1593 "src/engine/jamgram.cpp" +#line 1444 "src/engine/jamgram.cpp" break; - case 14: + case 14: /* assign_list_opt: null */ #line 179 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_APPEND; } -#line 1599 "src/engine/jamgram.cpp" +#line 1450 "src/engine/jamgram.cpp" break; - case 15: + case 15: /* arglist_opt: _LPAREN_t lol _RPAREN_t */ #line 183 "src/engine/jamgram.y" { yyval.parse = yyvsp[-1].parse; } -#line 1605 "src/engine/jamgram.cpp" +#line 1456 "src/engine/jamgram.cpp" break; - case 16: + case 16: /* arglist_opt: %empty */ #line 185 "src/engine/jamgram.y" { yyval.parse = P0; } -#line 1611 "src/engine/jamgram.cpp" +#line 1462 "src/engine/jamgram.cpp" break; - case 17: + case 17: /* local_opt: LOCAL_t */ #line 189 "src/engine/jamgram.y" { yyval.number = 1; } -#line 1617 "src/engine/jamgram.cpp" +#line 1468 "src/engine/jamgram.cpp" break; - case 18: + case 18: /* local_opt: %empty */ #line 191 "src/engine/jamgram.y" { yyval.number = 0; } -#line 1623 "src/engine/jamgram.cpp" +#line 1474 "src/engine/jamgram.cpp" break; - case 19: + case 19: /* else_opt: ELSE_t rule */ #line 195 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 1629 "src/engine/jamgram.cpp" +#line 1480 "src/engine/jamgram.cpp" break; - case 20: + case 20: /* else_opt: %empty */ #line 197 "src/engine/jamgram.y" { yyval.parse = pnull(); } -#line 1635 "src/engine/jamgram.cpp" +#line 1486 "src/engine/jamgram.cpp" break; - case 21: + case 21: /* rule: _LBRACE_t block _RBRACE_t */ #line 200 "src/engine/jamgram.y" { yyval.parse = yyvsp[-1].parse; } -#line 1641 "src/engine/jamgram.cpp" +#line 1492 "src/engine/jamgram.cpp" break; - case 22: + case 22: /* $@4: %empty */ #line 201 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1647 "src/engine/jamgram.cpp" +#line 1498 "src/engine/jamgram.cpp" break; - case 23: + case 23: /* rule: INCLUDE_t $@4 list _SEMIC_t */ #line 202 "src/engine/jamgram.y" { yyval.parse = pincl( yyvsp[-1].parse ); yymode( SCAN_NORMAL ); } -#line 1653 "src/engine/jamgram.cpp" +#line 1504 "src/engine/jamgram.cpp" break; - case 24: + case 24: /* $@5: %empty */ #line 203 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1659 "src/engine/jamgram.cpp" +#line 1510 "src/engine/jamgram.cpp" break; - case 25: + case 25: /* rule: ARG $@5 lol _SEMIC_t */ #line 204 "src/engine/jamgram.y" { yyval.parse = prule( yyvsp[-3].string, yyvsp[-1].parse ); yymode( SCAN_NORMAL ); } -#line 1665 "src/engine/jamgram.cpp" +#line 1516 "src/engine/jamgram.cpp" break; - case 26: + case 26: /* $@6: %empty */ #line 205 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1671 "src/engine/jamgram.cpp" +#line 1522 "src/engine/jamgram.cpp" break; - case 27: + case 27: /* rule: arg assign $@6 list _SEMIC_t */ #line 206 "src/engine/jamgram.y" { yyval.parse = pset( yyvsp[-4].parse, yyvsp[-1].parse, yyvsp[-3].number ); yymode( SCAN_NORMAL ); } -#line 1677 "src/engine/jamgram.cpp" +#line 1528 "src/engine/jamgram.cpp" break; - case 28: + case 28: /* $@7: %empty */ #line 207 "src/engine/jamgram.y" { yymode( SCAN_ASSIGN ); } -#line 1683 "src/engine/jamgram.cpp" +#line 1534 "src/engine/jamgram.cpp" break; - case 29: + case 29: /* $@8: %empty */ #line 207 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1689 "src/engine/jamgram.cpp" +#line 1540 "src/engine/jamgram.cpp" break; - case 30: + case 30: /* rule: arg ON_t $@7 list assign $@8 list _SEMIC_t */ #line 208 "src/engine/jamgram.y" { yyval.parse = pset1( yyvsp[-7].parse, yyvsp[-4].parse, yyvsp[-1].parse, yyvsp[-3].number ); yymode( SCAN_NORMAL ); } -#line 1695 "src/engine/jamgram.cpp" +#line 1546 "src/engine/jamgram.cpp" break; - case 31: + case 31: /* $@9: %empty */ #line 209 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1701 "src/engine/jamgram.cpp" +#line 1552 "src/engine/jamgram.cpp" break; - case 32: + case 32: /* rule: RETURN_t $@9 list _SEMIC_t */ #line 210 "src/engine/jamgram.y" { yyval.parse = preturn( yyvsp[-1].parse ); yymode( SCAN_NORMAL ); } -#line 1707 "src/engine/jamgram.cpp" +#line 1558 "src/engine/jamgram.cpp" break; - case 33: + case 33: /* rule: BREAK_t _SEMIC_t */ #line 212 "src/engine/jamgram.y" { yyval.parse = pbreak(); } -#line 1713 "src/engine/jamgram.cpp" +#line 1564 "src/engine/jamgram.cpp" break; - case 34: + case 34: /* rule: CONTINUE_t _SEMIC_t */ #line 214 "src/engine/jamgram.y" { yyval.parse = pcontinue(); } -#line 1719 "src/engine/jamgram.cpp" +#line 1570 "src/engine/jamgram.cpp" break; - case 35: + case 35: /* $@10: %empty */ #line 215 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1725 "src/engine/jamgram.cpp" +#line 1576 "src/engine/jamgram.cpp" break; - case 36: + case 36: /* $@11: %empty */ #line 215 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1731 "src/engine/jamgram.cpp" +#line 1582 "src/engine/jamgram.cpp" break; - case 37: + case 37: /* rule: FOR_t local_opt ARG IN_t $@10 list _LBRACE_t $@11 block _RBRACE_t */ #line 216 "src/engine/jamgram.y" { yyval.parse = pfor( yyvsp[-7].string, yyvsp[-4].parse, yyvsp[-1].parse, yyvsp[-8].number ); } -#line 1737 "src/engine/jamgram.cpp" +#line 1588 "src/engine/jamgram.cpp" break; - case 38: + case 38: /* $@12: %empty */ #line 217 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1743 "src/engine/jamgram.cpp" +#line 1594 "src/engine/jamgram.cpp" break; - case 39: + case 39: /* $@13: %empty */ #line 217 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1749 "src/engine/jamgram.cpp" +#line 1600 "src/engine/jamgram.cpp" break; - case 40: + case 40: /* rule: SWITCH_t $@12 list _LBRACE_t $@13 cases _RBRACE_t */ #line 218 "src/engine/jamgram.y" { yyval.parse = pswitch( yyvsp[-4].parse, yyvsp[-1].parse ); } -#line 1755 "src/engine/jamgram.cpp" +#line 1606 "src/engine/jamgram.cpp" break; - case 41: + case 41: /* $@14: %empty */ #line 219 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1761 "src/engine/jamgram.cpp" +#line 1612 "src/engine/jamgram.cpp" break; - case 42: + case 42: /* $@15: %empty */ #line 219 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1767 "src/engine/jamgram.cpp" +#line 1618 "src/engine/jamgram.cpp" break; - case 43: + case 43: /* rule: IF_t $@14 expr _LBRACE_t $@15 block _RBRACE_t else_opt */ #line 220 "src/engine/jamgram.y" { yyval.parse = pif( yyvsp[-5].parse, yyvsp[-2].parse, yyvsp[0].parse ); } -#line 1773 "src/engine/jamgram.cpp" +#line 1624 "src/engine/jamgram.cpp" break; - case 44: + case 44: /* $@16: %empty */ #line 221 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1779 "src/engine/jamgram.cpp" +#line 1630 "src/engine/jamgram.cpp" break; - case 45: + case 45: /* $@17: %empty */ #line 221 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1785 "src/engine/jamgram.cpp" +#line 1636 "src/engine/jamgram.cpp" break; - case 46: + case 46: /* rule: MODULE_t $@16 list _LBRACE_t $@17 block _RBRACE_t */ #line 222 "src/engine/jamgram.y" { yyval.parse = pmodule( yyvsp[-4].parse, yyvsp[-1].parse ); } -#line 1791 "src/engine/jamgram.cpp" +#line 1642 "src/engine/jamgram.cpp" break; - case 47: + case 47: /* $@18: %empty */ #line 223 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1797 "src/engine/jamgram.cpp" +#line 1648 "src/engine/jamgram.cpp" break; - case 48: + case 48: /* $@19: %empty */ #line 223 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1803 "src/engine/jamgram.cpp" +#line 1654 "src/engine/jamgram.cpp" break; - case 49: + case 49: /* rule: CLASS_t $@18 lol _LBRACE_t $@19 block _RBRACE_t */ #line 224 "src/engine/jamgram.y" { yyval.parse = pclass( yyvsp[-4].parse, yyvsp[-1].parse ); } -#line 1809 "src/engine/jamgram.cpp" +#line 1660 "src/engine/jamgram.cpp" break; - case 50: + case 50: /* $@20: %empty */ #line 225 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1815 "src/engine/jamgram.cpp" +#line 1666 "src/engine/jamgram.cpp" break; - case 51: + case 51: /* $@21: %empty */ #line 225 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1821 "src/engine/jamgram.cpp" +#line 1672 "src/engine/jamgram.cpp" break; - case 52: + case 52: /* rule: WHILE_t $@20 expr $@21 _LBRACE_t block _RBRACE_t */ #line 226 "src/engine/jamgram.y" { yyval.parse = pwhile( yyvsp[-4].parse, yyvsp[-1].parse ); } -#line 1827 "src/engine/jamgram.cpp" +#line 1678 "src/engine/jamgram.cpp" break; - case 53: + case 53: /* $@22: %empty */ #line 227 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 1833 "src/engine/jamgram.cpp" +#line 1684 "src/engine/jamgram.cpp" break; - case 54: + case 54: /* $@23: %empty */ #line 227 "src/engine/jamgram.y" { yymode( SCAN_PARAMS ); } -#line 1839 "src/engine/jamgram.cpp" +#line 1690 "src/engine/jamgram.cpp" break; - case 55: + case 55: /* $@24: %empty */ #line 227 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1845 "src/engine/jamgram.cpp" +#line 1696 "src/engine/jamgram.cpp" break; - case 56: + case 56: /* rule: local_opt RULE_t $@22 ARG $@23 arglist_opt $@24 rule */ #line 228 "src/engine/jamgram.y" { yyval.parse = psetc( yyvsp[-4].string, yyvsp[0].parse, yyvsp[-2].parse, yyvsp[-7].number ); } -#line 1851 "src/engine/jamgram.cpp" +#line 1702 "src/engine/jamgram.cpp" break; - case 57: + case 57: /* rule: ON_t arg rule */ #line 230 "src/engine/jamgram.y" { yyval.parse = pon( yyvsp[-1].parse, yyvsp[0].parse ); } -#line 1857 "src/engine/jamgram.cpp" +#line 1708 "src/engine/jamgram.cpp" break; - case 58: + case 58: /* $@25: %empty */ #line 232 "src/engine/jamgram.y" { yymode( SCAN_STRING ); } -#line 1863 "src/engine/jamgram.cpp" +#line 1714 "src/engine/jamgram.cpp" break; - case 59: + case 59: /* $@26: %empty */ #line 234 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 1869 "src/engine/jamgram.cpp" +#line 1720 "src/engine/jamgram.cpp" break; - case 60: + case 60: /* rule: ACTIONS_t eflags ARG bindlist _LBRACE_t $@25 STRING $@26 _RBRACE_t */ #line 236 "src/engine/jamgram.y" { yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); } -#line 1875 "src/engine/jamgram.cpp" +#line 1726 "src/engine/jamgram.cpp" break; - case 61: + case 61: /* assign: _EQUALS_t */ #line 244 "src/engine/jamgram.y" { yyval.number = ASSIGN_SET; } -#line 1881 "src/engine/jamgram.cpp" +#line 1732 "src/engine/jamgram.cpp" break; - case 62: + case 62: /* assign: _PLUS_EQUALS_t */ #line 246 "src/engine/jamgram.y" { yyval.number = ASSIGN_APPEND; } -#line 1887 "src/engine/jamgram.cpp" +#line 1738 "src/engine/jamgram.cpp" break; - case 63: + case 63: /* assign: _QUESTION_EQUALS_t */ #line 248 "src/engine/jamgram.y" { yyval.number = ASSIGN_DEFAULT; } -#line 1893 "src/engine/jamgram.cpp" +#line 1744 "src/engine/jamgram.cpp" break; - case 64: + case 64: /* assign: DEFAULT_t _EQUALS_t */ #line 250 "src/engine/jamgram.y" { yyval.number = ASSIGN_DEFAULT; } -#line 1899 "src/engine/jamgram.cpp" +#line 1750 "src/engine/jamgram.cpp" break; - case 65: + case 65: /* expr: arg */ #line 257 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_EXISTS, yyvsp[0].parse, pnull() ); yymode( SCAN_COND ); } -#line 1905 "src/engine/jamgram.cpp" +#line 1756 "src/engine/jamgram.cpp" break; - case 66: + case 66: /* $@27: %empty */ #line 258 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1911 "src/engine/jamgram.cpp" +#line 1762 "src/engine/jamgram.cpp" break; - case 67: + case 67: /* expr: expr _EQUALS_t $@27 expr */ #line 259 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_EQUALS, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1917 "src/engine/jamgram.cpp" +#line 1768 "src/engine/jamgram.cpp" break; - case 68: + case 68: /* $@28: %empty */ #line 260 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1923 "src/engine/jamgram.cpp" +#line 1774 "src/engine/jamgram.cpp" break; - case 69: + case 69: /* expr: expr _BANG_EQUALS_t $@28 expr */ #line 261 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_NOTEQ, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1929 "src/engine/jamgram.cpp" +#line 1780 "src/engine/jamgram.cpp" break; - case 70: + case 70: /* $@29: %empty */ #line 262 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1935 "src/engine/jamgram.cpp" +#line 1786 "src/engine/jamgram.cpp" break; - case 71: + case 71: /* expr: expr _LANGLE_t $@29 expr */ #line 263 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_LESS, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1941 "src/engine/jamgram.cpp" +#line 1792 "src/engine/jamgram.cpp" break; - case 72: + case 72: /* $@30: %empty */ #line 264 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1947 "src/engine/jamgram.cpp" +#line 1798 "src/engine/jamgram.cpp" break; - case 73: + case 73: /* expr: expr _LANGLE_EQUALS_t $@30 expr */ #line 265 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_LESSEQ, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1953 "src/engine/jamgram.cpp" +#line 1804 "src/engine/jamgram.cpp" break; - case 74: + case 74: /* $@31: %empty */ #line 266 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1959 "src/engine/jamgram.cpp" +#line 1810 "src/engine/jamgram.cpp" break; - case 75: + case 75: /* expr: expr _RANGLE_t $@31 expr */ #line 267 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_MORE, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1965 "src/engine/jamgram.cpp" +#line 1816 "src/engine/jamgram.cpp" break; - case 76: + case 76: /* $@32: %empty */ #line 268 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1971 "src/engine/jamgram.cpp" +#line 1822 "src/engine/jamgram.cpp" break; - case 77: + case 77: /* expr: expr _RANGLE_EQUALS_t $@32 expr */ #line 269 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_MOREEQ, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1977 "src/engine/jamgram.cpp" +#line 1828 "src/engine/jamgram.cpp" break; - case 78: + case 78: /* $@33: %empty */ #line 270 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1983 "src/engine/jamgram.cpp" +#line 1834 "src/engine/jamgram.cpp" break; - case 79: + case 79: /* expr: expr _AMPER_t $@33 expr */ #line 271 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_AND, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 1989 "src/engine/jamgram.cpp" +#line 1840 "src/engine/jamgram.cpp" break; - case 80: + case 80: /* $@34: %empty */ #line 272 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 1995 "src/engine/jamgram.cpp" +#line 1846 "src/engine/jamgram.cpp" break; - case 81: + case 81: /* expr: expr _AMPERAMPER_t $@34 expr */ #line 273 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_AND, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 2001 "src/engine/jamgram.cpp" +#line 1852 "src/engine/jamgram.cpp" break; - case 82: + case 82: /* $@35: %empty */ #line 274 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 2007 "src/engine/jamgram.cpp" +#line 1858 "src/engine/jamgram.cpp" break; - case 83: + case 83: /* expr: expr _BAR_t $@35 expr */ #line 275 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_OR, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 2013 "src/engine/jamgram.cpp" +#line 1864 "src/engine/jamgram.cpp" break; - case 84: + case 84: /* $@36: %empty */ #line 276 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 2019 "src/engine/jamgram.cpp" +#line 1870 "src/engine/jamgram.cpp" break; - case 85: + case 85: /* expr: expr _BARBAR_t $@36 expr */ #line 277 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_OR, yyvsp[-3].parse, yyvsp[0].parse ); } -#line 2025 "src/engine/jamgram.cpp" +#line 1876 "src/engine/jamgram.cpp" break; - case 86: + case 86: /* $@37: %empty */ #line 278 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 2031 "src/engine/jamgram.cpp" +#line 1882 "src/engine/jamgram.cpp" break; - case 87: + case 87: /* expr: arg IN_t $@37 list */ #line 279 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_IN, yyvsp[-3].parse, yyvsp[0].parse ); yymode( SCAN_COND ); } -#line 2037 "src/engine/jamgram.cpp" +#line 1888 "src/engine/jamgram.cpp" break; - case 88: + case 88: /* $@38: %empty */ #line 280 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 2043 "src/engine/jamgram.cpp" +#line 1894 "src/engine/jamgram.cpp" break; - case 89: + case 89: /* expr: _BANG_t $@38 expr */ #line 281 "src/engine/jamgram.y" { yyval.parse = peval( EXPR_NOT, yyvsp[0].parse, pnull() ); } -#line 2049 "src/engine/jamgram.cpp" +#line 1900 "src/engine/jamgram.cpp" break; - case 90: + case 90: /* $@39: %empty */ #line 282 "src/engine/jamgram.y" { yymode( SCAN_CONDB ); } -#line 2055 "src/engine/jamgram.cpp" +#line 1906 "src/engine/jamgram.cpp" break; - case 91: + case 91: /* expr: _LPAREN_t $@39 expr _RPAREN_t */ #line 283 "src/engine/jamgram.y" { yyval.parse = yyvsp[-1].parse; } -#line 2061 "src/engine/jamgram.cpp" +#line 1912 "src/engine/jamgram.cpp" break; - case 92: + case 92: /* cases: %empty */ #line 294 "src/engine/jamgram.y" { yyval.parse = P0; } -#line 2067 "src/engine/jamgram.cpp" +#line 1918 "src/engine/jamgram.cpp" break; - case 93: + case 93: /* cases: case cases */ #line 296 "src/engine/jamgram.y" { yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); } -#line 2073 "src/engine/jamgram.cpp" +#line 1924 "src/engine/jamgram.cpp" break; - case 94: + case 94: /* $@40: %empty */ #line 299 "src/engine/jamgram.y" { yymode( SCAN_CASE ); } -#line 2079 "src/engine/jamgram.cpp" +#line 1930 "src/engine/jamgram.cpp" break; - case 95: + case 95: /* $@41: %empty */ #line 299 "src/engine/jamgram.y" { yymode( SCAN_NORMAL ); } -#line 2085 "src/engine/jamgram.cpp" +#line 1936 "src/engine/jamgram.cpp" break; - case 96: + case 96: /* case: CASE_t $@40 ARG _COLON_t $@41 block */ #line 300 "src/engine/jamgram.y" { yyval.parse = psnode( yyvsp[-3].string, yyvsp[0].parse ); } -#line 2091 "src/engine/jamgram.cpp" +#line 1942 "src/engine/jamgram.cpp" break; - case 97: + case 97: /* lol: list */ #line 309 "src/engine/jamgram.y" { yyval.parse = pnode( P0, yyvsp[0].parse ); } -#line 2097 "src/engine/jamgram.cpp" +#line 1948 "src/engine/jamgram.cpp" break; - case 98: + case 98: /* lol: list _COLON_t lol */ #line 311 "src/engine/jamgram.y" { yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); } -#line 2103 "src/engine/jamgram.cpp" +#line 1954 "src/engine/jamgram.cpp" break; - case 99: + case 99: /* list: listp */ #line 321 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 2109 "src/engine/jamgram.cpp" +#line 1960 "src/engine/jamgram.cpp" break; - case 100: + case 100: /* listp: %empty */ #line 325 "src/engine/jamgram.y" { yyval.parse = pnull(); } -#line 2115 "src/engine/jamgram.cpp" +#line 1966 "src/engine/jamgram.cpp" break; - case 101: + case 101: /* listp: listp arg */ #line 327 "src/engine/jamgram.y" { yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); } -#line 2121 "src/engine/jamgram.cpp" +#line 1972 "src/engine/jamgram.cpp" break; - case 102: + case 102: /* arg: ARG */ #line 331 "src/engine/jamgram.y" { yyval.parse = plist( yyvsp[0].string ); } -#line 2127 "src/engine/jamgram.cpp" +#line 1978 "src/engine/jamgram.cpp" break; - case 103: + case 103: /* @42: %empty */ #line 332 "src/engine/jamgram.y" { yyval.number = yymode( SCAN_CALL ); } -#line 2133 "src/engine/jamgram.cpp" +#line 1984 "src/engine/jamgram.cpp" break; - case 104: + case 104: /* arg: _LBRACKET_t @42 func _RBRACKET_t */ #line 333 "src/engine/jamgram.y" { yyval.parse = yyvsp[-1].parse; yymode( yyvsp[-2].number ); } -#line 2139 "src/engine/jamgram.cpp" +#line 1990 "src/engine/jamgram.cpp" break; - case 105: + case 105: /* $@43: %empty */ #line 341 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 2145 "src/engine/jamgram.cpp" +#line 1996 "src/engine/jamgram.cpp" break; - case 106: + case 106: /* func: ARG $@43 lol */ #line 342 "src/engine/jamgram.y" { yyval.parse = prule( yyvsp[-2].string, yyvsp[0].parse ); } -#line 2151 "src/engine/jamgram.cpp" +#line 2002 "src/engine/jamgram.cpp" break; - case 107: + case 107: /* $@44: %empty */ #line 343 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 2157 "src/engine/jamgram.cpp" +#line 2008 "src/engine/jamgram.cpp" break; - case 108: + case 108: /* func: ON_t arg ARG $@44 lol */ #line 344 "src/engine/jamgram.y" { yyval.parse = pon( yyvsp[-3].parse, prule( yyvsp[-2].string, yyvsp[0].parse ) ); } -#line 2163 "src/engine/jamgram.cpp" +#line 2014 "src/engine/jamgram.cpp" break; - case 109: + case 109: /* $@45: %empty */ #line 345 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 2169 "src/engine/jamgram.cpp" +#line 2020 "src/engine/jamgram.cpp" break; - case 110: + case 110: /* func: ON_t arg RETURN_t $@45 list */ #line 346 "src/engine/jamgram.y" { yyval.parse = pon( yyvsp[-3].parse, yyvsp[0].parse ); } -#line 2175 "src/engine/jamgram.cpp" +#line 2026 "src/engine/jamgram.cpp" break; - case 111: + case 111: /* eflags: %empty */ #line 356 "src/engine/jamgram.y" { yyval.number = 0; } -#line 2181 "src/engine/jamgram.cpp" +#line 2032 "src/engine/jamgram.cpp" break; - case 112: + case 112: /* eflags: eflags eflag */ #line 358 "src/engine/jamgram.y" { yyval.number = yyvsp[-1].number | yyvsp[0].number; } -#line 2187 "src/engine/jamgram.cpp" +#line 2038 "src/engine/jamgram.cpp" break; - case 113: + case 113: /* eflag: UPDATED_t */ #line 362 "src/engine/jamgram.y" { yyval.number = EXEC_UPDATED; } -#line 2193 "src/engine/jamgram.cpp" +#line 2044 "src/engine/jamgram.cpp" break; - case 114: + case 114: /* eflag: TOGETHER_t */ #line 364 "src/engine/jamgram.y" { yyval.number = EXEC_TOGETHER; } -#line 2199 "src/engine/jamgram.cpp" +#line 2050 "src/engine/jamgram.cpp" break; - case 115: + case 115: /* eflag: IGNORE_t */ #line 366 "src/engine/jamgram.y" { yyval.number = EXEC_IGNORE; } -#line 2205 "src/engine/jamgram.cpp" +#line 2056 "src/engine/jamgram.cpp" break; - case 116: + case 116: /* eflag: QUIETLY_t */ #line 368 "src/engine/jamgram.y" { yyval.number = EXEC_QUIETLY; } -#line 2211 "src/engine/jamgram.cpp" +#line 2062 "src/engine/jamgram.cpp" break; - case 117: + case 117: /* eflag: PIECEMEAL_t */ #line 370 "src/engine/jamgram.y" { yyval.number = EXEC_PIECEMEAL; } -#line 2217 "src/engine/jamgram.cpp" +#line 2068 "src/engine/jamgram.cpp" break; - case 118: + case 118: /* eflag: EXISTING_t */ #line 372 "src/engine/jamgram.y" { yyval.number = EXEC_EXISTING; } -#line 2223 "src/engine/jamgram.cpp" +#line 2074 "src/engine/jamgram.cpp" break; - case 119: + case 119: /* bindlist: %empty */ #line 381 "src/engine/jamgram.y" { yyval.parse = pnull(); } -#line 2229 "src/engine/jamgram.cpp" +#line 2080 "src/engine/jamgram.cpp" break; - case 120: + case 120: /* $@46: %empty */ #line 382 "src/engine/jamgram.y" { yymode( SCAN_PUNCT ); } -#line 2235 "src/engine/jamgram.cpp" +#line 2086 "src/engine/jamgram.cpp" break; - case 121: + case 121: /* bindlist: BIND_t $@46 list */ #line 383 "src/engine/jamgram.y" { yyval.parse = yyvsp[0].parse; } -#line 2241 "src/engine/jamgram.cpp" +#line 2092 "src/engine/jamgram.cpp" break; -#line 2245 "src/engine/jamgram.cpp" +#line 2096 "src/engine/jamgram.cpp" default: break; } @@ -2401,13 +2252,13 @@ yyabortlab: yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ + goto yyreturn; #endif -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ +/*-------------------------------------------------------. +| yyreturn -- parsing is finished, clean up and return. | +`-------------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { diff --git a/src/engine/jamgram.hpp b/src/engine/jamgram.hpp index 325bbe141..48e84c194 100644 --- a/src/engine/jamgram.hpp +++ b/src/engine/jamgram.hpp @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.6.4. */ +/* A Bison parser, made by GNU Bison 3.7.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/src/tools/clang-linux.jam b/src/tools/clang-linux.jam index 28ddcde7b..aaeb2dc71 100644 --- a/src/tools/clang-linux.jam +++ b/src/tools/clang-linux.jam @@ -20,6 +20,7 @@ import type ; import numbers ; import os ; import property ; +import set ; feature.extend-subfeature toolset clang : platform : linux ; @@ -112,6 +113,8 @@ rule init ( version ? : command * : options * ) { ############################################################################### # Flags +local all-os = [ feature.values ] ; + # note: clang silently ignores some of these inlining options # For clang, 'on' and 'full' are identical. toolset.flags clang-linux.compile OPTIONS full : -Wno-inline ; @@ -133,6 +136,11 @@ toolset.flags clang-linux.link OPTIONS gnu gnu11 : -stdlib=libst toolset.flags clang-linux.compile OPTIONS libc++ : -stdlib=libc++ ; toolset.flags clang-linux.link OPTIONS libc++ : -stdlib=libc++ ; +# Enable response file control +toolset.flags clang-linux RESPONSE_FILE_SUB auto : a ; +toolset.flags clang-linux RESPONSE_FILE_SUB file : f ; +toolset.flags clang-linux RESPONSE_FILE_SUB contents : c ; + ############################################################################### # C and C++ compilation @@ -203,85 +211,21 @@ actions compile.c.pch ############################################################################### # Linking -SPACE = " " ; +local soname-os = [ set.difference $(all-os) : windows ] ; +toolset.flags clang-linux.link SONAME_OPT $(soname-os) : "-Wl,-soname -Wl," ; rule link ( targets * : sources * : properties * ) { - SPACE on $(targets) = " " ; - - local tosw ; - local pselect = [ property.select : $(properties) ] ; - - if $(pselect) - { - - local tosv = [ feature.get-values : $(pselect) ] ; - - if $(tosv) = windows - { - tosw = 1 ; - } - } - else if [ os.name ] in NT - { - tosw = 1 ; - } - if $(tosw) - { - link-w $(targets) : $(sources) ; - } - else - { - link-o $(targets) : $(sources) ; - } + _ on $(targets) = " " ; } rule link.dll ( targets * : sources * : properties * ) { - SPACE on $(targets) = " " ; - - local tosw ; - local pselect = [ property.select : $(properties) ] ; - - if $(pselect) - { - - local tosv = [ feature.get-values : $(pselect) ] ; - - if $(tosv) = windows - { - tosw = 1 ; - } - } - else if [ os.name ] in NT - { - tosw = 1 ; - } - if $(tosw) - { - link.dll-w $(targets) : $(sources) ; - } - else - { - link.dll-o $(targets) : $(sources) ; - } + _ on $(targets) = " " ; } -# Target OS is not Windows, needs the RPATH stuff -actions link-o bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @"@($(<[1]:T).rsp:E=-Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP))" $(OPTIONS) $(USER_OPTIONS) +actions link bind LIBRARIES { + "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" -Wl,-rpath-link$(_)-Wl,"$(RPATH_LINK)" $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) } -# Target OS is not Windows, needs the RPATH and SONAME stuff -actions link.dll-o bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @"@($(<[1]:T).rsp:E=-Wl,-R$(SPACE)-Wl,"$(RPATH)" -Wl,-soname$(SPACE)-Wl,$(<[1]:D=) -shared $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP))" $(OPTIONS) $(USER_OPTIONS) -} - -# Target OS is Windows, does not need the RPATH stuff -actions link-w bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @"@($(<[1]:T).rsp:E=$(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP))" $(OPTIONS) $(USER_OPTIONS) -} - -# Target OS is Windows, does not need the RPATH and SONAME stuff -actions link.dll-w bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" -shared @"@($(<[1]:T).rsp:E=$(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP))" $(OPTIONS) $(USER_OPTIONS) - +actions link.dll bind LIBRARIES { + "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" $(SONAME_OPT)$(<[1]:D=) -shared $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) } diff --git a/src/tools/features/response-file-feature.jam b/src/tools/features/response-file-feature.jam new file mode 100644 index 000000000..de910d55b --- /dev/null +++ b/src/tools/features/response-file-feature.jam @@ -0,0 +1,26 @@ +# Copyright 2020 René Ferdinand Rivera Morell +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import feature ; + +#| tag::doc[] + +[[bbv2.builtin.features.response-file]]`response-file`:: +*Allowed values:* `file`, `contents`, `auto`. ++ +Controls whether a response file is used, or not, during the build of the +applicable target. For `file` a response file is created and the filename +replaced in the action. For `contents` the contents (`:E=`) is replaced +in the action and no response file is created. For `auto` either a response +file is created, or the contents replaced, based on the length of the +contents such that if the contents fits within the limits of the command +execution line length limits the contents is replaced. Otherwise a +response file is created and the filename is replaced in the actions. + +|# # end::doc[] + +feature.feature response-file + : auto file contents + : incidental ; diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index 3d65128e5..6f298e755 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -968,13 +968,15 @@ toolset.flags gcc.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib # support -s. toolset.flags gcc.link OPTIONS $(generic-os)/on : -Wl,--strip-all ; - toolset.flags gcc.link RPATH $(generic-os) : ; - toolset.flags gcc.link RPATH_OPTION $(generic-os) : -rpath ; - toolset.flags gcc.link RPATH_LINK $(generic-os) : ; toolset.flags gcc.link START-GROUP $(generic-os) : -Wl,--start-group ; toolset.flags gcc.link END-GROUP $(generic-os) : -Wl,--end-group ; + local rpath-os = [ set.difference $(all-os) : aix darwin vxworks solaris osf hpux windows ] ; + toolset.flags gcc.link RPATH $(rpath-os) : ; + toolset.flags gcc.link RPATH_OPTION $(rpath-os) : -rpath ; + toolset.flags gcc.link RPATH_LINK $(rpath-os) : ; + # gnu ld has the ability to change the search behaviour for libraries # referenced by the -l switch. These modifiers are -Bstatic and # -Bdynamic and change search for -l switches that follow them. The diff --git a/test/core_at_file.py b/test/core_at_file.py index 50fa51220..0a321f4c9 100755 --- a/test/core_at_file.py +++ b/test/core_at_file.py @@ -13,27 +13,27 @@ t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0) t.write("file.jam", """\ name = n1 n2 ; contents = M1 M2 ; -EXIT "file:" "@(o$(name) .txt:E= test -D$(contents))" : 0 ; +EXIT "file:" "@(o$(name:J=) .txt:E= test -D$(contents))" : 0 ; """) t.run_build_system() -t.expect_output_lines("file: on1 on2 .txt"); -t.expect_addition("on1 on2 .txt") -t.expect_content("on1 on2 .txt", " test -DM1 -DM2", True) +t.expect_output_lines("file: on1n2 .txt"); +t.expect_addition("on1n2 .txt") +t.expect_content("on1n2 .txt", " test -DM1 -DM2", True) t.rm(".") t.write("file.jam", """\ name = n1 n2 ; contents = M1 M2 ; -actions run { echo file: "@(o$(name) .txt:E= test -D$(contents))" } +actions run { echo file: "@(o$(name:J=) .txt:E= test -D$(contents))" } run all ; """) t.run_build_system(["-d2"]) -t.expect_output_lines(' echo file: "on1 on2 .txt" '); -t.expect_addition("on1 on2 .txt") -t.expect_content("on1 on2 .txt", " test -DM1 -DM2", True) +t.expect_output_lines(' echo file: "on1n2 .txt" '); +t.expect_addition("on1n2 .txt") +t.expect_content("on1n2 .txt", " test -DM1 -DM2", True) t.rm(".") diff --git a/test/toolset-mock/src/MockProgram.py b/test/toolset-mock/src/MockProgram.py index 795b8676d..e6f46af94 100644 --- a/test/toolset-mock/src/MockProgram.py +++ b/test/toolset-mock/src/MockProgram.py @@ -1,4 +1,5 @@ # Copyright 2017 Steven Watanabe +# Copyright 2020 René Ferdinand Rivera Morell # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at @@ -120,6 +121,17 @@ class arg(object): if s.startswith(self.prefix) and try_match([s[len(self.prefix):]], 0, self.a, outputs) == 1: return pos + 1 +# +class opt(object): + def __init__(self, *args): + self.args = args + def match(self, command_line, pos, outputs): + for p in self.args: + res = try_match_one(command_line, pos, p, outputs) + if res is not None: + pos = res + return pos + # Given a file id, returns a string that will be # written to the file to allow it to be recognized. def make_file_contents(id): diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py index 853fe1dd8..9fb681eef 100644 --- a/test/toolset-mock/src/ar.py +++ b/test/toolset-mock/src/ar.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright 2017-2018 Steven Watanabe +# Copyright 2020 René Ferdinand Rivera Morell # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at @@ -20,5 +21,6 @@ command('ar', 'rc', output_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a command('ar', 'rc', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/lib.o')) command('ar', 'rcu', output_file('bin/clang-vxworks-4.0.1/debug/link-static/libl1.a'), input_file('bin/clang-vxworks-4.0.1/debug/link-static/lib.o')) command('ar', 'rcu', output_file('bin/clang-vxworks-4.0.1/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/clang-vxworks-4.0.1/debug/link-static/runtime-link-static/lib.o')) +command('ar', 'rc', output_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/libl1.lib'), input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/lib.obj')) main() diff --git a/test/toolset-mock/src/clang-linux-3.9.0.py b/test/toolset-mock/src/clang-linux-3.9.0.py index 02d28db54..0194818c8 100644 --- a/test/toolset-mock/src/clang-linux-3.9.0.py +++ b/test/toolset-mock/src/clang-linux-3.9.0.py @@ -1,7 +1,7 @@ #!/usr/bin/python # # Copyright 2017 Steven Watanabe -# Copyright 2020 Rene Rivera +# Copyright 2020 René Ferdinand Rivera Morell # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at @@ -12,38 +12,76 @@ from MockProgram import * command('clang++', '-print-prog-name=ar', stdout=script('ar.py')) command('clang++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) -if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared'): +# target-os=linux .. + +if allow_properties('target-os=linux', 'variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), arg_file('@bin/clang-linux-3.9.0/debug*/libl1.so.rsp'), unordered('-g', '-fPIC')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-fPIC')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/test'), arg_file('@bin/clang-linux-3.9.0/debug*/test.rsp'), unordered('-g', '-fPIC')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-fPIC')) -if allow_properties('variant=release', 'link=shared', 'threading=single', 'runtime-link=shared', 'strip=on'): +if allow_properties('target-os=linux', 'variant=release', 'link=shared', 'threading=single', 'runtime-link=shared', 'strip=on'): command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/strip-on/libl1.so'), arg_file('@bin/clang-linux-3.9.0/release/strip-on*/libl1.so.rsp'), unordered('-fPIC', '-Wl,--strip-all')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-fPIC', '-Wl,--strip-all')) command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/test'), arg_file('@bin/clang-linux-3.9.0/release/strip-on*/test.rsp'), unordered('-fPIC', '-Wl,--strip-all')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/test'), '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/main.o'), input_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-fPIC', '-Wl,--strip-all')) -if allow_properties('variant=debug', 'link=shared', 'threading=multi', 'runtime-link=shared'): +if allow_properties('target-os=linux', 'variant=debug', 'link=shared', 'threading=multi', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), arg_file('@bin/clang-linux-3.9.0/debug*/threading-multi/libl1.so.rsp'), unordered('-g', '-pthread', '-fPIC')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), arg_file('@bin/clang-linux-3.9.0/debug*/threading-multi/test.rsp'), unordered('-g', '-pthread', '-fPIC')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) -if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=shared'): +if allow_properties('target-os=linux', 'variant=debug', 'link=static', 'threading=single', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/lib.o'), input_file(source='lib.cpp')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/test'), arg_file('@bin/clang-linux-3.9.0/debug/link-static*/test.rsp'), '-g') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g') -if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=static'): +if allow_properties('target-os=linux', 'variant=debug', 'link=static', 'threading=single', 'runtime-link=static'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/test'), arg_file('@bin/clang-linux-3.9.0/debug/link-static/runtime-link-static*/test.rsp'), unordered('-g', '-static')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', unordered('-g', '-static')) -if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared', 'architecture=x86', 'address-model=32'): +if allow_properties('target-os=linux', 'variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared', 'architecture=x86', 'address-model=32'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), arg_file('@bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86*/libl1.so.rsp'), unordered('-g', '-march=i686', '-fPIC', '-m32')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-fPIC', '-m32')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/test'), arg_file('@bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86*/test.rsp'), unordered('-g', '-march=i686', '-fPIC', '-m32')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-fPIC', '-m32')) + +# target-os=windows .. + +if allow_properties('target-os=windows', 'variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/lib.obj'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/l1.dll'), '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/target-os-windows/lib.obj'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/test.exe'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/target-os-windows/main.obj'), input_file('bin/clang-linux-3.9.0/debug/target-os-windows/l1.dll'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g')) + +if allow_properties('target-os=windows', 'variant=release', 'link=shared', 'threading=single', 'runtime-link=shared', 'strip=on'): + command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/target-os-windows/lib.obj'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/strip-on/target-os-windows/l1.dll'), '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/target-os-windows/lib.obj'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-Wl,--strip-all')) + command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/strip-on/target-os-windows/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/strip-on/target-os-windows/main.obj'), input_file('bin/clang-linux-3.9.0/release/strip-on/target-os-windows/l1.dll'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-Wl,--strip-all')) + +if allow_properties('target-os=windows', 'variant=debug', 'link=shared', 'threading=multi', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/lib.obj'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/l1.dll'), '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/lib.obj'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-pthread')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/main.obj'), input_file('bin/clang-linux-3.9.0/debug/target-os-windows/threading-multi/l1.dll'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-pthread')) + +if allow_properties('target-os=windows', 'variant=debug', 'link=static', 'threading=single', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/lib.obj'), input_file(source='lib.cpp')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/test.exe'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/main.obj'), input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/libl1.lib'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g') + +if allow_properties('target-os=windows', 'variant=debug', 'link=static', 'threading=single', 'runtime-link=static'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/target-os-windows/lib.obj'), input_file(source='lib.cpp')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/target-os-windows/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/target-os-windows/test.exe'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/main.obj'), input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/libl1.lib'), '-Wl,--end-group', unordered('-g', '-static')) + +if allow_properties('target-os=windows', 'variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared', 'architecture=x86', 'address-model=32'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/lib.obj'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/l1.dll'), '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/lib.obj'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-m32')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/main.obj'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/test.exe'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/main.obj'), input_file('bin/clang-linux-3.9.0/debug/address-model-32/architecture-x86/target-os-windows/l1.dll'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-m32')) main() diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py index 4abe21ed0..6a3e9b63c 100644 --- a/test/toolset-mock/src/ranlib.py +++ b/test/toolset-mock/src/ranlib.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright 2017 Steven Watanabe +# Copyright 2020 René Ferdinand Rivera Morell # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at @@ -18,5 +19,6 @@ command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/tar command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) command('ranlib', input_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a')) command('ranlib', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a')) +command('ranlib', input_file('bin/clang-linux-3.9.0/debug/link-static/target-os-windows/libl1.lib')) main() diff --git a/test/toolset_clang_linux.py b/test/toolset_clang_linux.py index 2fbf84b6d..b4fe0d5a1 100644 --- a/test/toolset_clang_linux.py +++ b/test/toolset_clang_linux.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright 2017 Steven Watanabe +# Copyright 2020 René Ferdinand Rivera Morell # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at @@ -17,3 +18,11 @@ test_toolset("clang-linux", "3.9.0", [ ["target-os=linux", "link=static"], ["target-os=linux", "link=static", "runtime-link=static"], ["target-os=linux", "architecture=x86", "address-model=32"]]) + +test_toolset("clang-linux", "3.9.0", [ + ["target-os=windows"], + ["target-os=windows", "release", "strip=on"], + ["target-os=windows", "threading=multi"], + ["target-os=windows", "link=static"], + ["target-os=windows", "architecture=x86", "address-model=32"] + ])