[macruby-changes] [1530] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Mon May 4 18:27:14 PDT 2009


Revision: 1530
          http://trac.macosforge.org/projects/ruby/changeset/1530
Author:   lsansonetti at apple.com
Date:     2009-05-04 18:27:14 -0700 (Mon, 04 May 2009)
Log Message:
-----------
implemented rb_str_format

Modified Paths:
--------------
    MacRuby/branches/experimental/objc.m
    MacRuby/branches/experimental/roxor.cpp

Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m	2009-05-04 20:55:33 UTC (rev 1529)
+++ MacRuby/branches/experimental/objc.m	2009-05-05 01:27:14 UTC (rev 1530)
@@ -582,202 +582,6 @@
 #endif
 }
 
-#if 0
-static void
-rb_objc_get_types_for_format_str(char **octypes, const int len, VALUE *args,
-				 const char *format_str, char **new_fmt)
-{
-    unsigned i, j, format_str_len;
-
-    format_str_len = strlen(format_str);
-    i = j = 0;
-
-    while (i < format_str_len) {
-	bool sharp_modifier = false;
-	bool star_modifier = false;
-	if (format_str[i++] != '%')
-	    continue;
-	if (i < format_str_len && format_str[i] == '%') {
-	    i++;
-	    continue;
-	}
-	while (i < format_str_len) {
-	    char *type = NULL;
-	    switch (format_str[i]) {
-		case '#':
-		    sharp_modifier = true;
-		    break;
-
-		case '*':
-		    star_modifier = true;
-		    type = "i"; // C_INT;
-		    break;
-
-		case 'd':
-		case 'i':
-		case 'o':
-		case 'u':
-		case 'x':
-		case 'X':
-		    type = "i"; // _C_INT;
-		    break;
-
-		case 'c':
-		case 'C':
-		    type = "c"; // _C_CHR;
-		    break;
-
-		case 'D':
-		case 'O':
-		case 'U':
-		    type = "l"; // _C_LNG;
-		    break;
-
-		case 'f':       
-		case 'F':
-		case 'e':       
-		case 'E':
-		case 'g':       
-		case 'G':
-		case 'a':
-		case 'A':
-		    type = "d"; // _C_DBL;
-		    break;
-
-		case 's':
-		case 'S':
-		    {
-			if (i - 1 > 0) {
-			    long k = i - 1;
-			    while (k > 0 && format_str[k] == '0')
-				k--;
-			    if (k < i && format_str[k] == '.')
-				args[j] = (VALUE)CFSTR("");
-			}
-			type = "*"; // _C_CHARPTR;
-		    }
-		    break;
-
-		case 'p':
-		    type = "^"; // _C_PTR;
-		    break;
-
-		case '@':
-		    type = "@"; // _C_ID;
-		    break;
-
-		case 'B':
-		case 'b':
-		    {
-			VALUE arg = args[j];
-			switch (TYPE(arg)) {
-			    case T_STRING:
-				arg = rb_str_to_inum(arg, 0, Qtrue);
-				break;
-			}
-			arg = rb_big2str(arg, 2);
-			if (sharp_modifier) {
-			    VALUE prefix = format_str[i] == 'B'
-				? (VALUE)CFSTR("0B") : (VALUE)CFSTR("0b");
-			   rb_str_update(arg, 0, 0, prefix);
-			}
-			if (*new_fmt == NULL)
-			    *new_fmt = strdup(format_str);
-			(*new_fmt)[i] = '@';
-			args[j] = arg;
-			type = "@"; 
-		    }
-		    break;
-	    }
-
-	    i++;
-
-	    if (type != NULL) {
-		if (len == 0 || j >= len) {
-		    rb_raise(rb_eArgError, 
-			    "Too much tokens in the format string `%s' "\
-			    "for the given %d argument(s)", format_str, len);
-		}
-		octypes[j++] = type;
-		if (!star_modifier) {
-		    break;
-		}
-	    }
-	}
-    }
-    for (; j < len; j++) {
-	octypes[j] = "@"; // _C_ID;
-    }
-}
-#endif
-
-VALUE
-rb_str_format(int argc, const VALUE *argv, VALUE fmt)
-{
-#if 0
-    char **types;
-    ffi_type *ffi_rettype, **ffi_argtypes;
-    void *ffi_ret, **ffi_args;
-    ffi_cif *cif;
-    int i;
-    void *null;
-    char *new_fmt;
-
-    if (argc == 0)
-	return fmt;
-
-    types = (char **)alloca(sizeof(char *) * argc);
-    ffi_argtypes = (ffi_type **)alloca(sizeof(ffi_type *) * (argc + 4));
-    ffi_args = (void **)alloca(sizeof(void *) * (argc + 4));
-
-    null = NULL;
-    new_fmt = NULL;
-
-    rb_objc_get_types_for_format_str(types, argc, (VALUE *)argv, 
-	    RSTRING_PTR(fmt), &new_fmt);
-    if (new_fmt != NULL) {
-	fmt = (VALUE)CFStringCreateWithCString(NULL, new_fmt, 
-		kCFStringEncodingUTF8);
-	xfree(new_fmt);
-	CFMakeCollectable((void *)fmt);
-    }  
-
-    for (i = 0; i < argc; i++) {
-	ffi_argtypes[i + 3] = rb_objc_octype_to_ffitype(types[i]);
-	ffi_args[i + 3] = (void *)alloca(ffi_argtypes[i + 3]->size);
-	rb_objc_rval_to_ocval(argv[i], types[i], ffi_args[i + 3]);
-    }
-
-    ffi_argtypes[0] = &ffi_type_pointer;
-    ffi_args[0] = &null;
-    ffi_argtypes[1] = &ffi_type_pointer;
-    ffi_args[1] = &null;
-    ffi_argtypes[2] = &ffi_type_pointer;
-    ffi_args[2] = &fmt;
-   
-    ffi_argtypes[argc + 4] = NULL;
-    ffi_args[argc + 4] = NULL;
-
-    ffi_rettype = &ffi_type_pointer;
-    
-    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
-
-    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, argc + 3, ffi_rettype, ffi_argtypes)
-        != FFI_OK)
-        rb_fatal("can't prepare cif for CFStringCreateWithFormat");
-
-    ffi_ret = NULL;
-
-    ffi_call(cif, FFI_FN(CFStringCreateWithFormat), &ffi_ret, ffi_args);
-
-    if (ffi_ret != NULL) {
-        CFMakeCollectable((CFTypeRef)ffi_ret);
-        return (VALUE)ffi_ret;
-    }
-#endif
-    return Qnil;
-}
-
 extern bool __CFStringIsMutable(void *);
 extern bool _CFArrayIsMutable(void *);
 extern bool _CFDictionaryIsMutable(void *);

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-05-04 20:55:33 UTC (rev 1529)
+++ MacRuby/branches/experimental/roxor.cpp	2009-05-05 01:27:14 UTC (rev 1530)
@@ -5878,31 +5878,43 @@
 
     // Arguments.
     std::vector<int> byval_args;
