summaryrefslogtreecommitdiffstats
path: root/src/boost/tools/build/src/engine/variable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/tools/build/src/engine/variable.cpp')
-rw-r--r--src/boost/tools/build/src/engine/variable.cpp393
1 files changed, 393 insertions, 0 deletions
diff --git a/src/boost/tools/build/src/engine/variable.cpp b/src/boost/tools/build/src/engine/variable.cpp
new file mode 100644
index 000000000..574c344ce
--- /dev/null
+++ b/src/boost/tools/build/src/engine/variable.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright 1993, 2000 Christopher Seiwald.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/* This file is ALSO:
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Reece H. Dunn.
+ * Copyright 2005 Rene Rivera.
+ * 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)
+ */
+
+/*
+ * variable.c - handle Jam multi-element variables.
+ *
+ * External routines:
+ *
+ * var_defines() - load a bunch of variable=value settings
+ * var_get() - get value of a user defined symbol
+ * var_set() - set a variable in jam's user defined symbol table.
+ * var_swap() - swap a variable's value with the given one
+ * var_done() - free variable tables
+ *
+ * Internal routines:
+ *
+ * var_enter() - make new var symbol table entry, returning var ptr
+ * var_dump() - dump a variable to stdout
+ */
+
+#include "jam.h"
+#include "variable.h"
+
+#include "filesys.h"
+#include "hash.h"
+#include "modules.h"
+#include "parse.h"
+#include "pathsys.h"
+#include "jam_strings.h"
+#include "output.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*
+ * VARIABLE - a user defined multi-value variable
+ */
+
+typedef struct _variable VARIABLE ;
+
+struct _variable
+{
+ OBJECT * symbol;
+ LIST * value;
+};
+
+static LIST * * var_enter( struct module_t *, OBJECT * symbol );
+static void var_dump( OBJECT * symbol, LIST * value, const char * what );
+
+
+/*
+ * var_defines() - load a bunch of variable=value settings
+ *
+ * If preprocess is false, take the value verbatim.
+ *
+ * Otherwise, if the variable value is enclosed in quotes, strip the quotes.
+ * Otherwise, if variable name ends in PATH, split value at :'s.
+ * Otherwise, split the value at blanks.
+ */
+
+void var_defines( struct module_t * module, const char * const * e, int preprocess )
+{
+ string buf[ 1 ];
+
+ string_new( buf );
+
+ for ( ; *e; ++e )
+ {
+ const char * val;
+
+ if ( ( val = strchr( *e, '=' ) )
+#if defined( OS_MAC )
+ /* On the mac (MPW), the var=val is actually var\0val */
+ /* Think different. */
+ || ( val = *e + strlen( *e ) )
+#endif
+ )
+ {
+ LIST * l = L0;
+ size_t const len = strlen( val + 1 );
+ int const quoted = ( val[ 1 ] == '"' ) && ( val[ len ] == '"' ) &&
+ ( len > 1 );
+
+ if ( quoted && preprocess )
+ {
+ string_append_range( buf, val + 2, val + len );
+ l = list_push_back( l, object_new( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ else
+ {
+ const char * p;
+ const char * pp;
+ char split =
+#if defined( OPT_NO_EXTERNAL_VARIABLE_SPLIT )
+ '\0'
+#elif defined( OS_MAC )
+ ','
+#else
+ ' '
+#endif
+ ;
+
+ /* Split *PATH at :'s, not spaces. */
+ if ( val - 4 >= *e )
+ {
+ if ( !strncmp( val - 4, "PATH", 4 ) ||
+ !strncmp( val - 4, "Path", 4 ) ||
+ !strncmp( val - 4, "path", 4 ) )
+ split = SPLITPATH;
+ }
+
+ /* Do the split. */
+ for
+ (
+ pp = val + 1;
+ preprocess && ( ( p = strchr( pp, split ) ) != 0 );
+ pp = p + 1
+ )
+ {
+ string_append_range( buf, pp, p );
+ l = list_push_back( l, object_new( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+
+ l = list_push_back( l, object_new( pp ) );
+ }
+
+ /* Get name. */
+ string_append_range( buf, *e, val );
+ {
+ OBJECT * const varname = object_new( buf->value );
+ var_set( module, varname, l, VAR_SET );
+ object_free( varname );
+ }
+ string_truncate( buf, 0 );
+ }
+ }
+ string_free( buf );
+}
+
+
+/* Last returned variable value saved so we may clear it in var_done(). */
+static LIST * saved_var = L0;
+
+
+/*
+ * var_get() - get value of a user defined symbol
+ *
+ * Returns NULL if symbol unset.
+ */
+
+LIST * var_get( struct module_t * module, OBJECT * symbol )
+{
+ LIST * result = L0;
+#ifdef OPT_AT_FILES
+ /* Some "fixed" variables... */
+ if ( object_equal( symbol, constant_TMPDIR ) )
+ {
+ list_free( saved_var );
+ result = saved_var = list_new( object_new( path_tmpdir()->value ) );
+ }
+ else if ( object_equal( symbol, constant_TMPNAME ) )
+ {
+ list_free( saved_var );
+ result = saved_var = list_new( path_tmpnam() );
+ }
+ else if ( object_equal( symbol, constant_TMPFILE ) )
+ {
+ list_free( saved_var );
+ result = saved_var = list_new( path_tmpfile() );
+ }
+ else if ( object_equal( symbol, constant_STDOUT ) )
+ {
+ list_free( saved_var );
+ result = saved_var = list_new( object_copy( constant_STDOUT ) );
+ }
+ else if ( object_equal( symbol, constant_STDERR ) )
+ {
+ list_free( saved_var );
+ result = saved_var = list_new( object_copy( constant_STDERR ) );
+ }
+ else
+#endif
+ {
+ VARIABLE * v;
+ int n;
+
+ if ( ( n = module_get_fixed_var( module, symbol ) ) != -1 )
+ {
+ if ( DEBUG_VARGET )
+ var_dump( symbol, module->fixed_variables[ n ], "get" );
+ result = module->fixed_variables[ n ];
+ }
+ else if ( module->variables && ( v = (VARIABLE *)hash_find(
+ module->variables, symbol ) ) )
+ {
+ if ( DEBUG_VARGET )
+ var_dump( v->symbol, v->value, "get" );
+ result = v->value;
+ }
+
+#ifdef OS_VMS
+ else if ( ( module->name && object_equal( module->name, constant_ENVIRON ) )
+ || root_module() == module )
+ {
+ /* On VMS, when a variable from root or ENVIRON module is not found,
+ * explicitly request it from the process.
+ * By design, process variables (and logicals) are not made available
+ * to C main(), and thus will not get loaded in bulk to root/ENVRON.
+ * So we get around it by getting any such variable on first request.
+ */
+ const char * val = getenv( object_str( symbol ) );
+
+ if ( val )
+ {
+ struct module_t * environ_module = module;
+ char * environ[ 2 ] = { 0 }; /* NULL-terminated */
+ string buf[ 1 ];
+
+ if ( root_module() == module )
+ {
+ environ_module = bindmodule( constant_ENVIRON );
+ }
+
+ string_copy( buf, object_str( symbol ) );
+ string_append( buf, "=" );
+ string_append( buf, val );
+
+ environ[ 0 ] = buf->value;
+
+ /* Load variable to global module, with splitting, for backward
+ * compatibility. Then to .ENVIRON, without splitting.
+ */
+ var_defines( root_module(), environ, 1 );
+ var_defines( environ_module, environ, 0 );
+ string_free( buf );
+
+ if ( module->variables && ( v = (VARIABLE *)hash_find(
+ module->variables, symbol ) ) )
+ {
+ if ( DEBUG_VARGET )
+ var_dump( v->symbol, v->value, "get" );
+ result = v->value;
+ }
+ }
+ }
+#endif
+ }
+ return result;
+}
+
+
+LIST * var_get_and_clear_raw( module_t * module, OBJECT * symbol )
+{
+ LIST * result = L0;
+ VARIABLE * v;
+
+ if ( module->variables && ( v = (VARIABLE *)hash_find( module->variables,
+ symbol ) ) )
+ {
+ result = v->value;
+ v->value = L0;
+ }
+
+ return result;
+}
+
+
+/*
+ * var_set() - set a variable in Jam's user defined symbol table
+ *
+ * 'flag' controls the relationship between new and old values of the variable:
+ * SET replaces the old with the new; APPEND appends the new to the old; DEFAULT
+ * only uses the new if the variable was previously unset.
+ *
+ * Copies symbol. Takes ownership of value.
+ */
+
+void var_set( struct module_t * module, OBJECT * symbol, LIST * value, int flag
+ )
+{
+ LIST * * v = var_enter( module, symbol );
+
+ if ( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+
+ switch ( flag )
+ {
+ case VAR_SET: /* Replace value */
+ list_free( *v );
+ *v = value;
+ break;
+
+ case VAR_APPEND: /* Append value */
+ *v = list_append( *v, value );
+ break;
+
+ case VAR_DEFAULT: /* Set only if unset */
+ if ( list_empty( *v ) )
+ *v = value;
+ else
+ list_free( value );
+ break;
+ }
+}
+
+
+/*
+ * var_swap() - swap a variable's value with the given one
+ */
+
+LIST * var_swap( struct module_t * module, OBJECT * symbol, LIST * value )
+{
+ LIST * * v = var_enter( module, symbol );
+ LIST * oldvalue = *v;
+ if ( DEBUG_VARSET )
+ var_dump( symbol, value, "set" );
+ *v = value;
+ return oldvalue;
+}
+
+
+/*
+ * var_enter() - make new var symbol table entry, returning var ptr
+ */
+
+static LIST * * var_enter( struct module_t * module, OBJECT * symbol )
+{
+ int found;
+ VARIABLE * v;
+ int n;
+
+ if ( ( n = module_get_fixed_var( module, symbol ) ) != -1 )
+ return &module->fixed_variables[ n ];
+
+ if ( !module->variables )
+ module->variables = hashinit( sizeof( VARIABLE ), "variables" );
+
+ v = (VARIABLE *)hash_insert( module->variables, symbol, &found );
+ if ( !found )
+ {
+ v->symbol = object_copy( symbol );
+ v->value = L0;
+ }
+
+ return &v->value;
+}
+
+
+/*
+ * var_dump() - dump a variable to stdout
+ */
+
+static void var_dump( OBJECT * symbol, LIST * value, const char * what )
+{
+ out_printf( "%s %s = ", what, object_str( symbol ) );
+ list_print( value );
+ out_printf( "\n" );
+}
+
+
+/*
+ * var_done() - free variable tables
+ */
+
+static void delete_var_( void * xvar, void * data )
+{
+ VARIABLE * const v = (VARIABLE *)xvar;
+ object_free( v->symbol );
+ list_free( v->value );
+}
+
+void var_done( struct module_t * module )
+{
+ list_free( saved_var );
+ saved_var = L0;
+ hashenumerate( module->variables, delete_var_, 0 );
+ hash_free( module->variables );
+}