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

📄 l_script.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

Quake III Arena source code 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.

Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

/*****************************************************************************
 * name:		l_script.c
 *
 * desc:		lexicographical parser
 *
 * $Archive: /MissionPack/code/botlib/l_script.c $
 *
 *****************************************************************************/

//#define SCREWUP
//#define BOTLIB
//#define MEQCC
//#define BSPC

#ifdef SCREWUP
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
#include "l_memory.h"
#include "l_script.h"

typedef enum {qfalse, qtrue}	qboolean;

#endif //SCREWUP

#ifdef BOTLIB
//include files for usage in the bot library
#include "../game/q_shared.h"
#include "../game/botlib.h"
#include "be_interface.h"
#include "l_script.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_libvar.h"
#endif //BOTLIB

#ifdef MEQCC
//include files for usage in MrElusive's QuakeC Compiler
#include "qcc.h"
#include "l_script.h"
#include "l_memory.h"
#include "l_log.h"

#define qtrue	true
#define qfalse	false
#endif //MEQCC

#ifdef BSPC
//include files for usage in the BSP Converter
#include "../bspc/qbsp.h"
#include "../bspc/l_log.h"
#include "../bspc/l_mem.h"

#define qtrue	true
#define qfalse	false
#endif //BSPC


#define PUNCTABLE

//longer punctuations first
punctuation_t default_punctuations[] =
{
	//binary operators
	{">>=",P_RSHIFT_ASSIGN, NULL},
	{"<<=",P_LSHIFT_ASSIGN, NULL},
	//
	{"...",P_PARMS, NULL},
	//define merge operator
	{"##",P_PRECOMPMERGE, NULL},
	//logic operators
	{"&&",P_LOGIC_AND, NULL},
	{"||",P_LOGIC_OR, NULL},
	{">=",P_LOGIC_GEQ, NULL},
	{"<=",P_LOGIC_LEQ, NULL},
	{"==",P_LOGIC_EQ, NULL},
	{"!=",P_LOGIC_UNEQ, NULL},
	//arithmatic operators
	{"*=",P_MUL_ASSIGN, NULL},
	{"/=",P_DIV_ASSIGN, NULL},
	{"%=",P_MOD_ASSIGN, NULL},
	{"+=",P_ADD_ASSIGN, NULL},
	{"-=",P_SUB_ASSIGN, NULL},
	{"++",P_INC, NULL},
	{"--",P_DEC, NULL},
	//binary operators
	{"&=",P_BIN_AND_ASSIGN, NULL},
	{"|=",P_BIN_OR_ASSIGN, NULL},
	{"^=",P_BIN_XOR_ASSIGN, NULL},
	{">>",P_RSHIFT, NULL},
	{"<<",P_LSHIFT, NULL},
	//reference operators
	{"->",P_POINTERREF, NULL},
	//C++
	{"::",P_CPP1, NULL},
	{".*",P_CPP2, NULL},
	//arithmatic operators
	{"*",P_MUL, NULL},
	{"/",P_DIV, NULL},
	{"%",P_MOD, NULL},
	{"+",P_ADD, NULL},
	{"-",P_SUB, NULL},
	{"=",P_ASSIGN, NULL},
	//binary operators
	{"&",P_BIN_AND, NULL},
	{"|",P_BIN_OR, NULL},
	{"^",P_BIN_XOR, NULL},
	{"~",P_BIN_NOT, NULL},
	//logic operators
	{"!",P_LOGIC_NOT, NULL},
	{">",P_LOGIC_GREATER, NULL},
	{"<",P_LOGIC_LESS, NULL},
	//reference operator
	{".",P_REF, NULL},
	//seperators
	{",",P_COMMA, NULL},
	{";",P_SEMICOLON, NULL},
	//label indication
	{":",P_COLON, NULL},
	//if statement
	{"?",P_QUESTIONMARK, NULL},
	//embracements
	{"(",P_PARENTHESESOPEN, NULL},
	{")",P_PARENTHESESCLOSE, NULL},
	{"{",P_BRACEOPEN, NULL},
	{"}",P_BRACECLOSE, NULL},
	{"[",P_SQBRACKETOPEN, NULL},
	{"]",P_SQBRACKETCLOSE, NULL},
	//
	{"\\",P_BACKSLASH, NULL},
	//precompiler operator
	{"#",P_PRECOMP, NULL},
#ifdef DOLLAR
	{"$",P_DOLLAR, NULL},
#endif //DOLLAR
	{NULL, 0}
};

