Exemplo n.º 1
0
/* TODO maybe try not to use string port? */
static SgObject normalise_path(SgObject fullpath)
{
  SgStringPort sp;
  SgObject out = Sg_InitStringOutputPort(&sp, SG_STRING_SIZE(fullpath));
  int64_t pos = 0;
  int i = 0;
  while (i < SG_STRING_SIZE(fullpath)) {
    SgChar c = SG_STRING_VALUE_AT(fullpath, i++);
    if (c == '.') {
      if (i != SG_STRING_SIZE(fullpath)) {
	SgChar c2 = SG_STRING_VALUE_AT(fullpath, i++);
	if (c2 == '.') {
	  if (SG_STRING_VALUE_AT(fullpath, i) == '/' ||
	      SG_STRING_SIZE(fullpath) == i) {
	    if (pos-2 > 0) {
	      SgObject tmp = Sg_GetStringFromStringPort(out);
	      /* skip previous '.' and '/' */
	      pos = search_separator(tmp, pos-2);
	    } else {
	      pos = 1;		/* root */
	    }
	    if (pos <= 0) pos = 1; /* root */
	    Sg_SetPortPosition(out, pos, SG_BEGIN);
	    if (pos == 1) i++;
	  } else {
	    /* ok just a file named '..?' or longer*/
	    Sg_PutcUnsafe(out, '.');
	    Sg_PutcUnsafe(out, '.');
	    pos += 2;
	    for (; i < SG_STRING_SIZE(fullpath); i++) {
	      SgChar c3 = SG_STRING_VALUE_AT(fullpath, i);
	      if (c3 != '.') break;
	      Sg_PutcUnsafe(out, c3);
	      pos++;
	    }
	  }
	} else if (c2 != '/') {
	  Sg_PutcUnsafe(out, '.');
	  Sg_PutcUnsafe(out, c2);
	  pos += 2;
	}
      }
    } else {
      Sg_PutcUnsafe(out, c);
      pos++;
    }
  }
  return strip_trailing_slash(Sg_GetStringFromStringPort(out));
}
Exemplo n.º 2
0
static SgObject brace_expand(SgString *str, int flags)
{
  const int escape = !(flags & SG_NOESCAPE);
  int lbrace = 0, rbrace = 0, nest = 0, i;
  int haslb = FALSE, hasrb = FALSE;

  /* find { and }*/
  for (i = 0; i < SG_STRING_SIZE(str); i++) {
    if (SG_STRING_VALUE_AT(str, i) == '{' && nest++ == 0) {
      lbrace = i;
      haslb = TRUE;
    }
    if (SG_STRING_VALUE_AT(str, i) == '}' && --nest == 0) {
      rbrace = i;
      hasrb = TRUE;
      break;
    }
    if (SG_STRING_VALUE_AT(str, i) == '\\' && escape) {
      if (++i == SG_STRING_SIZE(str)) break;
    }
  }
  /* make "foo/{a,b}" to ("foo/a" "foo/b") */
  if (haslb && hasrb) {
    SgObject h = SG_NIL, t = SG_NIL;
    SgPort *out;
    SgStringPort tp;
    int i;
    /* copy value until the first '{' */
    out = Sg_InitStringOutputPort(&tp, 255);
    for (i = 0; i < lbrace; i++) {
      Sg_PutcUnsafe(out, SG_STRING_VALUE_AT(str, i));
    }
    /* skip '{' */
    i++;
    while (i < rbrace) {
      /* now we need to copy one by one */
      int nest = 0, j;
      SgObject tmp;
      for (;SG_STRING_VALUE_AT(str, i) != ',' || nest != 0; i++) {
	if (i >= rbrace) break;

  	if (SG_STRING_VALUE_AT(str, i) == '{') nest++;
  	if (SG_STRING_VALUE_AT(str, i) == '}') nest--;
  	if (SG_STRING_VALUE_AT(str, i) == '\\' && escape) {
  	  if (++i == rbrace) break;
  	}
  	Sg_PutcUnsafe(out, SG_STRING_VALUE_AT(str, i));
      }
      /* skip ',' */
      i++;
      /* copy after the '}' */
      for (j = rbrace+1; j < SG_STRING_SIZE(str); j++) {
  	Sg_PutcUnsafe(out, SG_STRING_VALUE_AT(str, j));
      }
      tmp = Sg_GetStringFromStringPort(&tp);
      SG_APPEND(h, t, brace_expand(tmp, flags));
      /* back to the starting position */
      Sg_SetPortPosition(out, lbrace, SG_BEGIN);
    }
    SG_CLEAN_STRING_PORT(&tp);
    return h;
  } else {
    return SG_LIST1(str);
  }
}