Пример #1
0
LIST *
builtin_match(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
	LIST *l, *r;
	LIST *result = 0;

	/* For each pattern */

	for( l = lol_get( args, 0 ); l; l = l->next )
	{
	    regexp *re = jam_regcomp( l->string );

	    /* For each string to match against */

	    for( r = lol_get( args, 1 ); r; r = r->next )
		if( jam_regexec( re, r->string ) )
	    {
		int i, top;

		/* Find highest parameter */

		for( top = NSUBEXP; top-- > 1; )
		    if( re->startp[top] )
			break;

		/* And add all parameters up to highest onto list. */
		/* Must have parameters to have results! */

		for( i = 1; i <= top; i++ )
		{
		    BUFFER buff;
		    size_t l;
		    buffer_init( &buff );
		    l = re->endp[i] - re->startp[i];
		    buffer_addstring( &buff, re->startp[i], l );
		    buffer_addchar( &buff, 0 );
		    result = list_new( result, buffer_ptr( &buff ), 0 );
		    buffer_free( &buff );
		}
	    }

	    free( (char *)re );
	}

	return result;
}
Пример #2
0
static	/* Needs to be global if header caching is on */
#endif
LIST *
headers1(
	const char *file,
	LIST *hdrscan )
{
	FILE	*f;
	int	i;
	int	rec = 0;
	LIST	*result = 0;
	LISTITEM* pattern;
	regexp	*re[ MAXINC ];
	char	buf[ 1024 ];

#ifdef OPT_IMPROVED_PATIENCE_EXT
	static int count = 0;
	++count;
	if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
	    printf("*** patience...\n");
#endif

	if( !( f = fopen( file, "r" ) ) )
	    return result;

	if ( !regexhash )
	    regexhash = hashinit( sizeof(regexdata), "regex" );

	pattern = list_first(hdrscan);
	while( rec < MAXINC && pattern )
	{
	    regexdata data, *d = &data;
	    data.name = list_value(pattern);
	    if( !hashcheck( regexhash, (HASHDATA **)&d ) )
	    {
		d->re = jam_regcomp( hdrscan->string );
		(void)hashenter( regexhash, (HASHDATA **)&d );
	    }
	    re[rec++] = d->re;
		pattern = list_next(pattern);
	}

	while( fgets( buf, sizeof( buf ), f ) )
	{
	    for( i = 0; i < rec; i++ )
		if( jam_regexec( re[i], buf ) && re[i]->startp[1] )
	    {
		/* Copy and terminate extracted string. */

		char buf2[ MAXSYM ];
		int l = re[i]->endp[1] - re[i]->startp[1];
# ifdef DOWNSHIFT_PATHS
		const char *target = re[i]->startp[1];
		char *p = buf2;

		do *p++ = tolower( *target++ );
		while( --l );

		*p = 0;
#else
		memcpy( buf2, re[i]->startp[1], l );
		buf2[ l ] = 0;
# endif
		result = list_append( result, buf2, 0 );

		if( DEBUG_HEADER )
		    printf( "header found: %s\n", buf2 );
	    }
	}

/*	while( rec )
	    free( (char *)re[--rec] );
*/
	fclose( f );

	return result;
}
Пример #3
0
static LIST *headers1helper(
	FILE *f,
	LIST *hdrscan )
{
	int	i;
	int	rec = 0;
	LIST	*result = 0;
	regexp	*re[ MAXINC ];
	char	buf[ 1024 ];
	LIST	*hdrdownshift;
	int	dodownshift = 1;
	LISTITEM* pattern;

#ifdef OPT_IMPROVED_PATIENCE_EXT
	static int count = 0;
	++count;
	if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
	    printf("*** patience...\n");
#endif

	hdrdownshift = var_get( "HDRDOWNSHIFT" );
	if ( list_first(hdrdownshift) )
	{
		char const* str = list_value(list_first(hdrdownshift));
	    dodownshift = strcmp( str, "false" ) != 0  &&
		    strcmp( str, "0" ) != 0;
	}

	if ( !regexhash )
	    regexhash = hashinit( sizeof(regexdata), "regex" );

	pattern = list_first(hdrscan);
	while( rec < MAXINC && pattern )
	{
	    regexdata data, *d = &data;
	    data.name = list_value(pattern);
	    if( !hashcheck( regexhash, (HASHDATA **)&d ) )
	    {
		d->re = jam_regcomp( list_value(pattern) );
		(void)hashenter( regexhash, (HASHDATA **)&d );
	    }
	    re[rec++] = d->re;
	    pattern = list_next( pattern );
	}

	while( fgets( buf, sizeof( buf ), f ) )
	{
	    for( i = 0; i < rec; i++ )
		if( jam_regexec( re[i], buf ) && re[i]->startp[1] )
	    {
		/* Copy and terminate extracted string. */

		char buf2[ MAXSYM ];
		int l = (int)(re[i]->endp[1] - re[i]->startp[1]);
# ifdef DOWNSHIFT_PATHS
		if ( dodownshift )
		{
		    const char *target = re[i]->startp[1];
		    char *p = buf2;

		    if ( l > 0 )
		    {
			do *p++ = (char)tolower( *target++ );
			while( --l );
		    }

		    *p = 0;
		}
		else
# endif
		{
		memcpy( buf2, re[i]->startp[1], l );
		buf2[ l ] = 0;
		}

		result = list_append( result, buf2, 0 );

		if( DEBUG_HEADER )
		    printf( "header found: %s\n", buf2 );
	    }
	}

	return result;
}
Пример #4
0
LIST *
var_expand(
	LIST		*prefix,
	const char 	*in,
	const char 	*end,
	LOL		*lol,
	int		cancopyin )
{
	BUFFER buff;
	const char *inp = in;
	int depth;
	size_t save_buffer_pos, ov_save_buffer_pos;
	int literal = 0;

	if( DEBUG_VAREXP )
	    printf( "expand '%.*s'\n", end - in, in );

	/* This gets alot of cases: $(<) and $(>) */

	if( end - in == 4 && in[0] == '$' && in[1] == leftParen && in[3] == rightParen )
	{
	    switch( in[2] )
	    {
	    case '1':
	    case '<':
		return list_copy( prefix, lol_get( lol, 0 ) );

	    case '2':
	    case '>':
		return list_copy( prefix, lol_get( lol, 1 ) );
	    }
	}

	buffer_init( &buff );

	/* Just try simple copy of in to out. */

	while( in < end ) {
	    char ch = *in++;
	    buffer_addchar( &buff, ch );
	    if( ch == '$' && *in == leftParen )
		goto expand;
#ifdef OPT_EXPAND_LITERALS_EXT
	    if( ch == '@' && *in == leftParen ) {
		literal = 1;
		goto expand;
	    }
	    if( ch == '@' && in[0] == '$' && in[1] == leftParen ) {
		++in;
		literal = 1;
		goto expand;
	    }
#endif
	}

	/* 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(). */

	buffer_putchar( &buff, 0 );

	if( cancopyin ) {
	    LIST *new_list = list_append( prefix, inp, 1 );
	    buffer_free( &buff );
	    return new_list;
	}
	else {
	    LIST *new_list = list_append( prefix, buffer_ptr( &buff ), 0 );
	    buffer_free( &buff );
	    return new_list;
	}

    expand:
	/*
	 * 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;
	buffer_deltapos( &buff, -1 );
	save_buffer_pos = buffer_pos( &buff );
	in++;

	while( in < end && depth )
	{
	    char ch = *in++;
	    buffer_addchar( &buff, ch );
        if ( ch == leftParen )
        {
            depth++;
        }
        else if ( ch == rightParen )
        {
            depth--;
        }
        else
        {
	    switch( ch )
	    {
	    case ':': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_COLON ); break;
	    case '[': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_LEFT ); break;
	    case ']': buffer_deltapos( &buff, -1 ); buffer_addchar( &buff, MAGIC_RIGHT ); break;
	    }
        }
	}

	/* Copied ) - back up. */

	buffer_deltapos( &buff, -1 );
	ov_save_buffer_pos = buffer_pos( &buff );
	buffer_setpos( &buff, save_buffer_pos );

	/*
	 * 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;
	    LISTITEM *vars;

	    /* Recursively expand variable name & rest of input */

	    if( save_buffer_pos < ov_save_buffer_pos )
		variables = var_expand( L0, buffer_posptr( &buff ), buffer_ptr( &buff ) + ov_save_buffer_pos, lol, 0 );
	    if( in < end )
		remainder = var_expand( L0, in, end, lol, 0 );

	    /* Now produce the result chain */

	    /* For each variable name */

	    for( vars = list_first(variables); vars; vars = list_next( vars ) )
	    {
		LIST *value, *evalue = 0;
		LISTITEM* valueSliceStart = NULL;
#ifdef OPT_EXPAND_LITERALS_EXT
		LIST *origvalue = 0;
#endif
		char *colon;
		char *bracket;
		BUFFER varnamebuff;
		int sub1 = 0, sub2 = -1;
		VAR_EDITS edits;
		memset(&edits, 0, sizeof(VAR_EDITS));
		if (leftParen == '{') {
			edits.empty.ptr = "";
			edits.empty.len = 0;
		}

		/* Look for a : modifier in the variable name */
		/* Must copy into varname so we can modify it */

		buffer_init( &varnamebuff );
		buffer_addstring( &varnamebuff, list_value(vars), strlen( list_value(vars) ) );
		buffer_addchar( &varnamebuff, 0 );

		if( ( colon = strchr( buffer_ptr( &varnamebuff ), MAGIC_COLON ) ) )
		{
		    *colon = '\0';
		    var_edit_parse( colon + 1, &edits );
		}

		/* Look for [x-y] and [x-] subscripting */
		/* sub1 is x (0 default) */
		/* sub2 is length (-1 means forever) */

		if( ( bracket = strchr( buffer_ptr( &varnamebuff ), MAGIC_LEFT ) ) )
		{
		    char *dash;

		    if( ( dash = strchr( bracket + 1, '-' ) ) )
			*dash = '\0';

		    sub1 = atoi( bracket + 1 ) - 1;

		    if( !dash )
			sub2 = 1;
		    else if( !dash[1] || dash[1] == MAGIC_RIGHT )
			sub2 = -1;
		    else
			sub2 = atoi( dash + 1 ) - sub1;

		    *bracket = '\0';
		}

		/* Get variable value, specially handling $(<), $(>), $(n) */

#ifdef OPT_EXPAND_LITERALS_EXT
		if ( !literal )
#endif
		{
		    const char* varname = buffer_ptr( &varnamebuff );
		    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 if ( edits.targetsetting ) {
				TARGET* t = bindtarget(edits.targetname.ptr);
				SETTINGS* settings = quicksettingslookup(t, varname);
				if (settings)
					value = list_copy(L0, settings->value);
				else
					value = L0;
			} else
			value = var_get( varname );
		}
#ifdef OPT_EXPAND_LITERALS_EXT
		else {
		    origvalue = value = list_append( L0, buffer_ptr( &varnamebuff ), 0 );
		}
#endif

		/* The fast path: $(x) - just copy the variable value. */
		/* This is only an optimization */

		if( buffer_isempty( &buff ) && !bracket && !colon && in == end )
		{
		    prefix = list_copy( prefix, value );
		    buffer_free( &buff );
		    continue;
		}

		/* Handle start subscript */
		valueSliceStart = list_first(value);
		while(sub1 > 0 && valueSliceStart)
		{
			sub1 -= 1;
			valueSliceStart = list_next(valueSliceStart);
		}

		/* Empty w/ :E=default? */

		if( !valueSliceStart && (colon || leftParen == '{') && edits.empty.ptr ) {
		    evalue = value = list_append( L0, edits.empty.ptr, 0 );
		    valueSliceStart = list_first(value);
		}

#ifdef OPT_EXPAND_LITERALS_EXT
		if ( colon && edits.expandliteral ) {
		    LOL lol;
		    char const* string = list_value(list_first(value));
		    LIST *newvalue = var_expand( L0, string, string + strlen( string ), &lol, 0 );
		    if ( origvalue ) {
			list_free( origvalue );
			origvalue = 0;
		    }
		    value = newvalue;
			valueSliceStart = list_first(value);
		    sub2 = -1;
		}
#endif

#ifdef OPT_EXPAND_FILEGLOB_EXT
		if ( edits.wildcard ) {
		    LIST *newl = L0;
		    for( ; valueSliceStart; valueSliceStart = list_next( valueSliceStart ) ) {
				LIST *foundfiles = L0;
				fileglob* glob;

				/* Handle end subscript (length actually) */
				if( sub2 >= 0 && --sub2 < 0 )
					break;

				glob = fileglob_Create( list_value(valueSliceStart) );
				while ( fileglob_Next( glob ) ) {
					foundfiles = list_append( foundfiles, fileglob_FileName( glob ) + edits.wildcard_remove_prepend.len, 0 );
				}
				fileglob_Destroy( glob );

				/* TODO: Efficiency: Just append to newl above? */
				newl = list_copy( newl, foundfiles );
				list_free( foundfiles );
			}
			if ( origvalue ) {
				list_free( origvalue );
				origvalue = 0;
		    }

		    value = newl;
		    origvalue = value;
			valueSliceStart = list_first(value);
		}
#endif

		/* For each variable value */

		for( ; valueSliceStart; valueSliceStart = list_next( valueSliceStart ) )
		{
		    LISTITEM *rem;
		    size_t save_buffer_pos;
		    size_t end_buffer_pos;
		    const char *valuestring;

		    /* Handle end subscript (length actually) */

		    if( sub2 >= 0 && --sub2 < 0 )
			break;

		    /* Apply : mods, if present */

		    save_buffer_pos = buffer_pos( &buff );

		    valuestring = list_value(valueSliceStart);

#ifdef OPT_EXPAND_BINDING_EXT
		    if( colon && edits.expandbinding ) {
				SETTINGS *expandText;
				TARGET *t = bindtarget( valuestring );
				expandText = quicksettingslookup( t, "EXPAND_TEXT" );
				if ( expandText && list_first(expandText->value) ) {
					valuestring = list_value(list_first(expandText->value));
				} else {
					if( t->binding == T_BIND_UNBOUND ) {
						t->boundname = search_using_target_settings( t, t->name, &t->time );
						t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
					}
					valuestring = t->boundname;
				}
		    }
#endif

		    if( colon && edits.filemods ) {
			var_edit_file( valuestring, &buff, &edits );
		    } else {
			buffer_addstring( &buff, valuestring, strlen( valuestring ) + 1 );
		    }
		    buffer_setpos( &buff, save_buffer_pos );

		    if( colon && ( edits.upshift || edits.downshift ) )
			var_edit_shift( buffer_posptr( &buff ), &edits );

#ifdef OPT_SLASH_MODIFIERS_EXT
		    if( colon && ( edits.fslash || edits.bslash ) )
			var_edit_slash( buffer_posptr( &buff ), &edits );
#endif

#ifdef OPT_EXPAND_ESCAPE_PATH_EXT
			if ( colon && edits.escapepath )
			{
				const char* ptr = buffer_posptr( &buff );
				const char* endptr = ptr + strlen( ptr );
				BUFFER escapebuff;
				buffer_init( &escapebuff );
			    save_buffer_pos = buffer_pos( &buff );

#ifdef NT
				while ( ptr != endptr  &&  *ptr != ' '  &&  *ptr != '/' )
					++ptr;
				if (*ptr == ' '  ||  *ptr == '/' ) {
					buffer_addchar( &escapebuff, '"' );
					buffer_addstring( &escapebuff, buffer_posptr( &buff ), endptr - buffer_posptr( &buff ) );
					buffer_addchar( &escapebuff, '"' );
					buffer_addchar( &escapebuff, 0 );
					buffer_addstring( &buff, buffer_ptr( &escapebuff ), buffer_pos( &escapebuff ) );
				}

#else
				while ( ptr != endptr ) {
					if ( *ptr == ' '  ||  *ptr == '\\'  ||  *ptr == leftParen  ||  *ptr == rightParen  ||  *ptr == '"' ) {
						buffer_addchar( &escapebuff, '\\' );
					}
					buffer_addchar( &escapebuff, *ptr );
					++ptr;
				}
				buffer_addchar( &escapebuff, 0 );
				buffer_addstring( &buff, buffer_ptr( &escapebuff ), buffer_pos( &escapebuff ) );
#endif

				buffer_setpos( &buff, save_buffer_pos );
				buffer_free( &escapebuff );
			}
#endif

		    /* 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( valueSliceStart ) || list_next( vars ) ) )
		    {
			buffer_setpos( &buff, buffer_pos( &buff ) + strlen( buffer_posptr( &buff ) ) );
			buffer_addstring( &buff, edits.join.ptr, strlen( edits.join.ptr ) + 1 );
			buffer_deltapos( &buff, -1 );
			continue;
		    }

		    /* If no remainder, append result to output chain. */

		    if( in == end )
		    {
			prefix = list_append( prefix, buffer_ptr( &buff ), 0 );
			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' */

		    save_buffer_pos = buffer_pos( &buff );
		    end_buffer_pos = strlen( buffer_ptr( &buff ) );
		    buffer_setpos( &buff, end_buffer_pos );

		    for( rem = list_first(remainder); rem; rem = list_next( rem ) )
		    {
			buffer_addstring( &buff, list_value(rem), strlen( list_value(rem) ) + 1 );
			buffer_setpos( &buff, end_buffer_pos );
			prefix = list_append( prefix, buffer_ptr( &buff ), 0 );
		    }

		    buffer_setpos( &buff, save_buffer_pos );
		}

		/* Toss used empty */

		if( evalue )
		    list_free( evalue );

#ifdef OPT_EXPAND_LITERALS_EXT
		if ( origvalue )
		    list_free( origvalue );
#endif

#ifdef OPT_EXPAND_INCLUDES_EXCLUDES_EXT
		if ( edits.includes_excludes ) {
		    LIST *newl = L0;
		    LISTITEM* l;

		    LIST *origprefix = prefix;
		    int hasInclude = 0;

		    if ( !regexhash )
			regexhash = hashinit( sizeof(regexdata), "regex" );

		    {
			LISTITEM *inex = list_first(edits.includes_excludes);
			while ( inex ) {
			    char mod = list_value(inex)[0];
			    inex = list_next( inex );

			    if ( mod == 'I' ) {
				hasInclude = 1;
			    }
			}
		    }

		    for (l = list_first(prefix) ; l; l = list_next( l ) )
		    {
			LISTITEM *inex = list_first(edits.includes_excludes);
			int remove = hasInclude;

			while ( inex ) {
			    char mod = list_value(inex)[0];
			    regexp *re;
			    regexdata data, *d = &data;
			    inex = list_next( inex );
			    data.name = list_value(inex);
			    if( !hashcheck( regexhash, (HASHDATA **)&d ) )
			    {
				d->re = jam_regcomp( list_value(inex) );
				(void)hashenter( regexhash, (HASHDATA **)&d );
			    }
			    re = d->re;
			    inex = list_next( inex );

			    if ( mod == 'X' ) {
				if( jam_regexec( re, list_value(l) ) )
				    remove = 1;
			    } else if ( mod == 'I' ) {
				if( jam_regexec( re, list_value(l) ) )
				    remove = 0;
			    }
			}

			if ( !remove )
			    newl = list_append( newl, list_value(l), 1 );
		    }

			/* TODO: Efficiency: Just modify prefix? */
		    list_free( origprefix );
		    prefix = newl;
		}
#endif

//#ifdef OPT_EXPAND_LITERALS_EXT
//		buffer_free( &buff );
//#endif
#ifdef OPT_EXPAND_INCLUDES_EXCLUDES_EXT
		list_free( edits.includes_excludes );
#endif

	    }

	    /* variables & remainder were gifts from var_expand */
	    /* and must be freed */

		list_free( variables );
		list_free( remainder );

	    if( DEBUG_VAREXP )
	    {
		printf( "expanded to " );
		list_print( prefix );
		printf( "\n" );
	    }

	    buffer_free( &buff );
	    return prefix;
	}
}