Пример #1
0
void path_build( PATHNAME * f, string * file )
{
    file_build1( f, file );

    /* Do not prepend root if it is '.' or the directory is rooted. */
    if ( f->f_root.len
        && !( f->f_root.len == 1 && f->f_root.ptr[ 0 ] == '.' )
        && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '/' )
#if PATH_DELIM == '\\'
        && !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '\\' )
        && !( f->f_dir.len && f->f_dir.ptr[ 1 ] == ':' )
#endif
    )
    {
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len
            );
        /* If 'root' already ends with a path delimeter, do not add another one.
         */
        if ( !is_path_delim( f->f_root.ptr[ f->f_root.len - 1 ] ) )
            string_push_back( file, as_path_delim( f->f_root.ptr[ f->f_root.len
                ] ) );
    }

    if ( f->f_dir.len )
        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );

    /* Put path separator between dir and file. */
    /* Special case for root dir: do not add another path separator. */
    if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len )
#if PATH_DELIM == '\\'
        && !( f->f_dir.len == 3 && f->f_dir.ptr[ 1 ] == ':' )
#endif
        && !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[ 0 ] ) ) )
        string_push_back( file, as_path_delim( f->f_dir.ptr[ f->f_dir.len ] ) );

    if ( f->f_base.len )
        string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len
            );

    if ( f->f_suffix.len )
        string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr +
            f->f_suffix.len );

    if ( f->f_member.len )
    {
        string_push_back( file, '(' );
        string_append_range( file, f->f_member.ptr, f->f_member.ptr +
            f->f_member.len );
        string_push_back( file, ')' );
    }
}
Пример #2
0
void file_build1( PATHNAME * f, string * file )
{
    if ( DEBUG_SEARCH )
    {
        printf("build file: ");
        if ( f->f_root.len )
            printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
        if ( f->f_dir.len )
            printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
        if ( f->f_base.len )
            printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
        printf( "\n" );
    }

    /* Start with the grist.  If the current grist isn't */
    /* surrounded by <>'s, add them. */

    if ( f->f_grist.len )
    {
        if ( f->f_grist.ptr[0] != '<' )
            string_push_back( file, '<' );
        string_append_range(
            file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len );
        if ( file->value[file->size - 1] != '>' )
            string_push_back( file, '>' );
    }
}
Пример #3
0
RULE * lookup_rule( OBJECT * rulename, module_t * m, int local_only )
{
    RULE       rule;
    RULE     * r = &rule;
    RULE     * result = 0;
    module_t * original_module = m;

    r->name = rulename;

    if ( m->class_module )
        m = m->class_module;

    if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) )
        result = r;
    else if ( !local_only && m->imported_modules )
    {
        /* Try splitting the name into module and rule. */
        char *p = strchr( object_str( r->name ), '.' ) ;
        if ( p )
        {
            string buf[1];
            OBJECT * module_part;
            OBJECT * rule_part;
            string_new( buf );
            string_append_range( buf, object_str( r->name ), p );
            module_part = object_new( buf->value );
            rule_part = object_new( p + 1 );
            r->name = module_part;
            /* Now, r->name keeps the module name, and p+1 keeps the rule name.
             */
            if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
                result = lookup_rule( rule_part, bindmodule( module_part ), 1 );
            object_free( rule_part );
            object_free( module_part );
            string_free( buf );
        }
    }

    if ( result )
    {
        if ( local_only && !result->exported )
            result = 0;
        else
        {
            /* Lookup started in class module. We have found a rule in class
             * module, which is marked for execution in that module, or in some
             * instances. Mark it for execution in the instance where we started
             * the lookup.
             */
            int execute_in_class = ( result->module == m );
            int execute_in_some_instance = ( result->module->class_module &&
                ( result->module->class_module == m ) );
            if ( ( original_module != m ) &&
                ( execute_in_class || execute_in_some_instance ) )
                result->module = original_module;
        }
    }

    return result;
}
LIST* get_grist(char* f)
{
    char* end = strchr(f, '>');
    string s[1];
    LIST* result;
    
    string_new(s);

    string_append_range(s, f, end+1);
    result = list_new(0, newstr(s->value));
        
    string_free(s);
    return result;
}
Пример #5
0
LIST * regex_replace( FRAME * frame, int flags )
{
    LIST * args = lol_get( frame->args, 0 );
    OBJECT * s;
    OBJECT * match;
    OBJECT * replacement;
    regexp * re;
    const char * pos;
    string buf[ 1 ];
    LIST * result;
    LISTITER iter = list_begin( args );
    s = list_item( iter );
    iter = list_next( iter );
    match = list_item( iter );
    iter = list_next( iter );
    replacement = list_item(iter );
    
    re = regex_compile( match );
    
    string_new( buf );

    pos = object_str( s );
    while ( regexec( re, pos ) )
    {
        string_append_range( buf, pos, re->startp[ 0 ] );
        string_append( buf, object_str( replacement ) );
        pos = re->endp[ 0 ];
    }
    string_append( buf, pos );

    result = list_new( object_new( buf->value ) );

    string_free( buf );

    return result;
}
Пример #6
0
void path_build( PATHNAME * f, string * file, int binding )
{
    struct dirinf root;
    struct dirinf dir;
    int g;

    file_build1( f, file );

    /* Get info on root and dir for combining. */
    dir_flags( f->f_root.ptr, f->f_root.len, &root );
    dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );

    /* Combine. */
    switch ( g = grid[ root.flags ][ dir.flags ] )
    {
    case G_DIR:
        /* take dir */
        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );
        break;

    case G_ROOT:
        /* take root */
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
        break;

    case G_VAD:
        /* root's dev + abs directory */
        string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
        string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len  );
        break;

    case G_DRD:
    case G_DDD:
        /* root's dev:[dir] + rel directory */
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );

        /* sanity checks: root ends with ] */

        if ( file->value[file->size - 1] == ']' )
            string_pop_back( file );

        /* Add . if separating two -'s */

        if ( g == G_DDD )
            string_push_back( file, '.' );

        /* skip [ of dir */
        string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1  );
        break;

    case G_VRD:
        /* root's dev + rel directory made abs */
        string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
        string_push_back( file, '[' );
        /* skip [. of rel dir */
        string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2  );
        break;
    }

