Example #1
0
void filecache_disable(TARGET *t)
{
	BUFFER buff;
	LIST *filecache;
	pushsettings( t->settings );
	filecache = var_get( "FILECACHE" );
	if ( !filecache ) {
		popsettings( t->settings );
		return;
	}

	buffer_init(&buff);
	buffer_addstring(&buff, filecache->string, strlen(filecache->string));
	buffer_addstring(&buff, ".USE", 4);
	buffer_addchar(&buff, 0);
	var_set(buffer_ptr(&buff), list_new(L0, "0", 0), VAR_SET);
	buffer_free(&buff);

	buffer_init(&buff);
	buffer_addstring(&buff, filecache->string, strlen(filecache->string));
	buffer_addstring(&buff, ".GENERATE", 9);
	buffer_addchar(&buff, 0);
	var_set(buffer_ptr(&buff), list_new(L0, "0", 0), VAR_SET);
	buffer_free(&buff);
}
Example #2
0
static int filecache_findlink(const char *cachedname, MD5SUM blobmd5sum)
{
	int haveblobmd5sum = 0;

	/* Search for the appropriate .link file that matches the target. */
	BUFFER linknamebuff;
	BUFFER wildbuff;
	buffer_init(&wildbuff);
	buffer_addstring(&wildbuff, cachedname, strlen(cachedname));
	buffer_addstring(&wildbuff, "-*.link", 7);
	buffer_addchar(&wildbuff, 0);

	if (findfile(buffer_ptr(&wildbuff), &linknamebuff))
	{
		const char* dashPtr = strrchr(buffer_ptr(&linknamebuff), '-');
		const char* slashPtr = strrchr(buffer_ptr(&linknamebuff), '/');
#ifdef OS_NT
		const char* backslashPtr = strrchr(buffer_ptr(&linknamebuff), '\\');
		if (backslashPtr > slashPtr)
			slashPtr = backslashPtr;
#endif
		if (dashPtr > slashPtr)
			haveblobmd5sum = read_md5sum_string(dashPtr + 1, blobmd5sum);
	}

	buffer_free(&linknamebuff);
	buffer_free(&wildbuff);

	return haveblobmd5sum;
}
Example #3
0
LIST *
builtin_usefilecache(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
	LIST *l = lol_get( args, 0 );
	LIST *l2 = lol_get( args, 1 );
	const char* cachevar = l2 ? l2->string : "generic";
	BUFFER buff;
	buffer_init( &buff );
	buffer_addstring( &buff, "FILECACHE.", 10 );
	buffer_addstring( &buff, cachevar, strlen( cachevar ) );
	buffer_addchar( &buff, 0 );

	for( ; l; l = list_next( l ) ) {
	    TARGET *t = bindtarget( l->string );
	    t->settings = addsettings( t->settings, VAR_SET, "FILECACHE", list_new( L0, buffer_ptr( &buff ), 0 ) );
	    t->flags |= parse->num;
	}

	buffer_free( &buff );

	return L0;
}
Example #4
0
/*
 * Get a filename in cache for given md5sum.
 */
