📄 variable.c
字号:
/* * 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 http://www.boost.org/LICENSE_1_0.txt) */# include "jam.h"# include "lists.h"# include "parse.h"# include "variable.h"# include "expand.h"# include "hash.h"# include "filesys.h"# include "newstr.h"# include "strings.h"# include "pathsys.h"# include <stdlib.h># include <stdio.h>/* * variable.c - handle jam multi-element variables * * External routines: * * var_defines() - load a bunch of variable=value settings * var_string() - expand a string with variables in it * 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 * * 04/13/94 (seiwald) - added shorthand L0 for null list pointer * 08/23/94 (seiwald) - Support for '+=' (append to variable) * 01/22/95 (seiwald) - split environment variables at blanks or :'s * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :) * 09/11/00 (seiwald) - defunct var_list() removed */static struct hash *varhash = 0;/* * VARIABLE - a user defined multi-value variable */typedef struct _variable VARIABLE ;struct _variable { char *symbol; LIST *value;} ;static VARIABLE *var_enter( char *symbol );static void var_dump( char *symbol, LIST *value, char *what );/* * var_hash_swap() - swap all variable settings with those passed * * Used to implement separate settings spaces for modules */void var_hash_swap( struct hash** new_vars ){ struct hash* old = varhash; varhash = *new_vars; *new_vars = old;}/* * 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. */voidvar_defines( char *const* e, int preprocess ){ string buf[1]; string_new( buf ); for( ; *e; e++ ) { char *val;# ifdef OS_MAC /* On the mac (MPW), the var=val is actually var\0val */ /* Think different. */ if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )# else if( val = strchr( *e, '=' ) )# endif { LIST *l = L0; char *pp, *p;# ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT char split = '\0';# else# ifdef OS_MAC char split = ',';# else char split = ' ';# endif# endif size_t len = strlen(val + 1); int quoted = val[1] == '"' && val[len] == '"' && len > 1; if ( quoted && preprocess ) { string_append_range( buf, val + 2, val + len ); l = list_new( l, newstr( buf->value ) ); string_truncate( buf, 0 ); } else { /* 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_new( l, newstr( buf->value ) ); string_truncate( buf, 0 ); } l = list_new( l, newstr( pp ) ); } /* Get name */ string_append_range( buf, *e, val ); var_set( buf->value, l, VAR_SET ); string_truncate( buf, 0 ); } } string_free( buf );}/* * var_string() - expand a string with variables in it * * Copies in to out; doesn't modify targets & sources. */intvar_string( char *in, char *out, int outsize, LOL *lol ){ char *out0 = out; char *oute = out + outsize - 1; while( *in ) { char *lastword; int dollar = 0; /* Copy white space */ while( isspace( *in ) ) { if( out >= oute ) return -1; *out++ = *in++; } lastword = out; /* Copy non-white space, watching for variables */ while( *in && !isspace( *in ) ) { if( out >= oute ) return -1; if( in[0] == '$' && in[1] == '(' ) { dollar++; *out++ = *in++; } #ifdef OPT_AT_FILES else if ( in[0] == '@' && in[1] == '(' ) { int depth = 1; char *ine = in + 2; char *split = 0; /* Scan the content of the response file @() section. */ while( *ine && depth > 0 ) { switch( *ine ) { case '(': ++depth; break; case ')': --depth; break; case ':': if( depth == 1 && ine[1] == 'E' && ine[2] == '=' ) { split = ine; } break; } ++ine; } if (!split) { /* the @() reference doesn't match the @(foo:E=bar) format. hence we leave it alone by copying directly to output. */ int l = 0; if ( out+2 >= oute ) return -1; *(out++) = '@'; *(out++) = '('; l = var_string(in+2,out,oute-out,lol); if ( l < 0 ) return -1; out += l; if ( out+1 >= oute ) return -1; *(out++) = ')'; } else if ( depth == 0 ) { string file_name_v; int file_name_l = 0; const char * file_name_s = 0; /* expand the temporary file name var inline */ #if 0 string_copy(&file_name_v,"$("); string_append_range(&file_name_v,in+2,split); string_push_back(&file_name_v,')'); #else string_new(&file_name_v); string_append_range(&file_name_v,in+2,split); #endif file_name_l = var_string(file_name_v.value,out,oute-out+1,lol); string_free(&file_name_v); if ( file_name_l < 0 ) return -1; file_name_s = out; /* 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 ) { int err_redir = strcmp( "STDERR", out ) == 0; out[0] = '\0'; file_name_s = path_tmpfile(); file_name_l = strlen(file_name_s); #ifdef OS_NT if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1; sprintf( out,"type \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #else if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1; sprintf( out,"cat \"%s\"%s", file_name_s, err_redir ? " 1>&2" : "" ); #endif /* we also make sure that the temp files created by this get nuked eventually. */ file_remove_atexit( file_name_s ); } /* expand the file value into the file reference */ var_string_to_file( split+3, ine-split-4, file_name_s, lol ); /* continue on with the expansion */ out += strlen(out); } /* and continue with the parsing just past the @() reference */ in = ine; } #endif else { *out++ = *in++; } } /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -