Ejemplo n.º 1
0
Archivo: pr_lex.cpp Proyecto: luaman/zq
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);
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 4
0
Archivo: pr_lex.cpp Proyecto: luaman/zq
/*
============
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;
}
Ejemplo n.º 5
0
/*
============
PR_SkipToSemicolon

For error recovery, also pops out of nested braces
============
*/
void PR_SkipToSemicolon (void)
{
	do
	{
		if (!pr_bracelevel && PR_Check (";"))
			return;
		PR_Lex ();
	} while (pr_token[0]);	// eof will return a null token
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
============
PR_Term
============
*/
def_t *PR_Term (void)
{
	def_t	*e, *e2;
	etype_t	t;
	
	if (PR_Check ("!"))
	{
		e = PR_Expression (NOT_PRIORITY);
		t = e->type->type;
		if (t == ev_float)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_F], e, 0);
		else if (t == ev_string)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_S], e, 0);
		else if (t == ev_entity)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_ENT], e, 0);
		else if (t == ev_vector)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_V], e, 0);
		else if (t == ev_function)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0);
		else
		{
			e2 = NULL;		// shut up compiler warning;
			PR_ParseError ("type mismatch for !");
		}
		return e2;
	}
	
	if (PR_Check ("("))
	{
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		return e;
	}
	
	return PR_ParseValue ();
}
Ejemplo n.º 8
0
/*
============
PR_CompileFile

compiles the 0 terminated text, adding defintions to the pr structure
============
*/
bool PR_CompileFile (char *string, char *filename)
{
	if (!pr.memory)
		Error ("PR_CompileFile: Didn't clear");

	PR_ClearGrabMacros ();	// clear the frame macros

	pr_file_p = string;
	s_file = CopyString (filename);

	pr_source_line = 0;

	PR_NewLine ();

	PR_Lex ();	// read first token

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

	while (pr_token_type != tt_eof)
	{
		if (setjmp(pr_parse_abort))
		{
			if (++pr_error_count > MAX_ERRORS)
				return false;
			PR_SkipToSemicolon ();
			if (pr_token_type == tt_eof)
				return false;
		}

		pr_scope = NULL;	// outside all functions

		PR_ParseDefs ();
	}

	return (pr_error_count == 0);
}
Ejemplo n.º 9
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 (";");
}
Ejemplo n.º 10
0
/*
============
PR_ParseStatement

============
*/
void PR_ParseStatement (void)
{
	def_t				*e;
	dstatement_t		*patch1, *patch2;
	
	if (PR_Check ("{"))
	{
		do
		{
			PR_ParseStatement ();
		} while (!PR_Check ("}"));
		return;
	}
	
	if (PR_Check("return"))
	{
		if (PR_Check (";"))
		{
			PR_Statement (&pr_opcodes[OP_RETURN], 0, 0);
			return;
		}
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (";");
		PR_Statement (&pr_opcodes[OP_RETURN], e, 0);
		return;		
	}
	
	if (PR_Check("while"))
	{
		PR_Expect ("(");
		patch2 = &statements[numstatements];
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		patch1 = &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IFNOT], e, 0);
		PR_ParseStatement ();
		junkdef.ofs = patch2 - &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_GOTO], &junkdef, 0);
		patch1->b = &statements[numstatements] - patch1;
		return;
	}
	
	if (PR_Check("do"))
	{
		patch1 = &statements[numstatements];
		PR_ParseStatement ();
		PR_Expect ("while");
		PR_Expect ("(");
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		PR_Expect (";");
		junkdef.ofs = patch1 - &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IF], e, &junkdef);
		return;
	}
	
	if (PR_Check("local"))
	{
		PR_ParseDefs ();
		locals_end = numpr_globals;
		return;
	}
	
	if (PR_Check("if"))
	{
		PR_Expect ("(");
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		
		patch1 = &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IFNOT], e, 0);
		
		PR_ParseStatement ();
		
		if (PR_Check ("else"))
		{
			patch2 = &statements[numstatements];
			PR_Statement (&pr_opcodes[OP_GOTO], 0, 0);
			patch1->b = &statements[numstatements] - patch1;
			PR_ParseStatement ();
			patch2->a = &statements[numstatements] - patch2;
		}
		else
			patch1->b = &statements[numstatements] - patch1;
		
		return;
	}
	
	PR_Expression (TOP_PRIORITY);
	PR_Expect (";");
}
Ejemplo n.º 11
0
def_t *PR_Expression (int priority)
{
	opcode_t	*op, *oldop;
	def_t		*e, *e2;
	etype_t		type_a, type_b, type_c;
	
	if (priority == 0)
		return PR_Term ();
		
	e = PR_Expression (priority-1);
		
	while (1)
	{
		if (priority == 1 && PR_Check ("(") )
			return PR_ParseFunctionCall (e);

		for (op=pr_opcodes ; op->name ; op++)
		{
			if (op->priority != priority)
				continue;
			if (!PR_Check (op->name))
				continue;
			if ( op->right_associative )
			{
			// if last statement is an indirect, change it to an address of
				if ( (unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 )
				{
					statements[numstatements-1].op = OP_ADDRESS;
					def_pointer.type->aux_type = e->type;
					e->type = def_pointer.type;
				}
				e2 = PR_Expression (priority);
			}
			else
				e2 = PR_Expression (priority-1);
				
		// type check
			type_a = e->type->type;
			type_b = e2->type->type;

			if (op->name[0] == '.')// field access gets type from field
			{
				if (e2->type->aux_type)
					type_c = e2->type->aux_type->type;
				else
					type_c = -1;	// not a field
			}
			else
				type_c = ev_void;
				
			oldop = op;
			while (type_a != op->type_a->type->type
			|| type_b != op->type_b->type->type
			|| (type_c != ev_void && type_c != op->type_c->type->type) )
			{
				op++;
				if (!op->name || strcmp (op->name , oldop->name))
					PR_ParseError ("type mismatch for %s", oldop->name);
			}
			
			if (type_a == ev_pointer && type_b != e->type->aux_type->type)
				PR_ParseError ("type mismatch for %s", op->name);
			
			
			if (op->right_associative)
				e = PR_Statement (op, e2, e);
			else
				e = PR_Statement (op, e, e2);
			
			if (type_c != ev_void)	// field access gets type from field
				e->type = e2->type->aux_type;
			
			break;
		}
		if (!op->name)
			break;	// next token isn't at this priority level
	}
	
	return e;
}
Ejemplo n.º 12
0
/*
============
PR_ParseStatement

============
*/
void PR_ParseStatement (void)
{
	def_t			*e		= NULL;
	dstatement_t	*patch1	= NULL;
	dstatement_t	*patch2	= NULL;

	if (PR_Check(";"))
		return;

	if (PR_Check ("{"))
	{
		while (!PR_Check ("}"))
			PR_ParseStatement ();
		return;
	}

	if (PR_Check("return"))
	{
		if (PR_Check (";"))
		{
			PR_Statement (&pr_opcodes[OP_RETURN], 0, 0);
			return;
		}
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (";");
		PR_Statement (&pr_opcodes[OP_RETURN], e, 0);
		return;
	}

	if (PR_Check("while"))
	{
		PR_Expect ("(");
		patch2 = &statements[numstatements];
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		patch1 = &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IFNOT], e, 0);
		PR_ParseStatement ();
		junkdef.ofs = patch2 - &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_GOTO], &junkdef, 0);
		patch1->b = (unsigned short)(&statements[numstatements] - patch1);
		return;
	}

	if (PR_Check("do"))
	{
		patch1 = &statements[numstatements];
		PR_ParseStatement ();
		PR_Expect ("while");
		PR_Expect ("(");
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		PR_Expect (";");
		junkdef.ofs = patch1 - &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IF], e, &junkdef);
		return;
	}

	if ( PR_Check("local") || !strcmp(pr_token, "const") || !strcmp(pr_token, "float") || !strcmp(pr_token, "vector")
		|| !strcmp(pr_token, "entity") || !strcmp(pr_token, "string") || !strcmp(pr_token, "void"))
	{
		PR_ParseDefs ();
		locals_end = numpr_globals;
		return;
	}

	if (PR_Check("if"))
	{
		PR_Expect ("(");
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");

		patch1 = &statements[numstatements];
		PR_Statement (&pr_opcodes[OP_IFNOT], e, 0);

		PR_ParseStatement ();

		if (PR_Check ("else"))
		{
			patch2 = &statements[numstatements];
			PR_Statement (&pr_opcodes[OP_GOTO], 0, 0);
			patch1->b = (unsigned short)(&statements[numstatements] - patch1);
			PR_ParseStatement ();
			patch2->a = (unsigned short)(&statements[numstatements] - patch2);
		}
		else
			patch1->b = (unsigned short)(&statements[numstatements] - patch1);

		return;
	}

	if (PR_Check("else"))
		PR_ParseError ("illegal else without matching if");

	PR_Expression (TOP_PRIORITY);
	PR_Expect (";");
}
Ejemplo n.º 13
0
/*
==============
PR_Expression
==============
*/
def_t *PR_Expression (int priority)
{
	opcode_t	*op, *oldop;
	def_t		*e, *e2;
	etype_t		type_a, type_b, type_c;

	if (priority == 0)
		return PR_Term ();

	e = PR_Expression (priority-1);

	while (1)
	{
		if (priority == 1 && PR_Check ("(") )
			return PR_ParseFunctionCall (e);

		for (op=pr_opcodes ; op->name ; op++)
		{
			if (op->priority != priority)
				continue;
			if (!PR_Check (op->name))
				continue;

			if (op->name[0] == '.')
			{
				char *name = PR_ParseName ();

				if (e->type != &type_entity)
					PR_ParseError ("left of '.%s' must have entity type", name);

				e2 = PR_FindDef (name, pr_scope);
				if (!e2 || e2->type->type != ev_field)
					PR_ParseError ("'%s' is not a field", name);

				type_c = e2->type->aux_type->type;

				// we still allow ".void foo" so need to check
				if (type_c == ev_void)
					PR_ParseError ("tried to access a 'void' field");

				assert (type_c != ev_pointer && type_c != ev_void);
				while (type_c != op->type_c) {
					op++;
					assert (op->name);
				}

				e = PR_Statement (op, e, e2);

				// field access gets type from field
				e->type = e2->type->aux_type;
				break;
			}

			if (op->right_associative)
			{
				if (e->type->constant)
					PR_ParseError ("assignment to constant");

			// if last statement is an indirect, change it to an address of
				if ( (unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 )
				{
					statements[numstatements-1].op = (unsigned short)OP_ADDRESS;
					def_pointer.type->aux_type = e->type;
					e->type = def_pointer.type;
				}
				e2 = PR_Expression (priority);
			}
			else
				e2 = PR_Expression (priority-1);

		// type check
			type_a = e->type->type;
			type_b = e2->type->type;

			oldop = op;
			while (type_a != op->type_a || type_b != op->type_b )
			{
				op++;
				if (!op->name || strcmp (op->name , oldop->name))
					PR_ParseError ("type mismatch for %s", oldop->name);
			}

			if (type_a == ev_pointer && type_b != e->type->aux_type->type)
				PR_ParseError ("type mismatch for %s", op->name);

#if 0
			if (e->type->constant && e2->type->constant) {
				// try to calculate the expression at compile time
				eval_t result;
				if (PR_Calc(op - pr_opcodes, (eval_t *)(pr_globals + e->ofs),
						(eval_t *)(pr_globals + e2->ofs), &result))
				{
//					printf ("line %i: folding %s %s %s into %s\n", pr_source_line, e->name, op->name, e2->name,
//						PR_ValueString(op->type_c, &val));

					type_t *resulttype;
					switch (op->type_c) {
						case ev_float: resulttype = &type_const_float; break;
						//case ev_string: resulttype = &type_const_string; break;
						case ev_vector: resulttype = &type_const_vector; break;
						default: assert (false);
					}

					e = PR_GetImmediate (resulttype, result);
					break;
				}
			}
#endif

			if (op->right_associative)
				e = PR_Statement (op, e2, e);
			else
				e = PR_Statement (op, e, e2);

			break;
		}
		if (!op->name)
			break;	// next token isn't at this priority level
	}

	return e;
}
Ejemplo n.º 14
0
/*
============
PR_Term
============
*/
def_t *PR_Term (void)
{
	if (pr_token_type != tt_punct)
		return PR_ParseValue ();

	def_t	*e, *e2;
	etype_t	t;

	if (PR_Check ("!"))
	{
		e = PR_Expression (NOT_PRIORITY);
		t = e->type->type;
		if (t == ev_float)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_F], e, 0);
		else if (t == ev_string)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_S], e, 0);
		else if (t == ev_entity)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_ENT], e, 0);
		else if (t == ev_vector)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_V], e, 0);
		else if (t == ev_function)
			e2 = PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0);
		else {
			PR_ParseError ("type mismatch for !");
			return NULL;	// shut up compiler
		}
		return e2;
	}

	if (PR_Check ("("))
	{
		e = PR_Expression (TOP_PRIORITY);
		PR_Expect (")");
		return e;
	}

	if (PR_Check("-")) {
		e = PR_Expression (1 /* FIXME, correct? */);
		t = e->type->type;
		if (t == ev_float) {
			eval_t v;
			v._float = 0;
			def_t *imm = PR_GetImmediate (&type_const_float, v);
			e2 = PR_Statement (&pr_opcodes[OP_SUB_F], imm, e);
		} else if (t == ev_vector) {
			eval_t v;
			v.vector[0] = v.vector[1] = v.vector[2] = 0;
			def_t *imm = PR_GetImmediate (&type_const_vector, v);
			e2 = PR_Statement (&pr_opcodes[OP_SUB_V], imm, e);
		} else {
			PR_ParseError ("type mismatch for -");
			return NULL;	// shut up compiler
		}
		return e2;
	}

	if (PR_Check("+")) {
		e = PR_Expression (1 /* FIXME, correct? */);
		t = e->type->type;
		if (t != ev_float && t != ev_vector) {
			PR_ParseError ("type mismatch for +");
			return NULL;	// shut up compiler
		}
		return e;
	}

	PR_ParseError ("syntax error : '%s'", pr_token);
	return NULL;	// shut up compiler
}
Ejemplo n.º 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
}
Ejemplo n.º 16
0
Archivo: pr_lex.cpp Proyecto: luaman/zq
/*
========================
PR_LexPrecomp

parses and executes directives
  with a leading '#':
  #define
  #undef
  #ifdef
  #ifndef
  #else
  #endif
  #error
  #message
  #pragma message
========================
*/
void          PR_LexPrecomp (void)
{
	// yeah it isn't quite Precompiler is it?
	pr_file_p++;  // skip the hash
	if (!PR_SimpleGetToken ())
		PR_ParseError ("Q534: Invalid preprocessor command"); // that's not possible

	if (!strcmp(pr_token, "ifdef"))
	{
		if (ifdefdepth > ignoredepth)
		{
			// inside another ignored "ifdef"/"ifndef"
			// -> ignore statements
			ifdefdepth++;
			return;
		}
		ifdefdepth++;
		ignoredepth = ifdefdepth;
		PR_Lex();
		if (!PR_FindDefine(pr_token, true))
		{
			// not defined
			// -> ignore statements until endif or else
			ignoredepth--;
			while(ifdefdepth > ignoredepth)
				PR_Lex();
			return;
		}
		// defined
		// -> parse statements
		PR_Lex();
		return;
	}
	else
	if (!strcmp(pr_token, "ifndef"))
	{
		if (ifdefdepth > ignoredepth)
		{
			// inside another ignored ifdef
			// -> ignore statements
			ifdefdepth++;
			return;
		}
		ifdefdepth++;
		ignoredepth = ifdefdepth;
		PR_Lex();
		if (PR_FindDefine(pr_token, true))
		{
			// defined
			// -> ignore statements
			ignoredepth--;
			while(ifdefdepth > ignoredepth)
				PR_Lex();
			return;
		}
		PR_Lex();
		return;
	}
	else
	if (!strcmp(pr_token, "endif"))
	{
		ifdefdepth--;
		if (ifdefdepth < 0)
		  PR_ParseError ("Q119: Too many #endifs");
		PR_Lex();
		return;
	}
	else
	if (!strcmp(pr_token, "else"))
	{
		if (ifdefdepth == (ignoredepth + 1))
		{
			// the "ifdef" or "ifndef" part has not been entered
			// -> parse the statements inside "else"
			//print("parsing statment %s in else on %s(%ld)", pr_token, s_file + strings, pr_source_line);
			ignoredepth = ifdefdepth;
			pr_token_type = tt_name;
			PR_Lex();
			return;
		}

		// "ifdef" or "ifndef" part has already been entered
		// -> ignore statements in "else" part
		ignoredepth--;
		while (ifdefdepth > ignoredepth)
			PR_Lex();
		return;
	}
	else
	if (ifdefdepth > ignoredepth)
	{
		//print("ignored %s on %s(%ld)", pr_token, s_file + strings, pr_source_line);
		return;
	}
	else
	if (PR_Check("error"))
	{
		if (pr_immediate_type != &type_string && pr_immediate_type != &type_const_string)
		  PR_ParseError ("Q541: Error must be a string");
		PR_ParseError ("User Error on %s(%ld): %s", s_file + strings, pr_source_line, pr_immediate_string);
		PR_Lex();
		return;
	}
	else
	if (PR_Check("message"))
	{
		if (pr_immediate_type != &type_string && pr_immediate_type != &type_const_string)
		  PR_ParseError ("Q541: Message must be a string");
		printf ("Message on %s(%ld): %s\n", s_file + strings, (long)pr_source_line, pr_immediate_string);
		PR_Lex();
		return;
	}
	else
	if (PR_Check("pragma"))
	{
		if (PR_Check("message"))
		{
			if (pr_immediate_type != &type_string && pr_immediate_type != &type_const_string)
				PR_ParseError ("Q541: Message must be a string");
			printf ("Message on %s(%ld): %s\n", s_file + strings, (long)pr_source_line, pr_immediate_string);
			PR_Lex();
			return;
		}

		// unknown pragma directive
		printf ("Warning on %s(%ld): unknown #pragma \"%s\" (will be ignored)", s_file + strings, (long)pr_source_line, pr_token);

		// skip to the end of the line
		while (PR_SimpleGetToken ())
			;

		PR_Lex();
		return;
	}
	else
	if (PR_Check("define"))
	{
		char	define_name[2048];

		if (pr_token_type != tt_name)
			PR_ParseError ("Q543: #define: Invalid name");

		// predefine it:
		strlcpy (define_name, pr_token, sizeof(define_name));

		if (PR_AddDefine (define_name, &type_const_float, NULL, false) <= 0)
			PR_ParseError ("Q544: #define \"%s\": creation failed", define_name);

		// get the value of the define
		PR_Lex();
		if (pr_token_type == tt_immediate)
		{
			if (pr_immediate_type != &type_float && pr_immediate_type != &type_const_float)
				PR_ParseError ("Q545: #define \"%s\": Invalid type of value", define_name);

         // finally fix the define (with given value)
			if (PR_AddDefine (define_name, pr_immediate_type, &pr_immediate, false) <= 0)
				PR_ParseError ("Q544: #define \"%s\": creation failed", define_name);

			PR_Lex();
		}
		else
		{
			eval_t   value;

			value._float = 1;

			// finally fix the define (with default-value)
			if (PR_AddDefine (define_name, &type_const_float, &value, false) <= 0)
				PR_ParseError ("Q544: #define \"%s\": creation failed", define_name);
		}

		return;
	}
	else
	if (PR_Check("undef"))
	{
		if (pr_token_type != tt_name)
			PR_ParseError ("Q544: #undef: Invalid name");

		PR_DelDefine (pr_token, false);

		PR_Lex();
		return;
	}
} // END_FUNC PR_LexPrecomp