File: qcc.h

package info (click to toggle)
fteqcc 3343%2Bsvn3400-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 1,472 kB
  • sloc: ansic: 38,594; makefile: 69; sh: 6
file content (904 lines) | stat: -rw-r--r-- 25,767 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
#define COMPILER
#define PROGSUSED

//#define COMMONINLINES
//#define inline _inline

#include "cmdlib.h"
#include <setjmp.h>
/*
#include <stdio.h>
#include <conio.h>


#include "pr_comp.h"
*/

//this is for testing
#define WRITEASM

#ifdef __MINGW32_VERSION
#define MINGW
#endif

#define progfuncs qccprogfuncs
extern progfuncs_t *qccprogfuncs;

#ifndef _WIN32
#define stricmp strcasecmp
#define strnicmp strncasecmp
#endif

void *qccHunkAlloc(size_t mem);
void qccClearHunk(void);

extern short   (*PRBigShort) (short l);
extern short   (*PRLittleShort) (short l);
extern int     (*PRBigLong) (int l);
extern int     (*PRLittleLong) (int l);
extern float   (*PRBigFloat) (float l);
extern float   (*PRLittleFloat) (float l);


#define	MAX_ERRORS		10

#define	MAX_NAME		64		// chars long

extern unsigned int MAX_REGS;

extern int	MAX_STRINGS;
extern int	MAX_GLOBALS;
extern int	MAX_FIELDS;
extern int	MAX_STATEMENTS;
extern int	MAX_FUNCTIONS;

#define	MAX_SOUNDS		1024	//convert to int?
#define MAX_TEXTURES	1024	//convert to int?
#define	MAX_MODELS		1024	//convert to int?
#define	MAX_FILES		1024	//convert to int?
#define	MAX_DATA_PATH	64

extern int MAX_CONSTANTS;
#define MAXCONSTANTLENGTH 64
#define MAXCONSTANTVALUELENGTH 1024
#define MAXCONSTANTPARAMLENGTH 32
#define MAXCONSTANTPARAMS 32

typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_DARKPLACES, QCF_FTE, QCF_FTEDEBUG, QCF_KK7} qcc_targetformat_t;
extern qcc_targetformat_t qcc_targetformat;


/*

TODO:

"stopped at 10 errors"

other pointer types for models and clients?

compact string heap?

always initialize all variables to something safe

the def->type->type arrangement is really silly.

return type checking

parm count type checking

immediate overflow checking

pass the first two parms in call->b and call->c

*/

/*

comments
--------
// comments discard text until the end of line
/ *  * / 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)

code structure
--------------
A definition is:
	<type> <name> [ = <immediate>] {, <name> [ = <immediate>] };


types
-----
simple types: void, float, vector, string, or entity
	float		width, height;
	string		name;
	entity		self, other;

vector types:
	vector		org;	// also creates org_x, org_y, and org_z float defs
	
	
A function type is specified as: 	simpletype ( type name {,type name} )
The names are ignored except when the function is initialized.	
	void()		think;
	entity()	FindTarget;
	void(vector destination, float speed, void() callback)	SUB_CalcMove;
	void(...)	dprint;		// variable argument builtin

A field type is specified as:  .type
	.vector		origin;
	.string		netname;
	.void()		think, touch, use;
	

names
-----
Names are a maximum of 64 characters, must begin with A-Z,a-z, or _, and can continue with those characters or 0-9.

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, 


immediates
----------
Float immediates must begin with 0-9 or minus sign.  .5 is illegal.
	
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.
	12
	1.6
	0.5
	-100

Vector immediates are three float immediates enclosed in single quotes.
	'0 0 0'
	'20.5 -10 0.00001'
	
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.
	"maps/jrwiz1.bsp"
	"sound/nin/pain.wav"
	"ouch!\n"

Code immediates are statements enclosed in {} braces.
statement:
	{ <multiple statements> }
	<expression>;
	local <type> <name> [ = <immediate>] {, <name> [ = <immediate>] };
	return <expression>;
	if ( <expression> ) <statement> [ else <statement> ];
	while ( <expression> ) <statement>;
	do <statement> while ( <expression> );
	<function name> ( <function parms> );
	
expression:
	combiations of names and these operators with standard C precedence:
	"&&", "||", "<=", ">=","==", "!=", "!", "*", "/", "-", "+", "=", ".", "<", ">", "&", "|"
	Parenthesis can be used to alter order of operation.
	The & and | operations perform integral bit ops on floats
	
A built in function immediate is a number sign followed by an integer.
	#1
	#12


compilation
-----------
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.

The language is strongly typed and there are no casts.

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.

Functions cannot have more than eight parameters.

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.

Names can be defined multiple times until they are defined with an initialization, allowing functions to be prototyped before their definition.

void()	MyFunction;			// the prototype

void()	MyFunction =		// the initialization
{
	dprint ("we're here\n");
};


entities and fields
-------------------


execution
---------
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.

There are three global variables that are set before beginning code execution:
	entity	world;		// the server's world object, which holds all global
						// state for the server, like the deathmatch flags
						// and the body ques.
	entity	self;		// the entity the function is executing for
	entity	other;		// the other object in an impact, not used for thinks
	float	time;		// the current game time.  Note that because the
						// entities in the world are simulated sequentially,
						// time is NOT strictly increasing.  An impact late
						// in one entity's time slice may set time higher
						// than the think function of the next entity. 
						// The difference is limited to 0.1 seconds.
Execution is also caused by a few uncommon events, like the addition of a new client to an existing server.
	
There is a runnaway counter that stops a program if 100000 statements are executed, assuming it is in an infinite loop.

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.

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.

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.


afunc ( 4, bfunc(1,2,3));
will fail because there is a shared parameter marshaling area, which will cause the 1 from bfunc to overwrite the 4 already 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.

total = factorial(3) + factorial(4);
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.


built in functions
------------------
void(string text)	dprint;
Prints the string to the server console.

void(entity client, string text)	cprint;
Prints a message to a specific client.

void(string text)	bprint;
Broadcast prints a message to all clients on the current server.

entity()	spawn;
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.

entity(entity start, .string field, string match) find;
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.

<FIXME: define all the other functions...>


gotchas
-------

The && and || operators DO NOT EARLY OUT like C!

Don't confuse single quoted vectors with double quoted strings

The function declaration syntax takes a little getting used to.

Don't forget the ; after the trailing brace of a function initialization.

Don't forget the "local" before defining local variables.

There are no ++ / -- operators, or operate/assign operators.

*/


#if 1
#include "hash.h"
extern hashtable_t compconstantstable;
extern hashtable_t globalstable, localstable;
#endif

#ifdef WRITEASM
extern FILE *asmfile;
#endif
//=============================================================================

// offsets are always multiplied by 4 before using
typedef unsigned int	gofs_t;				// offset in global data block
typedef struct QCC_function_s QCC_function_t;

#define	MAX_PARMS	8

typedef struct QCC_type_s
{
	etype_t			type;

	struct QCC_type_s	*parentclass;	//type_entity...
	struct QCC_type_s	*next;
// function types are more complex
	struct QCC_type_s	*aux_type;	// return type or field type
	struct QCC_type_s	*param;
	int				num_parms;	// -1 = variable args
//	struct QCC_type_s	*parm_types[MAX_PARMS];	// only [num_parms] allocated	

	unsigned int ofs;	//inside a structure.
	unsigned int size;
	char *name;
} QCC_type_t;
int typecmp(QCC_type_t *a, QCC_type_t *b);

typedef struct temp_s {
	gofs_t ofs;
	struct QCC_def_s	*scope;
#ifdef WRITEASM
	struct QCC_def_s	*lastfunc;
#endif
	struct temp_s	*next;
	pbool used;
	unsigned int size;
} temp_t;

//not written
typedef struct QCC_def_s
{
	QCC_type_t		*type;
	char		*name;
	struct QCC_def_s	*next;
	struct QCC_def_s	*nextlocal;	//provides a chain of local variables for the opt_locals_marshalling optimisation.
	gofs_t		ofs;
	struct QCC_def_s	*scope;		// function the var was defined in, or NULL
	int			initialized;	// 1 when a declaration included "= immediate"
	int			constant;		// 1 says we can use the value over and over again

	int references;
	int timescalled;	//part of the opt_stripfunctions optimisation.

	int s_file;
	int s_line;

	int arraysize;
	pbool shared;
	pbool saved;
	pbool isstatic;

	temp_t *temp;
} QCC_def_t;

//============================================================================

// pr_loc.h -- program local defs


//=============================================================================
extern char QCC_copyright[1024];
extern char QCC_Packname[5][128];
extern int QCC_packid;

typedef union QCC_eval_s
{
	QCC_string_t			string;
	float				_float;
	float				vector[3];
	func_t				function;
	int					_int;
	union QCC_eval_s		*ptr;
} QCC_eval_t;

const extern	unsigned int		type_size[];
//extern	QCC_def_t	*def_for_type[9];

extern	QCC_type_t	*type_void, *type_string, *type_float, *type_vector, *type_entity, *type_field, *type_function, *type_pointer, *type_integer, *type_variant, *type_floatfield;

struct QCC_function_s
{
	int					builtin;	// if non 0, call an internal function
	int					code;		// first statement
	char				*file;		// source file with definition
	int					file_line;
	struct QCC_def_s		*def;
	unsigned int		parm_ofs[MAX_PARMS];	// always contiguous, right?
};


//
// output generated by prog parsing
//
typedef struct
{
	char		*memory;
	int			max_memory;
	int			current_memory;
	QCC_type_t		*types;
	
	QCC_def_t		def_head;		// unused head of linked list
	QCC_def_t		*def_tail;		// add new defs after this and move it
	QCC_def_t		*localvars;		// chain of variables which need to be pushed and stuff.
	
	int			size_fields;
} QCC_pr_info_t;

extern	QCC_pr_info_t	pr;


typedef struct
{
	char name[MAXCONSTANTLENGTH];
	char value[MAXCONSTANTVALUELENGTH];
	char params[MAXCONSTANTPARAMS][MAXCONSTANTPARAMLENGTH];
	int numparams;
	pbool used;
	pbool inside;

	int namelen;
} CompilerConstant_t;
extern CompilerConstant_t *CompilerConstant;

//============================================================================

extern	pbool	pr_dumpasm;

//extern	QCC_def_t		**pr_global_defs;	// to find def for a global variable

typedef enum {
tt_eof,			// end of file reached
tt_name, 		// an alphanumeric name token
tt_punct, 		// code punctuation
tt_immediate,	// string, float, vector
} token_type_t;

extern	char		pr_token[8192];
extern	token_type_t	pr_token_type;
extern	QCC_type_t		*pr_immediate_type;
extern	QCC_eval_t		pr_immediate;

extern pbool keyword_asm;
extern pbool keyword_break;
extern pbool keyword_case;
extern pbool keyword_class;
extern pbool keyword_const;
extern pbool keyword_continue;
extern pbool keyword_default;
extern pbool keyword_do;
extern pbool keyword_entity;
extern pbool keyword_float;
extern pbool keyword_for;
extern pbool keyword_goto;
extern pbool keyword_int;
extern pbool keyword_integer;
extern pbool keyword_state;
extern pbool keyword_string;
extern pbool keyword_struct;
extern pbool keyword_switch;
extern pbool keyword_thinktime;
extern pbool keyword_var;
extern pbool keyword_vector;
extern pbool keyword_union;
extern pbool keyword_enum;	//kinda like in c, but typedef not supported.
extern pbool keyword_enumflags;	//like enum, but doubles instead of adds 1.
extern pbool keyword_typedef;	//fixme
extern pbool keyword_extern;	//function is external, don't error or warn if the body was not found
extern pbool keyword_shared;	//mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
extern pbool keyword_noref;	//nowhere else references this, don't strip it.
extern pbool keyword_nosave;	//don't write the def to the output.
extern pbool keyword_union;	//you surly know what a union is!


extern pbool keywords_coexist;
extern pbool output_parms;
extern pbool autoprototype;
extern pbool flag_ifstring;
extern pbool flag_iffloat;
extern pbool flag_acc;
extern pbool flag_caseinsensative;
extern pbool flag_laxcasts;
extern pbool flag_hashonly;
extern pbool flag_fasttrackarrays;
extern pbool flag_assume_integer;

extern pbool opt_overlaptemps;
extern pbool opt_shortenifnots;
extern pbool opt_noduplicatestrings;
extern pbool opt_constantarithmatic;
extern pbool opt_nonvec_parms;
extern pbool opt_constant_names;
extern pbool opt_precache_file;
extern pbool opt_filenames;
extern pbool opt_assignments;
extern pbool opt_unreferenced;
extern pbool opt_function_names;
extern pbool opt_locals;
extern pbool opt_dupconstdefs;
extern pbool opt_constant_names_strings;
extern pbool opt_return_only;
extern pbool opt_compound_jumps;
//extern pbool opt_comexprremoval;
extern pbool opt_stripfunctions;
extern pbool opt_locals_marshalling;
extern pbool opt_logicops;
extern pbool opt_vectorcalls;

extern int optres_shortenifnots;
extern int optres_overlaptemps;
extern int optres_noduplicatestrings;
extern int optres_constantarithmatic;
extern int optres_nonvec_parms;
extern int optres_constant_names;
extern int optres_precache_file;
extern int optres_filenames;
extern int optres_assignments;
extern int optres_unreferenced;
extern int optres_function_names;
extern int optres_locals;
extern int optres_dupconstdefs;
extern int optres_constant_names_strings;
extern int optres_return_only;
extern int optres_compound_jumps;
//extern int optres_comexprremoval;
extern int optres_stripfunctions;
extern int optres_locals_marshalling;
extern int optres_logicops;

pbool CompileParams(progfuncs_t *progfuncs, int doall, int nump, char **parms);

void QCC_PR_PrintStatement (QCC_dstatement_t *s);

void QCC_PR_Lex (void);
// reads the next token into pr_token and classifies its type

QCC_type_t *QCC_PR_NewType (char *name, int basictype);
QCC_type_t *QCC_PR_ParseType (int newtype); extern pbool type_inlinefunction;
QCC_type_t *QCC_TypeForName(char *name);
QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype);
char *QCC_PR_ParseName (void);
CompilerConstant_t *QCC_PR_DefineName(char *name);

void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin);

#ifndef COMMONINLINES
pbool QCC_PR_CheckToken (char *string);
pbool QCC_PR_CheckName (char *string);
void QCC_PR_Expect (char *string);
pbool QCC_PR_CheckKeyword(int keywordenabled, char *string);
#endif
void VARGS QCC_PR_ParseError (int errortype, char *error, ...);
void VARGS QCC_PR_ParseWarning (int warningtype, char *error, ...);
void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...);
void QCC_PR_ParsePrintDef (int warningtype, QCC_def_t *def);
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...);

int QCC_WarningForName(char *name);

