[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