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

📄 expand.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 2 页
字号:
                    sub2 -= sub1;                /*                ** The "sub2 < 0" test handles the semantic error                ** of sub2 < sub1.                */                if ( sub2 < 0 )                    sub2 = 0;            }            /* The fast path: $(x) - just copy the variable value. */            /* This is only an optimization */            if( out == out_buf && !bracket && !colon && in == end )            {                string_free( variable );                l = list_copy( l, value );                continue;            }            /* Handle start subscript */            while( sub1 > 0 && value )                --sub1, value = list_next( value );            /* Empty w/ :E=default? */            if( !value && colon && edits.empty.ptr )                evalue = value = list_new( L0, newstr( edits.empty.ptr ) );            /* For each variable value */            string_new( out1 );            for( ; value; value = list_next( value ) )            {                LIST *rem;                size_t postfix_start;                /* Handle end subscript (length actually) */                if( sub2 >= 0 && --sub2 < 0 )                    break;                string_truncate( buf, prefix_length );                /* Apply : mods, if present */                if( colon && edits.filemods )                    var_edit_file( value->string, out1, &edits );                else                    string_append( out1, value->string );                if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )                    var_edit_shift( out1, &edits );                /* Handle :J=joinval */                /* If we have more values for this var, just */                /* keep appending them (with the join value) */                /* rather than creating separate LIST elements. */                if( colon && edits.join.ptr &&                     ( list_next( value ) || list_next( vars ) ) )                {                    string_append( out1, edits.join.ptr );                    continue;                }                string_append( buf, out1->value );                string_free( out1 );                string_new( out1 );                /* If no remainder, append result to output chain. */                if( in == end )                {                    l = list_new( l, newstr( buf->value ) );                    continue;                }                /* For each remainder, append the complete string */                /* to the output chain. */                /* Remember the end of the variable expansion so */                /* we can just tack on each instance of 'remainder' */                postfix_start = buf->size;                for( rem = remainder; rem; rem = list_next( rem ) )                {                    string_truncate( buf, postfix_start );                    string_append( buf, rem->string );                    l = list_new( l, newstr( buf->value ) );                }            }            string_free( out1 );            /* Toss used empty */            if( evalue )                list_free( evalue );            string_free( variable );        }        /* variables & remainder were gifts from var_expand */        /* and must be freed */        if( variables )            list_free( variables );        if( remainder)            list_free( remainder );        if( DEBUG_VAREXP )        {            printf( "expanded to " );            list_print( l );            printf( "\n" );        }        string_free( buf );        return l;    }}/* * var_edit_parse() - parse : modifiers into PATHNAME structure * * The : modifiers in a $(varname:modifier) currently support replacing * or omitting elements of a filename, and so they are parsed into a  * PATHNAME structure (which contains pointers into the original string). * * Modifiers of the form "X=value" replace the component X with * the given value.  Modifiers without the "=value" cause everything  * but the component X to be omitted.  X is one of: * *	G <grist> *	D directory name *	B base name *	S .suffix *	M (member) *	R root directory - prepended to whole path * * This routine sets: * *	f->f_xxx.ptr = 0 *	f->f_xxx.len = 0 *		-> leave the original component xxx * *	f->f_xxx.ptr = string *	f->f_xxx.len = strlen( string ) *		-> replace component xxx with string * *	f->f_xxx.ptr = "" *	f->f_xxx.len = 0 *		-> omit component xxx * * var_edit_file() below and path_build() obligingly follow this convention. */static voidvar_edit_parse(	char		*mods,	VAR_EDITS	*edits ){	int havezeroed = 0;	memset( (char *)edits, 0, sizeof( *edits ) );	while( *mods )	{	    char *p;	    PATHPART *fp;	    switch( *mods++ )	    {	    case 'L': edits->downshift = 1; continue;	    case 'U': edits->upshift = 1; continue;	    case 'P': edits->parent = edits->filemods = 1; continue;	    case 'E': fp = &edits->empty; goto strval;	    case 'J': fp = &edits->join; goto strval;	    case 'G': fp = &edits->f.f_grist; goto fileval;	    case 'R': fp = &edits->f.f_root; goto fileval;	    case 'D': fp = &edits->f.f_dir; goto fileval;	    case 'B': fp = &edits->f.f_base; goto fileval;	    case 'S': fp = &edits->f.f_suffix; goto fileval;	    case 'M': fp = &edits->f.f_member; goto fileval;            case 'T': edits->to_slashes = 1; continue;            case 'W': edits->to_windows = 1; continue;	    default: return; /* should complain, but so what... */	    }	fileval:	    /* Handle :CHARS, where each char (without a following =) */	    /* selects a particular file path element.  On the first such */	    /* char, we deselect all others (by setting ptr = "", len = 0) */	    /* and for each char we select that element (by setting ptr = 0) */	    edits->filemods = 1;	    if( *mods != '=' )	    {		int i;		if( !havezeroed++ )		    for( i = 0; i < 6; i++ )		{		    edits->f.part[ i ].len = 0;		    edits->f.part[ i ].ptr = "";		}		fp->ptr = 0;		continue;	    }	strval:	    /* Handle :X=value, or :X */	    if( *mods != '=' )	    {		fp->ptr = "";		fp->len = 0;	    }	    else if( p = strchr( mods, MAGIC_COLON ) )	    {		*p = 0;		fp->ptr = ++mods;		fp->len = p - mods;		mods = p + 1;	    }	    else	    {		fp->ptr = ++mods;		fp->len = strlen( mods );		mods += fp->len;	    }	}}/* * var_edit_file() - copy input target name to output, modifying filename */	static voidvar_edit_file( 	char	*in,	string	*out,	VAR_EDITS *edits ){	PATHNAME pathname;	/* Parse apart original filename, putting parts into "pathname" */	path_parse( in, &pathname );	/* Replace any pathname with edits->f */	if( edits->f.f_grist.ptr )	    pathname.f_grist = edits->f.f_grist;	if( edits->f.f_root.ptr )	    pathname.f_root = edits->f.f_root;	if( edits->f.f_dir.ptr )	    pathname.f_dir = edits->f.f_dir;	if( edits->f.f_base.ptr )	    pathname.f_base = edits->f.f_base;	if( edits->f.f_suffix.ptr )	    pathname.f_suffix = edits->f.f_suffix;	if( edits->f.f_member.ptr )	    pathname.f_member = edits->f.f_member;	/* If requested, modify pathname to point to parent */	if( edits->parent )	    path_parent( &pathname );	/* Put filename back together */    path_build( &pathname, out, 0 );}/* * var_edit_shift() - do upshift/downshift mods */static voidvar_edit_shift( 	string	*out,	VAR_EDITS *edits ){	/* Handle upshifting, downshifting and slash translation now */    char *p;    for ( p = out->value; *p; ++p)    {        if (edits->upshift)        {            *p = toupper( *p );        }        else if ( edits->downshift )        {            *p = tolower( *p );        }         if ( edits->to_slashes )        {            if ( *p == '\\')                *p = '/';        }# ifdef OS_CYGWIN        if ( edits->to_windows )        {            char result[MAX_PATH + 1];            cygwin_conv_to_win32_path(out->value, result);            assert(strlen(result) <= MAX_PATH);            string_free( out );            string_copy( out, result );        }# endif    }    out->size = p - out->value;}#ifndef NDEBUGvoid var_expand_unit_test(){    LOL lol[1];    LIST* l, *l2;    LIST *expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );    LIST *e2;    char axyb[] = "a$(xy)b";    char azb[] = "a$($(z))b";    char path[] = "$(p:W)";        # ifdef OS_CYGWIN    char cygpath[256];    cygwin_conv_to_posix_path("c:\\foo\\bar", cygpath);    # else    char cygpath[] = "/cygdrive/c/foo/bar";    # endif            lol_init(lol);    var_set("xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );    var_set("z", list_new( L0, newstr( "xy" ) ), VAR_SET );    var_set("p", list_new( L0, newstr( cygpath ) ), VAR_SET );    l = var_expand( 0, axyb, axyb + sizeof(axyb) - 1, lol, 0 );    for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )        assert( !strcmp( e2->string, l2->string ) );    assert(l2 == 0 && e2 == 0);    list_free(l);        l = var_expand( 0, azb, azb + sizeof(azb) - 1, lol, 0 );    for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )        assert( !strcmp( e2->string, l2->string ) );    assert(l2 == 0 && e2 == 0);    list_free(l);    l = var_expand( 0, path, path + sizeof(path) - 1, lol, 0 );    assert(l != 0);    assert(list_next(l) == 0);    # ifdef OS_CYGWIN    assert( !strcmp( l->string, "c:\\foo\\bar" ) );    # else     assert( !strcmp( l->string, cygpath ) );    # endif       list_free(l);    list_free(expected);        lol_free(lol);}#endif/*     Local Variables:     tab-width: 8     End: */

⌨️ 快捷键说明

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