# ifdef DEBUG
    if ( DEBUG_SEARCH && ( root.flags || dir.flags ) )
        printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
                grid[ root.flags ][ dir.flags ], file->value );
# endif

    /*
     * Now do the special :P modifier when no file was present.
     *  (none)      (none)
     *  [dir1.dir2] [dir1]
     *  [dir]       [000000]
     *  [.dir]      (none)
     *  []      []
     */

    if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent )
    {
        char * p = file->value + file->size;
        while ( p-- > file->value )
        {
            if ( *p == '.' )
            {
                /* If we've truncated everything and left with '[',
                   return empty string. */
                if ( p == file->value + 1 )
                    string_truncate( file, 0 );
                else
                {
                    string_truncate( file, p - file->value );
                    string_push_back( file, ']' );
                }
                break;
            }
            
            if ( *p == '-' )
            {
                /* handle .- or - */
                if ( ( p > file->value ) && ( p[ -1 ] == '.' ) )
                    --p;

                *p++ = ']';
                break;
            }
            
            if ( *p == '[' )
            {
                if ( p[ 1 ] == ']' )
                {
                    /* CONSIDER: I don't see any use of this code. We immediately
                       break, and 'p' is a local variable. */
                    p += 2;
                }
                else
                {
                    string_truncate( file, p - file->value );
                    string_append( file, "[000000]" );
                }
                break;
            }
        }
    }

    /* Now copy the file pieces. */
    if ( f->f_base.len )
    {
        string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len  );
    }

    /* If there is no suffix, we append a "." onto all generated names. This
     * keeps VMS from appending its own (wrong) idea of what the suffix should
     * be.
     */
    if ( f->f_suffix.len )
        string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len  );
    else if ( binding && f->f_base.len )
        string_push_back( file, '.' );

    if ( f->f_member.len )
    {
        string_push_back( file, '(' );
        string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len  );
        string_push_back( file, ')' );
    }

# ifdef DEBUG
    if ( DEBUG_SEARCH )
        printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
               f->f_root.len, f->f_root.ptr,
               f->f_dir.len, f->f_dir.ptr,
               f->f_base.len, f->f_base.ptr,
               f->f_suffix.len, f->f_suffix.ptr,
               f->f_member.len, f->f_member.ptr,
               file->value );
# endif
}
Пример #7
0
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] )
    {
        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 ) );
        }
    }

    /* 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
                    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;
    }
}
Пример #8
0
void
path_build(
    PATHNAME *f,
    string  *file,
    int binding )
{
    file_build1( f, file );

    /* Don't prepend root if it's . or directory is rooted */
# if PATH_DELIM == '/'

    if ( f->f_root.len
        && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
        && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )

# else /* unix */

    if ( f->f_root.len
        && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
        && !( f->f_dir.len && f->f_dir.ptr[0] == '/' )
        && !( f->f_dir.len && f->f_dir.ptr[0] == '\\' )
        && !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) )

