rewrote huge chunks of qcc code to track which symbols were used where.

this makes inlining more efficient, and allows stripping irrelevant defs.
(there may still be things broken due to this)
gui version behaves a little better now, and saves debug+optimisation etc settings on a per-mod basis, instead of using the windows registry to store which engine+path+args to run.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4850 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-04-14 12:24:05 +00:00
parent 178a0117ff
commit 18de6445ba
15 changed files with 5216 additions and 4328 deletions

View File

@ -9,13 +9,22 @@ LIB_OBJS=
CC?=gcc
CFLAGS?=-Wall
all: qcc
all: help qcc
help:
@echo for fteqccgui: win or nocyg
@echo for commandline: qcc
@echo for debug builds, add: DEBUG=1
@echo
USEGUI_CFLAGS=
# set to -DUSEGUI when compiling the GUI
BASE_CFLAGS=-ggdb $(USEGUI_CFLAGS)
BASE_CFLAGS=$(USEGUI_CFLAGS)
BASE_LDFLAGS=-s
ifneq ($(DEBUG),)
BASE_CFLAGS+=-ggdb
else
BASE_LDFLAGS+=-s
endif
# set to "" for debugging
DO_CC?=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS)

View File

@ -236,7 +236,10 @@ int QC_strncasecmp(const char *s1, const char *s2, int n)
void editbadfile(char *fname, int line)
{
strcpy(errorfile, fname);
errorline = line;
if (!*errorfile)
{
strcpy(errorfile, fname);
errorline = line;
}
}

View File

