ucfunc.cc
来自「一个制作3d游戏的源程序」· CC 代码 · 共 1,080 行 · 第 1/3 页
CC
1,080 行
/* * Copyright (C) 2001-2002 The Exult Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include "ucdata.h"#include "ucfunc.h"#include <set>#ifdef HAVE_SSTREAM#include <sstream>#else#include <strstream>#endif#include <algorithm>#include <iomanip>#include "files/utils.h"#include "ops.h"#if 0 #define DEBUG_INDENT #define DEBUG_PARSE #define DEBUG_PARSE2 #define DEBUG_PARSE2a #define DEBUG_READ #define DEBUG_PRINT #define DEBUG_READ_PAIR(X, Y) cout << '\t' << X << '\t' << Y << endl;#else #undef DEBUG_INDENT #undef DEBUG_PARSE #undef DEBUG_PARSE2 #undef DEBUG_READ #undef DEBUG_PRINT #define DEBUG_READ_PAIR(X, Y)#endif//#define DEBUG_PARSE2//#define DEBUG_PARSE2a//#define DEBUG_PRINTusing std::ostream;using std::ifstream;using std::string;using std::vector;using std::map;using std::endl;using std::pair;using std::ios;using std::streampos;using std::cout;using std::setw;using std::less;const string VARNAME = "var";const string VARPREFIX = "var";string demunge_ocstring(UCFunc &ucf, const FuncMap &funcmap, const string &asmstr, const vector<unsigned int> ¶ms, const map<unsigned int, string> &intrinsics, const UCc &op, bool ucs_output);/* Assumption the 'var's are in their 'zeroed' state on initialization, unless something else is assigned to them. */inline ostream &tab_indent(const unsigned int indent, ostream &o){ #ifdef DEBUG_INDENT o << indent; #endif switch(indent) { case 0: break; case 1: o << '\t'; break; case 2: o << "\t\t"; break; case 3: o << "\t\t\t"; break; case 4: o << "\t\t\t\t"; break; case 5: o << "\t\t\t\t\t"; break; default: for(unsigned int i=0; i<indent; ++i) o << '\t'; break; } return o;}/* Outputs the short function data 'list' format, returns true upon success */bool UCFunc::output_list(ostream &o, unsigned int funcno, const UCOptions &options){ o << "#" << std::setbase(10) << std::setw(4) << funcno << std::setbase(16) << ": " << (return_var ? '&' : ' ') << std::setw(4) << _funcid << "H " << std::setw(8) << _offset << " " << std::setw(4) << _funcsize << " " << std::setw(4) << _datasize << " " << std::setw(4) << codesize() << " "; if(options.ucdebug) o << _data.find(0)->second; o << endl; return true;}/* Outputs the usecode-script formatted usecode, returns true upon success */bool UCFunc::output_ucs(ostream &o, const FuncMap &funcmap, const map<unsigned int, string> &intrinsics, const UCOptions &options){ unsigned int indent=0; if(_externs.size()) tab_indent(indent, o) << "// externs" << endl; // output the 'externs' for(vector<unsigned int>::iterator e=_externs.begin(); e!=_externs.end(); e++) { FuncMap::const_iterator fmp = funcmap.find(*e); output_ucs_funcname(tab_indent(indent, o) << "extern ", funcmap, *e, fmp->second.num_args, fmp->second.return_var) << ';' << endl; } if(_externs.size()) o << endl; // output the function name output_ucs_funcname(tab_indent(indent, o), funcmap, _funcid, _num_args, return_var) << endl; // start of func tab_indent(indent++, o) << '{' << endl; for(unsigned int i=_num_args; i<_num_args+_num_locals; i++) tab_indent(indent, o) << VARNAME << ' ' << VARPREFIX << std::setw(4) << i << ';' << endl; if(return_var) tab_indent(indent, o) << VARNAME << ' ' << "rr" << ';' << endl; if(_num_locals>0) o << endl; output_ucs_data(o, funcmap, intrinsics, options, indent); tab_indent(--indent, o) << '}' << endl; return true;}/* outputs the general 'function name' in long format. For function declarations and externs */ostream &UCFunc::output_ucs_funcname(ostream &o, const FuncMap &funcmap, unsigned int funcid, unsigned int numargs, bool return_var){ // do we return a variable if(return_var) o << VARNAME << ' '; // output the "function name" // TODO: Probably want to grab this from a file in the future... //o << demunge_ocstring(*this, funcmap, "%f1", ucc._params_parsed, intrinsics, ucc, true) FuncMap::const_iterator fmp = funcmap.find(funcid); if(fmp->second.funcname.size()) { if(fmp->second.funcname[0]=='&') o << fmp->second.funcname.substr(1, fmp->second.funcname.size()-1); else o << fmp->second.funcname; } else o << "Func" << std::setw(4) << funcid; // output the "function number" o << " 0x" << funcid // output ObCurly braces << " ("; for(unsigned int i=0; i<numargs; i++) o << VARNAME << ' ' << VARPREFIX << std::setw(4) << i << ((i==numargs-1) ? "" : ", "); o << ")"; return o;}ostream &UCFunc::output_ucs_funcname(ostream &o, const FuncMap &funcmap){ return output_ucs_funcname(o, funcmap, _funcid, _num_args, return_var);}void UCFunc::output_ucs_data(ostream &o, const FuncMap &funcmap, const map<unsigned int, string> &intrinsics, const UCOptions &options, unsigned int indent){ vector<unsigned int> labeltmp(1); for(vector<GotoSet>::iterator i=gotoset.begin(); i!=gotoset.end(); ++i) { // we don't want to output the first "jump" (the start of the function) if(i!=gotoset.begin()) { labeltmp[0]=i->offset(); tab_indent(indent++, o) << demunge_ocstring(*this, funcmap, "label%f*_%1:", labeltmp, intrinsics, UCc(), true) << endl; } for(GotoSet::iterator j=(*i)().begin(); j!=(*i)().end(); j++) { const UCc &ucc = *(j->first); if(options.uselesscomment) tab_indent(indent, o) << "// Offset: " << std::setw(4) << ucc._offset << endl; output_ucs_opcode(o, funcmap, opcode_table_data, ucc, intrinsics, indent); } if(i!=gotoset.begin()) --indent; //decrement it again to skip the label statement. }}void UCFunc::output_ucs_opcode(ostream &o, const FuncMap &funcmap, const vector<UCOpcodeData> &optab, const UCc &op, const map<unsigned int, string> &intrinsics, unsigned int indent){ tab_indent(indent, o) << demunge_ocstring(*this, funcmap, optab[op._id].ucs_nmo, op._params_parsed, intrinsics, op, true) << ';' << endl; #ifdef DEBUG_PRINT for(vector<UCc *>::const_iterator i=op._popped.begin(); i!=op._popped.end(); i++) { if((*i)->_popped.size()) output_ucs_opcode(o, funcmap, opcode_table_data, **i, intrinsics, indent+1); else// tab_indent(indent+1, o) << demunge_ocstring(*this, funcmap, optab[(*i)->_id].ucs_nmo, op._params_parsed, **i) << endl; tab_indent(indent+1, o) << optab[(*i)->_id].ucs_nmo << endl; } #endif}void UCFunc::output_ucs_node(ostream &o, const FuncMap &funcmap, UCNode* ucn, const map<unsigned int, string> &intrinsics, unsigned int indent, const UCOptions &options){ if(!ucn->nodelist.empty()) tab_indent(indent, o) << '{' << endl; if(ucn->ucc!=0) output_asm_opcode(tab_indent(indent, o), funcmap, opcode_table_data, intrinsics, *(ucn->ucc), options); if(ucn->nodelist.size()) for(vector<UCNode *>::iterator i=ucn->nodelist.begin(); i!=ucn->nodelist.end(); i++) { //tab_indent(indent, o); output_ucs_node(o, funcmap, *i, intrinsics, indent+1, options); } // end of func if(!ucn->nodelist.empty()) tab_indent(indent, o) << '}' << endl;}/* Just a quick function to remove all the ucc structured flagged as removable */inline void gc_gotoset(vector<GotoSet> &gotoset){ for(vector<GotoSet>::iterator i=gotoset.begin(); i!=gotoset.end(); i++) { i->gc(); #ifdef DEBUG_GOTOSET cout << "----" << endl; #endif }}void UCFunc::parse_ucs(const FuncMap &funcmap, const map<unsigned int, string> &intrinsics, const UCOptions &options){ for(vector<UCc>::iterator i=_opcodes.begin(); i!=_opcodes.end(); i++) node.nodelist.push_back(new UCNode(&(*i))); parse_ucs_pass1(node.nodelist); parse_ucs_pass2(gotoset, funcmap, intrinsics); gc_gotoset(gotoset); if(!options.basic) { parse_ucs_pass3(gotoset, intrinsics); } #ifdef DEBUG_PARSE2 for(vector<GotoSet>::iterator i=gotoset.begin(); i!=gotoset.end(); i++) { cout << std::setw(4) << i->offset() << endl; for(GotoSet::iterator j=(*i)().begin(); j!=(*i)().end(); j++) { cout << '\t' << std::setw(4) << j->first->_offset << '\t' << j->first->_id << endl; } } #endif}/* Pass 1 turns the 1-dimentional vector of opcodes, into a 2-dimentional array consisting of all the opcodes within two 'goto target offsets'. */void UCFunc::parse_ucs_pass1(vector<UCNode *> &nodes){ vector<unsigned int> jumps; // collect jump references for(unsigned int i=0; i<nodes.size(); i++) { if(nodes[i]->ucc!=0) { unsigned int isjump=0; for(vector<pair<unsigned int, unsigned int> >::iterator op=opcode_jumps.begin(); op!=opcode_jumps.end(); op++) if(op->first==nodes[i]->ucc->_id) { isjump=op->second; break; } if(isjump!=0) { assert(nodes[i]->ucc->_params_parsed.size()>=isjump); jumps.push_back(nodes[i]->ucc->_params_parsed[isjump-1]); } } } gotoset.push_back(GotoSet()); for(unsigned int i=0; i<nodes.size(); i++) { if(nodes[i]->ucc!=0) { if(count(jumps.begin(), jumps.end(), nodes[i]->ucc->_offset)) { gotoset.push_back(nodes[i]->ucc); } else gotoset.back().add(nodes[i]->ucc); } }}/* In Pass 2 we convert our 2-dimensional 'GotoSet' array into an array with each UCc, having it's parameters sitting in it's UCc::_popped vector. Elements that are parameters are flagged for removal (Gotoset::()[i]->second=true) from the original GotoSet. */void UCFunc::parse_ucs_pass2(vector<GotoSet> &gotoset, const FuncMap &funcmap, const map<unsigned int, string> &intrinsics){ for(vector<GotoSet>::iterator i=gotoset.begin(); i!=gotoset.end(); ++i) { parse_ucs_pass2a((*i)().rbegin(), (*i)(), 0, funcmap, intrinsics); }}vector<UCc *> UCFunc::parse_ucs_pass2a(vector<pair<UCc *, bool> >::reverse_iterator current, vector<pair<UCc *, bool> > &vec, unsigned int opsneeded, const FuncMap &funcmap, const map<unsigned int, string> &intrinsics){ vector<UCc *> vucc; unsigned int opsfound=0; #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif for(;vec.rend()!=current; current++) { #ifdef DEBUG_PARSE2
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?