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;
}
Exemple #2
0
void PR_Expect (char *string, token_type_t type)
{
	if (STRCMP(string, pr_token))
		PR_ParseError (550, "Expected %s, found %s",string, pr_token);
	if (type)
		if (pr_token_type != type)
			PR_ParseError (550, "Expected %s, found %s",string, pr_token);
	PR_Lex ();
} 
Exemple #3
0
/*
============
PR_ParseFunctionCall
============
*/
def_t *PR_ParseFunctionCall (def_t *func)
{
	def_t		*e;
	int			arg;
	type_t		*t;
	
	t = func->type;

	if (t->type != ev_function)
		PR_ParseError ("not a function");
	
// copy the arguments to the global parameter variables
	arg = 0;
	if (!PR_Check(")"))
	{
		do
		{
			if (t->num_parms != -1 && arg >= t->num_parms)
				PR_ParseError ("too many parameters");
			e = PR_Expression (TOP_PRIORITY);

			if (arg == 0 && func->name)
			{
			// save information for model and sound caching
				if (!strncmp(func->name,"precache_sound", 14))
					PrecacheSound (e, func->name[14]);
				else if (!strncmp(func->name,"precache_model", 14))
					PrecacheModel (e, func->name[14]);
				else if (!strncmp(func->name,"precache_file", 13))
					PrecacheFile (e, func->name[13]);
			}
						
			if (t->num_parms != -1 && ( e->type != t->parm_types[arg] ) )
				PR_ParseError ("type mismatch on parm %i", arg);
		// a vector copy will copy everything
			def_parms[arg].type = t->parm_types[arg];
			PR_Statement (&pr_opcodes[OP_STORE_V], e, &def_parms[arg]);
			arg++;
		} while (PR_Check (","));
	
		if (t->num_parms != -1 && arg != t->num_parms)
			PR_ParseError ("too few parameters");
		PR_Expect (")");
	}
	if (arg >8)
		PR_ParseError ("More than eight parameters");
		

	PR_Statement (&pr_opcodes[OP_CALL0+arg], func, 0);
	
	def_ret.type = t->aux_type;
	return &def_ret;
}
Exemple #4
0
/*
============
PR_ParseName

Checks to see if the current token is a valid name
============
*/
char *PR_ParseName (void)
{
	static char	ident[MAX_NAME];
	
	if (pr_token_type != tt_name)
		PR_ParseError ("not a name");
	if (strlen(pr_token) >= MAX_NAME-1)
		PR_ParseError ("name too long");
	strcpy (ident, pr_token);
	PR_Lex ();
	
	return ident;
}
Exemple #5
0
/*
==============
PR_LexPunctuation
==============
*/
void PR_LexPunctuation (void)
{
	int		i;
	int		len;
	char	*p;
	
	pr_token_type = tt_punct;
	
	for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
	{
		len = strlen(p);
		if (!strncmp(p, pr_file_p, len) )
		{
			strcpy (pr_token, p);
			if (p[0] == '{')
				pr_bracelevel++;
			else if (p[0] == '}')
				pr_bracelevel--;
			pr_file_p += len;
			return;
		}
	}
	
	PR_ParseError ("Unknown punctuation");
}
Exemple #6
0
/*
==============
PR_LexGrab

Deals with counting sequence numbers and replacing frame macros
==============
*/
void PR_LexGrab (void)
{	
	pr_file_p++;	// skip the $
	if (!PR_SimpleGetToken ())
		PR_ParseError ("hanging $");
	
// check for $frame
	if (!strcmp (pr_token, "frame"))
	{
		PR_ParseFrame ();
		PR_Lex ();
	}
// ignore other known $commands
	else if (!strcmp (pr_token, "cd")
	|| !strcmp (pr_token, "origin")
	|| !strcmp (pr_token, "base")
	|| !strcmp (pr_token, "flags")
	|| !strcmp (pr_token, "scale")
	|| !strcmp (pr_token, "skin") )
	{	// skip to end of line
		while (PR_SimpleGetToken ())
		;
		PR_Lex ();
	}
// look for a frame name macro
	else
		PR_FindMacro ();
}
static void ParseCase (void)
{
	def_t	*e;
	def_t	*e2;

	do
	{
		e = EX_Expression(TOP_PRIORITY);
		if (TK_CHECK(TK_RANGE))
		{
			e2 = EX_Expression(TOP_PRIORITY);
			if (e->type->type != ev_float || e2->type->type != ev_float)
			{
				PR_ParseError("type mismatch for case range");
			}
		}
		else
		{
			e2 = NULL;
		}
		AddCase(e->type->type, e, e2, false);
	} while (TK_CHECK(TK_COMMA));

	LX_Require(":");
}
Exemple #8
0
type_t *PR_ParseFunctionType (type_t *returnType)
{
	type_t	newtype;
	memset (&newtype, 0, sizeof(newtype));
	newtype.type = ev_function;
	newtype.aux_type = returnType;
	newtype.num_parms = 0;

	if (PR_Check (")")) {
		// empty args
		return PR_GetType (&newtype);
	}

	do {
		if (PR_Check ("...")) {
			// variable args
			PR_Expect (")");
			newtype.num_parms |= VA_BIT;
			return PR_GetType (&newtype);
		}

		if (newtype.num_parms >= MAX_PARMS)
			PR_ParseError ("too many parameters (max. %d allowed)", (int)MAX_PARMS);

		type_t *type = PR_ParseType ();
		char *name = PR_ParseName ();
		strlcpy (pr_parm_names[newtype.num_parms], name, sizeof(pr_parm_names[newtype.num_parms]));
		newtype.parm_types[newtype.num_parms] = type;
		newtype.num_parms++;
	} while (PR_Check (","));

	PR_Expect (")");

	return PR_GetType(&newtype);
}
Exemple #9
0
void 
PR_Expect(char *string)
{
    if (DefCmp(string, pr_token))
	PR_ParseError("expected %s, found %s", string, pr_token);
    PR_Lex();
}
const char *PR_ParseName (void)
{
	static char	ident[MAX_NAME];

	if (pr_token_type != tt_name)
	{
		PR_ParseError ("not a name");
	}
	if (strlen(pr_token) >= MAX_NAME-1)
	{
		PR_ParseError ("name too long");
	}
	strcpy(ident, pr_token);
	LX_Fetch();

	return ident;
}
void LX_Require (const char *string)
{
	if (strcmp(string, pr_token))
	{
		PR_ParseError("expected %s, found %s", string, pr_token);
	}
	LX_Fetch();
}
Exemple #12
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;
}
static void AddContinue (void)
{
	if (ContinueIndex == MAX_CONTINUE)
	{
		PR_ParseError("continue overflow");
	}
	ContinueInfo[ContinueIndex].level = ContextLevel;
	ContinueInfo[ContinueIndex].patch = &statements[numstatements];
	CO_GenCode(&pr_opcodes[OP_GOTO], NULL, NULL);
	ContinueIndex++;
}
static void AddBreak (void)
{
	if (BreakIndex == MAX_BREAK)
	{
		PR_ParseError("break overflow");
	}
	BreakInfo[BreakIndex].level = ContextLevel;
	BreakInfo[BreakIndex].patch = &statements[numstatements];
	CO_GenCode(&pr_opcodes[OP_GOTO], NULL, NULL);
	BreakIndex++;
}
Exemple #15
0
/*
============
PR_ParseFunctionCall
============
*/
def_t *PR_ParseFunctionCall (def_t *func)
{
	def_t		*e;
	int			 arg;
	type_t		*t;

	t = func->type;

	if (t->type != ev_function)
		PR_ParseError ("not a function");

	// copy the arguments to the global parameter variables
	arg = 0;
	if (!PR_Check(")"))
	{
		do
		{
			if (arg >= t->num_parms || arg >= MAX_PARMS /* works properly with varargs */)
				PR_ParseError ("too many parameters");
			e = PR_Expression (TOP_PRIORITY);

			if (arg < (t->num_parms & VA_MASK) && !CompareType(e->type, t->parm_types[arg]))
				PR_ParseError ("type mismatch on parm %i", arg);
			// a vector copy will copy everything
			def_parms[arg].type = t->parm_types[arg];
			PR_Statement (&pr_opcodes[OP_STORE_V], e, &def_parms[arg]);
			arg++;
		} while (PR_Check (","));

		if (arg < (t->num_parms & VA_MASK))
			PR_ParseError ("too few parameters");
		PR_Expect (")");
	}
	if (arg > MAX_PARMS)
		PR_ParseError ("more than %d parameters", (int)MAX_PARMS);

	PR_Statement (&pr_opcodes[OP_CALL0+arg], func, 0);

	def_ret.type = t->aux_type;
	return &def_ret;
}
Exemple #16
0
/*
================
PR_ParseInitialization

"<type> <name> = " was parsed, parse the rest
================
*/
void PR_ParseInitialization (type_t *type, char *name, def_t *def)
{
	if (def->initialized)
		PR_ParseError ("%s redeclared", name);

	if (pr_token_type != tt_immediate && pr_token_type != tt_name)
		PR_ParseError ("syntax error : '%s'", pr_token);

	if (pr_token_type == tt_name) {
		PR_ParseError ("initializer is not a constant");
	}

	if (!CompareType(pr_immediate_type, type))
		PR_ParseError ("wrong immediate type for %s", name);

	def->initialized = 1;
	if (type == &type_const_string || type == &type_string)
		pr_immediate.string = CopyString (pr_immediate_string);
	memcpy (pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
	PR_Lex ();
}
Exemple #17
0
/*
================
PR_ParseFunctionBody
================
*/
void PR_ParseFunctionBody (type_t *type, char *name, def_t *def)
{
	function_t	*f;
	dfunction_t	*df;
	int			locals_start;

	if (pr_scope)
		PR_ParseError ("'%s': local function definitions are illegal", name);

	if (def->initialized)
		PR_ParseError ("function '%s' already has a body", name);

	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 (opt_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;
	// id's qcc would set numparms to -1 for varargs functions
	// but non-builtin varargs functions don't make sense anyway so don't bother checking
	df->numparms = f->def->type->num_parms & VA_MASK;
	df->locals = locals_end - locals_start;
	df->parm_start = locals_start;
	for (int i=0 ; i<df->numparms ; i++)
		df->parm_size[i] = type_size[f->def->type->parm_types[i]->type];
}
Exemple #18
0
/*
==============
PR_FinishCompilation

called after all files are compiled to check for errors
Returns false if errors were detected.
==============
*/
boolean	PR_FinishCompilation (void)
{
	def_t		*d;
	boolean	errors;
	int i;
	s_file = "LINK" - strings;
	pr_source_line = 0;
	errors = false;
// check to make sure all functions prototyped have code
	for (d=pr.def_head.next ; d ; d=d->next)
	{
		if (d->constant)
		{
			if (!d->defined)
			{
				PR_ParseError (551, "%s was not defined (see prototype %s(%i))",d->name, d->s_file, d->line);
				errors = true;
				pr_source_line++; // just to be cute
			}
		}
	}

// FrikaC: make sure all labels were defined
	for(i = num_defines; i > 0; i--)
	{
		if (pr_defines[i].label)
		{
			if (!pr_defines[i].defined)
			{
				PR_ParseError (552, "Label %s was not defined",pr_defines[i].name);
				errors = true;
				pr_source_line++; // just to be cute
			}
		}
	}


	return !errors;
}
Exemple #19
0
/*
==============
PR_LexString

Parses a quoted string
==============
*/
void PR_LexString (void)
{
	int		c;
	int		len;
	
	len = 0;
	pr_file_p++;
	do
	{
		c = *pr_file_p++;
		if (!c)
			PR_ParseError ("EOF inside quote");
		if (c=='\n')
			PR_ParseError ("newline inside quote");
		if (c=='\\')
		{	// escape char
			c = *pr_file_p++;
			if (!c)
				PR_ParseError ("EOF inside quote");
			if (c == 'n')
				c = '\n';
			else if (c == '"')
				c = '"';
			else
				PR_ParseError ("Unknown escape char");
		}
		else if (c=='\"')
		{
			pr_token[len] = 0;
			pr_token_type = tt_immediate;
			pr_immediate_type = &type_string;
			strcpy (pr_immediate_string, pr_token);
			return;
		}
		pr_token[len] = c;
		len++;
	} while (1);
}
static void AddCase(etype_t type, def_t *value1, def_t *value2, qboolean isDefault)
{
	if (CaseIndex == MAX_CASE)
	{
		PR_ParseError("case overflow");
	}
	CaseInfo[CaseIndex].level = ContextLevel;
	CaseInfo[CaseIndex].value1 = value1;
	CaseInfo[CaseIndex].value2 = value2;
	CaseInfo[CaseIndex].isDefault = isDefault;
	CaseInfo[CaseIndex].statement = numstatements;
	CaseInfo[CaseIndex].type = type;
	CaseIndex++;
}
Exemple #21
0
/*
============
PR_ParseType

Parses a variable type, including field and functions types
============
*/
type_t *PR_ParseType (void)
{
	if (PR_Check ("."))
	{
		type_t	newtype;
		memset (&newtype, 0, sizeof(newtype));
		newtype.type = ev_field;
		newtype.aux_type = PR_ParseType ();
		return PR_GetType (&newtype);
	}

	type_t	*type;

	bool constant = PR_Check ("const");

	if (!strcmp (pr_token, "float") )
		type = constant ? &type_const_float : &type_float;
	else if (!strcmp (pr_token, "vector") )
		type = constant ? &type_const_vector : &type_vector;
	else if (!strcmp (pr_token, "entity") )
		type = &type_entity;
	else if (!strcmp (pr_token, "string") )
		type = constant ? &type_const_string : &type_string;
	else if (!strcmp (pr_token, "void") )
		type = &type_void;
	else
	{
		PR_ParseError ("\"%s\" is not a type", pr_token);
		type = &type_void;	// shut up compiler warning
	}
	PR_Lex ();

	if (PR_Check("(")) {
		// function type

		// go back to non-const types
		// FIXME: don't bother?  Or force const types instead?
		if (type == &type_const_float)
			type = &type_float;
		else if (type == &type_const_vector)
			type = &type_vector;
		else if (type == &type_const_string)
			type = &type_string;

		return PR_ParseFunctionType(type);
	}

	return type;
}
static type_t *ParseUnionType (void)
{
	type_t	*type;
	type_t	newType;

	type = PR_ParseType();
	if (type->type == ev_field)
	{
		PR_ParseError("union field types are implicit");
	}
	memset(&newType, 0, sizeof(newType));
	newType.type = ev_field;
	newType.aux_type = type;
	return PR_FindType(&newType);
}
static void ParseReturn (void)
{
	def_t	*e;

	//if (TK_CHECK(TK_SEMICOLON))
	if (pr_tokenclass == TK_SEMICOLON)
	{
		if (st_ReturnType->type != ev_void)
		{
			PR_ParseError("missing return value");
		}
		CO_GenCode(&pr_opcodes[OP_RETURN], 0, 0);
		LX_Fetch();
		return;
	}
	e = EX_Expression(TOP_PRIORITY);
	if (e->type != st_ReturnType)
	{
		PR_ParseError("return type mismatch");
	}
	LX_Require(";");
	CO_GenCode(&pr_opcodes[OP_RETURN], e, 0);
	st_ReturnParsed = true;
}
Exemple #24
0
void PR_FindMacro (void)
{
	int		i;
	
	for (i=0 ; i<pr_nummacros ; i++)
		if (!strcmp (pr_token, pr_framemacros[i]))
		{
			sprintf (pr_token,"%d", i);
			pr_token_type = tt_immediate;
			pr_immediate_type = &type_float;
			pr_immediate._float = i;
			return;
		}
	PR_ParseError ("Unknown frame macro $%s", pr_token);
}
static void ParseThinktime (void)
{
	def_t	*expr1;
	def_t	*expr2;

	expr1 = EX_Expression(TOP_PRIORITY);
	LX_Require(":");
	expr2 = EX_Expression(TOP_PRIORITY);
	if (expr1->type->type != ev_entity || expr2->type->type != ev_float)
	{
		PR_ParseError("type mismatch for thinktime");
	}
	LX_Require(";");
	CO_GenCode(&pr_opcodes[OP_THINKTIME], expr1, expr2);
}
Exemple #26
0
/*
==============
PR_LexVector

Parses a single quoted vector
==============
*/
void PR_LexVector (void)
{
	int		i;
	
	pr_file_p++;
	pr_token_type = tt_immediate;
	pr_immediate_type = &type_vector;
	for (i=0 ; i<3 ; i++)
	{
		pr_immediate.vector[i] = PR_LexNumber ();
		PR_LexWhitespace ();
	}
	if (*pr_file_p != '\'')
		PR_ParseError ("Bad vector");
	pr_file_p++;
}
Exemple #27
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;
}
Exemple #28
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_FindDef (name, pr_scope);
	if (!d)
		PR_ParseError ("'%s' : undeclared identifier", name);
	return d;
}
static void FindFrameMacro (void)
{
	int		i;

	for (i = 0; i < FrameMacroCount; i++)
	{
		if (!strcmp(pr_token, FrameMacroNames[i]))
		{
			sprintf(pr_token, "%d", i);
			pr_token_type = tt_immediate;
			pr_immediate_type = &type_float;
			pr_immediate._float = (float)FrameMacroValues[i];
			return;
		}
	}
	PR_ParseError("unknown frame macro $%s", pr_token);
}
Exemple #30
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);
}