CFArrayRef VMKXMLPathProcessorEvaluateExpression(VMKXMLPathProcessorRef processor, const char *expression)
{
    assert(processor);
    
    xmlXPathObjectPtr xpathObject = xmlXPathEvalExpression((xmlChar *)expression, processor->_rawXMLPathContext);
	
	xmlNodeSetPtr nodes = xpathObject->nodesetval;
	
    CFMutableArrayRef results = NULL;
    
    if (nodes)
    {
        
        results = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        
        int looper = 0;
        while (looper < nodes->nodeNr)
        {
            VMKXMLNodeRef node = VMKXMLNodeCreate(nodes->nodeTab[looper]);
            
            CFArrayAppendValue(results, node);
            
            CFRelease(node);
            
            ++looper;
        }
        
    }
    
    xmlXPathFreeObject(xpathObject);
    
    CFMakeCollectable(results);
    
    return results;
}
Example #2
0
File: class.c Project: MSch/MacRuby
VALUE
rb_singleton_class_clone(VALUE obj)
{
    VALUE klass = RBASIC(obj)->klass;
    if (!RCLASS_SINGLETON(klass)) {
	return klass;
    }

    // Create new singleton class.
    VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass));

    // Copy ivars.
    CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass);
    if (ivar_dict != NULL) {
	CFMutableDictionaryRef cloned_ivar_dict =
	    CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict);
	rb_class_ivar_set_dict(clone, cloned_ivar_dict);
	CFMakeCollectable(cloned_ivar_dict);
    }

    // Copy methods.
    rb_vm_copy_methods((Class)klass, (Class)clone);	

    rb_singleton_class_attached(clone, obj);
    if (RCLASS_SUPER(clone) == rb_cRubyObject) {
	long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS;
	RCLASS_SET_VERSION(clone, v);
    }
    RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON);
    return clone;
}
Example #3
0
static VALUE
format_message(VALUE exc)
{
    CFMutableStringRef result = CFStringCreateMutable(NULL, 0);
    VALUE message = rb_vm_call(exc, sel_registerName("message"), 0, NULL);
    VALUE bt = rb_vm_call(exc, sel_registerName("backtrace"), 0, NULL);

    message = rb_check_string_type(message);
    const char *msg = message == Qnil ? "" : RSTRING_PTR(message);

    const long count = (bt != Qnil ? RARRAY_LEN(bt) : 0);
    if (count > 0) {
	for (long i = 0; i < count; i++) {
	    const char *bte = RSTRING_PTR(RARRAY_AT(bt, i));
	    if (i == 0) {
		CFStringAppendFormat(result, NULL, CFSTR("%s: %s (%s)\n"),
		    bte, msg, rb_class2name(*(VALUE *)exc));
	    }
	    else {
		CFStringAppendFormat(result, NULL, CFSTR("\tfrom %s\n"), bte);
	    }
	}
    }
    else {
	CFStringAppendFormat(result, NULL, CFSTR("%s (%s)\n"),
	    msg, rb_class2name(*(VALUE *)exc));
    }
    CFMakeCollectable(result);
    return (VALUE)result;
}
Example #4
0
__private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) {
    CFStringRef theString = (CFStringRef)ptr;
    CFStringRef result = CFStringCreateCopy(allocator, theString);
    if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
        result = (CFStringRef)CFMakeCollectable(result);
    }
    return (const void *)result;
}
Example #5
0
CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFDataRef data) {
    // Do not allow magic allocator for now for mutable datas, because it
    // isn't remembered for proper handling later when growth of the buffer
    // has to occur.
    Boolean wasMagic = (0);
    CFMutableDataRef r = (CFMutableDataRef) __CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, CFDataGetBytePtr(data), CFDataGetLength(data), NULL);
    if (wasMagic) CFMakeCollectable(r);
    return r;
}
Example #6
0
VALUE
rb_set_dup(VALUE rcv)
{
    VALUE dup = (VALUE)CFSetCreateMutableCopy(NULL, 0, (CFSetRef)rcv);
    if (OBJ_TAINTED(rcv))
	OBJ_TAINT(dup);
    CFMakeCollectable((CFTypeRef)dup);
    return dup;
}
CFMutableDataRef CFDataCreateMutable(CFAllocatorRef allocator, CFIndex capacity) {
    // Do not allow magic allocator for now for mutable datas, because it
    // isn't remembered for proper handling later when growth of the buffer
    // has to occur.
    Boolean wasMagic = _CFAllocatorIsGCRefZero(allocator);
    if (0 == capacity) allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator);
    CFMutableDataRef r = (CFMutableDataRef)__CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, NULL, 0, NULL);
    if (wasMagic) CFMakeCollectable(r);
    return r;
}
Example #8
0
static VALUE
rb_yaml_resolver_initialize(VALUE self, SEL sel)
{
    rb_yaml_resolver_t *resolver = RYAMLResolver(self);
    CFMutableDictionaryRef d = CFDictionaryCreateMutable(NULL, 0, NULL,
	    &kCFTypeDictionaryValueCallBacks);
    GC_WB(&resolver->tags, d);
    CFMakeCollectable(d);
    return self;
}
Example #9
0
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    rb_obj_init_copy(clone, 0, orig);

    VALUE super;
    if (!RCLASS_RUBY(orig)) {
	super = orig;
	rb_warn("cloning class `%s' is not supported, creating a " \
		"subclass instead", rb_class2name(orig));
    }
    else {
	super = RCLASS_SUPER(orig);
    }
    RCLASS_SET_SUPER(clone, super);

    // Copy flags.
    unsigned long version_flag = RCLASS_IS_RUBY_CLASS;
    if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS)
	    == RCLASS_IS_OBJECT_SUBCLASS) {
	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
    }
    if (RCLASS_MODULE(orig)) {
	version_flag |= RCLASS_IS_MODULE;
    }
    RCLASS_SET_VERSION(clone, version_flag);
    if (!class_isMetaClass((Class)clone)) {
	// Clear type info.
	RCLASS_SET_VERSION(*(Class *)clone, RCLASS_VERSION(*(Class *)clone));
    }

    // Copy methods.
    rb_vm_copy_methods((Class)orig, (Class)clone);
    if (!class_isMetaClass((Class)orig)) {
	rb_vm_copy_methods(*(Class *)orig, *(Class *)clone);
    }

    // Copy ivars.
    CFMutableDictionaryRef orig_dict = rb_class_ivar_dict(orig);
    CFMutableDictionaryRef clone_dict;
    if (orig_dict != NULL) {
	clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, orig_dict);
	rb_class_ivar_set_dict(clone, clone_dict);
	CFMakeCollectable(clone_dict);
    }
    else {
	clone_dict = rb_class_ivar_dict_or_create(clone);
    }

    // Remove the classpath & classid (name) so that they are not
    // copied over the new module / class.
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classpath);
    CFDictionaryRemoveValue(clone_dict, (const void *)id_classid);
    return clone;
}
Example #10
0
File: class.c Project: MSch/MacRuby
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
{
    static ID classpath = 0;
    static ID classid = 0;

    rb_obj_init_copy(clone, 0, orig);
    {
	VALUE super;
	unsigned long version_flag;

	if (!RCLASS_RUBY(orig)) {
	    super = orig;
	    rb_warn("cloning class `%s' is not supported, creating a " \
		    "subclass instead", rb_class2name(orig));
	}
	else {
	    super = RCLASS_SUPER(orig);
	}
	RCLASS_SET_SUPER(clone, super);

	version_flag = RCLASS_IS_RUBY_CLASS;
	if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
	    version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
	}

	RCLASS_SET_VERSION(clone, version_flag);

	rb_vm_copy_methods((Class)orig, (Class)clone);
	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig);
	if (ivar_dict != NULL) {
	    CFMutableDictionaryRef cloned_ivar_dict;

	    if (classpath == 0) {
		classpath = rb_intern("__classpath__");
	    }
	    if (classid == 0) {
		classid = rb_intern("__classid__");
	    }
	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0,
		(CFDictionaryRef)ivar_dict);
	    // Remove the classpath & classid (name) so that they are not
	    // copied over the new module / class
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath);
	    CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid);
	    CFMakeCollectable(cloned_ivar_dict);
	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
	}
    }

    return clone;
}
Example #11
0
static VALUE
set_alloc(VALUE klass)
{
    CFMutableSetRef set;

    set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
    if (klass != 0 && klass != rb_cNSSet && klass != rb_cNSMutableSet)
	*(Class *)set = (Class)klass;

    CFMakeCollectable(set);

    return (VALUE)set;
}
Example #12
0
File: bs.c Project: MSch/MacRuby
bool 
bs_parser_parse(bs_parser_t *parser, const char *path, 
                const char *framework_path, bs_parse_options_t options, 
                bs_parse_callback_t callback, void *context, char **error)
{
  xmlTextReaderPtr reader;
  bs_element_function_t *func;
  bs_element_class_t *klass;
  bs_element_method_t *method;
  unsigned int i;
#define MAX_ARGS 128
  bs_element_arg_t args[MAX_ARGS];
  bs_element_arg_t fptr_args[MAX_ARGS];
  char *protocol_name = NULL;
  int func_ptr_arg_depth;
  bs_element_function_pointer_t *func_ptr;
  bool success;
  CFStringRef cf_path;
  bool nested_func_ptr;
  unsigned int version_number = 0;

  if (callback == NULL)
    return false;

  /* check if the given framework path has not been loaded already */
  cf_path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorMalloc, 
    path);
  CFMakeCollectable(cf_path);
  for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths);
       i < count; i++) {
    CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i);
    if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive)
        == kCFCompareEqualTo) {
      /* already loaded */
      return true;
    }
  }

  CFArrayAppendValue(parser->loaded_paths, cf_path);

  //printf("parsing %s\n", path);

