Пример #1
0
static bool
is_special_global_name(UChar *ptr, long len)
{
    if (len <= 0) {
	return false;
    }

    long pos = 0;
    switch (ptr[pos]) {
	case '~': case '*': case '$': case '?': case '!':
	case '@': case '/': case '\\': case ';': case ',':
	case '.': case '=': case ':': case '<': case '>': 
	case '\"': case '&': case '`': case '\'': case '+': case '0':
	    pos++;
	    break;

	case '-':
	    pos++;
	    if (pos < len && is_identchar(ptr[pos])) {
		pos++;
	    }
	    break;

	default:
	    if (!isdigit(ptr[pos])) {
		return false;
	    }
	    do {
		pos++;
	    }
	    while (pos < len && isdigit(ptr[pos]));
	    break;
    }
    return pos == len;
}
Пример #2
0
static mrb_bool
is_special_global_name(const char* m)
{
  switch (*m) {
    case '~': case '*': case '$': case '?': case '!': case '@':
    case '/': case '\\': case ';': case ',': case '.': case '=':
    case ':': case '<': case '>': case '\"':
    case '&': case '`': case '\'': case '+':
    case '0':
      ++m;
      break;
    case '-':
      ++m;
      if (is_identchar(*m)) m += 1;
      break;
    default:
      if (!ISDIGIT(*m)) return FALSE;
      do ++m; while (ISDIGIT(*m));
      break;
  }
  return !*m;
}
Пример #3
0
static mrb_bool
symname_p(const char *name)
{
  const char *m = name;
  mrb_bool localid = FALSE;

  if (!m) return FALSE;
  switch (*m) {
    case '\0':
      return FALSE;

    case '$':
      if (is_special_global_name(++m)) return TRUE;
      goto id;

    case '@':
      if (*++m == '@') ++m;
      goto id;

    case '<':
      switch (*++m) {
        case '<': ++m; break;
        case '=': if (*++m == '>') ++m; break;
        default: break;
      }
      break;

    case '>':
      switch (*++m) {
        case '>': case '=': ++m; break;
        default: break;
      }
      break;

    case '=':
      switch (*++m) {
        case '~': ++m; break;
        case '=': if (*++m == '=') ++m; break;
        default: return FALSE;
      }
      break;

    case '*':
      if (*++m == '*') ++m;
      break;
    case '!':
      if (*++m == '=') ++m;
      break;
    case '+': case '-':
      if (*++m == '@') ++m;
      break;
    case '|':
      if (*++m == '|') ++m;
      break;
    case '&':
      if (*++m == '&') ++m;
      break;

    case '^': case '/': case '%': case '~': case '`':
      ++m;
      break;

    case '[':
      if (*++m != ']') return FALSE;
      if (*++m == '=') ++m;
      break;

    default:
      localid = !ISUPPER(*m);
id:
      if (*m != '_' && !ISALPHA(*m)) return FALSE;
      while (is_identchar(*m)) m += 1;
      if (localid) {
        switch (*m) {
          case '!': case '?': case '=': ++m;
          default: break;
            }
        }
      break;
  }
  return *m ? FALSE : TRUE;
}
Пример #4
0
static ID
rb_intern_uchars(const UChar *chars, const size_t chars_len, VALUE str)
{
    const unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
    LOCK();
    ID id = (ID)CFDictionaryGetValue(sym_id, (const void *)name_hash); 
    UNLOCK();
    if (id != 0) {
	goto return_id;
    }
 
    if (str == Qnil) {
	str = rb_unicode_str_new(chars, chars_len);
    }

    rb_sym_t *sym = NULL;
    long pos = 0;
    if (chars_len > 0) {
	UChar c = chars[0];
	switch (c) {
	    case '$':
		id = ID_GLOBAL;
		goto new_id;

	    case '@':
		if (chars_len > 1 && chars[1] == '@') {
		    pos++;
		    id = ID_CLASS;
		}
		else {
		    id = ID_INSTANCE;
		}
		pos++;
		break;

	    default:
		if (chars_len > 1 && chars[chars_len - 1] == '=') {
		    // Attribute assignment.
		    id = rb_intern_str(rb_str_substr(str, 0, chars_len - 1));
		    if (!is_attrset_id(id)) {
			id = rb_id_attrset(id);
			goto id_register;
		    }
		    id = ID_ATTRSET;
		}
		else if (iswupper(c)) {
		    id = ID_CONST;
		}
		else {
		    id = ID_LOCAL;
		}
		break;
	}
    }

    if (pos < chars_len && !isdigit(chars[pos])) {
	for (; pos < chars_len; pos++) {
	    if (!is_identchar(chars[pos])) {
		break;
	    }
	}
    }
    if (pos < chars_len) {
	id = ID_JUNK;
    }

new_id:
    id |= ++last_id << ID_SCOPE_SHIFT;

id_register:
//printf("register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
    sym = sym_alloc(str, id);
    LOCK();
    CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
    CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
    UNLOCK();

return_id:
    return id;
}
Пример #5
0
static bool
sym_should_be_escaped(VALUE sym)
{
    RB_STR_GET_UCHARS(RSYM(sym)->str, chars, chars_len);

    if (chars_len == 0) {
	return true;
    }

    bool escape = false;
    for (long i = 0; i < chars_len; i++) {
	if (!isprint(chars[i])) {
	    escape = true;
	    break;
	}
    }

    if (escape) {
	goto bail;
    }

    long pos = 0;
    bool localid = false;

    switch (chars[pos]) {
	case '\0':
	    escape = true;
	    break;

	case '$':
	    pos++;
	    if (pos < chars_len && is_special_global_name(&chars[pos],
			chars_len - pos)) {
		goto bail;
	    }
	    goto id;

	case '@':
	    pos++;
	    if (pos < chars_len && chars[pos] == '@') {
		pos++;
	    }
	    goto id;

	case '<':
	    pos++;
	    if (pos < chars_len) {
		if (chars[pos] == '<') {
		    pos++;
		}
		else if (chars[pos] == '=') {
		    pos++;
		    if (pos < chars_len && chars[pos] == '>') {
			pos++;
		    }
		}
	    }
	    break;

	case '>':
	    pos++;
	    if (pos < chars_len) {
		if (chars[pos] == '>' || chars[pos] == '=') {
		    pos++;
		}
	    }
	    break;

	case '=':
	    pos++;
	    if (pos == chars_len) {
		escape = true;
		goto bail;
	    }
	    else {
		if (chars[pos] == '~') {
		    pos++;
		}
		else if (chars[pos] == '=') {
		    pos++;
		    if (pos < chars_len && chars[pos] == '=') {
			pos++;
		    }
		}
		else {
		    escape = true;
		    goto bail;
		}
	    }
	    break;

	case '*':
	    pos++;
	    if (pos < chars_len && chars[pos] == '*') {
		pos++;
	    }
	    break;

	case '+':
	case '-':
	    pos++;
	    if (pos < chars_len && chars[pos] == '@') {
		pos++;
	    }
	    break;

	case '|': case '^': case '&': case '/':
	case '%': case '~': case '`':
	    pos++;
	    break;

	case '[':
	    pos++;
	    if (pos < chars_len && chars[pos] != ']') {
		escape = true;
		goto bail;
	    }
	    pos++;
	    if (pos < chars_len && chars[pos] == '=') {
		pos++;
	    }
	    break;

	case '!':
	    pos++;
	    if (pos == chars_len) {
		goto bail;
	    }
	    else {
		if (chars[pos] == '=' || chars[pos] == '~') {
		    pos++;
		}
		else {
		    escape = true;
		    goto bail;
		}
	    }
	    break;

	default:
	    localid = !isupper(chars[pos]);
	    // fall through	

	id:
	    if (pos >= chars_len
		    || (chars[pos] != '_' && !isalpha(chars[pos])
			&& isascii(chars[pos]))) {
		escape = true;
		goto bail;
	    }
	    while (pos < chars_len && is_identchar(chars[pos])) {
		pos++;
	    }
	    if (localid) {
		if (pos < chars_len
			&& (chars[pos] == '!' || chars[pos] == '?'
			    || chars[pos] == '=')) {
		    pos++;
		}
	    }
	    break;
    }

    if (pos < chars_len) {
	escape = true;
    }

bail:
    return escape;
}