⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expand.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * * This file is part of Jam - see jam.c for Copyright information. */# include "jam.h"# include "lists.h"# include "variable.h"# include "expand.h"# include "pathsys.h"# include "newstr.h"# include <assert.h># include <stdlib.h># include <limits.h># ifdef OS_CYGWIN#  include <sys/cygwin.h>#  include <windows.h># endif/* * expand.c - expand a buffer, given variable values * * External routines: * *	var_expand() - variable-expand input string into list of strings * * Internal routines: * *	var_edit_parse() - parse : modifiers into PATHNAME structure *	var_edit_file() - copy input target name to output, modifying filename *	var_edit_shift() - do upshift/downshift mods * * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X) * 04/13/94 (seiwald) - added shorthand L0 for null list pointer * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval */typedef struct {	PATHNAME	f;		/* :GDBSMR -- pieces */	char		parent;		/* :P -- go to parent directory */	char		filemods;	/* one of the above applied */	char		downshift;	/* :L -- downshift result */	char		upshift;	     /* :U -- upshift result */    char        to_slashes;    /* :T -- convert "\" to "/" */    char        to_windows;    /* :W -- convert cygwin to native paths */	PATHPART	empty;		/* :E -- default for empties */	PATHPART	join;		/* :J -- join list with char */} VAR_EDITS ;static void var_edit_parse( char *mods, VAR_EDITS *edits );static void var_edit_file( char *in, string *out, VAR_EDITS *edits );static void var_edit_shift( string *out, VAR_EDITS *edits );# define MAGIC_COLON	'\001'# define MAGIC_LEFT	'\002'# define MAGIC_RIGHT	'\003'/* * var_expand() - variable-expand input string into list of strings * * Would just copy input to output, performing variable expansion,  * except that since variables can contain multiple values the result * of variable expansion may contain multiple values (a list).  Properly * performs "product" operations that occur in "$(var1)xxx$(var2)" or * even "$($(var2))". * * Returns a newly created list. */LIST *var_expand( 	LIST	*l,	char	*in,	char	*end,	LOL	*lol,	int	cancopyin ){    char out_buf[ MAXSYM ];    string buf[1];    string out1[1]; /* Temporary buffer */    size_t prefix_length;    char *out;    char *inp = in;    char *ov;		/* for temp copy of variable in outbuf */    int depth;    if( DEBUG_VAREXP )        printf( "expand '%.*s'\n", end - in, in );    /* This gets alot of cases: $(<) and $(>) */    if( in[0] == '$' && in[1] == '(' && in[3] == ')' && in[4] == '\0' )    {        switch( in[2] )        {        case '<':            return list_copy( l, lol_get( lol, 0 ) );        case '>':            return list_copy( l, lol_get( lol, 1 ) );                case '1':        case '2':        case '3':        case '4':        case '5':        case '6':        case '7':        case '8':        case '9':            return list_copy( l, lol_get( lol, in[2]-'1' ) );        }    }        /* Expand @() files, to single item plus accompanying file. */        if ( in[0] == '@' && in[1] == '(' && *(end-1) == ')' )    {        /* We try the expansion until it fits within the propspective output buffer. */        char * at_buf = 0;        int at_size = MAXJPATH;        int at_len = 0;        do        {            BJAM_FREE(at_buf);            at_buf = (char*)BJAM_MALLOC_ATOMIC(at_size + 1);            at_len = var_string( in, at_buf, at_size, lol );            at_size *= 2;        } while ( at_len < 0 && at_size < INT_MAX / 2 );        /* Return the result as a single item list. */        if ( at_len > 0 )        {            LIST * r;            string_copy( buf, at_buf );            r = list_new( l, newstr( buf->value) );            string_free( buf );            BJAM_FREE(at_buf);            return r;        }        BJAM_FREE(at_buf);    }    /* Just try simple copy of in to out. */    while( in < end )        if( *in++ == '$' && *in == '(' )             goto expand;    /* No variables expanded - just add copy of input string to list. */    /* Cancopyin is an optimization: if the input was already a list */    /* item, we can use the copystr() to put it on the new list. */    /* Otherwise, we use the slower newstr(). */    if( cancopyin )     {        return list_new( l, copystr( inp ) );    }    else    {        LIST* r;        string_new( buf );        string_append_range( buf, inp, end );        r = list_new( l, newstr( buf->value) );        string_free( buf );        return r;    }expand:    string_new( buf );    string_append_range( buf, inp, in - 1); /* copy the part before '$'. */    /*     * Input so far (ignore blanks):     *     *  stuff-in-outbuf $(variable) remainder     *                   ^                   ^     *                   in                  end     * Output so far:     *     *  stuff-in-outbuf $     *  ^                ^     *  out_buf          out     *     *     * We just copied the $ of $(...), so back up one on the output.     * We now find the matching close paren, copying the variable and     * modifiers between the $( and ) temporarily into out_buf, so that     * we can replace :'s with MAGIC_COLON.  This is necessary to avoid     * being confused by modifier values that are variables containing     * :'s.  Ugly.     */    depth = 1;    inp = ++in; /* skip over the '(' */    while( in < end && depth )    {        switch( *in++ )        {        case '(': depth++; break;        case ')': depth--; break;        }    }    /*     * Input so far (ignore blanks):     *     *  stuff-in-outbuf $(variable) remainder     *                    ^        ^         ^     *                    inp      in        end     */    prefix_length = buf->size;    string_append_range( buf, inp, in - 1 );    out = buf->value + prefix_length;    for ( ov = out; ov < buf->value + buf->size; ++ov )    {        switch( *ov )        {        case ':': *ov = MAGIC_COLON; break;        case '[': *ov = MAGIC_LEFT; break;        case ']': *ov = MAGIC_RIGHT; break;        }    }    /*     * Input so far (ignore blanks):     *     *  stuff-in-outbuf $(variable) remainder     *                              ^        ^     *                              in       end     * Output so far:     *     *  stuff-in-outbuf variable     *  ^               ^       ^     *  out_buf         out     ov     *     * Later we will overwrite 'variable' in out_buf, but we'll be     * done with it by then.  'variable' may be a multi-element list,      * so may each value for '$(variable element)', and so may 'remainder'.     * Thus we produce a product of three lists.     */    {        LIST *variables = 0;        LIST *remainder = 0;        LIST *vars;        /* Recursively expand variable name & rest of input */        if( out < ov )            variables = var_expand( L0, out, ov, lol, 0 );        if( in < end )            remainder = var_expand( L0, in, end, lol, 0 );        /* Now produce the result chain */        /* For each variable name */        for( vars = variables; vars; vars = list_next( vars ) )        {            LIST *value, *evalue = 0;            char *colon;            char *bracket;            string variable[1];            char *varname;            int sub1 = 0, sub2 = -1;            VAR_EDITS edits;            /* Look for a : modifier in the variable name */            /* Must copy into varname so we can modify it */            string_copy( variable, vars->string );            varname = variable->value;            if( colon = strchr( varname, MAGIC_COLON ) )            {                string_truncate( variable, colon - varname );                var_edit_parse( colon + 1, &edits );            }            /* Look for [x-y] subscripting */            /* sub1 and sub2 are x and y. */            if ( bracket = strchr( varname, MAGIC_LEFT ) )            {                /*                ** Make all syntax errors in [] subscripting                ** result in the same behavior: silenty return an empty                ** expansion (by setting sub2 = 0). Brute force parsing;                ** May get moved into yacc someday.                */                char *s = bracket + 1;                string_truncate( variable, bracket - varname );                do  /* so we can use "break" */                {                    /* Allow negative indexes. */                    if (! isdigit( *s ) && ! ( *s == '-') )                    {                        sub2 = 0;                        break;                    }                    sub1 = atoi(s);                    /* Skip over the first symbol, which is either a digit or dash. */                    s++;                    while ( isdigit( *s ) ) s++;                    if ( *s == MAGIC_RIGHT )                    {                        sub2 = sub1;                        break;                    }                    if ( *s != '-')                    {                        sub2 = 0;                        break;                    }                    s++;                    if ( *s == MAGIC_RIGHT )                    {                        sub2 = -1;                        break;                    }                    if (! isdigit( *s ) && ! ( *s == '-') )                    {                        sub2 = 0;                        break;                    }                    /* First, compute the index of the last element. */                    sub2 = atoi(s);                                   s++;                    while ( isdigit( *s ) ) s++;                    if ( *s != MAGIC_RIGHT)                        sub2 = 0;                } while (0);                /*                ** Anything but the end of the string, or the colon                ** introducing a modifier is a syntax error.                */                s++;                                if (*s && *s != MAGIC_COLON)                    sub2 = 0;                *bracket = '\0';            }            /* Get variable value, specially handling $(<), $(>), $(n) */		            if( varname[0] == '<' && !varname[1] )                value = lol_get( lol, 0 );            else if( varname[0] == '>' && !varname[1] )                value = lol_get( lol, 1 );            else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] )                value = lol_get( lol, varname[0] - '1' );            else                 value = var_get( varname );            /* Handle negitive indexes: part two. */            {                int length = list_length( value );                if (sub1 < 0)                    sub1 = length + sub1;                else                    sub1 -= 1;                if (sub2 < 0)                    sub2 = length + 1 + sub2 - sub1;                else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -