# include "jam.h"
# include "lists.h"
# include "variable.h"
# include "expand.h"
# include "filesys.h"
# include "newstr.h"
static void var_edit();
static void var_mods();
# define MAGIC_COLON '\001'
# define MAGIC_LEFT '\002'
# define MAGIC_RIGHT '\003'
LIST *
var_expand( l, in, end, lol, cancopyin )
LIST *l;
char *in;
char *end;
LOL *lol;
int cancopyin;
{
char out_buf[ MAXSYM * 3 ];
char *out = out_buf;
char *inp = in;
char *ov;
int depth;
if( DEBUG_VAREXP )
printf( "expand '%.*s'\n", end - in, in );
if( in[0] == '$' && in[1] == '(' && in[3] == ')' && !in[4] )
{
switch( in[2] )
{
case '1':
case '<':
return list_copy( l, lol_get( lol, 0 ) );
case '2':
case '>':
return list_copy( l, lol_get( lol, 1 ) );
}
}
while( in < end )
if( ( *out++ = *in++ ) == '$' && *in == '(' )
goto expand;
*out = '\0';
if( cancopyin )
return list_new( l, copystr( inp ) );
else
return list_new( l, newstr( out_buf ) );
expand:
depth = 1;
out--, in++;
ov = out;
while( in < end && depth )
{
switch( *ov++ = *in++ )
{
case '(': depth++; break;
case ')': depth--; break;
case ':': ov[-1] = MAGIC_COLON; break;
case '[': ov[-1] = MAGIC_LEFT; break;
case ']': ov[-1] = MAGIC_RIGHT; break;
}
}
ov--;
{
LIST *variables = 0;
LIST *remainder = 0;
LIST *vars;
if( out < ov )
variables = var_expand( L0, out, ov, lol, 0 );
if( in < end )
remainder = var_expand( L0, in, end, lol, 0 );
for( vars = variables; vars; vars = list_next( vars ) )
{
LIST *value;
char *colon;
char *bracket;
char varname[ MAXSYM ];
int i, sub1, sub2;
strcpy( varname, vars->string );
if( (colon = strchr( varname, MAGIC_COLON )) != NULL )
*colon = '\0';
if( (bracket = strchr( varname, MAGIC_LEFT )) != NULL )
{
char *dash;
if( (dash = strchr( bracket + 1, '-' )) != NULL )
{
*dash = '\0';
sub1 = atoi( bracket + 1 );
sub2 = atoi( dash + 1 );
}
else
{
sub1 = sub2 = atoi( bracket + 1 );
}
*bracket = '\0';
}
else
{
sub1 = sub2 = 0;
}
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 );
}
if( out == out_buf && !bracket && !colon && in == end )
{
l = list_copy( l, value );
continue;
}
for( i = 1; value; i++, value = list_next( value ) )
{
LIST *rem;
char *out1;
if( bracket && ( i < sub1 || ( sub2 && i > sub2 ) ) )
continue;
if( colon )
var_edit( value->string, colon + 1, out );
else
strcpy( out, value->string );
if( in == end )
{
l = list_new( l, newstr( out_buf ) );
continue;
}
out1 = out + strlen( out );
for( rem = remainder; rem; rem = list_next( rem ) )
{
strcpy( out1, rem->string );
l = list_new( l, newstr( out_buf ) );
}
}
}
if( variables )
list_free( variables );
if( remainder)
list_free( remainder );
if( DEBUG_VAREXP )
{
printf( "expanded to " );
list_print( l );
printf( "\n" );
}
return l;
}
}
typedef struct {
char downshift;
char upshift;
char parent;
} VAR_ACTS ;
static void
var_edit( in, mods, out )
char *in;
char *mods;
char *out;
{
FILENAME old, new;
VAR_ACTS acts;
file_parse( in, &old );
var_mods( mods, &new, &acts );
if( new.f_grist.ptr )
old.f_grist = new.f_grist;
if( new.f_root.ptr )
old.f_root = new.f_root;
if( new.f_dir.ptr )
old.f_dir = new.f_dir;
if( new.f_base.ptr )
old.f_base = new.f_base;
if( new.f_suffix.ptr )
old.f_suffix = new.f_suffix;
if( new.f_member.ptr )
old.f_member = new.f_member;
if( new.f_archive.ptr )
old.f_archive = new.f_archive;
#ifdef APPLE_EXTENSIONS
old.quoting_style = new.quoting_style;
#endif
if( acts.parent )
file_parent( &old );
file_build( &old, out, 0 );
if( acts.upshift )
{
for( ; *out; ++out )
*out = toupper( *out );
}
else if( acts.downshift )
{
for( ; *out; ++out )
*out = tolower( *out );
}
}
static void
var_mods( mods, f, acts )
char *mods;
FILENAME *f;
VAR_ACTS *acts;
{
char *flags = "GRDBSMA";
int havezeroed = 0;
memset( (char *)f, 0, sizeof( *f ) );
memset( (char *)acts, 0, sizeof( *acts ) );
#ifdef APPLE_EXTENSIONS
f->quoting_style = NO_QUOTING;
#endif
while( *mods )
{
char *fl;
struct filepart *fp;
if( *mods == 'L' )
{
acts->downshift = 1;
++mods;
continue;
}
else if( *mods == 'U' )
{
acts->upshift = 1;
++mods;
continue;
}
else if( *mods == 'P' )
{
acts->parent = 1;
++mods;
continue;
}
#ifdef APPLE_EXTENSIONS
else if( *mods == 'q' )
{
f->quoting_style = SINGLE_QUOTING;
++mods;
continue;
}
else if( *mods == 'Q' )
{
f->quoting_style = DOUBLE_QUOTING;
++mods;
continue;
}
else if( *mods == 'E' )
{
f->quoting_style = BACKSLASH_QUOTING;
++mods;
continue;
}
#endif
if( !( fl = strchr( flags, *mods++ ) ) )
break;
fp = &f->part[ fl - flags ];
if( *mods++ != '=' )
{
int i;
mods--;
if( !havezeroed++ )
for( i = 0; i < FILEPARTS; i++ )
{
f->part[ i ].len = 0;
f->part[ i ].ptr = "";
}
fp->ptr = 0;
}
else
{
char *p;
if (fp == &f->f_base)
{
f->f_archive.len = 0;
f->f_archive.ptr = "";
}
if( (p = strchr( mods, MAGIC_COLON )) != NULL )
{
fp->ptr = mods;
fp->len = p - mods;
mods = p + 1;
}
else
{
fp->ptr = mods;
fp->len = strlen( mods );
mods += fp->len;
}
}
}
}