Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) { Dsymbol *s; //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); if (scope && !symtab) { Scope *sc = scope; sc->mustsemantic++; // If speculatively gagged, ungag now. unsigned oldgag = global.gag; if (global.isSpeculativeGagging()) global.gag = 0; semantic(sc); global.gag = oldgag; sc->mustsemantic--; } if (!members || !symtab) { error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; return NULL; } s = ScopeDsymbol::search(loc, ident, flags); if (!s) { // Search bases classes in depth-first, left to right order for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (*baseclasses)[i]; if (b->base) { if (!b->base->symtab) error("base %s is forward referenced", b->base->ident->toChars()); else { s = b->base->search(loc, ident, flags); if (s == this) // happens if s is nested in this and derives from this s = NULL; else if (s) break; } } } } return s; }
Dsymbol *Nspace::search(const Loc &loc, Identifier *ident, int flags) { //printf("%s::Nspace::search('%s')\n", toChars(), ident->toChars()); if (_scope && !symtab) semantic(_scope); if (!members || !symtab) // opaque or semantic() is not yet called { error("is forward referenced when looking for '%s'", ident->toChars()); return NULL; } return ScopeDsymbol::search(loc, ident, flags); }
Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) { //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); if (scope && !symtab) semantic(scope); if (!members || !symtab) // opaque or semantic() is not yet called { error("is forward referenced when looking for '%s'", ident->toChars()); return NULL; } return ScopeDsymbol::search(loc, ident, flags); }
Dsymbol *AliasDeclaration::toAlias() { //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); assert(this != aliassym); //static int count; if (++count == 75) exit(0); //*(char*)0=0; if (inSemantic) { error("recursive alias declaration"); aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL); type = Type::terror; } else if (!aliassym && scope) semantic(scope); Dsymbol *s = aliassym ? aliassym->toAlias() : this; return s; }
void Nspace::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { //printf("Nspace::setFieldOffset() %s\n", toChars()); if (_scope) // if fwd reference semantic(NULL); // try to resolve it if (members) { for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; //printf("\t%s\n", s->toChars()); s->setFieldOffset(ad, poffset, isunion); } } }
Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) { Dsymbol *s; //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); //if (scope) printf("%s doAncestorsSemantic = %d\n", toChars(), doAncestorsSemantic); if (scope && doAncestorsSemantic == SemanticStart) { // must semantic on base class/interfaces doAncestorsSemantic = SemanticIn; semantic(scope); if (doAncestorsSemantic != SemanticDone) doAncestorsSemantic = SemanticStart; } if (!members || !symtab) // opaque or semantic() is not yet called { error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; return NULL; } s = ScopeDsymbol::search(loc, ident, flags); if (!s) { // Search bases classes in depth-first, left to right order for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (*baseclasses)[i]; if (b->base) { if (!b->base->symtab) error("base %s is forward referenced", b->base->ident->toChars()); else { s = b->base->search(loc, ident, flags); if (s == this) // happens if s is nested in this and derives from this s = NULL; else if (s) break; } } } } return s; }
Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags) { //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars()); if (scope) // Try one last time to resolve this enum semantic(scope); if (!members || !symtab || scope) { error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; return NULL; } Dsymbol *s = ScopeDsymbol::search(loc, ident, flags); return s; }
Initializer *StructInitializer::inferType(Scope *sc, Type *tx) { if (tx && !(tx->ty == Tident && ((TypeIdentifier *)tx)->ident == Id::empty)) { Type *tb = tx->toBasetype(); //printf("si tb = %s => %s\n", tb->toChars(), toChars()); if (tb->ty == Tstruct || tb->ty == Tdelegate || tb->ty == Tpointer && tb->nextOf()->ty == Tfunction) { return semantic(sc, tb, INITnointerpret); } } error(loc, "cannot infer type from struct initializer"); return new ErrorInitializer(); }
Expression *EnumMember::getVarExp(Loc loc, Scope *sc) { semantic(sc); if (errors) return new ErrorExp(); if (!vd) { assert(value); vd = new VarDeclaration(loc, type, ident, new ExpInitializer(loc, value->copy())); vd->storage_class = STCmanifest; vd->semantic(sc); vd->protection = ed->isAnonymous() ? ed->protection : PROTpublic; vd->parent = ed->isAnonymous() ? ed->parent : ed; vd->userAttribDecl = ed->isAnonymous() ? ed->userAttribDecl : NULL; } Expression *e = new VarExp(loc, vd); return e->semantic(sc); }
bool Compiler::compile(Error& error) { error.clear(); error.step = Error::COMPILATION; error.state = Error::ERROR; m_tokenList = MUON_NEW(std::vector<parser::Token>); m_nodeRoot = MUON_NEW(parser::ASTNode); // avoid a macro, and avoid duplicating code auto clearVariable = [&]() { m_loadBuffer.clear(); MUON_DELETE(m_tokenList); MUON_DELETE(m_nodeRoot); }; if (!lexical(error)) { clearVariable(); return false; } if (!syntaxic(error)) { clearVariable(); return false; } if (!semantic(error)) { clearVariable(); return false; } clearVariable(); error.state = Error::SUCCESS; return true; }
Expression *arrayOp(BinExp *e, Scope *sc) { //printf("BinExp::arrayOp() %s\n", toChars()); Type *tb = e->type->toBasetype(); assert(tb->ty == Tarray || tb->ty == Tsarray); Type *tbn = tb->nextOf()->toBasetype(); if (tbn->ty == Tvoid) { e->error("cannot perform array operations on void[] arrays"); return new ErrorExp(); } if (!isArrayOpValid(e)) { e->error("invalid array operation %s (possible missing [])", e->toChars()); return new ErrorExp(); } Expressions *arguments = new Expressions(); /* The expression to generate an array operation for is mangled * into a name to use as the array operation function name. * Mangle in the operands and operators in RPN order, and type. */ OutBuffer buf; buf.writestring("_array"); buildArrayIdent(e, &buf, arguments); buf.writeByte('_'); /* Append deco of array element type */ buf.writestring(e->type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco); char *name = buf.peekString(); Identifier *ident = Identifier::idPool(name); FuncDeclaration **pFd = (FuncDeclaration **)dmd_aaGet(&arrayfuncs, (void *)ident); FuncDeclaration *fd = *pFd; if (!fd) fd = buildArrayOp(ident, e, sc); if (fd && fd->errors) { const char *fmt; if (tbn->ty == Tstruct || tbn->ty == Tclass) fmt = "invalid array operation '%s' because %s doesn't support necessary arithmetic operations"; else if (!tbn->isscalar()) fmt = "invalid array operation '%s' because %s is not a scalar type"; else fmt = "invalid array operation '%s' for element type %s"; e->error(fmt, e->toChars(), tbn->toChars()); return new ErrorExp(); } *pFd = fd; Expression *ev = new VarExp(e->loc, fd); Expression *ec = new CallExp(e->loc, ev, arguments); return semantic(ec, sc); }
Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id) { //printf("EnumDeclaration::getMaxValue()\n"); bool first = true; Expression **pval = (id == Id::max) ? &maxval : &minval; if (inuse) { error(loc, "recursive definition of .%s property", id->toChars()); goto Lerrors; } if (*pval) goto Ldone; if (scope) semantic(scope); if (errors) goto Lerrors; if (semanticRun == PASSinit || !members) { error("is forward referenced looking for .%s", id->toChars()); goto Lerrors; } if (!(memtype && memtype->isintegral())) { error(loc, "has no .%s property because base type %s is not an integral type", id->toChars(), memtype ? memtype->toChars() : ""); goto Lerrors; } for (size_t i = 0; i < members->dim; i++) { EnumMember *em = (*members)[i]->isEnumMember(); if (!em) continue; if (em->errors) goto Lerrors; Expression *e = em->value; if (first) { *pval = e; first = false; } else { /* In order to work successfully with UDTs, * build expressions to do the comparisons, * and let the semantic analyzer and constant * folder give us the result. */ /* Compute: * if (e > maxval) * maxval = e; */ Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval); inuse++; ec = ec->semantic(em->scope); inuse--; ec = ec->ctfeInterpret(); if (ec->toInteger()) *pval = e; } } Ldone: { Expression *e = *pval; if (e->op != TOKerror) { e = e->copy(); e->loc = loc; } return e; } Lerrors: *pval = new ErrorExp(); return *pval; }
Scope *ProtDeclaration::newScope(Scope *sc) { if (pkg_identifiers) semantic(sc); return createNewScope(sc, sc->stc, sc->linkage, this->protection, 1, sc->structalign); }
bool CheckSpecifier::visit(TypeofSpecifierAST *ast) { semantic()->check(ast->expression, _scope); accept(ast->next); return false; }
bool DeclReferencer::Reference(const clang::NamedDecl *D) { if (D->isInvalidDecl()) return true; for (const clang::Decl *DI = D; !isa<clang::TranslationUnitDecl>(DI); DI = cast<clang::Decl>(DI->getDeclContext())) if (auto RD = dyn_cast<clang::CXXRecordDecl>(DI)) if (RD->isLocalClass()) return true; // are local records emitted when emitting a function? if no this is a FIXME if (auto VD = dyn_cast<clang::VarDecl>(D)) if (!VD->isFileVarDecl()) return true; if (auto FD = dyn_cast<clang::FunctionDecl>(D)) { if (!isMapped(D)) return true; if (FD->getBuiltinID() || (FD->isOverloadedOperator() && FD->isImplicit())) return true; if (FD->isExternC()) return true; // FIXME: Clang 3.6 doesn't always map decls to the right source file, // so the path generated by typeQualifiedFor although correct will result in a failed lookup. // This may get fixed by 3.7. } if (Referenced.count(D->getCanonicalDecl())) return true; Referenced.insert(D->getCanonicalDecl()); // Although we try to add all the needed imports during importAll(), sometimes we miss a module so ensure it gets loaded auto im = mapper.AddImplicitImportForDecl(loc, D, true); im->isstatic = true; auto dst = Package::resolve(im->packages, NULL, &im->pkg); if (!dst->lookup(im->id)) { im->semantic(sc); im->semantic2(sc); } ReferenceTemplateArguments(D); auto Func = dyn_cast<clang::FunctionDecl>(D); if (Func && Func->getPrimaryTemplate()) D = cast<clang::NamedDecl>(getCanonicalDecl(getSpecializedDeclOrExplicit(Func))); // HACK FIXME if (Func && Func->isOutOfLine() && Func->getFriendObjectKind() != clang::Decl::FOK_None) { auto Pattern = Func; if (auto MemberFunc = Func->getInstantiatedFromMemberFunction()) Pattern = MemberFunc; if (Pattern->isDependentContext()) return true; } auto e = expmap.fromExpressionDeclRef(loc, const_cast<clang::NamedDecl*>(D), nullptr, TQ_OverOpSkipSpecArg); e = e->semantic(sc); if (Func && Func->getPrimaryTemplate()) { assert(e->op == TOKvar || e->op == TOKtemplate || e->op == TOKimport); Dsymbol *s; if (e->op == TOKvar) s = static_cast<SymbolExp*>(e)->var; else if (e->op == TOKtemplate) s = static_cast<TemplateExp*>(e)->td; else s = static_cast<ScopeExp*>(e)->sds; // if it's a non-template function there's nothing to do, it will be semantic'd along with its declcontext // if it's a template spec we must instantiate the right overload struct DEquals { const clang::Decl* D; Dsymbol *s = nullptr; // return value static int fp(void *param, Dsymbol *s) { if (!isCPP(s)) return 0; auto fd = s->isFuncDeclaration(); auto td = static_cast<cpp::TemplateDeclaration*>( s->isTemplateDeclaration()); DEquals *p = (DEquals *)param; decltype(D) s_D = fd ? getFD(fd) : td->TempOrSpec; if (p->D == getCanonicalDecl(s_D)) { p->s = s; return 1; } return 0; } }; DEquals p; p.D = D; overloadApply(s, &p, &DEquals::fp); assert(p.s && p.s->isTemplateDeclaration()); auto td = static_cast<cpp::TemplateDeclaration*>(p.s->isTemplateDeclaration()); if (td->semanticRun == PASSinit) { assert(td->scope); td->semantic(td->scope); // this must be done here because havetempdecl being set to true it won't be done by findTempDecl() assert(td->semanticRun > PASSinit); } auto tiargs = mapper.fromTemplateArguments(loc, Func->getTemplateSpecializationArgs()); assert(tiargs); SpecValue spec(mapper); getIdentifier(Func, &spec, true); if (spec) tiargs->shift(spec.toTemplateArg(loc)); auto tempinst = new cpp::TemplateInstance(loc, td, tiargs); tempinst->Inst = const_cast<clang::FunctionDecl*>(Func); tempinst->semantictiargsdone = false; // NOTE: the "havetempdecl" ctor of Templateinstance set semantictiargsdone to true... // Time was lost finding this out for the second or third time. td->makeForeignInstance(tempinst); tempinst->semantic(sc); } // Memory usage can skyrocket when using a large library if (im->packages) delete im->packages; delete im; delete e; return true; }
void cgfxVaryingParameter::setupAttributes( cgfxRCPtr<cgfxVertexAttribute>& vertexAttributes, CGprogram program) { // Make sure our parameter name is acceptable is a Maya attribute name MString attrName = fName; int lastDot = attrName.rindex( '.'); if( lastDot >= 0) attrName = attrName.substring( lastDot + 1, attrName.length() - 1); MString semanticName = cgGetParameterSemantic( fParameter); MString semantic(semanticName); cgGetParameterSemantic( fParameter); semantic.toUpperCase(); // Is this varying parameter packed or atomic? CGtype type = cgGetNamedUserType( program, attrName.asChar()); if( type != CG_UNKNOWN_TYPE) { // It's packed: explode the inputs into the structure elements CGcontext context = cgGetProgramContext( program); CGparameter packing = cgCreateParameter( context, type); fVertexStructure = new cgfxVaryingParameterStructure(); fVertexStructure->fLength = 0; fVertexStructure->fSize = 0; CGparameter element = cgGetFirstStructParameter( packing); while( element) { MString elementName = cgGetParameterName( element); int lastDot = elementName.rindex( '.'); if( lastDot >= 0) elementName = elementName.substring( lastDot + 1, elementName.length() - 1); cgfxRCPtr<cgfxVertexAttribute> attr = setupAttribute( elementName, semantic, element, vertexAttributes); fVertexStructure->fElements[ fVertexStructure->fLength].fVertexAttribute = attr; int size = cgGetParameterRows( element) * cgGetParameterColumns( element); CGtype type = cgGetParameterBaseType( element); if( type == CG_FLOAT) size *= sizeof( GLfloat); else if( type == CG_INT) size *= sizeof( GLint); fVertexStructure->fElements[ fVertexStructure->fLength].fSize = size; fVertexStructure->fLength++; fVertexStructure->fSize += size; element = cgGetNextParameter( element); } cgDestroyParameter( packing); } else { // It's atomic - create a single, simple input fVertexAttribute = setupAttribute( attrName, semantic, fParameter, vertexAttributes); } // Now pull apart the semantic string to work out where to bind // this value in open GL (as the automagic binding through cgGL // didn't work so well when this was written) int radix = 1; fGLIndex = 0; unsigned int length = semantic.length(); const char* str = semantic.asChar(); // If sematic is NULL then stop here, bug 327649 if (length == 0) { fGLType = glRegister::kUnknown; return; } for(;;) { char c = str[ length - 1]; if( c < '0' || c > '9') break; fGLIndex += radix * (c - '0'); radix *= 10; --length; } if( semantic.length() != length) semantic = semantic.substring( 0, length - 1); // Determine the semantic and setup the gl binding type we should use // to set this parameter. If there's a sensible default value, set that // while we're here. // Note there is no need to set the source type, this gets determined // when the vertex attribute sources are analysed if( semantic == "POSITION") { fGLType = glRegister::kPosition; fVertexAttribute->fSourceName = "position"; } else if( semantic == "NORMAL") { fGLType = glRegister::kNormal; if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "normal"; } else if( semantic == "TEXCOORD") { fGLType = glRegister::kTexCoord; if( fVertexAttribute.isNull() == false ) { if( attrName.toLowerCase() == "tangent") fVertexAttribute->fSourceName = "tangent:map1"; else if( attrName.toLowerCase() == "binormal") fVertexAttribute->fSourceName = "binormal:map1"; else fVertexAttribute->fSourceName = "uv:map1"; } } else if( semantic == "TANGENT") { fGLType = glRegister::kTexCoord; fGLIndex += 6; // TANGENT is TEXCOORD6 if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "tangent:map1"; } else if( semantic == "BINORMAL") { fGLType = glRegister::kTexCoord; fGLIndex += 7; // BINORMAL is TEXCOORD7 if( fVertexAttribute.isNull() == false ) fVertexAttribute->fSourceName = "binormal:map1"; } else if( semantic == "COLOR") { fGLType = fGLIndex == 1 ? glRegister::kSecondaryColor : glRegister::kColor; } else if( semantic == "ATTR") { fGLType = glRegister::kVertexAttrib; if( fVertexAttribute.isNull() == false ) { fVertexAttribute->fSourceName = semanticName; } } else if( semantic == "PSIZE") { fGLType = glRegister::kVertexAttrib; fGLIndex = 6; } else { fGLType = glRegister::kUnknown; } }
/*********************************** * Parse and run semantic analysis on a GccAsmStatement. * Params: * s = gcc asm statement being parsed * sc = the scope where the asm statement is located * Returns: * the completed gcc asm statement, or null if errors occurred */ Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc) { //printf("GccAsmStatement::semantic()\n"); Parser p(sc->_module, (const utf8_t *)";", 1, false); // Make a safe copy of the token list before parsing. Token *toklist = NULL; Token **ptoklist = &toklist; for (Token *token = s->tokens; token; token = token->next) { *ptoklist = Token::alloc(); memcpy(*ptoklist, token, sizeof(Token)); ptoklist = &(*ptoklist)->next; *ptoklist = NULL; } p.token = *toklist; // Parse the gcc asm statement. s = parseGccAsm(&p, s); if (p.errors) return NULL; s->stc = sc->stc; // Fold the instruction template string. s->insn = semantic(s->insn, sc); s->insn = s->insn->ctfeInterpret(); if (s->insn->op != TOKstring || ((StringExp *) s->insn)->sz != 1) s->insn->error("asm instruction template must be a constant char string"); if (s->labels && s->outputargs) s->error("extended asm statements with labels cannot have output constraints"); // Analyse all input and output operands. if (s->args) { for (size_t i = 0; i < s->args->dim; i++) { Expression *e = (*s->args)[i]; e = semantic(e, sc); // Check argument is a valid lvalue/rvalue. if (i < s->outputargs) e = e->modifiableLvalue(sc, NULL); else if (e->checkValue()) e = new ErrorExp(); (*s->args)[i] = e; e = (*s->constraints)[i]; e = semantic(e, sc); assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); (*s->constraints)[i] = e; } } // Analyse all clobbers. if (s->clobbers) { for (size_t i = 0; i < s->clobbers->dim; i++) { Expression *e = (*s->clobbers)[i]; e = semantic(e, sc); assert(e->op == TOKstring && ((StringExp *) e)->sz == 1); (*s->clobbers)[i] = e; } } // Analyse all goto labels. if (s->labels) { for (size_t i = 0; i < s->labels->dim; i++) { Identifier *ident = (*s->labels)[i]; GotoStatement *gs = new GotoStatement(s->loc, ident); if (!s->gotos) s->gotos = new GotoStatements(); s->gotos->push(gs); semantic(gs, sc); } } return s; }
void PragmaDeclaration::parsepragmas(Module *m) { semantic(new Scope()); }
bool GPT::parse(list<pair<string,istream*> >& istream_list) { stringstream s; try { TokenStreamSelector* selector = new TokenStreamSelector; //codigo desgracado, mas faz o que deve //1: controle de multiplos tokenStreams //2: utilizar o filename adequado para error reporting PortugolLexer* lexer; PortugolLexer* prev = 0; PortugolLexer* fst = 0; string firstFile; int c = 0; for(list<pair<string,istream*> >::reverse_iterator it = istream_list.rbegin(); it != istream_list.rend(); ++it, ++c) { lexer = new PortugolLexer(*((*it).second), selector); selector->addInputStream(lexer, (*it).first); selector->select(lexer); selector->push((*it).first); if(!firstFile.empty()) { lexer->setNextFilename(firstFile); } prev = lexer; GPTDisplay::self()->addFileName((*it).first); firstFile = (*it).first; fst = lexer; } selector->select(fst); PortugolParser parser(*selector); GPTDisplay::self()->setCurrentFile(firstFile); ASTFactory ast_factory(PortugolAST::TYPE_NAME,&PortugolAST::factory); parser.initializeASTFactory(ast_factory); parser.setASTFactory(&ast_factory); parser.algoritmo(); if(_outputfile.empty()) { _outputfile = parser.nomeAlgoritmo(); } if(GPTDisplay::self()->hasError()) { GPTDisplay::self()->showErrors(); return false; } _astree = parser.getPortugolAST(); if(!_astree) { s << PACKAGE << ": erro interno: no parse tree" << endl; GPTDisplay::self()->showError(s); return false; } if(_printParseTree) { std::cerr << _astree->toStringList() << std::endl << std::endl; } SemanticWalker semantic(_stable); semantic.algoritmo(_astree); if(GPTDisplay::self()->hasError()) { GPTDisplay::self()->showErrors(); return false; } return true; } catch(ANTLRException& e) { s << PACKAGE << ": erro interno: " << e.toString() << endl; GPTDisplay::self()->showError(s); return false; } catch(exception& e) { s << PACKAGE << ": erro interno: " << e.what() << endl; GPTDisplay::self()->showError(s); return false; } s << "GPT::parse: bug, nao deveria executar essa linha!" << endl; GPTDisplay::self()->showError(s); return false; }
unsigned AggregateDeclaration::size(Loc loc) { //printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope); if (loc.linnum == 0) loc = this->loc; if (sizeok != SIZEOKdone && scope) { semantic(NULL); // Determine the instance size of base class first. if (ClassDeclaration *cd = isClassDeclaration()) cd->baseClass->size(loc); } if (sizeok != SIZEOKdone && members) { /* See if enough is done to determine the size, * meaning all the fields are done. */ struct SV { /* Returns: * 0 this member doesn't need further processing to determine struct size * 1 this member does */ static int func(Dsymbol *s, void *param) { VarDeclaration *v = s->isVarDeclaration(); if (v) { /* Bugzilla 12799: enum a = ...; is a VarDeclaration and * STCmanifest is already set in parssing stage. So we can * check this before the semantic() call. */ if (v->storage_class & STCmanifest) return 0; if (v->scope) v->semantic(NULL); if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter)) return 0; if (v->isField() && v->sem >= SemanticDone) return 0; return 1; } return 0; } }; SV sv; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; if (s->apply(&SV::func, &sv)) goto L1; } finalizeSize(NULL); L1: ; } if (!members) { error(loc, "unknown size"); } else if (sizeok != SIZEOKdone) { error(loc, "no size yet for forward reference"); //*(char*)0=0; } return structsize; }
bool Model::loadCollada(std::string filename){ //Load the collada xml file rapidxml::file<> xmlFile(filename.c_str()); rapidxml::xml_document<> doc; doc.parse<0>(xmlFile.data()); bool zup = std::string(doc.first_node()->first_node("asset")->first_node("up_axis")->value()) == "Z_UP"; //Load textures rapidxml::xml_node<> *images = doc.first_node()->first_node("library_images"); if(images->first_node("image") == 0){ Logger::error << "Couldn't load model: file contains no texture data." << std::endl; return false; } std::map<std::string, unsigned int> textures; for(rapidxml::xml_node<> *image = images->first_node("image"); image != 0; image = image->next_sibling("image")){ textures.insert(std::pair<std::string, unsigned int>(image->first_attribute("id")->value(), loadTextureFromPNG(filename.substr(0, filename.find_last_of("\\/")+1) + image->first_node("init_from")->value()))); } //Load effects //TODO: only supports common profiles using phong techniques rapidxml::xml_node<> *effectsNode = doc.first_node()->first_node("library_effects"); if(effectsNode->first_node("effect") == 0){ Logger::error << "Couldn't load model: file contains no effects data." << std::endl; return false; } std::map<std::string, Material> effects; for(rapidxml::xml_node<> *effect = effectsNode->first_node("effect"); effect != 0; effect = effect->next_sibling("effect")){ rapidxml::xml_node<> *profile = effect->first_node("profile_COMMON"); if(profile != 0){ rapidxml::xml_node<> *technique = profile->first_node("technique"); Material mat; rapidxml::xml_node<> *phong = technique->first_node("phong"); if(phong != 0){ if(phong->first_node("emission") != 0){ mat.emission = getVec4(phong->first_node("emission")->first_node("color")); } if(phong->first_node("ambient") != 0){ mat.ambient = getVec4(phong->first_node("ambient")->first_node("color")); } if(phong->first_node("diffuse") != 0){ if(phong->first_node("diffuse")->first_node("color") != 0){ mat.diffuse = getVec4(phong->first_node("diffuse")->first_node("color")); } if(phong->first_node("diffuse")->first_node("texture") != 0){ mat.diffuseTexture = textures.at(searchByAttribute(profile, "sid", searchByAttribute(profile, "sid", phong->first_node("diffuse")->first_node("texture")->first_attribute("texture")->value(), "newparam") ->first_node("sampler2D")->first_node("source")->value() , "newparam")->first_node("surface")->first_node("init_from")->value()); } } if(phong->first_node("specular") != 0){ if(phong->first_node("specular")->first_node("color") != 0){ mat.specular = getVec4(phong->first_node("specular")->first_node("color")); } if(phong->first_node("specular")->first_node("texture") != 0){ mat.specularTexture = textures.at(searchByAttribute(profile, "sid", searchByAttribute(profile, "sid", phong->first_node("specular")->first_node("texture")->first_attribute("texture")->value(), "newparam") ->first_node("sampler2D")->first_node("source")->value() , "newparam")->first_node("surface")->first_node("init_from")->value()); } } if(phong->first_node("shininess") != 0){ mat.shininess = std::stof(phong->first_node("shininess")->first_node("float")->value()); } } else { Logger::error << "Couldn't load model: material doesn't use the phong technique." << std::endl; return false; } if(technique->first_node("extra") != 0 && technique->first_node("extra")->first_node("technique")->first_node("bump") != 0){ mat.bumpmapTexture = textures.at(searchByAttribute(profile, "sid", searchByAttribute(profile, "sid", technique->first_node("extra")->first_node("technique")->first_node("bump")->first_node("texture")->first_attribute("texture")->value(), "newparam") ->first_node("sampler2D")->first_node("source")->value() , "newparam")->first_node("surface")->first_node("init_from")->value()); } effects.insert(std::pair<std::string, Material>(effect->first_attribute("id")->value(), mat)); } else { Logger::error << "Couldn't load model: material doesn't have a profile_COMMON tag." << std::endl; return false; } } //Load materials //TODO: make them overridable (collada spec)) rapidxml::xml_node<> *materialsNode = doc.first_node()->first_node("library_materials"); if(materialsNode->first_node("material") == 0){ Logger::error << "Couldn't load model: file contains no material data." << std::endl; return false; } std::map<std::string, Material> materials; for(rapidxml::xml_node<> *material = materialsNode->first_node("material"); material != 0; material = material->next_sibling("material")){ materials.insert(std::pair<std::string, Material>(material->first_attribute("id")->value(), effects.at(std::string(material->first_node("instance_effect")->first_attribute("url")->value()).substr(1)))); } //Load geometry std::map<std::string, Mesh> meshes; rapidxml::xml_node<> *geometries = doc.first_node()->first_node("library_geometries"); if(geometries->first_node("geometry") == 0){ Logger::error << "Couldn't load model: file contains no geometry data." << std::endl; return false; } for(rapidxml::xml_node<> *geometry = geometries->first_node("geometry"); geometry != 0; geometry = geometry->next_sibling("geometry")){ Mesh mesh; rapidxml::xml_node<> *meshNode = geometry->first_node("mesh"); if(meshNode == 0){ Logger::error << "Couldn't load model: The loader can only load geometry of type \"mesh\" (geometry with name: " << geometry->first_attribute("name")->value() << ")." << std::endl; return false; } if(meshNode->first_node("polylist") == 0){ Logger::error << "Couldn't load model: The loader can only load meshes that use polylists. (geometry with name: " << geometry->first_attribute("name")->value() << ")." << std::endl; return false; } //TODO: allow for multiple data types //<name, <stride, data>> std::map<std::string, std::pair<unsigned int, std::vector<float>>> sources; GLenum dataType; for(rapidxml::xml_node<> *source = meshNode->first_node("source"); source != 0; source = source->next_sibling("source")){ std::vector<float> container; dataType = readData(&container, source); if(dataType == GL_NONE){ return false; } sources.insert(std::pair<std::string, std::pair<unsigned int, std::vector<float>>>(source->first_attribute("id")->value(), std::pair<unsigned int, std::vector<float>>(std::stoi(source->first_node("technique_common")->first_node("accessor")->first_attribute("stride")->value()), container))); } //TODO: same data vertex merging (aka indexing) for(rapidxml::xml_node<> *polylist = meshNode->first_node("polylist"); polylist != 0; polylist = polylist->next_sibling("polylist")){ std::vector<float> openglData; std::vector<unsigned int> indices; std::vector<std::string> tempContainer; std::vector<int> colladaIndices; split(polylist->first_node("p")->value(), " ", &tempContainer); for(std::string s : tempContainer){ colladaIndices.push_back(std::stoi(s)); } std::vector<float> vertexData; float vertexOffset; float vertexStride; std::vector<float> normalData; float normalOffset; float normalStride; std::vector<float> uvData; float uvOffset; float uvStride; std::pair<unsigned int, std::vector<float>> pair; for(rapidxml::xml_node<> *input = polylist->first_node("input"); input != 0; input = input->next_sibling("input")){ std::string semantic(input->first_attribute("semantic")->value()); if(semantic == "VERTEX"){ pair = sources.at(std::string(meshNode->first_node("vertices")->first_node("input")->first_attribute("source")->value()).substr(1)); vertexData = pair.second; vertexOffset = std::stoi(input->first_attribute("offset")->value()); vertexStride = pair.first; } else if(semantic == "NORMAL"){ pair = sources.at(std::string(input->first_attribute("source")->value()).substr(1)); normalData = pair.second; normalOffset = std::stoi(input->first_attribute("offset")->value()); normalStride = pair.first; } else if(semantic == "TEXCOORD"){ pair = sources.at(std::string(input->first_attribute("source")->value()).substr(1)); uvData = pair.second; uvOffset = std::stoi(input->first_attribute("offset")->value()); uvStride = pair.first; } else { Logger::error << "Unknown input semantic: " << semantic << std::endl; return 0; } } PolyGroup poly; poly.elements = std::stoi(polylist->first_attribute("count")->value())*3; //Generate vertices for(unsigned int i = 0; i < poly.elements; i++){ openglData.push_back(vertexData.at(colladaIndices.at(i*3+vertexOffset)*vertexStride)); if(zup){ openglData.push_back(vertexData.at(colladaIndices.at(i*3+vertexOffset)*vertexStride+2)); openglData.push_back(-vertexData.at(colladaIndices.at(i*3+vertexOffset)*vertexStride+1)); } else { openglData.push_back(vertexData.at(colladaIndices.at(i*3+vertexOffset)*vertexStride+1)); openglData.push_back(vertexData.at(colladaIndices.at(i*3+vertexOffset)*vertexStride+2)); } openglData.push_back(normalData.at(colladaIndices.at(i*3+normalOffset)*normalStride)); if(zup){ openglData.push_back(normalData.at(colladaIndices.at(i*3+normalOffset)*normalStride+2)); openglData.push_back(-normalData.at(colladaIndices.at(i*3+normalOffset)*normalStride+1)); } else { openglData.push_back(normalData.at(colladaIndices.at(i*3+normalOffset)*normalStride+1)); openglData.push_back(normalData.at(colladaIndices.at(i*3+normalOffset)*normalStride+2)); } openglData.push_back(uvData.at(colladaIndices.at(i*3+uvOffset)*uvStride)); //collada stores the uv data the other way around. how silly. openglData.push_back(1.0f - uvData.at(colladaIndices.at(i*3+uvOffset)*uvStride+1)); //temp index indices.push_back(i); } poly.vaoid = sendToOpengl(openglData, indices); poly.material = materials.at(polylist->first_attribute("material")->value()); mesh.addPolyGroup(poly); } meshes.insert(std::pair<std::string, Mesh>(geometry->first_attribute("id")->value(), mesh)); //this->meshes.insert(std::pair<std::string, std::pair<glm::mat4, Mesh>>(std::string(geometry->first_attribute("id")->value()).substr(1), std::pair<glm::mat4, Mesh>(glm::mat4(1.0f), mesh))); } //Load scene rapidxml::xml_node<> *scenes = doc.first_node()->first_node("library_visual_scenes"); if(scenes->first_node("visual_scene") == 0){ Logger::error << "Couldn't load model: file contains no scene data." << std::endl; return false; } else { rapidxml::xml_node<> *scene = scenes->first_node("visual_scene"); for(rapidxml::xml_node<> *node = scene->first_node("node"); node != 0; node = node->next_sibling("node")){ if(node->first_node("instance_geometry") != 0){ std::vector<float> matrix; std::vector<std::string> tempContainer; glm::mat4 mat4 = glm::mat4(1.0f); if(node->first_node("matrix") == 0){ split(node->first_node("translate")->value(), " ", &tempContainer); mat4 = glm::translate(mat4, glm::vec3(std::stof(tempContainer[0]), std::stof(tempContainer[2]), -std::stof(tempContainer[1]))); tempContainer.clear(); split(searchByAttribute(node, "sid", "rotationX", "rotate")->value(), " ", &tempContainer); mat4 = glm::rotate(mat4, glm::radians(std::stof(tempContainer[3])), glm::vec3(1.0f, 0.0f, 0.0f)); tempContainer.clear(); split(searchByAttribute(node, "sid", "rotationZ", "rotate")->value(), " ", &tempContainer); mat4 = glm::rotate(mat4, glm::radians(std::stof(tempContainer[3])), glm::vec3(0.0f, 1.0f, 0.0f)); tempContainer.clear(); split(searchByAttribute(node, "sid", "rotationY", "rotate")->value(), " ", &tempContainer); mat4 = glm::rotate(mat4, glm::radians(std::stof(tempContainer[3])), glm::vec3(0.0f, 0.0f, -1.0f)); tempContainer.clear(); split(node->first_node("scale")->value(), " ", &tempContainer); mat4 = glm::scale(mat4, glm::vec3(std::stof(tempContainer[0]), std::stof(tempContainer[2]), std::stof(tempContainer[1]))); //mat4 = glm::mat4(1.0f); } else { split(node->first_node("matrix")->value(), " ", &tempContainer); for(std::string s : tempContainer){ matrix.push_back(std::stof(s)); } glm::mat4 mat4 = glm::make_mat4(matrix.data()); if(std::string(doc.first_node()->first_node("asset")->first_node("up_axis")->value()) == "Z_UP"){ mat4 = convertToRightHandedCoords(mat4); } } this->meshes.insert(std::pair<std::string,std::pair<glm::mat4, Mesh>>( node->first_attribute("id")->value(), std::pair<glm::mat4, Mesh>( mat4, meshes.at(std::string(node->first_node("instance_geometry")->first_attribute("url")->value()).substr(1))))); } } } rapidjson::Document animDoc; if(readJsonFile(filename.substr(0, filename.find_last_of("/")+1) + "animation.json", animDoc)){ rapidxml::xml_node<> *animations = doc.first_node()->first_node("library_animations"); if(animations->first_node("animation") != 0){ std::map<std::string, std::vector< std::pair<float, glm::vec3> > > locationKeyframes; std::map<std::string, std::vector< std::pair<float, glm::vec3> > > rotationKeyframes; for(rapidxml::xml_node<> *animNode = animations->first_node("animation"); animNode != 0; animNode = animNode->next_sibling("animation")){ std::vector<float> inputContainer; readData(&inputContainer, searchByAttribute( animNode, "id", std::string(searchByAttribute( animNode->first_node("sampler"), "semantic", "INPUT", "input" )->first_attribute("source")->value()).substr(1), "source")); std::vector<float> outputContainer; readData(&outputContainer, searchByAttribute( animNode, "id", std::string(searchByAttribute( animNode->first_node("sampler"), "semantic", "OUTPUT", "input" )->first_attribute("source")->value()).substr(1), "source"));/* std::vector< std::pair<float, glm::vec3> > keyframes; for(int i = 0; i < inputContainer.size(); i++){ keyframes.push_back(std::pair<float, glm::vec3>(inputContainer.at(i), outputContainer.at(i))); }*/ std::string target = animNode->first_node("channel")->first_attribute("target")->value(); std::string meshName = target.substr(0, target.find_first_of("/")); if(target.substr(target.find_first_of("/")+1, target.find_first_of(".")-target.find_first_of("/")-2) == "rotation"){ if(!rotationKeyframes.count(meshName)){ rotationKeyframes.insert(std::pair<std::string, std::vector< std::pair<float, glm::vec3> > >(meshName, std::vector< std::pair<float, glm::vec3> >())); } for(int i = 0; i < inputContainer.size(); i++){ if(rotationKeyframes.at(meshName).size() <= i){ rotationKeyframes.at(meshName).push_back(std::pair<float, glm::vec3>(inputContainer.at(i), glm::vec3(0.0f, 0.0f, 0.0f))); } if(target.substr(target.find_first_of("/")+1, target.find_first_of(".")-target.find_first_of("/")-1) == "rotationX"){ rotationKeyframes.at(meshName).at(i).second.x = outputContainer.at(i); } else if(target.substr(target.find_first_of("/")+1, target.find_first_of(".")-target.find_first_of("/")-1) == "rotationY"){ rotationKeyframes.at(meshName).at(i).second.y = outputContainer.at(i); } else if(target.substr(target.find_first_of("/")+1, target.find_first_of(".")-target.find_first_of("/")-1) == "rotationZ"){ rotationKeyframes.at(meshName).at(i).second.z = outputContainer.at(i); } } } else if(target.substr(target.find_first_of("/")+1, target.find_first_of(".")) == "location"){ if(locationKeyframes.count(meshName)){ locationKeyframes.insert(std::pair<std::string, std::vector< std::pair<float, glm::vec3> > >(meshName, std::vector< std::pair<float, glm::vec3> >())); } for(int i = 0; i < inputContainer.size(); i++){ if(locationKeyframes.at(meshName).size() <= i){ locationKeyframes.at(meshName).push_back(std::pair<float, glm::vec3>(inputContainer.at(i), glm::vec3(0.0f, 0.0f, 0.0f))); } if(target.substr(target.find_first_of(".")+1) == "X"){ locationKeyframes.at(meshName).at(i).second.x = outputContainer.at(i); } else if(target.substr(target.find_first_of(".")+1) == "Y"){ locationKeyframes.at(meshName).at(i).second.y = outputContainer.at(i); } else if(target.substr(target.find_first_of(".")+1) == "Z"){ locationKeyframes.at(meshName).at(i).second.z = outputContainer.at(i); } } } else { Logger::info << "unknown animation target: " << target << std::endl; } } for (rapidjson::SizeType i = 0; i < animDoc.Size(); i++) { Animation animation; rapidjson::Value& animjson = animDoc[i]; animation.mesh = animjson["mesh"].GetString(); int start = animjson["startKeyframe"].GetInt(); int end = animjson["endKeyframe"].GetInt(); for(int j = start; j <= end; j++){ glm::mat4 mat4 = this->meshes.at(animation.mesh).first; glm::vec3 rotation = rotationKeyframes.count(animation.mesh) ? rotationKeyframes.at(animation.mesh).at(j).second : glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 translation = locationKeyframes.count(animation.mesh) ? locationKeyframes.at(animation.mesh).at(j).second : glm::vec3(0.0f, 0.0f, 0.0f); if(zup){ mat4 = glm::translate(mat4, glm::vec3(translation.x, translation.z, -translation.y)); mat4 = glm::rotate(mat4, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); mat4 = glm::rotate(mat4, glm::radians(rotation.z), glm::vec3(0.0f, 1.0f, 0.0f)); mat4 = glm::rotate(mat4, glm::radians(rotation.y), glm::vec3(0.0f, 0.0f, -1.0f)); } else { mat4 = glm::translate(mat4, glm::vec3(translation.x, translation.y, translation.z)); mat4 = glm::rotate(mat4, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); mat4 = glm::rotate(mat4, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); mat4 = glm::rotate(mat4, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); } animation.keyframes.push_back(std::make_pair(rotationKeyframes.at(animation.mesh).at(j).first, mat4)); } this->animations.insert(std::make_pair(animjson["name"].GetString(), animation)); } } } return true; }