void inspect_internal( VMachine *vm, const Item *elem, int32 level, int32 maxLevel, int32 maxSize, Item* i_stream, bool add, bool addline ) { uint32 count; int32 i; Stream *stream = i_stream != 0 ? dyncast<Stream*>(i_stream->asObjectSafe()->getFalconData()) : vm->stdErr(); // return if we reached the maximum level. if ( maxLevel >= 0 && level > maxLevel ) { stream->writeString( "..." ); if ( addline ) stream->writeString( "\n" ); return; } if ( stream == 0 ) { stream = vm->stdOut(); if ( stream == 0 ) return; } if ( add ) for ( i = 0; i < level*3; i ++ ) { stream->put( 0x20 ); // space } if ( elem == 0 ) { stream->writeString( "Nothing" ); if ( addline ) stream->writeString( "\n" ); return; } String temp; switch( elem->type() ) { case FLC_ITEM_NIL: stream->writeString( "Nil" ); break; case FLC_ITEM_UNB: stream->writeString( "_" ); break; case FLC_ITEM_BOOL: stream->writeString( elem->asBoolean() ? "true" : "false" ); break; case FLC_ITEM_INT: temp.writeNumber( elem->asInteger() ); stream->writeString( "int(" ); stream->writeString( temp ); stream->writeString( ")" ); break; case FLC_ITEM_NUM: temp.writeNumber( elem->asNumeric(), "%g" ); stream->writeString( "num(" ); stream->writeString( temp ); stream->writeString( ")" ); break; case FLC_ITEM_RANGE: elem->toString(temp); stream->writeString( temp ); break; case FLC_ITEM_STRING: stream->writeString( "\"" ); if ( maxSize < 0 || elem->asString()->length() < (uint32) maxSize ) { stream->writeString( *elem->asString() ); stream->writeString( "\"" ); } else { stream->writeString( elem->asString()->subString(0, maxSize ) ); stream->writeString( " ... \"" ); } break; case FLC_ITEM_LBIND: stream->writeString( "&" ); stream->writeString( *elem->asLBind() ); break; case FLC_ITEM_MEMBUF: { MemBuf *mb = elem->asMemBuf(); temp = "MemBuf("; temp.writeNumber( (int64) mb->length() ); temp += ","; temp.writeNumber( (int64) mb->wordSize() ); temp += ")"; if ( maxSize == 0 ) stream->writeString( temp ); else { temp += " [\n"; String fmt; int limit = 0; switch ( mb->wordSize() ) { case 1: fmt = "%02" LLFMT "X"; limit = 24; break; case 2: fmt = "%04" LLFMT "X"; limit = 12; break; case 3: fmt = "%06" LLFMT "X"; limit = 9; break; case 4: fmt = "%08" LLFMT "X"; limit = 6; break; } int written = 0; uint32 max = maxSize < 0 || mb->length() < (uint32) maxSize ? mb->length() : (uint32) maxSize; for( count = 0; count < max; count++ ) { temp.writeNumber( (int64) mb->get( count ), fmt ); temp += " "; written ++; if ( written == limit ) { temp += "\n"; written = 0; } stream->writeString( temp ); temp = ""; } if ( count == (uint32) maxSize ) stream->writeString( " ... " ); stream->writeString( "]" ); } } break; case FLC_ITEM_ARRAY: { CoreArray *arr = elem->asArray(); temp = "Array["; temp.writeNumber( (int64) arr->length() ); temp += "]"; stream->writeString( temp ); if ( level == maxLevel ) { stream->writeString( "{...}" ); break; } stream->writeString( "{\n" ); for( count = 0; count < arr->length(); count++ ) { inspect_internal( vm, & ((*arr)[count]), level + 1, maxLevel, maxSize, i_stream, true, true ); } for ( i = 0; i < level; i ++ ) { stream->writeString( " " ); } stream->writeString( "}" ); } break; case FLC_ITEM_DICT: { CoreDict *dict = elem->asDict(); temp = "Dict["; temp.writeNumber( (int64) dict->length() ); temp += "]"; stream->writeString( temp ); if ( level == maxLevel ) { stream->writeString( "{...}" ); break; } stream->writeString( "{\n" ); Iterator iter( &dict->items() ); while( iter.hasCurrent() ) { inspect_internal( vm, &iter.getCurrentKey(), level + 1, maxLevel, maxSize, i_stream, true, false ); stream->writeString( " => " ); inspect_internal( vm, &iter.getCurrent(), level + 1, maxLevel, maxSize, i_stream, false, true ); iter.next(); } for ( i = 0; i < level; i ++ ) { stream->writeString(" "); } stream->writeString( "}" ); } break; case FLC_ITEM_OBJECT: { CoreObject *arr = elem->asObjectSafe(); stream->writeString( "Object of class " + arr->generator()->symbol()->name() ); if ( level == maxLevel ) { stream->writeString( "{...}" ); break; } stream->writeString( " {\n" ); const PropertyTable &pt = arr->generator()->properties(); for( count = 0; count < pt.added() ; count++ ) { for ( i = 0; i < (level+1); i ++ ) { stream->writeString(" "); } const String &propName = *pt.getKey( count ); if ( pt.getEntry(count).isWriteOnly() ) { stream->writeString( "(" ); stream->writeString( propName + ")\n" ); } else { stream->writeString( propName + " => " ); Item dummy; arr->getProperty( propName, dummy); inspect_internal( vm, &dummy, level + 1, maxLevel, maxSize, i_stream, false, true ); } } for ( i = 0; i < level; i ++ ) { stream->writeString(" "); } stream->writeString( "}" ); } break; case FLC_ITEM_CLASS: stream->writeString( "Class " + elem->asClass()->symbol()->name() ); break; case FLC_ITEM_METHOD: { temp = "Method "; temp += "->" + elem->asMethodFunc()->name(); stream->writeString( temp ); Item itemp; elem->getMethodItem( itemp ); inspect_internal( vm, &itemp, level + 1, maxLevel, maxSize, i_stream, true, true ); for ( i = 0; i < level; i ++ ) { stream->writeString(" "); } stream->writeString( "}" ); } break; case FLC_ITEM_CLSMETHOD: temp = "Cls.Method 0x"; temp.writeNumberHex( (uint64) elem->asMethodClassOwner() ); temp += "->" + elem->asMethodClass()->symbol()->name(); stream->writeString( temp ); break; case FLC_ITEM_FUNC: { const Symbol *funcSym = elem->asFunction()->symbol(); if ( funcSym->isExtFunc() ) { stream->writeString( "Ext. Function " + funcSym->name() ); } else { stream->writeString( "Function " + funcSym->name() ); FuncDef *def = funcSym->getFuncDef(); uint32 itemId = def->onceItemId(); if ( itemId != FuncDef::NO_STATE ) { if ( elem->asFunction()->liveModule()->globals()[ itemId ].isNil() ) stream->writeString( "{ not called }"); else stream->writeString( "{ called }"); } } } break; case FLC_ITEM_REFERENCE: stream->writeString( "Ref to " ); inspect_internal( vm, elem->dereference(), level + 1, maxLevel, maxSize, i_stream, false, true ); break; default: stream->writeString( "Invalid type"); } if ( addline ) stream->writeString( "\n" ); stream->flush(); }
static void describe_internal( VMachine *vm, String &tgt, const Item *elem, int32 level, int32 maxLevel, int32 maxSize ) { uint32 count; // return if we reached the maximum level. if ( maxLevel >= 0 && level > maxLevel ) { tgt += "..."; return; } switch( elem->type() ) { case FLC_ITEM_NIL: tgt += "Nil"; break; case FLC_ITEM_UNB: tgt += "_"; break; case FLC_ITEM_BOOL: tgt += elem->asBoolean() ? "true" : "false"; break; case FLC_ITEM_INT: tgt.writeNumber( elem->asInteger() ); break; case FLC_ITEM_NUM: tgt.writeNumber( elem->asNumeric(), "%g" ); break; case FLC_ITEM_RANGE: elem->toString(tgt); break; case FLC_ITEM_STRING: tgt += "\""; if ( maxSize < 0 || elem->asString()->length() < (uint32) maxSize ) { tgt += *elem->asString(); tgt += "\""; } else { tgt += elem->asString()->subString(0, maxSize ); tgt += " ... \""; } break; case FLC_ITEM_LBIND: tgt += "&"; tgt += *elem->asLBind(); if (elem->isFutureBind()) { tgt +="|"; describe_internal( vm, tgt, &elem->asFutureBind(), level+1, maxLevel, maxSize ); } break; case FLC_ITEM_MEMBUF: { MemBuf *mb = elem->asMemBuf(); tgt += "MB("; tgt.writeNumber( (int64) mb->length() ); tgt += ","; tgt.writeNumber( (int64) mb->wordSize() ); tgt += ")"; tgt += " ["; String fmt; int limit = 0; switch ( mb->wordSize() ) { case 1: fmt = "%02" LLFMT "X"; limit = 24; break; case 2: fmt = "%04" LLFMT "X"; limit = 12; break; case 3: fmt = "%06" LLFMT "X"; limit = 9; break; case 4: fmt = "%08" LLFMT "X"; limit = 6; break; } uint32 max = maxSize < 0 || mb->length() < (uint32) maxSize ? mb->length() : (uint32) maxSize; for( count = 0; count < max; count++ ) { tgt.writeNumber( (int64) mb->get( count ), fmt ); tgt += " "; } if ( count == (uint32) maxSize ) tgt += " ..."; tgt += "]"; } break; case FLC_ITEM_ARRAY: { CoreArray *arr = elem->asArray(); tgt += "["; if ( level == maxLevel ) { tgt += "...]"; break; } for( count = 0; count < arr->length(); count++ ) { if ( count == 0 ) tgt += " "; describe_internal( vm, tgt, & ((*arr)[count]), level + 1, maxLevel, maxSize ); if ( count + 1 < arr->length() ) tgt += ", "; } tgt +="]"; } break; case FLC_ITEM_DICT: { CoreDict *dict = elem->asDict(); if( dict->isBlessed() ) tgt += "*"; tgt += "["; if ( level == maxLevel ) { tgt += "...=>...]"; break; } if ( dict->length() == 0 ) { tgt += "=>]"; break; } Item key, value; Iterator iter( &dict->items() ); // separate the first loop to be able to add ", " describe_internal( vm, tgt, &iter.getCurrentKey(), level + 1, maxLevel, maxSize ); tgt += " => "; describe_internal( vm, tgt, &iter.getCurrent(), level + 1, maxLevel, maxSize ); iter.next(); while( iter.hasCurrent() ) { tgt += ", "; describe_internal( vm, tgt, &iter.getCurrentKey(), level + 1, maxLevel, maxSize ); tgt += " => "; describe_internal( vm, tgt, &iter.getCurrent(), level + 1, maxLevel, maxSize ); iter.next(); } tgt += "]"; } break; case FLC_ITEM_OBJECT: { CoreObject *arr = elem->asObjectSafe(); tgt += arr->generator()->symbol()->name() + "(){ "; if ( level == maxLevel ) { tgt += "...}"; break; } const PropertyTable &pt = arr->generator()->properties(); for( count = 0; count < pt.added() ; count++ ) { const String &propName = *pt.getKey( count ); // write only? if ( pt.getEntry( count ).isWriteOnly() ) { tgt.A( "(" ).A( propName ).A(")"); } else { Item dummy; arr->getProperty( propName, dummy ); // in describe skip methods. if ( dummy.isFunction() || dummy.isMethod() ) continue; tgt += propName + " = "; describe_internal( vm, tgt, &dummy, level + 1, maxLevel, maxSize ); } if (count+1 < pt.added()) { tgt += ", "; } } tgt += "}"; } break; case FLC_ITEM_CLASS: tgt += "Class " + elem->asClass()->symbol()->name(); break; case FLC_ITEM_METHOD: { tgt += "("; Item itemp; elem->getMethodItem( itemp ); describe_internal( vm, tgt, &itemp, level + 1, maxLevel, maxSize ); tgt += ")."; tgt += elem->asMethodFunc()->name() + "()"; } break; case FLC_ITEM_CLSMETHOD: tgt += "Class "; tgt += elem->asMethodClassOwner()->generator()->symbol()->name(); tgt += "." + elem->asMethodClass()->symbol()->name() + "()"; break; case FLC_ITEM_FUNC: { const Symbol *funcSym = elem->asFunction()->symbol(); tgt += funcSym->name() + "()"; } break; case FLC_ITEM_REFERENCE: tgt += "->"; describe_internal( vm, tgt, elem->dereference(), level + 1, maxLevel, maxSize ); break; default: tgt += "?"; } }
/*# @method parse CmdlineParser @brief Starts command line parsing. @optparam args A specific string array that will be used as arguments to be parsed. @return true if the parsing is complete, false on error. Start the parsing process. If args parameter is not provided, the method gets the content of the @a args global vector defined in the Core module. Returns true if the parsing was complete, and false on error (for example, if some element in the array wasn't a string). */ FALCON_FUNC CmdlineParser_parse( ::Falcon::VMachine *vm ) { CoreObject *self = vm->self().asObject(); Item *i_params = vm->param( 0 ); if ( i_params == 0 ) { // get the parameters from the VM args object i_params = vm->findGlobalItem( "args" ); if ( i_params == 0 || ! i_params->isArray() ) { throw new CodeError( ErrorParam( e_undef_sym ).extra( "args" ).hard() ); } } else if ( ! i_params->isArray() ) { throw new ParamError( ErrorParam( e_inv_params ).extra( "( A )" ) ); } CoreArray *args = i_params->asArray(); // zero request. self->setProperty( "_request", Item((int64) 0) ); self->setProperty( "lastParsed", Item((int64) 0) ); // status. typedef enum { t_none, t_waitingValue, t_allFree } t_states; t_states state = t_none ; String currentOption; Item i_method; Item i_passMM; self->getProperty( "passMinusMinus", i_passMM ); bool passMM = i_passMM.isTrue(); Item _request; String subParam; uint32 i; for ( i = 0; i < args->length(); i++ ) { Item &i_opt = args->at( i ); if ( !i_opt.isString() ) { throw new ParamError( ErrorParam( e_param_type ). extra( vm->moduleString( rtl_cmdp_0 ) ) ); } String &opt = *i_opt.asString(); // if we were expecting a value, we MUST consider ANYTHING as it was a value. if ( state == t_waitingValue ) { self->getProperty( "onValue", i_method ); if ( i_method.methodize( self ) ) { vm->pushParam( new CoreString(currentOption) ); vm->pushParam( i_opt ); vm->callItemAtomic( i_method, 2 ); state = t_none; } else { vm->retval( false ); self->setProperty( "lastParsed", i ); return; } } else if( opt.length() == 0 || (opt.getCharAt( 0 ) != '-' || opt.length() == 1) || state == t_allFree ) { self->getProperty( "onFree", i_method ); if ( i_method.methodize( self ) ) { vm->pushParam( i_opt ); vm->callItemAtomic( i_method, 1 ); } else { vm->retval( false ); self->setProperty( "lastParsed", i ); return; } } else if ( opt == "--" && ! passMM ) { state = t_allFree; continue; // to skip return value. } else { // we have at least one '-', and length > 1 if ( opt.getCharAt( 1 ) == (uint32) '-' ) { self->getProperty( "onOption", i_method ); if ( i_method.methodize( self ) ) { if ( passMM && opt.size() == 2 ) vm->pushParam( i_opt ); else { //Minimal optimization; reuse the same string and memory subParam = opt.subString( 2 ); vm->pushParam( new CoreString( subParam ) ); } vm->callItemAtomic( i_method, 1 ); self->getProperty( "_request", _request ); // value requested? if ( _request.asInteger() == 1 ) { currentOption = subParam; } } else { vm->retval( false ); self->setProperty( "lastParsed", i ); return; } } else { // we have a switch set. for( uint32 chNum = 1; chNum < opt.length(); chNum++ ) { //Minimal optimization; reuse the same string and memory subParam.size( 0 ); subParam.append( opt.getCharAt( chNum ) ); if ( chNum < opt.length() -1 && opt.getCharAt( chNum +1 ) == (uint32) '-' ) { // switch turnoff. self->getProperty( "onSwitchOff", i_method ); if ( i_method.methodize( self ) ) { vm->pushParam( new CoreString(subParam) ); vm->callItemAtomic( i_method, 1 ); } else { vm->retval( false ); self->setProperty( "lastParsed", (int64) i ); return; } chNum++; } else { self->getProperty( "onOption", i_method ); if ( i_method.methodize( self ) ) { vm->pushParam( new CoreString(subParam) ); vm->callItemAtomic( i_method, 1 ); } else { vm->retval( false ); self->setProperty( "lastParsed", (int64) i ); return; } } self->getProperty( "_request", _request ); // value requested? if ( _request.asInteger() == 1 ) { currentOption = subParam; } } } self->getProperty( "_request", _request ); // value requested? if ( _request.asInteger() == 1 ) { state = t_waitingValue; self->setProperty( "_request", Item(0) ); } // or request to terminate? else if ( _request.asInteger() == 2 ) { self->setProperty( "_request", Item(0) ); vm->retval( true ); self->setProperty( "lastParsed", (int64) i ); return; } } } self->setProperty( "lastParsed", (int64) i ); vm->retval( true ); }