@ -57,9 +57,15 @@ cont: //last statement may have been a breakpoint
case ev_float:
printf("Watch point hit in %s, \"%s\" changed from %g to %g.\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), prinst.watch_name, prinst.watch_old._float, prinst.watch_ptr->_float);
break;
case ev_vector:
printf("Watch point hit in %s, \"%s\" changed from '%g %g %g' to '%g %g %g'.\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), prinst.watch_name, prinst.watch_old._vector[0], prinst.watch_old._vector[1], prinst.watch_old._vector[2], prinst.watch_ptr->_vector[0], prinst.watch_ptr->_vector[1], prinst.watch_ptr->_vector[2]);
break;
default:
printf("Watch point hit in %s, \"%s\" changed from %i to %i.\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), prinst.watch_name, prinst.watch_old._int, prinst.watch_ptr->_int);
break;
case ev_entity:
printf("Watch point hit in %s, \"%s\" changed from %i(%s) to %i(%s).\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), prinst.watch_name, prinst.watch_old._int, PR_GetEdictClassname(progfuncs, prinst.watch_old._int), prinst.watch_ptr->_int, PR_GetEdictClassname(progfuncs, prinst.watch_ptr->_int));
break;
case ev_function:
case ev_string:
printf("Watch point hit in %s, \"%s\" now set to %s.\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), prinst.watch_name, PR_ValueString(progfuncs, prinst.watch_type, prinst.watch_ptr, false));
@ -364,7 +370,10 @@ reeval:
{
if (OPB->_int == -1)
break;
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
if (OPB->_int == 0)
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (null pointer)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
else
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_int = OPA->_int;

View File

@ -1,6 +1,6 @@
void GoToDefinition(char *name);
int Grep(char *filename, char *string);
void EditFile(char *name, int line);
void EditFile(char *name, int line, pbool setcontrol);
void GUI_SetDefaultOpts(void);
int GUI_BuildParms(char *args, char **argv, pbool quick);
@ -17,6 +17,7 @@ extern char progssrcdir[256];
extern pbool fl_nondfltopts;
extern pbool fl_hexen2;
extern pbool fl_ftetarg;
extern pbool fl_autohighlight;
extern pbool fl_compileonstart;
extern pbool fl_showall;

View File

@ -363,6 +363,7 @@ enum qcop_e {
OP_MULSTOREP_VI,
OP_LOADA_STRUCT,
OP_LOADP_P,
OP_STOREP_P,
OP_BITNOT_F,
@ -397,6 +398,9 @@ enum qcop_e {
OP_RSHIFT_F,
OP_LSHIFT_F,
OP_AND_ANY,
OP_OR_ANY, //190
OP_NUMOPS
};
@ -445,11 +449,17 @@ typedef struct statement32_s
#define QCC_dstatement16_t dstatement16_t
#define QCC_dstatement32_t dstatement32_t
typedef struct
{
struct QCC_def_s *sym;
unsigned int ofs;
struct QCC_type_s *cast; //the entire sref is considered null if there is no cast, although it *MAY* have an ofs specified if its part of a jump instruction
} QCC_sref_t;
typedef struct qcc_statement_s
{
unsigned int op;
unsigned int a,b,c;
unsigned int linenum;
unsigned int op;
QCC_sref_t a, b, c;
unsigned int linenum;
} QCC_statement_t;
//these should be the same except the string type
@ -505,20 +515,6 @@ typedef struct
int numparms;
qbyte parm_size[MAX_PARMS];
} dfunction_t;
typedef struct
{
unsigned int first_statement; // negative numbers are builtins
unsigned int parm_start;
int locals; // total ints of parms + locals
int profile; // runtime
QCC_string_t s_name;
QCC_string_t s_file; // source file defined in
int numparms;
qbyte parm_size[MAX_PARMS];
} QCC_dfunction_t;
typedef struct
{

View File

@ -515,6 +515,9 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val, pbool v
if (current_progstate && pr_types)
type = pr_types[type].type;
if (!val)
type = ev_void;
switch (type)
{
case ev_struct:
@ -1440,7 +1443,7 @@ char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buf, int *bufofs, int bufmax
ddef16_t *def16;
unsigned int i;
unsigned int j;
char *name;
const char *name;
int type;
int curprogs = pr_typecurrent;
int len;
@ -1515,9 +1518,11 @@ char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buf, int *bufofs, int bufmax
case PST_FTE32:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
size_t nlen;
def32 = &pr_globaldefs32[i];
name = def32->s_name + progfuncs->funcs.stringtable;
if (name[strlen(name)-2] == '_')
name = PR_StringToNative(&progfuncs->funcs, def32->s_name);
nlen = strlen(name);
if (nlen >= 3 && name[nlen-2] == '_')
continue; // skip _x, _y, _z vars (vector components, which are saved as one vector not 3 floats)
type = def32->type;
@ -2523,6 +2528,62 @@ void PR_TestForWierdness(progfuncs_t *progfuncs)
}
#endif
*/
void PR_CleanUpStatements16(progfuncs_t *progfuncs, dstatement16_t *st, pbool hexencalling)
{
unsigned int numst = pr_progs->numstatements;
unsigned int numglob = pr_progs->numglobals+3; //+3 because I'm too lazy to deal with vectors
unsigned int i;
for (i=0 ; i<numst ; i++)
{
if (st[i].op >= OP_CALL1 && st[i].op <= OP_CALL8 && hexencalling)
st[i].op += OP_CALL1H - OP_CALL1;
if (st[i].op >= OP_RAND0 && st[i].op <= OP_RANDV2 && hexencalling)
if (!st[i].c)
st[i].c = OFS_RETURN;
if (st[i].a < 0 || st[i].a >= numglob)
if (st[i].op != OP_GOTO)
st[i].op = ~0;
if (st[i].b < 0 || st[i].b >= numglob)
if (st[i].op != OP_IFNOT_I && st[i].op != OP_IF_I &&
st[i].op != OP_IFNOT_F && st[i].op != OP_IF_F &&
st[i].op != OP_IFNOT_S && st[i].op != OP_IF_S &&
st[i].op != OP_BOUNDCHECK && st[i].op != OP_CASE)
st[i].op = ~0;
if (st[i].c < 0 || st[i].c >= numglob)
if (st[i].op != OP_BOUNDCHECK && st[i].op != OP_CASERANGE)
st[i].op = ~0;
}
}
void PR_CleanUpStatements32(progfuncs_t *progfuncs, dstatement32_t *st, pbool hexencalling)
{
unsigned int numst = pr_progs->numstatements;
unsigned int numglob = pr_progs->numglobals+3; //+3 because I'm too lazy to deal with vectors
unsigned int i;
for (i=0 ; i<numst ; i++)
{
if (st[i].op >= OP_CALL1 && st[i].op <= OP_CALL8 && hexencalling)
st[i].op += OP_CALL1H - OP_CALL1;
if (st[i].op >= OP_RAND0 && st[i].op <= OP_RANDV2 && hexencalling)
if (!st[i].c)
st[i].c = OFS_RETURN;
if (st[i].a < 0 || st[i].a >= numglob)
if (st[i].op != OP_GOTO)
st[i].op = ~0;
if (st[i].b < 0 || st[i].b >= numglob)
if (st[i].op != OP_IFNOT_I && st[i].op != OP_IF_I &&
st[i].op != OP_IFNOT_F && st[i].op != OP_IF_F &&
st[i].op != OP_IFNOT_S && st[i].op != OP_IF_S &&
st[i].op != OP_BOUNDCHECK)
st[i].op = ~0;
if (st[i].c < 0 || st[i].c >= numglob)
if (st[i].op != OP_BOUNDCHECK)
st[i].op = ~0;
}
}
char *decode(int complen, int len, int method, char *info, char *buffer);
/*
===============
@ -2798,7 +2859,7 @@ retry:
if (pr_progs->blockscompressed & 32) //globals
{
len=sizeof(float)*pr_progs->numglobals;
s = PRHunkAlloc(progfuncs, len, "dglobaltable");
s = PRHunkAlloc(progfuncs, len + sizeof(float)*2, "dglobaltable");
QC_decode(progfuncs, PRLittleLong(*(int *)pr_globals), len, 2, (char *)(((int *)pr_globals)+1), s);
glob = pr_globals = (float *)s;
@ -2827,7 +2888,7 @@ retry:
pr_strings = (char *)s;
len=sizeof(float)*pr_progs->numglobals;
s = PRAddressableExtend(progfuncs, len);
s = PRAddressableExtend(progfuncs, len + sizeof(float)*2);
memcpy(s, pr_globals, len);
glob = pr_globals = (float *)s;
@ -3115,6 +3176,7 @@ retry:
// could use the line info as lno information maybe? is it really worth it?
// also never assuming h2 calling mechanism
}
PR_CleanUpStatements16(progfuncs, st16, false);
break;
case PST_DEFAULT:
for (i=0 ; i<pr_progs->numstatements ; i++)
@ -3134,17 +3196,7 @@ retry:
}
}
}
if (hexencalling)
{
for (i=0 ; i<pr_progs->numstatements ; i++)
{
if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8)
st16[i].op += OP_CALL1H - OP_CALL1;
if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2)
if (!st16[i].c)
st16[i].c = OFS_RETURN;
}
}
PR_CleanUpStatements16(progfuncs, st16, hexencalling);
break;
case PST_KKQWSV: //24 sucks. Guess why.
@ -3166,17 +3218,7 @@ retry:
}
}
}
if (hexencalling)
{
for (i=0 ; i<pr_progs->numstatements ; i++)
{
if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
pr_statements32[i].op += OP_CALL1H - OP_CALL1;
if (pr_statements32[i].op >= OP_RAND0 && pr_statements32[i].op <= OP_RANDV2)
if (!pr_statements32[i].c)
pr_statements32[i].c = OFS_RETURN;
}
}
PR_CleanUpStatements32(progfuncs, pr_statements32, hexencalling);
break;
}
@ -3225,7 +3267,7 @@ retry:
break;
case ev_string:
if (((unsigned int *)glob)[gd16[i].ofs]>=progstate->progs->numstrings)
printf("Insane value\n");
printf("PR_LoadProgs: invalid string value (%x >= %x) in '%s'\n", ((unsigned int *)glob)[gd16[i].ofs], progstate->progs->numstrings, gd16[i].s_name+pr_strings-stringadjust);
else if (isfriked != -1)
{
if (pr_strings[((int *)glob)[gd16[i].ofs]]) //quakec uses string tables. 0 must remain null, or 'if (s)' can break.

View File

@ -140,6 +140,7 @@ void PDECL PR_GenerateStatementString (pubprogfuncs_t *ppf, int statementnum, ch
default:
return;
}
op = op & ~0x8000; //break points.
if (current_progstate->linenums)
{
@ -244,6 +245,7 @@ static void PDECL PR_PrintRelevantLocals(progfuncs_t *progfuncs)
ddef16_t *fld = ED_GlobalAtOfs16(progfuncs, st16[st].b);
pbool skip = false;
edictrun_t *ed;
unsigned int entnum;
eval_t *ptr;
fdef_t *fdef;
fdef_t *cnfd;
@ -265,17 +267,26 @@ static void PDECL PR_PrintRelevantLocals(progfuncs_t *progfuncs)
}
if (skip)
continue;
ed = PROG_TO_EDICT(progfuncs, ((eval_t *)&pr_globals[st16[st].a])->edict);
ptr = (eval_t *)(((int *)edvars(ed)) + ((eval_t *)&pr_globals[st16[st].b])->_int + progfuncs->funcs.fieldadjust);
cnfd = ED_FindField(progfuncs, "classname");
if (cnfd)
entnum = ((eval_t *)&pr_globals[st16[st].a])->edict;
if (entnum >= sv_num_edicts)
{
string_t *v = (string_t *)((char *)edvars(ed) + cnfd->ofs*4);
classname = PR_StringToNative(&progfuncs->funcs, *v);
classname = "INVALID";
ptr = NULL;
}
else
classname = "";
{
ed = PROG_TO_EDICT(progfuncs, entnum);
ptr = (eval_t *)(((int *)edvars(ed)) + ((eval_t *)&pr_globals[st16[st].b])->_int + progfuncs->funcs.fieldadjust);
cnfd = ED_FindField(progfuncs, "classname");
if (cnfd)
{
string_t *v = (string_t *)((char *)edvars(ed) + cnfd->ofs*4);
classname = PR_StringToNative(&progfuncs->funcs, *v);
}
else
classname = "";
}
if (*classname)
fdef = ED_ClassFieldAtOfs(progfuncs, ((eval_t *)&pr_globals[st16[st].b])->_int, classname);
else
@ -296,6 +307,7 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
int progs;
int arg;
int *globalbase;
int tracing = progfuncs->funcs.debug_trace;
progs = -1;
if (pr_depth == 0)
@ -304,6 +316,8 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
return;
}
progfuncs->funcs.debug_trace = -10;
//point this to the function's locals
globalbase = (int *)pr_globals + pr_xfunction->parm_start + pr_xfunction->locals;
@ -328,13 +342,13 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
printf ("<%s>\n", pr_progstate[progs].filename);
}
if (!f->s_file)
printf ("stripped : %s\n", f->s_name+progfuncs->funcs.stringtable);
printf ("stripped : %s\n", PR_StringToNative(ppf, f->s_name));
else
{
if (pr_progstate[progs].linenums)
printf ("%12s:%i: %s\n", f->s_file+progfuncs->funcs.stringtable, pr_progstate[progs].linenums[pr_stack[i].s], f->s_name+progfuncs->funcs.stringtable);
printf ("%12s:%i: %s\n", PR_StringToNative(ppf, f->s_file), pr_progstate[progs].linenums[pr_stack[i].s], PR_StringToNative(ppf, f->s_name));
else
printf ("%12s : %s\n", f->s_file+progfuncs->funcs.stringtable, f->s_name+progfuncs->funcs.stringtable);
printf ("%12s : %s\n", PR_StringToNative(ppf, f->s_file), PR_StringToNative(ppf, f->s_name));
}
//locals:0 = no locals
@ -365,6 +379,7 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
globalbase = localstack + localstack_used;
}
}
progfuncs->funcs.debug_trace = tracing;
}
/*
@ -714,6 +729,14 @@ char *PDECL PR_EvaluateDebugString(pubprogfuncs_t *ppf, char *key)
etype_t type;
eval_t fakeval;
if (*key == '&')
{
if (!LocateDebugTerm(progfuncs, key+1, &val, &type, &fakeval) && val != &fakeval)
return "(unable to evaluate)";
QC_snprintfz(buf, sizeof(buf), "%#x", (char*)val - progfuncs->funcs.stringtable);
return buf;
}
assignment = strchr(key, '=');
if (assignment)
*assignment = '\0';
@ -1286,6 +1309,18 @@ pbool PR_RunWarning (pubprogfuncs_t *ppf, char *error, ...)
return false;
}
//For debugging. Assumes classname field exists.
const char *PR_GetEdictClassname(progfuncs_t *progfuncs, int edict)
{
fdef_t *cnfd = ED_FindField(progfuncs, "classname");
if (cnfd && edict < maxedicts)
{
string_t *v = (string_t *)((char *)edvars(PROG_TO_EDICT(progfuncs, edict)) + cnfd->ofs*4);
return PR_StringToNative(&progfuncs->funcs, *v);
}
return "";
}
static pbool casecmp_f(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) {return ref->_float == val->_float;}
static pbool casecmp_i(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) {return ref->_int == val->_int;}
@ -1454,9 +1489,15 @@ static void PR_ExecuteCode (progfuncs_t *progfuncs, int s)
case ev_float:
printf("Watch point \"%s\" changed by engine from %g to %g.\n", prinst.watch_name, prinst.watch_old._float, prinst.watch_ptr->_float);
break;
case ev_vector:
printf("Watch point \"%s\" changed by engine from '%g %g %g' to '%g %g %g'.\n", prinst.watch_name, prinst.watch_old._vector[0], prinst.watch_old._vector[1], prinst.watch_old._vector[2], prinst.watch_ptr->_vector[0], prinst.watch_ptr->_vector[1], prinst.watch_ptr->_vector[2]);
break;
default:
printf("Watch point \"%s\" changed by engine from %i to %i.\n", prinst.watch_name, prinst.watch_old._int, prinst.watch_ptr->_int);
break;
case ev_entity:
printf("Watch point \"%s\" changed by engine from %i(%s) to %i(%s).\n", prinst.watch_name, prinst.watch_old._int, PR_GetEdictClassname(progfuncs, prinst.watch_old._int), prinst.watch_ptr->_int, PR_GetEdictClassname(progfuncs, prinst.watch_ptr->_int));
break;
case ev_function:
case ev_string:
printf("Watch point \"%s\" set by engine to %s.\n", prinst.watch_name, PR_ValueString(progfuncs, prinst.watch_type, prinst.watch_ptr, false));

View File

@ -294,6 +294,28 @@ typedef struct QCC_function_s QCC_function_t;
#define MAX_PARMS 8
//keep this sizeof(float)
typedef union QCC_eval_s
{
QCC_string_t string;
float _float;
float vector[1];
func_t function;
int _int;
// union QCC_eval_s *ptr;
} QCC_eval_t;
//must be the maximum size possible for a single basic type.
typedef union QCC_evalstorage_s
{
QCC_string_t string;
float _float;
float vector[3];
func_t function;
int _int;
// union QCC_eval_s *ptr;
} QCC_evalstorage_t;
struct QCC_typeparam_s
{
struct QCC_type_s *type;
@ -307,7 +329,7 @@ struct accessor_s
struct accessor_s *next;
struct QCC_type_s *type;
struct QCC_type_s *indexertype; //null if not indexer
struct QCC_def_s *getset_func[2];
QCC_sref_t getset_func[2];
pbool getset_isref[2];
char *fieldname;
};
@ -335,18 +357,9 @@ typedef struct QCC_type_s
int typecmp(QCC_type_t *a, QCC_type_t *b);
int typecmp_lax(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
int laststatement;
struct temp_s *next;
int used;
unsigned int size;
} temp_t;
typedef struct temp_s temp_t;
void QCC_PurgeTemps(void);
void QCC_FinaliseTemps(void);
//not written
typedef struct QCC_def_s
@ -357,30 +370,52 @@ typedef struct QCC_def_s
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
struct QCC_function_s *scope; // function the var was defined in, or NULL
struct QCC_def_s *deftail; // arrays and structs create multiple globaldef objects providing different types at the different parts of the single object (struct), or alternative names (vectors). this allows us to correctly set the const type based upon how its initialised.
struct QCC_def_s *generatedfor;
int initialized; // 1 when a declaration included "= immediate". 2 = extern. 3 = don't warn (unless actually called)
int constant; // 1 says we can use the value over and over again
int references;
struct QCC_def_s *symbolheader; //this is the original symbol within which the def is stored.
union QCC_eval_s *symboldata; //null if uninitialised.
unsigned int symbolsize; //total byte size of symbol
int refcount; //if 0, temp can be reused. tracked on globals too in order to catch bugs that would otherwise be a little too obscure.
int timescalled; //part of the opt_stripfunctions optimisation.
int s_file;
int s_line;
int arraysize;
pbool shared:1;
pbool saved:1;
pbool isstatic:1;
pbool subscoped_away:1;
pbool followptr:1;
pbool strip:1;
pbool allowinline:1;
//should really use proper flags
pbool funccalled:1; //was called somewhere.
pbool read:1; //variable was read
pbool written:1; //variable was written
pbool referenced:1; //was used somewhere in the code (even if it can still be stripped). this controls warnings only.
pbool shared:1; //weird multiprogs flag thing.
pbool saved:1; //def may be saved to saved games.
pbool isstatic:1; //global, even if scoped. also specific to the file it was seen in.
pbool subscoped_away:1; //this local is no longer linked into the locals hash table. don't do remove it twice.
// pbool followptr:1;
pbool strip:1; //info about this def should be stripped. it may still consume globals space however, and its storage can still be used, its just not visible.
pbool allowinline:1; //calls to this function will attempt to inline the specified function. requires const, supposedly.
pbool used:1; //if it remains 0, it may be stripped. this is forced for functions and fields. commonly 0 on fields.
pbool localscope:1; //is a local, as opposed to a static (which is only visible within its scope)
int fromstatement; //statement that it is valid from.
temp_t *temp;
} QCC_def_t;
struct temp_s {
QCC_def_t *def;
unsigned char locked;
unsigned int size;
struct QCC_function_s *lastfunc;
unsigned int laststatement;
};
extern size_t tempsused;
typedef struct
{
enum{
@ -393,8 +428,8 @@ typedef struct
REF_ACCESSOR //buf_create()[5]
} type;
QCC_def_t *base;
QCC_def_t *index;
QCC_sref_t base;
QCC_sref_t index;
QCC_type_t *cast; //entity.float is float, not pointer.
struct accessor_s *accessor; //the accessor field of base that we're trying to use
int postinc; //+1 or -1
@ -411,16 +446,6 @@ 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];
@ -428,11 +453,16 @@ extern QCC_type_t *type_void, *type_string, *type_float, *type_vector, *type_ent
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;
int builtin; // the builtin number. >= 0
int code; // first statement. if -1, is a builtin.
string_t s_file; // source file with definition
const char *file;
int line;
char *name; //internal name of function
struct QCC_type_s *type; //same as the def's type
struct QCC_def_s *def;
struct QCC_def_s *firstlocal;
pbool privatelocals; //false means locals may overlap with other functions, true is needed for compat if stuff is uninitialised.
// unsigned int parm_ofs[MAX_PARMS]; // always contiguous, right?
};
@ -449,9 +479,10 @@ typedef struct
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.
QCC_def_t local_head; // chain of variables which need to be pushed and stuff (head unused).
QCC_def_t *local_tail; // add new defs after this and move it
int size_fields;
unsigned int size_fields;
} QCC_pr_info_t;
extern QCC_pr_info_t pr;
@ -490,7 +521,7 @@ extern token_type_t pr_token_type;
extern int pr_token_line;
extern int pr_token_line_last;
extern QCC_type_t *pr_immediate_type;
extern QCC_eval_t pr_immediate;
extern QCC_evalstorage_t pr_immediate;
extern pbool keyword_asm;
extern pbool keyword_break;
@ -524,6 +555,8 @@ extern pbool keyword_extern; //function is external, don't error or warn if the
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_inline; //don't write the def to the output.
extern pbool keyword_strip; //don't write the def to the output.
extern pbool keyword_union; //you surly know what a union is!
@ -531,8 +564,7 @@ extern pbool keywords_coexist;
extern pbool output_parms;
extern pbool autoprototype, autoprototyped, parseonly;
extern pbool pr_subscopedlocals;
extern pbool flag_ifstring;
extern pbool flag_iffloat;
extern pbool flag_nullemptystr, flag_ifstring, flag_iffloat, flag_ifvector, flag_vectorlogic;
extern pbool flag_acc;
extern pbool flag_caseinsensitive;
extern pbool flag_laxcasts;
@ -608,26 +640,26 @@ 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);
int QCC_PR_IntConstExpr(void);
#ifndef COMMONINLINES
pbool QCC_PR_CheckImmediate (char *string);
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);
pbool QCC_PR_CheckImmediate (const char *string);
pbool QCC_PR_CheckToken (const char *string);
pbool QCC_PR_CheckName (const char *string);
void QCC_PR_Expect (const char *string);
pbool QCC_PR_CheckKeyword(int keywordenabled, const char *string);
#endif
pbool QCC_PR_CheckTokenComment(char *string, char **comment);
void VARGS QCC_PR_ParseError (int errortype, char *error, ...);
pbool VARGS QCC_PR_ParseWarning (int warningtype, char *error, ...);
pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...);
void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...);
pbool QCC_PR_CheckTokenComment(const char *string, char **comment);
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...);
pbool VARGS QCC_PR_ParseWarning (int warningtype, const char *error, ...);
pbool VARGS QCC_PR_Warning (int type, const char *file, int line, const char *error, ...);
void VARGS QCC_PR_Note (int type, const char *file, int line, const 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, ...);
void QCC_PR_ParsePrintSRef (int warningtype, QCC_sref_t sref);
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...);
void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t sref, const char *error, ...);
int QCC_WarningForName(char *name);
int QCC_WarningForName(const char *name);
char *QCC_NameForWarning(int idx);
//QccMain.c must be changed if this is changed.
@ -672,7 +704,6 @@ enum {
WARN_MACROINSTRING,
WARN_BADPARAMS,
WARN_IMPLICITCONVERSION,
WARN_FIXEDRETURNVALUECONFLICT,
WARN_EXTRAPRECACHE,
WARN_NOTPRECACHED,
WARN_DEADCODE,
@ -698,6 +729,7 @@ enum {
WARN_UNARYNOTSCOPE, //!foo & bar the ! applies to the result of &. This is unlike C.
WARN_STRICTTYPEMISMATCH, //self.think = T_Damage; both are functions, but the arguments/return types/etc differ.
WARN_MISUSEDAUTOCVAR, //various issues with autocvar definitions.
WARN_IGNORECOMMANDLINE,
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
@ -845,7 +877,7 @@ void *QCC_PR_Malloc (int size);
#define RESERVED_OFS 28
extern QCC_def_t *pr_scope;
extern struct QCC_function_s *pr_scope;
extern int pr_error_count, pr_warning_count;
void QCC_PR_NewLine (pbool incomment);
@ -856,7 +888,10 @@ void QCC_PR_NewLine (pbool incomment);
#define GDF_STRIP 8 //always stripped, regardless of optimisations. used for class member fields
#define GDF_SILENT 16 //used by the gui, to suppress ALL warnings.
#define GDF_INLINE 32 //attempt to inline calls to this function
QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, unsigned int flags);
#define GDF_USED 64 //don't strip this, ever.
QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
QCC_sref_t QCC_PR_GetSRef (QCC_type_t *type, char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
void QCC_FreeTemp(QCC_sref_t t);
char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend);
void QCC_PR_PrintDefs (void);
@ -867,17 +902,11 @@ extern char *pr_parm_argcount_name;
#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];
extern QCC_sref_t extra_parms[MAX_EXTRA_PARMS];
#else
extern char pr_parm_names[MAX_PARMS][MAX_NAME];
#endif
#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 (pbool newfile);
@ -891,22 +920,21 @@ 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, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype);
void QCC_PR_EmitArrayGetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitArraySetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *defscope, QCC_type_t *basetype);
void PostCompile(void);
pbool PreCompile(void);
void QCC_Cleanup(void);
#define FIRST_LOCAL (MAX_REGS)
#define FIRST_TEMP (MAX_REGS+MAX_LOCALS)
#define FIRST_LOCAL 0//(MAX_REGS)
//=============================================================================
extern char pr_immediate_string[8192];
extern float *qcc_pr_globals;
extern QCC_eval_t *qcc_pr_globals;
extern unsigned int numpr_globals;
extern char *strings;
@ -915,7 +943,8 @@ extern int strofs;
extern QCC_statement_t *statements;
extern int numstatements;
extern QCC_dfunction_t *functions;
extern QCC_function_t *functions;
extern dfunction_t *dfunctions;
extern int numfunctions;
extern QCC_ddef_t *qcc_globals;

View File

@ -137,7 +137,7 @@ void QC_strlcat(char *dest, const char *src, size_t destsize)
}
void QC_strlcpy(char *dest, const char *src, size_t destsize)
{
size_t curlen = strlen(dest);
size_t curlen = 0;
if (!destsize)
return; //err
while(*src && ++curlen < destsize)
@ -148,7 +148,7 @@ void QC_strlcpy(char *dest, const char *src, size_t destsize)
}
void QC_strnlcpy(char *dest, const char *src, size_t srclen, size_t destsize)
{
size_t curlen = strlen(dest);
size_t curlen = 0;
if (!destsize)
return; //err
for(; *src && srclen > 0 && ++curlen < destsize; srclen--)
@ -502,32 +502,6 @@ char *VARGS qcva (char *text, ...)
#if !defined(MINIMAL) && !defined(OMIT_QCC)
char *QC_strupr (char *start)
{
char *in;
in = start;
while (*in)
{
*in = toupper(*in);
in++;
}
return start;
}
char *QC_strlower (char *start)
{
char *in;
in = start;
while (*in)
{
*in = tolower(*in);
in++;
}
return start;
}
/*
=============================================================================
@ -969,7 +943,7 @@ unsigned int utf8_check(const void *in, unsigned int *value)
//read utf-16 chars and output the 'native' utf-8.
//we don't expect essays written in code, so we don't need much actual support for utf-8.
static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, int *outlen, pbool usemalloc)
static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, unsigned int *outlen, pbool usemalloc)
{
char *utf8, *start;
unsigned int inc;
@ -995,7 +969,7 @@ static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, in
break;
default:
*outlen = inbytes;
return inputf;
return (char*)inputf;
}
chars = inbytes / w;
if (usemalloc)
@ -1136,15 +1110,20 @@ unsigned short *QCC_makeutf16(char *mem, unsigned int len, int *outlen)
long QCC_LoadFile (char *filename, void **bufferptr)
{
char *mem;
int len;
len = externs->FileSize(filename);
if (len < 0)
int check;
int flen;
unsigned int len;
int line;
pbool warned = false;
flen = externs->FileSize(filename);
if (flen < 0)
{
QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
// if (!externs->Abort)
return -1;
// externs->Abort("failed to find file %s", filename);
}
len = flen;
mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+2);
((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
@ -1171,6 +1150,20 @@ long QCC_LoadFile (char *filename, void **bufferptr)
//its only in strings where it actually makes a difference, and the interpretation of those is basically entirely up to the engine.
//that said, we could insert a utf-8 BOM into ones with utf-8 chars, but that would mess up a lot of builtins+mods, so we won't.
for (check = 0, line = 1; check < len; check++)
{
if (mem[check] == '\n')
line++;
else if (!mem[check])
{
if (!warned)
QCC_PR_Warning(WARN_UNEXPECTEDPUNCT, filename, line, "file contains null bytes %u/%u", check, len);
warned = true;
//fixme: insert modified-utf-8 nulls instead.
mem[check] = ' ';
}
}
mem[len] = '\n';
mem[len+1] = '\0';

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ char *QCC_PR_CheckCompConstString(char *def);
CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
int QCC_PR_CheckCompConst(void);
pbool QCC_Include(char *filename);
void QCC_FreeDef(QCC_def_t *def);
char *compilingfile;
@ -31,7 +32,7 @@ token_type_t pr_token_type;
int pr_token_line;
int pr_token_line_last;
QCC_type_t *pr_immediate_type;
QCC_eval_t pr_immediate;
QCC_evalstorage_t pr_immediate;
char pr_immediate_string[8192];
@ -46,7 +47,7 @@ extern pbool expandedemptymacro;
//really these should not be in here
extern unsigned int locals_end, locals_start;
extern QCC_type_t *pr_classtype;
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type);
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type);
static void Q_strlcpy(char *dest, const char *src, int sizeofdest)
@ -981,41 +982,57 @@ pbool QCC_PR_Precompiler(void)
extern pbool qcc_nopragmaoptimise;
if (pr_scope)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s: unable to change optimisation options mid-function", qcc_token);
else if (qcc_nopragmaoptimise)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s %s: overriden by commandline", qcc_token, msg);
else if (*msg >= '0' && *msg <= '3')
{
int lev = atoi(msg);
pbool state;
int once = false;
for (o = 0; optimisations[o].enabled; o++)
{
if (optimisations[o].optimisationlevel <= lev)
*optimisations[o].enabled = true;
state = optimisations[o].optimisationlevel <= lev;
if (qcc_nopragmaoptimise && *optimisations[o].enabled != state)
{
if (!once++)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s %s: overriden by commandline", qcc_token, msg);
}
else
*optimisations[o].enabled = state;
}
}
else if (!strnicmp(msg, "addon", 5) || !strnicmp(msg, "mutator", 7))
{
int lev = 2;
pbool state = false;
for (o = 0; optimisations[o].enabled; o++)
{
if (optimisations[o].optimisationlevel > lev)
{
if (qcc_nopragmaoptimise && *optimisations[o].enabled != state)
QCC_PR_ParseWarning(WARN_IGNORECOMMANDLINE, "pragma %s %s: disabling %s", qcc_token, msg, optimisations[o].fullname);
*optimisations[o].enabled = state;
}
}
}
else
{
char *opt = msg;
pbool state = true;
if (!strnicmp(msg, "no-", 3))
{
for (o = 0; optimisations[o].enabled; o++)
state = false;
opt += 3;
}
for (o = 0; optimisations[o].enabled; o++)
if ((*optimisations[o].abbrev && !stricmp(opt, optimisations[o].abbrev)) || !stricmp(opt, optimisations[o].fullname))
{
if ((*optimisations[o].abbrev && !stricmp(msg+3, optimisations[o].abbrev)) || !stricmp(msg+3, optimisations[o].fullname))
{
*optimisations[o].enabled = false;
break;
}
if (qcc_nopragmaoptimise && *optimisations[o].enabled != state)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s %s: overriden by commandline", qcc_token, optimisations[o].fullname);
else
*optimisations[o].enabled = state;
break;
}
}
else
{
for (o = 0; optimisations[o].enabled; o++)
if ((*optimisations[o].abbrev && !stricmp(msg, optimisations[o].abbrev)) || !stricmp(msg, optimisations[o].fullname))
{
*optimisations[o].enabled = true;
break;
}
}
if (!optimisations[o].enabled)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s: %s unsupported", qcc_token, msg);
QCC_PR_ParseWarning(WARN_BADPRAGMA, "pragma %s: %s unsupported", qcc_token, opt);
}
}
else if (!QC_strcasecmp(qcc_token, "sourcefile"))
@ -1335,7 +1352,7 @@ void QCC_PR_LexString (void)
char *end, *cnst;
int raw;
char rawdelim[64];
int code;
unsigned int code;
int texttype;
pbool first = true;
@ -1939,7 +1956,7 @@ Parses an identifier
*/
void QCC_PR_LexName (void)
{
int c;
unsigned int c;
int len;
len = 0;
@ -2389,7 +2406,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name)
cnst = qccHunkAlloc(sizeof(CompilerConstant_t));
cnst->used = false;
cnst->numparams = 0;
cnst->numparams = -1;
cnst->evil = false;
strcpy(cnst->name, name);
cnst->namelen = strlen(name);
@ -2433,6 +2450,7 @@ void QCC_PR_PreProcessor_Define(pbool append)
if (*pr_file_p == '(')
{
cnst->numparams = 0;
pr_file_p++;
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
@ -2605,6 +2623,8 @@ so if present, the preceeding \\\n and following \\\n must become an actual \n i
s+=2;
break;
}
if (s[0] == '\n')
pr_source_line++;
s++;
}
continue;
@ -3239,13 +3259,18 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
}
}
}
void QCC_PR_ParsePrintSRef (int type, QCC_sref_t def)
{
QCC_PR_ParsePrintDef(type, def.sym);
}
void *errorscope;
void QCC_PR_PrintScope (void)
{
if (pr_scope)
{
if (errorscope != pr_scope)
printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->s_line);
printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->line);
errorscope = pr_scope;
}
else
@ -3270,7 +3295,7 @@ Aborts the current file load
void editbadfile(char *file, int line);
#endif
//will abort.
void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3292,7 +3317,7 @@ void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
longjmp (pr_parse_abort, 1);
}
//will abort.
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3315,7 +3340,30 @@ void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error
longjmp (pr_parse_abort, 1);
}
pbool VARGS QCC_PR_PrintWarning (int type, char *file, int line, char *string)
void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t def, const char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,error);
QC_vsnprintf (string,sizeof(string)-1, error,argptr);
va_end (argptr);
#ifndef QCC
editbadfile(strings+s_file, pr_source_line);
#endif
QCC_PR_PrintScope();
if (flag_msvcstyle)
printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
else
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
QCC_PR_ParsePrintSRef(WARN_ERROR, def);
longjmp (pr_parse_abort, 1);
}
pbool VARGS QCC_PR_PrintWarning (int type, const char *file, int line, const char *string)
{
char *wnam = QCC_NameForWarning(type);
if (!wnam)
@ -3324,7 +3372,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, char *file, int line, char *string)
QCC_PR_PrintScope();
if (type >= ERR_PARSEERRORS)
{
if (!file)
if (!file || !*file)
printf ("error%s: %s\n", wnam, string);
else if (flag_msvcstyle)
printf ("%s(%i) : error%s: %s\n", file, line, wnam, string);
@ -3334,7 +3382,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, char *file, int line, char *string)
}
else if (qccwarningaction[type] == 2)
{ //-werror
if (!file)
if (!file || !*file)
printf ("werror%s: %s\n", wnam, string);
else if (flag_msvcstyle)
printf ("%s(%i) : werror%s: %s\n", file, line, wnam, string);
@ -3344,7 +3392,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, char *file, int line, char *string)
}
else
{
if (!file)
if (!file || !*file)
printf ("warning%s: %s\n", wnam, string);
else if (flag_msvcstyle)
printf ("%s(%i) : warning%s: %s\n", file, line, wnam, string);
@ -3354,7 +3402,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, char *file, int line, char *string)
}
return true;
}
pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
pbool VARGS QCC_PR_Warning (int type, const char *file, int line, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3370,7 +3418,7 @@ pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
}
//can be used for errors, qcc execution will continue.
pbool VARGS QCC_PR_ParseWarning (int type, char *error, ...)
pbool VARGS QCC_PR_ParseWarning (int type, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3385,7 +3433,7 @@ pbool VARGS QCC_PR_ParseWarning (int type, char *error, ...)
return QCC_PR_PrintWarning(type, strings + s_file, pr_source_line, string);
}
void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
void VARGS QCC_PR_Note (int type, const char *file, int line, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3416,7 +3464,7 @@ Gets the next token
=============
*/
#ifndef COMMONINLINES
void QCC_PR_Expect (char *string)
void QCC_PR_Expect (const char *string)
{
if (STRCMP (string, pr_token))
QCC_PR_ParseError (ERR_EXPECTED, "expected %s, found %s",string, pr_token);
@ -3424,7 +3472,7 @@ void QCC_PR_Expect (char *string)
}
#endif
pbool QCC_PR_CheckTokenComment(char *string, char **comment)
pbool QCC_PR_CheckTokenComment(const char *string, char **comment)
{
char c;
char *start;
@ -3551,7 +3599,7 @@ Returns false and does nothing otherwise
=============
*/
#ifndef COMMONINLINES
pbool QCC_PR_CheckToken (char *string)
pbool QCC_PR_CheckToken (const char *string)
{
if (pr_token_type != tt_punct)
return false;
@ -3563,7 +3611,7 @@ pbool QCC_PR_CheckToken (char *string)
return true;
}
pbool QCC_PR_CheckImmediate (char *string)
pbool QCC_PR_CheckImmediate (const char *string)
{
if (pr_token_type != tt_immediate)
return false;
@ -3575,7 +3623,7 @@ pbool QCC_PR_CheckImmediate (char *string)
return true;
}
pbool QCC_PR_CheckName(char *string)
pbool QCC_PR_CheckName(const char *string)
{
if (pr_token_type != tt_name)
return false;
@ -3593,7 +3641,7 @@ pbool QCC_PR_CheckName(char *string)
return true;
}
pbool QCC_PR_CheckKeyword(int keywordenabled, char *string)
pbool QCC_PR_CheckKeyword(int keywordenabled, const char *string)
{
if (!keywordenabled)
return false;
@ -3622,14 +3670,14 @@ Checks to see if the current token is a valid name
*/
char *QCC_PR_ParseName (void)
{
static char ident[MAX_NAME];
char ident[MAX_NAME];
char *ret;
if (pr_token_type != tt_name)
{
if (pr_token_type == tt_eof)
QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token);
else
else if (strcmp(pr_token, "...")) //seriously? someone used '...' as an intrinsic NAME?
QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
}
if (strlen(pr_token) >= MAX_NAME-1)
@ -3653,7 +3701,7 @@ a new one and copies it out.
*/
//requires EVERYTHING to be the same
int typecmp_strict(QCC_type_t *a, QCC_type_t *b)
static int typecmp_strict(QCC_type_t *a, QCC_type_t *b)
{
int i;
if (a == b)
@ -4087,6 +4135,11 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
paramlist[numparms].paramname = "";
if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
{
if (QCC_PR_CheckToken ("..."))
{
ftype->vargs = true;
break;
}
newtype = true;
name = QCC_PR_ParseName ();
paramlist[numparms].paramname = qccHunkAlloc(strlen(name)+1);
@ -4253,7 +4306,7 @@ QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, QCC_type_t **args, char
extern char *basictypenames[];
extern QCC_type_t **basictypes[];
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, unsigned int flags);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
pbool type_inlinefunction;
/*newtype=true: creates a new type always
@ -4379,7 +4432,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
char *fieldtypename;
QCC_type_t *fieldtype;
QCC_type_t *indextype;
QCC_def_t *def;
QCC_sref_t def;
QCC_type_t *functype;
char *argname[3];
QCC_type_t *arg[3];
@ -4457,53 +4510,27 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (pr_token_type != tt_name)
{
QCC_function_t *f;
QCC_dfunction_t *df;
char funcname[256];
QC_snprintfz(funcname, sizeof(funcname), "%s::%s_%s", newt->name, setnotget?"set":"get", accessorname);
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, GDF_CONST | (isinline?GDF_INLINE:0));
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST | (isinline?GDF_INLINE:0));
pr_scope = def;
//pr_classtype = newt;
f = QCC_PR_ParseImmediateStatements (functype);
f = QCC_PR_ParseImmediateStatements (def.sym, functype);
pr_classtype = NULL;
pr_scope = NULL;
G_FUNCTION(def->ofs) = numfunctions;
f->def = def;
def->initialized = 1;
if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs");
// fill in the dfunction
df = &functions[numfunctions];
numfunctions++;
if (f->builtin)
df->first_statement = -f->builtin;
else
df->first_statement = f->code;
if (f->builtin && opt_function_names)
optres_function_names += strlen(f->def->name);
else
df->s_name = QCC_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] = functype->params[i].type->size;
}
def.sym->symboldata[def.ofs].function = f - functions;
f->def = def.sym;
def.sym->initialized = 1;
}
else
{
funcname = QCC_PR_ParseName();
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, GDF_CONST|(isinline?GDF_INLINE:0));
if (!def)
def = QCC_PR_GetSRef(functype, funcname, NULL, true, 0, GDF_CONST|(isinline?GDF_INLINE:0));
if (!def.cast)
QCC_Error(ERR_NOFUNC, "%s::set_%s: %s was not defined", newt->name, accessorname, funcname);
}
if (!def)
if (!def.cast || !def.sym || def.sym->temp)
QCC_Error(ERR_NOFUNC, "%s::%s_%s function invalid", newt->name, setnotget?"set":"get", accessorname);
for (acc = newt->accessors; acc; acc = acc->next)
@ -4519,10 +4546,11 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
newt->accessors = acc;
}
if (acc->getset_func[setnotget])
if (acc->getset_func[setnotget].cast)
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::%s_%s already declared", newt->name, setnotget?"set":"get", accessorname);
acc->getset_func[setnotget] = def;
acc->getset_isref[setnotget] = isref;
QCC_FreeTemp(def);
} while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
QCC_PR_Expect("}");
}
@ -4686,7 +4714,6 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{
QCC_def_t *def;
QCC_function_t *f;
QCC_dfunction_t *df;
if (pr_scope)
QCC_Error(ERR_INTERNAL, "Nested function declaration");
@ -4695,7 +4722,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (isnull)
{
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, 0);
G_FUNCTION(def->ofs) = 0;
def->symboldata[def->ofs].function = 0;
def->initialized = 1;
}
else
@ -4728,41 +4755,17 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
}
else
{
pr_scope = def;
pr_classtype = newt;
f = QCC_PR_ParseImmediateStatements (newparm);
f = QCC_PR_ParseImmediateStatements (def, newparm);
pr_classtype = NULL;
pr_scope = NULL;
G_FUNCTION(def->ofs) = numfunctions;
def->symboldata[def->ofs].function = f - functions;
f->def = def;
def->initialized = 1;
if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs");
// fill in the dfunction
df = &functions[numfunctions];
numfunctions++;
if (f->builtin)
df->first_statement = -f->builtin;
else
df->first_statement = f->code;
if (f->builtin && opt_function_names)
optres_function_names += strlen(f->def->name);
else
df->s_name = QCC_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] = newparm->params[i].type->size;
}
}
}
}
QCC_FreeDef(def);
if (!isvirt)
{
@ -4800,7 +4803,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (isnonvirt || isstatic || (newparm->type == ev_function && !arraysize))
{
QC_snprintfz(membername, sizeof(membername), "%s::%s", classname, parmname);
QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST);
QCC_FreeDef(QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST));
if (isnonvirt || isstatic)
continue;
@ -4877,19 +4880,20 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{
d = QCC_PR_GetDef(QCC_PR_FieldType(*basictypes[newparm->type]), membername, NULL, 2, 0, GDF_CONST);
for (i = 0; (unsigned int)i < newparm->size; i++)
((int *)qcc_pr_globals)[i+d->ofs] = pr.size_fields + i;
d->symboldata[i]._int = pr.size_fields+i;
pr.size_fields += i;
d->references++; //always referenced, so you can inherit safely.
d->referenced = true; //always referenced, so you can inherit safely.
}
}
QCC_FreeDef(d);
//and make sure we can do member::__fname
//actually, that seems pointless.
QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, classname, parmname);
// printf("define %s -> %s\n", membername, d->name);
d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d->ofs, true, (isnull?0:GDF_CONST)|(opt_classfields?GDF_STRIP:0));
d->references++; //always referenced, so you can inherit safely.
d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d, 0, true, (isnull?0:GDF_CONST)|(opt_classfields?GDF_STRIP:0));
d->referenced = true; //always referenced, so you can inherit safely.
}
if (redeclaration)
@ -4921,8 +4925,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
//if there's a constructor, make sure the spawnfunc_ function is defined so that its available to maps.
QC_snprintfz(membername, sizeof(membername), "spawnfunc_%s", classname);
d = QCC_PR_GetDef(type_function, membername, NULL, true, 0, GDF_CONST);
d->timescalled++;
d->references++;
d->funccalled = true;
d->referenced = true;
QCC_FreeDef(d);
}
QCC_PR_Expect(";");
@ -4979,7 +4984,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
}
else
newparm = QCC_PR_ParseType(true, false);
newparm = QCC_PR_ParseType(false, false);
arraysize = 0;

View File

@ -7,6 +7,7 @@
#include <stdio.h>
#include <sys/stat.h>
#include <shlobj.h>
#include <shlwapi.h>
#include "qcc.h"
#include "gui.h"
@ -50,9 +51,13 @@ void GUI_RevealOptions(void);
#define SCI_SETSAVEPOINT 2014
#define SCI_GETCURLINE 2027
#define SCI_SETCODEPAGE 2037
#define SCI_MARKERDEFINE 2040
#define SCI_MARKERSETFORE 2041
#define SCI_MARKERSETBACK 2042
#define SCI_MARKERADD 2043
#define SCI_MARKERDELETE 2044
#define SCI_MARKERDELETEALL 2045
#define SCI_MARKERSETALPHA 2476
#define SCI_MARKERGET 2046
#define SCI_MARKERNEXT 2047
#define SCI_STYLECLEARALL 2050
@ -70,6 +75,9 @@ void GUI_RevealOptions(void);
#define SCI_GETTEXT 2182
#define SCI_CALLTIPSHOW 2200
#define SCI_CALLTIPCANCEL 2201
#define SCI_TOGGLEFOLD 2231
#define SCI_SETMARGINWIDTHN 2242
#define SCI_SETMARGINMASKN 2244
#define SCI_SETMARGINSENSITIVEN 2246
#define SCI_SETMOUSEDWELLTIME 2264
#define SCI_CHARLEFT 2304
@ -141,6 +149,47 @@ void GUI_RevealOptions(void);
#define STYLE_BRACELIGHT 34
#define STYLE_BRACEBAD 35
#define SC_MARKNUM_FOLDEREND 25
#define SC_MARKNUM_FOLDEROPENMID 26
#define SC_MARKNUM_FOLDERMIDTAIL 27
#define SC_MARKNUM_FOLDERTAIL 28
#define SC_MARKNUM_FOLDERSUB 29
#define SC_MARKNUM_FOLDER 30
#define SC_MARKNUM_FOLDEROPEN 31
#define SC_MASK_FOLDERS 0xFE000000
#define SC_MARK_CIRCLE 0
#define SC_MARK_ROUNDRECT 1
#define SC_MARK_ARROW 2
#define SC_MARK_SMALLRECT 3
#define SC_MARK_SHORTARROW 4
#define SC_MARK_EMPTY 5
#define SC_MARK_ARROWDOWN 6
#define SC_MARK_MINUS 7
#define SC_MARK_PLUS 8
#define SC_MARK_VLINE 9
#define SC_MARK_LCORNER 10
#define SC_MARK_TCORNER 11
#define SC_MARK_BOXPLUS 12
#define SC_MARK_BOXPLUSCONNECTED 13
#define SC_MARK_BOXMINUS 14
#define SC_MARK_BOXMINUSCONNECTED 15
#define SC_MARK_LCORNERCURVE 16
#define SC_MARK_TCORNERCURVE 17
#define SC_MARK_CIRCLEPLUS 18
#define SC_MARK_CIRCLEPLUSCONNECTED 19
#define SC_MARK_CIRCLEMINUS 20
#define SC_MARK_CIRCLEMINUSCONNECTED 21
#define SC_MARK_BACKGROUND 22
#define SC_MARK_DOTDOTDOT 23
#define SC_MARK_ARROWS 24
#define SC_MARK_PIXMAP 25
#define SC_MARK_FULLRECT 26
#define SC_MARK_LEFTRECT 27
#define SC_MARK_AVAILABLE 28
#define SC_MARK_UNDERLINE 29
#define SC_MARK_RGBAIMAGE 30
#define SC_MARK_BOOKMARK 31
#define SCN_CHARADDED 2001
#define SCN_SAVEPOINTREACHED 2002
#define SCN_SAVEPOINTLEFT 2003
@ -205,6 +254,7 @@ typedef struct
static pbool EngineCommandf(char *message, ...);
static void EngineGiveFocus(void);
/*
static pbool QCC_RegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen)
{
pbool result = false;
@ -237,6 +287,7 @@ static pbool QCC_RegSetValue(HKEY base, char *keyname, char *valuename, int type
}
return result;
}
*/
/*
==============
@ -498,6 +549,7 @@ void GUIPrint(HWND wnd, char *msg);
char finddef[256];
char greptext[256];
extern pbool fl_extramargins;
extern char enginebinary[MAX_PATH];
extern char enginebasedir[MAX_PATH];
extern char enginecommandline[8192];
@ -517,6 +569,7 @@ pbool resetprogssrc; //progs.src was changed, reload project info.
HWND mainwindow;
HWND gamewindow;
HWND mdibox;
HWND optionsmenu;
HWND outputwindow;
HWND outputbox;
HWND projecttree;
@ -605,7 +658,7 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{
if (!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0))
{
char buffer[65536];
static char buffer[65536];
char prefixbuffer[128];
char *pre = WordUnderCursor(editor, prefixbuffer, sizeof(prefixbuffer), NULL, 0, SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0));
if (pre && *pre)
@ -649,6 +702,65 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
return 0;
}
}
if (uMsg == WM_LBUTTONDBLCLK && hWnd == outputbox)
{
CHARRANGE selrange = {0};
SendMessage(hWnd, EM_EXGETSEL, 0, (LPARAM)&selrange);
if (1) //some text is selected.
{
unsigned int bytes;
char line[1024];
char *colon1, *colon2 = NULL;
int l1;
int l2;
l1 = Edit_LineFromChar(hWnd, selrange.cpMin);
l2 = Edit_LineFromChar(hWnd, selrange.cpMax);
if (l1 == l2)
{
bytes = Edit_GetLine(hWnd, Edit_LineFromChar(outputbox, selrange.cpMin), line, sizeof(line)-1);
line[bytes] = 0;
for (colon1 = line+strlen(line)-1; *colon1 <= ' ' && colon1>=line; colon1--)
*colon1 = '\0';
if (!strncmp(line, "warning: ", 9))
memmove(line, line+9, sizeof(line));
colon1=line;
do
{
colon1 = strchr(colon1+1, ':');
} while (colon1 && colon1[1] == '\\');
if (colon1)
{
colon2 = strchr(colon1+1, ':');
while (colon2 && colon2[1] == '\\')
{
colon2 = strchr(colon2+1, ':');
}
if (colon2)
{
*colon1 = '\0';
*colon2 = '\0';
EditFile(line, atoi(colon1+1)-1, false);
}
else if (!strncmp(line, "Source file: ", 13))
EditFile(line+13, -1, false);
else if (!strncmp(line, "Including: ", 11))
EditFile(line+11, -1, false);
}
else if (!strncmp(line, "including ", 10))
EditFile(line+10, -1, false);
else if (!strncmp(line, "compiling ", 10))
EditFile(line+10, -1, false);
else if (!strncmp(line, "prototyping ", 12))
EditFile(line+12, -1, false);
Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it.
}
}
return 0;
}
return pDefSubclassProc(hWnd, uMsg, wParam, lParam);
}
@ -786,12 +898,56 @@ HWND CreateAnEditControl(HWND parent, pbool *scintillaokay)
"virtual nonvirtual class static nonstatic local return"
);
SendMessage(newc, SCI_SETPROPERTY, (WPARAM)"fold", (LPARAM)"1");
SendMessage(newc, SCI_SETMOUSEDWELLTIME, 1000, 0);
SendMessage(newc, SCI_AUTOCSETORDER, SC_ORDER_PERFORMSORT, 0);
SendMessage(newc, SCI_AUTOCSETFILLUPS, 0, (LPARAM)".,[<>(*/+-=\t\n");
SendMessage(newc, SCI_SETMARGINSENSITIVEN, 1, (LPARAM)true);
//line numbers
SendMessage(newc, SCI_SETMARGINWIDTHN, 0, (LPARAM)fl_extramargins?40:0);
//add margin for breakpoints
SendMessage(newc, SCI_SETMARGINMASKN, 1, (LPARAM)~SC_MASK_FOLDERS);
SendMessage(newc, SCI_SETMARGINWIDTHN, 1, (LPARAM)16);
SendMessage(newc, SCI_SETMARGINSENSITIVEN, 1, (LPARAM)true);
//give breakpoints a nice red circle.
SendMessage(newc, SCI_MARKERDEFINE, 0, SC_MARK_CIRCLE);
SendMessage(newc, SCI_MARKERSETFORE, 0, RGB(0x7F, 0x00, 0x00));
SendMessage(newc, SCI_MARKERSETBACK, 0, RGB(0xFF, 0x00, 0x00));
//give current line a yellow arrow
SendMessage(newc, SCI_MARKERDEFINE, 1, SC_MARK_SHORTARROW);
SendMessage(newc, SCI_MARKERSETFORE, 1, RGB(0xFF, 0xFF, 0x00));
SendMessage(newc, SCI_MARKERSETBACK, 1, RGB(0x7F, 0x7F, 0x00));
SendMessage(newc, SCI_MARKERDEFINE, 2, SC_MARK_BACKGROUND);
SendMessage(newc, SCI_MARKERSETFORE, 2, RGB(0x00, 0x00, 0x00));
SendMessage(newc, SCI_MARKERSETBACK, 2, RGB(0xFF, 0xFF, 0x00));
SendMessage(newc, SCI_MARKERSETALPHA, 2, 0x40);
//add margin for folding
SendMessage(newc, SCI_SETPROPERTY, (WPARAM)"fold", (LPARAM)"1");
SendMessage(newc, SCI_SETMARGINWIDTHN, 2, (LPARAM)fl_extramargins?16:0);
SendMessage(newc, SCI_SETMARGINMASKN, 2, (LPARAM)SC_MASK_FOLDERS);
SendMessage(newc, SCI_SETMARGINSENSITIVEN, 2, (LPARAM)true);
//stop the images from being stupid
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED);
SendMessage(newc, SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE);
//and fuck with colours so that its visible.
#define FOLDBACK RGB(0x50, 0x50, 0x50)
SendMessage(newc, SCI_MARKERSETFORE, SC_MARKNUM_FOLDER, RGB(0xFF, 0xFF, 0xFF));
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDER, FOLDBACK);
SendMessage(newc, SCI_MARKERSETFORE, SC_MARKNUM_FOLDEROPEN, RGB(0xFF, 0xFF, 0xFF));
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDEROPEN, FOLDBACK);
SendMessage(newc, SCI_MARKERSETFORE, SC_MARKNUM_FOLDEROPENMID, RGB(0xFF, 0xFF, 0xFF));
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDEROPENMID, FOLDBACK);
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDERSUB, FOLDBACK);
SendMessage(newc, SCI_MARKERSETFORE, SC_MARKNUM_FOLDEREND, RGB(0xFF, 0xFF, 0xFF));
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDEREND, FOLDBACK);
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDERTAIL, FOLDBACK);
SendMessage(newc, SCI_MARKERSETBACK, SC_MARKNUM_FOLDERMIDTAIL, FOLDBACK);
}
else
{
@ -837,6 +993,7 @@ enum {
IDM_GREP,
IDM_GOTODEF,
IDM_OUTPUT_WINDOW,
IDM_SHOWLINENUMBERS,
IDM_SAVE,
IDM_RECOMPILE,
IDM_FIND,
@ -865,10 +1022,10 @@ enum {
IDI_O_ADDITIONALPARAMETERS,
IDI_O_OPTIMISATION,
IDI_O_COMPILER_FLAG,
IDI_O_USE,
IDI_O_APPLYSAVE,
IDI_O_APPLY,
IDI_O_TARGET,
IDI_O_SYNTAX_HIGHLIGHTING,
IDI_O_TARGETH2,
IDI_O_TARGETFTE,
IDI_O_ENGINE,
IDI_O_ENGINEBASEDIR,
IDI_O_ENGINECOMMANDLINE,
@ -878,7 +1035,7 @@ enum {
static void EditorReload(editor_t *editor);
int EditorSave(editor_t *edit);
void EditFile(char *name, int line);
void EditFile(char *name, int line, pbool setcontrol);
pbool EditorModified(editor_t *e);
void QueryOpenFile(void)
@ -894,7 +1051,7 @@ void QueryOpenFile(void)
memset(filename, 0, sizeof(filename));
GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
if (GetOpenFileName(&ofn))
EditFile(filename, -1);
EditFile(filename, -1, false);
SetCurrentDirectory(oldpath);
}
@ -933,7 +1090,27 @@ void GenericMenu(WPARAM wParam)
SetFocus(outputbox);
}
break;
case IDM_SHOWLINENUMBERS:
{
editor_t *ed;
MENUITEMINFO mii = {sizeof(mii)};
fl_extramargins = !fl_extramargins;
mii.fMask = MIIM_STATE;
mii.fState = fl_extramargins?MFS_CHECKED:MFS_UNCHECKED;
SetMenuItemInfo(GetMenu(mainwindow), IDM_SHOWLINENUMBERS, FALSE, &mii);
for (ed = editors; ed; ed = ed->next)
{
if (ed->scintilla)
{
SendMessage(ed->editpane, SCI_SETMARGINWIDTHN, 0, (LPARAM)fl_extramargins?40:0);
SendMessage(ed->editpane, SCI_SETMARGINWIDTHN, 2, (LPARAM)fl_extramargins?16:0);
}
}
}
break;
case IDM_DEBUG_RUN:
EditFile(NULL, -1, true);
EngineGiveFocus();
if (!EngineCommandf("qcresume\n"))
RunEngine();
@ -942,12 +1119,15 @@ void GenericMenu(WPARAM wParam)
buttons[ID_COMPILE].washit = true;
return;
case IDM_DEBUG_STEPOVER:
EditFile(NULL, -1, true);
EngineCommandf("qcstep over\n");
return;
case IDM_DEBUG_STEPINTO:
EditFile(NULL, -1, true);
EngineCommandf("qcstep into\n");
return;
case IDM_DEBUG_STEPOUT:
EditFile(NULL, -1, true);
EngineCommandf("qcstep out\n");
return;
}
@ -969,7 +1149,7 @@ void EditorMenu(editor_t *editor, WPARAM wParam)
break;
}
else
EditFile(buffer, -1);
EditFile(buffer, -1, false);
}
break;
case IDM_SAVE:
@ -1207,7 +1387,7 @@ char *GetTooltipText(editor_t *editor, int pos, pbool dwell)
line = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0);
//FIXME: we may need to display types too
for (fno = 0, def = NULL; fno < sourcefilesnumdefs; fno++)
for (fno = 0, def = NULL; fno < sourcefilesnumdefs && !def; fno++)
{
for (def = sourcefilesdefs[fno]; def; def = def->next)
{
@ -1224,11 +1404,19 @@ char *GetTooltipText(editor_t *editor, int pos, pbool dwell)
if (def)
{
char typebuf[1024];
char valuebuf[1024];
char *value = "";
if (def->constant && def->type->type == ev_float)
QC_snprintfz(value=valuebuf, sizeof(valuebuf), " = %g", def->symboldata[def->ofs]._float);
else if (def->constant && def->type->type == ev_integer)
QC_snprintfz(value=valuebuf, sizeof(valuebuf), " = %i", def->symboldata[def->ofs]._int);
else if (def->constant && def->type->type == ev_vector)
QC_snprintfz(value=valuebuf, sizeof(valuebuf), " = '%g %g %g'", def->symboldata[def->ofs].vector[0], def->symboldata[def->ofs].vector[1], def->symboldata[def->ofs].vector[2]);
//note function argument names do not persist beyond the function def. we might be able to read the function's localdefs for them, but that's unreliable/broken with builtins where they're most needed.
if (def->comment)
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s\r\n%s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name, def->comment);
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s%s\r\n%s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name, value, def->comment);
else
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name);
QC_snprintfz(buffer, sizeof(buffer)-1, "%s %s%s", TypeName(def->type, typebuf, sizeof(typebuf)), def->name, value);
if (dwell)
{
@ -1463,11 +1651,18 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
switch(nmhdr->code)
{
case SCN_MARGINCLICK:
/*fixme: should we scan the statements to ensure the line is valid? this applies to the f9 key too*/
l = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, not->position, 0);
mode = !(SendMessage(editor->editpane, SCI_MARKERGET, l, 0) & 1);
SendMessage(editor->editpane, mode?SCI_MARKERADD:SCI_MARKERDELETE, l, 0);
EngineCommandf("qcbreakpoint %i \"%s\" %i\n", mode, editor->filename, l+1);
if (not->margin == 1)
{
/*fixme: should we scan the statements to ensure the line is valid? this applies to the f9 key too*/
mode = !(SendMessage(editor->editpane, SCI_MARKERGET, l, 0) & 1);
SendMessage(editor->editpane, mode?SCI_MARKERADD:SCI_MARKERDELETE, l, 0);
EngineCommandf("qcbreakpoint %i \"%s\" %i\n", mode, editor->filename, l+1);
}
else if (not->margin == 2)
{
SendMessage(editor->editpane, SCI_TOGGLEFOLD, l, 0);
}
break;
case SCN_CHARADDED:
if (not->ch == '(')
@ -1660,13 +1855,27 @@ static void EditorReload(editor_t *editor)
}
//line is 0-based. use -1 for no reselection
void EditFile(char *name, int line)
void EditFile(char *name, int line, pbool setcontrol)
{
char title[1024];
editor_t *neweditor;
WNDCLASS wndclass;
HMENU menu, menufile, menuhelp, menunavig;
if (setcontrol)
{
for (neweditor = editors; neweditor; neweditor = neweditor->next)
{
if (neweditor->scintilla)
{
SendMessage(neweditor->editpane, SCI_MARKERDELETEALL, 1, 0);
SendMessage(neweditor->editpane, SCI_MARKERDELETEALL, 2, 0);
}
}
}
if (!name)
return;
for (neweditor = editors; neweditor; neweditor = neweditor->next)
{
if (neweditor->window && !strcmp(neweditor->filename, name))
@ -1675,6 +1884,12 @@ void EditFile(char *name, int line)
{
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)-1);
Edit_ScrollCaret(neweditor->editpane);
if (setcontrol && neweditor->scintilla)
{
SendMessage(neweditor->editpane, SCI_MARKERADD, line, 1);
SendMessage(neweditor->editpane, SCI_MARKERADD, line, 2);
}
}
if (mdibox)
SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)neweditor->window, 0);
@ -1785,6 +2000,12 @@ void EditFile(char *name, int line)
SetFocus(mainwindow);
SetFocus(neweditor->window);
SetFocus(neweditor->editpane);
if (setcontrol && neweditor->scintilla)
{
SendMessage(neweditor->editpane, SCI_MARKERADD, line, 1);
SendMessage(neweditor->editpane, SCI_MARKERADD, line, 2);
}
}
int EditorSave(editor_t *edit)
@ -1793,36 +2014,45 @@ int EditorSave(editor_t *edit)
char title[2048];
struct stat sbuf;
int len;
wchar_t *file;
wchar_t *wfile;
char *afile;
if (edit->scintilla)
{
len = SendMessage(edit->editpane, SCI_GETLENGTH, 0, 0)+1;
file = malloc(len);
SendMessage(edit->editpane, SCI_GETTEXT, len, (LPARAM)file);
if (!QCC_WriteFile(edit->filename, file, len))
{
MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
return false;
}
SendMessage(edit->editpane, SCI_SETSAVEPOINT, 0, 0);
}
else
{
len = GetWindowTextLengthW(edit->editpane);
file = malloc((len+1)*2);
if (!file)
len = SendMessage(edit->editpane, SCI_GETLENGTH, 0, 0);
afile = malloc(len+1);
if (!afile)
{
MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
return false;
}
GetWindowTextW(edit->editpane, file, len+1);
if (!QCC_WriteFileW(edit->filename, file, len))
SendMessage(edit->editpane, SCI_GETTEXT, len+1, (LPARAM)afile);
if (!QCC_WriteFile(edit->filename, afile, len))
{
free(afile);
MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
return false;
}
SendMessage(edit->editpane, SCI_SETSAVEPOINT, 0, 0);
free(afile);
}
else
{
len = GetWindowTextLengthW(edit->editpane);
wfile = malloc((len+1)*2);
if (!wfile)
{
MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
return false;
}
GetWindowTextW(edit->editpane, wfile, len+1);
if (!QCC_WriteFileW(edit->filename, wfile, len))
{
free(wfile);
MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
return false;
}
free(wfile);
}
free(file);
/*now whatever is on disk should have the current time*/
edit->modified = false;
@ -1893,7 +2123,7 @@ int GUIFileSize(const char *fname)
{
int len;
if (e->scintilla)
len = SendMessage(e->editpane, SCI_GETLENGTH, 0, 0)+1;
len = SendMessage(e->editpane, SCI_GETLENGTH, 0, 0);
else
len = (GetWindowTextLengthW(e->editpane)+1)*2;
return len;
@ -2133,6 +2363,11 @@ unsigned int WINAPI threadwrapper(void *args)
{
enginewindow_t *ctx = args;
{
char workingdir[MAX_PATH+10];
char absexe[MAX_PATH+10];
char absbase[MAX_PATH+10];
char mssucks[MAX_PATH+10];
char *gah;
PROCESS_INFORMATION childinfo;
STARTUPINFO startinfo;
SECURITY_ATTRIBUTES pipesec = {sizeof(pipesec), NULL, TRUE};
@ -2172,7 +2407,34 @@ unsigned int WINAPI threadwrapper(void *args)
WriteFile(ctx->pipetoengine, message, strlen(message), &written, NULL);
}
CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, enginebasedir, &startinfo, &childinfo);
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
strcpy(mssucks, enginebasedir);
while ((gah = strchr(mssucks, '/')))
*gah = '\\';
PathCombine(absbase, workingdir, mssucks);
strcpy(mssucks, enginebinary);
while ((gah = strchr(mssucks, '/')))
*gah = '\\';
PathCombine(absexe, absbase, mssucks);
if (!CreateProcess(absexe, cmdline, NULL, NULL, TRUE, 0, NULL, absbase, &startinfo, &childinfo))
{
HRESULT hr = GetLastError();
switch(hr)
{
case ERROR_FILE_NOT_FOUND:
MessageBox(mainwindow, "File Not Found", "Cannot Start Engine", 0);
break;
case ERROR_PATH_NOT_FOUND:
MessageBox(mainwindow, "Path Not Found", "Cannot Start Engine", 0);
break;
case ERROR_ACCESS_DENIED:
MessageBox(mainwindow, "Access Denied", "Cannot Start Engine", 0);
break;
default:
MessageBox(mainwindow, qcva("gla: %x", hr), "Cannot Start Engine", 0);
break;
}
}
//these ends of the pipes were inherited by now, so we can discard them in the caller.
CloseHandle(startinfo.hStdOutput);
@ -2339,8 +2601,9 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message,
break;
case WM_USER:
//engine broke. show code.
SetForegroundWindow(mainwindow);
EditFile((char*)lParam, wParam-1);
if (lParam)
SetForegroundWindow(mainwindow);
EditFile((char*)lParam, wParam-1, true);
break;
case WM_USER+1:
//engine loaded a progs, reset breakpoints.
@ -2435,8 +2698,9 @@ void PromptForEngine(int force)
#define OFN_DONTADDTORECENT 0x02000000
#endif
char oldworkingdir[MAX_PATH+10]; //cmdlg changes it...
char workingdir[MAX_PATH+10];
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
GetCurrentDirectory(sizeof(oldworkingdir)-1, oldworkingdir);
if (!*enginebasedir || force==1)
{
BROWSEINFO bi;
@ -2444,6 +2708,7 @@ void PromptForEngine(int force)
memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow;
bi.pidlRoot = NULL;
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
bi.pszDisplayName = workingdir;
bi.lpszTitle = "Please locate your base directory";
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
@ -2451,41 +2716,51 @@ void PromptForEngine(int force)
bi.lParam = 0;
bi.iImage = 0;
il = SHBrowseForFolder(&bi);
SetCurrentDirectory(oldworkingdir); //revert microsoft stupidity.
if (il)
{
SHGetPathFromIDList(il, enginebasedir);
char *foo;
char absbase[MAX_PATH+10];
SHGetPathFromIDList(il, absbase);
CoTaskMemFree(il);
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
//use the relative path instead. this'll be stored in a file, and I expect people will zip+email without thinking.
if (!PathRelativePathToA(enginebasedir, workingdir, FILE_ATTRIBUTE_DIRECTORY, absbase, FILE_ATTRIBUTE_DIRECTORY))
QC_strlcpy(enginebasedir, absbase, sizeof(enginebasedir));
while(foo = strchr(enginebasedir, '\\'))
*foo = '/';
}
else
return;
QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", REG_SZ, enginebasedir, strlen(enginebasedir));
if (optionsmenu)
DestroyWindow(optionsmenu);
buttons[ID_OPTIONS].washit = true;
}
if (!*enginebinary || force==2)
{
char *s;
char initialdir[MAX_PATH+10];
char absengine[MAX_PATH+10];
OPENFILENAME ofn;
pbool okay;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = mainwindow;
ofn.hInstance = ghInstance;
ofn.lpstrFile = enginebinary;
ofn.lpstrFile = absengine;
ofn.Flags = OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_DONTADDTORECENT;
ofn.lpstrTitle = "Please choose an engine";
ofn.nMaxFile = sizeof(enginebinary)-1;
ofn.lpstrFilter = "Executables\0*.exe\0All files\0*.*\0";
strcpy(enginebinary, "fteglqw.exe");
if (enginebasedir[0] == '.' && enginebasedir[1] == '.' && (!enginebasedir[2] || enginebasedir[2] == '/' || enginebasedir[2] == '\\'))
{
_snprintf(initialdir, sizeof(initialdir), "%s/%s", workingdir, enginebasedir);
strcat(initialdir, "/");
strcat(initialdir, enginebasedir);
}
else
strcpy(initialdir, enginebasedir);
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
_snprintf(absengine, sizeof(absengine), "%s/", enginebasedir);
for (s = absengine; *s; s++)
if (*s == '/')
*s = '\\';
PathCombine(initialdir, workingdir, absengine);
strcpy(absengine, "fteglqw.exe");
//and the fuck-you-microsoft loop
for (s = initialdir; *s; s++)
if (*s == '/')
@ -2503,12 +2778,49 @@ void PromptForEngine(int force)
}
break;
}
if (!PathRelativePathToA(enginebinary, initialdir, FILE_ATTRIBUTE_DIRECTORY, absengine, FILE_ATTRIBUTE_DIRECTORY))
QC_strlcpy(enginebinary, absengine, sizeof(enginebasedir));
if (!strncmp(enginebinary, ".\\", 2))
memmove(enginebinary, enginebinary+2, strlen(enginebinary+2)+1);
//undo any damage caused by microsoft's stupidity
SetCurrentDirectory(workingdir);
SetCurrentDirectory(oldworkingdir);
if (!okay)
return;
QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", REG_SZ, enginebinary, strlen(enginebinary));
if (optionsmenu)
DestroyWindow(optionsmenu);
buttons[ID_OPTIONS].washit = true;
if (*enginebinary && (!*enginecommandline || force==2))
{
char absbase[MAX_PATH+10];
char guessdir[MAX_PATH+10];
char *slash;
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
_snprintf(guessdir, sizeof(guessdir), "%s/", enginebasedir);
for (s = guessdir; *s; s++)
if (*s == '/')
*s = '\\';
PathCombine(absbase, workingdir, guessdir);
if (PathRelativePathToA(guessdir, absbase, FILE_ATTRIBUTE_DIRECTORY, workingdir, FILE_ATTRIBUTE_DIRECTORY))
{
if (!strncmp(guessdir, ".\\", 2))
memmove(guessdir, guessdir+2, strlen(guessdir+2)+1);
slash = strchr(guessdir, '/');
if (slash)
*slash = 0;
slash = strchr(guessdir, '\\');
if (slash)
*slash = 0;
if (!*guessdir)
QC_snprintfz(enginecommandline, sizeof(enginecommandline), "-window -nohome");
else if (!strchr(guessdir, ' '))
QC_snprintfz(enginecommandline, sizeof(enginecommandline), "-window -nohome -game %s", guessdir);
else
QC_snprintfz(enginecommandline, sizeof(enginecommandline), "-window -nohome -game \"%s\"", guessdir);
}
}
}
}
void RunEngine(void)
@ -2565,8 +2877,8 @@ void RunEngine(void)
HWND optionsmenu;
HWND hexen2item;
HWND targitem_hexen2;
HWND targitem_fte;
HWND nokeywords_coexistitem;
HWND autoprototype_item;
//HWND autohighlight_item;
@ -2589,7 +2901,7 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
case WM_COMMAND:
switch(wParam)
{
case IDI_O_USE:
case IDI_O_APPLYSAVE:
case IDI_O_APPLY:
for (i = 0; optimisations[i].enabled; i++)
{
@ -2601,7 +2913,8 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
else
optimisations[i].flags &= ~FLAG_SETINGUI;
}
fl_hexen2 = Button_GetCheck(hexen2item);
fl_hexen2 = Button_GetCheck(targitem_hexen2);
fl_ftetarg = Button_GetCheck(targitem_fte);
for (i = 0; compiler_flag[i].enabled; i++)
{
if (compiler_flag[i].flags & FLAG_HIDDENINGUI)
@ -2611,20 +2924,16 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
else
compiler_flag[i].flags &= ~FLAG_SETINGUI;
}
fl_autohighlight = false;//Button_GetCheck(autohighlight_item);
Edit_GetText(extraparmsitem, parameters, sizeof(parameters)-1);
#ifdef EMBEDDEBUG
Edit_GetText(w_enginebinary, enginebinary, sizeof(enginebinary)-1);
Edit_GetText(w_enginebasedir, enginebasedir, sizeof(enginebasedir)-1);
Edit_GetText(w_enginecommandline, enginecommandline, sizeof(enginecommandline)-1);
QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", REG_SZ, enginebinary, strlen(enginebinary));
QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", REG_SZ, enginebasedir, strlen(enginebasedir));
QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginecommandline", REG_SZ, enginecommandline, strlen(enginecommandline));
#endif
if (wParam == IDI_O_USE)
buttons[ID_COMPILE].washit = true;
if (wParam == IDI_O_APPLYSAVE)
GUI_SaveConfig();
DestroyWindow(hWnd);
break;
case IDI_O_CHANGE_PROGS_SRC:
{
@ -2757,10 +3066,10 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
MessageBox(hWnd, "Type in additional commandline parameters here. Use -Dname to define a named precompiler constant before compiling.", "Help", MB_OK|MB_ICONINFORMATION);
break;
case IDI_O_APPLY:
MessageBox(hWnd, "Apply changes shown, but do not recompile yet.", "Help", MB_OK|MB_ICONINFORMATION);
MessageBox(hWnd, "Apply changes shown.", "Help", MB_OK|MB_ICONINFORMATION);
break;
case IDI_O_USE:
MessageBox(hWnd, "Apply changes shown here and recompile.", "Help", MB_OK|MB_ICONINFORMATION);
case IDI_O_APPLYSAVE:
MessageBox(hWnd, "Apply changes shown and save the settings for next time.", "Help", MB_OK|MB_ICONINFORMATION);
break;
case IDI_O_OPTIMISATION:
for (i = 0; optimisations[i].enabled; i++)
@ -2782,11 +3091,11 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
}
}
break;
case IDI_O_TARGET:
MessageBox(hWnd, "Click here to compile a hexen2 compatible progs. Note that this uses the -Thexen2. There are other targets available.", "Help", MB_OK|MB_ICONINFORMATION);
case IDI_O_TARGETH2:
MessageBox(hWnd, "Click here to compile a hexen2 compatible progs, as well as enable all hexen2 keywords. Note that this uses the -Thexen2. There are other targets available.", "Help", MB_OK|MB_ICONINFORMATION);
break;
case IDI_O_SYNTAX_HIGHLIGHTING:
MessageBox(hWnd, "Should syntax be highlighted automatically when a file is opened?", "Help", MB_OK|MB_ICONINFORMATION);
case IDI_O_TARGETFTE:
MessageBox(hWnd, "Click here to allow the use of extended instructions not found in the original instruction set.", "Help", MB_OK|MB_ICONINFORMATION);
break;
}
}
@ -2798,6 +3107,7 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
}
void OptionsDialog(void)
{
char nicername[256], *us;
HWND subsection;
RECT r;
WNDCLASS wndclass;
@ -2892,7 +3202,11 @@ void OptionsDialog(void)
continue;
}
optimisations[i].guiinfo = wnd = CreateWindow("BUTTON",optimisations[i].fullname,
QC_strlcpy(nicername, optimisations[i].fullname, sizeof(nicername));
while((us = strchr(nicername, '_')))
*us = ' ';
optimisations[i].guiinfo = wnd = CreateWindow("BUTTON",nicername,
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
8+200*(num&1),16+16*(num/2),200-16,16,
subsection,
@ -2991,11 +3305,11 @@ void OptionsDialog(void)
(HMENU)IDI_O_APPLY,
ghInstance,
NULL);
CreateWindow("BUTTON","Use",
CreateWindow("BUTTON","Save",
WS_CHILD | WS_VISIBLE,
8+64,height-40,64,32,
optionsmenu,
(HMENU)IDI_O_USE,
(HMENU)IDI_O_APPLYSAVE,
ghInstance,
NULL);
CreateWindow("BUTTON","progs.src",
@ -3009,11 +3323,11 @@ void OptionsDialog(void)
y=4;
hexen2item = wnd = CreateWindow("BUTTON","HexenC",
targitem_hexen2 = wnd = CreateWindow("BUTTON","HexenC",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
408,y,200-16,16,
optionsmenu,
(HMENU)IDI_O_TARGET,
(HMENU)IDI_O_TARGETH2,
ghInstance,
NULL);
y+=16;
@ -3022,6 +3336,19 @@ void OptionsDialog(void)
else
Button_SetCheck(wnd, 0);
targitem_fte = wnd = CreateWindow("BUTTON","Extended Instructions",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
408,y,200-16,16,
optionsmenu,
(HMENU)IDI_O_TARGETFTE,
ghInstance,
NULL);
y+=16;
if (fl_ftetarg)
Button_SetCheck(wnd, 1);
else
Button_SetCheck(wnd, 0);
/* autohighlight_item = wnd = CreateWindow("BUTTON","Syntax Highlighting",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
408,y,200-16,16,
@ -3168,6 +3495,7 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
AppendMenu(m, 0, IDM_GOTODEF, "Go to definition\tF12");
AppendMenu(m, 0, IDM_OPENDOCU, "Open selected file");
AppendMenu(m, 0, IDM_OUTPUT_WINDOW, "Show Output Window\tF6");
AppendMenu(m, (fl_extramargins?MF_CHECKED:MF_UNCHECKED), IDM_SHOWLINENUMBERS, "Show Line Numbers");
AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = windowmenu = CreateMenu()), "&Window");
AppendMenu(m, 0, IDM_CASCADE, "Cascade");
AppendMenu(m, 0, IDM_TILE_HORIZ, "Tile Horizontally");
@ -3369,7 +3697,7 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
filename[newlen] = '/';
strncpy(filename, i.pszText, newlen);
}
EditFile(filename, -1);
EditFile(filename, -1, false);
break;
}
}
@ -3499,6 +3827,7 @@ int GUIprintf(const char *msg, ...)
buf[sizeof(buf)-1] = 0;
printf("%s", buf);
//OutputDebugStringA(buf);
if (logfile)
fprintf(logfile, "%s", buf);
@ -3962,12 +4291,12 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
GUI_SetDefaultOpts();
if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", enginebinary, sizeof(enginebinary)))
// if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", enginebinary, sizeof(enginebinary)))
strcpy(enginebinary, "");
if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", enginebasedir, sizeof(enginebasedir)))
// if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", enginebasedir, sizeof(enginebasedir)))
strcpy(enginebasedir, "");
if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginecommandline", enginecommandline, sizeof(enginecommandline)))
strcpy(enginecommandline, "-window +map start -nohome");
// if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginecommandline", enginecommandline, sizeof(enginecommandline)))
strcpy(enginecommandline, "");
if(strstr(lpCmdLine, "-stdout"))
{
@ -3982,7 +4311,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
FILE *f;
char *s;
f = fopen("fteqcc.cfg", "rb");
f = fopen("fteqcc.arg", "rb");
if (f)
{
fseek(f, 0, SEEK_END);
@ -4167,63 +4496,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
DoTranslateMessage(&msg);
}
if (mainwindow)
if (mainwindow)
{
i = Edit_GetSel(outputbox);
if ((i>>16) != (i&0xffff) && i != -1) //some text is selected.
{
int bytes;
char line[1024];
char *colon1, *colon2 = NULL;
int l1;
int l2;
l1 = Edit_LineFromChar(outputbox, i&0xffff);
l2 = Edit_LineFromChar(outputbox, (i>>16)&0xffff);
if (l1 == l2)
{
bytes = Edit_GetLine(outputbox, Edit_LineFromChar(outputbox, i&0xffff), line, sizeof(line)-1);
line[bytes] = 0;
for (colon1 = line+strlen(line)-1; *colon1 <= ' ' && colon1>=line; colon1--)
*colon1 = '\0';
if (!strncmp(line, "warning: ", 9))
memmove(line, line+9, sizeof(line));
colon1=line;
do
{
colon1 = strchr(colon1+1, ':');
} while (colon1 && colon1[1] == '\\');
if (colon1)
{
colon2 = strchr(colon1+1, ':');
while (colon2 && colon2[1] == '\\')
{
colon2 = strchr(colon2+1, ':');
}
if (colon2)
{
*colon1 = '\0';
*colon2 = '\0';
EditFile(line, atoi(colon1+1)-1);
}
else if (!strncmp(line, "Source file: ", 13))
EditFile(line+13, -1);
else if (!strncmp(line, "Including: ", 11))
EditFile(line+11, -1);
}
else if (!strncmp(line, "including ", 10))
EditFile(line+10, -1);
else if (!strncmp(line, "compiling ", 10))
EditFile(line+10, -1);
else if (!strncmp(line, "prototyping ", 12))
EditFile(line+12, -1);
Edit_SetSel(outputbox, i&0xffff, i&0xffff); //deselect it.
}
}
if (buttons[ID_COMPILE].washit)
{
CreateOutputWindow();
@ -4235,7 +4509,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
{
buttons[ID_EDIT].washit = false;
if (*progssrcname)
EditFile(progssrcname, -1);
EditFile(progssrcname, -1, false);
}
#ifdef EMBEDDEBUG
if (buttons[ID_RUN].washit)

View File

@ -5,10 +5,11 @@
pbool fl_nondfltopts;
pbool fl_hexen2;
pbool fl_autohighlight;
pbool fl_ftetarg;
pbool fl_compileonstart;
pbool fl_showall;
pbool fl_log;
pbool fl_extramargins;
char parameters[16384];
char progssrcname[256];
@ -63,7 +64,7 @@ int Grep(char *filename, char *string)
void GoToDefinition(char *name)
{
QCC_def_t *def;
QCC_dfunction_t *fnc;
QCC_function_t *fnc;
char *strip; //trim whitespace (for convieniance).
while (*name <= ' ' && *name)
@ -92,22 +93,259 @@ void GoToDefinition(char *name)
if (def->type->type == ev_function && def->constant)
{
fnc = &functions[((int *)qcc_pr_globals)[def->ofs]];
if (fnc->first_statement>=0 && fnc->s_file)
if (fnc->code>=0 && fnc->s_file)
{
EditFile(fnc->s_file+strings, statements[fnc->first_statement].linenum-1);
EditFile(strings+fnc->s_file, statements[fnc->code].linenum-1, false);
return;
}
}
if (!def->s_file)
GUI_DialogPrint("Not found", "Global definition of var was not specified.");
else
EditFile(def->s_file+strings, def->s_line-1);
EditFile(def->s_file+strings, def->s_line-1, false);
}
else
GUI_DialogPrint("Not found", "Global instance of var was not found.");
}
static void GUI_WriteConfigLine(FILE *file, char *part1, char *part2, char *part3, char *desc)
{
int align = 0;
if (part1)
{
if (strchr(part1, ' '))
align += fprintf(file, "\"%s\" ", part1);
else
align += fprintf(file, "%s ", part1);
for (; align < 14; align++)
fputc(' ', file);
}
if (part2)
{
if (strchr(part2, ' '))
align += fprintf(file, "\"%s\" ", part2);
else
align += fprintf(file, "%s ", part2);
for (; align < 28; align++)
fputc(' ', file);
}
if (part3)
{
if (strchr(part3, ' '))
align += fprintf(file, "\"%s\" ", part3);
else
align += fprintf(file, "%s ", part3);
for (; align < 40; align++)
fputc(' ', file);
}
if (desc)
{
if (align > 40)
{
fputc('\n', file);
align = 0;
}
for (; align < 40; align++)
fputc(' ', file);
fputs("# ", file);
align -= 40;
if (align < 0)
align = 0;
while(*desc)
{
if (*desc == '\n' || (*desc == ' ' && align > 60))
{
fputs("\n", file);
for (align = 0; align < 40; align++)
fputc(' ', file);
fputs("# ", file);
align = 0;
}
else
{
fputc(*desc, file);
align++;
}
desc++;
}
}
fputs("\n", file);
}
void GUI_SaveConfig(void)
{
FILE *file = fopen("fteqcc.ini", "wt");
int p;
if (!file)
return;
for (p = 0; optimisations[p].enabled; p++)
{
if ((!(optimisations[p].flags&FLAG_SETINGUI)) == (!(optimisations[p].flags&FLAG_ASDEFAULT)))
GUI_WriteConfigLine(file, "optimisation", optimisations[p].abbrev, "default", optimisations[p].description);
else
GUI_WriteConfigLine(file, "optimisation", optimisations[p].abbrev, (optimisations[p].flags&FLAG_SETINGUI)?"on":"off", optimisations[p].description);
}
for (p = 0; compiler_flag[p].enabled; p++)
{
if (!strncmp(compiler_flag[p].fullname, "Keyword: ", 9))
GUI_WriteConfigLine(file, "keyword", compiler_flag[p].abbrev, (compiler_flag[p].flags&FLAG_SETINGUI)?"true":"false", compiler_flag[p].description);
else
GUI_WriteConfigLine(file, "flag", compiler_flag[p].abbrev, (compiler_flag[p].flags&FLAG_SETINGUI)?"true":"false", compiler_flag[p].description);
}
GUI_WriteConfigLine(file, "showall", fl_showall?"on":"off", NULL, "Show all keyword options in the gui");
GUI_WriteConfigLine(file, "compileonstart", fl_compileonstart?"on":"off", NULL, "Recompile on GUI startup");
GUI_WriteConfigLine(file, "log", fl_log?"on":"off", NULL, "Write out a compile log");
GUI_WriteConfigLine(file, "enginebinary", enginebinary, NULL, "Location of the engine binary to run. Change this to something else to run a different engine, but not all support debugging.");
GUI_WriteConfigLine(file, "basedir", enginebasedir, NULL, "The base directory of the game that contains your sub directory");
GUI_WriteConfigLine(file, "engineargs", enginecommandline, NULL, "The engine commandline to use when debugging. You'll likely want to ensure this contains -window as well as the appropriate -game argument.");
GUI_WriteConfigLine(file, "srcfile", progssrcname, NULL, "The progs.src file to load to find ordering of other qc files.");
GUI_WriteConfigLine(file, "src", progssrcdir, NULL, "Additional subdir to read qc files from. Typically blank (ie: the working directory).");
GUI_WriteConfigLine(file, "extramargins", fl_extramargins?"on":"off", NULL, "Enables line number and folding margins.");
GUI_WriteConfigLine(file, "hexen2", fl_hexen2?"on":"off", NULL, "Enable the extra tweaks needed for compatibility with hexen2 engines.");
GUI_WriteConfigLine(file, "extendedopcodes", fl_ftetarg?"on":"off", NULL, "Utilise an extended instruction set, providing support for pointers and faster arrays and other speedups.");
GUI_WriteConfigLine(file, "parameters", parameters, NULL, "Other additional parameters that are not supported by the gui. Likely including -DFOO");
fclose(file);
}
//grabs a token. modifies original string.
static char *GUI_ParseInPlace(char **state)
{
char *str = *state, *end;
while(*str == ' ' || *str == '\t')
str++;
if (*str == '\"')
{
char *fmt;
str++;
for (end = str, fmt = str; *end; )
{
if (*end == '\"')
break;
else if (*end == '\'' && end[1] == '\\')
*fmt = '\\';
else if (*end == '\'' && end[1] == '\"')
*fmt = '\"';
else if (*end == '\'' && end[1] == '\n')
*fmt = '\n';
else if (*end == '\'' && end[1] == '\r')
*fmt = '\r';
else if (*end == '\'' && end[1] == '\t')
*fmt = '\t';
else
{
*fmt++ = *end++;
continue;
}
fmt+=1;
end+=2;
}
}
else
for (end = str; *end&&*end!=' '&&*end !='\t' && *end != '#'; end++)
;
*end = 0;
*state = end+1;
return str;
}
static int GUI_ParseBooleanInPlace(char **state, int defaultval)
{
char *token = GUI_ParseInPlace(state);
if (!stricmp(token, "default"))
return defaultval;
else if (!stricmp(token, "on") || !stricmp(token, "true") || !stricmp(token, "yes"))
return 1;
else if (!stricmp(token, "off") || !stricmp(token, "false") || !stricmp(token, "no"))
return 0;
else
return !!atoi(token);
}
void GUI_LoadConfig(void)
{
char buf[2048];
char *token, *str;
FILE *file = fopen("fteqcc.ini", "rb");
int p;
if (!file)
return;
fl_nondfltopts = false;
while (fgets(buf, sizeof(buf), file))
{
str = buf;
token = GUI_ParseInPlace(&str);
if (!stricmp(token, "optimisation") || !stricmp(token, "opt"))
{
char *item = GUI_ParseInPlace(&str);
int value = GUI_ParseBooleanInPlace(&str, -1);
for (p = 0; optimisations[p].enabled; p++)
if (!stricmp(item, optimisations[p].abbrev))
{
if (value == -1)
value = !!(optimisations[p].flags & FLAG_ASDEFAULT);
else
fl_nondfltopts = true;
if (value)
optimisations[p].flags |= FLAG_SETINGUI;
else
optimisations[p].flags &= ~FLAG_SETINGUI;
break;
}
//don't worry if its not known
}
else if (!stricmp(token, "flag") || !stricmp(token, "fl") || !stricmp(token, "keyword"))
{
char *item = GUI_ParseInPlace(&str);
int value = GUI_ParseBooleanInPlace(&str, -1);
for (p = 0; compiler_flag[p].enabled; p++)
if (!stricmp(item, compiler_flag[p].abbrev))
{
if (value == -1)
value = !!(compiler_flag[p].flags & FLAG_ASDEFAULT);
if (value)
compiler_flag[p].flags |= FLAG_SETINGUI;
else
compiler_flag[p].flags &= ~FLAG_SETINGUI;
break;
}
//don't worry if its not known
}
else if (!stricmp(token, "enginebinary"))
QC_strlcpy(enginebinary, GUI_ParseInPlace(&str), sizeof(enginebinary));
else if (!stricmp(token, "basedir"))
QC_strlcpy(enginebasedir, GUI_ParseInPlace(&str), sizeof(enginebasedir));
else if (!stricmp(token, "engineargs"))
QC_strlcpy(enginecommandline, GUI_ParseInPlace(&str), sizeof(enginecommandline));
else if (!stricmp(token, "srcfile"))
QC_strlcpy(progssrcname, GUI_ParseInPlace(&str), sizeof(progssrcname));
else if (!stricmp(token, "src"))
QC_strlcpy(progssrcdir, GUI_ParseInPlace(&str), sizeof(progssrcdir));
else if (!stricmp(token, "parameters"))
QC_strlcpy(parameters, GUI_ParseInPlace(&str), sizeof(parameters));
else if (!stricmp(token, "log"))
fl_log = GUI_ParseBooleanInPlace(&str, false);
else if (!stricmp(token, "compileonstart"))
fl_compileonstart = GUI_ParseBooleanInPlace(&str, false);
else if (!stricmp(token, "showall"))
fl_showall = GUI_ParseBooleanInPlace(&str, false);
else if (!stricmp(token, "extramargins"))
fl_extramargins = GUI_ParseBooleanInPlace(&str, false);
else if (!stricmp(token, "hexen2"))
fl_hexen2 = GUI_ParseBooleanInPlace(&str, false);
else if (!stricmp(token, "extendedopcodes"))
fl_ftetarg = GUI_ParseBooleanInPlace(&str, false);
else if (*token)
{
puts("Unknown setting: "); puts(token); puts("\n");
}
}
fclose(file);
}
//this function takes the windows specified commandline and strips out all the options menu items.
@ -116,13 +354,55 @@ void GUI_ParseCommandLine(char *args)
int paramlen=0;
int l, p;
char *next;
pbool isfirst = true;
//find the first argument
while (*args == ' ' || *args == '\t')
args++;
for (next = args; *next&&*next!=' '&&*next !='\t'; next++)
;
if (*args != '-')
{
pbool qt = *args == '\"';
l = 0;
if (qt)
args++;
while (*args != ' ' && *args)
{
if (qt && *args == '\"')
{
args++;
break;
}
progssrcname[l++] = *args++;
}
progssrcname[l] = 0;
next = args;
args = strrchr(progssrcname, '\\');
while(args && strchr(args, '/'))
args = strchr(args, '/');
if (args)
{
memcpy(progssrcdir, progssrcname, args-progssrcname);
progssrcdir[args-progssrcname] = 0;
args++;
memmove(progssrcname, args, strlen(args)+1);
SetCurrentDirectoryA(progssrcdir);
*progssrcdir = 0;
}
args = next;
}
GUI_LoadConfig();
while(*args)
{
while (*args <= ' ' && *args)
while (*args == ' ' || *args == '\t')
args++;
for (next = args; *next>' '; next++)
for (next = args; *next&&*next!=' '&&*next !='\t'; next++)
;
strncpy(parameters+paramlen, args, next-args);
@ -242,10 +522,6 @@ void GUI_ParseCommandLine(char *args)
{
fl_showall = true;
}
else if (!strnicmp(parameters+paramlen, "-ah", 3) || !strnicmp(parameters+paramlen, "/ah", 3))
{
fl_autohighlight = true;
}
else if (!strnicmp(parameters+paramlen, "-ac", 3) || !strnicmp(parameters+paramlen, "/ac", 3))
{
fl_compileonstart = true;
@ -308,6 +584,7 @@ void GUI_ParseCommandLine(char *args)
paramlen += l;
}
}
/*
else if (isfirst && *args != '-' && *args != '/')
{
pbool qt = *args == '\"';
@ -339,14 +616,13 @@ void GUI_ParseCommandLine(char *args)
*progssrcdir = 0;
}
}
*/
else
{
parameters[paramlen+next-args] = ' ';
paramlen += l;
}
isfirst = false;
args=next;
}
if (paramlen)
@ -402,6 +678,8 @@ int GUI_BuildParms(char *args, char **argv, pbool quick)
int argc;
char *next;
int i;
int targ;
char *targs[] = {"", "-Th2", "-Tfte", "-Tfteh2"};
argc = 1;
@ -429,9 +707,12 @@ int GUI_BuildParms(char *args, char **argv, pbool quick)
args=next;
}
if (fl_hexen2)
targ = 0;
targ |= fl_hexen2?1:0;
targ |= fl_ftetarg?2:0;
if (*targs[targ])
{
strcpy(param+paramlen, "-Th2");
strcpy(param+paramlen, targs[targ]);
argv[argc++] = param+paramlen;
paramlen += strlen(param+paramlen)+1;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
LoadFile
==============
*/
unsigned char *PDECL QCC_ReadFile (const char *fname, void *buffer, int len)
unsigned char *PDECL QCC_ReadFile (const char *fname, void *buffer, int len, size_t *sz)
{
long length;
FILE *f;
@ -21,6 +21,8 @@ unsigned char *PDECL QCC_ReadFile (const char *fname, void *buffer, int len)
if (length != len)
return NULL;
if (sz)
*sz = length;
return buffer;
}
int PDECL QCC_FileSize (const char *fname)
@ -84,14 +86,17 @@ int logprintf(const char *format, ...)
va_end (argptr);
printf("%s", string);
// fputs(string, stderr);
if (logfile)
fputs(string, logfile);
return 0;
}
#include <windows.h>
int main (int argc, char **argv)
{
unsigned int i;
pbool sucess;
progexterns_t ext;
progfuncs_t funcs;
@ -105,6 +110,15 @@ int main (int argc, char **argv)
funcs.funcs.parms->Printf = logprintf;
funcs.funcs.parms->Sys_Error = Sys_Error;
logfile = fopen("fteqcc.log", "wt");
fputs("Args:", logfile);
for (i = 0; i < argc; i++)
{
if (strchr(argv[i], ' '))
fprintf(logfile, " \"%s\"", argv[i]);
else
fprintf(logfile, " %s", argv[i]);
}
fprintf(logfile, "\n");
sucess = CompileParams(&funcs, true, argc, argv);
qccClearHunk();
if (logfile)