diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index aa5fce8..5e2dc3d 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -90,12 +90,13 @@ extend Apex ## ------------------------------------------------------- ## ------------------------------------------------------- - ##method(#primitive,#lenient) _shallowCopy. + ##method(#dual,#primitive,#lenient) _shallowCopy. + ##method(#dual,#primitive) shallowCopy. method(#dual) shallowCopy { - self primitiveFailed. + self primitiveFailed(thisContext method). } diff --git a/moo/kernel/Collect.moo b/moo/kernel/Collect.moo index 932ecd7..75a910c 100644 --- a/moo/kernel/Collect.moo +++ b/moo/kernel/Collect.moo @@ -112,6 +112,12 @@ class(#character) String(Array) { } *) + + + (* The strlen method returns the number of characters before a terminating null. + * if no terminating null character exists, it returns the same value as the size method *) + method(#primitive,#lenient) _strlen. + method(#primitive) strlen. } ## ------------------------------------------------------------------------------- diff --git a/moo/kernel/Except.moo b/moo/kernel/Except.moo index 1a869bb..482cd29 100644 --- a/moo/kernel/Except.moo +++ b/moo/kernel/Except.moo @@ -431,12 +431,34 @@ class ProhibitedMessageException(Exception) { } +(* +pooldic ErrorToException +{ + ErrorCode.EINVAL := InvalidArgumentException. + ErrorCode.ENOIMPL := NotImplementedException. +} +*) + extend Apex { method(#dual,#liberal) primitiveFailed(method) { | a b msg ec ex | + (* since method is an argument, the caller can call this method + * from a context chain where the method context actually doesn't exist. + * when a primitive method is defined using the #primitive method, + * the VM invokes this primtiveFailed method without creating + * the context for the primitive method. + * method(#primitive) xxx. + * method(#primitive) xxx { ^self primitiveFailed(thisContext method). } + * in the former definition, primitiveFailed is called without + * an activate context for the method xxx if the primitive fails. + * on the other handle, in the latter definition, the context + * for the method is activated first before primitiveFailed is + * invoked. in the context chain, the method for xxx is found. + *) + (*System logNl: 'Arguments: '. a := 0. b := thisContext vargCount. @@ -445,11 +467,13 @@ extend Apex System logNl: (thisContext vargAt: a) asString. a := a + 1. }.*) - + ec := thisProcess primError. - msg := ec asString. + msg := thisProcess primErrorMessage. + if (msg isNil) { msg := ec asString }. if (method notNil) { msg := msg & ' - ' & (method owner name) & '>>' & (method name) }. - (PrimitiveFailureException withErrorCode: ec) signal: msg. + + (PrimitiveFailureException (* in: method *) withErrorCode: ec) signal: msg. } method(#dual) doesNotUnderstand: message_name diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index d291434..e114f33 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -1,7 +1,7 @@ class(#pointer,#final,#limited) Process(Object) { - var initial_context, current_context, state, sp, prev, next, sem, perr. + var initial_context, current_context, state, sp, prev, next, sem, perr, perrmsg. method prev { ^self.prev } method next { ^self.next } @@ -10,30 +10,16 @@ class(#pointer,#final,#limited) Process(Object) method prev: process { self.prev := process } method primError { ^self.perr } + method primErrorMessage { ^self.perrmsg } - method resume - { - - self primitiveFailed - - ##^Processor resume: self. - } - - method _terminate - { - - self primitiveFailed - } - - method _suspend - { - - self primitiveFailed - } + method(#primitive) resume. + method(#primitive) yield. + method(#primitive) _terminate. + method(#primitive) _suspend. method terminate { -##search from the top contextof the process down to intial_contextand find ensure blocks and execute them. +##search from the top contextof the process down to intial_context and find ensure blocks and execute them. ## if a different process calls 'terminate' on a process, ## the ensureblock is not executed in the context of the ## process being terminated, but in the context of terminatig process. @@ -62,12 +48,6 @@ class(#pointer,#final,#limited) Process(Object) ^self _terminate } - method yield - { - - self primitiveFailed - } - method sp { ^self.sp. diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 52df135..63c0f5d 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -3797,6 +3797,113 @@ static int compile_method_pragma (moo_t* moo) return 0; } +static int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, var_info_t* var) +{ + /* if a name is dotted, + * + * self.XXX - instance variable + * A.B.C - namespace or pool dictionary related reference. + * self.B.C - B.C under the current class where B is not an instance variable + */ + + moo_oocs_t last; + moo_oop_set_t ns_oop; + moo_oop_association_t ass; + const moo_ooch_t* dot; + + dot = moo_findoochar (name->ptr, name->len, '.'); + MOO_ASSERT (moo, dot != MOO_NULL); + if (dot - (const moo_ooch_t*)name->ptr == 4 && + moo_equaloochars(name->ptr, vocas[VOCA_SELF].str, 4)) + { + /* special case. the dotted name begins with self. */ + dot = moo_findoochar (dot + 1, name->len - 5, '.'); + if (!dot) + { + /* the dotted name is composed of 2 segments only */ + last.ptr = name->ptr + 5; + last.len = name->len - 5; + if (is_reserved_word(&last)) + { + /* self. is followed by a reserved word. + * a proper variable name is expected. */ + set_syntax_error (moo, MOO_SYNERR_VARNAME, name_loc, name); + return -1; + } + + if (find_class_level_variable(moo, moo->c->cls.self_oop, &last, var) >= 0) + { + /* indicate that it's not a global variable */ + return 1; + } + else + { + /* undeclared identifier */ + set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); + return -1; + } + } + } + + if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, MOO_NULL, name, name_loc, &last, &ns_oop) <= -1) return -1; + + ass = moo_lookupdic (moo, ns_oop, &last); + if (!ass) + { + /* undeclared identifier */ + set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); + return -1; + } + + var->type = VAR_GLOBAL; + var->gbl = ass; + return 0; +} + +static int find_ident_in_nsdic_and_sysdic (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, var_info_t* var) +{ + moo_oop_association_t ass; + + /* find an undotted identifier in dictionaries */ + + ass = moo_lookupdic (moo, moo->c->cls.ns_oop, name); /* in the current name space */ + if (!ass && moo->c->cls.ns_oop != moo->sysdic) + ass = moo_lookupdic (moo, moo->sysdic, name); /* in the top-level system dictionary */ + + if (!ass) + { + moo_oow_t i; + moo_oop_association_t ass2 = MOO_NULL; + + /* attempt to find the variable in pool dictionaries */ + for (i = 0; i < moo->c->cls.pooldic_count; i++) + { + ass = moo_lookupdic (moo, moo->c->cls.pooldic_imp_oops[i], name); + if (ass) + { + if (ass2) + { + /* the variable name has been found at least in 2 dictionaries - ambiguous */ + set_syntax_error (moo, MOO_SYNERR_VARAMBIG, name_loc, name); + return -1; + } + ass2 = ass; + } + } + + ass = ass2; + if (!ass) + { + set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); + return -1; + } + } + + var->type = VAR_GLOBAL; + var->gbl = ass; + return 0; +} + static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, int name_dotted, var_info_t* var) { moo_oow_t index; @@ -3805,61 +3912,9 @@ static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_iolo if (name_dotted) { - /* if a name is dotted, - * - * self.XXX - instance variable - * A.B.C - namespace or pool dictionary related reference. - * self.B.C - B.C under the current class where B is not an instance variable - */ - - moo_oocs_t last; - moo_oop_set_t ns_oop; - moo_oop_association_t ass; - const moo_ooch_t* dot; - - dot = moo_findoochar (name->ptr, name->len, '.'); - MOO_ASSERT (moo, dot != MOO_NULL); - if (dot - (const moo_ooch_t*)name->ptr == 4 && - moo_equaloochars(name->ptr, vocas[VOCA_SELF].str, 4)) - { - /* the dotted name begins with self. */ - dot = moo_findoochar (dot + 1, name->len - 5, '.'); - if (!dot) - { - /* the dotted name is composed of 2 segments only */ - last.ptr = name->ptr + 5; - last.len = name->len - 5; - if (!is_reserved_word(&last)) - { - if (find_class_level_variable(moo, moo->c->cls.self_oop, &last, var) >= 0) - { - goto class_level_variable; - } - else - { - /* undeclared identifier */ - set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); - return -1; - } - } - } - } - - if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, MOO_NULL, name, name_loc, &last, &ns_oop) <= -1) return -1; - - ass = moo_lookupdic (moo, ns_oop, &last); - if (ass) - { - var->type = VAR_GLOBAL; - var->gbl = ass; - } - else - { - /* undeclared identifier */ - set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); - return -1; - } - + int n; + if ((n = find_dotted_ident (moo, name, name_loc, var)) <= -1) return -1; + if (n >= 1) goto class_level_variable; return 0; } @@ -3918,50 +3973,7 @@ static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_iolo } else { - moo_oop_association_t ass; - /*ass = moo_lookupsysdic (moo, name);*/ - ass = moo_lookupdic (moo, moo->c->cls.ns_oop, name); - if (!ass && moo->c->cls.ns_oop != moo->sysdic) - ass = moo_lookupdic (moo, moo->sysdic, name); - - if (ass) - { - var->type = VAR_GLOBAL; - var->gbl = ass; - } - else - { - moo_oow_t i; - moo_oop_association_t ass2 = MOO_NULL; - - /* attempt to find the variable in pool dictionaries */ - for (i = 0; i < moo->c->cls.pooldic_count; i++) - { - ass = moo_lookupdic (moo, moo->c->cls.pooldic_imp_oops[i], name); - if (ass) - { - if (ass2) - { - /* the variable name has been found at least in 2 dictionaries */ - set_syntax_error (moo, MOO_SYNERR_VARAMBIG, name_loc, name); - return -1; - } - ass2 = ass; - } - } - - if (ass2) - { - var->type = VAR_GLOBAL; - var->gbl = ass2; - } - else - { - /* undeclared identifier */ - set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name); - return -1; - } - } + if (find_ident_in_nsdic_and_sysdic (moo, name, name_loc, var) <= -1) return -1; } } @@ -4356,6 +4368,31 @@ static int __read_array_literal (moo_t* moo, int rdonly, moo_oop_t* xlit) } break; + case MOO_IOTOK_IDENT: + { + var_info_t var; + if (find_ident_in_nsdic_and_sysdic (moo, TOKEN_NAME(moo), TOKEN_LOC(moo), &var) <= -1) return -1; + MOO_ASSERT (moo, var.type == VAR_GLOBAL); + lit = var.gbl->value; + /* [NOTE] i don't mark RDONLY on an array member resolved via an identifier */ + break; + } + + case MOO_IOTOK_IDENT_DOTTED: + { + var_info_t var; + if (find_dotted_ident (moo, TOKEN_NAME(moo), TOKEN_LOC(moo), &var) <= -1) return -1; + if (var.type != VAR_GLOBAL) + { +/* TODO: XXXXXXXXXXXXXXXXXXXXXXXXxx */ + return -1; + } + + lit = var.gbl->value; + /* [NOTE] i don't mark RDONLY on an array member resolved via an identifier */ + break; + } + case MOO_IOTOK_BABRACK: /* #[ */ GET_TOKEN (moo); if (__read_byte_array_literal (moo, &lit) <= -1) return -1; @@ -7371,6 +7408,11 @@ static int compile_pooldic_definition (moo_t* moo) moo->c->mth.balit_count = 0; moo->c->mth.arlit_count = 0; + /* these 2 are pooldic import information. pooldic definition doesn't + * have another pooldic import in it */ + moo->c->cls.pooldic_count = 0; + moo->c->cls.pooldic.len = 0; + n = __compile_pooldic_definition (moo); /* reset these oops plus literal pointers not to confuse gc_compiler() */ @@ -7379,6 +7421,9 @@ static int compile_pooldic_definition (moo_t* moo) moo->c->mth.balit_count = 0; moo->c->mth.arlit_count = 0; + MOO_ASSERT (moo, moo->c->cls.pooldic_count == 0); + MOO_ASSERT (moo, moo->c->cls.pooldic.len == 0); + return n; } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 05f25db..ff0874f 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -162,6 +162,7 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c) proc->current_context = c; proc->sp = MOO_SMOOI_TO_OOP(-1); proc->perr = MOO_ERROR_TO_OOP(MOO_ENOERR); + proc->perrmsg = moo->_nil; MOO_ASSERT (moo, (moo_oop_t)c->sender == moo->_nil); @@ -1472,7 +1473,7 @@ static MOO_INLINE moo_pfrc_t pf_basic_new (moo_t* moo, moo_ooi_t nargs) if (MOO_CLASS_SELFSPEC_FLAGS(MOO_OOP_TO_SMOOI(_class->selfspec)) & MOO_CLASS_SELFSPEC_FLAG_LIMITED) { MOO_DEBUG1 (moo, " Receiver is #limited - %O\n", _class); - moo_seterrbfmt (moo, MOO_EPERM, "#limited receiver - %O", _class); + moo_seterrbfmt (moo, MOO_EPERM, "limited receiver - %O", _class); return MOO_PF_FAILURE; } @@ -2098,13 +2099,18 @@ static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +/* ------------------------------------------------------------------ */ + static moo_pfrc_t pf_process_resume (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; - MOO_ASSERT (moo, nargs == 0); rcv = MOO_STACK_GETRCV(moo, nargs); - if (MOO_CLASSOF(moo,rcv) != moo->_process) return MOO_PF_FAILURE; + if (MOO_CLASSOF(moo,rcv) != moo->_process) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } resume_process (moo, (moo_oop_process_t)rcv); /* TODO: error check */ @@ -2115,12 +2121,15 @@ static moo_pfrc_t pf_process_resume (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_process_terminate (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; - MOO_ASSERT (moo, nargs == 0); /* TODO: need to run ensure blocks here.. * when it's executed here. it does't have to be in Exception>>handleException when there is no exception handler */ rcv = MOO_STACK_GETRCV(moo, nargs); - if (MOO_CLASSOF(moo,rcv) != moo->_process) return MOO_PF_FAILURE; + if (MOO_CLASSOF(moo,rcv) != moo->_process) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } terminate_process (moo, (moo_oop_process_t)rcv); @@ -2131,10 +2140,13 @@ static moo_pfrc_t pf_process_terminate (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_process_yield (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; - MOO_ASSERT (moo, nargs == 0); rcv = MOO_STACK_GETRCV(moo, nargs); - if (MOO_CLASSOF(moo,rcv) != moo->_process) return MOO_PF_FAILURE; + if (MOO_CLASSOF(moo,rcv) != moo->_process) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } yield_process (moo, (moo_oop_process_t)rcv); @@ -2145,10 +2157,13 @@ static moo_pfrc_t pf_process_yield (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_process_suspend (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; - MOO_ASSERT (moo, nargs == 0); rcv = MOO_STACK_GETRCV(moo, nargs); - if (MOO_CLASSOF(moo,rcv) != moo->_process) return MOO_PF_FAILURE; + if (MOO_CLASSOF(moo,rcv) != moo->_process) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } suspend_process (moo, (moo_oop_process_t)rcv); @@ -2156,6 +2171,25 @@ static moo_pfrc_t pf_process_suspend (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +static moo_pfrc_t pf_process_primerr_msg (moo_t* moo, moo_ooi_t nargs) +{ + moo_oop_t rcv, msg; + + rcv = MOO_STACK_GETRCV(moo, nargs); + if (MOO_CLASSOF(moo,rcv) != moo->_process) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } + + msg = moo_makestring (moo, (moo_ooch_t*)MOO_OBJ_GET_TRAILER_BYTE(rcv), moo_countoocstr((moo_ooch_t*)MOO_OBJ_GET_TRAILER_BYTE(rcv))); + if (!msg) return MOO_PF_FAILURE; + + MOO_STACK_SETRET (moo, nargs, msg); + return MOO_PF_SUCCESS; +} + +/* ------------------------------------------------------------------ */ static moo_pfrc_t pf_semaphore_signal (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; @@ -2432,6 +2466,8 @@ static moo_pfrc_t pf_processor_return_to (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +/* ------------------------------------------------------------------ */ + static moo_pfrc_t pf_integer_add (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv, arg, res; @@ -2775,6 +2811,8 @@ static moo_pfrc_t pf_integer_inttostr (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +/* ------------------------------------------------------------------ */ + static moo_pfrc_t pf_character_as_smooi (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv; @@ -2907,6 +2945,36 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +static moo_pfrc_t pf_strlen (moo_t* moo, moo_ooi_t nargs) +{ + moo_oop_t rcv, ret; + moo_oow_t i, limit; + moo_ooch_t* ptr; + + rcv = MOO_STACK_GETRCV(moo, nargs); + if (!MOO_OBJ_IS_CHAR_POINTER(rcv)) + { + moo_seterrnum (moo, MOO_EMSGRCV); + return MOO_PF_FAILURE; + } + + /* [NOTE] the length check loop is directly implemented + * here to be able to handle character objects + * regardless of the existence of the EXTRA flag */ + limit = MOO_OBJ_GET_SIZE(rcv); + ptr = MOO_OBJ_GET_CHAR_SLOT(rcv); + for (i = 0; i < limit; i++) + { + if (*ptr == '\0') break; + ptr++; + } + ret = moo_oowtoint (moo, i); + if (!ret) return MOO_PF_FAILURE; + + MOO_STACK_SETRET (moo, nargs, ret); + return MOO_PF_SUCCESS; +} + static MOO_INLINE moo_pfrc_t _system_alloc (moo_t* moo, moo_ooi_t nargs, int clear) { moo_oop_t tmp; @@ -3690,11 +3758,7 @@ static pf_t pftab[] = { "_block_value", { pf_block_value, 0, MA } }, { "_block_new_process", { pf_block_new_process, 0, 1 } }, - { "_process_resume", { pf_process_resume, 0, 0 } }, - { "_process_terminate", { pf_process_terminate, 0, 0 } }, - { "_process_yield", { pf_process_yield, 0, 0 } }, - { "_process_suspend", { pf_process_suspend, 0, 0 } }, - + { "_processor_schedule", { pf_processor_schedule, 1, 1 } }, { "_processor_add_timed_semaphore", { pf_processor_add_timed_semaphore, 2, 3 } }, { "_processor_add_input_semaphore", { pf_processor_add_input_semaphore, 2, 2 } }, @@ -3739,6 +3803,11 @@ static pf_t pftab[] = { "Error_asInteger", { pf_error_as_integer, 0, 0 } }, { "Error_asString", { pf_error_as_string, 0, 0 } }, + { "Process__suspend", { pf_process_suspend, 0, 0 } }, + { "Process__terminate", { pf_process_terminate, 0, 0 } }, + { "Process_resume", { pf_process_resume, 0, 0 } }, + { "Process_yield", { pf_process_yield, 0, 0 } }, + { "Semaphore_signal", { pf_semaphore_signal, 0, 0 } }, { "Semaphore_wait", { pf_semaphore_wait, 0, 0 } }, @@ -3764,6 +3833,9 @@ static pf_t pftab[] = { "SmallPointer_putUint32", { pf_smptr_put_uint32, 2, 2 } }, { "SmallPointer_putUint64", { pf_smptr_put_uint64, 2, 2 } }, + { "String__strlen", { pf_strlen, 0, 0 } }, + { "String_strlen", { pf_strlen, 0, 0 } }, + { "System__calloc", { pf_system_calloc, 1, 1 } }, { "System__free", { pf_system_free, 1, 1 } }, { "System__getInt16", { pf_system_get_int16, 2, 2 } }, @@ -4027,6 +4099,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) * directly in the stack unlik a normal activated method context where the * arguments are copied to the back. */ + moo_seterrnum (moo, MOO_ENOERR); n = pfbase->handler (moo, nargs); moo_poptmp (moo); @@ -4057,6 +4130,23 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) /* set the error number in the current process for 'thisProcess primError' */ moo->processor->active->perr = MOO_ERROR_TO_OOP(moo->errnum); + if (moo->errmsg.len > 0) + { + /* compose an error message string. */ + /* TODO: i don't like to do this here. + * is it really a good idea to compose a string here which + * is not really failure safe without losing integrity???? */ + moo_oop_t tmp; + moo_pushtmp (moo, (moo_oop_t*)&method); + tmp = moo_makestring (moo, moo->errmsg.buf, moo->errmsg.len); + moo_poptmp (moo); + /* [NOTE] carry on even if instantiation fails */ + moo->processor->active->perrmsg = tmp? tmp: moo->_nil; + } + else + { + moo->processor->active->perrmsg = moo->_nil; + } #if defined(MOO_USE_METHOD_TRAILER) MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method)); diff --git a/moo/lib/logfmt.c b/moo/lib/logfmt.c index 014d671..4065c8a 100644 --- a/moo/lib/logfmt.c +++ b/moo/lib/logfmt.c @@ -375,35 +375,37 @@ redo: /* ------------------------------------------------------------------------- */ -static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) +typedef moo_ooi_t (*outbfmt_t) (moo_t* moo, moo_oow_t mask, const moo_bch_t* fmt, ...); + +static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop, outbfmt_t outbfmt) { if (oop == moo->_nil) { - moo_logbfmt (moo, mask, "nil"); + outbfmt (moo, mask, "nil"); } else if (oop == moo->_true) { - moo_logbfmt (moo, mask, "true"); + outbfmt (moo, mask, "true"); } else if (oop == moo->_false) { - moo_logbfmt (moo, mask, "false"); + outbfmt (moo, mask, "false"); } else if (MOO_OOP_IS_SMOOI(oop)) { - moo_logbfmt (moo, mask, "%zd", MOO_OOP_TO_SMOOI(oop)); + outbfmt (moo, mask, "%zd", MOO_OOP_TO_SMOOI(oop)); } else if (MOO_OOP_IS_SMPTR(oop)) { - moo_logbfmt (moo, mask, "%p", MOO_OOP_TO_SMPTR(oop)); + outbfmt (moo, mask, "%p", MOO_OOP_TO_SMPTR(oop)); } else if (MOO_OOP_IS_CHAR(oop)) { - moo_logbfmt (moo, mask, "$%.1C", MOO_OOP_TO_CHAR(oop)); + outbfmt (moo, mask, "$%.1C", MOO_OOP_TO_CHAR(oop)); } else if (MOO_OOP_IS_ERROR(oop)) { - moo_logbfmt (moo, mask, "error(%zd)", MOO_OOP_TO_ERROR(oop)); + outbfmt (moo, mask, "error(%zd)", MOO_OOP_TO_ERROR(oop)); } else { @@ -416,26 +418,26 @@ static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) if (c == moo->_large_negative_integer) { moo_oow_t i; - moo_logbfmt (moo, mask, "-16r"); + outbfmt (moo, mask, "-16r"); for (i = MOO_OBJ_GET_SIZE(oop); i > 0;) { - moo_logbfmt (moo, mask, "%0*lX", (int)(MOO_SIZEOF(moo_liw_t) * 2), (unsigned long)((moo_oop_liword_t)oop)->slot[--i]); + outbfmt (moo, mask, "%0*lX", (int)(MOO_SIZEOF(moo_liw_t) * 2), (unsigned long)((moo_oop_liword_t)oop)->slot[--i]); } } else if (c == moo->_large_positive_integer) { moo_oow_t i; - moo_logbfmt (moo, mask, "16r"); + outbfmt (moo, mask, "16r"); for (i = MOO_OBJ_GET_SIZE(oop); i > 0;) { - moo_logbfmt (moo, mask, "%0*lX", (int)(MOO_SIZEOF(moo_liw_t) * 2), (unsigned long)((moo_oop_liword_t)oop)->slot[--i]); + outbfmt (moo, mask, "%0*lX", (int)(MOO_SIZEOF(moo_liw_t) * 2), (unsigned long)((moo_oop_liword_t)oop)->slot[--i]); } } else if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_CHAR) { if (c == moo->_symbol) { - moo_logbfmt (moo, mask, "#%.*js", MOO_OBJ_GET_SIZE(oop), ((moo_oop_char_t)oop)->slot); + outbfmt (moo, mask, "#%.*js", MOO_OBJ_GET_SIZE(oop), ((moo_oop_char_t)oop)->slot); } else /*if ((moo_oop_t)c == moo->_string)*/ { @@ -456,7 +458,7 @@ static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) { moo_ooch_t escaped; - moo_logbfmt (moo, mask, "S'"); + outbfmt (moo, mask, "S'"); for (i = 0; i < MOO_OBJ_GET_SIZE(oop); i++) { ch = ((moo_oop_char_t)oop)->slot[i]; @@ -494,74 +496,74 @@ static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) } if (escaped == ch) - moo_logbfmt (moo, mask, "\\x%X", ch); + outbfmt (moo, mask, "\\x%X", ch); else - moo_logbfmt (moo, mask, "\\%jc", escaped); + outbfmt (moo, mask, "\\%jc", escaped); } else { - moo_logbfmt (moo, mask, "%jc", ch); + outbfmt (moo, mask, "%jc", ch); } } - moo_logbfmt (moo, mask, "'"); + outbfmt (moo, mask, "'"); } else { - moo_logbfmt (moo, mask, "'%.*js'", MOO_OBJ_GET_SIZE(oop), ((moo_oop_char_t)oop)->slot); + outbfmt (moo, mask, "'%.*js'", MOO_OBJ_GET_SIZE(oop), ((moo_oop_char_t)oop)->slot); } } } else if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_BYTE) { - moo_logbfmt (moo, mask, "#["); + outbfmt (moo, mask, "#["); for (i = 0; i < MOO_OBJ_GET_SIZE(oop); i++) { - moo_logbfmt (moo, mask, " %d", ((moo_oop_byte_t)oop)->slot[i]); + outbfmt (moo, mask, " %d", ((moo_oop_byte_t)oop)->slot[i]); } - moo_logbfmt (moo, mask, "]"); + outbfmt (moo, mask, "]"); } else if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_HALFWORD) { - moo_logbfmt (moo, mask, "#[["); /* TODO: fix this symbol/notation */ + outbfmt (moo, mask, "#[["); /* TODO: fix this symbol/notation */ for (i = 0; i < MOO_OBJ_GET_SIZE(oop); i++) { - moo_logbfmt (moo, mask, " %zX", (moo_oow_t)((moo_oop_halfword_t)oop)->slot[i]); + outbfmt (moo, mask, " %zX", (moo_oow_t)((moo_oop_halfword_t)oop)->slot[i]); } - moo_logbfmt (moo, mask, "]]"); + outbfmt (moo, mask, "]]"); } else if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_WORD) { - moo_logbfmt (moo, mask, "#[[["); /* TODO: fix this symbol/notation */ + outbfmt (moo, mask, "#[[["); /* TODO: fix this symbol/notation */ for (i = 0; i < MOO_OBJ_GET_SIZE(oop); i++) { - moo_logbfmt (moo, mask, " %zX", ((moo_oop_word_t)oop)->slot[i]); + outbfmt (moo, mask, " %zX", ((moo_oop_word_t)oop)->slot[i]); } - moo_logbfmt (moo, mask, "]]]"); + outbfmt (moo, mask, "]]]"); } else if (c == moo->_array) { - moo_logbfmt (moo, mask, "#("); + outbfmt (moo, mask, "#("); for (i = 0; i < MOO_OBJ_GET_SIZE(oop); i++) { - moo_logbfmt (moo, mask, " "); - print_object (moo, mask, ((moo_oop_oop_t)oop)->slot[i]); + outbfmt (moo, mask, " "); + print_object (moo, mask, ((moo_oop_oop_t)oop)->slot[i], outbfmt); } - moo_logbfmt (moo, mask, ")"); + outbfmt (moo, mask, ")"); } else if (c == moo->_class) { /* print the class name */ - moo_logbfmt (moo, mask, "%.*js", MOO_OBJ_GET_SIZE(((moo_oop_class_t)oop)->name), ((moo_oop_class_t)oop)->name->slot); + outbfmt (moo, mask, "%.*js", MOO_OBJ_GET_SIZE(((moo_oop_class_t)oop)->name), ((moo_oop_class_t)oop)->name->slot); } else if (c == moo->_association) { - moo_logbfmt (moo, mask, "%O -> %O", ((moo_oop_association_t)oop)->key, ((moo_oop_association_t)oop)->value); + outbfmt (moo, mask, "%O -> %O", ((moo_oop_association_t)oop)->key, ((moo_oop_association_t)oop)->value); } else { - moo_logbfmt (moo, mask, "instance of %.*js(%p)", MOO_OBJ_GET_SIZE(c->name), ((moo_oop_char_t)c->name)->slot, oop); + outbfmt (moo, mask, "instance of %.*js(%p)", MOO_OBJ_GET_SIZE(c->name), ((moo_oop_char_t)c->name)->slot, oop); } } } @@ -574,7 +576,7 @@ static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) #undef fmtchar_t #undef logfmtv #define fmtchar_t moo_bch_t -#define logfmtv moo_logbfmtv +#define logfmtv __logbfmtv #define FMTCHAR_IS_BCH #if defined(MOO_OOCH_IS_BCH) # define FMTCHAR_IS_OOCH @@ -587,13 +589,25 @@ static void print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop) #undef fmtchar_t #undef logfmtv #define fmtchar_t moo_uch_t -#define logfmtv moo_logufmtv +#define logfmtv __logufmtv #define FMTCHAR_IS_UCH #if defined(MOO_OOCH_IS_UCH) # define FMTCHAR_IS_OOCH #endif #include "logfmtv.h" + +static int _logbfmtv (moo_t* moo, const moo_bch_t* fmt, moo_fmtout_t* data, va_list ap) +{ + return __logbfmtv (moo, fmt, data, ap, moo_logbfmt); +} + +static int _logufmtv (moo_t* moo, const moo_uch_t* fmt, moo_fmtout_t* data, va_list ap) +{ + return __logufmtv (moo, fmt, data, ap, moo_logbfmt); +} + + moo_ooi_t moo_logbfmt (moo_t* moo, moo_oow_t mask, const moo_bch_t* fmt, ...) { int x; @@ -605,7 +619,7 @@ moo_ooi_t moo_logbfmt (moo_t* moo, moo_oow_t mask, const moo_bch_t* fmt, ...) fo.putcs = put_oocs; va_start (ap, fmt); - x = moo_logbfmtv (moo, fmt, &fo, ap); + x = _logbfmtv (moo, fmt, &fo, ap); va_end (ap); if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n') @@ -627,7 +641,7 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_oow_t mask, const moo_uch_t* fmt, ...) fo.putcs = put_oocs; va_start (ap, fmt); - x = moo_logufmtv (moo, fmt, &fo, ap); + x = _logufmtv (moo, fmt, &fo, ap); va_end (ap); if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n') @@ -679,6 +693,35 @@ static int put_errcs (moo_t* moo, moo_oow_t mask, const moo_ooch_t* ptr, moo_oow return 1; /* success */ } + +static moo_ooi_t __errbfmtv (moo_t* moo, moo_oow_t mask, const moo_bch_t* fmt, ...); + +static int _errbfmtv (moo_t* moo, const moo_bch_t* fmt, moo_fmtout_t* data, va_list ap) +{ + return __logbfmtv (moo, fmt, data, ap, __errbfmtv); +} + +static int _errufmtv (moo_t* moo, const moo_uch_t* fmt, moo_fmtout_t* data, va_list ap) +{ + return __logufmtv (moo, fmt, data, ap, __errbfmtv); +} + +static moo_ooi_t __errbfmtv (moo_t* moo, moo_oow_t mask, const moo_bch_t* fmt, ...) +{ + va_list ap; + moo_fmtout_t fo; + + fo.mask = 0; /* not used */ + fo.putch = put_errch; + fo.putcs = put_errcs; + + va_start (ap, fmt); + _errbfmtv (moo, fmt, &fo, ap); + va_end (ap); + + return fo.count; +} + void moo_seterrbfmt (moo_t* moo, moo_errnum_t errnum, const moo_bch_t* fmt, ...) { va_list ap; @@ -692,7 +735,7 @@ void moo_seterrbfmt (moo_t* moo, moo_errnum_t errnum, const moo_bch_t* fmt, ...) fo.putcs = put_errcs; va_start (ap, fmt); - moo_logbfmtv (moo, fmt, &fo, ap); + _errbfmtv (moo, fmt, &fo, ap); va_end (ap); } @@ -709,6 +752,6 @@ void moo_seterrufmt (moo_t* moo, moo_errnum_t errnum, const moo_uch_t* fmt, ...) fo.putcs = put_errcs; va_start (ap, fmt); - moo_logufmtv (moo, fmt, &fo, ap); + _errufmtv (moo, fmt, &fo, ap); va_end (ap); } diff --git a/moo/lib/logfmtv.h b/moo/lib/logfmtv.h index 9daf7fc..a42cb3b 100644 --- a/moo/lib/logfmtv.h +++ b/moo/lib/logfmtv.h @@ -85,7 +85,7 @@ data->count += len; \ } while (0) -int logfmtv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_t* data, va_list ap) +static int logfmtv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_t* data, va_list ap, outbfmt_t outbfmt) { const fmtchar_t* percent; #if defined(FMTCHAR_IS_OOCH) @@ -549,7 +549,7 @@ reswitch: } case 'O': /* object - ignore precision, width, adjustment */ - print_object (moo, data->mask, va_arg (ap, moo_oop_t)); + print_object (moo, data->mask, va_arg (ap, moo_oop_t), outbfmt); break; #if 0 diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 2243c3a..00302f5 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -709,7 +709,7 @@ struct moo_context_t }; -#define MOO_PROCESS_NAMED_INSTVARS 8 +#define MOO_PROCESS_NAMED_INSTVARS 9 typedef struct moo_process_t moo_process_t; typedef struct moo_process_t* moo_oop_process_t; @@ -731,6 +731,7 @@ struct moo_process_t moo_oop_semaphore_t sem; moo_oop_t perr; /* last error set by a primitive function */ + moo_oop_t perrmsg; /* == variable indexed part == */ moo_oop_t slot[1]; /* process stack */