Esempio n. 1
0
/*
 * frees data
 */
int
rewrite_subst_destroy(
		struct rewrite_subst **psubst
)
{
	int			n;
	struct rewrite_subst	*subst;

	assert( psubst != NULL );
	assert( *psubst != NULL );

	subst = *psubst;

	for ( n = 0; n < subst->lt_num_submatch; n++ ) {
		if ( subst->lt_subs[ n ].bv_val ) {
			free( subst->lt_subs[ n ].bv_val );
			subst->lt_subs[ n ].bv_val = NULL;
		}

		switch ( subst->lt_submatch[ n ].ls_type ) {
		case REWRITE_SUBMATCH_ASIS:
			break;

		case REWRITE_SUBMATCH_XMAP:
			rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map );
			break;

		case REWRITE_SUBMATCH_MAP_W_ARG:
			rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map );
			break;

		default:
			break;
		}
	}

	free( subst->lt_submatch );
	subst->lt_submatch = NULL;

	/* last one */
	if ( subst->lt_subs[ n ].bv_val ) {
		free( subst->lt_subs[ n ].bv_val );
		subst->lt_subs[ n ].bv_val = NULL;
	}

	free( subst->lt_subs );
	subst->lt_subs = NULL;

	free( subst );
	*psubst = NULL;

	return 0;
}
Esempio n. 2
0
/*
 * Compiles a substitution pattern
 */
struct rewrite_subst *
rewrite_subst_compile(
		struct rewrite_info *info,
		const char *str
)
{
	size_t subs_len;
	struct berval *subs = NULL, *tmps;
	struct rewrite_submatch *submatch = NULL;

	struct rewrite_subst *s = NULL;

	char *result, *begin, *p;
	int nsub = 0, l;

	assert( info != NULL );
	assert( str != NULL );

	result = strdup( str );
	if ( result == NULL ) {
		return NULL;
	}

	/*
	 * Take care of substitution string
	 */
	for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) {

		/*
		 * Keep only single escapes '%'
		 */
		if (  !IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
			continue;
		} 

		if (  IS_REWRITE_SUBMATCH_ESCAPE( p[ 1 ] ) ) {
			/* Pull &p[1] over p, including the trailing '\0' */
			AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) );
			continue;
		}

		tmps = ( struct berval * )realloc( subs,
				sizeof( struct berval )*( nsub + 1 ) );
		if ( tmps == NULL ) {
			goto cleanup;
		}
		subs = tmps;
		
		/*
		 * I think an `if l > 0' at runtime is better outside than
		 * inside a function call ...
		 */
		l = p - begin;
		if ( l > 0 ) {
			subs_len += l;
			subs[ nsub ].bv_len = l;
			subs[ nsub ].bv_val = malloc( l + 1 );
			if ( subs[ nsub ].bv_val == NULL ) {
				goto cleanup;
			}
			AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
			subs[ nsub ].bv_val[ l ] = '\0';
		} else {
			subs[ nsub ].bv_val = NULL;
			subs[ nsub ].bv_len = 0;
		}
		
		/*
		 * Substitution pattern
		 */
		if ( isdigit( (unsigned char) p[ 1 ] ) ) {
			struct rewrite_submatch *tmpsm;
			int d = p[ 1 ] - '0';

			/*
			 * Add a new value substitution scheme
			 */

			tmpsm = ( struct rewrite_submatch * )realloc( submatch,
					sizeof( struct rewrite_submatch )*( nsub + 1 ) );
			if ( tmpsm == NULL ) {
				goto cleanup;
			}
			submatch = tmpsm;
			submatch[ nsub ].ls_submatch = d;

			/*
			 * If there is no argument, use default
			 * (substitute substring as is)
			 */
			if ( p[ 2 ] != '{' ) {
				submatch[ nsub ].ls_type = 
					REWRITE_SUBMATCH_ASIS;
				submatch[ nsub ].ls_map = NULL;
				begin = ++p + 1;

			} else {
				struct rewrite_map *map;

				submatch[ nsub ].ls_type =
					REWRITE_SUBMATCH_XMAP;

				map = rewrite_xmap_parse( info,
						p + 3, (const char **)&begin );
				if ( map == NULL ) {
					goto cleanup;
				}
				submatch[ nsub ].ls_map = map;
				p = begin - 1;
			}

		/*
		 * Map with args ...
		 */
		} else if ( p[ 1 ] == '{' ) {
			struct rewrite_map *map;
			struct rewrite_submatch *tmpsm;

			map = rewrite_map_parse( info, p + 2,
					(const char **)&begin );
			if ( map == NULL ) {
				goto cleanup;
			}
			p = begin - 1;

			/*
			 * Add a new value substitution scheme
			 */
			tmpsm = ( struct rewrite_submatch * )realloc( submatch,
					sizeof( struct rewrite_submatch )*( nsub + 1 ) );
			if ( tmpsm == NULL ) {
				rewrite_map_destroy( &map );
				goto cleanup;
			}
			submatch = tmpsm;
			submatch[ nsub ].ls_type =
				REWRITE_SUBMATCH_MAP_W_ARG;
			submatch[ nsub ].ls_map = map;

		/*
		 * Escape '%' ...
		 */
		} else if ( p[ 1 ] == '%' ) {
			AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) );
			continue;

		} else {
			goto cleanup;
		}

		nsub++;
	}
	
	/*
	 * Last part of string
	 */
	tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
	if ( tmps == NULL ) {
		/*
		 * XXX need to free the value subst stuff!
		 */
		free( subs );
		goto cleanup;
	}
	subs = tmps;
	l = p - begin;
	if ( l > 0 ) {
		subs_len += l;
		subs[ nsub ].bv_len = l;
		subs[ nsub ].bv_val = malloc( l + 1 );
		if ( subs[ nsub ].bv_val == NULL ) {
			goto cleanup;
		}
		AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
		subs[ nsub ].bv_val[ l ] = '\0';
	} else {
		subs[ nsub ].bv_val = NULL;
		subs[ nsub ].bv_len = 0;
	}

	s = calloc( sizeof( struct rewrite_subst ), 1 );
	if ( s == NULL ) {
		goto cleanup;
	}

	s->lt_subs_len = subs_len;
	s->lt_subs = subs;
	s->lt_num_submatch = nsub;
	s->lt_submatch = submatch;
	subs = NULL;
	submatch = NULL;

cleanup:;
	if ( subs ) {
		for ( l=0; l<nsub; l++ ) {
			free( subs[nsub].bv_val );
		}
		free( subs );
	}
	if ( submatch ) {
		for ( l=0; l<nsub; l++ ) {
			free( submatch[nsub].ls_map );
		}
		free( submatch );
	}
	free( result );

	return s;
}