Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
#include 
9
#include 
10
#include 
11
 
12
typedef struct Save {
13
  struct Save *prev;
14
  char *entry;
15
} Save;
16
 
17
static Save *save_list;
18
static int save_count;
19
static int flags;
20
static int (*errfunc)(const char *epath, int eerno);
21
static char *pathbuf;
22
static int wildcard_nesting;
23
static char use_lower_case;
24
static char slash;
25
 
26
static int glob2(const char *pattern, char *epathbuf);
27
static int add(const char *path);
28
static int str_compare(const void *va, const void *vb);
29
 
30
static int
31
add(const char *path)
32
{
33
  Save *sp;
34
  for (sp=save_list; sp; sp=sp->prev)
35
    if (strcmp(sp->entry, path) == 0)
36
      return 0;
37
  sp = (Save *)malloc(sizeof(Save));
38
  if (sp == 0)
39
    return 1;
40
  sp->entry = (char *)malloc(strlen(path)+1);
41
  if (sp->entry == 0)
42
  {
43
    free(sp);
44
    return 1;
45
  }
46
/*  printf("add: `%s'\n", path); */
47
  strcpy(sp->entry, path);
48
  sp->prev = save_list;
49
  save_list = sp;
50
  save_count++;
51
  return 0;
52
}
53
 
54
static int
55
glob_dirs(const char *rest, char *epathbuf, int first) /* rest is ptr to null or ptr after slash, bp after slash */
56
{
57
  struct ffblk ff;
58
  int done;
59
 
60
/*  printf("glob_dirs[%d]: rest=`%s' %c epathbuf=`%s' %c pathbuf=`%s'\n",
61
	 wildcard_nesting, rest, *rest, epathbuf, *epathbuf, pathbuf); */
62
 
63
  if (first)
64
  {
65
    if (*rest)
66
    {
67
      glob2(rest, epathbuf);
68
    }
69
    else
70
    {
71
      char sl = epathbuf[-1];
72
      *epathbuf = 0;
73
/*      printf("end, checking `%s'\n", pathbuf); */
74
      if (epathbuf == pathbuf)
75
      {
76
	epathbuf[0] = '.';
77
	epathbuf[1] = 0;
78
      }
79
      else
80
	epathbuf[-1] = 0;
81
      if (__file_exists(pathbuf))
82
	add(pathbuf);
83
      epathbuf[-1] = sl;
84
    }
85
  }
86
 
87
  strcpy(epathbuf, "*.*");
88
  done = findfirst(pathbuf, &ff, FA_DIREC);
89
  while (!done)
90
  {
91
    if ((ff.ff_name[0] != '.') && (ff.ff_attrib & FA_DIREC))
92
    {
93
      int i;
94
      char *tp;
95
      if (use_lower_case)
96
	for (i=0; ff.ff_name[i] && i<13; i++)
97
	  ff.ff_name[i] = tolower(ff.ff_name[i]);
98
 
99
/*      printf("found `%s' `%s'\n", pathbuf, ff.ff_name); */
100
 
101
      strcpy(epathbuf, ff.ff_name);
102
      tp = epathbuf + strlen(epathbuf);
103
      *tp++ = slash;
104
      *tp = 0;
105
 
106
      wildcard_nesting++;
107
      if (*rest)
108
      {
109
	glob2(rest, tp);
110
      }
111
      else
112
      {
113
	if (!(flags & GLOB_MARK))
114
	  tp[-1] = 0;
115
	add(pathbuf);
116
	tp[-1] = slash;
117
      }
118
      *tp = 0;
119
      glob_dirs(rest, tp, 0);
120
      wildcard_nesting--;
121
    }
122
    done = findnext(&ff);
123
  }
124
  return 0;
125
}
126
 