-    for (int i = 0; i < argc; i++) {
-	p = GetFirstType(p, buf, sizeof buf);
+    int given_argc = 0;
+    bool variadic = false;
+    while ((p = GetFirstType(p, buf, sizeof buf)) != NULL && buf[0] != '\0') {
+	if (given_argc == argc) {
+	    variadic = true;
+	}
+
 	const Type *llvm_type = convert_type(buf);
+	const Type *f_type = llvm_type;
 	if (GET_VM()->is_large_struct_type(llvm_type)) {
 	    // We are passing a large struct, we need to mark this argument
 	    // with the byval attribute and configure the internal stub
 	    // call to pass a pointer to the structure, to conform to the
 	    // ABI.
-	    f_types.push_back(PointerType::getUnqual(llvm_type));
-	    byval_args.push_back(i + 3);
+	    f_type = PointerType::getUnqual(llvm_type);
+	    byval_args.push_back(f_types.size() + 1 /* retval */);
 	}
-	else {
-	    f_types.push_back(llvm_type);
+
+	if (!variadic) {
+	    // In order to conform to the ABI, we must stop providing types once we
+	    // start dealing with variable arguments and instead mark the function as
+	    // variadic.
+	    f_types.push_back(f_type);
 	}
 
-	Value *index = ConstantInt::get(Type::Int32Ty, i);
+	Value *index = ConstantInt::get(Type::Int32Ty, given_argc);
 	Value *slot = GetElementPtrInst::Create(argv_arg, index, "", bb);
 	Value *arg_val = new LoadInst(slot, "", bb);
 	Value *new_val_slot = new AllocaInst(llvm_type, "", bb);
 
 	params.push_back(compile_conversion_to_c(buf, arg_val, new_val_slot));
+
+	given_argc++;
     }
 
     // Appropriately cast the IMP argument.
-    FunctionType *ft = FunctionType::get(ret_type, f_types, false);
+    FunctionType *ft = FunctionType::get(ret_type, f_types, variadic);
     Value *imp = new BitCastInst(imp_arg, PointerType::getUnqual(ft), "", bb);
 
     // Compile call.
@@ -7330,8 +7342,8 @@
 
     int n = 0;
     VALUE args[3];
-    VALUE message = rb_const_get(exc, rb_intern("message"));
-    args[n++] = rb_funcall(message, '!', 3, rb_str_new2(format), obj, argv[0]);
+    args[n++] = rb_funcall(rb_cNameErrorMesg, '!', 3, rb_str_new2(format), obj,
+	    argv[0]);
     args[n++] = argv[0];
     if (exc == rb_eNoMethodError) {
 	args[n++] = rb_ary_new4(argc - 1, argv + 1);
@@ -9913,6 +9925,166 @@
 #endif
 }
 
+// String format
+
+static void
+get_types_for_format_str(std::string &octypes, const unsigned int len,
+			 VALUE *args, const char *format_str, char **new_fmt)
+{
+    size_t format_str_len = strlen(format_str);
+    unsigned int i = 0, j = 0;
+
+    while (i < format_str_len) {
+	bool sharp_modifier = false;
+	bool star_modifier = false;
+	if (format_str[i++] != '%') {
+	    continue;
+	}
+	if (i < format_str_len && format_str[i] == '%') {
+	    i++;
+	    continue;
+	}
+	while (i < format_str_len) {
+	    char type = 0;
+	    switch (format_str[i]) {
+		case '#':
+		    sharp_modifier = true;
+		    break;
+
+		case '*':
+		    star_modifier = true;
+		    type = _C_INT;
+		    break;
+
+		case 'd':
+		case 'i':
+		case 'o':
+		case 'u':
+		case 'x':
+		case 'X':
+		    type = _C_INT;
+		    break;
+
+		case 'c':
+		case 'C':
+		    type = _C_CHR;
+		    break;
+
+		case 'D':
+		case 'O':
+		case 'U':
+		    type = _C_LNG;
+		    break;
+
+		case 'f':       
+		case 'F':
+		case 'e':       
+		case 'E':
+		case 'g':       
+		case 'G':
+		case 'a':
+		case 'A':
+		    type = _C_DBL;
+		    break;
+
+		case 's':
+		case 'S':
+		    {
+			if (i - 1 > 0) {
+			    unsigned long k = i - 1;
+			    while (k > 0 && format_str[k] == '0') {
+				k--;
+			    }
+			    if (k < i && format_str[k] == '.') {
+				args[j] = (VALUE)CFSTR("");
+			    }
+			}
+			type = _C_CHARPTR;
+		    }
+		    break;
+
+		case 'p':
+		    type = _C_PTR;
+		    break;
+
+		case '@':
+		    type = _C_ID;
+		    break;
+
+		case 'B':
+		case 'b':
+		    {
+			VALUE arg = args[j];
+			switch (TYPE(arg)) {
+			    case T_STRING:
+				arg = rb_str_to_inum(arg, 0, Qtrue);
+				break;
+			}
+			arg = rb_big2str(arg, 2);
+			if (sharp_modifier) {
+			    VALUE prefix = format_str[i] == 'B'
+				? (VALUE)CFSTR("0B") : (VALUE)CFSTR("0b");
+			    rb_str_update(arg, 0, 0, prefix);
+			}
+			if (*new_fmt == NULL) {
+			    *new_fmt = strdup(format_str);
+			}
+			(*new_fmt)[i] = '@';
+			args[j] = arg;
+			type = _C_ID;
+		    }
+		    break;
+	    }
+
+	    i++;
+
+	    if (type != 0) {
+		if (len == 0 || j >= len) {
+		    rb_raise(rb_eArgError, 
+			    "Too much tokens in the format string `%s' "\
+			    "for the given %d argument(s)", format_str, len);
+		}
+		octypes.push_back(type);
+		j++;
+		if (!star_modifier) {
+		    break;
+		}
+	    }
+	}
+    }
+    for (; j < len; j++) {
+	octypes.push_back(_C_ID);
+    }
+}
+
+VALUE
+rb_str_format(int argc, const VALUE *argv, VALUE fmt)
+{
+    char *new_fmt = NULL;
+    std::string types("@@@@");
+    get_types_for_format_str(types, (unsigned int)argc, (VALUE *)argv, 
+	    RSTRING_PTR(fmt), &new_fmt);
+
+    if (new_fmt != NULL) {
+	fmt = rb_str_new2(new_fmt);
+    }  
+
+    VALUE *stub_args = (VALUE *)alloca(sizeof(VALUE) * argc + 4);
+    stub_args[0] = Qnil; // allocator
+    stub_args[1] = Qnil; // format options
+    stub_args[2] = fmt;  // format string
+    for (int i = 0; i < argc; i++) {
+	stub_args[3 + i] = argv[i];
+    }
+
+    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types,
+	    3, false);
+
+    VALUE str = (*stub)((IMP)&CFStringCreateWithFormat, argc + 3, stub_args);
+    CFMakeCollectable((void *)str);
+    return str;
+}
+
 // FFI
 
 static const char *
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090504/418dcde5/attachment.html>


More information about the macruby-changes mailing list