Example #1
0
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 );
	}
}
Example #2
0
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;
	}
}
Example #3
0
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 );
}
Example #4
0
void DaoStream_WriteLocalString( DaoStream *self, DString *str )
{
	str = DString_Copy( str );
	DString_ToLocal( str );
	DaoStream_WriteString( self, str );
	DString_Delete( str );
}
Example #5
0
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 );
}
Example #6
0
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 );
	}
}
Example #7
0
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 );
}
Example #8
0
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 );
	}
}
Example #9
0
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 );
	}
}
Example #10
0
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 );
}
Example #11
0
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 );
}
Example #12
0
/*
// 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 );
}
Example #13
0
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 );
}
Example #14
0
/*
// 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 );
}