//QccMain.c must be changed if this is changed.
enum {
	WARN_DEBUGGING,
	WARN_ERROR,
	WARN_NOTREFERENCED,
	WARN_NOTREFERENCEDCONST,
	WARN_CONFLICTINGRETURNS,
	WARN_TOOFEWPARAMS,
	WARN_TOOMANYPARAMS,
	WARN_UNEXPECTEDPUNCT,
	WARN_ASSIGNMENTTOCONSTANT,
	WARN_ASSIGNMENTTOCONSTANTFUNC,
	WARN_MISSINGRETURNVALUE,
	WARN_WRONGRETURNTYPE,
	WARN_CORRECTEDRETURNTYPE,
	WARN_POINTLESSSTATEMENT,
	WARN_MISSINGRETURN,
	WARN_DUPLICATEDEFINITION,
	WARN_UNDEFNOTDEFINED,
	WARN_PRECOMPILERMESSAGE,
	WARN_TOOMANYPARAMETERSFORFUNC,
	WARN_STRINGTOOLONG,
	WARN_BADTARGET,
	WARN_BADPRAGMA,
	WARN_HANGINGSLASHR,
	WARN_NOTDEFINED,
	WARN_NOTCONSTANT,
	WARN_SWITCHTYPEMISMATCH,
	WARN_CONFLICTINGUNIONMEMBER,
	WARN_KEYWORDDISABLED,
	WARN_ENUMFLAGS_NOTINTEGER,
	WARN_ENUMFLAGS_NOTBINARY,
	WARN_CASEINSENSATIVEFRAMEMACRO,
	WARN_DUPLICATELABEL,
	WARN_DUPLICATEMACRO,
	WARN_ASSIGNMENTINCONDITIONAL,
	WARN_MACROINSTRING,
	WARN_BADPARAMS,
	WARN_IMPLICITCONVERSION,
	WARN_FIXEDRETURNVALUECONFLICT,
	WARN_EXTRAPRECACHE,
	WARN_NOTPRECACHED,
	WARN_DEADCODE,
	WARN_UNREACHABLECODE,
	WARN_NOTSTANDARDBEHAVIOUR,
	WARN_INEFFICIENTPLUSPLUS,
	WARN_DUPLICATEPRECOMPILER,
	WARN_IDENTICALPRECOMPILER,
	WARN_FTE_SPECIFIC,	//extension that only FTEQCC will have a clue about.
	WARN_EXTENSION_USED,	//extension that frikqcc also understands
	WARN_IFSTRING_USED,
	WARN_LAXCAST,	//some errors become this with a compiler flag
	WARN_UNDESIRABLECONVENTION,
	WARN_SAMENAMEASGLOBAL,
	WARN_CONSTANTCOMPARISON,
	WARN_UNSAFEFUNCTIONRETURNTYPE,

	ERR_PARSEERRORS,	//caused by qcc_pr_parseerror being called.

	//these are definatly my fault...
	ERR_INTERNAL,
	ERR_TOOCOMPLEX,
	ERR_BADOPCODE,
	ERR_TOOMANYSTATEMENTS,
	ERR_TOOMANYSTRINGS,
	ERR_BADTARGETSWITCH,
	ERR_TOOMANYTYPES,
	ERR_TOOMANYPAKFILES,
	ERR_PRECOMPILERCONSTANTTOOLONG,
	ERR_MACROTOOMANYPARMS,
	ERR_CONSTANTTOOLONG,
	ERR_TOOMANYFRAMEMACROS,

	//limitations, some are imposed by compiler, some arn't.
	ERR_TOOMANYGLOBALS,
	ERR_TOOMANYGOTOS,
	ERR_TOOMANYBREAKS,
	ERR_TOOMANYCONTINUES,
	ERR_TOOMANYCASES,
	ERR_TOOMANYLABELS,
	ERR_TOOMANYOPENFILES,
	ERR_TOOMANYPARAMETERSVARARGS,
	ERR_TOOMANYTOTALPARAMETERS,