# endif /* unix */

    {
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
        /* If 'root' already ends with path delimeter,
           don't add yet another one. */
        if ( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
            string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
    }

    if ( f->f_dir.len )
        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );

    /* UNIX: Put / between dir and file */
    /* NT:   Put \ between dir and file */

    if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) )
    {
        /* UNIX: Special case for dir \ : don't add another \ */
        /* NT:   Special case for dir / : don't add another / */

# if PATH_DELIM == '\\'
        if ( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
# endif
            if ( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
                string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) );
    }

    if ( f->f_base.len )
    {
        string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len  );
    }

    if ( f->f_suffix.len )
    {
        string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len  );
    }

    if ( f->f_member.len )
    {
        string_push_back( file, '(' );
        string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len  );
        string_push_back( file, ')' );
    }
}
Пример #9
0
void exec_cmd
(
    string const * cmd_orig,
    ExecCmdCallback func,
    void * closure,
    LIST * shell
)
{
    int const slot = get_free_cmdtab_slot();
    int const is_raw_cmd = is_raw_command_request( shell );
    string cmd_local[ 1 ];

    /* Initialize default shell - anything more than /Q/C is non-portable. */
    static LIST * default_shell;
    if ( !default_shell )
        default_shell = list_new( object_new( "cmd.exe /Q/C" ) );

    /* Specifying no shell means requesting the default shell. */
    if ( list_empty( shell ) )
        shell = default_shell;

    if ( DEBUG_EXECCMD )
        if ( is_raw_cmd )
            out_printf( "Executing raw command directly\n" );
        else
        {
            out_printf( "Executing using a command file and the shell: " );
            list_print( shell );
            out_printf( "\n" );
        }

    /* If we are running a raw command directly - trim its leading whitespaces
     * as well as any trailing all-whitespace lines but keep any trailing
     * whitespace in the final/only line containing something other than
     * whitespace).
     */
    if ( is_raw_cmd )
    {
        char const * start = cmd_orig->value;
        char const * p = cmd_orig->value + cmd_orig->size;
        char const * end = p;
        while ( isspace( *start ) ) ++start;
        while ( p > start && isspace( p[ -1 ] ) )
            if ( *--p == '\n' )
                end = p;
        string_new( cmd_local );
        string_append_range( cmd_local, start, end );
        assert( cmd_local->size == raw_command_length( cmd_orig->value ) );
    }
    /* If we are not running a raw command directly, prepare a command file to
     * be executed using an external shell and the actual command string using
     * that command file.
     */
    else
    {
        char const * const cmd_file = prepare_command_file( cmd_orig, slot );
        char const * argv[ MAXARGC + 1 ];  /* +1 for NULL */
        argv_from_shell( argv, shell, cmd_file, slot );
        string_new_from_argv( cmd_local, argv );
    }

    /* Catch interrupts whenever commands are running. */
    if ( !intr_installed )
    {
        intr_installed = 1;
        signal( SIGINT, onintr );
    }

    /* Save input data into the selected running commands table slot. */
    cmdtab[ slot ].func = func;
    cmdtab[ slot ].closure = closure;

    /* Invoke the actual external process using the constructed command line. */
    invoke_cmd( cmd_local->value, slot );

    /* Free our local command string copy. */
    string_free( cmd_local );
}
Пример #10
0
LIST * regex_transform( FRAME * frame, int flags )
{
    LIST * const l = lol_get( frame->args, 0 );
    LIST * const pattern = lol_get( frame->args, 1 );
    LIST * const indices_list = lol_get( frame->args, 2 );
    int * indices = 0;
    int size;
    LIST * result = L0;

    if ( !list_empty( indices_list ) )
    {
        int * p;
        LISTITER iter = list_begin( indices_list );
        LISTITER const end = list_end( indices_list );
        size = list_length( indices_list );
        indices = (int *)BJAM_MALLOC( size * sizeof( int ) );
        for ( p = indices; iter != end; iter = list_next( iter ) )
            *p++ = atoi( object_str( list_item( iter ) ) );
    }
    else
    {
        size = 1;
        indices = (int *)BJAM_MALLOC( sizeof( int ) );
        *indices = 1;
    }

    {
        /* Result is cached and intentionally never freed */
        regexp * const re = regex_compile( list_front( pattern ) );

        LISTITER iter = list_begin( l );
        LISTITER const end = list_end( l );

        string buf[ 1 ];
        string_new( buf );

        for ( ; iter != end; iter = list_next( iter ) )
        {
            if ( regexec( re, object_str( list_item( iter ) ) ) )
            {
                int i = 0;
                for ( ; i < size; ++i )
                {
                    int const index = indices[ i ];
                    /* Skip empty submatches. Not sure it is right in all cases,
                     * but surely is right for the case for which this routine
                     * is optimized -- header scanning.
                     */
                    if ( re->startp[ index ] != re->endp[ index ] )
                    {
                        string_append_range( buf, re->startp[ index ],
                            re->endp[ index ] );
                        result = list_push_back( result, object_new( buf->value
                            ) );
                        string_truncate( buf, 0 );
                    }
                }
            }
        }
        string_free( buf );
    }

    BJAM_FREE( indices );
    return result;
}
Пример #11
0
int var_string( const 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;
                const char * ine = in + 2;
                const 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;
                    OBJECT * file_name = 0;
                    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 = path_tmpfile();
                        file_name_s = object_str(file_name);
                        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 );
                    }

                    /* Expand the file value into the file reference. */
                    var_string_to_file( split + 3, ine - split - 4, file_name_s,
                        lol );

                    if ( file_name )
                    {
                        object_free( file_name );
                    }

                    /* 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. */
        if ( out >= oute )
            return -1;
        /* Do not increment, intentionally. */
        *out = '\0';

        /* If a variable encountered, expand it and and embed the
         * space-separated members of the list in the output.
         */
        if ( dollar )
        {
            LIST * l = var_expand( L0, lastword, out, lol, 0 );
            LIST * saved = l;

            out = lastword;

            while ( l )
            {
                int so = strlen( object_str( l->value ) );

                if ( out + so >= oute )
                    return -1;

                strcpy( out, object_str( l->value ) );
                out += so;
                l = list_next( l );
                if ( l ) *out++ = ' ';
            }

            list_free( saved );
        }
    }

    if ( out >= oute )
        return -1;

    *out++ = '\0';

    return out - out0;
}
Пример #12
0
void string_push_back( string* self, char x )
{
    string_append_range( self, &x, &x + 1 );
}
Пример #13
0
void
var_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 );
}
Пример #14
0
int
var_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++;
                #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)
                    {
                        printf( "no file specified!\n" );
                        exit( EXITBAD );
                    }
                    
                    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 */
                        if ( !globs.noexec )
                            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

		*out++ = *in++;
	    }

        /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
        if (out >= oute)
            return -1;
        /* Don't increment, intentionally. */
        *out= '\0';
           
	    /* If a variable encountered, expand it and and embed the */
	    /* space-separated members of the list in the output. */

	    if( dollar )
	    {
		LIST	*l;

		l = var_expand( L0, lastword, out, lol, 0 );

		out = lastword;

		while ( l )
		{
		    int so = strlen( l->string );

		    if( out + so >= oute )
			return -1;

		    strcpy( out, l->string );
		    out += so;
		    l = list_next( l );
		    if ( l ) *out++ = ' ';
		}

		list_free( l );
	    }
	}

	if( out >= oute )
	    return -1;

	*out++ = '\0';

	return out - out0;
}
Пример #15
0
static void canonicWindowsPath( char const * const path, int const path_length,
    string * const out )
{
    char const * last_element;
    unsigned long saved_size;
    char const * p;

    /* This is only called via path_key(), which initializes the cache. */
    assert( path_key_cache );

    if ( !path_length )
        return;

    if ( path_length == 1 && path[ 0 ] == '\\' )
    {
        string_push_back( out, '\\' );
        return;
    }

    if ( path[ 1 ] == ':' &&
        ( path_length == 2 ||
        ( path_length == 3 && path[ 2 ] == '\\' ) ) )
    {
        string_push_back( out, toupper( path[ 0 ] ) );
        string_push_back( out, ':' );
        string_push_back( out, '\\' );
        return;
    }

    /* Find last '\\'. */
    for ( p = path + path_length - 1; p >= path && *p != '\\'; --p );
    last_element = p + 1;

    /* Special case '\' && 'D:\' - include trailing '\'. */
    if ( p == path ||
        p == path + 2 && path[ 1 ] == ':' )
        ++p;

    if ( p >= path )
    {
        char const * const dir = path;
        int const dir_length = p - path;
        OBJECT * const dir_obj = object_new_range( dir, dir_length );
        int found;
        path_key_entry * const result = (path_key_entry *)hash_insert(
            path_key_cache, dir_obj, &found );
        if ( !found )
        {
            result->path = dir_obj;
            canonicWindowsPath( dir, dir_length, out );
            result->key = object_new( out->value );
        }
        else
        {
            object_free( dir_obj );
            string_append( out, object_str( result->key ) );
        }
    }

    if ( out->size && out->value[ out->size - 1 ] != '\\' )
        string_push_back( out, '\\' );

    saved_size = out->size;
    string_append_range( out, last_element, path + path_length );

    {
        char const * const n = last_element;
        int const n_length = path + path_length - n;
        if ( !( n_length == 1 && n[ 0 ] == '.' )
            && !( n_length == 2 && n[ 0 ] == '.' && n[ 1 ] == '.' ) )
        {
            WIN32_FIND_DATA fd;
            HANDLE const hf = FindFirstFileA( out->value, &fd );
            if ( hf != INVALID_HANDLE_VALUE )
            {
                string_truncate( out, saved_size );
                string_append( out, fd.cFileName );
                FindClose( hf );
            }
        }
    }
}
Пример #16
0
void
path_build(
	PATHNAME *f,
	string* file,
	int	binding )
{
    int dflag, rflag, act;

    file_build1( f, file );
	
    /* Combine root & directory, according to the grid. */
	
    dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
    rflag = file_flags( f->f_root.ptr, f->f_root.len );
	
    switch( act = grid[ rflag ][ dflag ] )
    {
    case G_DTDR:
        {
            /* :: of rel dir */
            string_push_back( file, DELIM );
        }
        /* fall through */
		
    case G_DIR: 	
        /* take dir */
        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );
        break;
		
    case G_ROOT:	
        /* take root */
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
        break;
	    
    case G_CAT:	
        /* prepend root to dir */
        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
        if( file->value[file->size - 1] == DELIM )
            string_pop_back( file );
        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );
        break;
	
    case G_DDDD:	
        /* make it ::: (../..) */
        string_append( file, ":::" );
        break;
    }

    /* Put : between dir and file (if none already) */
	
    if( act != G_MT && 
        file->value[file->size - 1] != DELIM && 
        ( f->f_base.len || f->f_suffix.len ) )
    {
        string_push_back( file, DELIM );
    }

    if( f->f_base.len )
    {
        string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len  );
    }

    if( f->f_suffix.len )
    {
        string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len  );
    }

    if( f->f_member.len )
    {
        string_push_back( file, '(' );
        string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len  );
        string_push_back( file, ')' );
    }
	
    if( DEBUG_SEARCH )
        printf(" -> '%s'\n", file->value);
}
Пример #17
0
void var_defines( struct module_t * module, char * const * e, int preprocess )
{
    string buf[ 1 ];

    string_new( buf );

    for ( ; *e; ++e )
    {
        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
            {
                char * p;
                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 );
}
Пример #18
0
/*
rule transform ( list * : pattern : indices * )
{
    indices ?= 1 ;
    local result ;
    for local e in $(list)
    {
        local m = [ MATCH $(pattern) : $(e) ] ;
        if $(m)
        {
            result += $(m[$(indices)]) ;
        }        
    }
    return $(result) ;
}
*/
LIST *regex_transform( FRAME *frame, int flags )
{
    LIST* l = lol_get( frame->args, 0 );    
    LIST* pattern = lol_get( frame->args, 1 );    
    LIST* indices_list = lol_get(frame->args, 2);
    int* indices = 0;
    int size;
    int* p;
    LIST* result = 0;

    string buf[1];
    string_new(buf);

    if (indices_list)
    {
        size = list_length(indices_list);
        indices = (int*)BJAM_MALLOC(size*sizeof(int));
        for(p = indices; indices_list; indices_list = indices_list->next)
        {
            *p++ = atoi(object_str(indices_list->value));
        }        
    }
    else 
    {
        size = 1;
        indices = (int*)BJAM_MALLOC(sizeof(int));
        *indices = 1;
    }

    {
        /* Result is cached and intentionally never freed */
        regexp *re = regex_compile( pattern->value );

        for(; l; l = l->next)
        {
            if( regexec( re, object_str( l->value ) ) )
            {
                int i = 0;
                for(; i < size; ++i)
                {
                    int index = indices[i];
                    /* Skip empty submatches. Not sure it's right in all cases,
                       but surely is right for the case for which this routine
                       is optimized -- header scanning.
                    */
                    if (re->startp[index] != re->endp[index])
                    {
                        string_append_range( buf, re->startp[index], re->endp[index] );
                        result = list_new( result, object_new( buf->value ) ); 
                        string_truncate( buf, 0 );
                    }
                }
            }
        }
        string_free( buf );
    }

    BJAM_FREE(indices);
    
    return result;
}