127
static int
128
glob2(const char *pattern, char *epathbuf) /* both point *after* the slash */
129
{
130
  const char *pp, *pslash;
131
  char *bp;
132
  struct ffblk ff;
133
  char *my_pattern;
134
  int done;
135
 
136
  if (strcmp(pattern, "...") == 0)
137
  {
138
    return glob_dirs(pattern+3, epathbuf, 1);
139
  }
140
  if (strncmp(pattern, "...", 3) == 0 && (pattern[3] == '\\' || pattern[3] == '/'))
141
  {
142
    slash = pattern[3];
143
    return glob_dirs(pattern+4, epathbuf, 1);
144
  }
145
 
146
  *epathbuf = 0;
147
  /* copy as many non-wildcard segments as possible */
148
  pp = pattern;
149
  bp = epathbuf;
150
  pslash = bp-1;
151
  while (1)
152
  {
153
    if (*pp == ':' || *pp == '\\' || *pp == '/')
154
    {
155
      pslash = bp;
156
      if (strcmp(pp+1, "...") == 0
157
	  || (strncmp(pp+1, "...", 3) == 0 && (pp[4] == '/' || pp[4] == '\\')))
158
      {
159
	if (*pp != ':')
160
	  slash = *pp;
161
/*	printf("glob2: dots at `%s'\n", pp); */
162
	*bp++ = *pp++;
163
	break;
164
      }
165
    }
166
 
167
    else if (*pp == '*' || *pp == '?' || *pp == '[')
168
    {
169
      if (pslash > pathbuf)
170
	strncpy(epathbuf, pattern, pslash - pathbuf);
171
      pp = pattern + (pslash - epathbuf) + 1;
172
      bp = epathbuf + (pslash - epathbuf) + 1;
173
      break;
174
    }
175
 
176
    else if (*pp == 0)
177
    {
178
      break;
179
    }
180
 
181
    else if (islower(*pp))
182
      use_lower_case = 1;
183
    else if (isupper(*pp))
184
      use_lower_case = 0;
185
 
186
    *bp++ = *pp++;
187
  }
188
  *bp = 0;
189
 
190
  if (*pp == 0) /* end of pattern? */
191
  {
192
    if (wildcard_nesting==0 || __file_exists(pathbuf))
193
      add(pathbuf);
194
    return 0;
195
  }
196
/*  printf("glob2: initial segment is `%s'\n", pathbuf); */
197
  if (wildcard_nesting)
198
  {
199
    char s = bp[-1];
200
    bp[-1] = 0;
201
    if (!__file_exists(pathbuf))
202
      return 0;
203
    bp[-1] = s;
204
  }
205
 
206
  for (pslash = pp; *pslash && *pslash != '\\' && *pslash != '/';  pslash++)
207
  {
208
    if (islower(*pslash))
209
      use_lower_case = 1;
210
    else if (isupper(*pslash))
211
      use_lower_case = 0;
212
  }
213
  if (*pslash)
214
    slash = *pslash;
215
  my_pattern = (char *)alloca(pslash - pp + 1);
216
  if (my_pattern == 0)
217
    return 0;
218
  strncpy(my_pattern, pp, pslash - pp);
219
  my_pattern[pslash-pp] = 0;
220
 
221
/*  printf("glob2: `%s' `%s'\n", pathbuf, my_pattern); */
222
 
223
  if (strcmp(my_pattern, "...") == 0)
224
  {
225
    glob_dirs(*pslash ? pslash+1 : pslash, bp, 1);
226
    return 0;
227
  }
228
 
229
  strcpy(bp, "*.*");
230
 
231
  done = findfirst(pathbuf, &ff, FA_RDONLY|FA_SYSTEM|FA_DIREC|FA_ARCH);
232
  while (!done)
233
  {
234
    int i;
235
    if (ff.ff_name[0] != '.')
236
    {
237
      if (use_lower_case)
238
	for (i=0; ff.ff_name[i] && i<13; i++)
239
	  ff.ff_name[i] = tolower(ff.ff_name[i]);
240
      if (fnmatch(my_pattern, ff.ff_name, FNM_NOESCAPE|FNM_PATHNAME|FNM_NOCASE) == 0)
241
      {
242
	strcpy(bp, ff.ff_name);
243
	if (*pslash)
244
	{
245
	  char *tp = bp + strlen(bp);
246
	  *tp++ = *pslash;
247
	  *tp = 0;
248
/*	  printf("nest: `%s' `%s'\n", pslash+1, pathbuf); */
249
	  wildcard_nesting++;
250
	  glob2(pslash+1, tp);
251
	  wildcard_nesting--;
252
	}
253
	else
254
	{
255
/*	  printf("ffmatch: `%s' matching `%s', add `%s'\n",
256
		 ff.ff_name, my_pattern, pathbuf); */
257
	  if (ff.ff_attrib & FA_DIREC & (flags & GLOB_MARK))
258
	  {
259
	    bp[strlen(bp)] = slash;
260
	    bp[strlen(bp)+1] = 0;
261
	  }
262
	  add(pathbuf);
263
	}
264
      }
265
    }
266
    done = findnext(&ff);
267
  }
268
 
269
  return 0;
270
}
271
 
272
static int
273
str_compare(const void *va, const void *vb)
274
{
275
  return strcmp(*(char * const *)va, *(char * const *)vb);
276
}
277
 
278
int
279
glob(const char *_pattern, int _flags, int (*_errfunc)(const char *_epath, int _eerrno), glob_t *_pglob)
280
{
281
  char path_buffer[2000];
282
  int l_ofs, l_ptr;
283
 
284
  pathbuf = path_buffer+1;
285
  flags = _flags;
286
  errfunc = _errfunc;
287
  wildcard_nesting = 0;
288
  save_count = 0;
289
  save_list = 0;
290
  use_lower_case = 1;
291
  slash = '/';
292
 
293
  glob2(_pattern, pathbuf);
294
 
295
  if (save_count == 0)
296
  {
297
    if (flags & GLOB_NOCHECK)
298
      add(_pattern);
299
    else
300
      return GLOB_NOMATCH;
301
  }
302
 
303
  if (flags & GLOB_DOOFFS)
304
    l_ofs = _pglob->gl_offs;
305
  else
306
    l_ofs = 0;
307
 
308
  if (flags & GLOB_APPEND)
309
  {
310
    _pglob->gl_pathv = (char **)realloc(_pglob->gl_pathv, (l_ofs + _pglob->gl_pathc + save_count + 1) * sizeof(char *));
311
    if (_pglob->gl_pathv == 0)
312
      return GLOB_ERR;
313
    l_ptr = l_ofs + _pglob->gl_pathc;
314
  }
315
  else
316
  {
317
    _pglob->gl_pathv = (char* *)malloc((l_ofs + save_count + 1) * sizeof(char *));
318
    if (_pglob->gl_pathv == 0)
319
      return GLOB_ERR;
320
    l_ptr = l_ofs;
321
    if (l_ofs)
322
      memset(_pglob->gl_pathv, 0, l_ofs * sizeof(char *));
323
  }
324
 
325
  l_ptr += save_count;
326
  _pglob->gl_pathv[l_ptr] = 0;
327
  while (save_list)
328
  {
329
    Save *s = save_list;
330
    l_ptr --;
331
    _pglob->gl_pathv[l_ptr] = save_list->entry;
332
    save_list = save_list->prev;
333
    free(s);
334
  }
335
  if (!(flags & GLOB_NOSORT))
336
    qsort(_pglob->gl_pathv + l_ptr, save_count, sizeof(char *), str_compare);
337
 
338
  _pglob->gl_pathc = l_ptr + save_count;
339
 
340
  return 0;
341
}