const char *filecache_getfilename(TARGET *t, MD5SUM sum, const char* extension)
{
	BUFFER buff;
	size_t pos;
	const char *cachedir;
	const char* result;

	cachedir = filecache_getpath(t);
	/* if no cachedir, no cachefiles */
	if (cachedir==NULL) {
		return NULL;
	}

	/* put the cachedir in front of buffer */
	buffer_init(&buff);
	buffer_addstring(&buff, cachedir, strlen(cachedir));
	buffer_addchar(&buff, '/');

	pos = buffer_pos(&buff);
	buffer_addstring(&buff, "000/", 4);

	/* add use md5 as filename */
	buffer_addstring(&buff, md5tostring(sum), 32);
	if (extension)
		buffer_addstring(&buff, extension, strlen(extension));
	buffer_addchar(&buff, 0);

	buffer_setpos(&buff, pos);
	buffer_putstring(&buff, buffer_ptr(&buff) + pos + 4, 3);

	result = newstr(buffer_ptr(&buff));
	buffer_free(&buff);
	return result;
}
Example #5
0
void filecache_disable(TARGET *t)
{
	BUFFER buff;
	LIST *filecache;
	char const* filecacheStr;
	pushsettings( t->settings );
	filecache = var_get( "FILECACHE" );
	if ( !list_first(filecache) ) {
		popsettings( t->settings );
		return;
	}

	filecacheStr = list_value(list_first(filecache));

	buffer_init(&buff);
	buffer_addstring(&buff, filecacheStr, strlen(filecacheStr));
	buffer_addstring(&buff, ".USE", 4);
	buffer_addchar(&buff, 0);
	var_set(buffer_ptr(&buff), list_append(L0, "0", 0), VAR_SET);
	buffer_free(&buff);

	buffer_init(&buff);
	buffer_addstring(&buff, filecacheStr, strlen(filecacheStr));
	buffer_addstring(&buff, ".GENERATE", 9);
	buffer_addchar(&buff, 0);
	var_set(buffer_ptr(&buff), list_append(L0, "0", 0), VAR_SET);
	buffer_free(&buff);
}
Example #6
0
LIST *filecache_fillvalues(TARGET *t)
{
	LIST *filecache;

	if ( !( t->flags & T_FLAG_USEFILECACHE ) )
		return 0;

	filecache = var_get( "FILECACHE" );
	if ( filecache ) {
		LIST *l;
		BUFFER buff;
		buffer_init(&buff);
		buffer_addstring(&buff, filecache->string, strlen(filecache->string));
		buffer_addstring(&buff, ".USE", 4);
		buffer_addchar(&buff, 0);
		l = var_get( buffer_ptr( &buff ) );
		if ( l  &&  atoi( l->string ) != 0) {
			t->filecache_use = 1;
		}
		buffer_free(&buff);

		buffer_init(&buff);
		buffer_addstring(&buff, filecache->string, strlen(filecache->string));
		buffer_addstring(&buff, ".GENERATE", 9);
		buffer_addchar(&buff, 0);
		l = var_get( buffer_ptr( &buff ) );
		if ( l  &&  atoi( l->string ) != 0) {
			t->filecache_generate = 1;
		}
		buffer_free(&buff);
	}

	return filecache;
}
/**
	\internal Simple path splicing (assumes no '/' in either part)
	\author Matthias Wandel ([email protected]) http://www.sentex.net/~mwandel/
**/
static void SplicePath(BUFFER* dest, const char * p1, const char * p2) {
	size_t l;
	buffer_reset(dest);
	l = strlen(p1);
	if (l == 0) {
		buffer_addstring(dest, p2, strlen(p2) + 1);
	} else {
		buffer_addstring(dest, p1, l + 1);
		if (buffer_ptr(dest)[l-1] != '/'  &&  buffer_ptr(dest)[l-1] != ':') {
			buffer_ptr(dest)[l] = '/';
			buffer_deltapos(dest, 1);
		}
		buffer_deltapos(dest, -1);
		buffer_addstring(dest, p2, strlen(p2) + 1);
	}
}
Example #8
0
int str_gsub (BUFFER *buff, const char *src, const char *p, const char *repl, int max_s) {
  int anchor;
  int n = 0;
  MatchState ms;
  size_t srcl = strlen(src);
  if (max_s == -1)
	max_s = srcl + 1;
  anchor = (*p == '^') ? (p++, 1) : 0;
  n = 0;
  ms.buff = buff;
  ms.src_init = src;
  ms.src_end = src+srcl;
  while (n < max_s) {
    const char *e;
    ms.level = 0;
    e = match(&ms, src, p);
    if (e) {
      n++;
      add_s(&ms, src, e, repl, strlen(repl));
    }
    if (e && e>src) /* non empty match? */
      src = e;  /* skip it */
	else if (src < ms.src_end) {
      buffer_addchar(ms.buff, *src++);
	} else break;
    if (anchor) break;
  }
  buffer_addstring(ms.buff, src, ms.src_end-src);
  buffer_addchar(ms.buff, 0);
  return n;
}
Example #9
0
static void push_onecapture (MatchState *ms, int i, const char *s,
                                                    const char *e) {
  if (i >= ms->level) {
	if (i == 0) { /* ms->level == 0, too */
      buffer_addstring(ms->buff, s, e - s);  /* add whole match */
	} else
      gsub_error("invalid capture index");
  }
  else {
    ptrdiff_t l = ms->capture[i].len;
    if (l == CAP_UNFINISHED) gsub_error("unfinished capture");
	if (l == CAP_POSITION) {
      // lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
	  assert(0);
	} else
      buffer_addstring(ms->buff, ms->capture[i].init, l);
  }
}
Example #10
0
int findfile(const char* wildcard, BUFFER* foundfilebuff)
{
    HANDLE handle;
    WIN32_FIND_DATA fd;
    const char* lastslash;

    buffer_init(foundfilebuff);
    handle = FindFirstFile(wildcard, &fd);
    if (handle == INVALID_HANDLE_VALUE)
	return 0;
    FindClose(handle);

    lastslash = max(strrchr(wildcard, '/'), strrchr(wildcard, '\\'));
    buffer_addstring(foundfilebuff, wildcard, lastslash - wildcard + 1);
    buffer_addstring(foundfilebuff, fd.cFileName, strlen( fd.cFileName ));
    buffer_addchar(foundfilebuff, 0);
    return 1;
}
Example #11
0
int findfile(const char* wildcard, BUFFER* foundfilebuff)
{
	DIR* dirp;
	struct dirent* dp;
    const char* lastslash;
	const char* lastslash2;
	BUFFER pathbuff;

	lastslash = strrchr(wildcard, '/');
	lastslash2 = strrchr(wildcard, '\\');
	lastslash = lastslash > lastslash2 ? lastslash : lastslash2;

	buffer_init(&pathbuff);
	buffer_addstring(&pathbuff, wildcard, lastslash - wildcard);
	buffer_addchar(&pathbuff, 0);

    buffer_init(foundfilebuff);

	dirp = opendir(buffer_ptr(&pathbuff));
	if (!dirp)
	{
		buffer_free(&pathbuff);
		return 0;
	}

	// Any files found?
	while ((dp = readdir(dirp)) != NULL)
	{
		if (wildmatch(lastslash + 1, dp->d_name, 1))
		{
			buffer_addstring(foundfilebuff, wildcard, lastslash - wildcard + 1);
			buffer_addstring(foundfilebuff, dp->d_name, strlen(dp->d_name));
			buffer_addchar(foundfilebuff, 0);
			closedir(dirp);
			return 1;
		}
	}

	closedir(dirp);
	return 0;
}
Example #12
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;
}
Example #13
0
LIST *filecache_fillvalues(TARGET *t)
{
	LIST *filecache;

	if ( !( t->flags & T_FLAG_USEFILECACHE ) )
		return 0;

	filecache = var_get( "FILECACHE" );
	if ( list_first(filecache) ) {
		LIST *l;
		BUFFER buff;
		char const* filecacheStr = list_value(list_first(filecache));

		buffer_init(&buff);
		buffer_addstring(&buff, filecacheStr, strlen(filecacheStr));
		buffer_addstring(&buff, ".USE", 4);
		buffer_addchar(&buff, 0);
		l = var_get( buffer_ptr( &buff ) );
		if ( list_first(l)  &&  atoi( list_value(list_first(l)) ) != 0) {
			t->filecache_use = 1;
		}
		buffer_free(&buff);

		buffer_init(&buff);
		buffer_addstring(&buff, filecacheStr, strlen(filecacheStr));
		buffer_addstring(&buff, ".GENERATE", 9);
		buffer_addchar(&buff, 0);
		l = var_get( buffer_ptr( &buff ) );
		if ( list_first(l)  &&  atoi(list_value(list_first(l))) != 0) {
			t->filecache_generate = 1;
		}
		buffer_free(&buff);
	}

	return filecache;
}
Example #14
0
/* Based on code from ftjam by David Turner */
LIST *
builtin_split(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
    LIST*	input  = lol_get( args, 0 );
    LIST*	tokens = lol_get( args, 1 );
    LIST*	result = L0;
	char	token[256];
	BUFFER  buff;

	buffer_init( &buff );

    /* build token array */
    memset( token, 0, sizeof( token ) );
    for ( ; tokens; tokens = tokens->next ) {
        const char* s = tokens->string;
        for ( ; *s; s++ )
            token[(unsigned char)*s] = 1;
    }

    /* now parse the input and split it */
    for ( ; input; input = input->next ) {
		const char* ptr = input->string;
		const char* lastPtr = input->string;

		while ( *ptr ) {
            if ( token[(unsigned char) *ptr] ) {
                size_t count = ptr - lastPtr;
                if ( count > 0 ) {
					buffer_reset( &buff );
					buffer_addstring( &buff, lastPtr, count );
					buffer_addchar( &buff, 0 );

                    result = list_new( result, buffer_ptr( &buff ), 0 );
                }
				lastPtr = ptr + 1;
            }
			++ptr;
        }
        if ( ptr > lastPtr )
            result = list_new( result, lastPtr, 0 );
    }

	buffer_free( &buff );
    return  result;
}
Example #15
0
static void
var_edit_file(
	const char *in,
	BUFFER *buff,
	VAR_EDITS *edits )
{
	PATHNAME pathname;
	char		buf[ MAXJPATH ];

	/* 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 */

#ifdef OPT_ROOT_PATHS_AS_ABSOLUTE_EXT
	path_build( &pathname, buf, 0, 1 );
#else
	path_build( &pathname, buf, 0 );
#endif
	buffer_addstring( buff, buf, strlen( buf ) + 1 );
}
Example #16
0
static void add_s (MatchState *ms, const char *s, const char *e, const char *news, size_t l) {
  size_t i;
  for (i = 0; i < l; i++) {
	if (news[i] != L_ESC) {
	  buffer_addchar(ms->buff, news[i]);
	} else {
      i++;  /* skip ESC */
	  if (!isdigit(uchar(news[i]))) {
        buffer_addchar(ms->buff, news[i]);
	  } else if (news[i] == '0') {
        buffer_addstring(ms->buff, s, e - s);
	  } else {
        push_onecapture(ms, news[i] - '1', s, e);
//        luaL_addvalue(b);  /* add capture to accumulated result */
      }
    }
  }
}
Example #17
0
void filecache_update(TARGET *t, MD5SUM buildmd5sum)
{
	MD5SUM blobmd5sum;
	int haveblobmd5sum = 0;
	const char *cachedname;
	const char *blobname;
	int cacheerror;

	if (!t->filecache_generate)
		return;

	/* If the buildmd5sum is empty, then the file doesn't exist. */
	cacheerror = ismd5empty(buildmd5sum);
	if (cacheerror)
		return;

	haveblobmd5sum = 0;
	cachedname = filecache_getfilename(t, buildmd5sum, NULL);
	if (!cachedname)
		return;

	/* Search for the appropriate .link file that matches the target. */
	haveblobmd5sum = filecache_findlink(cachedname, blobmd5sum);

	/* If we weren't able to determine the target md5sum, do it now. */
	if (!haveblobmd5sum)
	{
		getcachedmd5sum( t, 1 );
		memcpy(blobmd5sum, t->contentchecksum->contentmd5sum, MD5_SUMSIZE);
		if (ismd5empty(t->contentchecksum->contentmd5sum))
			return;
	}

	{
		/* Is the blob already there? */
		time_t blobtime;
		blobname = filecache_getfilename(t, blobmd5sum, ".blob");
		if (file_time(blobname, &blobtime) == -1)
		{
			time_t blobpartialtime;
			const char *blobpartialname;

			if(DEBUG_MD5HASH)
				printf("Caching %s as %s\n", t->name, cachedname);
			else
				printf("Caching %s\n", t->name);

			/* Write the new .blob to the cache. */
			blobpartialname = filecache_getfilename(t, blobmd5sum, ".blob.partial");
			if (file_time(blobpartialname, &blobpartialtime) == -1)
			{
				if (copyfile(blobpartialname, t->boundname, &blobmd5sum) == 0  ||
					rename(blobpartialname, blobname) != 0)
				{
					printf("** Unable to write %s to cache.\n", t->name);
					filecache_disable(t);
					return;
				}
			}
		}
	}

	/* Write the new .link file to the cache. */
	{
		FILE *file;
		BUFFER linknamebuff;
		buffer_init(&linknamebuff);
		buffer_addstring(&linknamebuff, cachedname, strlen(cachedname));
		buffer_addchar(&linknamebuff, '-');
		buffer_addstring(&linknamebuff, md5tostring(blobmd5sum), 32);
		buffer_addstring(&linknamebuff, ".link", 5);
		buffer_addchar(&linknamebuff, 0);

		file_mkdir(buffer_ptr(&linknamebuff));
		file = fopen(buffer_ptr(&linknamebuff), "wb");
		if (file)
		{
			write_md5sum(file, blobmd5sum);
			write_string(file, t->name);
			fclose(file);
		}

		buffer_free(&linknamebuff);
	}
}
Example #18
0
void filecache_update(TARGET *t)
{
	MD5SUM blobmd5sum;
	int haveblobmd5sum = 0;
	const char *cachedname;
	const char *blobname;
	int cacheerror;

	if (!t->filecache_generate)
		return;

	/* If the buildmd5sum is empty, then the file doesn't exist. */
	cacheerror = ismd5empty(t->buildmd5sum);
	if (cacheerror)
		return;

	haveblobmd5sum = 0;
	cachedname = filecache_getfilename(t, t->buildmd5sum, NULL);
	if (!cachedname)
		return;

	/* Search for the appropriate .link file that matches the target. */
	haveblobmd5sum = filecache_findlink(cachedname, blobmd5sum);

	/* If we weren't able to determine the target md5sum, do it now. */
	if (!haveblobmd5sum)
	{
#ifdef OPT_BUILTIN_LUA_SUPPORT_EXT
		LIST *md5callback;

		pushsettings( t->settings );
		md5callback = var_get( "MD5CALLBACK" );
		popsettings( t->settings );

		if ( md5callback )
		{
			luahelper_md5callback(t->boundname, blobmd5sum, md5callback->string);
		}
		else
		{
#endif
			md5file(t->boundname, blobmd5sum);
#ifdef OPT_BUILTIN_LUA_SUPPORT_EXT
		}
#endif
		memcpy(t->contentmd5sum, blobmd5sum, sizeof(MD5SUM));
		if (ismd5empty(t->contentmd5sum))
			return;
	}

	{
		/* Is the blob already there? */
		time_t blobtime;
		blobname = filecache_getfilename(t, blobmd5sum, ".blob");
		if (file_time(blobname, &blobtime) == -1)
		{
			time_t blobpartialtime;
			const char *blobpartialname;

			if(DEBUG_MD5HASH)
				printf("Caching %s as %s\n", t->name, cachedname);
			else
				printf("Caching %s\n", t->name);

			/* Write the new .blob to the cache. */
			blobpartialname = filecache_getfilename(t, blobmd5sum, ".blob.partial");
			if (file_time(blobpartialname, &blobpartialtime) == -1)
			{
				if (copyfile(blobpartialname, t->boundname, &blobmd5sum) == 0  ||
					rename(blobpartialname, blobname) != 0)
				{
					printf("** Unable to write %s to cache.\n", t->name, cachedname);
					filecache_disable(t);
					return;
				}
			}
		}
	}

	/* Write the new .link file to the cache. */
	{
		FILE *file;
		BUFFER linknamebuff;
		buffer_init(&linknamebuff);
		buffer_addstring(&linknamebuff, cachedname, strlen(cachedname));
		buffer_addchar(&linknamebuff, '-');
		buffer_addstring(&linknamebuff, md5tostring(blobmd5sum), 32);
		buffer_addstring(&linknamebuff, ".link", 5);
		buffer_addchar(&linknamebuff, 0);

		file_mkdir(buffer_ptr(&linknamebuff));
		file = fopen(buffer_ptr(&linknamebuff), "wb");
		if (file)
		{
			write_md5sum(file, blobmd5sum);
			write_string(file, t->name);
			fclose(file);
		}

		buffer_free(&linknamebuff);
	}
}
int _fileglob_GlobHelper(fileglob* self, const char* inPattern) {
	fileglob_Context* context = self->context;
	int hasWildcard;
	int found;

Setup:
	if (!context) {
		context = (fileglob_Context*)self->allocFunction(self->userData, NULL, sizeof(fileglob_Context));
		context->prev = self->context;
#if defined(WIN32)
		context->handle = INVALID_HANDLE_VALUE;
#else
		context->dirp = NULL;
		context->hasattr = 0;
		context->statted = 0;
#endif
		context->pattern = NULL;
		context->iterNode = NULL;
		context->directoryListHead = context->directoryListTail = 0;
		context->basePathLastSlashPos = 0;
		buffer_initwithalloc(&context->patternBuf, self->allocFunction, self->userData);
		buffer_addstring(&context->patternBuf, inPattern, strlen(inPattern) + 1);
		buffer_initwithalloc(&context->basePath, self->allocFunction, self->userData);
		buffer_initwithalloc(&context->matchPattern, self->allocFunction, self->userData);
		self->context = context;
		if (context->prev == NULL)
			return 1;
	}

DoRecursion:
	found = 1;

	if (!context->pattern) {
		char* pattern;

		context->basePathEndPos = context->basePathLastSlashPos = 0;
		context->recurseAtPos = (size_t)-1;

		// Split the path into base path and pattern to match against.
		hasWildcard = 0;

		for (pattern = buffer_ptr(&context->patternBuf); *pattern != '\0'; ++pattern) {
			char ch = *pattern;

			// Is it a '?' ?
			if (ch == '?')
				hasWildcard = 1;

			// Is it a '*' ?
			else if (ch == '*') {
				hasWildcard = 1;

				// Is there a '**'?
				if (pattern[1] == '*') {
					// If we're just starting the pattern or the characters immediately
					// preceding the pattern are a drive letter ':' or a directory path
					// '/', then set up the internals for later recursion.
					if (pattern == buffer_ptr(&context->patternBuf)  ||  pattern[-1] == '/'  ||  pattern[-1] == ':') {
						char ch2 = pattern[2];
						if (ch2 == '/') {
							context->recurseAtPos = pattern - buffer_ptr(&context->patternBuf);
							memcpy(pattern, pattern + 3, strlen(pattern) - 2);
							buffer_deltapos(&context->patternBuf, -3);
						} else if (ch2 == '\0') {
							context->recurseAtPos = pattern - buffer_ptr(&context->patternBuf);
							*pattern = '\0';
						}
					}
				}
			}

			// Is there a '/' or ':' in the pattern at this location?
			if (ch == '/'  ||  ch == ':') {
				if (hasWildcard)
					break;
				else {
					if (pattern[1])
						context->basePathLastSlashPos = pattern - buffer_ptr(&context->patternBuf) + 1;
					context->basePathEndPos = pattern - buffer_ptr(&context->patternBuf) + 1;
				}
			}
		}

		context->pattern = pattern;

		// Copy the directory down.
		context->basePathLen = context->basePathEndPos;
		buffer_reset(&context->basePath);
		buffer_addstring(&context->basePath, buffer_ptr(&context->patternBuf), context->basePathLen);
		buffer_addchar(&context->basePath, 0);

		if (context->iterNode) {
			context->matchFiles = *context->pattern == 0;
			goto NextDirectory;
		}
	}

#if defined(WIN32)
	if (context->handle == INVALID_HANDLE_VALUE) {
#else
	if (!context->dirp  &&  !context->statted) {
#endif
		size_t matchLen;

		// Did we make it to the end of the pattern?  If so, we should match files,
		// since there were no slashes encountered.
		context->matchFiles = *context->pattern == 0;

		// Copy the wildcard matching string.
		matchLen = (context->pattern - buffer_ptr(&context->patternBuf)) - context->basePathLen;
		buffer_reset(&context->matchPattern);
		buffer_addstring(&context->matchPattern, buffer_ptr(&context->patternBuf) + context->basePathLen, matchLen + 1);
		buffer_deltapos(&context->matchPattern, -1);
		if (*buffer_posptr(&context->matchPattern) == '/') {
			buffer_deltapos(&context->matchPattern, 1);
			buffer_addchar(&context->matchPattern, 0);
		}

#if defined(WIN32)
		// Do the file search with *.* in the directory specified in basePattern.
		buffer_setpos(&context->basePath, context->basePathEndPos);
		buffer_addstring(&context->basePath, "*.*", 4);

		// Start the find.
		context->handle = FindFirstFile(buffer_ptr(&context->basePath), &context->fd);
		if (context->handle == INVALID_HANDLE_VALUE) {
			found = 0;
		}
#else
		// Start the find.
		buffer_setpos(&context->basePath, context->basePathEndPos);
		buffer_addchar(&context->basePath, 0);
		context->dirp = opendir(buffer_ptr(&context->basePath)[0] ? buffer_ptr(&context->basePath) : ".");
		if (!context->dirp) {
			found = 0;
		} else {
			context->dp = readdir(context->dirp);
			found = context->dp != NULL;
		}
#endif

		// Clear out the *.* so we can use the original basePattern string.
		buffer_setpos(&context->basePath, context->basePathEndPos);
		buffer_putchar(&context->basePath, 0);
	} else {
		goto NextFile;
	}

	// Any files found?
#if defined(WIN32)
	if (context->handle != INVALID_HANDLE_VALUE) {
#else
	if (context->dirp) {
#endif
		for (;;) {
#if defined(WIN32)
			char* filename = context->fd.cFileName;
#else
			char* filename = context->dp->d_name;
			context->hasattr = 0;
#endif

			// Is the file a directory?
#if defined(WIN32)
			if (context->fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
#else
			if (context->dp->d_type == DT_DIR) {
#endif
				// Knock out "." or ".."
				int ignore = filename[0] == '.'  &&
						(filename[1] == 0  ||
							(filename[1] == '.'  &&  filename[2] == 0));

				// Should this file be ignored?
				int matches = 0;
				if (!ignore) {
					size_t len = strlen(filename);
					filename[len] = '/';
					filename[len + 1] = '\0';
					matches = fileglob_WildMatch(buffer_ptr(&context->matchPattern), filename, 0);
				}

				// Do a wildcard match.
				if (!ignore  &&  matches) {
					// It matched.  Let's see if the file should be ignored.

					// See if this is a directory to ignore.
					ignore = _fileglob_MatchIgnoreDirectoryPattern(self, filename);

					// Should this file be ignored?
					if (!ignore) {
						_fileglob_list_append(self, &context->directoryListHead, &context->directoryListTail, filename);

						// Is this pattern exclusive?
						if (self->exclusiveDirectoryPatternsHead) {
							if (_fileglob_MatchExclusiveDirectoryPattern(self, filename))
								break;
						} else {
							if ((!context->matchFiles  &&  context->pattern[0] == '/'  &&  context->pattern[1] == 0)
									||  (self->filesAndFolders))
								break;
						}
					}
				}
			} else {
				// Do a wildcard match.
				if (fileglob_WildMatch(buffer_ptr(&context->matchPattern), filename, 0)) {
					// It matched.  Let's see if the file should be ignored.
					int ignore = _fileglob_MatchIgnoreFilePattern(self, filename);

					// Is this pattern exclusive?
					if (!ignore  &&  self->exclusiveFilePatternsHead) {
						ignore = !_fileglob_MatchExclusiveFilePattern(self, filename);
					}

					// Should this file be ignored?
					if (!ignore) {
						if (context->matchFiles)
							break;
					}
				}
			}

NextFile:
			// Look up the next file.
#if defined(WIN32)
			found = FindNextFile(context->handle, &context->fd) == TRUE;
#else
			if (context->dirp) {
				context->dp = readdir(context->dirp);
				found = context->dp != NULL;
			} else {
				found = 0;
			}
#endif
			if (!found)
				break;
		}

		if (!found) {
			// Close down the file find handle.
#if defined(WIN32)
			FindClose(context->handle);
			context->handle = INVALID_HANDLE_VALUE;
#else
			if (context->dirp) {
				closedir(context->dirp);
				context->dirp = NULL;
			}
#endif

			context->iterNode = context->directoryListHead;
		}
	}

	// Iterate the file list and either recurse or add the file as a found
	// file.
	if (!context->matchFiles) {
		if (found) {
			return 1;
		}

NextDirectory:
		if (context->iterNode) {
			// Need more directories.
			SplicePath(&self->combinedName, buffer_ptr(&context->basePath), context->iterNode->buffer);
			buffer_deltapos(&self->combinedName, -2);
			buffer_addstring(&self->combinedName, context->pattern, strlen(context->pattern) + 1);

			context->iterNode = context->iterNode->next;

			context = NULL;
			inPattern = buffer_ptr(&self->combinedName);
			goto Setup;
		}
	} else {
		if (found)
			return 1;
	}

	// Do we need to recurse?
	if (context->recurseAtPos == (size_t)-1) {
		_fileglob_FreeContextLevel(self);

		context = self->context;
		if (!context)
			return 0;

		goto NextDirectory;
	}

	buffer_reset(&context->matchPattern);
	buffer_setpos(&context->patternBuf, context->recurseAtPos);
	buffer_addstring(&context->matchPattern, buffer_posptr(&context->patternBuf), strlen(buffer_posptr(&context->patternBuf)));
	buffer_addstring(&context->patternBuf, "*/**/", 5);
	buffer_addstring(&context->patternBuf, buffer_ptr(&context->matchPattern), buffer_pos(&context->matchPattern) + 1);

	inPattern = buffer_ptr(&context->patternBuf);
	context->pattern = NULL;

	if (context->matchFiles) {
		context->iterNode = context->directoryListHead;
	} else {
		_fileglob_list_clear(self, &context->directoryListHead, &context->directoryListTail);
	}
	goto DoRecursion;
}
Example #20
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;
	}
}