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> &params, 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 + -
显示快捷键?