1 #ifndef QCC_H
2 #define QCC_H
3 
4 #include "cmdlib.h"
5 #include <stdio.h>
6 #include <setjmp.h>
7 
8 #include "pr_comp.h"
9 
10 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1,s2))
11 #define STRNCMP(s1,s2,n) (((*s1)!=(*s2)) || strncmp(s1,s2,n))
12 
13 #ifdef WIN32
14 #pragma warning (disable:4244)
15 #endif
16 
17 /*
18 
19 TODO:
20 
21 "stopped at 10 errors"
22 
23 other pointer types for models and clients?
24 
25 compact string heap?
26 
27 allways initialize all variables to something safe
28 
29 the def->type->type arrangement is really silly.
30 
31 return type checking
32 
33 parm count type checking
34 
35 immediate overflow checking
36 
37 pass the first two parms in call->b and call->c
38 
39 */
40 
41 /*
42 
43 comments
44 --------
45 // comments discard text until the end of line
46 / *  * / comments discard all enclosed text (spaced out on this line because this documentation is in a regular C comment block, and typing them in normally causes a parse error)
47 
48 code structure
49 --------------
50 A definition is:
51 	<type> <name> [ = <immediate>] {, <name> [ = <immediate>] };
52 
53 
54 types
55 -----
56 simple types: void, float, vector, string, or entity
57 	float		width, height;
58 	string		name;
59 	entity		self, other;
60 
61 vector types:
62 	vector		org;	// also creates org_x, org_y, and org_z float defs
63 
64 
65 A function type is specified as: 	simpletype ( type name {,type name} )
66 The names are ignored except when the function is initialized.
67 	void()		think;
68 	entity()	FindTarget;
69 	void(vector destination, float speed, void() callback)	SUB_CalcMove;
70 	void(...)	dprint;		// variable argument builtin
71 
72 A field type is specified as:  .type
73 	.vector		origin;
74 	.string		netname;
75 	.void()		think, touch, use;
76 
77 
78 names
79 -----
80 Names are a maximum of 64 characters, must begin with A-Z,a-z, or _, and can continue with those characters or 0-9.
81 
82 There are two levels of scoping: global, and function.  The parameter list of a function and any vars declared inside a function with the "local" statement are only visible within that function,
83 
84 
85 immediates
86 ----------
87 Float immediates must begin with 0-9 or minus sign.  .5 is illegal.
88 
89 A parsing ambiguity is present with negative constants. "a-5" will be parsed as "a", then "-5", causing an error.  Seperate the - from the digits with a space "a - 5" to get the proper behavior.
90 	12
91 	1.6
92 	0.5
93 	-100
94 
95 Vector immediates are three float immediates enclosed in single quotes.
96 	'0 0 0'
97 	'20.5 -10 0.00001'
98 
99 String immediates are characters enclosed in double quotes.  The string cannot contain explicit newlines, but the escape character \n can embed one.  The \" escape can be used to include a quote in the string.
100 	"maps/jrwiz1.bsp"
101 	"sound/nin/pain.wav"
102 	"ouch!\n"
103 
104 Code immediates are statements enclosed in {} braces.
105 statement:
106 	{ <multiple statements> }
107 	<expression>;
108 	local <type> <name> [ = <immediate>] {, <name> [ = <immediate>] };
109 	return <expression>;
110 	if ( <expression> ) <statement> [ else <statement> ];
111 	while ( <expression> ) <statement>;
112 	do <statement> while ( <expression> );
113 	<function name> ( <function parms> );
114 
115 expression:
116 	combiations of names and these operators with standard C precedence:
117 	"&&", "||", "<=", ">=","==", "!=", "!", "*", "/", "-", "+", "=", ".", "<", ">", "&", "|"
118 	Parenthesis can be used to alter order of operation.
119 	The & and | operations perform integral bit ops on floats
120 
121 A built in function immediate is a number sign followed by an integer.
122 	#1
123 	#12
124 
125 
126 compilation
127 -----------
128 Source files are processed sequentially without dumping any state, so if a
129 defs file is the first one processed, the definitions will be available to
130 all other files.
131 
132 The language is strongly typed and there are no casts.
133 
134 Anything that is initialized is assumed to be constant, and will have
135 immediates folded into it.  If you change the value, your program will
136 malfunction.  All uninitialized globals will be saved to savegame files.
137 
138 Functions cannot have more than eight parameters.
139 
140 Error recovery during compilation is minimal.  It will skip to the next
141 global definition, so you will never see more than one error at a time in a
142 given function.  All compilation aborts after ten error messages.
143 
144 Names can be defined multiple times until they are defined with an
145 initialization, allowing functions to be prototyped before their definition.
146 
147 void()	MyFunction;			// the prototype
148 
149 void()	MyFunction =		// the initialization
150 {
151 	dprint ("we're here\n");
152 };
153 
154 entities and fields
155 -------------------
156 
157 execution
158 ---------
159 Code execution is initiated by C code in quake from two main places:  the
160 timed think routines for periodic control, and the touch function when two
161 objects impact each other.
162 
163 There are three global variables that are set before beginning code execution:
164 	entity	world;		// the server's world object, which holds all global
165 					// state for the server, like the deathmatch flags
166 					// and the body ques.
167 	entity	self;		// the entity the function is executing for
168 	entity	other;		// the other object in an impact, not used for thinks
169 	float	time;		// the current game time.  Note that because the
170 					// entities in the world are simulated sequentially,
171 					// time is NOT strictly increasing.  An impact late
172 					// in one entity's time slice may set time higher
173 					// than the think function of the next entity.
174 					// The difference is limited to 0.1 seconds.
175 
176 Execution is also caused by a few uncommon events, like the addition of a
177 new client to an existing server.
178 
179 There is a runaway counter that stops a program if 100000 statements are
180 executed, assuming it is in an infinite loop.
181 
182 It is acceptable to change the system set global variables.  This is usually
183 done to pose as another entity by changing self and calling a function.
184 
185 The interpretation is fairly efficient, but it is still over an order of
186 magnitude slower than compiled C code.  All time consuming operations should
187 be made into built in functions.
188 
189 A profile counter is kept for each function, and incremented for each
190 interpreted instruction inside that function.  The "profile" console command
191 in Quake will dump out the top 10 functions, then clear all the counters.
192 The "profile all" command will dump sorted stats for every function that has
193 been executed.
194 
195 afunc ( 4, bfunc(1,2,3));
196 will fail because there is a shared parameter marshaling area, which will
197 cause the 1 from bfunc to overwrite the 4 allready placed in parm0.  When a
198 function is called, it copies the parms from the globals into it's privately
199 scoped variables, so there is no collision when calling another function.
200 
201 total = factorial(3) + factorial(4);
202 Will fail because the return value from functions is held in a single global
203 area.  If this really gets on your nerves, tell me and I can work around it
204 at a slight performance and space penalty by allocating a new register for
205 the function call and copying it out.
206 
207 
208 built in functions
209 ------------------
210 void(string text)	dprint;
211 Prints the string to the server console.
212 
213 void(entity client, string text)	cprint;
214 Prints a message to a specific client.
215 
216 void(string text)	bprint;
217 Broadcast prints a message to all clients on the current server.
218 
219 entity()	spawn;
220 Returns a totally empty entity.  You can manually set everything up, or just set the origin and call one of the existing entity setup functions.
221 
222 entity(entity start, .string field, string match) find;
223 Searches the server entity list beginning at start, looking for an entity that has entity.field = match.  To start at the beginning of the list, pass world.  World is returned when the end of the list is reached.
224 
225 <FIXME: define all the other functions...>
226 
227 
228 gotchas
229 -------
230 
231 The && and || operators DO NOT EARLY OUT like C!
232 
233 Don't confuse single quoted vectors with double quoted strings
234 
235 The function declaration syntax takes a little getting used to.
236 
237 Don't forget the ; after the trailing brace of a function initialization.
238 
239 Don't forget the "local" before defining local variables.
240 
241 There are no ++ / -- operators, or operate/assign operators.
242 
243 */
244 
245 //=============================================================================
246 
247 // offsets are allways multiplied by 4 before using
248 typedef int	gofs_t;				// offset in global data block
249 typedef struct function_s function_t;
250 
251 #define	MAX_PARMS	8
252 #define MAX_NAME	64
253 
254 typedef struct type_s
255 {
256 	etype_t			type;
257 	struct def_s	*def;		// a def that points to this type
258 	struct type_s	*next;
259 // function types are more complex
260 	struct type_s	*aux_type;	// return type or field type
261 	int				num_parms;	// -1 = variable args
262 	struct type_s	*parm_types[MAX_PARMS];	// only [num_parms] allocated
263 	//char			parm_names[MAX_PARMS][MAX_NAME];
264 } type_t;
265 
266 typedef struct def_s
267 {
268 	type_t		*type;
269 	char		*name;
270 	struct def_s	*next;
271 	gofs_t		ofs;
272 	struct def_s	*scope;	// function the var was defined in, or NULL
273 	int	initialized;	// 1 when a declaration included "= immediate"
274 
275 	etype_t		cast;	// used for type casting
276 } def_t;
277 
278 //============================================================================
279 
280 // pr_loc.h -- program local defs
281 
282 #define	MAX_ERRORS		10
283 
284 #define	MAX_NAME		64		// chars long
285 
286 #define MAX_REGS                65536
287 
288 //=============================================================================
289 
290 typedef union eval_s
291 {
292 	string_t			string;
293 	float				_float;
294 	float				vector[3];
295 	func_t				function;
296 	int					_int;
297 	union eval_s		*ptr;
298 } eval_t;
299 
300 extern	int	type_size[8];
301 extern	def_t	*def_for_type[8];
302 
303 extern	type_t	type_void, type_string, type_float, type_vector, type_entity, type_field, type_function, type_pointer, type_floatfield;
304 
305 extern	def_t	def_void, def_string, def_float, def_vector, def_entity, def_field, def_function, def_pointer;
306 
307 struct function_s
308 {
309 	int					builtin;	// if non 0, call an internal function
310 	int					code;		// first statement
311 	char				*file;		// source file with definition
312 	int					file_line;
313 	struct def_s		*def;
314 	int					parm_ofs[MAX_PARMS];	// allways contiguous, right?
315 };
316 
317 
318 //
319 // output generated by prog parsing
320 //
321 typedef struct
322 {
323 	char		*memory;
324 	int		max_memory;
325 	int		current_memory;
326 	type_t		*types;
327 
328 	def_t		def_head;	// unused head of linked list
329 	def_t		*def_tail;	// add new defs after this and move it
330 
331 	int		size_fields;
332 } pr_info_t;
333 
334 extern	pr_info_t	pr;
335 
336 typedef struct
337 {
338 	char	*name;
339 	char	*opname;
340 	int		op;
341     int     priority;
342 	boolean	right_associative;
343 	def_t	*type_a, *type_b, *type_c;
344 } opcode_t;
345 
346 //============================================================================
347 
348 
349 extern	opcode_t	pr_opcodes[99];		// sized by initialization
350 
351 extern	boolean	pr_dumpasm;
352 
353 extern	def_t		*pr_global_defs[MAX_REGS];	// to find def for a global variable
354 
355 typedef enum {
356 tt_eof,			// end of file reached
357 tt_name, 		// an alphanumeric name token
358 tt_punct, 		// code punctuation
359 tt_immediate,	// string, float, vector
360 } token_type_t;
361 
362 extern	char		pr_token[2048];
363 extern	token_type_t	pr_token_type;
364 extern	type_t		*pr_immediate_type;
365 extern	eval_t		pr_immediate;
366 extern	int			pr_immediate_index;
367 
368 void PR_PrintStatement (dstatement_t *s);
369 
370 void PR_Lex (void);
371 // reads the next token into pr_token and classifies its type
372 
373 type_t *PR_ParseType (void);
374 char *PR_ParseName (void);
375 
376 void PR_ParseError (char *error, ...);
377 
378 
379 extern	jmp_buf		pr_parse_abort;		// longjump with this on parse error
380 extern	int			pr_source_line;
381 extern	char		*pr_file_p;
382 
383 void *PR_Malloc (int size);
384 
385 
386 #define	OFS_NULL		0
387 #define	OFS_RETURN		1
388 #define	OFS_PARM0		4		// leave 3 ofs for each parm to hold vectors
389 #define	OFS_PARM1		7
390 #define	OFS_PARM2		10
391 #define	OFS_PARM3		13
392 #define	OFS_PARM4		16
393 #define OFS_PARM5		19
394 #define OFS_PARM6		22
395 #define OFS_PARM7		25
396 #define	RESERVED_OFS	28
397 
398 
399 extern	def_t	*pr_scope;
400 extern	int	pr_error_count;
401 
402 void PR_NewLine (void);
403 def_t *PR_GetDef (type_t *type, char *name, def_t *scope, boolean allocate);
404 
405 void PR_PrintDefs (void);
406 
407 void PR_SkipToSemicolon (void);
408 
409 extern	char pr_parm_names[MAX_PARMS][MAX_NAME];
410 extern	boolean	pr_trace;
411 
412 #define	G_FLOAT(o) (pr_globals[o])
413 #define	G_INT(o) (*(int *)&pr_globals[o])
414 #define	G_VECTOR(o) (&pr_globals[o])
415 #define	G_STRING(o) (strings + *(string_t *)&pr_globals[o])
416 #define	G_FUNCTION(o) (*(func_t *)&pr_globals[o])
417 
418 char *PR_ValueString (etype_t type, void *val);
419 
420 void PR_ClearGrabMacros (void);
421 
422 boolean	PR_CompileFile (char *string, char *filename);
423 
424 extern	boolean	pr_dumpasm;
425 
426 extern	string_t	s_file;			// filename for function definition
427 
428 extern	def_t	def_ret, def_parms[MAX_PARMS];
429 
430 //=============================================================================
431 
432 #define	MAX_STRINGS		500000
433 #define MAX_GLOBALS             32768
434 #define	MAX_FIELDS		1024
435 #define	MAX_STATEMENTS	65536
436 #define	MAX_FUNCTIONS	8192
437 #define MAX_TEMPS		256
438 
439 #define	MAX_SOUNDS		1024
440 #define	MAX_MODELS		1024
441 #define	MAX_FILES		1024
442 #define	MAX_DATA_PATH	64
443 
444 extern	char	strings[MAX_STRINGS];
445 extern	int		strofs;
446 
447 extern	dstatement_t	statements[MAX_STATEMENTS];
448 extern	int			numstatements;
449 extern	int			statement_linenums[MAX_STATEMENTS];
450 
451 extern	dfunction_t	functions[MAX_FUNCTIONS];
452 extern	int			numfunctions;
453 
454 extern	float		pr_globals[MAX_REGS];
455 extern	int			numpr_globals;
456 
457 extern	char		pr_immediate_string[2048];
458 extern	int			pr_immediate_strlen;
459 
460 extern	char		precache_sounds[MAX_SOUNDS][MAX_DATA_PATH];
461 extern	int			precache_sounds_block[MAX_SOUNDS];
462 extern	int			numsounds;
463 
464 extern	char		precache_models[MAX_MODELS][MAX_DATA_PATH];
465 extern	int			precache_models_block[MAX_SOUNDS];
466 extern	int			nummodels;
467 
468 extern	char		precache_files[MAX_FILES][MAX_DATA_PATH];
469 extern	int			precache_files_block[MAX_SOUNDS];
470 extern	int			numfiles;
471 
472 extern int pr_optimize_eliminate_temps;
473 extern int pr_optimize_shorten_ifs;
474 extern int pr_optimize_nonvec_parms;
475 extern int pr_optimize_constant_names;
476 extern int pr_optimize_defs;
477 extern int pr_optimize_hash_strings;
478 
479 extern int num_temps_removed;
480 extern int num_stores_shortened;
481 extern int num_ifs_shortened;
482 extern int num_nonvec_parms;
483 extern int num_constant_names;
484 extern int num_defs;
485 extern int num_strings;
486 
487 extern int ofstemp;
488 
489 int	CopyString (char *str, int len = 0);
490 
491 
PR_Expect(char * string)492 inline static void PR_Expect (char *string)
493 {
494 	if (STRCMP(string, pr_token))
495 		PR_ParseError ("expected %s, found %s",string, pr_token);
496 	PR_Lex ();
497 }
498 
PR_Check(char * string)499 inline static boolean PR_Check (char *string)
500 {
501 	if (STRCMP(string, pr_token))
502 		return false;
503 
504 	PR_Lex ();
505 	return true;
506 }
507 
508 
509 #endif
510 
511