static void DaoObject_Print( DaoValue *self0, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { int ec; char buf[50]; DaoObject *self = & self0->xObject; sprintf( buf, "[%p]", self ); if( self0 == self->defClass->objType->value ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycData != NULL && DMap_Find( cycData, self ) != NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycData ) MAP_Insert( cycData, self, self ); DString_SetChars( proc->mbstring, "serialize" ); DaoValue_Clear( & proc->stackValues[0] ); ec = DaoObject_InvokeMethod( self, proc->activeObject, proc, proc->mbstring, NULL,0,1,1 ); if( ec && ec != DAO_ERROR_FIELD_NOTEXIST ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->mbstring->chars, NULL ); }else if( ec == DAO_ERROR_FIELD_NOTEXIST || proc->stackValues[0] == NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); }else{ DaoValue_Print( proc->stackValues[0], proc, stream, cycData ); } }
void DaoProcess_Trace( DaoProcess *self, int depth ) { DaoStream *stream = self->vmSpace->stdioStream; DaoStackFrame *frame = self->topFrame; int k, i = 0; while( frame && frame->routine ){ DaoRoutine *routine = frame->routine; if( depth && ++i > depth ) break; DaoStream_SetColor( stream, "white", "green" ); DaoStream_WriteString( stream, routine->routName ); DaoStream_WriteChars( stream, "()" ); DaoStream_SetColor( stream, NULL, NULL ); DaoStream_WriteChars( stream, ": " ); DaoStream_SetColor( stream, "green", NULL ); if( routine->routType ) DaoStream_WriteString( stream, routine->routType->name ); DaoStream_SetColor( stream, NULL, NULL ); if( frame->routine->body ){ k = (i==1) ? (int)( self->activeCode - frame->codes ) : frame->entry; if( k >= 0 && k < frame->routine->body->annotCodes->size ){ DaoStream_WriteChars( stream, ", instruction " ); DaoStream_WriteInt( stream, k ); DaoStream_WriteChars( stream, " at line " ); DaoStream_WriteInt( stream, frame->routine->body->annotCodes->items.pVmc[k]->line ); } } DaoStream_WriteChars( stream, " in " ); DaoStream_WriteString( stream, routine->nameSpace->name ); DaoStream_WriteChars( stream, ";" ); DaoStream_WriteNewLine( stream ); frame = frame->prev; } }
void DaoValue_Print( DaoValue *self, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { DString *name; DaoTypeBase *typer; DMap *cd = cycData; if( self == NULL ){ DaoStream_WriteMBS( stream, "none[0x0]" ); return; } if( cycData == NULL ) cycData = DMap_New(0,0); switch( self->type ){ case DAO_INTEGER : DaoStream_WriteInt( stream, self->xInteger.value ); break; case DAO_FLOAT : DaoStream_WriteFloat( stream, self->xFloat.value ); break; case DAO_DOUBLE : DaoStream_WriteFloat( stream, self->xDouble.value ); break; case DAO_COMPLEX : DaoStream_WriteFloat( stream, self->xComplex.value.real ); if( self->xComplex.value.imag >= -0.0 ) DaoStream_WriteMBS( stream, "+" ); DaoStream_WriteFloat( stream, self->xComplex.value.imag ); DaoStream_WriteMBS( stream, "C" ); break; #ifdef DAO_WITH_LONGINT case DAO_LONG : name = DString_New(1); DLong_Print( self->xLong.value, name ); DaoStream_WriteString( stream, name ); DString_Delete( name ); break; #endif case DAO_ENUM : name = DString_New(1); DaoEnum_MakeName( & self->xEnum, name ); DaoStream_WriteMBS( stream, name->mbs ); DaoStream_WriteMBS( stream, "(" ); DaoStream_WriteInt( stream, self->xEnum.value ); DaoStream_WriteMBS( stream, ")" ); DString_Delete( name ); break; case DAO_STRING : DaoStream_WriteString( stream, self->xString.data ); break; default : typer = DaoVmSpace_GetTyper( self->type ); if( typer->core->Print == DaoValue_Print ){ DaoValue_BasicPrint( self, proc, stream, cycData ); break; } typer->core->Print( self, proc, stream, cycData ); break; } if( cycData != cd ) DMap_Delete( cycData ); }
void DaoStream_WriteLocalString( DaoStream *self, DString *str ) { str = DString_Copy( str ); DString_ToLocal( str ); DaoStream_WriteString( self, str ); DString_Delete( str ); }
void DaoObject_Print( DaoValue *self, DaoStream *stream, DMap *cycmap, DaoProcess *proc ) { int ec = 0; char buf[50]; DMap *inmap = cycmap; DaoObject *object = (DaoObject*) self; DaoValue *params[2]; DaoRoutine *meth; sprintf( buf, "[%p]", object ); if( self == object->defClass->objType->value ){ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycmap != NULL && DMap_Find( cycmap, object ) != NULL ){ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycmap == NULL ) cycmap = DHash_New(0,0); DMap_Insert( cycmap, self, self ); DaoValue_Clear( & proc->stackValues[0] ); params[0] = (DaoValue*) dao_type_string; params[1] = (DaoValue*) stream; meth = DaoClass_FindMethod( object->defClass, "(string)", NULL ); if( meth ){ ec = DaoProcess_Call( proc, meth, self, params, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self, params, 1 ); }else{ meth = DaoClass_FindMethod( object->defClass, "serialize", NULL ); if( meth ) ec = DaoProcess_Call( proc, meth, self, NULL, 0 ); } if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], stream, cycmap, proc ); }else{ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, buf ); } if( inmap == NULL ) DMap_Delete( cycmap ); }
static void DaoObject_Print( DaoValue *self0, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { int ec = 0; char buf[50]; DaoObject *self = & self0->xObject; DaoValue *params[2]; DaoRoutine *meth; sprintf( buf, "[%p]", self ); if( self0 == self->defClass->objType->value ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycData != NULL && DMap_Find( cycData, self ) != NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycData ) MAP_Insert( cycData, self, self ); DaoValue_Clear( & proc->stackValues[0] ); params[0] = (DaoValue*) dao_type_string; params[1] = (DaoValue*) stream; meth = DaoClass_FindMethod( self->defClass, "(string)", NULL ); if( meth ){ ec = DaoProcess_Call( proc, meth, self0, params, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self0, params, 1 ); }else{ meth = DaoClass_FindMethod( self->defClass, "serialize", NULL ); if( meth ) ec = DaoProcess_Call( proc, meth, self0, NULL, 0 ); } if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], proc, stream, cycData ); }else{ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); } }
static void DaoCinValue_Print( DaoValue *self, DaoStream *stream, DMap *cycmap, DaoProcess *proc ) { int ec = 0; char buf[50]; DaoRoutine *meth; DaoValue *args[2]; DaoType *type = self->xCinValue.cintype->vatype; DMap *inmap = cycmap; if( cycmap != NULL && DMap_Find( cycmap, self ) != NULL ){ sprintf( buf, "[%p]", self ); DaoStream_WriteString( stream, type->name ); DaoStream_WriteChars( stream, buf ); return; } if( cycmap == NULL ) cycmap = DHash_New(0,0); DMap_Insert( cycmap, self, self ); args[0] = (DaoValue*) proc->vmSpace->typeString; args[1] = (DaoValue*) stream; meth = DaoType_FindFunctionChars( type, "(string)" ); if( meth ){ ec = DaoProcess_Call( proc, meth, self, args, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self, args, 1 ); }else{ meth = DaoType_FindFunctionChars( type, "serialize" ); if( meth ) ec = DaoProcess_Call( proc, meth, self, NULL, 0 ); } if( meth == NULL ){ DaoValue_Print( self->xCinValue.value, stream, cycmap, proc ); }else if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], stream, cycmap, proc ); }else{ DaoStream_WriteString( stream, type->name ); DaoStream_WriteChars( stream, buf ); } if( inmap == NULL ) DMap_Delete( cycmap ); }
void DaoClass_PrintCode( DaoClass *self, DaoStream *stream ) { daoint i; DaoStream_WriteMBS( stream, "class " ); DaoStream_WriteString( stream, self->className ); DaoStream_WriteMBS( stream, ":\n" ); for(i=0; i<self->constants->size; ++i){ DaoValue *cst = self->constants->items.pConst[i]->value; if( cst->type != DAO_ROUTINE || cst->xRoutine.body == NULL ) continue; if( cst->xRoutine.routHost != self->objType ) continue; DaoRoutine_PrintCode( & cst->xRoutine, stream ); } }
void DaoClass_PrintCode( DaoClass *self, DaoStream *stream ) { DNode *node = DMap_First( self->lookupTable ); DaoStream_WriteMBS( stream, "class " ); DaoStream_WriteString( stream, self->className ); DaoStream_WriteMBS( stream, ":\n" ); for( ; node != NULL; node = DMap_Next( self->lookupTable, node ) ){ DaoValue *val; if( LOOKUP_ST( node->value.pInt ) != DAO_CLASS_CONSTANT ) continue; val = self->constants->items.pConst[ LOOKUP_ID( node->value.pInt ) ]->value; if( val->type == DAO_ROUTINE && val->xRoutine.body ) DaoRoutine_PrintCode( & val->xRoutine, stream ); } }
void DaoSTD_Debug( DaoProcess *proc, DaoValue *p[], int N ) { DaoDebugger *debugger = proc->vmSpace->debugger; DaoStream *stream = proc->vmSpace->stdioStream; DString *input; if( ! (proc->vmSpace->options & DAO_OPTION_DEBUG ) ) return; input = DString_New(); if( N > 0 && DaoValue_CastCstruct( p[0], dao_type_stream ) ){ stream = (DaoStream*)p[0]; p ++; N --; } if( N > 0 ){ Dao_AboutVars( proc, p, N, input ); DaoStream_WriteString( stream, input ); DaoStream_WriteChars( stream, "\n" ); DString_Delete( input ); return; } DString_Delete( input ); if( debugger && debugger->Debug ) debugger->Debug( debugger, proc, stream ); }
void STD_Debug( DaoProcess *proc, DaoValue *p[], int N ) { DaoUserHandler *handler = proc->vmSpace->userHandler; DaoRoutine *routine = proc->activeRoutine; DaoStream *stream = proc->vmSpace->stdioStream; DString *input; DArray *tokens; DMap *cycData; char *chs, *cmd; int i; if( ! (proc->vmSpace->options & DAO_OPTION_DEBUG ) ) return; input = DString_New(1); if( N > 0 && DaoValue_CastCstruct( p[0], dao_type_stream ) ){ stream = (DaoStream*)p[0]; p ++; N --; } if( N > 0 ){ Dao_AboutVars( proc->activeNamespace, p, N, input ); DaoStream_WriteString( stream, input ); DaoStream_WriteMBS( stream, "\n" ); DString_Delete( input ); return; } if( handler && handler->StdlibDebug ){ handler->StdlibDebug( handler, proc ); return; } tokens = DArray_New(D_STRING); cycData = DMap_New(0,0); while(1){ if( proc->vmSpace->ReadLine ){ chs = proc->vmSpace->ReadLine( "(debug) " ); if( chs ){ DString_SetMBS( input, chs ); DString_Trim( input ); if( input->size && proc->vmSpace->AddHistory ) proc->vmSpace->AddHistory( chs ); dao_free( chs ); } }else{ DaoStream_WriteMBS( stream, "(debug) " ); DaoStream_ReadLine( stream, input ); } if( input->size == 0 ) continue; SplitByWhiteSpaces( input->mbs, tokens ); if( tokens->size == 0 ) continue; cmd = tokens->items.pString[0]->mbs; if( strcmp( cmd, "q" ) == 0 || strcmp( cmd, "quit" ) == 0 ){ break; }else if( strcmp( cmd, "k" ) == 0 || strcmp( cmd, "kill" ) == 0 ){ proc->status = DAO_PROCESS_ABORTED; break; }else if( strcmp( cmd, "a" ) == 0 || strcmp( cmd, "about" ) == 0 ){ if( tokens->size > 1 ){ ushort_t reg = (ushort_t)strtod( tokens->items.pString[1]->mbs, 0 ); DaoType *tp = proc->activeTypes[ reg ]; DString_Clear( input ); Dao_AboutVar( proc->activeNamespace, proc->activeValues[reg], input ); DaoStream_WriteMBS( stream, "type: " ); if( tp ) DaoStream_WriteString( stream, tp->name ); else DaoStream_WriteMBS( stream, "?" ); DaoStream_WriteMBS( stream, ", value: " ); DaoStream_WriteString( stream, input ); DaoStream_WriteMBS( stream, "\n" ); } }else if( strcmp( cmd, "g" ) == 0 || strcmp( cmd, "goto" ) == 0 ){ if( tokens->size > 1 ){ int n = atoi( tokens->items.pString[1]->mbs ); int entry = proc->activeCode - proc->activeRoutine->body->vmCodes->data.codes; if( n < 0 ) n = entry - n; if( n >= routine->body->vmCodes->size ) n = routine->body->vmCodes->size -1; proc->topFrame->entry = n; proc->status = DAO_PROCESS_STACKED; return; } }else if( strcmp( cmd, "h" ) == 0 || strcmp( cmd, "help" ) == 0 ){ DaoStream_WriteMBS( stream, help ); }else if( strcmp( cmd, "l" ) == 0 || strcmp( cmd, "list" ) == 0 ){ DString *mbs = DString_New(1); int entry = proc->activeCode - proc->activeRoutine->body->vmCodes->data.codes; int start = entry - 10; int end = entry; if( tokens->size >1 ){ int dn = atoi( tokens->items.pString[1]->mbs ); if( dn < 0 ){ start = entry + dn; }else if( dn > 0 ){ start = entry; end = entry + dn; } } if( start < 0 ) start = 0; if( end >= routine->body->vmCodes->size ) end = routine->body->vmCodes->size - 1; DaoStream_WriteString( stream, routine->routName ); DaoStream_WriteMBS( stream, "(): " ); if( routine->routType ) DaoStream_WriteString( stream, routine->routType->name ); DaoStream_WriteMBS( stream, "\n" ); DaoStream_WriteMBS( stream, daoRoutineCodeHeader ); DaoStream_WriteMBS( stream, sep ); for( i=start; i<=end; i++ ){ DaoRoutine_FormatCode( routine, i, *routine->body->annotCodes->items.pVmc[i], mbs ); DaoStream_WriteString( stream, mbs ); } DString_Delete( mbs ); }else if( strcmp( cmd, "p" ) == 0 || strcmp( cmd, "print" ) == 0 ){ if( tokens->size > 1 ){ ushort_t reg = (ushort_t)atoi( tokens->items.pString[1]->mbs ); DaoValue_Print( proc->activeValues[reg], proc, stream, cycData ); DaoStream_WriteMBS( stream, "\n" ); } }else if( strcmp( cmd, "t" ) == 0 || strcmp( cmd, "trace" ) == 0 ){ int depth = 1; if( tokens->size >1 ) depth = atoi( tokens->items.pString[1]->mbs ); DaoProcess_Trace( proc, depth ); }else{ DaoStream_WriteMBS( stream, "Unknown debugging command.\n" ); } } DString_Delete( input ); DArray_Delete( tokens ); }
/* // C printf format: %[parameter][flags][width][.precision][length]type // // Dao writef format: %[parameter][flags][width][.precision]type[color] // // Where 'parameter', 'flags', 'width' and 'precision' will conform to the // C format, but 'type' can only be: // c, d, i, o, u, x/X : for integer; // e/E, f/F, g/G : for float and double; // s : for string; // p : for any type, write address; // a : automatic, for any type, write in the default format; // Namely the standard ones exception 'n', and plus 'a'. // // Optional 'color' format will be in form of: [foreground:background], [foreground] // or [:background]. The supported color name format will depend on the color printing // handle. Mininum requirement is the support of the following 8 color names: // black, white, red, green, blue, yellow, magenta, cyan. */ static void DaoIO_Writef0( DaoStream *self, DaoProcess *proc, DaoValue *p[], int N ) { DaoValue *value; DMap *cycData; DString *format, *fmt2; DString *fgcolor, *bgcolor; const char *convs = "aspcdiouxXfFeEgG"; char F, *s, *end, *fg, *bg, *fmt, message[100]; int k, id = 1; if( (self->attribs & (DAO_IO_FILE | DAO_IO_PIPE)) && self->file == NULL ){ DaoProcess_RaiseException( proc, DAO_ERROR, "stream is not open!" ); return; } cycData = DMap_New(0,0); fmt2 = DString_New(1); fgcolor = DString_New(1); bgcolor = DString_New(1); format = DString_Copy( p[0]->xString.data ); DString_ToMBS( format ); s = format->mbs; end = s + format->size; for(; s<end; s++){ k = 0; if( *s =='%' ){ fmt = s; s += 1; if( *s =='%' || *s == '[' ){ DaoStream_WriteChar( self, *s ); continue; } if( isdigit( *s ) && (*s > '0') ){ while( isdigit( *s ) ) s += 1; if( *s == '$' ){ /* parameter: number$ */ *s = '\0'; k = strtol( fmt + 1, NULL, 10 ); if( k == 0 || k >= N ){ DaoProcess_RaiseException( proc, DAO_WARNING, "invalid parameter number" ); } *s = '%'; fmt = s ++; } } /* flags: */ while( *s == '+' || *s == '-' || *s == '#' || *s == '0' || *s == ' ' ) s += 1; while( isdigit( *s ) ) s += 1; /* width; */ if( *s == '.' ){ /* precision: */ s += 1; while( isdigit( *s ) ) s += 1; } DString_SetDataMBS( fmt2, fmt, s - fmt + 1 ); if( strchr( convs, *s ) == NULL ){ DaoProcess_RaiseException( proc, DAO_WARNING, "invalid format conversion" ); continue; } F = *s; s += 1; fg = bg = NULL; if( *s == '[' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; DString_SetDataMBS( fgcolor, fmt, s - fmt ); if( fgcolor->size ) fg = fgcolor->mbs; if( *s == ':' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; DString_SetDataMBS( bgcolor, fmt, s - fmt ); if( bgcolor->size ) bg = bgcolor->mbs; } if( *s != ']' ) DaoProcess_RaiseException( proc, DAO_WARNING, "invalid color format" ); }else{ s -= 1; } if( k == 0 ) k = id; value = p[k]; id += 1; if( fg || bg ) DaoStream_SetColor( self, fg, bg ); self->format = fmt2->mbs; if( value == NULL ){ if( F == 'p' ){ DaoStream_WriteMBS( self, "0x0" ); }else{ DaoProcess_RaiseException( proc, DAO_WARNING, "null parameter" ); } } self->format = fmt2->mbs; if( F == 'c' || F == 'd' || F == 'i' || F == 'o' || F == 'x' || F == 'X' ){ if( sizeof(daoint) != 4 ) DString_InsertChar( fmt2, DAO_INT_FORMAT[0], fmt2->size-1 ); self->format = fmt2->mbs; if( value->type == DAO_INTEGER ){ DaoStream_WriteInt( self, value->xInteger.value ); }else{ goto WrongParameter; } }else if( toupper( F ) == 'E' || toupper( F ) == 'F' || toupper( F ) == 'G' ){ if( value->type == DAO_FLOAT ){ DaoStream_WriteFloat( self, value->xFloat.value ); }else if( value->type == DAO_DOUBLE ){ DaoStream_WriteFloat( self, value->xDouble.value ); }else{ goto WrongParameter; } }else if( F == 's' && value->type == DAO_STRING ){ DaoStream_WriteString( self, value->xString.data ); }else if( F == 'p' ){ DaoStream_WritePointer( self, value ); }else if( F == 'a' ){ self->format = NULL; DaoValue_Print( value, proc, self, cycData ); }else{ goto WrongParameter; } self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); continue; WrongParameter: self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); sprintf( message, "%i-th parameter has wrong type for format \"%s\"!", k, fmt2->mbs ); DaoProcess_RaiseException( proc, DAO_WARNING, message ); }else{ DaoStream_WriteChar( self, *s ); } } DString_Delete( fgcolor ); DString_Delete( bgcolor ); DString_Delete( format ); DString_Delete( fmt2 ); DMap_Delete( cycData ); }
static void FRAME_PRINT( DaoProcess *proc, DaoValue *p[], int n ) { DaoxDataFrame *self = (DaoxDataFrame*) p[0]; DaoxDataFrame *original = self->original; DaoStream *stream = proc->stdioStream; DaoStream *sstream = DaoStream_New(); DaoValue valueBuffer, *nulls[3] = {NULL,NULL,NULL}; DVector *rlabwidth = DVector_New( sizeof(int) ); DVector *clabwidth = DVector_New( sizeof(int) ); DVector *decimals = DVector_New( sizeof(int) ); DVector *scifmts = DVector_New( sizeof(int) ); DVector *aligns = DVector_New( sizeof(int) ); DString *label = DString_New(1); daoint d, g, i, j, k, s, N, M, K, J = 1; int idwidth, maxwidth = 16, maxdec = 3; char idfmt[16]; char fmt[16]; char buf[512]; sstream->attribs |= DAO_IO_STRING; memset( &valueBuffer, 0, sizeof(DaoValue) ); if( stream == NULL ) stream = proc->vmSpace->stdioStream; if( self->original == NULL ){ DaoxDataFrame_PrepareSlices( self ); DaoDataFrame_MakeSlice( self, proc, nulls, 3, self->slices ); original = self; } N = self->slices->items.pVector[0]->data.daoints[1]; M = self->slices->items.pVector[1]->data.daoints[1]; K = self->slices->items.pVector[2]->data.daoints[1]; DString_Reset( label, 10 + 4*sizeof(void*) + log10(1+N+M+K) ); sprintf( label->mbs, "\nDataFrame[%p]", self ); DaoStream_WriteMBS( stream, label->mbs ); if( original != self ){ sprintf( label->mbs, " (Slices from DataFrame[%p])", original ); DaoStream_WriteMBS( stream, label->mbs ); } sprintf( label->mbs, "\nDimensions: Rows=%" DAO_INT_FORMAT ";", N ); DaoStream_WriteMBS( stream, label->mbs ); sprintf( label->mbs, " Cols=%" DAO_INT_FORMAT ";", M ); DaoStream_WriteMBS( stream, label->mbs ); sprintf( label->mbs, " Deps=%" DAO_INT_FORMAT ";\n", K ); DaoStream_WriteMBS( stream, label->mbs ); idwidth = 1 + (int)log10(N+1); for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); int width = 1 + (int)log10(ii+1); if( width > idwidth ) idwidth = width; } sprintf( idfmt, "%%%i%s:", idwidth, DAO_INT_FORMAT ); if( M == 1 ){ maxwidth = 64; maxdec = 24; }else if( M == 2 ){ maxwidth = 40; maxdec = 12; }else if( M <= 4 ){ maxwidth = 24; maxdec = 6; } for(g=0; g<original->labels[DAOX_DF_ROW]->size; ++g){ int width = 0; for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); DaoxDataFrame_GetLabel( original, DAOX_DF_ROW, g, ii, label ); if( label->size > width ) width = label->size; if( width > maxwidth ) break; } if( width > maxwidth ) width = maxwidth; DVector_PushInt( rlabwidth, width ); } for(j=0; j<M; ++j){ int w, datatype, max = 0, min = 0, dec = 0; daoint width, jj = DaoSlice_GetIndex( self->slices->items.pVector[2], j ); DaoxDataColumn *col = (DaoxDataColumn*) original->columns->items.pVoid[jj]; DVector *cells = col->cells; datatype = DaoType_GetDataType( col->type ); width = DaoxDataColumn_GetPrintWidth( col, 16 ); for(i=0; i<N && i<1000; ++i){ daoint v, ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); complex16 com; switch( datatype ){ case DAO_INTEGER : v = cells->data.daoints[ii]; w = log10( fabs(v) + 1E-32 ) + (v < 0); if( w > max ) max = w; break; case DAO_FLOAT : CheckPrintWidth( cells->data.floats[ii], & max, & min, & dec ); break; case DAO_DOUBLE : CheckPrintWidth( cells->data.doubles[ii], & max, & min, & dec ); break; case DAO_COMPLEX : com = cells->data.complexes[ii]; CheckPrintWidth( com.real, & max, & min, & dec ); CheckPrintWidth( com.imag, & max, & min, & dec ); break; case DAO_STRING : if( cells->data.strings[i].size > max ) max = cells->data.strings[i].size; break; default : break; } } if( dec > maxdec ) dec = maxdec; if( col->type->tid == DAO_COMPLEX ){ max *= 2; min *= 2; } if( datatype == 0 ){ width = maxwidth; DVector_PushInt( aligns, 1 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, 0 ); }else if( datatype == DAO_STRING ){ width = max; DVector_PushInt( aligns, 1 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, 0 ); }else if( max >= maxwidth || min <= -dec ){ width = 16; DVector_PushInt( aligns, 0 ); DVector_PushInt( scifmts, 1 ); DVector_PushInt( decimals, dec ); }else{ width = max + dec + 1; if( col->type->tid == DAO_COMPLEX ) width += dec + 6; DVector_PushInt( aligns, 0 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, dec ); } for(g=0; g<original->labels[DAOX_DF_COL]->size; ++g){ DaoxDataFrame_GetLabel( original, DAOX_DF_COL, g, jj, label ); if( label->size > width ) width = label->size; if( width > maxwidth ) break; } if( width > maxwidth ) width = maxwidth; DVector_PushInt( clabwidth, width ); } for(k=0; k<K; ++k){ daoint kk = DaoSlice_GetIndex( self->slices->items.pVector[2], k ); DaoStream_WriteMBS( stream, "Depth: " ); DaoStream_WriteInt( stream, kk ); DaoStream_WriteMBS( stream, ";" ); if( original->labels[DAOX_DF_DEP]->size ) DaoStream_WriteMBS( stream, "\nLabels:" ); for(g=0; g<original->labels[DAOX_DF_DEP]->size; ++g){ DaoxDataFrame_GetLabel( original, DAOX_DF_DEP, g, kk, label ); DaoStream_WriteMBS( stream, " " ); DaoStream_WriteString( stream, label ); DaoStream_WriteMBS( stream, ";" ); } DaoStream_WriteMBS( stream, "\n" ); for(j=0; j<M; j=J){ int width2, width = idwidth+1; for(i=0; i<rlabwidth->size; ++i) width += rlabwidth->data.ints[i] + 1; width += 1; J = j; width2 = width; for(J=j; J<M; ++J){ daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[1], J ); width2 += clabwidth->data.ints[J] + 2; if( width2 > 80 ){ width2 -= clabwidth->data.ints[J] + 2; break; } } if( J == j ) J += 1; sprintf( buf, "from %" DAO_INT_FORMAT " to %" DAO_INT_FORMAT ":\n", j, J-1 ); DaoStream_WriteMBS( stream, j == 0 ? "| Columns " : "> Columns " ); DaoStream_WriteMBS( stream, buf ); for(g=0; g<original->labels[DAOX_DF_COL]->size; ++g){ sprintf( fmt, "%%-%is", width ); sprintf( buf, fmt, j == 0 ? "|" : ">" ); DaoStream_WriteMBS( stream, buf ); for(s=j; s<J; ++s){ daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[1], s ); int width = clabwidth->data.ints[s]; int align = aligns->data.ints[s]; if( align ){ sprintf( fmt, "%%-%is", width ); }else{ sprintf( fmt, "%%%is", width ); } DaoxDataFrame_GetLabel( original, DAOX_DF_COL, g, jj, label ); if( label->size > width ) DString_Reset( label, width ); snprintf( buf, width+1, fmt, label->mbs ); DaoStream_WriteMBS( stream, " " ); DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, "\n" ); } printf( j == 0 ? "|" : ">" ); while( --width2 ) printf( "-" ); DaoStream_WriteMBS( stream, J < M ? ">" : "|" ); DaoStream_WriteMBS( stream, "\n" ); for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); sprintf( buf, idfmt, ii ); DaoStream_WriteMBS( stream, buf ); for(g=0; g<original->labels[DAOX_DF_ROW]->size; ++g){ int width = rlabwidth->data.ints[g]; DaoxDataFrame_GetLabel( original, DAOX_DF_ROW, g, ii, label ); if( label->size > width ) DString_Reset( label, width ); if( g ) DaoStream_WriteMBS( stream, "," ); sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, label->mbs ); DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, ": " ); for(s=j; s<J; ++s){ int scifmt = scifmts->data.ints[s]; int dec = decimals->data.ints[s]; int width = clabwidth->data.ints[s]; daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[2], s ); DaoxDataColumn *col = (DaoxDataColumn*) original->columns->items.pVoid[jj]; DaoValue *value = DaoxDataColumn_GetCell( col, i, & valueBuffer ); DaoStream_WriteMBS( stream, " " ); if( value == NULL ){ sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, " " ); }else if( value->type == DAO_INTEGER ){ sprintf( fmt, "%%%i%s", width, DAO_INT_FORMAT ); snprintf( buf, width+1, fmt, value->xInteger.value ); }else if( value->type == DAO_FLOAT || value->type == DAO_DOUBLE ){ double f = DaoValue_GetDouble( value ); if( scifmt ){ sprintf( fmt, "%%%iE", width ); }else{ sprintf( fmt, "%%%i.%if", width, dec ); } snprintf( buf, width+1, fmt, f ); }else if( value->type == DAO_COMPLEX ){ complex16 com = value->xComplex.value; char s = com.imag>=0 ? '+' : '-'; int w = width/2-2; int d = dec; if( scifmt ){ sprintf( fmt, "(%%%i.3E,%%%i.3E)", w, w ); }else{ sprintf( fmt, "(%%%i.%if,%%%i.%if)", w, d, w, d ); } snprintf( buf, width, fmt, com.real, com.imag ); }else{ DString_Reset( sstream->streamString, 0 ); DaoValue_Print( value, proc, sstream, NULL ); DString_Reset( label, 0 ); DString_Append( label, sstream->streamString ); if( label->size > width ) DString_Reset( label, width ); DString_ChangeMBS( label, "%t", "\\t", 0 ); DString_ChangeMBS( label, "%n", "\\n", 0 ); sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, label->mbs ); } DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, "\n" ); } DaoStream_WriteMBS( stream, "\n" ); } } DaoStream_Delete( sstream ); DVector_Delete( aligns ); DVector_Delete( scifmts ); DVector_Delete( decimals ); DVector_Delete( rlabwidth ); DVector_Delete( clabwidth ); DString_Delete( label ); }
/* // C printf format: %[parameter][flags][width][.precision][length]type // // Dao writef format: %[flags][width][.precision]type[color] // // Where 'flags', 'width' and 'precision' will conform to the C format, // but 'type' can only be: // d, i, o, u, x/X : for integer; // e/E, f/F, g/G : for float and double; // c/C : for character, C for local encoding; // s/S : for string, S for local encoding; // p : for any type, write address; // a : automatic, for any type, write in the default format; // Namely the standard ones except 'n', and plus 'a'. // // Optional 'color' format will be in form of: [foreground:background], [foreground] // or [:background]. The supported color name format will depend on the color printing // handle. Mininum requirement is the support of the following 8 color names: // black, white, red, green, blue, yellow, magenta, cyan. */ static void DaoIO_Writef0( DaoStream *self, DaoProcess *proc, DaoValue *p[], int N ) { DaoValue *value; DString *fmt2; DString *fgcolor = NULL; DString *bgcolor = NULL; DMap *cycmap = NULL; const char *convs = "asSpcCdiouxXfFeEgG"; char F, *s, *end, *fg, *bg, *fmt, message[100]; int i, k, id = 0; if( DaoIO_CheckMode( self, proc, DAO_STREAM_WRITABLE ) == 0 ) return; fmt2 = DString_New(); for(i=0; i<N; i++){ if( p[i]->type > DAO_ARRAY ){ cycmap = DHash_New(0,0); break; } } s = p[0]->xString.value->chars; end = s + p[0]->xString.value->size; for(; s<end; s++){ if( *s != '%' ){ DaoStream_WriteChar( self, *s ); continue; } fmt = s; s += 1; if( *s =='%' || *s == '[' ){ DaoStream_WriteChar( self, *s ); continue; } if( ++id >= N || p[id] == NULL ) goto NullParameter; value = p[id]; /* flags: */ while( *s == '+' || *s == '-' || *s == '#' || *s == '0' || *s == ' ' ) s += 1; while( isdigit( *s ) ) s += 1; /* width; */ if( *s == '.' ){ /* precision: */ s += 1; while( isdigit( *s ) ) s += 1; } DString_SetBytes( fmt2, fmt, s - fmt + 1 ); if( strchr( convs, *s ) == NULL ){ DaoProcess_RaiseWarning( proc, NULL, "invalid format conversion" ); continue; } F = *s; s += 1; fg = bg = NULL; if( *s == '[' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; if( fgcolor == NULL ) fgcolor = DString_New(); DString_SetBytes( fgcolor, fmt, s - fmt ); if( fgcolor->size ) fg = fgcolor->chars; if( *s == ':' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; if( bgcolor == NULL ) bgcolor = DString_New(); DString_SetBytes( bgcolor, fmt, s - fmt ); if( bgcolor->size ) bg = bgcolor->chars; } if( *s != ']' ) goto WrongColor; }else{ s -= 1; } if( fg || bg ){ if( DaoStream_SetColor( self, fg, bg ) == 0 ) goto WrongColor; } self->format = fmt2->chars; if( F == 'c' || F == 'C' ){ if( value->type != DAO_INTEGER ) goto WrongParameter; DString_Reset( fmt2, 0 ); DString_AppendWChar( fmt2, value->xInteger.value ); self->format = "%s"; if( F == 'C' ) DString_ToLocal( fmt2 ); DaoStream_WriteString( self, fmt2 ); }else if( F == 'd' || F == 'i' || F == 'o' || F == 'x' || F == 'X' ){ if( value->type == DAO_NONE || value->type > DAO_FLOAT ) goto WrongParameter; DString_InsertChars( fmt2, "ll", fmt2->size-1, 0, 2 ); self->format = fmt2->chars; DaoStream_WriteInt( self, DaoValue_GetInteger( value ) ); }else if( toupper( F ) == 'E' || toupper( F ) == 'F' || toupper( F ) == 'G' ){ if( value->type == DAO_NONE || value->type > DAO_FLOAT ) goto WrongParameter; DaoStream_WriteFloat( self, DaoValue_GetFloat( value ) ); }else if( F == 's' && value->type == DAO_STRING ){ DaoStream_WriteString( self, value->xString.value ); }else if( F == 'S' && value->type == DAO_STRING ){ DaoStream_WriteLocalString( self, value->xString.value ); }else if( F == 'p' ){ DaoStream_WritePointer( self, value ); }else if( F == 'a' ){ self->format = NULL; if( value->type > DAO_ARRAY ) DMap_Reset( cycmap ); DaoValue_Print( value, self, cycmap, proc ); }else{ goto WrongParameter; } self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); continue; NullParameter: sprintf( message, "%i-th parameter is null!", id ); DaoProcess_RaiseWarning( proc, NULL, message ); continue; WrongColor: sprintf( message, "%i-th parameter has wrong color format!", id ); DaoProcess_RaiseWarning( proc, NULL, message ); continue; WrongParameter: self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); sprintf( message, "%i-th parameter has wrong type for format \"%s\"!", id, fmt2->chars ); DaoProcess_RaiseWarning( proc, NULL, message ); } if( cycmap ) DMap_Delete( cycmap ); if( fgcolor ) DString_Delete( fgcolor ); if( bgcolor ) DString_Delete( bgcolor ); DString_Delete( fmt2 ); }