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