IntermediateData *ScriptParser::generateOCode(FunctionData *fdata)
{
    //Z_message("yes");
    bool failure = false;
    vector<ASTFuncDecl *> funcs = fdata->functions;
    vector<ASTVarDecl *> globals = fdata->globalVars;
    vector<ASTArrayDecl *> globalas = fdata->globalArrays;
    
    //we have no need of newglobals at this point anymore
    for(vector<ASTVarDecl *>::iterator it = fdata->newGlobalVars.begin(); it != fdata->newGlobalVars.end(); it++)
        globals.push_back(*it);
        
    for(vector<ASTArrayDecl *>::iterator it = fdata->newGlobalArrays.begin(); it != fdata->newGlobalArrays.end(); it++)
        globalas.push_back(*it);
        
    map<string, int> runsymbols = fdata->scriptRunSymbols;
    SymbolTable *symbols = fdata->symbols;
    map<string, int> numparams = fdata->numParams;
    map<string, int> scripttypes = fdata->scriptTypes;
    map<string, int> thisptr = fdata->thisPtr;
    delete fdata;
    LinkTable lt;
    
    for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++)
    {
        int vid2 = symbols->getID(*it);
        lt.addGlobalVar(vid2);
    }
    
    for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++)
    {
        int vid2 = symbols->getID(*it);
        lt.addGlobalVar(vid2);
    }
    
    //Z_message("yes");
    //and add the this pointers
    for(vector<int>::iterator it = symbols->getGlobalPointers().begin(); it != symbols->getGlobalPointers().end(); it++)
    {
        lt.addGlobalPointer(*it);
    }
    
    for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++)
    {
        int fid2 = symbols->getID(*it);
        lt.functionToLabel(fid2);
    }
    
    //Z_message("yes");
    
    //we now have labels for the functions and ids for the global variables.
    //we can now generate the code to intialize the globals
    IntermediateData *rval = new IntermediateData();
    
    //Link against the global symbols, and add their labels
    map<int, vector<Opcode *> > globalcode = GlobalSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = FFCSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ItemSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ItemclassSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = LinkSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ScreenSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = GameSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = NPCSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = LinkWeaponSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = EnemyWeaponSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    //Z_message("yes");
    
    for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++)
    {
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = NULL;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
        {
            failure = true;
        }
        
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++)
        {
            rval->globalsInit.push_back(*it2);
        }
        
        delete *it; //say so long to our lovely data structure the AST
    }
    
    //Z_message("yes");
    for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++)
    {
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = NULL;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
        {
            failure = true;
        }
        
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++)
        {
            rval->globalasInit.push_back(*it2);
        }
        
        delete *it; //say so long to our lovely data structure the AST
    }
    
    //Z_message("yes");
    
    //globals have been initialized, now we repeat for the functions
    for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++)
    {
        bool isarun = false;
        string scriptname;
        
        for(map<string,int>::iterator it2 = runsymbols.begin(); it2 != runsymbols.end(); it2++)
        {
            if(it2->second == symbols->getID(*it))
            {
                isarun=true;
                scriptname = it2->first;
                break;
            }
        }
        
        vector<Opcode *> funccode;
        //count the number of stack-allocated variables
        vector<int> stackvars;
        pair<vector<int> *, SymbolTable *> param = pair<vector<int> *, SymbolTable *>(&stackvars, symbols);
        CountStackSymbols temp;
        (*it)->execute(temp, &param);
        int offset = 0;
        StackFrame sf;
        
        //if this is a run, there is the this pointer
        if(isarun)
        {
            sf.addToFrame(thisptr[scriptname], offset);
            offset += 10000;
        }
        
        //the params are now the first elements of this list
        //so assign them depths in reverse order
        for(vector<int>::reverse_iterator it2 = stackvars.rbegin(); it2 != stackvars.rend(); it2++)
        {
            sf.addToFrame(*it2, offset);
            offset += 10000;
        }
        
        //start of the function
        Opcode *first = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0));
        first->setLabel(lt.functionToLabel(symbols->getID(*it)));
        funccode.push_back(first);
        //push on the 0s
        int numtoallocate = (unsigned int)stackvars.size()-(unsigned int)symbols->getFuncParams(symbols->getID(*it)).size();
        
        for(int i = 0; i < numtoallocate; i++)
        {
            funccode.push_back(new OPushRegister(new VarArgument(EXP1)));
        }
        
        //push on the this, if a script
        if(isarun)
        {
            switch(scripttypes[scriptname])
            {
            case ScriptParser::TYPE_FFC:
                funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFFFC)));
                break;
                
            case ScriptParser::TYPE_ITEMCLASS:
                funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFITEMCLASS)));
                break;
                
            case ScriptParser::TYPE_GLOBAL:
                //don't care, we don't have a valid this pointer
                break;
            }
            
            funccode.push_back(new OPushRegister(new VarArgument(EXP2)));
        }
        
        //set up the stack frame register
        funccode.push_back(new OSetRegister(new VarArgument(SFRAME), new VarArgument(SP)));
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = &sf;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
            failure = true;
            
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2 != code.end(); it2++)
        {
            funccode.push_back(*it2);
        }
        
        //add appendix code
        //nop label
        Opcode *next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0));
        next->setLabel(bo.getReturnLabelID());
        funccode.push_back(next);
        
        //pop off everything
        for(unsigned int i=0; i< stackvars.size(); i++)
        {
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
        }
        
        //if it's a main script, quit.
        if(isarun)
            funccode.push_back(new OQuit());
        else
        {
            //pop off the return address
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
            //and return
            funccode.push_back(new OGotoRegister(new VarArgument(EXP2)));
        }
        
        rval->funcs[lt.functionToLabel(symbols->getID(*it))]=funccode;
        delete *it;
    }
    
    //Z_message("yes");
    
    //update the run symbols
    for(map<string, int>::iterator it = runsymbols.begin(); it != runsymbols.end(); it++)
    {
        int labelid = lt.functionToLabel(it->second);
        rval->scriptRunLabels[it->first] = labelid;
        rval->numParams[it->first] = numparams[it->first];
        rval->scriptTypes[it->first] = scripttypes[it->first];
    }
    
    delete symbols; //and so long to our beloved ;) symbol table
    //Z_message("yes");
    
    if(failure)
    {
        //delete all kinds of crap if there was a problem :-/
        for(map<int, vector<Opcode *> >::iterator it = rval->funcs.begin(); it != rval->funcs.end(); it++)
        {
            for(vector<Opcode *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
            {
                delete *it2;
            }
        }
        
        for(vector<Opcode *>::iterator it = rval->globalsInit.begin(); it != rval->globalsInit.end(); it++)
        {
            delete *it;
        }
        
        for(vector<Opcode *>::iterator it = rval->globalasInit.begin(); it != rval->globalasInit.end(); it++)
        {
            delete *it;
        }
        
        delete rval;
        return NULL;
    }
    
    //Z_message("yes");
    return rval;
}