	//these are probably yours, or qcc being fussy.
	ERR_BADEXTENSION,
	ERR_BADIMMEDIATETYPE,
	ERR_NOOUTPUT,
	ERR_NOTAFUNCTION,
	ERR_FUNCTIONWITHVARGS,
	ERR_BADHEX,
	ERR_UNKNOWNPUCTUATION,
	ERR_EXPECTED,
	ERR_NOTANAME,
	ERR_NAMETOOLONG,
	ERR_NOFUNC,
	ERR_COULDNTOPENFILE,
	ERR_NOTFUNCTIONTYPE,
	ERR_TOOFEWPARAMS,
	ERR_TOOMANYPARAMS,
	ERR_CONSTANTNOTDEFINED,
	ERR_BADFRAMEMACRO,
	ERR_TYPEMISMATCH,
	ERR_TYPEMISMATCHREDEC,
	ERR_TYPEMISMATCHPARM,
	ERR_TYPEMISMATCHARRAYSIZE,
	ERR_UNEXPECTEDPUNCTUATION,
	ERR_NOTACONSTANT,
	ERR_REDECLARATION,
	ERR_INITIALISEDLOCALFUNCTION,
	ERR_NOTDEFINED,
	ERR_ARRAYNEEDSSIZE,
	ERR_ARRAYNEEDSBRACES,
	ERR_TOOMANYINITIALISERS,
	ERR_TYPEINVALIDINSTRUCT,
	ERR_NOSHAREDLOCALS,
	ERR_TYPEWITHNONAME,
	ERR_BADARRAYSIZE,
	ERR_NONAME,
	ERR_SHAREDINITIALISED,
	ERR_UNKNOWNVALUE,
	ERR_BADARRAYINDEXTYPE,
	ERR_NOVALIDOPCODES,
	ERR_MEMBERNOTVALID,
	ERR_BADPLUSPLUSOPERATOR,
	ERR_BADNOTTYPE,
	ERR_BADTYPECAST,
	ERR_MULTIPLEDEFAULTS,
	ERR_CASENOTIMMEDIATE,
	ERR_BADSWITCHTYPE,
	ERR_BADLABELNAME,
	ERR_NOLABEL,
	ERR_THINKTIMETYPEMISMATCH,
	ERR_STATETYPEMISMATCH,
	ERR_BADBUILTINIMMEDIATE,
	ERR_PARAMWITHNONAME,
	ERR_BADPARAMORDER,
	ERR_ILLEGALCONTINUES,
	ERR_ILLEGALBREAKS,
	ERR_ILLEGALCASES,
	ERR_NOTANUMBER,
	ERR_WRONGSUBTYPE,
	ERR_EOF,
	ERR_NOPRECOMPILERIF,
	ERR_NOENDIF,
	ERR_HASHERROR,
	ERR_NOTATYPE,
	ERR_TOOMANYPACKFILES,
	ERR_INVALIDVECTORIMMEDIATE,
	ERR_INVALIDSTRINGIMMEDIATE,
	ERR_BADCHARACTERCODE,
	ERR_BADPARMS,
	ERR_WERROR,

	WARN_MAX
};

#define FLAG_KILLSDEBUGGERS	1
#define FLAG_ASDEFAULT		2
#define FLAG_SETINGUI		4
#define FLAG_HIDDENINGUI	8
#define FLAG_MIDCOMPILE		16	//option can be changed mid-compile with the special pragma
typedef struct {
	pbool *enabled;
	char *abbrev;
	int optimisationlevel;
	int flags;	//1: kills debuggers. 2: applied as default.
	char *fullname;
	char *description;
	void *guiinfo;
} optimisations_t;
extern optimisations_t optimisations[];

typedef struct {
	pbool *enabled;
	int flags;	//2 applied as default
	char *abbrev;
	char *fullname;
	char *description;
	void *guiinfo;
} compiler_flag_t;
extern compiler_flag_t compiler_flag[];

extern pbool qccwarningdisabled[WARN_MAX];

extern	jmp_buf		pr_parse_abort;		// longjump with this on parse error
extern	int			pr_source_line;
extern	char		*pr_file_p;

void *QCC_PR_Malloc (int size);


#define	OFS_NULL		0
#define	OFS_RETURN		1
#define	OFS_PARM0		4		// leave 3 ofs for each parm to hold vectors
#define	OFS_PARM1		7
#define	OFS_PARM2		10
#define	OFS_PARM3		13
#define	OFS_PARM4		16
#define	RESERVED_OFS	28


extern	QCC_def_t	*pr_scope;
extern	int		pr_error_count, pr_warning_count;

void QCC_PR_NewLine (pbool incomment);
QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, pbool saved);

void QCC_PR_PrintDefs (void);

