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