⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 script.cpp

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 CPP
字号:
////////////////////////////////////////////////////////
//
// script.cpp
// 
// Implementaion of a basic basic :) interpreter
//
//
// Maarten Bosma, 09.01.2004
// maarten.paul@bosma.de
//
////////////////////////////////////////////////////////////////////

#include "package.hpp"
#include "script.h"
#include "log.h"
#include <fstream>

using namespace std;

// just a few Helpers
void Replace (string* Where, string Old, string New, int start = 0, int end = -1, int instring = 1);
int FindCount (string What, string Where, int start = 0, int end = -1);
int Find (string Where, string What, int start = 0, int end = -1, int instring = 1);


// Loads script from file, checks if it's synaxially correct
// and converts it into a easy to interprete one.
int RPS_Load (SCRIPT** script, const char* path)
{
	string source;

	/* We have to do it that way (doublepointer) because MinGw 
	   calls "delete" at the end of function otherwise. */
	(*script) = new SCRIPT;	

	// Load file to string
	ifstream file(path, ios_base::in);
	if (!file.is_open())
		return ERR_FILE;

	getline(file, source, '\0');

	// make sure last char is a new line
	source += "\n"; 
	
	// Are all subs and strings closed ?
	// FIXME: Just a quick hack sould be both checked line by line
	if(FindCount(source, "\"")%2) // if count is uneven not all strings are closed 
		return ERR_SYNATX;

	if(FindCount(source, "Sub ") != FindCount(source, "End Sub\n"))
		return ERR_SYNATX;

	// Delete comments
	while (true)
	{
		int start = Find(source, "'");
		if(start == NOTFOUND)
			break;
		int end = Find(source, "\n", start);
		source.erase(start, end-start); // needs size not line
	}

	// Converte the file into some thing easier to interprete
	Replace(&source, "(", " ");
	Replace(&source, ")", " ");
	Replace(&source, ";", " ");
	Replace(&source, ",", " ");
	Replace(&source, "\"", " \" ");
	Replace(&source, "\t", " ");

	Replace(&source, "  ", " ");
	Replace(&source, "\n ", "\n");
	Replace(&source, " \n", "\n");
	Replace(&source, "\n\n", "\n");

	if(source[0]=='\n')
		source.erase(0,1);

	// copy string into struct (line by line)
	UINT i, line=0;
	for (i=0; i < source.size(); i++)
	{
		// Make everything non capital letters
		if (source[i] >= 65 && source[i] <= 90) // ASCII-Code (A-Z 65-90)
		{
			source[i] += 32; // ASCII-Code (a-z 97-122)
		}

		else if (source[i] == '\"')
		{
			while(source[++i]!='\"');
		}

		else if (source[i] == '\n')
		{
			(*script)->code.push_back(source.substr(line, i-line));
			line = i+1;
		}
	}

	// create a sub table (with name, beginnig and end of function)
	for (i=0; i < (*script)->code.size(); i++) // code.size() is the cout of lines
	{
		SUB sub;
		
		if((*script)->code[i].substr(0,4) != "sub ")
			return ERR_SYNATX; // script has to start with sub

		sub.name = (*script)->code[i].substr(4,((*script)->code[i].size()-4));
		sub.start = i+1;

		while ((*script)->code[i] != "end sub")
		{
			i++;
			//if script does not end with "end sub" we got a problem
			if (i>(*script)->code.size())
				return ERR_SYNATX; 
		}

		sub.end = i;
		(*script)->subs.push_back(sub);
	}

	return ERR_OK;
}


// Executes a subroutine of the script
int RPS_Execute (SCRIPT* script, const char* function)
{
	char *argv[100];
	char *buffer;
	int a, b, c, nr = NOTFOUND, argc = 0;

	// find the right fuction
	for(a=0; (UINT)a<script->subs.size(); a++)
		if(script->subs[a].name == function)
			nr = a;

	// if there isn't a fuction with this name we can't do anything
	if(nr == NOTFOUND)
		return ERR_OK;

	// call the function
	for (a=script->subs[nr].start; a<script->subs[nr].end; a++)
	{
		// create a temporarry buffer 
		buffer = new char[script->code[a].size()];
		strcpy(buffer, script->code[a].c_str());

		// make the fist argument the function's name
		argv[0] = &buffer[0];
	
		int buffer_size = (int)strlen(buffer);
		for (b=0; b<buffer_size+1; b++)
		{
			// ignore chars in strings
			if(buffer[b]=='\"')
			{
				argv[argc] = &buffer[b+1];

				while(buffer[++b]!='\"');

				buffer[b] = '\0';
			}

			// create a new argument
			else if(buffer[b]==' ')
			{
				argc++;
				argv[argc] = &buffer[b+1];
				buffer[b] = '\0';

				// we don't want buffer overflows
				if(argc == 99) 
					return ERR_GENERIC;

			}

			// call the function
			else if(buffer[b]=='\0')
			{
				int error = 0;

				// log the name
				Log("*   excute command: ");
				for(c=0; c<argc+1; c++)
				{
					LogAdd(argv[c]); 
					LogAdd(" ");
				}

				for(c=0; c<FUNC_COUNT; c++)
					if(!strcmp(argv[0], FuncTable[c].name))
						error = FuncTable[c].function(argc, &argv[0]);

				if(error)
					return error;
			}

		}

		// start again with next line
		delete[] buffer;
		argc = 0;
	}

	return ERR_OK;
}

// get a Constant or a variavle
int RPS_getVar (const char* name)
{
	return ERR_OK;
}

// Clears up Memory
void RPS_Clear (SCRIPT* script)
{
	if(script)
		delete script;
}

/* Helper Functions */

// How often do we find a string inside another one
int FindCount (string where, string what, int start, int end)
{
	int counter = 0, pos;
	
	while(true)
	{
		pos = (int)where.find (what, start);
		//could could not be found or is outside of search area 
		if (pos == (int)string::npos || (end!=-1 && pos>end)) 
			break;
		start = pos+1;
		counter++;
	}

	return counter;
}

// Find (with only or not in Strings option)
int Find (string where, string what, int start, int end, int instring)
{
	int pos = (int)where.find (what, start);

	//could could not be found or is outside of search area 
	if (pos == (int)string::npos || (end!=-1 && pos>end)) 
		return -1;

	// if the count of this quotes is eaven we are in string 
	int isInString = FindCount(where, "\"", start, pos)%2;

	// if so we go on searching 
    if(isInString == instring)
		return Find (where, what, pos+1, end, instring);

	return pos;

}

// Replace (using Find)
void Replace (string* String, string Old, string New, int start, int end, int instring)
{
	int pos = start;

	while(true)
	{
		pos = Find(String->c_str(), Old, pos, end, instring);
		if (pos == -1)
			break;

		String->replace (pos, Old.length(), New);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -