예제 #1
0
static SgObject convert_star(SgObject p)
{
  /* for may laziness, we use regular expression for '*' */
  SgObject h = SG_NIL, t = SG_NIL;
  int has_star = FALSE;
  SG_FOR_EACH(p, p) {
    if (SG_EQ(SG_CAR(p), STAR)) {
      has_star = TRUE;
      break;
    }
    SG_APPEND1(h, t, SG_CAR(p));
  }
  if (has_star) {
    /* TODO should we use AST directly to save some memory? */
    SgPort *out;
    SgStringPort tp;

    /* copy value until the first '{' */
    out = Sg_InitStringOutputPort(&tp, 255);
    Sg_PutzUnsafe(out, ".*");
    SG_FOR_EACH(p, SG_CDR(p)) {
      if (SG_STRINGP(SG_CAR(p))) {
	Sg_PutsUnsafe(out, SG_STRING(SG_CAR(p)));
      } else if (SG_CHAR_SET_P(SG_CAR(p))) {
	Sg_PutsUnsafe(out, Sg_CharSetToRegexString(SG_CAR(p), FALSE));
      } else if (SG_EQ(SG_CAR(p), STAR)) {
	Sg_PutzUnsafe(out, ".*");
      } else {
	Sg_Error(UC("[Internal] Unknown pattern '%S'"), SG_CAR(p));
      }
    }
    Sg_PutcUnsafe(out, '$');
    SG_APPEND1(h, t, Sg_CompileRegex(Sg_GetStringFromStringPort(&tp), 0,
				     FALSE));
    SG_CLEAN_STRING_PORT(&tp);
    return h;
  }
  /* FIXME: we don't want to allocate memory in this case */
  return h;
}
예제 #2
0
SgObject Sg_ReadDirectory(SgString *path)
{
  DIR* dir;
  struct dirent* entry;
  SgObject h = SG_NIL, t = SG_NIL;
  if (NULL == (dir = opendir(Sg_Utf32sToUtf8s(path)))) {
    return SG_FALSE;
  }
  for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) {
    SG_APPEND1(h, t, Sg_Utf8sToUtf32s(entry->d_name, strlen(entry->d_name)));
  }
  closedir(dir);
  return h;
}
예제 #3
0
static SgObject glob_make_pattern(SgString *path, int flags)
{
  const int escape = !(flags & SG_NOESCAPE);
  SgObject h = SG_NIL, t = SG_NIL, h1 = SG_NIL, t1 = SG_NIL;
  int i, start;
#define emit()							\
  do {								\
    if (start != i) {						\
      SgObject tmp = Sg_Substring(path, start, i);		\
      if (escape) tmp = remove_backslashes(tmp);		\
      SG_APPEND1(h1, t1, tmp);					\
    }								\
    start = i+1;						\
  } while (0)
  
  for (i = 0, start = 0; i < SG_STRING_SIZE(path);) {
    SgChar c = SG_STRING_VALUE_AT(path, i);
    
    switch (c) {
    case '[': {
      int s = i, e;
      e = find_close_bracket(path, start, flags);
      if (s != e) {
	emit();
	SG_APPEND1(h1, t1, Sg_ParseCharSetString(path, FALSE, s, i=++e));
	start = i;
      }
      i++;
    } break;
    case '/': 
      /* next */
      emit();
      /* if the path starts with '/', then this can be null  */
      if (!SG_NULLP(h1)) {
	SG_APPEND1(h, t, convert_star(h1));
      }
      h1 = t1 = SG_NIL;		/* reset it */
      /* this need to be updated */
      start = ++i;
      break;
    case '*': {
      int has = (start != i);
      emit();
      /* merge it if it's there */
      if (!has && SG_STRING_SIZE(path) - i >= 3 &&
	  SG_STRING_VALUE_AT(path, i+1) == '*' &&
	  SG_STRING_VALUE_AT(path, i+2) == '/') {
	do {
	  i += 3;
	  /* skip '/' */
	  while (SG_STRING_VALUE_AT(path, i) == '/') i++;
	} while (SG_STRING_VALUE_AT(path,   i) == '*' &&
		 SG_STRING_VALUE_AT(path, i+1) == '*' &&
		 SG_STRING_VALUE_AT(path, i+2) == '/');
	SG_APPEND1(h1, t1, STAR_SLASH);
	SG_APPEND1(h, t, h1);
	h1 = t1 = SG_NIL;		/* reset it */
	start = i;
      } else {
	SG_APPEND1(h1, t1, STAR);
	while (SG_STRING_VALUE_AT(path, i) == '*') i++;
      }
      break;
    }
    case '?':
      emit();
      SG_APPEND1(h1, t1, FULL_CHARSET);
      i++;
      break;
    default:
      i++;
      break;
    }
  }

  emit();
  if (!SG_NULLP(h1)) {
    SG_APPEND1(h, t, convert_star(h1));
    SG_APPEND1(h, t, SG_LIST1(ANY));
  } else {
    SG_APPEND1(h, t, SG_LIST1(DIR));
  }
#undef emit
  return h;
}