void QCC_PR_SkipToSemicolon (void);

#define MAX_EXTRA_PARMS 128
#ifdef MAX_EXTRA_PARMS
extern	char		pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
extern QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
#else
extern	char		pr_parm_names[MAX_PARMS][MAX_NAME];
#endif
extern	pbool	pr_trace;

#define	G_FLOAT(o) (qcc_pr_globals[o])
#define	G_INT(o) (*(int *)&qcc_pr_globals[o])
#define	G_VECTOR(o) (&qcc_pr_globals[o])
#define	G_STRING(o) (strings + *(QCC_string_t *)&qcc_pr_globals[o])
#define	G_FUNCTION(o) (*(func_t *)&qcc_pr_globals[o])

char *QCC_PR_ValueString (etype_t type, void *val);

void QCC_PR_ClearGrabMacros (void);

pbool	QCC_PR_CompileFile (char *string, char *filename);
void QCC_PR_ResetErrorScope(void);

extern	pbool	pr_dumpasm;

extern	QCC_string_t	s_file;			// filename for function definition

extern	QCC_def_t	def_ret, def_parms[MAX_PARMS];

void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname);
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname);

//=============================================================================

extern char	pr_immediate_string[8192];

extern float		*qcc_pr_globals;
extern unsigned int	numpr_globals;

extern char		*strings;
extern int			strofs;

extern QCC_dstatement_t	*statements;
extern int			numstatements;
extern int			*statement_linenums;

extern QCC_dfunction_t	*functions;
extern int			numfunctions;

extern QCC_ddef_t		*qcc_globals;
extern int			numglobaldefs;

extern QCC_def_t		*activetemps;

extern QCC_ddef_t		*fields;
extern int			numfielddefs;

extern QCC_type_t *qcc_typeinfo;
extern int numtypeinfos;
extern int maxtypeinfos;

extern int ForcedCRC;
extern pbool defaultstatic;

extern int *qcc_tempofs;
extern int max_temps;
//extern int qcc_functioncalled;	//unuse temps if this is true - don't want to reuse the same space.

extern int tempsstart;
extern int numtemps;

typedef char PATHSTRING[MAX_DATA_PATH];

extern PATHSTRING		*precache_sounds;
extern int			*precache_sounds_block;
extern int			*precache_sounds_used;
extern int			numsounds;

extern PATHSTRING		*precache_textures;
extern int			*precache_textures_block;
extern int			numtextures;

extern PATHSTRING		*precache_models;
extern int			*precache_models_block;
extern int			*precache_models_used;
extern int			nummodels;

extern PATHSTRING		*precache_files;
extern int			*precache_files_block;
extern int			numfiles;

int	QCC_CopyString (char *str);




typedef struct qcc_cachedsourcefile_s {
	char filename[128];
	int size;
	char *file;
	enum{FT_CODE, FT_DATA} type;	//quakec source file or not.
	struct qcc_cachedsourcefile_s *next;
} qcc_cachedsourcefile_t;
extern qcc_cachedsourcefile_t *qcc_sourcefile;





#ifdef COMMONINLINES
static bool inline QCC_PR_CheckToken (char *string)
{
	if (pr_token_type != tt_punct)
		return false;

	if (STRCMP (string, pr_token))
		return false;

	QCC_PR_Lex ();
	return true;
}

static void inline QCC_PR_Expect (char *string)
{
	if (strcmp (string, pr_token))
		QCC_PR_ParseError ("expected %s, found %s",string, pr_token);
	QCC_PR_Lex ();
}
#endif

void editbadfile(char *fname, int line);
char *TypeName(QCC_type_t *type);
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename);
void QCC_PR_IncludeChunkEx(char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst);
pbool QCC_PR_UnInclude(void);
extern void *(*pHash_Get)(hashtable_t *table, char *name);
extern void *(*pHash_GetNext)(hashtable_t *table, char *name, void *old);
extern void *(*pHash_Add)(hashtable_t *table, char *name, void *data, bucket_t *);