#ifdef BSPC
char basefolder[MAX_PATH];
#else
char basefolder[MAX_QPATH];
#endif

//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations)
{
	int i;
	punctuation_t *p, *lastp, *newp;

	//get memory for the table
	if (!script->punctuationtable) script->punctuationtable = (punctuation_t **)
												GetMemory(256 * sizeof(punctuation_t *));
	Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *));
	//add the punctuations in the list to the punctuation table
	for (i = 0; punctuations[i].p; i++)
	{
		newp = &punctuations[i];
		lastp = NULL;
		//sort the punctuations in this table entry on length (longer punctuations first)
		for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next)
		{
			if (strlen(p->p) < strlen(newp->p))
			{
				newp->next = p;
				if (lastp) lastp->next = newp;
				else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
				break;
			} //end if
			lastp = p;
		} //end for
		if (!p)
		{
			newp->next = NULL;
			if (lastp) lastp->next = newp;
			else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
		} //end if
	} //end for
} //end of the function PS_CreatePunctuationTable
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
char *PunctuationFromNum(script_t *script, int num)
{
	int i;

	for (i = 0; script->punctuations[i].p; i++)
	{
		if (script->punctuations[i].n == num) return script->punctuations[i].p;
	} //end for
	return "unkown punctuation";
} //end of the function PunctuationFromNum
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void QDECL ScriptError(script_t *script, char *str, ...)
{
	char text[1024];
	va_list ap;

	if (script->flags & SCFL_NOERRORS) return;

	va_start(ap, str);
	vsprintf(text, str, ap);
	va_end(ap);
#ifdef BOTLIB
	botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text);
#endif //BOTLIB
#ifdef MEQCC
	printf("error: file %s, line %d: %s\n", script->filename, script->line, text);
#endif //MEQCC
#ifdef BSPC
	Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text);
#endif //BSPC
} //end of the function ScriptError
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void QDECL ScriptWarning(script_t *script, char *str, ...)
{
	char text[1024];
	va_list ap;

	if (script->flags & SCFL_NOWARNINGS) return;

	va_start(ap, str);
	vsprintf(text, str, ap);
	va_end(ap);
#ifdef BOTLIB
	botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text);
#endif //BOTLIB
#ifdef MEQCC
	printf("warning: file %s, line %d: %s\n", script->filename, script->line, text);
#endif //MEQCC
#ifdef BSPC
	Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text);
