CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack) { CBotToken* pp = p; p = p->GetNext(); if (p->GetType() == ID_OPENPAR) { CBotVar* ppVars[1000]; CBotInstrCall* inst = new CBotInstrCall(); inst->SetToken(pp); // compile la list of parameters inst->m_parameters = CompileParams(p, pStack, ppVars); if ( !pStack->IsOk() ) { delete inst; return nullptr; } // the routine is known? // CBotClass* pClass = nullptr; inst->m_typRes = pStack->CompileCall(pp, ppVars, inst->m_nFuncIdent); if ( inst->m_typRes.GetType() >= 20 ) { // if (pVar2!=nullptr) pp = pVar2->RetToken(); pStack->SetError( static_cast<CBotError>(inst->m_typRes.GetType()), pp ); delete pStack->TokenStack(); delete inst; return nullptr; } delete pStack->TokenStack(); if ( inst->m_typRes.GetType() > 0 ) { CBotVar* pRes = CBotVar::Create("", inst->m_typRes); pStack->SetVar(pRes); // for knowing the type of the result } else pStack->SetVar(nullptr); // routine returns void if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack))) { inst->m_exprRetVar->SetToken(&inst->m_token); delete pStack->TokenStack(); } if ( !pStack->IsOk() ) { delete inst; return nullptr; } return inst; } p = pp; delete pStack->TokenStack(); return nullptr; }
int main (int argc, char **argv) { int sucess; progexterns_t ext; progfuncs_t funcs; progfuncs = &funcs; memset(&funcs, 0, sizeof(funcs)); funcs.parms = &ext; memset(&ext, 0, sizeof(progexterns_t)); funcs.parms->ReadFile = QCC_ReadFile; funcs.parms->FileSize = QCC_FileSize; funcs.parms->WriteFile = QCC_WriteFile; funcs.parms->printf = logprintf; funcs.parms->Sys_Error = Sys_Error; logfile = fopen("rmqcc.log", "wt"); sucess = CompileParams(&funcs, true, argc, argv); qccClearHunk(); if (logfile) fclose(logfile); #ifdef _WIN32 // fgetc(stdin); //wait for keypress #endif return !sucess; }
CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack) { CBotToken* pp = p; if (!IsOfType(p, ID_NEW)) return nullptr; // verifies that the token is a class name if (p->GetType() != TokenTypVar) { pStack->SetError(CBotErrBadNew, p); return nullptr; } CBotClass* pClass = CBotClass::Find(p); if (pClass == nullptr) { pStack->SetError(CBotErrBadNew, p); return nullptr; } CBotNew* inst = new CBotNew(); inst->SetToken(pp); inst->m_vartoken = *p; p = p->GetNext(); // creates the object on the stack // with a pointer to the object CBotVar* pVar = CBotVar::Create("", pClass); // do the call of the creator CBotCStack* pStk = pStack->TokenStack(); { // check if there are parameters CBotVar* ppVars[1000]; inst->m_parameters = CompileParams(p, pStk, ppVars); if (!pStk->IsOk()) goto error; // constructor exist? CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent); delete pStk->TokenStack(); // release extra stack int typ = r.GetType(); // if there is no constructor, and no parameters either, it's ok if (typ == CBotErrUndefCall && inst->m_parameters == nullptr) typ = 0; pVar->SetInit(CBotVar::InitType::DEF); // mark the instance as init if (typ>20) { pStk->SetError(static_cast<CBotError>(typ), inst->m_vartoken.GetEnd()); goto error; } // if the constructor does not exist, but there are parameters if (typ<0 && inst->m_parameters != nullptr) { pStk->SetError(CBotErrNoConstruct, &inst->m_vartoken); goto error; } // makes pointer to the object on the stack pStk->SetVar(pVar); pp = p; // chained method ? if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true))) { inst->m_exprRetVar->SetToken(pp); delete pStk->TokenStack(); } if (pStack->IsOk()) return pStack->Return(inst, pStk); } error: delete inst; return pStack->Return(nullptr, pStk); }
pbool CompileFile(progfuncs_t *progfuncs, char *filename) { #ifdef MINIMAL return false; #else char srcfile[32]; char newname[32]; static char *p[5]; int parms; char *s, *s2; p[0] = NULL; parms = 1; strcpy(newname, filename); s = newname; if (strchr(s+1, '/')) { while(1) { s2 = strchr(s+1, '/'); if (!s2) { *s = '\0'; break; } s = s2; } p[parms] = "-src"; p[parms+1] = newname; parms+=2; strcpy(srcfile, s+1); srcfile[strlen(srcfile)-4] = '\0'; strcat(srcfile, ".src"); if (externs->FileSize(qcva("%s/%s", newname, srcfile))>0) { p[parms] = "-srcfile"; p[parms+1] = srcfile; parms+=2; } } else { p[parms] = "-srcfile"; p[parms+1] = newname; newname[strlen(newname)-4] = '\0'; strcat(newname, ".src"); parms+=2; } // p[2][strlen(p[2])-4] = '\0'; // strcat(p[2], "/"); while (!CompileParams(progfuncs, true, parms, p)) { return false; } return true; #endif }
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass) { // seeks the corresponding classes if ( pClass == NULL ) { pStack->SetStartError(p->GetStart()); pClass = CBotClass::Find(p); if ( pClass == NULL ) { // not found? is bizare pStack->SetError(TX_NOCLASS, p); return NULL; } p = p->GetNext(); } bool bIntrinsic = pClass->IsIntrinsic(); CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass ); CBotClassInst* inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type)); if ( inst != NULL || !pStack->IsOk() ) return inst; CBotCStack* pStk = pStack->TokenStack(); inst = new CBotClassInst(); /// \TODO Need to be revised and fixed after adding unit tests CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd()); inst->SetToken(&token); CBotToken* vartoken = p; if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) ) { (static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type; if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable { pStk->SetStartError(vartoken->GetStart()); pStk->SetError(TX_REDEFVAR, vartoken->GetEnd()); goto error; } if (IsOfType(p, ID_OPBRK)) // with any clues? { delete inst; // is not type CBotInt p = vartoken; // returns to the variable name // compiles declaration an array inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type )); if (!pStk->IsOk() ) { pStk->SetError(TX_CLBRK, p->GetStart()); goto error; } goto suite; // no assignment, variable already created } CBotVar* var; var = CBotVar::Create(vartoken->GetString(), type); // creates the instance // var->SetClass(pClass); var->SetUniqNum( (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); // its attribute a unique number pStack->AddVar(var); // placed on the stack // look if there are parameters inst->m_hasParams = (p->GetType() == ID_OPENPAR); CBotVar* ppVars[1000]; inst->m_Parameters = CompileParams(p, pStk, ppVars); if ( !pStk->IsOk() ) goto error; // if there are parameters, is the equivalent to the stament "new" // CPoint A ( 0, 0 ) is equivalent to // CPoint A = new CPoint( 0, 0 ) // if ( NULL != inst->m_Parameters ) if ( inst->m_hasParams ) { // the constructor is there? // CBotString noname; CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent); delete pStk->TokenStack(); // releases the supplement stack int typ = r.GetType(); if (typ == TX_UNDEFCALL) { // si le constructeur n'existe pas if (inst->m_Parameters != NULL) // with parameters { pStk->SetError(TX_NOCONST, vartoken); goto error; } typ = 0; } if (typ>20) { pStk->SetError(typ, vartoken->GetEnd()); goto error; } } if (IsOfType(p, ID_ASS)) // with a assignment? { if (inst->m_hasParams) { pStk->SetError(TX_ENDOF, p->GetStart()); goto error; } if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) ) { goto error; } CBotClass* result = pStk->GetClass(); if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) && ( !pStk->GetTypResult(1).Eq(CBotTypPointer) || ( result != NULL && !pClass->IsChildOf(result) ))) // type compatible ? { pStk->SetError(TX_BADTYPE, p->GetStart()); goto error; } // if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer()); if ( !bIntrinsic ) { // does not use the result on the stack, to impose the class CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(true); // marks the pointer as init } else if (inst->m_hasParams) { // creates the object on the "job" (\TODO "tas") // with a pointer to the object if ( !bIntrinsic ) { CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(2); // marks the pointer as init } suite: if (IsOfType(p, ID_COMMA)) // several chained definitions { if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following { return pStack->Return(inst, pStk); } } if (IsOfType(p, ID_SEP)) // complete instruction { return pStack->Return(inst, pStk); } pStk->SetError(TX_ENDOF, p->GetStart()); } error: delete inst; return pStack->Return(NULL, pStk); }