DaoXmlNode* DaoXmlNode_GetAncestor( DaoXmlNode *self, DString *name, int level ) { DaoXmlNode *node = self; for(; level > 0 && node != NULL; --level) node = node->parent; if( node && DString_EQ( node->name, name ) ) return node; return NULL; }
int DaoXmlParser_ParseNode( DaoXmlParser *self, DaoXmlDOM *dom, DaoXmlNode *node ) { if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; if( self->source >= self->end ) return 1; if( *self->source != '<' ) return 1; self->source += 1; if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; if( DaoXmlParser_ParseIdentifier( self, node->name ) ) return 1; if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; while( self->source < self->end && isalpha( *self->source ) ){ DaoXmlParser_ParseAttribute( self, self->key, self->value ); DMap_Insert( node->attributes, self->key, self->value ); if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; } if( self->source >= self->end ) return 1; if( *self->source == '/' ){ self->source += 1; if( self->source >= self->end ) return 1; if( *self->source != '>' ) return 1; self->source += 1; return 0; } if( *self->source != '>' ) return 1; self->source += 1; if( DaoXmlParser_ParseNodeContent( self, dom, node ) ) return 1; if( DaoXmlParser_ParseChar( self, '<' ) ) return 1; if( DaoXmlParser_ParseChar( self, '/' ) ) return 1; if( DaoXmlParser_ParseIdentifier( self, self->value ) ) return 1; if( DString_EQ( node->name, self->value ) == 0 ) return 1; if( DaoXmlParser_ParseChar( self, '>' ) ) return 1; return 0; }
DaoXmlNode* DaoXmlNode_GetChild( DaoXmlNode *self, DString *name ) { daoint i; for(i=0; i<self->children->size; ++i){ DaoXmlNode *child = (DaoXmlNode*) self->children->items.pVoid[i]; if( DString_EQ( child->name, name ) ) return child; } return NULL; }
DaoXmlNode* DaoXmlNode_GetChildByAttribute( DaoXmlNode *self, DString *key, DString *value ) { daoint i; for(i=0; i<self->children->size; ++i){ DaoXmlNode *child = (DaoXmlNode*) self->children->items.pVoid[i]; DString *att = DaoXmlNode_GetAttribute( child, key ); if( att && DString_EQ( att, value ) ) return child; } return NULL; }
void DaoRoutine_MakeName( DaoRoutine *self, DString *name, int max1, int max2, int max3 ) { DString *hostName = self->routHost ? self->routHost->name : NULL; DaoType *routType = self->routType; int M = (routType->attrib & DAO_TYPE_SELF) != 0; int N = routType->nested->size; int i; DString_Reset( name, 0 ); /* For builtin containers, whose methods may have no routHost set: */ if( hostName == NULL && M ) hostName = routType->nested->items.pType[0]->aux->xType.name; /* // Mixin classes have methods converted from constructors of component classes. // These methods still have the DAO_ROUT_INITOR flag. So checking the names is // the better way to use here. */ if( hostName && ! DString_EQ( self->routName, hostName ) ){ if( hostName->size + self->routName->size < (max1-2) ){ DString_Append( name, hostName ); DString_AppendChars( name, "::" ); DString_Append( name, self->routName ); }else{ DString_PartialAppend( name, hostName, max1/2-1 ); DString_AppendChars( name, "::" ); DString_PartialAppend( name, self->routName, max1/2-1 ); } }else{ DString_PartialAppend( name, self->routName, max1 ); } if( max3 == 0 ){ DString_AppendChars( name, "()" ); return; } DString_AppendChars( name, "( " ); if( N == M+1 ){ DaoType *type = routType->nested->items.pType[M]; DString_PartialAppend( name, type->name, 2*max2 ); }else{ for(i=M; i<N; ++i){ DaoType *type = routType->nested->items.pType[i]; if( i > M ) DString_AppendChars( name, ", " ); if( i < M + max3 ){ DString_PartialAppend( name, type->name, max2 ); }else{ DString_AppendChars( name, "~~" ); break; } } } DString_AppendChars( name, " )" ); }
static int DaoRoutine_GetFieldIndex( DaoRoutine *self, DString *name ) { DString none = DString_WrapMBS( "" ); DaoString str = {DAO_STRING,0,0,0,0,NULL}; DaoString *s = & str; daoint i; if( name == NULL ) name = & none; for(i=0; i<self->routConsts->items.size; ++i){ DaoValue *item = DaoList_GetItem( self->routConsts, i ); DString *field = DaoValue_TryGetString( item ); if( field == NULL ) continue; if( DString_EQ( field, name ) ) return i; } str.data = name; return DaoRoutine_AddConstant( self, (DaoValue*) s ); }
int DArray_MatchAffix( DArray *self, DString *name ) { daoint i, pos; if( self == NULL ) return 0; for(i=0; i<self->size; ++i){ DString tmp, *pat = self->items.pString[i]; daoint pos = DString_FindChar( pat, '~', 0 ); if( pos < 0 ){ if( DString_EQ( pat, name ) ) return 1; continue; } if( pos ){ tmp = *pat; tmp.size = pos; if( DString_Find( name, & tmp, 0 ) != 0 ) continue; } if( pos < pat->size-1 ){ tmp = DString_WrapMBS( pat->mbs + pos + 1 ); if( DString_RFind( name, & tmp, -1 ) != (name->size - 1) ) continue; } return 1; } return 0; }
static int DaoToken_EQ( DaoToken *self, DaoToken *other ) { if( self->name != other->name ) return 0; if( self->name <= DTOK_WCS ) return DString_EQ( & self->string, & other->string ); return 1; }
int DaoParser_ParseMacro( DaoParser *self, int start ) { int rb1, rb2, i = start, N = self->tokens->size; DaoToken **toks = self->tokens->items.pToken; DaoMacro *macro; DString *lang = NULL; DArray *stops; DMap *markers; if( start + 5 >= N ) return -1; if( toks[start+1]->type != DTOK_LCB ){ lang = & toks[start+1]->string; if( toks[start+1]->type != DTOK_IDENTIFIER ){ DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang ); return -1; } if( lang->size == 3 && strcmp( lang->mbs, "dao" ) == 0 ){ DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang ); return -1; } start += 1; } if( toks[start+1]->name != DTOK_LCB ) return -1; self->curLine = toks[start]->line; rb1 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, -1 ); if( rb1 <0 || rb1 +3 >= N ) return -1; if( toks[rb1+1]->name != DKEY_AS || toks[rb1+2]->name != DTOK_LCB ){ DaoParser_Error( self, DAO_CTW_INV_MAC_DEFINE, NULL ); return -1; } rb2 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, rb1 + 1, -1 ); if( rb2 <0 ) return -1; /* for( i=start; i<rb2; i++ ) printf( "%s ", toks[i]->string.mbs ); printf("\n"); */ macro = DaoMacro_New(); if( DaoParser_MakeMacroGroup( self, macro->macroMatch, macro->macroMatch, start+2, rb1 ) ==0 ){ DaoMacro_Delete( macro ); return -1; } if( macro->macroMatch->units->size >0 ){ DMacroUnit *unit = (DMacroUnit*) macro->macroMatch->units->items.pVoid[0]; if( unit->type != DMACRO_TOK ) DaoParser_Error( self, DAO_CTW_INV_MAC_FIRSTOK, & toks[i]->string ); } if( toks[rb1+3]->line != toks[rb1+2]->line ) macro->macroApply->cpos = toks[rb1+3]->cpos; if( DaoParser_MakeMacroGroup( self, macro->macroApply, macro->macroApply, rb1+3, rb2 ) ==0 ){ DaoMacro_Delete( macro ); return -1; } markers = DMap_New(D_STRING,0); for(i=start+2; i<rb1; i++){ if( toks[i]->string.mbs[0] == '$' ){ if( MAP_Find( markers, & toks[i]->string ) != NULL ){ self->curLine = toks[i]->line; DaoParser_Error( self, DAO_CTW_REDEF_MAC_MARKER, & toks[i]->string ); return 0; } MAP_Insert( markers, & toks[i]->string, 0 ); } } DMap_Clear( markers ); i = rb1+3; if( DString_EQ( & toks[start+2]->string, & toks[rb1+3]->string ) ) i ++; while( i < rb2 ){ char ch = toks[i]->string.mbs[0]; if( ch != '$' && ch != '\\' && ch != '\'' ){ if( MAP_Find( markers, & toks[i]->string ) == NULL ){ DArray_Append( macro->keyListApply, & toks[i]->string ); MAP_Insert( markers, & toks[i]->string, 0 ); } } i ++; } stops = DArray_New(D_TOKEN); DMacroGroup_SetStop( macro->macroMatch, stops ); DMacroGroup_FindVariables( macro->macroMatch ); DArray_Clear( stops ); DMacroGroup_SetStop( macro->macroApply, stops ); DaoNamespace_AddMacro( self->nameSpace, lang, & toks[start+2]->string, macro ); DArray_Delete( stops ); DMap_Delete( markers ); return rb2; }
/* assumed to be called before parsing class body */ void DaoClass_DeriveClassData( DaoClass *self ) { DaoType *type; DaoValue *value; DArray *parents, *offsets; DString *mbs; DNode *it, *search; daoint i, k, id, perm, index; mbs = DString_New(1); if( self->clsType->bases == NULL ) self->clsType->bases = DArray_New(D_VALUE); if( self->objType->bases == NULL ) self->objType->bases = DArray_New(D_VALUE); DArray_Clear( self->clsType->bases ); DArray_Clear( self->objType->bases ); for(i=0; i<self->superClass->size; i++){ if( self->superClass->items.pValue[i]->type == DAO_CLASS ){ DaoValue *klass = self->superClass->items.pValue[i]; DArray_Append( self->clsType->bases, klass->xClass.clsType ); DArray_Append( self->objType->bases, klass->xClass.objType ); DString_Assign( mbs, klass->xClass.className ); DString_AppendChar( mbs, '#' ); DString_AppendInteger( mbs, i+1 ); DaoClass_AddConst( self, mbs, klass, DAO_DATA_PRIVATE ); }else if( self->superClass->items.pValue[i]->type == DAO_CTYPE ){ DaoCtype *cdata = (DaoCtype*) self->superClass->items.pValue[i]; DaoTypeKernel *kernel = cdata->ctype->kernel; DMap *values = kernel->values; DMap *methods = kernel->methods; DArray_Append( self->clsType->bases, cdata->ctype ); DArray_Append( self->objType->bases, cdata->cdtype ); if( values == NULL ){ DaoNamespace_SetupValues( kernel->nspace, kernel->typer ); values = kernel->values; } if( methods == NULL ){ DaoNamespace_SetupMethods( kernel->nspace, kernel->typer ); methods = kernel->methods; } DString_Assign( mbs, cdata->ctype->name ); // XXX DaoClass_AddConst( self, mbs, (DaoValue*)cdata, DAO_DATA_PRIVATE ); DString_AppendChar( mbs, '#' ); DString_AppendInteger( mbs, i+1 ); DaoClass_AddConst( self, mbs, (DaoValue*)cdata, DAO_DATA_PRIVATE ); } } parents = DArray_New(0); offsets = DArray_New(0); DaoClass_Parents( self, parents, offsets ); for(i=1; i<parents->size; i++){ DaoClass *klass = parents->items.pClass[i]; DaoCdata *cdata = parents->items.pCdata[i]; if( klass->type == DAO_CLASS ){ if( klass->vtable ){ if( self->vtable == NULL ) self->vtable = DHash_New(0,0); for(it=DMap_First(klass->vtable); it; it=DMap_Next(klass->vtable,it)){ DMap_Insert( self->vtable, it->key.pVoid, it->value.pVoid ); } } /* For class data: */ for( id=0; id<klass->cstDataName->size; id++ ){ DString *name = klass->cstDataName->items.pString[id]; value = klass->constants->items.pConst[ id ]->value; search = MAP_Find( klass->lookupTable, name ); if( search == NULL ) continue; perm = LOOKUP_PM( search->value.pInt ); /* NO deriving private member: */ if( perm <= DAO_DATA_PRIVATE ) continue; if( value->type == DAO_ROUTINE ){ if( DString_EQ( value->xRoutine.routName, klass->className ) ) continue; } search = MAP_Find( self->lookupTable, name ); if( search == NULL && value->type == DAO_ROUTINE && value->xRoutine.overloads ){ /* To skip the private methods: */ DaoClass_AddConst( self, name, (DaoValue*)value, perm ); }else if( search == NULL ){ index = LOOKUP_BIND( DAO_CLASS_CONSTANT, perm, i+1, self->constants->size ); MAP_Insert( self->lookupTable, name, index ); DArray_Append( self->constants, klass->constants->items.pConst[id] ); DArray_Append( self->cstDataName, (void*)name ); if( value->type == DAO_ROUTINE && (value->xRoutine.attribs & DAO_ROUT_VIRTUAL) ){ if( self->vtable == NULL ) self->vtable = DHash_New(0,0); MAP_Insert( self->vtable, value, value ); } }else if( value->type == DAO_ROUTINE && value->xRoutine.overloads ){ DRoutines *routs = value->xRoutine.overloads; for(k=0; k<routs->routines->size; k++){ DaoRoutine *rout = routs->routines->items.pRoutine[k]; /* skip methods not defined in this parent type */ if( rout->routHost != klass->objType ) continue; if( rout->attribs & DAO_ROUT_PRIVATE ) continue; DaoClass_AddConst( self, name, (DaoValue*)rout, perm ); } }else if( value->type == DAO_ROUTINE ){ /* skip methods not defined in this parent type */ if( value->xRoutine.routHost != klass->objType ) continue; if( value->xRoutine.attribs & DAO_ROUT_PRIVATE ) continue; DaoClass_AddConst( self, name, value, perm ); } } /* class global data */ for( id=0; id<klass->glbDataName->size; id ++ ){ DString *name = klass->glbDataName->items.pString[id]; DaoVariable *var = klass->variables->items.pVar[id]; search = MAP_Find( klass->lookupTable, name ); perm = LOOKUP_PM( search->value.pInt ); /* NO deriving private member: */ if( perm <= DAO_DATA_PRIVATE ) continue; search = MAP_Find( self->lookupTable, name ); /* To overide data: */ if( search == NULL ){ index = LOOKUP_BIND( DAO_CLASS_VARIABLE, perm, i+1, self->variables->size ); MAP_Insert( self->lookupTable, name, index ); DArray_Append( self->variables, var ); DArray_Append( self->glbDataName, (void*)name ); } } }else if( cdata->type == DAO_CTYPE ){ DaoCtype *ctypeobj = (DaoCtype*) cdata; DaoTypeKernel *kernel = cdata->ctype->kernel; DaoTypeBase *typer = kernel->typer; DMap *values = kernel->values; DMap *methods = kernel->methods; DNode *it; int j; DaoCdataType_SpecializeMethods( cdata->ctype ); kernel = cdata->ctype->kernel; methods = kernel->methods; if( typer->numItems ){ for(j=0; typer->numItems[j].name!=NULL; j++){ DString name = DString_WrapMBS( typer->numItems[j].name ); it = DMap_Find( values, & name ); if( it && DMap_Find( self->lookupTable, & name ) == NULL ) DaoClass_AddConst( self, it->key.pString, it->value.pValue, DAO_DATA_PUBLIC ); } } for(it=DMap_First( methods ); it; it=DMap_Next( methods, it )){ DaoRoutine *func = it->value.pRoutine; DaoRoutine **funcs = & func; int k, count = 1; if( it->value.pValue->type == DAO_ROUTINE && it->value.pRoutine->overloads ){ DRoutines *routs = it->value.pRoutine->overloads; funcs = routs->routines->items.pRoutine; count = routs->routines->size; } for(k=0; k<count; k++){ DaoRoutine *func = funcs[k]; if( func->routHost != ctypeobj->cdtype ) continue; if( func->attribs & DAO_ROUT_INITOR ) continue; DaoClass_AddConst( self, it->key.pString, (DaoValue*)func, DAO_DATA_PUBLIC ); } } } } DArray_Delete( parents ); DArray_Delete( offsets ); DString_Delete( mbs ); }