Beispiel #1
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;
	}
}
Beispiel #2
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 );
}
Beispiel #3
0
void DaoStream_WriteFloat( DaoStream *self, double val )
{
	const char *format = self->format;
	const char *iconvs = "diouxXcC";
	char buffer[100];
	if( format && strchr( iconvs, format[ strlen(format)-1 ] ) && val ==(long)val ){
		DaoStream_WriteInt( self, (daoint)val );
		return;
	}
	if( format == NULL ) format = "%f";
	if( self->redirect && self->redirect->StdioWrite ){
		DString *mbs = DString_New(1);
		sprintf( buffer, format, val );
		DString_SetMBS( mbs, buffer );
		self->redirect->StdioWrite( self->redirect, mbs );
		DString_Delete( mbs );
	}else if( self->file ){
		fprintf( self->file, format, val );
	}else if( self->attribs & DAO_IO_STRING ){
		sprintf( buffer, format, val );
		DString_AppendMBS( self->streamString, buffer );
	}else{
		printf( format, val );
	}
}
Beispiel #4
0
void DaoStream_WriteFloat( DaoStream *self, double val )
{
	const char *format = self->format;
	const char *iconvs = "diouxXcC";
	char buffer[100];
	int count;
	if( self->Write == NULL ) return;
	if( format && strchr( iconvs, format[ strlen(format)-1 ] ) && val ==(dao_integer)val ){
		DaoStream_WriteInt( self, (dao_integer)val );
		return;
	}
	if( format == NULL ) format = "%f";
	count = snprintf( buffer, sizeof(buffer), format, val );
	self->Write( self, buffer, count );
}
Beispiel #5
0
static void DaoValue_BasicPrint( DaoValue *self, DaoProcess *proc, DaoStream *stream, DMap *cycData )
{
	DaoType *type = DaoNamespace_GetType( proc->activeNamespace, self );
	if( self->type <= DAO_TUPLE )
		DaoStream_WriteMBS( stream, coreTypeNames[ self->type ] );
	else
		DaoStream_WriteMBS( stream, DaoValue_GetTyper( self )->name );
	if( self->type == DAO_NONE ) return;
	if( self->type == DAO_TYPE ){
		DaoStream_WriteMBS( stream, "<" );
		DaoStream_WriteMBS( stream, self->xType.name->mbs );
		DaoStream_WriteMBS( stream, ">" );
	}
	DaoStream_WriteMBS( stream, "_" );
	DaoStream_WriteInt( stream, self->type );
	DaoStream_WriteMBS( stream, "_" );
	DaoStream_WritePointer( stream, self );
	if( self->type <= DAO_TUPLE ) return;
	if( type && self == type->value ) DaoStream_WriteMBS( stream, "[default]" );
}
Beispiel #6
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 );
}
Beispiel #7
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 );
}
Beispiel #8
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 );
}