static void ParseUnion (void)
{
	const char	*name;
	type_t	*type;
	int	startFieldOffset;
	int	highestFieldOffset;

	LX_Require("{");
	startFieldOffset = pr.size_fields;
	highestFieldOffset = startFieldOffset;
	do
	{
		if (LX_CheckFetch("struct"))
		{
			pr.size_fields = startFieldOffset;
			LX_Require("{");
			do
			{
				type = ParseUnionType();
				do
				{
					name = PR_ParseName();
					PR_GetDef(type, name, pr_scope, true);
				} while (TK_CHECK(TK_COMMA));

				LX_Require(";");
			} while (pr_tokenclass != TK_RBRACE);

			LX_Require("}");
			LX_Require(";");
			if (pr.size_fields > highestFieldOffset)
			{
				highestFieldOffset = pr.size_fields;
			}
		}
		else
		{
			type = ParseUnionType();
			do
			{
				name = PR_ParseName();
				pr.size_fields = startFieldOffset;
				PR_GetDef(type, name, pr_scope, true);
				if (pr.size_fields > highestFieldOffset)
				{
					highestFieldOffset = pr.size_fields;
				}
			} while (TK_CHECK(TK_COMMA));

			LX_Require(";");
		}
	} while (pr_tokenclass != TK_RBRACE);

	LX_Require("}");
	LX_Require(";");
	pr.size_fields = highestFieldOffset;
}
static int ParseArray (const char *name, type_t *type)
{
	int		count;
	etype_t	t;

	t = type->type;
	if (t == ev_field)
	{
		t = type->aux_type->type;
	}
	if (t != ev_float && t != ev_vector && t != ev_string
		&& t != ev_entity && t != ev_function)
	{
		PR_ParseError("bad array type");
	}
	if (PR_GetDef(type, name, pr_scope, false) != NULL)
	{
		PR_ParseError("array redefinition");
	}
	if (pr_token_type != tt_immediate
		|| pr_immediate_type != &type_float
		|| pr_immediate._float != (int)pr_immediate._float)
	{
		PR_ParseError("subscript is not integral");
	}
	count = (int)pr_immediate._float;
	if (count < 1 || count > MAX_ARRAY_ELEMENTS)
	{
		PR_ParseError("bad subscript: %d", count);
	}
	LX_Fetch();
	LX_Require("]");
	return count;
}
Example #3
0
/*
============
PR_ParseImmediateStatements

Parse a function body
============
*/
function_t *PR_ParseImmediateStatements (type_t *type)
{
	int			i;
	function_t	*f;
	def_t		*defs[MAX_PARMS];
	
	f = malloc (sizeof(function_t));

//
// check for builtin function definition #1, #2, etc
//
	if (PR_Check ("#"))
	{
		if (pr_token_type != tt_immediate
		|| pr_immediate_type != &type_float
		|| pr_immediate._float != (int)pr_immediate._float)
			PR_ParseError ("Bad builtin immediate");
		f->builtin = (int)pr_immediate._float;
		PR_Lex ();
		return f;
	}
	
	f->builtin = 0;
//
// define the parms
//
	for (i=0 ; i<type->num_parms ; i++)
	{
		defs[i] = PR_GetDef (type->parm_types[i], pr_parm_names[i], pr_scope, true);
		f->parm_ofs[i] = defs[i]->ofs;
		if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1])
			Error ("bad parm order");
	}
	
	f->code = numstatements;

//
// check for a state opcode
//
	if (PR_Check ("["))
		PR_ParseState ();
		
//
// parse regular statements
//
	PR_Expect ("{");

	while (!PR_Check("}"))
		PR_ParseStatement ();
	
