Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4972 → Rev 4973

/programs/develop/libraries/menuetlibc/src/libc/posix/glob/glob.c
0,0 → 1,341
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <fnmatch.h>
#include <dir.h>
#include <glob.h>
 
typedef struct Save {
struct Save *prev;
char *entry;
} Save;
 
static Save *save_list;
static int save_count;
static int flags;
static int (*errfunc)(const char *epath, int eerno);
static char *pathbuf;
static int wildcard_nesting;
static char use_lower_case;
static char slash;
 
static int glob2(const char *pattern, char *epathbuf);
static int add(const char *path);
static int str_compare(const void *va, const void *vb);
 
static int
add(const char *path)
{
Save *sp;
for (sp=save_list; sp; sp=sp->prev)
if (strcmp(sp->entry, path) == 0)
return 0;
sp = (Save *)malloc(sizeof(Save));
if (sp == 0)
return 1;
sp->entry = (char *)malloc(strlen(path)+1);
if (sp->entry == 0)
{
free(sp);
return 1;
}
/* printf("add: `%s'\n", path); */
strcpy(sp->entry, path);
sp->prev = save_list;
save_list = sp;
save_count++;
return 0;
}
 
static int
glob_dirs(const char *rest, char *epathbuf, int first) /* rest is ptr to null or ptr after slash, bp after slash */
{
struct ffblk ff;
int done;
 
/* printf("glob_dirs[%d]: rest=`%s' %c epathbuf=`%s' %c pathbuf=`%s'\n",
wildcard_nesting, rest, *rest, epathbuf, *epathbuf, pathbuf); */
 
if (first)
{
if (*rest)
{
glob2(rest, epathbuf);
}
else
{
char sl = epathbuf[-1];
*epathbuf = 0;
/* printf("end, checking `%s'\n", pathbuf); */
if (epathbuf == pathbuf)
{
epathbuf[0] = '.';
epathbuf[1] = 0;
}
else
epathbuf[-1] = 0;
if (__file_exists(pathbuf))
add(pathbuf);
epathbuf[-1] = sl;
}
}
 
strcpy(epathbuf, "*.*");
done = findfirst(pathbuf, &ff, FA_DIREC);
while (!done)
{
if ((ff.ff_name[0] != '.') && (ff.ff_attrib & FA_DIREC))
{
int i;
char *tp;
if (use_lower_case)
for (i=0; ff.ff_name[i] && i<13; i++)
ff.ff_name[i] = tolower(ff.ff_name[i]);
 
/* printf("found `%s' `%s'\n", pathbuf, ff.ff_name); */
 
strcpy(epathbuf, ff.ff_name);
tp = epathbuf + strlen(epathbuf);
*tp++ = slash;
*tp = 0;
 
wildcard_nesting++;
if (*rest)
{
glob2(rest, tp);
}
else
{
if (!(flags & GLOB_MARK))
tp[-1] = 0;
add(pathbuf);
tp[-1] = slash;
}
*tp = 0;
glob_dirs(rest, tp, 0);
wildcard_nesting--;
}
done = findnext(&ff);
}
return 0;
}
 