#endif //BSPC
} //end of the function ScriptWarning
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void SetScriptPunctuations(script_t *script, punctuation_t *p)
{
#ifdef PUNCTABLE
	if (p) PS_CreatePunctuationTable(script, p);
	else  PS_CreatePunctuationTable(script, default_punctuations);
#endif //PUNCTABLE
	if (p) script->punctuations = p;
	else script->punctuations = default_punctuations;
} //end of the function SetScriptPunctuations
//============================================================================
// Reads spaces, tabs, C-like comments etc.
// When a newline character is found the scripts line counter is increased.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadWhiteSpace(script_t *script)
{
	while(1)
	{
		//skip white space
		while(*script->script_p <= ' ')
		{
			if (!*script->script_p) return 0;
			if (*script->script_p == '\n') script->line++;
			script->script_p++;
		} //end while
		//skip comments
		if (*script->script_p == '/')
		{
			//comments //
			if (*(script->script_p+1) == '/')
			{
				script->script_p++;
				do
				{
					script->script_p++;
					if (!*script->script_p) return 0;
				} //end do
				while(*script->script_p != '\n');
				script->line++;
				script->script_p++;
				if (!*script->script_p) return 0;
				continue;
			} //end if
			//comments /* */
			else if (*(script->script_p+1) == '*')
			{
				script->script_p++;
				do
				{
					script->script_p++;
					if (!*script->script_p) return 0;
					if (*script->script_p == '\n') script->line++;
				} //end do
				while(!(*script->script_p == '*' && *(script->script_p+1) == '/'));
				script->script_p++;
				if (!*script->script_p) return 0;
				script->script_p++;
				if (!*script->script_p) return 0;
				continue;
			} //end if
		} //end if
		break;
	} //end while
	return 1;
} //end of the function PS_ReadWhiteSpace
//============================================================================
// Reads an escape character.
//
// Parameter:				script		: script to read from
//								ch				: place to store the read escape character
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadEscapeCharacter(script_t *script, char *ch)
{
	int c, val, i;

	//step over the leading '\\'
	script->script_p++;
	//determine the escape character
	switch(*script->script_p)
	{
		case '\\': c = '\\'; break;
		case 'n': c = '\n'; break;
		case 'r': c = '\r'; break;
		case 't': c = '\t'; break;
		case 'v': c = '\v'; break;
		case 'b': c = '\b'; break;
		case 'f': c = '\f'; break;
		case 'a': c = '\a'; break;
		case '\'': c = '\''; break;
		case '\"': c = '\"'; break;
		case '\?': c = '\?'; break;
		case 'x':
		{
			script->script_p++;
			for (i = 0, val = 0; ; i++, script->script_p++)
			{
				c = *script->script_p;
				if (c >= '0' && c <= '9') c = c - '0';
				else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
				else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
				else break;
				val = (val << 4) + c;
			} //end for
			script->script_p--;
			if (val > 0xFF)
			{
				ScriptWarning(script, "too large value in escape character");
				val = 0xFF;
			} //end if
			c = val;
			break;
		} //end case
		default: //NOTE: decimal ASCII code, NOT octal
		{
			if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char");
			for (i = 0, val = 0; ; i++, script->script_p++)
			{
				c = *script->script_p;
				if (c >= '0' && c <= '9') c = c - '0';
				else break;
				val = val * 10 + c;
			} //end for
			script->script_p--;
			if (val > 0xFF)
			{
				ScriptWarning(script, "too large value in escape character");
				val = 0xFF;
			} //end if
			c = val;
			break;
		} //end default
	} //end switch
	//step over the escape character or the last digit of the number
	script->script_p++;
	//store the escape character
	*ch = c;
	//succesfully read escape character
	return 1;
} //end of the function PS_ReadEscapeCharacter
//============================================================================
// Reads C-like string. Escape characters are interpretted.
// Quotes are included with the string.
// Reads two strings with a white space between them as one string.
//
// Parameter:				script		: script to read from
//								token			: buffer to store the string
// Returns:					qtrue when a string was read succesfully
// Changes Globals:		-
//============================================================================
int PS_ReadString(script_t *script, token_t *token, int quote)
{
	int len, tmpline;
	char *tmpscript_p;

	if (quote == '\"') token->type = TT_STRING;
	else token->type = TT_LITERAL;

	len = 0;
	//leading quote
	token->string[len++] = *script->script_p++;
	//
	while(1)
	{
		//minus 2 because trailing double quote and zero have to be appended
		if (len >= MAX_TOKEN - 2)
		{
			ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN);
			return 0;
		} //end if
		//if there is an escape character and
		//if escape characters inside a string are allowed
		if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS))
		{
			if (!PS_ReadEscapeCharacter(script, &token->string[len]))
			{
				token->string[len] = 0;
				return 0;
			} //end if
			len++;
		} //end if
		//if a trailing quote
		else if (*script->script_p == quote)
		{
			//step over the double quote
			script->script_p++;
			//if white spaces in a string are not allowed
			if (script->flags & SCFL_NOSTRINGWHITESPACES) break;
			//
			tmpscript_p = script->script_p;
			tmpline = script->line;
			//read unusefull stuff between possible two following strings

⌨️ 快捷键说明

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