#define BAIL(fmt, args...)                      \
  do {                                          \
    if (error != NULL) {                        \
      char buf[1024];                           \
      snprintf(buf, sizeof buf,                 \
               "%s:%ld - "fmt, path,            \
               xmlGetLineNo(xmlTextReaderCurrentNode(reader)), \
               ##args);                         \
      *error = strdup(buf);                     \
    }                                           \
    success = false;                            \
    goto bails;                                 \
  }                                             \
  while (0)

#if __LP64__
# define CHECK_TYPE_ATTRIBUTE(var) CHECK_ATTRIBUTE(var, "type")
#else
# define CHECK_TYPE_ATTRIBUTE(var) \
    if (var == NULL && get_type64_attribute(reader) != NULL) { \
	break; \
    } \
    CHECK_ATTRIBUTE(var, "type")
#endif

#define CHECK_ATTRIBUTE_CAN_BE_EMPTY(a, name) \
  CHECK_ATTRIBUTE0(a, name, true)

#define CHECK_ATTRIBUTE(a, name) \
  CHECK_ATTRIBUTE0(a, name, false)

#define CHECK_ATTRIBUTE0(a, name, can_be_empty)         \
  do {                                                  \
    if (a == NULL)                                      \
      BAIL("expected attribute `%s' for element `%s'",  \
           name, xmlTextReaderConstName(reader));       \
    if (!can_be_empty && *a == '\0') {                  \
      free(a);                                          \
      BAIL("empty attribute `%s' for element `%s'",     \
           name, xmlTextReaderConstName(reader));       \
    }                                                   \
  } while (0)                                           \

  reader = xmlNewTextReaderFilename(path);
  if (reader == NULL)
    BAIL("cannot create XML text reader for file at path `%s'", path);

  func = NULL;
  func_ptr = NULL;
  func_ptr_arg_depth = -1;
  nested_func_ptr = false;
  klass = NULL;
  method = NULL;
  protocol_name = NULL;

  while (true) {
    const char *name;
    unsigned int namelen;
    int node_type = -1;
    bool eof = false;
    struct bs_xml_atom *atom;
    void *bs_element;
    bs_element_type_t bs_element_type = 0;

    do {
      int retval = xmlTextReaderRead(reader);
      if (retval == 0) {
        eof = true;
        break;
      }
      else if (retval < 0)
        BAIL("parsing error: %d", retval);

      node_type = xmlTextReaderNodeType(reader);
    }
    while (node_type != XML_READER_TYPE_ELEMENT 
           && node_type != XML_READER_TYPE_END_ELEMENT);    
    
    if (eof)
      break;

    name = (const char *)xmlTextReaderConstName(reader);
    namelen = strlen(name); 

    bs_element = NULL;

    atom = bs_xml_element(name, namelen);
    if (atom == NULL) {
      // TODO: we should include the "signatures" string into the gperf
      // function.
      if (version_number == 0 && strcmp(name, "signatures") == 0) {
        char *str = get_attribute(reader, "version");
        if (str != NULL) {
          char *p = strchr(str, '.');
          if (p != NULL) {
            *p = '\0';
            int major = atoi(str);
            int minor = atoi(&p[1]);
            assert(major < 10 && minor < 10);
            version_number = (major * 10) + minor;
            parser->version_number = version_number;
          }
          free(str);
        }
      }
      continue;
    }

    if (nested_func_ptr) {
      // FIXME: elements nesting function_pointers aren't supported yet by the
      // parser, so we just ignore them.
      if (node_type == XML_READER_TYPE_END_ELEMENT
          && (atom->val == BS_XML_FUNCTION || atom->val == BS_XML_METHOD)) {
        nested_func_ptr = false;
      }
      continue;
    }

    if (node_type == XML_READER_TYPE_ELEMENT) {
      switch (atom->val) {
        case BS_XML_DEPENDS_ON:
        {
          char *depends_on_path;
          char bs_path[PATH_MAX];
          bool bs_path_found;
          
          depends_on_path = get_attribute(reader, "path");
          CHECK_ATTRIBUTE(depends_on_path, "path");

//printf("depends of %s\n", depends_on_path);
          
          bs_path_found = bs_find_path(depends_on_path, bs_path, 
                                       sizeof bs_path);
          if (bs_path_found) {
            if (!bs_parser_parse(parser, bs_path, depends_on_path, options, 
                                 callback, context, error)) {
              free(depends_on_path);
              return false;
	    }
          }
          free(depends_on_path);
          break;
        }

        case BS_XML_CONSTANT: 
        { 
          bs_element_constant_t *bs_const;
          char *const_name;
          char *const_type;

          const_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(const_name, "name");
          const_type = get_type_attribute(reader);
          CHECK_TYPE_ATTRIBUTE(const_type);

          bs_const = (bs_element_constant_t *)
            malloc(sizeof(bs_element_constant_t));
          ASSERT_ALLOC(bs_const);

          bs_const->name = const_name;
          bs_const->type = const_type;
          bs_const->ignore = false;
          bs_const->suggestion = NULL;
          bs_const->magic_cookie = get_boolean_attribute(reader,
            "magic_cookie", false);

          bs_element = bs_const;
          bs_element_type = BS_ELEMENT_CONSTANT;
          break;
        }

        case BS_XML_STRING_CONSTANT:
        {
          bs_element_string_constant_t *bs_strconst;
          char *strconst_name;
          char *strconst_value;

          strconst_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(strconst_name, "name");
          strconst_value = get_attribute(reader, "value");
          CHECK_ATTRIBUTE_CAN_BE_EMPTY(strconst_value, "value");

          bs_strconst = (bs_element_string_constant_t *)
            malloc(sizeof(bs_element_string_constant_t));
          ASSERT_ALLOC(bs_strconst);

          bs_strconst->name = strconst_name;
          bs_strconst->value = strconst_value;
          bs_strconst->nsstring = get_boolean_attribute(reader, "nsstring", 
            false);

          bs_element = bs_strconst;
          bs_element_type = BS_ELEMENT_STRING_CONSTANT;
          break;
        }

        case BS_XML_ENUM: 
        { 
          char *enum_name;
          char *enum_value;        

          enum_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(enum_name, "name");

#if __LP64__
	  enum_value = get_attribute(reader, "value64");
	  if (enum_value == NULL)
#endif
	    enum_value = get_attribute(reader, "value");

#if BYTE_ORDER == BIG_ENDIAN
# define BYTE_ORDER_VALUE_ATTR_NAME "be_value"
#else
# define BYTE_ORDER_VALUE_ATTR_NAME "le_value"
#endif

          if (enum_value == NULL)
            enum_value = get_attribute(reader, BYTE_ORDER_VALUE_ATTR_NAME); 
          
          if (enum_value != NULL) {
            bs_element_enum_t *bs_enum;
   
            bs_enum = (bs_element_enum_t *)malloc(sizeof(bs_element_enum_t));
            ASSERT_ALLOC(bs_enum);

            bs_enum->name = enum_name;
            bs_enum->value = enum_value;
            bs_enum->ignore = get_boolean_attribute(reader, "ignore", false);
            bs_enum->suggestion = get_attribute(reader, "suggestion");
            
            bs_element = bs_enum;
            bs_element_type = BS_ELEMENT_ENUM;
          }
          break;
        }

        case BS_XML_STRUCT: 
        {
          bs_element_struct_t *bs_struct;
          char *struct_decorated_type;
          char *struct_name;
          char type[MAX_ENCODE_LEN];
          bs_element_struct_field_t fields[128];
          int field_count;

          struct_decorated_type = get_type_attribute(reader);
          CHECK_TYPE_ATTRIBUTE(struct_decorated_type);
          struct_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(struct_name, "name");

          if (!undecorate_struct_type(struct_decorated_type, type, 
                                      sizeof type, fields, 128, 
                                      &field_count)) {
            BAIL("Can't handle structure '%s' with type '%s'", 
                 struct_name, struct_decorated_type);
          }

          free(struct_decorated_type);

          bs_struct = 
            (bs_element_struct_t *)malloc(sizeof(bs_element_struct_t));
          ASSERT_ALLOC(bs_struct);

          bs_struct->name = struct_name;
          bs_struct->type = strdup(type);
          
          bs_struct->fields = (bs_element_struct_field_t *)malloc(
            sizeof(bs_element_struct_field_t) * field_count);
          ASSERT_ALLOC(bs_struct->fields);
          memcpy(bs_struct->fields, fields, 
                 sizeof(bs_element_struct_field_t) * field_count); 
          
          bs_struct->fields_count = field_count;
          bs_struct->opaque = get_boolean_attribute(reader, "opaque", false);

          bs_element = bs_struct;
          bs_element_type = BS_ELEMENT_STRUCT;
          break;
        }

        case BS_XML_OPAQUE:
        {
          bs_element_opaque_t *bs_opaque;
          char *opaque_name;
          char *opaque_type;

          opaque_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(opaque_name, "name");
          opaque_type = get_type_attribute(reader);
          CHECK_TYPE_ATTRIBUTE(opaque_type);

          bs_opaque = 
            (bs_element_opaque_t *)malloc(sizeof(bs_element_opaque_t));
          ASSERT_ALLOC(bs_opaque);
          
          bs_opaque->name = opaque_name;
          bs_opaque->type = opaque_type;
          
          bs_element = bs_opaque;
          bs_element_type = BS_ELEMENT_OPAQUE;
          break;
        }
        
        case BS_XML_CFTYPE:
        {
          bs_element_cftype_t *bs_cftype;
          char *cftype_name;
          char *cftype_type;

          cftype_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(cftype_name, "name");
          cftype_type = get_type_attribute(reader);
          CHECK_TYPE_ATTRIBUTE(cftype_type);

          bs_cftype = 
            (bs_element_cftype_t *)malloc(sizeof(bs_element_cftype_t));
          ASSERT_ALLOC(bs_cftype);

          bs_cftype->name = cftype_name;
          bs_cftype->type = cftype_type;

#if 1
          /* the type_id field isn't used in MacRuby */
          bs_cftype->type_id = 0;
#else
          char *cftype_gettypeid_func_name;
          cftype_gettypeid_func_name = get_attribute(reader, "gettypeid_func");
          if (cftype_gettypeid_func_name != NULL) {
            void *sym;

            sym = dlsym(RTLD_DEFAULT, cftype_gettypeid_func_name);
            if (sym == NULL) {
              BAIL("cannot locate gettypeid_func function `%s'",
                   cftype_gettypeid_func_name);
            }
            else {
              CFTypeID (*cb)(void) = sym;
              bs_cftype->type_id = (*cb)();
            }
          }
          else {
            bs_cftype->type_id = 0;
          }
#endif

          bs_cftype->tollfree = get_attribute(reader, "tollfree");

          bs_element = bs_cftype;
          bs_element_type = BS_ELEMENT_CFTYPE;
          break;
        }
        
        case BS_XML_INFORMAL_PROTOCOL: 
        {
	  if (protocol_name != NULL)
	    free(protocol_name);
          protocol_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(protocol_name, "name");
          break;
        }

        case BS_XML_FUNCTION: 
        {
          char *func_name;
          
          func_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(func_name, "name");

          func = 
            (bs_element_function_t *)malloc(sizeof(bs_element_function_t));
          ASSERT_ALLOC(func);

          func->name = func_name;
          func->variadic = get_boolean_attribute(reader, "variadic", false);
          func->args_count = 0;
          func->args = NULL;
          func->retval = NULL;

          if (xmlTextReaderIsEmptyElement(reader)) {
            bs_element = func;
            bs_element_type = BS_ELEMENT_FUNCTION;
            func = NULL;
          }
          break;
        }

        case BS_XML_FUNCTION_ALIAS: 
        {
          bs_element_function_alias_t *bs_func_alias;
          char *alias_name;
          char *alias_original;

          alias_name = get_attribute(reader, "name"); 
          CHECK_ATTRIBUTE(alias_name, "name");
          alias_original = get_attribute(reader, "original");
          CHECK_ATTRIBUTE(alias_original, "original");

          bs_func_alias = (bs_element_function_alias_t *)malloc(
            sizeof(bs_element_function_alias_t));
          ASSERT_ALLOC(bs_func_alias);
          
          bs_func_alias->name = alias_name;
          bs_func_alias->original = alias_original;

          bs_element = bs_func_alias;
          bs_element_type = BS_ELEMENT_FUNCTION_ALIAS;
          break;
        }

        case BS_XML_CLASS: 
        {
          char *class_name;
          
          class_name = get_attribute(reader, "name");
          CHECK_ATTRIBUTE(class_name, "name");
        
          klass = (bs_element_class_t *)malloc(sizeof(bs_element_class_t));
          ASSERT_ALLOC(klass);
            
          klass->name = class_name;
          klass->class_methods = klass->instance_methods = NULL;
          klass->class_methods_count = klass->instance_methods_count = 0;
          break;
        }

        case BS_XML_ARG:
        {
          if (func != NULL || method != NULL || func_ptr != NULL) {
            bs_element_arg_t *bs_arg; 
            unsigned *argc;

            argc = func_ptr != NULL
              ? &func_ptr->args_count
              : func != NULL 
                ? &func->args_count 
                : &method->args_count;

            if (*argc >= MAX_ARGS) {
              if (func_ptr != NULL)
                BAIL("maximum number of arguments (%d) reached " \
                     "for function pointer", MAX_ARGS);
              else if (func != NULL)
                BAIL("maximum number of arguments (%d) reached " \
                     "for function '%s'", MAX_ARGS, func->name);
              else
                BAIL("maximum number of arguments (%d) reached " \
                     "for method '%s'", MAX_ARGS, (char *)method->name);
            } 

	    bs_element_arg_t *args_from =
		(func_ptr == NULL ? args : fptr_args);
	    bs_arg = &args_from[(*argc)++];

            if (method != NULL && func_ptr == NULL) {
              char *index = get_attribute(reader, "index");
              CHECK_ATTRIBUTE(index, "index");
              bs_arg->index = strtol(index, NULL, 10);
              free(index);
            }
            else {
              bs_arg->index = -1;
            }
            
            get_type_modifier_attribute(reader, &bs_arg->type_modifier);

#if __LP64__
            bs_arg->sel_of_type = get_attribute(reader, "sel_of_type64");
            if (bs_arg->sel_of_type == NULL)
#endif
              bs_arg->sel_of_type = get_attribute(reader, "sel_of_type");

            bs_arg->printf_format = get_boolean_attribute(reader, 
                "printf_format", false); 
            bs_arg->null_accepted = get_boolean_attribute(reader, 
                "null_accepted", true);
            get_c_ary_type_attribute(reader, 
                &bs_arg->carray_type, &bs_arg->carray_type_value); 
  
            bs_arg->type = get_type_attribute(reader);

            if (get_boolean_attribute(reader, "function_pointer", false)) {
              if (func_ptr != NULL) {
                func_ptr = NULL; 
		nested_func_ptr = true;
		break;
	      }
              bs_arg->function_pointer = (bs_element_function_pointer_t *)
                calloc(1, sizeof(bs_element_function_pointer_t));
              ASSERT_ALLOC(bs_arg->function_pointer);
              func_ptr = bs_arg->function_pointer;
              func_ptr_arg_depth = xmlTextReaderDepth(reader);
            }
	    else {
              bs_arg->function_pointer = NULL;
	    }
          }
          else {
            BAIL("argument defined outside of a " \
                 "function/method/function_pointer");
          }
          break;
        }

        case BS_XML_RETVAL: 
        {
          if (func != NULL || method != NULL || func_ptr != NULL) {
            bs_element_retval_t *bs_retval;  

            if (func_ptr != NULL) {
              if (func_ptr->retval != NULL)
                BAIL("function pointer return value defined more than once");
            }
            else if (func != NULL) {
              if (func->retval != NULL)
                BAIL("function '%s' return value defined more than once", 
                     func->name);
            }
            else if (method != NULL) {
              if (method->retval != NULL)
                BAIL("method '%s' return value defined more than once", 
                     (char *)method->name);
            }
    
            bs_retval = 
              (bs_element_retval_t *)malloc(sizeof(bs_element_retval_t));
            ASSERT_ALLOC(bs_retval);

            get_c_ary_type_attribute(reader, &bs_retval->carray_type, 
              &bs_retval->carray_type_value);

            bs_retval->type = get_type_attribute(reader);
            if (bs_retval->type != NULL)
              bs_retval->already_retained = 
                get_boolean_attribute(reader, "already_retained", false);

            if (func_ptr != NULL) {
              if (bs_retval->type != NULL) {
                func_ptr->retval = bs_retval;
              }
              else {
                free(bs_retval);
                BAIL("function pointer return value defined without type"); 
              }
            }
            else if (func != NULL) {
              if (bs_retval->type != NULL) {
                func->retval = bs_retval;
              }
              else {
                free(bs_retval);
#if !defined(__LP64__)
		if (get_type64_attribute(reader) != NULL) {
		    // The function has no 32-bit return value type and we
		    // run in 32-bit mode. We just ignore it.
		    func = NULL;
		    break;
		}
#endif
                BAIL("function '%s' return value defined without type", 
                     func->name);
              }
            }
            else {
              method->retval = bs_retval;
            }

            if (get_boolean_attribute(reader, "function_pointer", false)) {
              if (func_ptr != NULL) {
                func_ptr = NULL; 
		nested_func_ptr = true;
		break;
              }
              bs_retval->function_pointer = (bs_element_function_pointer_t *)
                calloc(1, sizeof(bs_element_function_pointer_t));
              ASSERT_ALLOC(bs_retval->function_pointer);
              func_ptr = bs_retval->function_pointer;
              func_ptr_arg_depth = xmlTextReaderDepth(reader);
            }
	    else {
              bs_retval->function_pointer = NULL;
	    }
          }
          else {
            BAIL("return value defined outside a function/method");
          }
          break;
        }

        case BS_XML_METHOD: 
        {
          if (protocol_name != NULL) {
            bs_element_informal_protocol_method_t *bs_informal_method;
            char *selector;
            char *method_type;

            selector = get_attribute(reader, "selector");
            CHECK_ATTRIBUTE(selector, "selector");
            
            method_type = get_type_attribute(reader);
            CHECK_TYPE_ATTRIBUTE(method_type);

            bs_informal_method = (bs_element_informal_protocol_method_t *)
              malloc(sizeof(bs_element_informal_protocol_method_t));
            ASSERT_ALLOC(bs_informal_method);

            bs_informal_method->name = sel_registerName(selector);
	    free(selector);
            bs_informal_method->class_method = 
              get_boolean_attribute(reader, "class_method", false);
            bs_informal_method->type = method_type;
            bs_informal_method->protocol_name = strdup(protocol_name);

            bs_element = bs_informal_method;
            bs_element_type = BS_ELEMENT_INFORMAL_PROTOCOL_METHOD;
          }
          else if (klass != NULL) {  
            char *selector;

            selector = get_attribute(reader, "selector");
            CHECK_ATTRIBUTE(selector, "selector");

            method = 
              (bs_element_method_t *)malloc(sizeof(bs_element_method_t));
            ASSERT_ALLOC(method);

            method->name = sel_registerName(selector);
	    free(selector);
            method->class_method = 
              get_boolean_attribute(reader, "class_method", false);
            method->variadic = 
              get_boolean_attribute(reader, "variadic", false);
            method->ignore = 
              get_boolean_attribute(reader, "ignore", false);
            method->suggestion = get_attribute(reader, "suggestion");
            method->args_count = 0;
            method->args = NULL;
            method->retval = NULL;

            if (xmlTextReaderIsEmptyElement(reader)) {
              goto index_method;
            }
          }
          else {
            BAIL("method defined outside a class or informal protocol");
          }
          break;
        }
      }
    }
    else if (node_type == XML_READER_TYPE_END_ELEMENT) {
      switch (atom->val) {
        case BS_XML_INFORMAL_PROTOCOL: 
        {
          protocol_name = NULL;
          break;
        }

        case BS_XML_RETVAL:
        case BS_XML_ARG: 
        {
          if (func_ptr != NULL 
              && func_ptr_arg_depth == xmlTextReaderDepth(reader)) {

	      bs_element_retval_t *retval = NULL;
	      bs_element_arg_t *arg = NULL;
	      unsigned args_count;

	      if (atom->val == BS_XML_RETVAL) {
		  retval = func != NULL ? func->retval : method->retval;
	      }
	      else {
		  args_count = func != NULL ? func->args_count
		      : method->args_count;
		  arg = &args[args_count - 1];
	      }

              // Determine if we deal with a block or a function pointer.
	      const char *old_type = (retval ? retval->type : arg->type);
              const char lambda_type = *old_type == '@'
		? _MR_C_LAMBDA_BLOCK
		: _MR_C_LAMBDA_FUNCPTR;

	      char tmp_type[1025]; // 3 less to fit <, type and >
	      char new_type[1028];

	      // Function ptr return type
	      strlcpy(tmp_type, func_ptr->retval->type, sizeof(tmp_type));
	      // Function ptr args
	      for (i = 0; i < func_ptr->args_count; i++) {
		  strlcat(tmp_type, fptr_args[i].type, sizeof(tmp_type));
	      }
	      // Clear the final type string
	      memset(new_type, 0, sizeof(new_type));
	      // Append the function pointer type
	      snprintf(new_type, sizeof(new_type), "%c%c%s%c",
		      _MR_C_LAMBDA_B, lambda_type, tmp_type, _MR_C_LAMBDA_E);

	      // Free the old values
	      if (retval) {
		  free(retval->type);
		  retval->type = strdup(new_type);
	      }
	      else {
		  free(arg->type);
		  arg->type = strdup(new_type);
	      }
            
	      if (func_ptr->args_count > 0) {
		  size_t len;
      
		  len = sizeof(bs_element_arg_t) * func_ptr->args_count;
		  func_ptr->args = (bs_element_arg_t *)malloc(len);
		  ASSERT_ALLOC(func_ptr->args);
		  memcpy(func_ptr->args, fptr_args, len);
	      }
	      else {
		  func_ptr->args = NULL;
	      }
                        
	      func_ptr = NULL;
	      func_ptr_arg_depth = -1;
          }
          break;
        }
 
        case BS_XML_FUNCTION: 
        {
          if (func == NULL) {
            break;
          }
          for (i = 0; i < func->args_count; i++) {
            if (args[i].type == NULL)
              BAIL("function '%s' argument #%d type not provided", 
                   func->name, i);
          }
    
          if (func->args_count > 0) {
            size_t len;
    
            len = sizeof(bs_element_arg_t) * func->args_count;
            func->args = (bs_element_arg_t *)malloc(len);
            ASSERT_ALLOC(func->args);
            memcpy(func->args, args, len);
          }

          bs_element = func;
          bs_element_type = BS_ELEMENT_FUNCTION;
          func = NULL;
          break;
        }

        case BS_XML_METHOD: 
        {
          bs_element_method_t *methods;
          unsigned *methods_count;
          
          if (method->args_count > 0) {
            size_t len;
      
            len = sizeof(bs_element_arg_t) * method->args_count;
            method->args = (bs_element_arg_t *)malloc(len);
            ASSERT_ALLOC(method->args);
            memcpy(method->args, args, len);
          }

index_method:
          methods = method->class_method 
            ? klass->class_methods : klass->instance_methods;

          methods_count = method->class_method
            ? &klass->class_methods_count : &klass->instance_methods_count;

          if (methods == NULL) {
            methods = (bs_element_method_t *)malloc(
              sizeof(bs_element_method_t) * (*methods_count + 1));
          }
          else {
            methods = (bs_element_method_t *)realloc(methods, 
              sizeof(bs_element_method_t) * (*methods_count + 1));
          }
          ASSERT_ALLOC(methods);

    //      methods[*methods_count] = method;
    // FIXME this is inefficient
          memcpy(&methods[*methods_count], method, 
            sizeof(bs_element_method_t));

          (*methods_count)++;
          
          if (method->class_method)
            klass->class_methods = methods;
          else
            klass->instance_methods = methods;
         
          free(method);
          method = NULL;
          break;
        }

        case BS_XML_CLASS: 
        {
          bs_element = klass;
          bs_element_type = BS_ELEMENT_CLASS;
          klass = NULL;
          break;
        }
      }
    }

    if (bs_element != NULL)
      (*callback)(parser, path, bs_element_type, bs_element, context);
  }
  
  success = true;

bails:
  if (protocol_name != NULL)
    free(protocol_name);

  xmlFreeTextReader(reader);

  if (!success) {
      for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths);
	      i < count; i++) {
	  CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i);
	  if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive)
		  == kCFCompareEqualTo) {
	      CFArrayRemoveValueAtIndex(parser->loaded_paths, i);
	      break;
	  }
      }
  }

  if (success && options == BS_PARSE_OPTIONS_LOAD_DYLIBS && framework_path != NULL) {
    char buf[PATH_MAX];

    if (_bs_find_path(framework_path, buf, sizeof buf, "dylib")) {
      if (dlopen(buf, RTLD_LAZY) == NULL) {
        if (error != NULL) {
          *error = dlerror();
        }
        success = false;
      }
    }
  }

  return success;
}
CGFloat *decodeValuesFromImageDictionary(CGPDFDictionaryRef dict, CGColorSpaceRef cgColorSpace, int bitsPerComponent) {
    CGFloat *decodeValues = NULL;
    CGPDFArrayRef decodeArray = NULL;
	
    if (CGPDFDictionaryGetArray(dict, "Decode", &decodeArray)) {
        size_t count = CGPDFArrayGetCount(decodeArray);
        decodeValues = malloc(sizeof(CGFloat) * count);
        CGPDFReal realValue;
        int i;
        for (i = 0; i < count; i++) {
            CGPDFArrayGetNumber(decodeArray, i, &realValue);
            decodeValues[i] = realValue;
        }
    } else {
        size_t n;
		int i;
        switch (CGColorSpaceGetModel(cgColorSpace)) {
            case kCGColorSpaceModelMonochrome:
                decodeValues = malloc(sizeof(CGFloat) * 2);
                decodeValues[0] = 0.0;
                decodeValues[1] = 1.0;
                break;
            case kCGColorSpaceModelRGB:
                decodeValues = malloc(sizeof(CGFloat) * 6);
                for (i = 0; i < 6; i++) {
                    decodeValues[i] = i % 2 == 0 ? 0 : 1;
                }
                break;
            case kCGColorSpaceModelCMYK:
                decodeValues = malloc(sizeof(CGFloat) * 8);
                for (i = 0; i < 8; i++) {
                    decodeValues[i] = i % 2 == 0 ? 0.0 :
                    1.0;
                }
                break;
            case kCGColorSpaceModelLab:
                // ????
                break;
            case kCGColorSpaceModelDeviceN:
                n =
                CGColorSpaceGetNumberOfComponents(cgColorSpace) * 2;
                decodeValues = malloc(sizeof(CGFloat) * (n *
                                                         2));
				i = 0;
                for (; i < n; i++) {
                    decodeValues[i] = i % 2 == 0 ? 0.0 :
                    1.0;
                }
                break;
            case kCGColorSpaceModelIndexed:
                decodeValues = malloc(sizeof(CGFloat) * 2);
                decodeValues[0] = 0.0;
                decodeValues[1] = pow(2.0,(double)bitsPerComponent) - 1;
                break;
            default:
                break;
        }
    }
	
    return (CGFloat *)CFMakeCollectable(decodeValues);
}
CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){
	CGColorSpaceRef       cgColorSpace = NULL, alternateColorSpace = NULL;
	CGPDFStreamRef        stream;
	const char            *colorSpaceName = NULL, *alternateColorSpaceName = NULL;
	CGPDFInteger        numberOfComponents;
	CGPDFDictionaryRef    dict;
	bool                retrieved;
	CGFloat                *range;
	CGPDFArrayRef        rangeArray;
	
	if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) {
		if (strcmp(colorSpaceName, "ICCBased") == 0) {
			if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) {
				dict = CGPDFStreamGetDictionary(stream);
				
				// First obtain the alternate color space if present
				if (CGPDFDictionaryGetName(dict, "Alternate",  &alternateColorSpaceName)) {
					if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) {
						alternateColorSpace = CGColorSpaceCreateDeviceRGB();
					} else if (strcmp(alternateColorSpaceName, "DeviceGray") == 
							   0) {
						alternateColorSpace = CGColorSpaceCreateDeviceGray();
					} else if (strcmp(alternateColorSpaceName, "DeviceCMYK") == 
							   0) {
						alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
					}
				}
				
				// Obtain the preferential color space
				CGPDFDataFormat        dataFormat;
				CFDataRef            colorSpaceDataPtr = 
				CGPDFStreamCopyData(stream, &dataFormat);
				
				if (dataFormat == CGPDFDataFormatRaw) {
					CGDataProviderRef    profile = 
					CGDataProviderCreateWithCFData(colorSpaceDataPtr);
					
					retrieved = CGPDFDictionaryGetInteger(dict, "N", 
														  &numberOfComponents);
					
					// Deduce an alternate color space if we don't have one 
					//already
					if (alternateColorSpace == NULL) {
						switch (numberOfComponents) {
							case 1:
								alternateColorSpace = CGColorSpaceCreateDeviceGray();
								break;
							case 3:
								alternateColorSpace = CGColorSpaceCreateDeviceRGB();
								break;
							case 4:
								alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
								break;
							default:
								break;
						}
					}
					
					range = malloc(numberOfComponents * 2 * sizeof(CGFloat));
					if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) {
						int i = 0;
						for (; i < numberOfComponents * 2; i += 2) {
							range[i] = (i % 2 == 0) ? 0.0 : 1.0;
						}
					} else {
						size_t count = CGPDFArrayGetCount(rangeArray);
						int i = 0;
						for (; i < count; i++) {
							(void)CGPDFArrayGetNumber(rangeArray, i, &range[i]);
						}
						
					}
					
					
					cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile, 
															  alternateColorSpace);
					CGDataProviderRelease(profile);
					free(range);
					if (cgColorSpace) {
						// Since we have a preferential color space, we no 
						//longer need the hang on to the alternate color space
						CGColorSpaceRelease(alternateColorSpace);
					} else {
						cgColorSpace = alternateColorSpace;
					}
					
				} else if (dataFormat == CGPDFDataFormatJPEGEncoded) {
					//
				} else if (dataFormat == CGPDFDataFormatJPEG2000) {
					//
				}
			}
		} else if (strcmp(colorSpaceName, "Indexed") == 0) {
			CGColorSpaceRef baseSpace;
			CGPDFArrayRef    base = NULL;
			CGPDFInteger    highValue = 0;
			CGPDFStreamRef    stream = NULL;
			CGPDFStringRef    string;
			const unsigned char *chars;
			const char        *namedColorSpaceName;
			
			if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) {
				baseSpace = colorSpaceFromPDFArray(base);
			} else if (CGPDFArrayGetName(colorSpaceArray, 1, 
										 &namedColorSpaceName)) {
				if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) {
					baseSpace = CGColorSpaceCreateDeviceRGB();
				} else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) {
					baseSpace = CGColorSpaceCreateDeviceGray();
				} else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) {
					baseSpace = CGColorSpaceCreateDeviceCMYK();
				}
			}
			
			retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue);
			
			if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) {
				chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL));
			} else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) {
				chars = CGPDFStringGetBytePtr(string);
			} else {
				
				// TODO: Raise some error state?
			}
			
			cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue, 
													 chars);
		}
	}
	
	return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace);
}