static int
glob2(const char *pattern, char *epathbuf) /* both point *after* the slash */
{
const char *pp, *pslash;
char *bp;
struct ffblk ff;
char *my_pattern;
int done;
 
if (strcmp(pattern, "...") == 0)
{
return glob_dirs(pattern+3, epathbuf, 1);
}
if (strncmp(pattern, "...", 3) == 0 && (pattern[3] == '\\' || pattern[3] == '/'))
{
slash = pattern[3];
return glob_dirs(pattern+4, epathbuf, 1);
}
 
*epathbuf = 0;
/* copy as many non-wildcard segments as possible */
pp = pattern;
bp = epathbuf;
pslash = bp-1;
while (1)
{
if (*pp == ':' || *pp == '\\' || *pp == '/')
{
pslash = bp;
if (strcmp(pp+1, "...") == 0
|| (strncmp(pp+1, "...", 3) == 0 && (pp[4] == '/' || pp[4] == '\\')))
{
if (*pp != ':')
slash = *pp;
/* printf("glob2: dots at `%s'\n", pp); */
*bp++ = *pp++;
break;
}
}
 
else if (*pp == '*' || *pp == '?' || *pp == '[')
{
if (pslash > pathbuf)
strncpy(epathbuf, pattern, pslash - pathbuf);
pp = pattern + (pslash - epathbuf) + 1;
bp = epathbuf + (pslash - epathbuf) + 1;
break;
}
 
else if (*pp == 0)
{
break;
}
 
else if (islower(*pp))
use_lower_case = 1;
else if (isupper(*pp))
use_lower_case = 0;
 
*bp++ = *pp++;
}
*bp = 0;
 
if (*pp == 0) /* end of pattern? */
{
if (wildcard_nesting==0 || __file_exists(pathbuf))
add(pathbuf);
return 0;
}
/* printf("glob2: initial segment is `%s'\n", pathbuf); */
if (wildcard_nesting)
{
char s = bp[-1];
bp[-1] = 0;
if (!__file_exists(pathbuf))
return 0;
bp[-1] = s;
}
 
for (pslash = pp; *pslash && *pslash != '\\' && *pslash != '/'; pslash++)
{
if (islower(*pslash))
use_lower_case = 1;
else if (isupper(*pslash))
use_lower_case = 0;
}
if (*pslash)
slash = *pslash;
my_pattern = (char *)alloca(pslash - pp + 1);
if (my_pattern == 0)
return 0;
strncpy(my_pattern, pp, pslash - pp);
my_pattern[pslash-pp] = 0;
 
/* printf("glob2: `%s' `%s'\n", pathbuf, my_pattern); */
 
if (strcmp(my_pattern, "...") == 0)
{
glob_dirs(*pslash ? pslash+1 : pslash, bp, 1);
return 0;
}
 
strcpy(bp, "*.*");
 
done = findfirst(pathbuf, &ff, FA_RDONLY|FA_SYSTEM|FA_DIREC|FA_ARCH);
while (!done)
{
int i;
if (ff.ff_name[0] != '.')
{
if (use_lower_case)
for (i=0; ff.ff_name[i] && i<13; i++)
ff.ff_name[i] = tolower(ff.ff_name[i]);
if (fnmatch(my_pattern, ff.ff_name, FNM_NOESCAPE|FNM_PATHNAME|FNM_NOCASE) == 0)
{
strcpy(bp, ff.ff_name);
if (*pslash)
{
char *tp = bp + strlen(bp);
*tp++ = *pslash;
*tp = 0;
/* printf("nest: `%s' `%s'\n", pslash+1, pathbuf); */
wildcard_nesting++;
glob2(pslash+1, tp);
wildcard_nesting--;
}
else
{
/* printf("ffmatch: `%s' matching `%s', add `%s'\n",
ff.ff_name, my_pattern, pathbuf); */
if (ff.ff_attrib & FA_DIREC & (flags & GLOB_MARK))
{
bp[strlen(bp)] = slash;
bp[strlen(bp)+1] = 0;
}
add(pathbuf);
}
}
}
done = findnext(&ff);
}
 
return 0;
}
 
static int
str_compare(const void *va, const void *vb)
{
return strcmp(*(char * const *)va, *(char * const *)vb);
}
 
int
glob(const char *_pattern, int _flags, int (*_errfunc)(const char *_epath, int _eerrno), glob_t *_pglob)
{
char path_buffer[2000];
int l_ofs, l_ptr;
 
pathbuf = path_buffer+1;
flags = _flags;
errfunc = _errfunc;
wildcard_nesting = 0;
save_count = 0;
save_list = 0;
use_lower_case = 1;
slash = '/';
 
glob2(_pattern, pathbuf);
 
if (save_count == 0)
{
if (flags & GLOB_NOCHECK)
add(_pattern);
else
return GLOB_NOMATCH;
}
 
if (flags & GLOB_DOOFFS)
l_ofs = _pglob->gl_offs;
else
l_ofs = 0;
 
if (flags & GLOB_APPEND)
{
_pglob->gl_pathv = (char **)realloc(_pglob->gl_pathv, (l_ofs + _pglob->gl_pathc + save_count + 1) * sizeof(char *));
if (_pglob->gl_pathv == 0)
return GLOB_ERR;
l_ptr = l_ofs + _pglob->gl_pathc;
}
else
{
_pglob->gl_pathv = (char* *)malloc((l_ofs + save_count + 1) * sizeof(char *));
if (_pglob->gl_pathv == 0)
return GLOB_ERR;
l_ptr = l_ofs;
if (l_ofs)
memset(_pglob->gl_pathv, 0, l_ofs * sizeof(char *));
}
 
l_ptr += save_count;
_pglob->gl_pathv[l_ptr] = 0;
while (save_list)
{
Save *s = save_list;
l_ptr --;
_pglob->gl_pathv[l_ptr] = save_list->entry;
save_list = save_list->prev;
free(s);
}
if (!(flags & GLOB_NOSORT))
qsort(_pglob->gl_pathv + l_ptr, save_count, sizeof(char *), str_compare);
 
_pglob->gl_pathc = l_ptr + save_count;
 
return 0;
}