// emit an end of statements opcode
	PR_Statement (pr_opcodes, 0,0);


	return f;
}
Example #4
0
/*
============
PR_ParseValue

Returns the global ofs for the current token
============
*/
def_t	*PR_ParseValue (void)
{
	def_t		*d;
	char		*name;
	
// if the token is an immediate, allocate a constant for it
	if (pr_token_type == tt_immediate)
		return PR_ParseImmediate ();
	
	name = PR_ParseName ();
	
// look through the defs
	d = PR_GetDef (NULL, name, pr_scope, false);
	if (!d)
		PR_ParseError ("Unknown value \"%s\"", name);	
	return d;
}
Example #5
0
/*
==============
PR_ParseState

States are special functions made for convenience.  They automatically
set frame, nextthink (implicitly), and think (allowing forward definitions).

// void() name = [framenum, nextthink] {code}
// expands to:
// function void name ()
// {
//		self.frame=framenum;
//		self.nextthink = time + 0.1;
//		self.think = nextthink
//		<code>
// };
==============
*/
void PR_ParseState (void)
{
	char	*name;
	def_t	*s1, *def;
	
	if (pr_token_type != tt_immediate || pr_immediate_type != &type_float)
		PR_ParseError ("state frame must be a number");
	s1 = PR_ParseImmediate ();
	
	PR_Expect (",");

	name = PR_ParseName ();
	def = PR_GetDef (&type_function, name,0, true);
		
	PR_Expect ("]");
	
	PR_Statement (&pr_opcodes[OP_STATE], s1, def);
}
void CO_ParseDefs (void)
{
	int		i;
	const char	*name;
	def_t	*def;
	type_t	*type;
	int	elementCount;
	gofs_t	offset;

	type = PR_ParseType();

	if (type == &type_union)
	{
		if (pr_scope)
		{
			PR_ParseError("unions must be global");
		}
		ParseUnion();
		return;
	}

	if (pr_scope && (type->type == ev_field || type->type == ev_function))
	{
		PR_ParseError("fields and functions must be global");
	}

	do
	{
		name = PR_ParseName();
		if (TK_CHECK(TK_LPAREN))
		{
			ParseCStyleFunctionDef(name, type);
			return;
		}

		elementCount = 0;
		if (TK_CHECK(TK_LBRACKET))
		{
			def = GetArrayDef(name, type, &elementCount);
		}
		else
		{
			def = PR_GetDef(type, name, pr_scope, true);
		}

		// Check for initialization
		if (TK_CHECK(TK_ASSIGN))
		{
			if (def->initialized)
			{
				PR_ParseError("'%s' : redefinition", name);
			}
			if (type->type == ev_field)
			{
				PR_ParseError("fields cannot be initialized");
			}

			if (elementCount != 0)
			{
				LX_Require("{");
				i = 0;
				offset = def->ofs;
				do
				{
					if (pr_token_type != tt_immediate)
					{
						PR_ParseError("immediate type required for %s", name);
					}
					if (pr_immediate_type->type != type->type)
					{
						PR_ParseError("wrong immediate type for %s", name);
					}
					memcpy(pr_globals+offset, &pr_immediate, 4*type_size[pr_immediate_type->type]);
					offset += type_size[pr_immediate_type->type];
					i++;
					LX_Fetch();
				} while (TK_CHECK(TK_COMMA));

				LX_Require("}");
				if (i != elementCount)
				{
					PR_ParseError("element count mismatch in array"
							" initialization");
				}
				def->initialized = 1;
				continue;
			}
			else if (type->type == ev_function)
			{
				ParseFunctionDef(def, type);
				continue;
			}
			else if (pr_immediate_type != type)
			{
				PR_ParseError("wrong immediate type for %s", name);
			}
			def->initialized = 1;
			memcpy(pr_globals+def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
			LX_Fetch();
		}
		else if (elementCount != 0 && type->type != ev_field)
		{
			memset(pr_globals+def->ofs, 0, elementCount*4*type_size[type->type]);
			def->initialized = 1;
		}
	} while (TK_CHECK(TK_COMMA));

	LX_Require(";");
}
def_t *PR_GetDef (type_t *type, const char *name, def_t *scope, qboolean allocate)
{
	def_t	*def;
	def_t	*elementDef;
	char	element[MAX_NAME];
	char	key[100], *tmp;
	int			idx = 0;
	struct hash_element *cell = NULL;

	if (scope != NULL)
	{
		sprintf(key, "%s:%s", name, scope->name);
		idx = COM_Hash(key);
	}
	else
	{
		idx = COM_Hash(name);
	}

	for (cell = HashTable[idx]; cell != NULL; cell = cell->next)
	{
		def = cell->def;
		if (!STRCMP(def->name, name))
		{ // Found a match
			if (def->scope && def->scope != scope)
			{ // In a different function
				continue;
			}
			if (type && def->type != type)
			{ // Type mismatch
				PR_ParseError("type mismatch on redeclaration of %s", name);
			}
			return def;
		}
	}

	if (scope != NULL)
	{
		idx = COM_Hash(name);
		for (cell = HashTable[idx]; cell != NULL; cell = cell->next)
		{
			def = cell->def;
			if (!STRCMP(def->name, name))
			{ // Found a match
				if (def->scope && def->scope != scope)
				{ // In a different function
					continue;
				}
				if (type && def->type != type)
				{ // Type mismatch
					PR_ParseError("type mismatch on redeclaration of %s", name);
				}
				return def;
			}
		}
	}

	if (allocate == false)
	{
		return NULL;
	}

	// Allocate a new def
	def = (def_t *) malloc(sizeof(def_t));
	memset(def, 0, sizeof(*def));
	def->next = NULL;
	pr.def_tail->next = def;
	pr.def_tail = def;

	// Add to hash table
	cell = (struct hash_element *) malloc(sizeof(struct hash_element));
	cell->next = HashTable[idx];
	cell->def = def;
	HashTable[idx] = cell;

	tmp = (char *) malloc(strlen(name) + 1);
	strcpy(tmp, name);
	def->name = tmp;
	def->type = type;

	def->scope = scope;

	def->ofs = numpr_globals;
	pr_global_defs[numpr_globals] = def;

	if (type->type == ev_vector)
	{ // Create vector element defs
		sprintf(element, "%s_x", name);
		elementDef = PR_GetDef(&type_float, element, scope, true);
		elementDef->parentVector = def;
		sprintf(element, "%s_y", name);
		elementDef = PR_GetDef(&type_float, element, scope, true);
		elementDef->parentVector = def;
		sprintf(element, "%s_z", name);
		elementDef = PR_GetDef(&type_float, element, scope, true);
		elementDef->parentVector = def;
	}
	else
	{
		numpr_globals += type_size[type->type];
	}

	if (type->type == ev_field)
	{
		*(int *)&pr_globals[def->ofs] = pr.size_fields;
		if (type->aux_type->type == ev_vector)
		{ // Create vector element defs
			sprintf(element, "%s_x", name);
			PR_GetDef(&type_floatfield, element, scope, true);
			sprintf(element, "%s_y", name);
			PR_GetDef(&type_floatfield, element, scope, true);
			sprintf(element, "%s_z", name);
			PR_GetDef(&type_floatfield, element, scope, true);
		}
		else
		{
			pr.size_fields += type_size[type->aux_type->type];
		}
	}

	return def;
}
static function_t *ParseImmediateStatements (type_t *type)
{
	int		i;
	function_t	*f;
	def_t	*defs[MAX_PARMS];
	def_t	*scopeDef;
	def_t	*searchDef;

	f = (function_t *) malloc(sizeof(function_t));

	// Check for builtin function definition
	if (TK_CHECK(TK_COLON))
	{
		if (pr_token_type != tt_immediate
			|| pr_immediate_type != &type_float
			|| pr_immediate._float != (int)pr_immediate._float)
		{
			PR_ParseError("bad builtin immediate");
		}
		f->builtin = (int)pr_immediate._float;
		LX_Fetch();
		return f;
	}

	f->builtin = 0;

	// Define the parms
	for (i = 0; i < type->num_parms; i++)
	{
		defs[i] = PR_GetDef(type->parm_types[i], pr_parm_names[i], pr_scope, true);
		f->parm_ofs[i] = defs[i]->ofs;
		if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1])
		{
			PR_ParseError("bad parm order");
		}
	}

	f->code = numstatements;

	// Check for a state opcode
	if (TK_CHECK(TK_LBRACKET))
	{
		ParseState();
	}

	// Check for regular statements
	st_ReturnType = type->aux_type;
	st_ReturnParsed = false;
	if (TK_CHECK(TK_LBRACE))
	{
		scopeDef = pr_scope;
		searchDef = pr.def_tail;

		while (pr_tokenclass != TK_RBRACE)
		{
			ST_ParseStatement();
		}

		while ((searchDef = searchDef->next) != NULL)
		{
			if (searchDef->scope == scopeDef
				&& searchDef->referenceCount == 0
				&& searchDef->parentVector == NULL)
			{
				PR_ParseWarning("unreferenced local variable '%s'", searchDef->name);
			}
		}
		if (type->aux_type->type != ev_void && st_ReturnParsed == false)
		{
			PR_ParseError("missing return");
		}

		LX_Fetch();
	}
	else if (type->aux_type->type != ev_void && st_ReturnParsed == false)
	{
		PR_ParseError("missing return");
	}

	// Emit an end of statements opcode
	CO_GenCode(pr_opcodes, 0, 0);

	return f;
}
static void ParseState (void)
{
	const char	*name;
	def_t	*def;
	def_t	*s1, *s2;
	int	frame1, frame2;
	int	direction;
	qboolean	weapon;

	if (pr_token_type == tt_name)
	{
		FrameIndex++;

		// Stuff a float for CO_ParseImmediate()
		pr_token_type = tt_immediate;
		pr_immediate_type = &type_float;
		pr_immediate._float = (float)FrameIndex;
		s1 = CO_ParseImmediate();

		pr_token_type = tt_name;
		name = PR_ParseName();
		def = PR_GetDef(&type_function, name, 0, true);
		LX_Require("]");
		CO_GenCode(&pr_opcodes[OP_STATE], s1, def);
		return;
	}
	else if (pr_tokenclass == TK_INC || pr_tokenclass == TK_DEC)
	{
		direction = pr_tokenclass;
		weapon = false;
		LX_Fetch();
		if (TK_CHECK(TK_LPAREN))
		{
			if (LX_Check("w"))
			{
				LX_Fetch();
			}
			else
			{
				LX_Require("W");
			}
			LX_Require(")");
			weapon = true;
		}
		if (pr_token_type != tt_immediate
			|| pr_immediate_type != &type_float)
		{
			PR_ParseError("state frame must be a number");
		}
		frame1 = (int)pr_immediate._float;
		s1 = CO_ParseImmediate();
		LX_Fetch();
		LX_Require("..");
		if (pr_token_type != tt_immediate
			|| pr_immediate_type != &type_float)
		{
			PR_ParseError("state frame must be a number");
		}
		frame2 = (int)pr_immediate._float;
		s2 = CO_ParseImmediate();
		LX_Fetch();
		if (direction == TK_INC)
		{
			if (frame1 > frame2)
			{
				PR_ParseError("bad frame order in state cycle");
			}
		}
		else if (frame1 < frame2)
		{
			PR_ParseError("bad frame order in state cycle");
		}
		LX_Require("]");
		if (weapon == true)
		{
			CO_GenCode(&pr_opcodes[OP_CWSTATE], s1, s2);
		}
		else
		{
			CO_GenCode(&pr_opcodes[OP_CSTATE], s1, s2);
		}
		return;
	}

	if (pr_token_type != tt_immediate
		|| pr_immediate_type != &type_float)
	{
		PR_ParseError("state frame must be a number");
	}
	FrameIndex = (int)pr_immediate._float;
	s1 = CO_ParseImmediate();
	LX_Fetch();
	if (pr_tokenclass == TK_COMMA)
	{
		LX_Fetch();
	}
	name = PR_ParseName();
	def = PR_GetDef(&type_function, name, 0, true);

	LX_Require("]");
	CO_GenCode(&pr_opcodes[OP_STATE], s1, def);
}
Example #10
0
static void ParseCStyleFunctionDef (const char *funcName, type_t *type)
{
	int		i;
	const char	*name = NULL;	// FIXME: init to NULL, avoid compiler warning
	type_t	newType;
	type_t	*funcType;
	def_t	*def;
	function_t	*f;
	dfunction_t	*df;
	int	locals_start;
	char	funcIdent[MAX_NAME];
	int	initClass;

	strcpy(funcIdent, funcName);
	memset(&newType, 0, sizeof(newType));
	newType.type = ev_function;
	newType.aux_type = type; // Return type
	newType.num_parms = 0;
	if (!TK_CHECK(TK_RPAREN))
	{
		if (TK_CHECK(TK_ELLIPSIS))
		{ // Variable args
			newType.num_parms = -1;
		}
		else if (!LX_CheckFetch("void"))
		{
			do
			{
				type = PR_ParseType();
				name = PR_ParseName();
				strcpy(pr_parm_names[newType.num_parms], name);
				newType.parm_types[newType.num_parms] = type;
				newType.num_parms++;
			} while (TK_CHECK(TK_COMMA));
		}
		LX_Require(")");
	}

	funcType = PR_FindType(&newType);
	def = PR_GetDef(funcType, funcIdent, pr_scope, true);

	if (def->initialized)
	{
		PR_ParseError("%s redeclared", funcName);
	}

	if (TK_TEST(TK_LBRACE)
		|| TK_TEST(TK_LBRACKET)
		|| TK_TEST(TK_COLON))
	{
		initClass = pr_tokenclass;
		if (def->initialized)
		{
			PR_ParseError("%s redeclared", name);
		}
		locals_start = locals_end = numpr_globals;
		pr_scope = def;
		f = ParseImmediateStatements(funcType);
		pr_scope = NULL;
		def->initialized = 1;
		G_FUNCTION(def->ofs) = numfunctions;
		f->def = def;
		df = &functions[numfunctions];
		numfunctions++;
		if (f->builtin)
		{
			df->first_statement = -f->builtin;
			def->referenceCount++;
		}
		else
		{
			df->first_statement = f->code;
		}
		df->s_name = CopyString(f->def->name);
		df->s_file = s_file;
		df->numparms =  f->def->type->num_parms;
		df->locals = locals_end - locals_start;
		df->parm_start = locals_start;
		for (i = 0; i < df->numparms; i++)
		{
			df->parm_size[i] =
				type_size[f->def->type->parm_types[i]->type];
		}
		if (initClass == TK_COLON)
		{
			LX_Require(";");
		}
	}
	else
	{
		LX_Require(";");
	}
}
Example #11
0
/*
================
PR_ParseDefs

Called at the outer layer and when a local statement is hit
================
*/
void PR_ParseDefs (void)
{
	char		*name;
	type_t		*type;
	def_t		*def;
	function_t	*f;
	dfunction_t	*df;
	int			i;
	int			locals_start;

	type = PR_ParseType ();
	
	if (pr_scope && (type->type == ev_field || type->type == ev_function) )
		PR_ParseError ("Fields and functions must be global");
		
	do
	{
		name = PR_ParseName ();

		def = PR_GetDef (type, name, pr_scope, true);
		
// check for an initialization
		if ( PR_Check ("=") )
		{
			if (def->initialized)
				PR_ParseError ("%s redeclared", name);
	
			if (type->type == ev_function)
			{
				locals_start = locals_end = numpr_globals;
				pr_scope = def;
				f = PR_ParseImmediateStatements (type);
				pr_scope = NULL;
				def->initialized = 1;
				G_FUNCTION(def->ofs) = numfunctions;
				f->def = def;
//				if (pr_dumpasm)
//					PR_PrintFunction (def);

		// fill in the dfunction
				df = &functions[numfunctions];
				numfunctions++;
				if (f->builtin)
					df->first_statement = -f->builtin;
				else
					df->first_statement = f->code;
				df->s_name = CopyString (f->def->name);
				df->s_file = s_file;
				df->numparms =  f->def->type->num_parms;
				df->locals = locals_end - locals_start;
				df->parm_start = locals_start;
				for (i=0 ; i<df->numparms ; i++)
					df->parm_size[i] = type_size[f->def->type->parm_types[i]->type];
				
				continue;
			}
			else if (pr_immediate_type != type)
				PR_ParseError ("wrong immediate type for %s", name);
	
			def->initialized = 1;
			memcpy (pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
			PR_Lex ();
		}
		
	} while (PR_Check (","));

	PR_Expect (";");
}
Example #12
0
/*
============
PR_GetDef

If type is NULL, it will match any type
If allocate is true, a new def will be allocated if it can't be found
============
*/
def_t *PR_GetDef (type_t *type, char *name, def_t *scope, qboolean allocate)
{
	def_t		*def, **old;
	char element[MAX_NAME];

// see if the name is already in use
	old = &pr.search;
	for (def = *old ; def ; old=&def->search_next,def = *old)
		if (!strcmp(def->name,name) )
		{
			if ( def->scope && def->scope != scope)
				continue;		// in a different function
			
			if (type && def->type != type)
				PR_ParseError ("Type mismatch on redeclaration of %s",name);

			// move to head of list to find fast next time
			*old = def->search_next;
			def->search_next = pr.search;
			pr.search = def;
			return def;
		}
	
	if (!allocate)
		return NULL;
		
// allocate a new def
	def = malloc (sizeof(def_t));
	memset (def, 0, sizeof(*def));
	def->next = NULL;
	pr.def_tail->next = def;
	pr.def_tail = def;

	def->search_next = pr.search;
	pr.search = def;

	def->name = malloc (strlen(name)+1);
	strcpy (def->name, name);
	def->type = type;

	def->scope = scope;
	
	def->ofs = numpr_globals;
	pr_global_defs[numpr_globals] = def;

//
// make automatic defs for the vectors elements
// .origin can be accessed as .origin_x, .origin_y, and .origin_z
//
	if (type->type == ev_vector)
	{		
		sprintf (element, "%s_x",name);
		PR_GetDef (&type_float, element, scope, true);
		
		sprintf (element, "%s_y",name);
		PR_GetDef (&type_float, element, scope, true);
		
		sprintf (element, "%s_z",name);
		PR_GetDef (&type_float, element, scope, true);
	}
	else
		numpr_globals += type_size[type->type];

	if (type->type == ev_field)
	{
		*(int *)&pr_globals[def->ofs] = pr.size_fields;
		
		if (type->aux_type->type == ev_vector)
		{
			sprintf (element, "%s_x",name);
			PR_GetDef (&type_floatfield, element, scope, true);
			
			sprintf (element, "%s_y",name);
			PR_GetDef (&type_floatfield, element, scope, true);
			
			sprintf (element, "%s_z",name);
			PR_GetDef (&type_floatfield, element, scope, true);
		}
		else
			pr.size_fields += type_size[type->aux_type->type];
	}

//	if (pr_dumpasm)
//		PR_PrintOfs (def->ofs);
		
	return def;
}
Example #13
0
void WriteData (int crc)
{
	def_t		*def;
	ddef_t		*dd;
	dprograms_t	progs;
	char tname[1024];
	int			h;
	unsigned int			i;
	int size;

	for (def = pr.def_head.next ; def ; def = def->next)
	{
		if ((def->type->type == ev_field) && def->constant)
		{
			dd = &fields[numfielddefs];
			numfielddefs++;
			dd->type = def->type->aux_type->type == ev_int ? ev_float : def->type->aux_type->type;
			if (def->save == 0)
			{
					strcpy(tname, def->name);
					strcat(tname, "__");
					dd->s_name = CopyString(tname, 0);
			}
			else 
				dd->s_name = CopyString (def->name, 0);
			dd->ofs = G_INT(def->ofs);
		}
		else if (pr_optimize_constant_names && def->constant && (def->type->type != ev_function))
		{
			num_constant_names += strlen(def->name) + 1;
			num_constant_names += sizeof(ddef_t);
			continue;
		}
		else if (pr_optimize_unreferenced && pr_global_refs[def->ofs] <= 0)
		{
			if (!(def->type->type != ev_function))
			{
				num_unreferenced += 1;
				continue;
			}
		}
		else if (pr_optimize_unreferenced && def->type->type == ev_vector)
		{

			if (pr_global_refs[def->ofs] + pr_global_refs[def->ofs + 1] + pr_global_refs[def->ofs +1] == 3)
			{
				num_unreferenced += 3;
				def = def->next; // def_x
				def = def->next; // def_y
				def = def->next; // def_z
				continue;
			}
		}
		dd = &globals[numglobaldefs];
		dd->type = def->type->type == ev_int ? ev_float : def->type->type;
		if (def->save && ( dd->type != ev_field || def->constant != 1))
			dd->type |= DEF_SAVEGLOBAL;
		if (def->name)
		{
			if (pr_optimize_locals && (def->scope || !(STRCMP(def->name, "IMMEDIATE"))))
			{
				num_locals_saved += strlen(def->name);
				dd->s_name = 0;
			}
			else
				dd->s_name = CopyString (def->name, 0);
		}

		dd->ofs = def->ofs;
		numglobaldefs++;
	}
	strofs = (strofs+3)&~3;
	if (strofs > INT_MAX)
		PR_ParseWarning(122, "strofs exceeds INT_MAX by %i", strofs - INT_MAX);
	if (numstatements > INT_MAX)
		PR_ParseWarning(123, "numstatements exceeds INT_MAX by %i", numstatements - INT_MAX);
	if (numfunctions > SHRT_MAX)
		PR_ParseWarning(124, "numfunctions exceeds SHRT_MAX by %i", numfunctions - SHRT_MAX);
	if (numglobaldefs > SHRT_MAX)
		PR_ParseWarning(125, "numglobaldefs exceeds SHRT_MAX by %i", numglobaldefs - SHRT_MAX);
	if (numfielddefs > SHRT_MAX)
		PR_ParseWarning(126, "numfielddefs exceeds SHRT_MAX by %i", numfielddefs - SHRT_MAX);
	if (numpr_globals > SHRT_MAX)
		PR_ParseWarning(127, "numpr_globals exceeds SHRT_MAX by %i", numpr_globals - SHRT_MAX);
	if (crc != NQ_PROGHEADER_CRC && crc != QW_PROGHEADER_CRC)
		PR_ParseWarning(208, "System defs do match internal crcs.");
	if (summary)
	{

		summary_print("----------- Summary -----------\n");

		i = I_FloatTime() - StartTime;
		summary_print (" %02i:%02i elapsed time\n", (i / 60) % 59, i % 59);
		summary_print ("%6i strofs         (MAX: %6i)\n", strofs, MAX_STRINGS	);
		summary_print ("%6i numstatements  (MAX: %6i)\n", numstatements, MAX_STATEMENTS);
		summary_print ("%6i numfunctions   (MAX: %6i)\n", numfunctions, SHRT_MAX);
		summary_print ("%6i numglobaldefs  (MAX: %6i)\n", numglobaldefs, SHRT_MAX);
		summary_print ("%6i numfielddefs   (MAX: %6i)\n", numfielddefs, SHRT_MAX);
		summary_print ("%6i numpr_globals  (MAX: %6i)\n", numpr_globals, SHRT_MAX);
	}
	h = SafeOpenWrite (destfile);
	SafeWrite (h, &progs, sizeof(progs));

	progs.ofs_strings = lseek (h, 0, SEEK_CUR);
	progs.numstrings = strofs;
	SafeWrite (h, strings, strofs);

	progs.ofs_statements = lseek (h, 0, SEEK_CUR);
	progs.numstatements = numstatements;
	for (i=0 ; i<numstatements ; i++)
	{
		statements[i].op = LittleShort(statements[i].op);
		statements[i].a = LittleShort(statements[i].a);
		statements[i].b = LittleShort(statements[i].b);
		statements[i].c = LittleShort(statements[i].c);
	}
	SafeWrite (h, statements, numstatements*sizeof(dstatement_t));

	progs.ofs_functions = lseek (h, 0, SEEK_CUR);
	progs.numfunctions = numfunctions;
	for (i=0 ; i<numfunctions ; i++)
	{
		functions[i].first_statement = LittleLong (functions[i].first_statement);
		functions[i].parm_start = LittleLong (functions[i].parm_start);
		functions[i].s_name = LittleLong (functions[i].s_name < 0 || functions[i].s_name > strofs ? 0 : functions[i].s_name);
		functions[i].s_file = LittleLong (functions[i].s_file < 0 || functions[i].s_file > strofs ? 0 : functions[i].s_file);
		functions[i].numparms = LittleLong (functions[i].numparms > MAX_PARMS ? MAX_PARMS : functions[i].numparms);
		functions[i].locals = LittleLong (functions[i].locals);
	}	
	SafeWrite (h, functions, numfunctions*sizeof(dfunction_t));

	progs.ofs_globaldefs = lseek (h, 0, SEEK_CUR);
	progs.numglobaldefs = numglobaldefs;
	for (i=0 ; i<numglobaldefs ; i++)
	{
		globals[i].type = LittleShort (globals[i].type);
		globals[i].ofs = LittleShort (globals[i].ofs);
		globals[i].s_name = LittleLong (globals[i].s_name);
	}
	SafeWrite (h, globals, numglobaldefs*sizeof(ddef_t));

	progs.ofs_fielddefs = lseek (h, 0, SEEK_CUR);
	progs.numfielddefs = numfielddefs;
	for (i=0 ; i<numfielddefs ; i++)
	{
		fields[i].type = LittleShort (fields[i].type);
		fields[i].ofs = LittleShort (fields[i].ofs);
		fields[i].s_name = LittleLong (fields[i].s_name < 0 || fields[i].s_name > strofs ? 0: fields[i].s_name);
	}
	SafeWrite (h, fields, numfielddefs*sizeof(ddef_t));

	progs.ofs_globals = lseek (h, 0, SEEK_CUR);
	progs.numglobals = numpr_globals;
	for (i=0 ; i<numpr_globals ; i++)
		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
	SafeWrite (h, pr_globals, numpr_globals*4);

	i = (int)lseek(h, 0, SEEK_CUR);
	if (summary)
		summary_print ("%6i TOTAL SIZE\n", i);	
	size = (i+16)&(~15);
	progs.entityfields = pr.size_fields;

	progs.version = PROG_VERSION;
	progs.crc = crc;
	if (summary)
	{
		summary_print("%6i Progheader CRC ", crc);
		if (crc == NQ_PROGHEADER_CRC)
			summary_print("(   Quake   )\n");
		else if (crc == QW_PROGHEADER_CRC)
			summary_print("(Quake World)\n");
		else
			summary_print("(  UNKNOWN  )\n");
	}

// byte swap the header and write it out
	for (i=0 ; i<sizeof(progs)/4 ; i++)
		((int *)&progs)[i] = LittleLong ( ((int *)&progs)[i] );		
	lseek (h, 0, SEEK_SET);
	SafeWrite (h, &progs, sizeof(progs));

// look for progs
	if ((def = PR_GetDef(&type_entity, "progs", NULL, false, 0, 0)))
	{
		lseek(h, progs.ofs_globals + 4 * def->ofs, SEEK_SET);
		i = - (size + 112);
		SafeWrite (h, &i, 4);
	}

	for (def = pr.def_head.next ; def ; def = def->next)
	{
		if (def->type->arraysize)
		{
			lseek(h, progs.ofs_globals + 4 * def->ofs, SEEK_SET);
			i = (-(size + 112)) + progs.ofs_globals + 4 * (def->arraystart);
			//printf("filled in %s with %i\n", def->name, def->arraystart);
			SafeWrite (h, &i, 4);		
		}
	}
	if (summary)
	{
		summary_print ("%6i precache_sounds(MAX: %6i)\n", numsounds, MAX_SOUNDS);
		summary_print ("%6i precache_models(MAX: %6i)\n", nummodels, MAX_MODELS);
	}
	close (h);
	
	if (summary)
	{
		if (pr_optimize_eliminate_temps || pr_optimize_shorten_ifs || pr_optimize_nonvec_parms
			|| pr_optimize_constant_names || pr_optimize_defs || pr_optimize_hash_strings ||
			pr_optimize_locals || pr_optimize_function_names || pr_optimize_filenames ||
			pr_optimize_unreferenced || pr_optimize_logicops || pr_optimize_recycle
			|| pr_optimize_constant_arithmetic) 
		{
			summary_print("----------- Optimization Summary -----------\n");
			if (pr_optimize_eliminate_temps)
				summary_print("%d stores shortened\n", num_stores_shortened);
			if (pr_optimize_shorten_ifs)
				summary_print("%d ifs shortened\n", num_ifs_shortened);
			if (pr_optimize_nonvec_parms)
				summary_print("%d non-vector parms\n", num_nonvec_parms);
			if (pr_optimize_constant_names)
				summary_print("%d bytes of constant defs/names eliminated\n", num_constant_names);
			if (pr_optimize_defs)
				summary_print("%d duplicate defs eliminated\n", num_defs);
			if (pr_optimize_hash_strings)
				summary_print("%d bytes of duplicate strings eliminated\n", num_strings);
			if (pr_optimize_locals)
				summary_print("%d bytes of immediate and local names eliminated\n", num_locals_saved);
			if (pr_optimize_function_names)
				summary_print("%d bytes of function names eliminated\n", num_funcs_saved);
			if (pr_optimize_filenames)
				summary_print("%d bytes of filenames eliminated\n", num_files_saved);
			if (pr_optimize_unreferenced)
				summary_print("%d unreferenced global defs eliminated\n", num_unreferenced);
			if (pr_optimize_logicops)
				summary_print("%d logic jumps added\n", num_logic_jumps);
			if (pr_optimize_recycle)
				summary_print("%d temporary globals recycled\n", num_recycled);
			if (pr_optimize_constant_arithmetic)
				summary_print("%d constant arithmetic statements eliminated\n", num_constant_ops_saved);
		}
	}
}
Example #14
0
/*
============
PR_GetDef

A new def will be allocated if it can't be found
============
*/
def_t *PR_GetDef (type_t *type, char *name, def_t *scope, def_t *visscope, bool isParm)
{
	def_t	*def;
	char	element[MAX_NAME];
	int		hash;

	hash = Com_HashKey (name);

// see if the name is already in use
	def = PR_FindDef2 (name, scope, hash);

	if (def) {
		if (def->scope != scope) {
			if (!opt_idcomp)
				goto allocNew;		// a local def overrides global (ok)
			else
				PR_Warning (WARN_HIGH, "'%s' already declared on global scope", name);
		}

		if (def->type != type)
			PR_ParseError ("type mismatch on redeclaration of %s", name);

		if (def->isParm && !isParm)
			if (!opt_idcomp)
				PR_ParseError ("redefinition of formal parameter '%s'", name);
			else
				PR_Warning (WARN_HIGH, "redefinition of formal parameter '%s'", name);

		// fixup visibility scope
		if (def->visscope)
			def->visscope = visscope;

		return def;
	}

// allocate a new def
allocNew:
	def = PR_NewDef (hash);

	def->name = (char *) malloc (strlen(name)+1);
	strcpy (def->name, name);
	def->type = type;
	def->isParm = isParm;
	def->scope = scope;
	def->visscope = visscope;

	if (numpr_globals + type_size[type->type] > MAX_REGS)
		Error ("numpr_globals > MAX_REGS");

	def->ofs = numpr_globals;
	pr_global_defs[numpr_globals] = def;

//
// make automatic defs for the vectors elements
// .origin can be accessed as .origin_x, .origin_y, and .origin_z
//
	if (type->type == ev_vector)
	{
		sprintf (element, "%s_x",name);
		PR_GetDef (&type_float, element, scope, visscope, isParm);

		sprintf (element, "%s_y",name);
		PR_GetDef (&type_float, element, scope, visscope, isParm);

		sprintf (element, "%s_z",name);
		PR_GetDef (&type_float, element, scope, visscope, isParm);
	}
	else
		numpr_globals += type_size[type->type];

	if (type->type == ev_field)
	{
		assert (scope == NULL && visscope == NULL);

		*(int *)&pr_globals[def->ofs] = pr.size_fields;

		if (type->aux_type->type == ev_vector)
		{
			sprintf (element, "%s_x",name);
			PR_GetDef (&type_floatfield, element, NULL, NULL, isParm);

			sprintf (element, "%s_y",name);
			PR_GetDef (&type_floatfield, element, NULL, NULL, isParm);

			sprintf (element, "%s_z",name);
			PR_GetDef (&type_floatfield, element, NULL, NULL, isParm);
		}
		else
			pr.size_fields += type_size[type->aux_type->type];
	}

	if (opt_dumpasm)
		PR_PrintOfs (def->ofs);

	return def;
}
Example #15
0
/*
================
PR_ParseDefs

Called at the outer layer and when a local statement is hit
================
*/
void PR_ParseDefs (void)
{
	type_t *type = PR_ParseType ();

	if (pr_scope && type->type == ev_field)
		PR_ParseError ("'%s': local field definitions are illegal", pr_token);

	int	c_defs = 0;
	bool qc_style_function_def = false;

	// functions are always global
	def_t *defscope = (type->type == ev_function) ? NULL : pr_scope;

	do
	{
		char *name = PR_ParseName ();

		if (type->type != ev_function && PR_Check("(")) {
			// C-style function declaration

			char functionName[MAX_NAME];

			if (strlen(name) >= (size_t)MAX_NAME)
				PR_ParseError ("name of function \"%s\" is too long (max. %d chars)", name, (int)(MAX_NAME - 1));

			strcpy (functionName, name);

			type_t *functionType = PR_ParseFunctionType (type);

			def_t *def = PR_GetDef (functionType, functionName, NULL, pr_scope);

			if ((!c_defs && !strcmp(pr_token, "{")) || PR_Check("=")) {
				// C-style function definition (including builtin function definition #1, #2, etc.)
				PR_ParseFunctionBody (functionType, functionName, def);
				while (PR_Check(";"))
					;	// skip redundant semicolons
				return;
			}

			continue;
		}

		def_t *def = PR_GetDef (type, name, defscope, pr_scope);

		if (type->type == ev_void) {
			// end_sys_globals and end_sys_fields are special flags for structure dumping
			if (strcmp(name, "end_sys_globals") && strcmp(name, "end_sys_fields"))
				PR_ParseError ("'%s' : illegal use of type 'void'", name);
		}

		// check for an initialization
		if (PR_Check("=")) {
			if (type->type == ev_function) {
				// QuakeC-style function definition
				qc_style_function_def = true;
				PR_ParseFunctionBody (type, name, def);
			}
			else
				// variable initialization
				PR_ParseInitialization (type, name, def);
		}

	} while (c_defs++, PR_Check (","));

	if (qc_style_function_def && c_defs == 1)
		;	// allow void() func = {} without semicolon
	else
		PR_Expect (";");

	while (PR_Check(";"))
		;	// skip redundant semicolons
}