]> git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/source/fteqcc-src/qcc_pr_comp.c
Update fteqcc source
[voretournament/voretournament.git] / misc / source / fteqcc-src / qcc_pr_comp.c
index a269987703a6747564f4569afb90c175b73c269e..badefcac4e2ff9b58f8355347db3fab4ee963a72 100644 (file)
@@ -12,9 +12,6 @@ extern char *compilingfile;
 
 int conditional;
 
-extern int dotranslate;
-extern int dotranslate_count;
-
 //standard qcc keywords
 #define keyword_do             1
 #define keyword_return 1
@@ -28,6 +25,7 @@ pbool keyword_asm;
 pbool keyword_break;
 pbool keyword_case;
 pbool keyword_class;
+pbool keyword_optional;
 pbool keyword_const;   //fixme
 pbool keyword_continue;
 pbool keyword_default;
@@ -80,6 +78,7 @@ pbool flag_fasttrackarrays;   //Faster arrays, dynamically detected, activated onl
 pbool flag_msvcstyle;          //MSVC style warnings, so msvc's ide works properly
 pbool flag_assume_integer;     //5 - is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
 pbool flag_filetimes;
+pbool flag_typeexplicit;       //no implicit type conversions, you must do the casts yourself.
 
 pbool opt_overlaptemps;                //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
 pbool opt_assignments;         //STORE_F isn't used if an operation wrote to a temp.
@@ -134,7 +133,6 @@ void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);
 void *(*pHash_Add)(hashtable_t *table, const char *name, void *data, bucket_t *);
 
 QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, pbool saved);
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
 QCC_type_t *QCC_PR_FindType (QCC_type_t *type);
 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
@@ -192,7 +190,7 @@ int num_labels;
 
 QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
 
-#define ASSOC_RIGHT_RESULT ASSOC_RIGHT
+//#define ASSOC_RIGHT_RESULT ASSOC_RIGHT
 
 //========================================
 
@@ -295,9 +293,9 @@ QCC_opcode_t pr_opcodes[] =
 
 //these are hexen2
  {7, "*=", "MULSTORE_F",       6, ASSOC_RIGHT_RESULT,                          &type_float, &type_float, &type_float},
- {7, "*=", "MULSTORE_V",       6, ASSOC_RIGHT_RESULT,                          &type_vector, &type_float, &type_vector},
+ {7, "*=", "MULSTORE_VF",      6, ASSOC_RIGHT_RESULT,                          &type_vector, &type_float, &type_vector},
  {7, "*=", "MULSTOREP_F",      6, ASSOC_RIGHT_RESULT,                          &type_pointer, &type_float, &type_float},
- {7, "*=", "MULSTOREP_V",      6, ASSOC_RIGHT_RESULT,                          &type_pointer, &type_float, &type_vector},
+ {7, "*=", "MULSTOREP_VF",     6, ASSOC_RIGHT_RESULT,                          &type_pointer, &type_float, &type_vector},
 
  {7, "/=", "DIVSTORE_F",       6, ASSOC_RIGHT_RESULT,                          &type_float, &type_float, &type_float},
  {7, "/=", "DIVSTOREP_F",      6, ASSOC_RIGHT_RESULT,                          &type_pointer, &type_float, &type_float},
@@ -358,8 +356,8 @@ QCC_opcode_t pr_opcodes[] =
  {7, "<CALL8H>", "CALL8H",     -1, ASSOC_LEFT,                 &type_function, &type_vector, &type_vector},
 
  {7, "=",      "STORE_I", 6, ASSOC_RIGHT,                              &type_integer, &type_integer, &type_integer},
- {7, "=",      "STORE_IF", 6, ASSOC_RIGHT,                     &type_integer, &type_float, &type_integer},
- {7, "=",      "STORE_FI", 6, ASSOC_RIGHT,                     &type_float, &type_integer, &type_float},
+ {7, "=",      "STORE_IF", 6, ASSOC_RIGHT,                     &type_float, &type_integer, &type_integer},
+ {7, "=",      "STORE_FI", 6, ASSOC_RIGHT,                     &type_integer, &type_float, &type_float},
 
  {7, "+", "ADD_I", 4, ASSOC_LEFT,                              &type_integer, &type_integer, &type_integer},
  {7, "+", "ADD_FI", 4, ASSOC_LEFT,                             &type_float, &type_integer, &type_float},
@@ -400,7 +398,7 @@ QCC_opcode_t pr_opcodes[] =
 
                                                                                //var,          offset                  return
  {7, "<ARRAY>", "GET_POINTER", -1, ASSOC_LEFT, &type_float,            &type_integer, &type_pointer},
- {7, "<ARRAY>", "ARRAY_OFS", -1, ASSOC_LEFT,           &type_pointer,  &type_integer, &type_pointer},
+ {7, "<ARRAY>", "MUL4ADD_I", -1, ASSOC_LEFT,           &type_pointer,  &type_integer, &type_pointer},
 
  {7, "=", "LOADA_F", 6, ASSOC_LEFT,                    &type_float,    &type_integer, &type_float},
  {7, "=", "LOADA_V", 6, ASSOC_LEFT,                    &type_vector,   &type_integer, &type_vector},
@@ -494,9 +492,9 @@ QCC_opcode_t pr_opcodes[] =
 {7, "<>",      "GLOAD_S",              -1, ASSOC_LEFT,                         &type_float,    &type_float,    &type_float},
 {7, "<>",      "GLOAD_FNC",    -1, ASSOC_LEFT,                         &type_float,    &type_float,    &type_float},
 
-{7, "<>",      "BOUNDCHECK",   -1, ASSOC_LEFT,                         &type_float,    &type_float,    &type_float},
+{7, "<>",      "BOUNDCHECK",   -1, ASSOC_LEFT,                         &type_integer,  NULL,   NULL},
 
-{7, "=",       "STOREP_P",             6,      ASSOC_RIGHT,                            &type_pointer,  &type_pointer,  &type_void},
+{7, "<UNUSED>",        "UNUSED",               6,      ASSOC_RIGHT,                            &type_void,     &type_void,     &type_void},
 {7, "<PUSH>",  "PUSH",         -1, ASSOC_RIGHT,                        &type_float,    &type_void,             &type_pointer},
 {7, "<POP>",   "POP",          -1, ASSOC_RIGHT,                        &type_float,    &type_void,             &type_void},
 
@@ -524,23 +522,30 @@ QCC_opcode_t pr_opcodes[] =
  {7, "+=", "ADDSTOREP_I",      6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_integer},
  {7, "-=", "SUBSTOREP_I",      6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_integer},
 
- {7, "*=", "OP_MULSTORE_IF",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "*=", "OP_MULSTOREP_IF",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "/=", "OP_DIVSTORE_IF",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "/=", "OP_DIVSTOREP_IF",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "+=", "OP_ADDSTORE_IF",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "+=", "OP_ADDSTOREP_IF",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "-=", "OP_SUBSTORE_IF",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
- {7, "-=", "OP_SUBSTOREP_IF",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_float, &type_integer},
-
- {7, "*=", "OP_MULSTORE_FI",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "*=", "OP_MULSTOREP_FI",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "/=", "OP_DIVSTORE_FI",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "/=", "OP_DIVSTOREP_FI",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "+=", "OP_ADDSTORE_FI",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "+=", "OP_ADDSTOREP_FI",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "-=", "OP_SUBSTORE_FI",   6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
- {7, "-=", "OP_SUBSTOREP_FI",  6,      ASSOC_RIGHT_RESULT,             &type_pointer, &type_integer, &type_float},
+ {7, "*=", "MULSTORE_IF",      6,      ASSOC_RIGHT_RESULT,             &type_integer, &type_float, &type_float},
+ {7, "*=", "MULSTOREP_IF",     6,      ASSOC_RIGHT_RESULT,             &type_intpointer, &type_float, &type_float},
+ {7, "/=", "DIVSTORE_IF",      6,      ASSOC_RIGHT_RESULT,             &type_integer, &type_float, &type_float},
+ {7, "/=", "DIVSTOREP_IF",     6,      ASSOC_RIGHT_RESULT,             &type_intpointer, &type_float, &type_float},
+ {7, "+=", "ADDSTORE_IF",      6,      ASSOC_RIGHT_RESULT,             &type_integer, &type_float, &type_float},
+ {7, "+=", "ADDSTOREP_IF",     6,      ASSOC_RIGHT_RESULT,             &type_intpointer, &type_float, &type_float},
+ {7, "-=", "SUBSTORE_IF",      6,      ASSOC_RIGHT_RESULT,             &type_integer, &type_float, &type_float},
+ {7, "-=", "SUBSTOREP_IF",     6,      ASSOC_RIGHT_RESULT,             &type_intpointer, &type_float, &type_float},
+
+ {7, "*=", "MULSTORE_FI",      6,      ASSOC_RIGHT_RESULT,             &type_float, &type_integer, &type_float},
+ {7, "*=", "MULSTOREP_FI",     6,      ASSOC_RIGHT_RESULT,             &type_floatpointer, &type_integer, &type_float},
+ {7, "/=", "DIVSTORE_FI",      6,      ASSOC_RIGHT_RESULT,             &type_float, &type_integer, &type_float},
+ {7, "/=", "DIVSTOREP_FI",     6,      ASSOC_RIGHT_RESULT,             &type_floatpointer, &type_integer, &type_float},
+ {7, "+=", "ADDSTORE_FI",      6,      ASSOC_RIGHT_RESULT,             &type_float, &type_integer, &type_float},
+ {7, "+=", "ADDSTOREP_FI",     6,      ASSOC_RIGHT_RESULT,             &type_floatpointer, &type_integer, &type_float},
+ {7, "-=", "SUBSTORE_FI",      6,      ASSOC_RIGHT_RESULT,             &type_float, &type_integer, &type_float},
+ {7, "-=", "SUBSTOREP_FI",     6,      ASSOC_RIGHT_RESULT,             &type_floatpointer, &type_integer, &type_float},
+
+ {7, "*=", "MULSTORE_VI",      6, ASSOC_RIGHT_RESULT,          &type_vector, &type_integer, &type_vector},
+ {7, "*=", "MULSTOREP_VI",     6, ASSOC_RIGHT_RESULT,          &type_pointer, &type_integer, &type_vector},
+
+ {7, "=", "LOADA_STRUCT",      6, ASSOC_LEFT,                          &type_float,    &type_integer, &type_float},
+
+ {7, "=",      "STOREP_P",             6,      ASSOC_RIGHT,                            &type_pointer,  &type_pointer,  &type_pointer},
 
  {0, NULL}
 };
@@ -595,6 +600,7 @@ pbool OpAssignsToB(unsigned int op)
 #undef ASSOC_RIGHT_RESULT
 
 #define        TOP_PRIORITY    7
+#define FUNC_PRIORITY  1
 #define UNARY_PRIORITY 1
 #define        NOT_PRIORITY    5
 //conditional and/or
@@ -657,11 +663,17 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
                &pr_opcodes[OP_MUL_F],
                &pr_opcodes[OP_MUL_V],
                &pr_opcodes[OP_MUL_FV],
+               &pr_opcodes[OP_MUL_IV],
                &pr_opcodes[OP_MUL_VF],
+               &pr_opcodes[OP_MUL_VI],
                &pr_opcodes[OP_MUL_I],
+               &pr_opcodes[OP_MUL_FI],
+               &pr_opcodes[OP_MUL_IF],
 
                &pr_opcodes[OP_DIV_F],
                &pr_opcodes[OP_DIV_I],
+               &pr_opcodes[OP_DIV_FI],
+               &pr_opcodes[OP_DIV_IF],
                &pr_opcodes[OP_DIV_VF],
 
                &pr_opcodes[OP_BITAND_F],
@@ -734,6 +746,8 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
 
                NULL
        }, {    //6
+               &pr_opcodes[OP_STOREP_P],
+
                &pr_opcodes[OP_STORE_F],
                &pr_opcodes[OP_STORE_V],
                &pr_opcodes[OP_STORE_S],
@@ -754,7 +768,6 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
                &pr_opcodes[OP_STOREP_I],
                &pr_opcodes[OP_STOREP_IF],
                &pr_opcodes[OP_STOREP_FI],
-               &pr_opcodes[OP_STOREP_P],
 
                &pr_opcodes[OP_DIVSTORE_F],
                &pr_opcodes[OP_DIVSTORE_I],
@@ -765,12 +778,14 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
                &pr_opcodes[OP_DIVSTOREP_IF],
                &pr_opcodes[OP_DIVSTOREP_FI],
                &pr_opcodes[OP_MULSTORE_F],
-               &pr_opcodes[OP_MULSTORE_V],
+               &pr_opcodes[OP_MULSTORE_VF],
+               &pr_opcodes[OP_MULSTORE_VI],
                &pr_opcodes[OP_MULSTORE_I],
                &pr_opcodes[OP_MULSTORE_IF],
                &pr_opcodes[OP_MULSTORE_FI],
                &pr_opcodes[OP_MULSTOREP_F],
-               &pr_opcodes[OP_MULSTOREP_V],
+               &pr_opcodes[OP_MULSTOREP_VF],
+               &pr_opcodes[OP_MULSTOREP_VI],
                &pr_opcodes[OP_MULSTOREP_I],
                &pr_opcodes[OP_MULSTOREP_IF],
                &pr_opcodes[OP_MULSTOREP_FI],
@@ -913,7 +928,6 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op)
 
                //stores into a pointer (generated from 'ent.field=XXX')
                case OP_STOREP_I:       //no worse than the other OP_STOREP_X functions
-               case OP_STOREP_P:
                //reads from an entity field
                case OP_LOAD_I:         //no worse than the other OP_LOAD_X functions.
                case OP_LOAD_P:
@@ -1011,9 +1025,9 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op)
                        return false; //DPFIXME: dp's bounds check may give false positives with expected uses.
 
                case OP_MULSTORE_F:
-               case OP_MULSTORE_V:
+               case OP_MULSTORE_VF:
                case OP_MULSTOREP_F:
-               case OP_MULSTOREP_V: // e.v *= f
+               case OP_MULSTOREP_VF: // e.v *= f
                case OP_DIVSTORE_F:
                case OP_DIVSTOREP_F:
                case OP_STORE_IF:
@@ -1097,8 +1111,14 @@ Emits a primitive statement, returning the var it places it's value in
 QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement);
 static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
 {
+       /*no conversion needed*/
+       if (var->type->type == wanted)
+               return 0;
        if (var->type->type == ev_integer && wanted == ev_function)
                return 0;
+       if (var->type->type == ev_integer && wanted == ev_pointer)
+               return 0;
+       /*stuff needs converting*/
        if (var->type->type == ev_pointer && var->type->aux_type)
        {
                if (var->type->aux_type->type == ev_float && wanted == ev_integer)
@@ -1116,10 +1136,12 @@ static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
                        return OP_CONV_ITOF;
        }
 
+       /*impossible*/
        return -1;
 }
-QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted)
+QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal)
 {
+       extern char *basictypenames[];
        int o;
 
        if (pr_classtype && var->type->type == ev_field && wanted != ev_field)
@@ -1127,7 +1149,7 @@ QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted)
                if (pr_classtype)
                {       //load self.var into a temp
                        QCC_def_t *self;
-                       self = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+                       self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
                        switch(wanted)
                        {
                        case ev_float:
@@ -1148,16 +1170,25 @@ QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted)
 
        o = QCC_ShouldConvert(var, wanted);
 
-       if (o <= 0)     //no conversion
+       if (o == 0) //type already matches
                return var;
-
+       if (flag_typeexplicit)
+               QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
+       if (o < 0)
+       {
+               if (fatal)
+                       QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
+               else
+                       return var;
+       }
 
        return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL);       //conversion return value
 }
-QCC_def_t *QCC_MakeStringDef(char *value);
-QCC_def_t *QCC_MakeFloatDef(float value);
-QCC_def_t *QCC_MakeIntDef(int value);
-QCC_def_t *QCC_MakeVectorDef(float a, float b, float c);
+QCC_def_t *QCC_MakeTranslateStringConst(char *value);
+QCC_def_t *QCC_MakeStringConst(char *value);
+QCC_def_t *QCC_MakeFloatConst(float value);
+QCC_def_t *QCC_MakeIntConst(int value);
+QCC_def_t *QCC_MakeVectorConst(float a, float b, float c);
 
 typedef struct freeoffset_s {
        struct freeoffset_s *next;
@@ -1363,10 +1394,8 @@ static void QCC_FreeTemps(void)
        while(t)
        {
                if (t->used && !pr_error_count) //don't print this after an error jump out.
-               {
-                       QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used in %s", pr_scope->name);
-                       t->used = false;
-               }
+                       QCC_PR_ParseWarning(WARN_DEBUGGING, "Internal: temp(ofs %i) was not released in %s. This implies miscompilation.", t->ofs, pr_scope->name);
+               t->used = false;
                t = t->next;
        }
 }
@@ -1399,6 +1428,13 @@ static void QCC_LockTemp(QCC_def_t *d)
        if (d->temp && d->temp->used)
                d->temp->scope = pr_scope;
 }
+static void QCC_ForceLockTempForOffset(int ofs)
+{
+       temp_t *t;
+       for (t = functemps; t; t = t->next)
+               if(t->ofs == ofs /* && t->used */)
+                       t->scope = pr_scope;
+}
 
 static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement)
 {
@@ -1501,14 +1537,17 @@ static void QCC_fprintfLocals(FILE *f, gofs_t paramstart, gofs_t paramend)
        {
                if (var->ofs >= paramstart && var->ofs < paramend)
                        continue;
-               fprintf(f, "local %s %s; /* at %d */\n", TypeName(var->type), var->name, var->ofs);
+               if (var->arraysize)
+                       fprintf(f, "local %s %s[%i];\n", TypeName(var->type), var->name, var->arraysize);
+               else
+                       fprintf(f, "local %s %s;\n", TypeName(var->type), var->name);
        }
 
        for (t = functemps, i = 0; t; t = t->next, i++)
        {
                if (t->lastfunc == pr_scope)
                {
-                       fprintf(f, "local %s temp_%i; /* at %d */\n", (t->size == 1)?"float":"vector", i, t->ofs);
+                       fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i);
                }
        }
 }
@@ -1528,9 +1567,9 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size)
                if (ofs >= t->ofs && ofs < t->ofs + t->size)
                {
                        if (size < t->size)
-                               sprintf(message, "temp_%i_%c", i, 'x' + (ofs-t->ofs)%3);
+                               sprintf(message, "temp_%i_%c", t->ofs, 'x' + (ofs-t->ofs)%3);
                        else
-                               sprintf(message, "temp_%i", i);
+                               sprintf(message, "temp_%i", t->ofs);
                        return message;
                }
        }
@@ -1615,36 +1654,28 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size)
 }
 #endif
 
-QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
+QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force);
+
+QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
 {
        QCC_dstatement_t        *statement;
        QCC_def_t                       *var_c=NULL, *temp=NULL;
 
        if (outstatement == (QCC_dstatement_t **)0xffffffff)
                outstatement = NULL;
-       else if (op->priority != -1)
+       else if (op->priority != -1 && op->priority != CONDITION_PRIORITY)
        {
                if (op->associative!=ASSOC_LEFT)
                {
-                       if (op->type_a == &type_pointer)
-                               var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
-                       else
-                               var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type);
+                       if (op->type_a != &type_pointer)
+                               var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type, false);
                }
                else
                {
                        if (var_a)
-                               var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
+                               var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type, false);
                        if (var_b)
-                               var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
-//                     if (op->type_a == &def_pointer)
-//                                     var_a = QCC_SupplyConversion(var_a, (*op->type_b)->type);
-//                             else
-//                                     var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
-//                     }
-//                             //can't convert the left componant of an assignment operation
-//                     if (var_b && var_b->type && var_b->type != op->type_b->type)
-//                             var_b = QCC_SupplyConversion(var_b, op->type_b->type->type);
+                               var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type, false);
                }
        }
 
@@ -1677,73 +1708,92 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                                //both are constants
                                switch (op - pr_opcodes)        //improve some of the maths.
                                {
+                               case OP_LOADA_F:
+                               case OP_LOADA_V:
+                               case OP_LOADA_S:
+                               case OP_LOADA_ENT:
+                               case OP_LOADA_FLD:
+                               case OP_LOADA_FNC:
+                               case OP_LOADA_I:
+                                       {
+                                               QCC_def_t *nd;
+                                               nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                               memset (nd, 0, sizeof(QCC_def_t));
+                                               nd->type = var_a->type;
+                                               nd->ofs = var_a->ofs + G_INT(var_b->ofs);
+                                               nd->temp = var_a->temp;
+                                               nd->constant = true;
+                                               nd->name = var_a->name;
+                                               return nd;
+                                       }
+                                       break;
                                case OP_BITOR_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
+                                       return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
                                case OP_BITAND_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
+                                       return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
                                case OP_MUL_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
+                                       return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
                                case OP_DIV_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
+                                       return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
                                case OP_ADD_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
+                                       return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
                                case OP_SUB_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
+                                       return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
 
                                case OP_BITOR_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) | G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) | G_INT(var_b->ofs));
                                case OP_BITAND_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) & G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) & G_INT(var_b->ofs));
                                case OP_MUL_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) * G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) * G_INT(var_b->ofs));
                                case OP_DIV_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) / G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) / G_INT(var_b->ofs));
                                case OP_ADD_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) + G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) + G_INT(var_b->ofs));
                                case OP_SUB_I:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) - G_INT(var_b->ofs));
 
                                case OP_AND_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs));
                                case OP_OR_F:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs));
+                                       return QCC_MakeIntConst(G_INT(var_a->ofs) || G_INT(var_b->ofs));
                                case OP_MUL_V:  //mul_f is actually a dot-product
                                        optres_constantarithmatic++;
-                                       return QCC_MakeFloatDef(        G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
+                                       return QCC_MakeFloatConst(      G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
                                                                                                G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1) +
                                                                                                G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
                                case OP_MUL_FV:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeVectorDef(       G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
+                                       return QCC_MakeVectorConst(     G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
                                                                                                G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1),
                                                                                                G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
                                case OP_MUL_VF:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeVectorDef(       G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
+                                       return QCC_MakeVectorConst(     G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
                                                                                                G_FLOAT(var_a->ofs+1) * G_FLOAT(var_b->ofs),
                                                                                                G_FLOAT(var_a->ofs+2) * G_FLOAT(var_b->ofs));
                                case OP_ADD_V:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeVectorDef(       G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
+                                       return QCC_MakeVectorConst(     G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
                                                                                                G_FLOAT(var_a->ofs+1) + G_FLOAT(var_b->ofs+1),
                                                                                                G_FLOAT(var_a->ofs+2) + G_FLOAT(var_b->ofs+2));
                                case OP_SUB_V:
                                        optres_constantarithmatic++;
-                                       return QCC_MakeVectorDef(       G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
+                                       return QCC_MakeVectorConst(     G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
                                                                                                G_FLOAT(var_a->ofs+1) - G_FLOAT(var_b->ofs+1),
                                                                                                G_FLOAT(var_a->ofs+2) - G_FLOAT(var_b->ofs+2));
                                }
@@ -1753,6 +1803,12 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                                //a is const, b is not
                                switch (op - pr_opcodes)
                                {
+                               case OP_CONV_FTOI:
+                                       optres_constantarithmatic++;
+                                       return QCC_MakeIntConst(G_FLOAT(var_a->ofs));
+                               case OP_CONV_ITOF:
+                                       optres_constantarithmatic++;
+                                       return QCC_MakeFloatConst(G_INT(var_a->ofs));
                                case OP_BITOR_F:
                                case OP_OR_F:
                                case OP_ADD_F:
@@ -1816,6 +1872,25 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        //b is const, a is not
                        switch (op - pr_opcodes)
                        {
+                       case OP_LOADA_F:
+                       case OP_LOADA_V:
+                       case OP_LOADA_S:
+                       case OP_LOADA_ENT:
+                       case OP_LOADA_FLD:
+                       case OP_LOADA_FNC:
+                       case OP_LOADA_I:
+                               {
+                                       QCC_def_t *nd;
+                                       nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                       memset (nd, 0, sizeof(QCC_def_t));
+                                       nd->type = var_a->type;
+                                       nd->ofs = var_a->ofs + G_INT(var_b->ofs);
+                                       nd->temp = var_a->temp;
+                                       nd->constant = false;
+                                       nd->name = var_a->name;
+                                       return nd;
+                               }
+                               break;
                        case OP_BITOR_F:
                        case OP_OR_F:
                        case OP_SUB_F:
@@ -1874,7 +1949,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                                        return var_a;
                                }
                        case OP_AND_I:
-                               if (G_INT(var_b->ofs) != 0)
+                               if (G_INT(var_b->ofs) == 0)
                                {
                                        optres_constantarithmatic++;
                                        QCC_UnFreeTemp(var_a);
@@ -1887,6 +1962,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
 
        switch (op - pr_opcodes)
        {
+       case OP_LOADA_F:
+       case OP_LOADA_V:
+       case OP_LOADA_S:
+       case OP_LOADA_ENT:
+       case OP_LOADA_FLD:
+       case OP_LOADA_FNC:
+       case OP_LOADA_I:
+               break;
        case OP_AND_F:
                if (var_a->ofs == var_b->ofs)
                        QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
@@ -2035,8 +2118,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
        {
                switch(op - pr_opcodes)
                {
+               case OP_LOADA_STRUCT:
+                       /*emit this anyway. if it reaches runtime then you messed up.
+                       this is valid only if you do &foo[0]*/
+                       break;
+
+
                case OP_IF_S:
-                       var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
+                       var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
                        numstatements--;
                        var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
                        statement = &statements[numstatements];
@@ -2047,7 +2136,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        break;
 
                case OP_IFNOT_S:
-                       var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
+                       var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
                        numstatements--;
                        var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
                        statement = &statements[numstatements];
@@ -2058,7 +2147,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        break;
 
                case OP_IF_F:
-                       var_c = QCC_MakeFloatDef(0);
+                       var_c = QCC_MakeFloatConst(0);
                        numstatements--;
                        var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
                        statement = &statements[numstatements];
@@ -2069,7 +2158,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        break;
 
                case OP_IFNOT_F:
-                       var_c = QCC_MakeFloatDef(0);
+                       var_c = QCC_MakeFloatConst(0);
                        numstatements--;
                        var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
                        statement = &statements[numstatements];
@@ -2086,6 +2175,13 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        var_a = var_c;
                        var_c = var_a;
                        break;
+               case OP_ADDSTORE_I:
+                       op = &pr_opcodes[OP_ADD_I];
+                       var_c = var_b;
+                       var_b = var_a;
+                       var_a = var_c;
+                       var_c = var_a;
+                       break;
                case OP_ADDSTORE_FI:
                        op = &pr_opcodes[OP_ADD_FI];
                        var_c = var_b;
@@ -2183,13 +2279,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        var_c = var_a;
                        break;
 
-               case OP_MULSTORE_V:
+               case OP_MULSTORE_VF:
                        op = &pr_opcodes[OP_MUL_VF];
                        var_c = var_b;
                        var_b = var_a;
                        var_a = var_c;
                        var_c = var_a;
                        break;
+               case OP_MULSTORE_VI:
+                       op = &pr_opcodes[OP_MUL_VI];
+                       var_c = var_b;
+                       var_b = var_a;
+                       var_a = var_c;
+                       var_c = var_a;
+                       break;
 
                case OP_BITSET_I:
                        op = &pr_opcodes[OP_BITOR_I];
@@ -2206,6 +2309,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        var_c = var_a;
                        break;
 
+               case OP_STOREP_P:
+                       op = &pr_opcodes[OP_STOREP_I];
+                       break;
+
                case OP_BITCLR:
                        //b = var, a = bit field.
 
@@ -2236,8 +2343,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                case OP_DIVSTOREP_FI:
                case OP_DIVSTOREP_IF:
 
+               case OP_MULSTOREP_VF:
+               case OP_MULSTOREP_VI:
+               case OP_SUBSTOREP_V:
+               case OP_ADDSTOREP_V:
 
                case OP_SUBSTOREP_F:
+               case OP_SUBSTOREP_I:
+               case OP_ADDSTOREP_I:
                case OP_ADDSTOREP_F:
                case OP_MULSTOREP_F:
                case OP_DIVSTOREP_F:
@@ -2251,35 +2364,60 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        {
                                int st;
                                int need_lock = false;
-                               for (st = numstatements-2; st>=0; st--)
+                               if (var_b->temp)
                                {
-                                       if (statements[st].op == OP_ADDRESS)
-                                               if (statements[st].c == var_b->ofs)
-                                                       break;
+                                       for (st = numstatements-2; st>=0; st--)
+                                       {
+                                               if (statements[st].op == OP_ADDRESS)
+                                                       if (statements[st].c == var_b->ofs)
+                                                               break;
 
-                                       if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
-                                               need_lock = true;
+                                               if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
+                                                       need_lock = true;
 
-                                       if (statements[st].c == var_b->ofs)
-                                               QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
+                                               if (statements[st].c == var_b->ofs)
+                                               {
+                                                       st = -1;
+                                                       break;
+                                               }
+                                       }
                                }
-                               if (st < 0)
-                                       QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement");
+                               else
+                                       st = -1;
+
                                var_c = QCC_GetTemp(*op->type_c);
-                               if (need_lock)
-                                       QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
+                               if (st < 0)
+                               {
+                                       /*generate new OP_LOADP instruction*/
+                                       statement->op = ((*op->type_c)->type==ev_vector)?OP_LOADP_V:OP_LOADP_F;
+                                       statement->a = var_b->ofs;
+                                       statement->b = var_c->ofs;
+                                       statement->c = 0;
+                               }
+                               else
+                               {
+                                       /*it came from an OP_ADDRESS - st says the instruction*/
+                                       if (need_lock)
+                                       {
+                                               QCC_ForceLockTempForOffset(statements[st].a);
+                                               QCC_ForceLockTempForOffset(statements[st].b);
+                                               QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
+                                       }
 
-                               statement_linenums[statement-statements] = statement_linenums[st];
-                               statement->op = OP_ADDRESS;
-                               statement->a = statements[st].a;
-                               statement->b = statements[st].b;
-                               statement->c = statements[st].c;
+                                       /*generate new OP_ADDRESS instruction - FIXME: the arguments may have changed since the original instruction*/
+                                       statement_linenums[statement-statements] = statement_linenums[st];
+                                       statement->op = OP_ADDRESS;
+                                       statement->a = statements[st].a;
+                                       statement->b = statements[st].b;
+                                       statement->c = statements[st].c;
 
-                               statement_linenums[st] = pr_source_line;
-                               statements[st].op = OP_LOAD_F;
-                               statements[st].a = statements[st].a;
-                               statements[st].b = statements[st].b;
-                               statements[st].c = var_c->ofs;
+                                       /*convert old one to an OP_LOAD*/
+                                       statement_linenums[st] = pr_source_line;
+                                       statements[st].op = ((*op->type_c)->type==ev_vector)?OP_LOAD_V:OP_LOAD_F;
+                                       statements[st].a = statements[st].a;
+                                       statements[st].b = statements[st].b;
+                                       statements[st].c = var_c->ofs;
+                               }
                        }
 
                        statement = &statements[numstatements];
@@ -2288,9 +2426,24 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        statement_linenums[statement-statements] = pr_source_line;
                        switch(op - pr_opcodes)
                        {
+                       case OP_SUBSTOREP_V:
+                               statement->op = OP_SUB_V;
+                               break;
+                       case OP_ADDSTOREP_V:
+                               statement->op = OP_ADD_V;
+                               break;
+                       case OP_MULSTOREP_VF:
+                               statement->op = OP_MUL_VF;
+                               break;
+                       case OP_MULSTOREP_VI:
+                               statement->op = OP_MUL_VI;
+                               break;
                        case OP_SUBSTOREP_F:
                                statement->op = OP_SUB_F;
                                break;
+                       case OP_SUBSTOREP_I:
+                               statement->op = OP_SUB_I;
+                               break;
                        case OP_SUBSTOREP_IF:
                                statement->op = OP_SUB_IF;
                                break;
@@ -2318,6 +2471,9 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        case OP_ADDSTOREP_F:
                                statement->op = OP_ADD_F;
                                break;
+                       case OP_ADDSTOREP_I:
+                               statement->op = OP_ADD_I;
+                               break;
                        case OP_MULSTOREP_F:
                                statement->op = OP_MUL_F;
                                break;
@@ -2370,7 +2526,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                                var_a = var_c;  //this is the value.
                        }
 
-                       op = &pr_opcodes[OP_STOREP_F];
+                       op = &pr_opcodes[((*op->type_c)->type==ev_vector)?OP_STOREP_V:OP_STOREP_F];
                        QCC_FreeTemp(var_c);
                        var_c = NULL;
                        QCC_FreeTemp(var_b);
@@ -2379,86 +2535,6 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
                        numstatements++;
                        break;
 
-               case OP_MULSTOREP_V:
-               case OP_SUBSTOREP_V:
-               case OP_ADDSTOREP_V:
-//                     QCC_PR_ParseWarning(0, "XSTOREP_V emulation is still experimental");
-                       QCC_UnFreeTemp(var_a);
-                       QCC_UnFreeTemp(var_b);
-                       //don't chain these... this expansion is not the same.
-                       {
-                               int st;
-                               int need_lock = false;
-                               for (st = numstatements-2; st>=0; st--)
-                               {
-                                       if (statements[st].op == OP_ADDRESS)
-                                               if (statements[st].c == var_b->ofs)
-                                                       break;
-
-                                       if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
-                                               need_lock = true;
-
-                                       if (statements[st].c == var_b->ofs)
-                                               QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
-                               }
-                               if (st < 0)
-                                       QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_V couldn't find pointer generation");
-                               var_c = QCC_GetTemp(*op->type_c);
-                               if (need_lock)
-                                       QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
-
-                               statement_linenums[statement-statements] = statement_linenums[st];
-                               statement->op = OP_ADDRESS;
-                               statement->a = statements[st].a;
-                               statement->b = statements[st].b;
-                               statement->c = statements[st].c;
-
-                               statement_linenums[st] = pr_source_line;
-                               statements[st].op = OP_LOAD_V;
-                               statements[st].a = statements[st].a;
-                               statements[st].b = statements[st].b;
-                               statements[st].c = var_c->ofs;
-                       }
-
-                       statement = &statements[numstatements];
-                       numstatements++;
-
-                       statement_linenums[statement-statements] = pr_source_line;
-                       switch(op - pr_opcodes)
-                       {
-                       case OP_SUBSTOREP_V:
-                               statement->op = OP_SUB_V;
-                               break;
-                       case OP_ADDSTOREP_V:
-                               statement->op = OP_ADD_V;
-                               break;
-                       case OP_MULSTOREP_V:
-                               statement->op = OP_MUL_VF;
-                               break;
-                       default:        //no way will this be hit...
-                               QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes);
-                       }
-                       statement->a = var_a ? var_a->ofs : 0;
-                       statement->b = var_c ? var_c->ofs : 0;
-                       QCC_FreeTemp(var_c);
-                       var_c = QCC_GetTemp(*op->type_c);
-                       statement->c = var_c ? var_c->ofs : 0;
-
-                       var_b = var_b;  //this is the ptr.
-                       QCC_FreeTemp(var_a);
-                       var_a = var_c;  //this is the value.
-                       op = &pr_opcodes[OP_STOREP_V];
-
-
-
-
-                       QCC_FreeTemp(var_c);
-                       var_c = NULL;
-                       QCC_FreeTemp(var_b);
-
-                       statement = &statements[numstatements];
-                       numstatements++;
-                       break;
                default:
                        QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname);
                        break;
@@ -2571,21 +2647,32 @@ QCC_def_t       *QCC_PR_ParseImmediate (void)
 
        if (pr_immediate_type == type_float)
        {
-               cn = QCC_MakeFloatDef(pr_immediate._float);
+               cn = QCC_MakeFloatConst(pr_immediate._float);
                QCC_PR_Lex ();
                return cn;
        }
        if (pr_immediate_type == type_integer)
        {
-               cn = QCC_MakeIntDef(pr_immediate._int);
+               cn = QCC_MakeIntConst(pr_immediate._int);
                QCC_PR_Lex ();
                return cn;
        }
 
        if (pr_immediate_type == type_string)
        {
-               cn = QCC_MakeStringDef(pr_immediate_string);
-               QCC_PR_Lex ();
+               char tmp[8192];
+               strcpy(tmp, pr_immediate_string);
+
+               for(;;)
+               {
+                       QCC_PR_Lex ();
+                       if (pr_token_type == tt_immediate && pr_token_type == tt_immediate)
+                               strcat(tmp, pr_immediate_string);
+                       else
+                               break;
+               } 
+
+               cn = QCC_MakeStringConst(tmp);
                return cn;
        }
 
@@ -2876,7 +2963,7 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i
 
                //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self'
                //thiscall. copy the right ent into 'self' (if it's not the same offset)
-               d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+               d = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
                if (statements[laststatement-1].a != d->ofs)
                {
                        oself = QCC_GetTemp(type_entity);
@@ -2922,11 +3009,11 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i
                                //first two args are passed in the call opcode, so don't need to be copied
                                arglist[i]->references++;
                                d->references++;
-                               QCC_FreeTemp(arglist[i]);
+                               /*don't free these temps yet, free them after the return check*/
                                continue;
                        }
 
-               if (arglist[i]->type->size>1 || !opt_nonvec_parms)
+               if (arglist[i]->type->size == 3 || !opt_nonvec_parms)
                        QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
                else
                {
@@ -2938,12 +3025,28 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i
 
        //if the return value was in use, save it off now, so that it doesn't get clobbered
        if (def_ret.temp->used)
-       {
                oldret = QCC_GetTemp(def_ret.type);
+       else
+               oldret = NULL;
+
+       /*can free temps used for arguments now*/
+       if (callconvention == OP_CALL1H)
+       {
+               for (i = 0; i < argcount && i < 2; i++)
+                       QCC_FreeTemp(arglist[i]);
+       }
+
+       if (oldret && !def_ret.temp->used)
+       {
+               QCC_FreeTemp(oldret);
+               oldret = NULL;
+       }
+       else if (def_ret.temp->used)
+       {
                if (def_ret.type->size == 3)
-                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, (void*)0xffffffff));
                else
-                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, (void*)0xffffffff));
                QCC_UnFreeTemp(oldret);
                QCC_UnFreeTemp(&def_ret);
                QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
@@ -2983,35 +3086,29 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i
        if (oself)
                QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false);
 
-       for(; argcount; argcount--)
-       {
-               QCC_FreeTemp(arglist[argcount-1]);
-       }
-
        if (oldret)
        {
-               // Make sure our def_ret backup temp wasn't freed above
-               QCC_UnFreeTemp(oldret); //this bug fix was brought to you by Blub, the character \ and the number 0.
-
+               if (oldret->temp && !oldret->temp->used)
+                       QCC_PR_ParseWarning(0, "Ret was freed\n");
 
                //if we preserved the ofs_ret global, restore it here
                if (t->type == ev_variant)
                {
                        d = QCC_GetTemp(type_variant);
-                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
                }
                else
                {
                        d = QCC_GetTemp(t->aux_type);
                        if (t->aux_type->size == 3)
-                               QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL));
+                               QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, (void*)0xffffffff));
                        else
-                               QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
+                               QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
                }
                if (def_ret.type->size == 3)
-                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, (void*)0xffffffff));
                else
-                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, (void*)0xffffffff));
                QCC_FreeTemp(oldret);
                QCC_UnFreeTemp(&def_ret);
                QCC_UnFreeTemp(d);
@@ -3068,9 +3165,36 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)    //warning, the func could
 
        if (!t->num_parms&&t->type != ev_variant)       //intrinsics. These base functions have variable arguments. I would check for (...) args too, but that might be used for extended builtin functionality. (this code wouldn't compile otherwise)
        {
+               if (!strcmp(func->name, "sizeof"))
+               {
+                       QCC_type_t *t;
+                       if (!func->initialized)
+                               func->initialized = 3;
+                       func->references++;
+                       t = QCC_PR_ParseType(false, false);
+                       QCC_PR_Expect(")");
+                       return QCC_MakeIntConst(t->size * 4);
+               }
+               if (!strcmp(func->name, "_"))
+               {
+                       if (!func->initialized)
+                               func->initialized = 3;
+                       func->references++;
+                       if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
+                       {
+                               d = QCC_MakeTranslateStringConst(pr_immediate_string);
+                               QCC_PR_Lex();
+                       }
+                       else
+                               QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "_() intrinsic accepts only a string immediate", 1);
+                       QCC_PR_Expect(")");
+                       return d;
+               }
                if (!strcmp(func->name, "random"))
                {
                        old = NULL;
+                       if (!func->initialized)
+                               func->initialized = 3;
                        func->references++;
                        if (!QCC_PR_CheckToken(")"))
                        {
@@ -3094,12 +3218,24 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                                d = NULL;
                        }
 
+                       out = &def_ret;
                        if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0]))
                        {
-                               if(def_ret.temp->used)
+                               if(qcc_targetformat != QCF_HEXEN2)
                                        out = QCC_GetTemp(type_float);
+                               else if (out->temp->used)
+                               {
+                                       old = QCC_GetTemp(out->type);
+                                       if (def_ret.type->size == 3)
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
+                                       else
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
+                                       QCC_UnFreeTemp(old);
+                                       QCC_UnFreeTemp(out);
+                                       QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
+                               }
                                else
-                                       out = &def_ret;
+                                       old = NULL;
 
                                if (e)
                                {
@@ -3113,15 +3249,15 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                        }
                        else
                        {
-                               if (def_ret.temp->used)
+                               if (out->temp->used)
                                {
-                                       old = QCC_GetTemp(def_ret.type);
+                                       old = QCC_GetTemp(out->type);
                                        if (def_ret.type->size == 3)
-                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL));
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
                                        else
-                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL));
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
                                        QCC_UnFreeTemp(old);
-                                       QCC_UnFreeTemp(&def_ret);
+                                       QCC_UnFreeTemp(out);
                                        QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
                                }
                                else
@@ -3191,16 +3327,21 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                                return d;
                        }
 
-                       if (def_ret.temp->used)
-                               QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
-                       def_ret.temp->used = true;
-                       def_ret.type = type_float;
-                       return &def_ret;
+                       if (out == &def_ret)
+                       {
+                               if (out->temp->used)
+                                       QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
+                               out->temp->used = true;
+                               out->type = type_float;
+                       }
+                       return out;
 
                }
                if (!strcmp(func->name, "randomv"))
                {
                        out = NULL;
+                       if (!func->initialized)
+                               func->initialized = 3;
                        func->references++;
                        if (!QCC_PR_CheckToken(")"))
                        {
@@ -3428,7 +3569,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)     //warning, the func could
                        {
                                char genfunc[2048];
                                sprintf(genfunc, "Class*%s", rettype->name);
-                               func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 1, false);
+                               func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, false);
                                func->references++;
                        }
                        QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
@@ -3455,39 +3596,32 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                {
                        //t = (a/%1) / (nextent(world)/%1)
                        //a/%1 does a (int)entity to float conversion type thing
-                       func->initialized = 1;
+                       if (!func->initialized)
+                               func->initialized = 3;
+                       func->references++;
 
                        e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
                        QCC_PR_Expect(")");
-                       e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
+                       e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
 
                        d = QCC_PR_GetDef(NULL, "nextent", NULL, false, 0, false);
                        if (!d)
                                QCC_PR_ParseError(0, "the nextent builtin is not defined");
                        QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff));
                        d = QCC_PR_Statement(&pr_opcodes[OP_CALL0], d, NULL, NULL);
-                       d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
+                       d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
 
                        e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, d, (QCC_dstatement_t **)0xffffffff);
 
                        return e;
                }
-               else if (!strcmp(func->name, "_") && !QCC_PR_CheckToken(")"))
-               {
-                       // return string as is, but set the dotranslate flag
-                       ++dotranslate;
-                       e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
-                       --dotranslate;
-                       QCC_PR_Expect(")");
-                       return e;
-               }
        }       //so it's not an intrinsic.
 
        if (opt_precache_file)  //should we strip out all precache_file calls?
        {
                if (!strncmp(func->name,"precache_file", 13))
                {
-                       if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
+                       if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string && pr_scope && !strcmp(pr_scope->name, "main"))
                        {
                                optres_precache_file += strlen(pr_immediate_string);
                                QCC_PR_Lex();
@@ -3524,7 +3658,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)     //warning, the func could
                                QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS);
                        else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
                                QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS);
-                       if (!extraparms && arg >= t->num_parms)
+                       if (!extraparms && arg >= t->num_parms && !p)
                        {
                                QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
                                QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
@@ -3539,12 +3673,13 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                                e = &def_parms[arg];
 
                                e->ofs = OFS_PARM0+0;
-                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
+                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
                                e->ofs = OFS_PARM0+1;
-                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
+                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
                                e->ofs = OFS_PARM0+2;
-                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
+                               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
                                e->ofs = OFS_PARM0;
+                               e->type = type_vector;
 
                                QCC_PR_Lex();
                        }
@@ -3583,7 +3718,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)     //warning, the func could
 
                        if (pr_classtype && e->type->type == ev_field && p->type != ev_field)
                        {       //convert.
-                               oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
+                               oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
                                switch(e->type->aux_type->type)
                                {
                                case ev_string:
@@ -3620,11 +3755,11 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)   //warning, the func could
                                                e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
                                        else if (p->type == ev_float && e->type->type == ev_integer)    //convert float -> int... is this a constant?
                                                e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
-                                       else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
+                                       else if ((p->type == ev_function && p->type == ev_string) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
                                        {       //you're allowed to use int 0 to pass a null function pointer
                                                //this is basically because __NULL__ is defined as ~0 (int 0)
                                        }
-                                       else if (p->type != ev_variant) //can cast to variant whatever happens
+                                       else if (p->type != ev_variant && e->type->type != ev_variant)  //can cast to variant whatever happens
                                        {
                                                if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
                                                {
@@ -3674,7 +3809,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func)     //warning, the func could
 int constchecks;
 int varchecks;
 int typechecks;
-QCC_def_t *QCC_MakeIntDef(int value)
+QCC_def_t *QCC_MakeIntConst(int value)
 {
        QCC_def_t       *cn;
 
@@ -3708,18 +3843,23 @@ QCC_def_t *QCC_MakeIntDef(int value)
        cn->constant = true;
        cn->initialized = 1;
        cn->scope = NULL;               // always share immediates
-       cn->arraysize = 1;
+       cn->arraysize = 0;
 
-// copy the immediate to the global area
-       cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
+       if (!value)
+               G_INT(cn->ofs) = 0;
+       else
+       {
+       // copy the immediate to the global area
+               cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
 
-       G_INT(cn->ofs) = value;
+               G_INT(cn->ofs) = value;
+       }
 
 
        return cn;
 }
 
-QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
+QCC_def_t *QCC_MakeVectorConst(float a, float b, float c)
 {
        QCC_def_t       *cn;
 
@@ -3755,7 +3895,7 @@ QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
        cn->constant = true;
        cn->initialized = 1;
        cn->scope = NULL;               // always share immediates
-       cn->arraysize = 1;
+       cn->arraysize = 0;
 
 // copy the immediate to the global area
        cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]);
@@ -3767,8 +3907,8 @@ QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
        return cn;
 }
 
-hashtable_t floatconstdefstable;
-QCC_def_t *QCC_MakeFloatDef(float value)
+extern hashtable_t floatconstdefstable;
+QCC_def_t *QCC_MakeFloatConst(float value)
 {
        QCC_def_t       *cn;
 
@@ -3796,7 +3936,7 @@ QCC_def_t *QCC_MakeFloatDef(float value)
        cn->constant = true;
        cn->initialized = 1;
        cn->scope = NULL;               // always share immediates
-       cn->arraysize = 1;
+       cn->arraysize = 0;
 
 // copy the immediate to the global area
        cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
@@ -3809,56 +3949,66 @@ QCC_def_t *QCC_MakeFloatDef(float value)
        return cn;
 }
 
-extern hashtable_t stringconstdefstable;
-extern hashtable_t stringconstdefstable_dotranslate;
-QCC_def_t *QCC_MakeStringDef(char *value)
+extern hashtable_t stringconstdefstable, stringconstdefstable_trans;
+int dotranslate_count;
+static QCC_def_t *QCC_MakeStringConstInternal(char *value, pbool translate)
 {
        QCC_def_t       *cn;
        int string;
-       hashtable_t *tbl = dotranslate ? &stringconstdefstable_dotranslate : &stringconstdefstable;
-       char buf[64];
 
-       cn = pHash_Get(tbl, value);
+       cn = pHash_Get(translate?&stringconstdefstable_trans:&stringconstdefstable, value);
        if (cn)
                return cn;
 
 // allocate a new one
-       cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+       if(translate)
+       {
+               char buf[64];
+               sprintf(buf, "dotranslate_%i", ++dotranslate_count);
+               cn = (void *)qccHunkAlloc (sizeof(QCC_def_t) + strlen(buf)+1);
+               cn->name = (char*)(cn+1);
+               strcpy(cn->name, buf);
+       }
+       else
+       {
+               cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+               cn->name = "IMMEDIATE";
+       }
        cn->next = NULL;
        pr.def_tail->next = cn;
        pr.def_tail = cn;
 
        cn->type = type_string;
-       if(dotranslate > 0)
-       {
-               sprintf(buf, "dotranslate_%d", ++dotranslate_count);
-               cn->name = strdup(buf);
-       }
-       else
-               cn->name = "IMMEDIATE";
        cn->constant = true;
        cn->initialized = 1;
        cn->scope = NULL;               // always share immediates
-       cn->arraysize = 1;
+       cn->arraysize = 0;
 
 // copy the immediate to the global area
        cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
 
        string = QCC_CopyString (value);
 
-       pHash_Add(tbl, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
+       pHash_Add(translate?&stringconstdefstable_trans:&stringconstdefstable, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
 
        G_INT(cn->ofs) = string;
 
-
        return cn;
 }
 
-QCC_type_t *QCC_PR_NewType (char *name, int basictype);
+QCC_def_t *QCC_MakeStringConst(char *value)
+{
+       return QCC_MakeStringConstInternal(value, false);
+}
+QCC_def_t *QCC_MakeTranslateStringConst(char *value)
+{
+       return QCC_MakeStringConstInternal(value, true);
+}
+
 QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type)
 {
        QCC_type_t *newtype;
-       newtype = QCC_PR_NewType("POINTER TYPE", ev_pointer);
+       newtype = QCC_PR_NewType("ptr", ev_pointer, false);
        newtype->aux_type = type;
        return newtype;
 }
@@ -3938,7 +4088,7 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas)
                f = QCC_MemberInParentClass(mt->name, clas->parentclass);
                if (f)
                {
-                       if (m->arraysize>1)
+                       if (m->arraysize)
                                QCC_Error(ERR_INTERNAL, "FTEQCC does not support overloaded arrays of members");
                        a=0;
                        for (o = 0; o < m->type->size; o++)
@@ -3946,16 +4096,20 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas)
                        continue;
                }
 
-               for (a = 0; a < m->arraysize; a++)
+               for (a = 0; a < (m->arraysize?m->arraysize:1); a++)
                {
+                       /*if it was already set, don't go recursive and generate 500 fields for a one-member class that was intheritted from 500 times*/
+                       if (((int *)qcc_pr_globals)[o+a*mt->size+m->ofs])
+                               continue;
+
                        //we need the type in here so saved games can still work without saving ints as floats. (would be evil)
-                       ft = QCC_PR_NewType(basictypenames[mt->type], ev_field);
-                       ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type);
+                       ft = QCC_PR_NewType(basictypenames[mt->type], ev_field, false);
+                       ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type, false);
                        ft->aux_type->aux_type = type_void;
                        ft->size = ft->aux_type->size;
                        ft = QCC_PR_FindType(ft);
                        sprintf(membername, "__f_%s_%i", ft->name, ++basictypefield[mt->type]);
-                       f = QCC_PR_GetDef(ft, membername, NULL, true, 1, true);
+                       f = QCC_PR_GetDef(ft, membername, NULL, true, 0, true);
 
                        for (o = 0; o < m->type->size; o++)
                                ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
@@ -3994,7 +4148,7 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_
                if (type->type == ev_function)  //FIXME: inheritance will not install all the member functions.
                {
                        sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, type->name);
-                       member = QCC_PR_GetDef(NULL, membername, NULL, false, 1, false);
+                       member = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
                        if (!member)
                        {
                                QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername);
@@ -4006,7 +4160,7 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_
                        }
                        point = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], ed, member, NULL);
                        sprintf(membername, "%s::%s", clas->name, type->name);
-                       virt = QCC_PR_GetDef(type, membername, NULL, false, 1, false);
+                       virt = QCC_PR_GetDef(type, membername, NULL, false, 0, false);
                        QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL);
                }
        }
@@ -4029,6 +4183,8 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
        if (!basetype)
                QCC_PR_ParseError(ERR_INTERNAL, "Type %s was not defined...", tname);
 
+       if (numfunctions >= MAX_FUNCTIONS)
+               QCC_Error(ERR_INTERNAL, "Too many function defs");
 
        pr_scope = NULL;
        memset(basictypefield, 0, sizeof(basictypefield));
@@ -4052,7 +4208,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
        G_FUNCTION(scope->ofs) = df - functions;
 
        //locals here...
-       ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 1, false);
+       ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 0, false);
 
        virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false);
        if (!virt)
@@ -4069,7 +4225,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
        if (constructor)
        {       //self = ent;
                self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
-               oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 1, false);
+               oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 0, false);
                QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL));
                QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL));      //return to our old self. boom boom.
                QCC_PR_SimpleStatement(OP_CALL0, constructor->ofs, 0, 0, false);
@@ -4088,684 +4244,480 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
        locals_end = numpr_globals + basetype->size;
        df->locals = locals_end - df->parm_start;
 }
-/*
-============
-PR_ParseValue
 
-Returns the global ofs for the current token
-============
-*/
-QCC_def_t      *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
+QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign)
 {
-       QCC_def_t       *ao=NULL;       //arrayoffset
-       QCC_def_t               *d, *nd, *od;
-       char            *name;
+       QCC_type_t *t;
+       QCC_def_t *idx;
+       QCC_def_t *tmp;
        QCC_dstatement_t *st;
-       int i;
-       static QCC_def_t intrinsic = {
-               NULL,   // QCC_type_t           *type;
-               NULL,   // char         *name;
-               NULL,   // struct QCC_def_s     *next;
-               NULL,   // struct QCC_def_s     *nextlocal;     //provides a chain of local variables for the opt_locals_marshalling optimisation.
-               0,      // gofs_t               ofs;
-               NULL,   // struct QCC_def_s     *scope;         // function the var was defined in, or NULL
-               1,      // int                  initialized;    // 1 when a declaration included "= immediate"
-               1,      // int                  constant;               // 1 says we can use the value over and over again
-               1,      // int references;
-               0,      // int timescalled;     //part of the opt_stripfunctions optimisation.
-               0,      // int s_file;
-               0,      // int s_line;
-               0,      // int arraysize;
-               0,      // pbool shared;
-               0,      // pbool saved;
-               0,      // pbool isstatic;
-               NULL    // temp_t *temp;
-       };
+       pbool allowarray;
 
-       char membername[2048];
+       t = d->type;
+       idx = NULL;
+       while(1)
+       {
+               allowarray = false;
+               if (idx)
+                       allowarray = t->arraysize>0;
+               else if (!idx)
+               {
+                       allowarray = d->arraysize ||
+                                               (d->type->type == ev_pointer) ||
+                                               (d->type->type == ev_string) ||
+                                               (d->type->type == ev_vector);
+               }
 
-// if the token is an immediate, allocate a constant for it
-       if (pr_token_type == tt_immediate)
-               return QCC_PR_ParseImmediate ();
+               if (allowarray && QCC_PR_CheckToken("["))
+               {
+                       tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
+                       QCC_PR_Expect("]");
 
-       if (QCC_PR_CheckToken("["))     //reacc support
-       {       //looks like a funky vector. :)
-               vec3_t v;
-               pr_immediate_type = type_vector;
-               v[0] = pr_immediate._float;
-               QCC_PR_Lex();
-               v[1] = pr_immediate._float;
-               QCC_PR_Lex();
-               v[2] = pr_immediate._float;
-               pr_immediate.vector[0] = v[0];
-               pr_immediate.vector[1] = v[1];
-               pr_immediate.vector[2] = v[2];
-               pr_immediate_type = type_vector;
-               d = QCC_PR_ParseImmediate();
-               QCC_PR_Expect("]");
-               return d;
-       }
-       name = QCC_PR_ParseName ();
-
-       if (assumeclass && assumeclass->parentclass)    // 'testvar' becomes 'self::testvar'
-       {       //try getting a member.
-               QCC_type_t *type;
-               type = assumeclass;
-               d = NULL;
-               while(type != type_entity && type)
-               {
-                       sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
-                       od = d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
-                       if (d)
-                               break;
-
-                       type = type->parentclass;
-               }
-               if (!d)
-                       od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
-       }
-       else
-
-// look through the defs
-       od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
+                       /*if its a pointer that got dereferenced, follow the type*/
+                       if (!idx && t->type == ev_pointer && !d->arraysize)
+                               t = t->aux_type;
 
-       if (!d)
-       {
-               if (    (!strcmp(name, "random" ))      ||
-                               (!strcmp(name, "randomv"))      ||
-                               (!strcmp(name, "entnum"))       ||
-                               (!strcmp(name, "_"))    )       //intrinsics, any old function with no args will do.
-               {
-                       intrinsic.name = name;
-                       intrinsic.type = type_function; // can't put that in the static var
-                       od = d = &intrinsic;
-               }
-               else if (keyword_class && !strcmp(name, "this"))
-               {
-                       if (!pr_classtype)
-                               QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
-                       od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
-                       od = d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false);
-               }
-               else if (keyword_class && !strcmp(name, "super"))
-               {
-                       if (!pr_classtype)
-                               QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
-                       od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
-                       od = d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false);
-               }
-               else
-               {
-                       od = d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false);
-                       if (!d)
-                               QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
-                       else
+                       if (!idx && d->type->type == ev_pointer)
                        {
-                               QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
+                               /*no bounds checks on pointer dereferences*/
                        }
-               }
-       }
-
-reloop:
-
-
-//FIXME: Make this work with double arrays/2nd level structures.
-//Should they just jump back to here?
-       if (QCC_PR_CheckToken("["))
-       {
-               QCC_type_t *newtype;
-               if (ao)
-               {
-                       numstatements--;        //remove the last statement
-
-                       nd = QCC_PR_Expression (TOP_PRIORITY, 0);
-                       QCC_PR_Expect("]");
-
-                       if (d->type->size != 1) //we need to multiply it to find the offset.
+                       else if (!idx && d->type->type == ev_string && !d->arraysize)
                        {
-                               if (ao->type->type == ev_integer)
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], nd, QCC_MakeIntDef(d->type->size), NULL);  //get add part
-                               else if (ao->type->type == ev_float)
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], nd, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
-                               else
+                               /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/
+                       }
+                       else if (!idx && d->type->type == ev_vector && !d->arraysize)
+                       {
+                               if (tmp->constant)
                                {
-                                       QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
-                                       nd = NULL;
+                                       unsigned int i;
+                                       if (tmp->type->type == ev_integer)
+                                               i = G_INT(tmp->ofs);
+                                       else if (tmp->type->type == ev_float)
+                                               i = G_FLOAT(tmp->ofs);
+                                       if (i < 0 || i >= 3)
+                                               QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds");
                                }
+                               else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
+                               {
+                                       tmp = QCC_SupplyConversion(tmp, ev_integer, true);
+                                       QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false);
+                               }
+                               t = type_float;
                        }
-
-                       if (nd->type->type == ao->type->type)
+                       else if (!((!idx)?d->arraysize:t->arraysize))
                        {
-                               if (ao->type->type == ev_integer)
-                                       ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL);     //get add part
-                               else if (ao->type->type == ev_float)
-                                       ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], ao, nd, NULL);     //get add part
-                               else
+                               QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array");
+                       }
+                       else if (tmp->constant)
+                       {
+                               unsigned int i;
+                               if (tmp->type->type == ev_integer)
+                                       i = G_INT(tmp->ofs);
+                               else if (tmp->type->type == ev_float)
+                                       i = G_FLOAT(tmp->ofs);
+                               if (i < 0 || i >= ((!idx)?d->arraysize:t->arraysize))
+                                       QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds");
+                       }
+                       else
+                       {
+                               if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
                                {
-                                       QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
-                                       nd = NULL;
+                                       tmp = QCC_SupplyConversion(tmp, ev_integer, true);
+                                       QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false);
                                }
                        }
-                       else
+                       if (t->size != 1 && (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))) /*don't multiply by type size if the instruction/emulation will do that instead*/
                        {
-                               if (nd->type->type == ev_float)
-                                       nd = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], nd, 0, NULL);
-                               ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL);     //get add part
+                               if (tmp->type->type == ev_float)
+                                       tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL);
+                               else
+                                       tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL);
                        }
 
-                       newtype = d->type;
-                       d = od;
+                       /*calc the new index*/
+                       if (idx)
+                               idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL);
+                       else
+                               idx = tmp;
                }
-               else
+               else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
                {
-                       ao = QCC_PR_Expression (TOP_PRIORITY, 0);
-                       QCC_PR_Expect("]");
+                       if (!idx && t->type == ev_pointer && !d->arraysize)
+                               t = t->aux_type;
 
-                       if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1)     //we need to multiply it to find the offset.
+                       for (t = t->param; t; t = t->next)
                        {
-                               if (ao->type->type == ev_integer)
-                                       ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(d->type->size), NULL);  //get add part
-                               else if (ao->type->type == ev_float)
-                                       ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], ao, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
-                               else
+                               if (QCC_PR_CheckName(t->name))
                                {
-                                       nd = NULL;
-                                       QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
+                                       break;
                                }
+                       
                        }
+                       if (!t)
+                               QCC_PR_ParseError(0, "%s is not a member", pr_token);
 
-                       newtype = d->type;
+                       tmp = QCC_MakeIntConst(t->ofs);
+                       if (idx)
+                               idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL);
+                       else
+                               idx = tmp;
                }
-               if (ao->type->type == ev_integer)
+               else
+                       break;
+       }
+
+       if (idx)
+       {
+               if (d->type->type == ev_pointer)
                {
-                       switch(newtype->type)
+                       switch (t->type)
                        {
+                       case ev_pointer:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
                        case ev_float:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL);    //get pointer to precise def.
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_integer:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_string:
-                               if (d->arraysize <= 1)
-                               {
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                       newtype = nd->type;//don't be fooled
-                               }
-                               else
-                               {
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL);    //get pointer to precise def.
-                               }
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_vector:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL);    //get pointer to precise def.
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_entity:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL);  //get pointer to precise def.
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_field:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL);  //get pointer to precise def.
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_function:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL);  //get pointer to precise def.
-                               nd->type = d->type;
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_struct:
+                       case ev_union:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
+
+                       default:
+                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
+                       }
+                       d->type = t;
+               }
+               else if (d->type->type == ev_string && d->arraysize == 0)
+               {
+                       d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL);
+               }
+               else if (d->type->type == ev_vector && d->arraysize == 0)
+               {
+                       d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                       d->type = type_float;
+               }
+               else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
+               {
+                       /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/
+                       /*source type is a struct, or its an array, or something that can otherwise be directly accessed*/
+                       switch(t->type)
+                       {
                        case ev_pointer:
-                               if (ao->constant && !G_INT(ao->ofs))
-                                       ao->ofs = 0;
-                               if (d->arraysize>1)     //use the array
-                               {
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL);    //get pointer to precise def.
-                                       nd->type = d->type->aux_type;
-                               }
-                               else
-                               {       //dereference the pointer.
-                                       switch(newtype->aux_type->type)
-                                       {
-                                       case ev_pointer:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL);    //get pointer to precise def.
-                                               nd->type = d->type->aux_type;
-                                               break;
-                                       case ev_float:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL);    //get pointer to precise def.
-                                               nd->type = d->type->aux_type;
-                                               break;
-                                       case ev_vector:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL);    //get pointer to precise def.
-                                               nd->type = d->type->aux_type;
-                                               break;
-                                       case ev_integer:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL);    //get pointer to precise def.
-                                               nd->type = d->type->aux_type;
-                                               break;
-                                       default:
-                                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                               nd = NULL;
-                                               break;
-                                       }
-                               }
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_float:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_integer:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL);    //get pointer to precise def.
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_string:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_vector:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_entity:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_field:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
+                               break;
+                       case ev_function:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        case ev_struct:
-                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL);    //get pointer to precise def.
-                               nd->type = d->type;
+                       case ev_union:
+                               //FIXME...
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_STRUCT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
                                break;
                        default:
                                QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                               nd = NULL;
-                               break;
                        }
-                       d=nd;
+                       d->type = t;
                }
-               else if (ao->type->type == ev_float)
+               else if (idx->constant)
                {
-                       if (qcc_targetformat == QCF_HEXEN2)
-                       {       //hexen2 style retrieval, mixed with q1 style assignments...
-                               if (QCC_PR_CheckToken("="))     //(hideous concept)
-                               {
-                                       QCC_def_t *funcretr;
-                                       QCC_def_t *args[2];
-                                       if (d->scope)
-                                               QCC_PR_ParseError(0, "Scoped array without specific engine support");
-
-                                       funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
-                                       nd = QCC_PR_Expression(TOP_PRIORITY, 0);
-                                       if (nd->type->type != d->type->type)
-                                               QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
-
-                                       args[0] = ao;
-                                       args[1] = nd;
-                                       return QCC_PR_GenerateFunctionCall(funcretr, args, 2);
-                               }
-
-                               switch(newtype->type)
-                               {
-                               case ev_float:
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, ao, &st); //get pointer to precise def.
-                                       st->a = d->ofs;
-                                       break;
-                               case ev_vector:
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, ao, &st); //get pointer to precise def.
-                                       st->a = d->ofs;
-                                       break;
-                               case ev_string:
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, ao, &st); //get pointer to precise def.
-                                       st->a = d->ofs;
-                                       break;
-                               case ev_entity:
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, ao, &st); //get pointer to precise def.
-                                       st->a = d->ofs;
-                                       break;
-                               case ev_function:
-                                       nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, ao, &st);       //get pointer to precise def.
-                                       st->a = d->ofs;
-                                       break;
-                               default:
-                                       QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                       nd = NULL;
-                                       break;
-                               }
-                               QCC_FreeTemp(d);
-                               QCC_FreeTemp(ao);
+                       int cidx;
+                       idx = QCC_SupplyConversion(idx, ev_integer, true);
+                       cidx = G_INT(idx->ofs);
 
-                               d=nd;
-                               d->type = newtype;
-                               return d;
-                       }
-                       else
-                       {
-                               if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))  //q1 compatible.
-                               {       //you didn't see this, okay?
-                                       QCC_def_t *funcretr;
-                                       if (d->scope)
-                                               QCC_PR_ParseError(0, "Scoped array without specific engine support");
+                       d->references++;
+                       tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                       memcpy (tmp, d, sizeof(QCC_def_t));
+                       tmp->arraysize = 0;
+                       tmp->ofs = d->ofs + (cidx * type_size[d->type->type]);
+                       d = tmp;
 
-                                       if (allowarrayassign && QCC_PR_CheckToken("="))
-                                       {
-                                               QCC_def_t *args[2];
+                       //d can be assigned to freely
+               }
+               else if (allowarrayassign && QCC_PR_CheckToken("="))
+               {
+                       /*if its assigned to, generate a functioncall to do the store*/
+                       QCC_def_t *args[2], *funcretr, *rhs;
 
-                                               funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
+                       d->references++;
+                       funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 0, false);
 
-                                               nd = QCC_PR_Expression(TOP_PRIORITY, 0);
-                                               if (nd->type->type != d->type->type)
-                                                       QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
+                       rhs = QCC_PR_Expression(TOP_PRIORITY, 0);
+                       if (rhs->type->type != d->type->type)
+                               QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
 
-                                               args[0] = ao;
-                                               args[1] = nd;
-                                               qcc_usefulstatement=true;
-                                               nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
-                                               nd->type = d->type->aux_type;
-                                       }
-                                       else
-                                       {
-                                               QCC_def_t *args[1];
-
-                                               def_parms[0].type = type_float;
-                                               funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false);
+                       args[0] = QCC_SupplyConversion(idx, ev_float, true);
+                       args[1] = rhs;
+                       qcc_usefulstatement=true;
+                       d = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
+                       d->type = t;
 
-                                               args[0] = ao;
-                                               nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
-                                               nd->type = d->type->aux_type;
-                                       }
-                               }
-                               else
-                               {
-                                       switch(newtype->type)
-                                       {
-                                       case ev_pointer:
-                                               if (d->arraysize>1)     //use the array
-                                               {
-                                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                                       nd->type = d->type->aux_type;
-                                               }
-                                               else
-                                               {       //dereference the pointer.
-                                                       switch(newtype->aux_type->type)
-                                                       {
-                                                       case ev_pointer:
-                                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                                               nd->type = d->type->aux_type;
-                                                               break;
-                                                       case ev_float:
-                                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                                               nd->type = d->type->aux_type;
-                                                               break;
-                                                       case ev_vector:
-                                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                                               nd->type = d->type->aux_type;
-                                                               break;
-                                                       case ev_integer:
-                                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                                               nd->type = d->type->aux_type;
-                                                               break;
-                                                       default:
-                                                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                                               nd = NULL;
-                                                               break;
-                                                       }
-                                               }
-                                               break;
+                       return d;
+               }
+               else if (QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F]))
+               {
+                       if (!d->arraysize)
+                               QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on non-array");
 
-                                       case ev_float:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                               break;
-                                       case ev_string:
-                                               if (d->arraysize <= 1)
-                                               {
-                                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, ao, NULL);    //get pointer to precise def.
-                                                       newtype = nd->type;//don't be fooled
-                                               }
-                                               else
-                                                       nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                               break;
-                                       case ev_vector:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                               break;
-                                       case ev_entity:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);   //get pointer to precise def.
-                                               break;
-                                       case ev_field:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);   //get pointer to precise def.
-                                               break;
-                                       case ev_function:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);   //get pointer to precise def.
-                                               nd->type = d->type;
-                                               break;
-                                       case ev_integer:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                               break;
+                       if (d->temp)
+                               QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on a temp");
 
-                                       case ev_struct:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL);     //get pointer to precise def.
-                                               nd->type = d->type;
-                                               break;
-                                       default:
-                                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                               nd = NULL;
-                                               break;
-                                       }
-                               }
+                       /*hexen2 format has opcodes to read arrays (but has no way to write)*/
+                       switch(t->type)
+                       {
+                       case ev_float:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(idx, ev_float, true), &st);   //get pointer to precise def.
+//                             st->a = d->ofs;
+                               break;
+                       case ev_vector:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(idx, ev_float, true), &st);   //get pointer to precise def.
+//                             st->a = d->ofs;
+                               break;
+                       case ev_string:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(idx, ev_float, true), &st);   //get pointer to precise def.
+//                             st->a = d->ofs;
+                               break;
+                       case ev_entity:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(idx, ev_float, true), &st);   //get pointer to precise def.
+//                             st->a = d->ofs;
+                               break;
+                       case ev_function:
+                               d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
+//                             st->a = d->ofs;
+                               break;
+                       default:
+                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
+                               d = NULL;
+                               break;
                        }
-                       d=nd;
+                       d->type = t;
                }
                else
-                       QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
-
-               d->type = newtype;
-               goto reloop;
-       }
+               {
+                       /*emulate the array access using a function call to do the read for us*/
+                       QCC_def_t *args[1], *funcretr;
 
+                       d->references++;
 
-       i = d->type->type;
-       if (i == ev_pointer)
-       {
-               int j;
-               QCC_type_t *type;
-               if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
-               {
-                       for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
-                       {
-                               if (QCC_PR_CheckName(type->name))
-                               {
-                                       //give result
-                                       if (ao)
-                                       {
-                                               numstatements--;        //remove the last statement
-                                               d = od;
+                       /*make sure the function type that we're calling exists*/
+                       def_parms[0].type = type_float;
+                       funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false);
 
-                                               nd = QCC_MakeIntDef(type->ofs);
-                                               ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL);     //get add part
+                       args[0] = QCC_SupplyConversion(idx, ev_float, true);
+                       d = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
+                       d->type = t;
+               }
 
-                                               //so that we may offset it and readd it.
-                                       }
-                                       else
-                                               ao = QCC_MakeIntDef(type->ofs);
-                                       switch (type->type)
-                                       {
-                                       case ev_float:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_string:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_vector:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_entity:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, ao, NULL);  //get pointer to precise def.
-                                               break;
-                                       case ev_field:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, ao, NULL);  //get pointer to precise def.
-                                               break;
-                                       case ev_function:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, ao, NULL);  //get pointer to precise def.
-                                               nd->type = type;
-                                               break;
-                                       case ev_integer:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL);    //get pointer to precise def.
-                                               break;
+               /*parse recursively*/
+               d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
+       }
 
-//                                     case ev_struct:
-                                               //no suitable op.
-//                                             nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL);    //get pointer to precise def.
-//                                             nd->type = type;
-//                                             break;
-                                       default:
-                                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                               nd = NULL;
-                                               break;
-                                       }
+       return d;
+}
 
-                                       d=nd;
-                                       break;
-                               }
-                               if (type->num_parms)
-                               {
-                                       for (j = type->num_parms; j;j--)
-                                               type++;
-                               }
-                       }
-                       if (!i)
-                               QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
+/*
+============
+PR_ParseValue
 
-                       goto reloop;
-               }
-       }
-       else if (i == ev_struct || i == ev_union)
-       {
-               int j;
-               QCC_type_t *type;
-               if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
-               {
-                       for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
-                       {
-                               if (QCC_PR_CheckName(type->name))
-                               {
-                                       //give result
-                                       if (ao)
-                                       {
-                                               numstatements--;        //remove the last statement
-                                               d = od;
+Returns the global ofs for the current token
+============
+*/
+QCC_def_t      *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
+{
+       QCC_def_t               *d, *od, *tmp;
+       QCC_type_t              *t;
+       char            *name;
 
-                                               nd = QCC_MakeIntDef(type->ofs);
-                                               ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL);     //get add part
+       char membername[2048];
 
-                                               //so that we may offset it and readd it.
-                                       }
-                                       else
-                                               ao = QCC_MakeIntDef(type->ofs);
-                                       switch (type->type)
-                                       {
-                                       case ev_float:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_string:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_vector:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL);    //get pointer to precise def.
-                                               break;
-                                       case ev_entity:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL);  //get pointer to precise def.
-                                               break;
-                                       case ev_field:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL);  //get pointer to precise def.
-                                               break;
-                                       case ev_function:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL);  //get pointer to precise def.
-                                               nd->type = type;
-                                               break;
-                                       case ev_integer:
-                                               nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL);    //get pointer to precise def.
-                                               break;
+// if the token is an immediate, allocate a constant for it
+       if (pr_token_type == tt_immediate)
+               return QCC_PR_ParseImmediate ();
 
-//                                     case ev_struct:
-                                               //no suitable op.
-//                                             nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL);    //get pointer to precise def.
-//                                             nd->type = type;
-//                                             break;
-                                       default:
-                                               QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
-                                               nd = NULL;
-                                               break;
-                                       }
+       if (QCC_PR_CheckToken("["))     //reacc support
+       {       //looks like a funky vector. :)
+               vec3_t v;
+               pr_immediate_type = type_vector;
+               v[0] = pr_immediate._float;
+               QCC_PR_Lex();
+               v[1] = pr_immediate._float;
+               QCC_PR_Lex();
+               v[2] = pr_immediate._float;
+               pr_immediate.vector[0] = v[0];
+               pr_immediate.vector[1] = v[1];
+               pr_immediate.vector[2] = v[2];
+               pr_immediate_type = type_vector;
+               d = QCC_PR_ParseImmediate();
+               QCC_PR_Expect("]");
+               return d;
+       }
+       name = QCC_PR_ParseName ();
 
-                                       d=nd;
-                                       break;
-                               }
-                               if (type->num_parms)
-                               {
-                                       for (j = type->num_parms; j;j--)
-                                               type++;
-                               }
-                       }
-                       if (!i)
-                               QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
+       if (assumeclass && assumeclass->parentclass)    // 'testvar' becomes 'self::testvar'
+       {       //try getting a member.
+               QCC_type_t *type;
+               type = assumeclass;
+               d = NULL;
+               while(type != type_entity && type)
+               {
+                       sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
+                       d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
+                       if (d)
+                               break;
 
-                       goto reloop;
+                       type = type->parentclass;
                }
+               if (!d)
+                       d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
+       }
+       else
+       {
+               // look through the defs
+               d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
        }
 
-/*     if (d->type->type == ev_pointer)
-       {       //expand now, not in function call/maths parsing
-               switch(d->type->aux_type->type)
+       if (!d)
+       {
+               if (    (!strcmp(name, "random" ))      ||
+                               (!strcmp(name, "randomv"))      ||
+                               (!strcmp(name, "sizeof"))       ||
+                               (!strcmp(name, "entnum"))       ||
+                               (!strcmp(name, "_")))   //intrinsics, any old function with no args will do.
                {
-               case ev_string:
-                       d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, NULL, NULL);
-                       break;
-               case ev_float:
-                       d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, NULL, NULL);
-                       break;
+                       d = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
+                       d->initialized = 0;
+               }
+               else if (keyword_class && !strcmp(name, "this"))
+               {
+                       if (!pr_classtype)
+                               QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
+                       od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
+                       d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 0, od->ofs, true, false);
+               }
+               else if (keyword_class && !strcmp(name, "super"))
+               {
+                       if (!pr_classtype)
+                               QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
+                       od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
+                       d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 0, od->ofs, true, false);
+               }
+               else
+               {
+                       d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 0, false);
+                       if (!d)
+                               QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
+                       else
+                       {
+                               QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
+                       }
                }
        }
-*/
-       if (!keyword_class)
-               return d;
 
-       if (d->type->parentclass||d->type->type == ev_entity)   //class
+       d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
+
+       t = d->type;
+       if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
        {
-               if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
+               QCC_def_t *field;
+               if (QCC_PR_CheckToken("("))
                {
-                       QCC_def_t *field;
-                       if (QCC_PR_CheckToken("("))
+                       field = QCC_PR_Expression(TOP_PRIORITY, 0);
+                       QCC_PR_Expect(")");
+               }
+               else
+                       field = QCC_PR_ParseValue(d->type, false);
+               if (field->type->type == ev_field)
+               {
+                       if (!field->type->aux_type)
                        {
-                               field = QCC_PR_Expression(TOP_PRIORITY, 0);
-                               QCC_PR_Expect(")");
+                               QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
+                               d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
                        }
                        else
-                               field = QCC_PR_ParseValue(d->type, false);
-                       if (field->type->type == ev_field)
-                       {
-                               if (!field->type->aux_type)
-                               {
-                                       QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
-                                       return QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
-                               }
-                               else
-                               {
-                                       switch(field->type->aux_type->type)
-                                       {
-                                       default:
-                                               QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
-                                               return d;
-                                       case ev_integer:
-                                               return QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
-                                       case ev_field:
-                                               d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
-                                               nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                               memset (nd, 0, sizeof(QCC_def_t));
-                                               nd->type = field->type->aux_type;
-                                               nd->ofs = d->ofs;
-                                               nd->temp = d->temp;
-                                               nd->constant = false;
-                                               nd->name = d->name;
-                                               return nd;
-                                       case ev_float:
-                                               return QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
-                                       case ev_string:
-                                               return QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
-                                       case ev_vector:
-                                               return QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
-                                       case ev_function:
-                                               {       //complicated for a typecast
-                                               d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
-                                               nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                               memset (nd, 0, sizeof(QCC_def_t));
-                                               nd->type = field->type->aux_type;
-                                               nd->ofs = d->ofs;
-                                               nd->temp = d->temp;
-                                               nd->constant = false;
-                                               nd->name = d->name;
-                                               return nd;
-
-                                               }
-                                       case ev_entity:
-                                               return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
-                                       }
+                       {
+                               switch(field->type->aux_type->type)
+                               {
+                               default:
+                                       QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
+                                       break;
+                               case ev_integer:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
+                                       break;
+                               case ev_field:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
+                                       tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                       memset (tmp, 0, sizeof(QCC_def_t));
+                                       tmp->type = field->type->aux_type;
+                                       tmp->ofs = d->ofs;
+                                       tmp->temp = d->temp;
+                                       tmp->constant = false;
+                                       tmp->name = d->name;
+                                       d = tmp;
+                                       break;
+                               case ev_float:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
+                                       break;
+                               case ev_string:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
+                                       break;
+                               case ev_vector:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
+                                       break;
+                               case ev_function:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
+                                       tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                       memset (tmp, 0, sizeof(QCC_def_t));
+                                       tmp->type = field->type->aux_type;
+                                       tmp->ofs = d->ofs;
+                                       tmp->temp = d->temp;
+                                       tmp->constant = false;
+                                       tmp->name = d->name;
+                                       d = tmp;
+                                       break;
+                               case ev_entity:
+                                       d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
+                                       break;
                                }
                        }
-                       else
-                               QCC_PR_IncludeChunk(".", false, NULL);
                }
+               else
+                       QCC_PR_IncludeChunk(".", false, NULL);
        }
 
        return d;
@@ -4794,10 +4746,10 @@ QCC_def_t *QCC_PR_Term (void)
                        switch (e->type->type)
                        {
                        case ev_integer:
-                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
+                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
                                break;
                        case ev_float:
-                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
+                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
                                break;
                        default:
                                QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "++ operator on unsupported type");
@@ -4816,10 +4768,10 @@ QCC_def_t *QCC_PR_Term (void)
                        switch (e->type->type)
                        {
                        case ev_integer:
-                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
+                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
                                break;
                        case ev_float:
-                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
+                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
                                break;
                        default:
                                QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "-- operator on unsupported type");
@@ -4857,18 +4809,30 @@ QCC_def_t *QCC_PR_Term (void)
                else if (QCC_PR_CheckToken ("&"))
                {
                        int st = numstatements;
-                       e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+                       e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
                        t = e->type->type;
 
                        if (st != numstatements)
                                //woo, something like ent.field?
                        {
-                               if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
+                               if ((OP_LOAD_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOAD_FNC) || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
                                {
                                        statements[numstatements-1].op = OP_ADDRESS;
                                        e->type = QCC_PR_PointerType(e->type);
                                        return e;
                                }
+                               else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I)
+                               {
+                                       statements[numstatements-1].op = OP_GLOBALADDRESS;
+                                       e->type = QCC_PR_PointerType(e->type);
+                                       return e;
+                               }
+                               else if (OP_LOADP_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADP_I)
+                               {
+                                       statements[numstatements-1].op = OP_POINTER_ADD;
+                                       e->type = QCC_PR_PointerType(e->type);
+                                       return e;
+                               }
                                else    //this is a restriction that could be lifted, I just want to make sure that I got all the bits first.
                                {
                                        QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference");
@@ -4886,62 +4850,65 @@ QCC_def_t *QCC_PR_Term (void)
                }
                else if (QCC_PR_CheckToken ("*"))
                {
-                       e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+                       e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
                        t = e->type->type;
 
-                       if (t != ev_pointer)
-                               QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
-
-                       switch(e->type->aux_type->type)
+                       if (t == ev_string)
+                               e2 = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], e, QCC_MakeFloatConst(0), NULL);
+                       else if (t == ev_pointer)
                        {
-                       case ev_float:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
-                               break;
-                       case ev_string:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
-                               break;
-                       case ev_vector:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
-                               break;
-                       case ev_entity:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
-                               break;
-                       case ev_field:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
-                               break;
-                       case ev_function:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
-                               break;
-                       case ev_integer:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
-                               break;
-                       case ev_pointer:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
-                               break;
+                               switch(e->type->aux_type->type)
+                               {
+                               case ev_float:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
+                                       break;
+                               case ev_string:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
+                                       break;
+                               case ev_vector:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
+                                       break;
+                               case ev_entity:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
+                                       break;
+                               case ev_field:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
+                                       break;
+                               case ev_function:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
+                                       break;
+                               case ev_integer:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
+                                       break;
+                               case ev_pointer:
+                                       e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
+                                       break;
 
-                       default:
-                               QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
-                               e2 = NULL;
-                               break;
+                               default:
+                                       QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
+                                       e2 = NULL;
+                                       break;
+                               }
+                               e2->type = e->type->aux_type;
                        }
-
-                       e2->type = e->type->aux_type;
+                       else
+                               QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
                        return e2;
                }
                else if (QCC_PR_CheckToken ("-"))
                {
-                       e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+                       e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
 
                        switch(e->type->type)
                        {
                        case ev_float:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatDef(0), e, NULL);
+                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), e, NULL);
                                break;
                        case ev_vector:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorDef(0, 0, 0), e, NULL);
+                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorConst(0, 0, 0), e, NULL);
                                break;
                        case ev_integer:
-                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntDef(0), e, NULL);
+                               e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntConst(0), e, NULL);
                                break;
                        default:
                                QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for -");
@@ -4952,7 +4919,7 @@ QCC_def_t *QCC_PR_Term (void)
                }
                else if (QCC_PR_CheckToken ("+"))
                {
-                       e = QCC_PR_Expression (UNARY_PRIORITY, 0);
+                       e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
 
                        switch(e->type->type)
                        {
@@ -4975,7 +4942,72 @@ QCC_def_t *QCC_PR_Term (void)
 
                if (QCC_PR_CheckToken ("("))
                {
-                       if (QCC_PR_CheckKeyword(keyword_float, "float"))        //check for type casts
+                       QCC_type_t *newtype;
+                       newtype = QCC_PR_ParseType(false, true);
+                       if (newtype)
+                       {
+                               QCC_PR_Expect (")");
+                               e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
+
+                               /*you may cast from a type to itself*/
+                               if (!typecmp(e->type, newtype))
+                               {
+                               }
+                               /*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/
+                               else if (newtype->size == e->type->size && (e->type->type == ev_integer || e->type->type == ev_float) && e->constant && !G_INT(e->ofs))
+                               {
+                                       //direct cast
+                                       e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                       memset (e2, 0, sizeof(QCC_def_t));
+
+                                       e2->type = newtype;
+                                       e2->ofs = e->ofs;
+                                       e2->constant = true;
+                                       e2->temp = e->temp;
+                                       return e2;
+                               }
+                               /*cast from int->float will convert*/
+                               else if (newtype->type == ev_float && e->type->type == ev_integer)
+                                       return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL);
+                               /*cast from float->int will convert*/
+                               else if (newtype->type == ev_integer && e->type->type == ev_float)
+                                       return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
+                               /*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
+                               else if (
+                                       //pointers
+                                       ((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer))
+                                       //ents/classs
+                                       || (newtype->type == ev_entity && e->type->type == ev_entity)
+                                       //variants are fine too
+                                       || (newtype->type == ev_variant || e->type->type == ev_variant)
+                                       )
+                               {
+                                       //direct cast
+                                       e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                                       memset (e2, 0, sizeof(QCC_def_t));
+
+                                       e2->type = newtype;
+                                       e2->ofs = e->ofs;
+                                       e2->constant = true;
+                                       e2->temp = e->temp;
+                                       return e2;
+                               }
+                               else
+                                       QCC_PR_ParseError(0, "Bad type cast\n");
+                       }
+/*                     else if (QCC_PR_CheckToken("*"))
+                       {
+                               QCC_PR_Expect (")");
+                               e = QCC_PR_Term();
+                               e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
+                               memset (e2, 0, sizeof(QCC_def_t));
+                               e2->type = type_pointer;
+                               e2->ofs = e->ofs;
+                               e2->constant = true;
+                               e2->temp = e->temp;
+                               return e2;
+                       }
+                       else if (QCC_PR_CheckKeyword(keyword_float, "float"))   //check for type casts
                        {
                                QCC_PR_Expect (")");
                                e = QCC_PR_Term();
@@ -5036,7 +5068,7 @@ QCC_def_t *QCC_PR_Term (void)
                                else
                                        QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
                        }
-                       else
+*/                     else
                        {
                                pbool oldcond = conditional;
                                conditional = conditional?2:0;
@@ -5068,6 +5100,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to)
                }
        }
 
+       if (from->type->type == ev_variant)
+               return 3;
+
 /*     if (from->type->type == ev_pointer && from->type->aux_type->type == to)
                return 1;
 
@@ -5077,6 +5112,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to)
        if (from->type->type == ev_integer && to == ev_function)
                return 1;
 
+       if (from->constant && from->arraysize == 0 && (from->type->type == ev_integer || from->type->type == ev_float) && !G_INT(from->ofs))
+               return 2;
+
        return -100;
 }
 /*
@@ -5105,7 +5143,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
        while (1)
        {
-               if (priority == 1)
+               if (priority == FUNC_PRIORITY)
                {
                        if (QCC_PR_CheckToken ("(") )
                        {
@@ -5141,8 +5179,8 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
                if (pr_token_type == tt_immediate)
                {
-                       if (pr_immediate_type->type == ev_float)
-                               if (pr_immediate._float < 0)    //hehehe... was a minus all along...
+                       if ((pr_immediate_type->type == ev_float && pr_immediate._float < 0) ||
+                               (pr_immediate_type->type == ev_integer && pr_immediate._int < 0))       //hehehe... was a minus all along...
                                {
                                        QCC_PR_IncludeChunk(pr_token, true, NULL);
                                        strcpy(pr_token, "+");//two negatives would make a positive.
@@ -5189,21 +5227,15 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
                                                //this kills the add 0.
                                                e->ofs = statements[numstatements-1].a;
                                                numstatements--;
-
-                                               if (e->type->type != ev_pointer)
-                                               {
-                                                       type_pointer->aux_type->type = e->type->type;
-                                                       e->type = type_pointer;
-                                               }
                                        }
                                        else
                                        {
-                                               statements[numstatements-1].op = OP_ADD_I;
-                                               if (e->type->type != ev_pointer)
-                                               {
-                                                       type_pointer->aux_type->type = e->type->type;
-                                                       e->type = type_pointer;
-                                               }
+                                               statements[numstatements-1].op = OP_POINTER_ADD;
+                                       }
+                                       if (e->type != type_pointer)
+                                       {
+                                               type_pointer->aux_type->type = e->type->type;
+                                               e->type = type_pointer;
                                        }
                                }
                                if ( !simplestore && statements[numstatements-1].op == OP_LOADP_C && e->ofs == statements[numstatements-1].c)
@@ -5271,6 +5303,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
                                                {//assignment
                                                        if (op->type_a == &type_pointer)        //ent var
                                                        {
+                                                               /*FIXME: I don't like this code*/
                                                                if (e->type->type != ev_pointer)
                                                                        c = -200;       //don't cast to a pointer.
                                                                else if ((*op->type_c)->type == ev_void && op->type_b == &type_pointer && e2->type->type == ev_pointer)
@@ -5285,6 +5318,8 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
                                                                c=QCC_canConv(e2, (*op->type_b)->type);
                                                                if (type_a != (*op->type_a)->type)      //in this case, a is the final assigned value
                                                                        c = -300;       //don't use this op, as we must not change var b's type
+                                                               else if ((*op->type_a)->type == ev_pointer && e->type->aux_type->type != (*op->type_a)->aux_type->type)
+                                                                       c = -300;       //don't use this op if its a pointer to a different type
                                                        }
                                                }
                                                else
@@ -5404,12 +5439,12 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
                                        QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
                                        if (e->type->type == ev_float)
                                        {
-                                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e2, false);
+                                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e2, false);
                                                QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
                                        }
                                        else if (e->type->type == ev_integer)
                                        {
-                                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e2, false);
+                                               QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e2, false);
                                                QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
                                        }
                                        else
@@ -5430,7 +5465,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
                                        e2 = QCC_GetTemp(type_float);
                                        QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
-                                       QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
+                                       QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
                                        QCC_FreeTemp(e);
                                        e = e2;
                                }
@@ -5441,7 +5476,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
                                        e2 = QCC_GetTemp(type_integer);
                                        QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
-                                       QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
+                                       QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
                                        QCC_FreeTemp(e);
                                        e = e2;
                                }
@@ -5466,12 +5501,12 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
                                        QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
                                        if (e->type->type == ev_float)
                                        {
-                                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e2, false);
+                                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e2, false);
                                                QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
                                        }
                                        else if (e->type->type == ev_integer)
                                        {
-                                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e2, false);
+                                               QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e2, false);
                                                QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
                                        }
                                        else
@@ -5489,7 +5524,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
                                        e2 = QCC_GetTemp(type_float);
                                        QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
-                                       QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
+                                       QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
                                        QCC_FreeTemp(e);
                                        e = e2;
                                }
@@ -5500,7 +5535,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
                                        e2 = QCC_GetTemp(type_integer);
                                        QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
-                                       QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
+                                       QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
                                        QCC_FreeTemp(e);
                                        e = e2;
                                }
@@ -5519,13 +5554,36 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
 
        if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (","))
        {
+               if (!qcc_usefulstatement)
+                       QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement");
+
                QCC_FreeTemp(e);
-               return QCC_PR_Expression(TOP_PRIORITY, exprflags);
+               qcc_usefulstatement = false;
+               e = QCC_PR_Expression(TOP_PRIORITY, exprflags);
        }
 
        return e;
 }
 
+int QCC_PR_IntConstExpr(void)
+{
+       QCC_def_t *def = QCC_PR_Expression(TOP_PRIORITY, 0);
+       if (def->constant)
+       {
+               def->references++;
+               if (def->type->type == ev_integer)
+                       return G_INT(def->ofs);
+               if (def->type->type == ev_float)
+               {
+                       int i = G_FLOAT(def->ofs);
+                       if ((float)i == G_FLOAT(def->ofs))
+                               return i;
+               }
+       }
+       QCC_PR_ParseError(ERR_NOTACONSTANT, "Value is not an integer constant");
+       return true;
+}
+
 void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname)
 {
        if (num_gotos >= max_gotos)
@@ -5606,7 +5664,7 @@ void QCC_PR_ParseStatement (void)
                {
                        e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
                        e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
-                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
                }*/
 
                if (QCC_PR_CheckToken (";"))
@@ -5620,7 +5678,7 @@ void QCC_PR_ParseStatement (void)
                        return;
                }
                e = QCC_PR_Expression (TOP_PRIORITY, 0);
-               e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type);
+               e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type, true);
                if (e != e2)
                {
                        QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
@@ -5902,7 +5960,7 @@ void QCC_PR_ParseStatement (void)
                float frame = pr_immediate._float;
                QCC_PR_Lex();
                name = QCC_PR_ParseName();
-               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatDef(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
+               QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatConst(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
                QCC_PR_Expect(";");
                return;
        }
@@ -6116,7 +6174,7 @@ void QCC_PR_ParseStatement (void)
                                if (pr_casesdef[i]->type->type != e->type->type)
                                {
                                        if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
-                                               pr_casesdef[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
+                                               pr_casesdef[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
                                        else
                                                QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch case type mismatch");
                                }
@@ -6125,7 +6183,7 @@ void QCC_PR_ParseStatement (void)
                                        if (pr_casesdef2[i]->type->type != e->type->type)
                                        {
                                                if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
-                                                       pr_casesdef2[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
+                                                       pr_casesdef2[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
                                                else
                                                        QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange type mismatch");
                                        }
@@ -6496,7 +6554,7 @@ void QCC_PR_ParseState (void)
 
                        frame = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], self, framef, NULL);
                        if (cycle_wrapped)
-                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(0), cycle_wrapped, NULL));
+                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(0), cycle_wrapped, NULL));
                        QCC_UnFreeTemp(frame);
 
                        //make sure the frame is within the bounds given.
@@ -6513,25 +6571,25 @@ void QCC_PR_ParseState (void)
                        t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL);
                        QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 7, 0, false);
                        QCC_FreeTemp(t1);       //this block is the 'it's in a forwards direction'
-                               QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
+                               QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
                                t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
                                QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
                                QCC_FreeTemp(t1);
                                        QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
                                        QCC_UnFreeTemp(frame);
                                        if (cycle_wrapped)
-                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
 
                        QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
                                //reverse animation.
-                               QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
+                               QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
                                t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
                                QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
                                QCC_FreeTemp(t1);
                                        QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
                                        QCC_UnFreeTemp(frame);
                                        if (cycle_wrapped)
-                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
+                                               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
 
                        //self.frame = frame happens with the normal state opcode.
                        QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], frame, pr_scope, NULL));
@@ -6550,7 +6608,7 @@ void QCC_PR_ParseState (void)
 
        name = QCC_PR_ParseName ();
        pr_scope = NULL;
-       def = QCC_PR_GetDef (type_function, name, NULL, true, 1, false);
+       def = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
        pr_scope = sc;
 
        QCC_PR_Expect ("]");
@@ -7109,6 +7167,7 @@ void QCC_Marshal_Locals(int first, int laststatement)
 {
        QCC_def_t *local;
        unsigned int newofs;
+       int size;
 
 //     if (!opt_overlaptemps)  //clear these after each function. we arn't overlapping them so why do we need to keep track of them?
 //     {
@@ -7144,9 +7203,11 @@ void QCC_Marshal_Locals(int first, int laststatement)
                if (local->constant)
                        continue;
 
-               newofs += local->type->size*local->arraysize;
-               if (local->arraysize>1)
-                       newofs++;
+               size = local->type->size*(local->arraysize?local->arraysize:1);
+               if (local->arraysize)
+                       size++;
+
+               newofs += size;
        }
 
        locals_start = MAX_REGS;
@@ -7163,12 +7224,14 @@ void QCC_Marshal_Locals(int first, int laststatement)
                if (((int*)qcc_pr_globals)[local->ofs])
                        QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value");
 
-               newofs -= local->type->size*local->arraysize;
-               if (local->arraysize>1)
-                       newofs--;
+               size = local->type->size*(local->arraysize?local->arraysize:1);
+               if (local->arraysize)
+                       size++;
+
+               newofs -= size;
 
-               QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+local->type->size*local->arraysize, newofs);
-               QCC_FreeOffset(local->ofs, local->type->size*local->arraysize);
+               QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+size, newofs);
+               QCC_FreeOffset(local->ofs, size);
 
                local->ofs = newofs;
        }
@@ -7203,9 +7266,9 @@ void QCC_WriteAsmFunction(QCC_def_t       *sc, unsigned int firststatement, gofs_t fir
                                break;
                }
                if (param)
-                       fprintf(asmfile, "%s %s /* at %d */", TypeName(type), param->name, o);
+                       fprintf(asmfile, "%s %s", TypeName(type), param->name);
                else
-                       fprintf(asmfile, "%s /* at %d */", TypeName(type), o);
+                       fprintf(asmfile, "%s", TypeName(type));
 
                o += type->size;
        }
@@ -7250,7 +7313,7 @@ void QCC_WriteAsmFunction(QCC_def_t       *sc, unsigned int firststatement, gofs_t fir
                                }
                        }
                }
-               fprintf(asmfile, ";\n");
+               fprintf(asmfile, "; /*%i*/\n", statement_linenums[i]);
        }
 
        fprintf(asmfile, "}\n\n");
@@ -7334,7 +7397,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
        {
                if (!*pr_parm_names[i])
                        QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
-               defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 1, false);
+               defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 0, false);
 
                defs[i]->references++;
                if (i < MAX_PARMS)
@@ -7379,9 +7442,9 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
        /*if (pr_classtype)
        {
                QCC_def_t *e, *e2;
-               e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 1);
-               e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 1);
-               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), e, NULL));
+               e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 0);
+               e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 0);
+               QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), e, NULL));
        }*/
 
 //
@@ -7404,7 +7467,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
                        do {
                                name = QCC_PR_ParseName();
                                QCC_PR_Expect(":");
-                               e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1, false);
+                               e2 = QCC_PR_GetDef(QCC_PR_ParseType(false, false), name, pr_scope, true, 0, false);
                                QCC_PR_Expect(";");
                        } while(!QCC_PR_CheckToken("{"));
                }
@@ -7469,7 +7532,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
                        QCC_def_t *e, *e2;
                        e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
                        e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
-                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
+                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
                }*/
 
                QCC_PR_Statement (pr_opcodes, 0,0, NULL);
@@ -7521,7 +7584,7 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi
        QCC_def_t *eq;
        if (min == max || min+1 == max)
        {
-               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
                QCC_UnFreeTemp(index);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
@@ -7534,7 +7597,7 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi
 
                if (max-min>4)
                {
-                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
                        QCC_UnFreeTemp(index);
                        QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                }
@@ -7555,7 +7618,7 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i
        QCC_def_t *eq;
        if (min == max || min+1 == max)
        {
-               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
                QCC_UnFreeTemp(index);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
@@ -7568,7 +7631,7 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i
 
                if (max-min>4)
                {
-                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
                        QCC_UnFreeTemp(index);
                        QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                }
@@ -7587,10 +7650,13 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
        QCC_dfunction_t *df;
        QCC_def_t *temp, *index, *func;
 
-       func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 1, false);
+       func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false);
 
        pr_scope = func;
 
+       if (numfunctions >= MAX_FUNCTIONS)
+               QCC_Error(ERR_INTERNAL, "Too many function defs");
+
        df = &functions[numfunctions];
        numfunctions++;
 
@@ -7600,17 +7666,17 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
        df->parm_size[0] = 1;
        df->numparms = 1;
        df->parm_start = numpr_globals;
-       index = QCC_PR_GetDef(type_float, "index___", func, true, 1, false);
+       index = QCC_PR_GetDef(type_float, "index___", func, true, 0, false);
        index->references++;
-       temp = QCC_PR_GetDef(type_float, "div3___", func, true, 1, false);
+       temp = QCC_PR_GetDef(type_float, "div3___", func, true, 0, false);
        locals_end = numpr_globals;
        df->locals = locals_end - df->parm_start;
-       QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp, false);
+       QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), temp, false);
        QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int
 
        QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3);  //round up
 
-       QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL);   //err... we didn't find it, give up.
+       QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); //err... we didn't find it, give up.
        QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);       //err... we didn't find it, give up.
 
        G_FUNCTION(func->ofs) = df - functions;
@@ -7630,7 +7696,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
        QCC_def_t *fasttrackpossible;
 
        if (flag_fasttrackarrays)
-               fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
+               fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
        else
                fasttrackpossible = NULL;
 
@@ -7645,6 +7711,9 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
 
        pr_scope = scope;
 
+       if (numfunctions >= MAX_FUNCTIONS)
+               QCC_Error(ERR_INTERNAL, "Too many function defs");
+
        df = &functions[numfunctions];
        numfunctions++;
 
@@ -7654,7 +7723,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
        df->parm_size[0] = 1;
        df->numparms = 1;
        df->parm_start = numpr_globals;
-       index = QCC_PR_GetDef(type_float, "indexg___", def, true, 1, false);
+       index = QCC_PR_GetDef(type_float, "indexg___", def, true, 0, false);
 
        G_FUNCTION(scope->ofs) = df - functions;
 
@@ -7683,44 +7752,44 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
                //we need to work out which part, x/y/z that it's stored in.
                //0,1,2 = i - ((int)i/3 *) 3;
 
-               div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false);
-               intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false);
+               div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false);
+               intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false);
 
-               eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatDef((float)def->arraysize), NULL);        //escape clause - should call some sort of error function instead.. that'd rule!
+               eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)def->arraysize), NULL);      //escape clause - should call some sort of error function instead.. that'd rule!
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
-               QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st);
+               QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, &st);
 
                div3->references++;
                QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
-               QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), div3, false);
+               QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), div3, false);
                QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, div3, div3, intdiv3, false);
 
                QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false);
                QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false);
                vectortrick->references++;
-               ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1, false);
+               ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 0, false);
                ret->references+=4;
                QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false);
                QCC_FreeTemp(&def_ret);
 
-               div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatDef(3), NULL);
+               div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatConst(3), NULL);
                QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
                QCC_FreeTemp(div3);
 
-               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(0+0.5f), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(0+0.5f), NULL);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
                QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
                st->a = ret->ofs + 0;
 
-               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(1+0.5f), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(1+0.5f), NULL);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
                QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
                st->a = ret->ofs + 1;
 
-               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(2+0.5), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(2+0.5), NULL);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 2;
                QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
@@ -7734,7 +7803,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
                QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize);
        }
 
-       QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL);
+       QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL);
 
        QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
 
@@ -7753,7 +7822,7 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t
        QCC_def_t *eq;
        if (min == max || min+1 == max)
        {
-               eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL);
+               eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatConst((float)min), NULL);
                QCC_UnFreeTemp(index);
                QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                st->b = 3;
@@ -7770,7 +7839,7 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t
 
                if (max-min>4)
                {
-                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef((float)mid), NULL);
+                       eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst((float)mid), NULL);
                        QCC_UnFreeTemp(index);
                        QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
                }
@@ -7791,13 +7860,16 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
        QCC_def_t *fasttrackpossible;
 
        if (flag_fasttrackarrays)
-               fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
+               fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
        else
                fasttrackpossible = NULL;
 
        def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
        pr_scope = scope;
 
+       if (numfunctions >= MAX_FUNCTIONS)
+               QCC_Error(ERR_INTERNAL, "Too many function defs");
+
        df = &functions[numfunctions];
        numfunctions++;
 
@@ -7808,8 +7880,8 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
        df->parm_size[1] = def->type->size;
        df->numparms = 2;
        df->parm_start = numpr_globals;
-       index = QCC_PR_GetDef(type_float, "indexs___", def, true, 1, false);
-       value = QCC_PR_GetDef(def->type, "value___", def, true, 1, false);
+       index = QCC_PR_GetDef(type_float, "indexs___", def, true, 0, false);
+       value = QCC_PR_GetDef(def->type, "value___", def, true, 0, false);
        locals_end = numpr_globals;
        df->locals = locals_end - df->parm_start;
 
@@ -7825,7 +7897,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
                QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats
                QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p
                if (def->type->size != 1)//shift it upwards for larger types
-                       QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntDef(def->type->size), index, true);
+                       QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(def->type->size), index, true);
                QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true);      //comes with built in add
                if (def->type->size >= 3)
                        QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true);  //*b = a
@@ -7883,7 +7955,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                KEYWORD(asm);
        }
 
-       for (a = 0; a < arraysize; a++)
+       for (a = 0; a < (arraysize?arraysize:1); a++)
        {
                if (a == 0)
                        *array = '\0';
@@ -7899,7 +7971,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
                memset (def, 0, sizeof(*def));
                def->next = NULL;
-               def->arraysize = arraysize;
+               def->arraysize = a?0:arraysize;
                if (name)
                {
                        pr.def_tail->next = def;
@@ -7911,6 +7983,8 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
 
                def->s_line = pr_source_line;
                def->s_file = s_file;
+               if (a)
+                       def->initialized = 1;
 
                def->name = (void *)qccHunkAlloc (strlen(newname)+1);
                strcpy (def->name, newname);
@@ -7919,7 +7993,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                def->scope = scope;
                def->saved = saved;
 
-       //      if (arraysize>1)
+               //if (type->type = ev_field)
                        def->constant = true;
 
                if (ofs + type->size*a >= MAX_REGS)
@@ -7941,14 +8015,14 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                                {
                                case ev_vector:
                                        sprintf(newname, "%s%s.%s", name, array, parttype->name);
-                                       QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
+                                       QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
 
                                        sprintf(newname, "%s%s.%s_x", name, array, parttype->name);
-                                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, false);
+                                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, false);
                                        sprintf(newname, "%s%s.%s_y", name, array, parttype->name);
-                                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+1, false, false);
+                                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+1, false, false);
                                        sprintf(newname, "%s%s.%s_z", name, array, parttype->name);
-                                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+2, false, false);
+                                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+2, false, false);
                                        break;
 
                                case ev_float:
@@ -7961,12 +8035,12 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                                case ev_union:
                                case ev_variant:        //for lack of any better alternative
                                        sprintf(newname, "%s%s.%s", name, array, parttype->name);
-                                       QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
+                                       QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
                                        break;
 
                                case ev_function:
                                        sprintf(newname, "%s%s.%s", name, array, parttype->name);
-                                       QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
+                                       QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
                                        break;
                                case ev_void:
                                        break;
@@ -7977,11 +8051,11 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                else if (type->type == ev_vector)
                {       //do the vector thing.
                        sprintf(newname, "%s%s_x", name, array);
-                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+0, referable, false);
+                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, false);
                        sprintf(newname, "%s%s_y", name, array);
-                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+1, referable, false);
+                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, false);
                        sprintf(newname, "%s%s_z", name, array);
-                       QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+2, referable, false);
+                       QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, false);
                }
                else if (type->type == ev_field)
                {
@@ -7989,20 +8063,21 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                        {
                                //do the vector thing.
                                sprintf(newname, "%s%s_x", name, array);
-                               QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+0, referable, false);
+                               QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+0, referable, false);
                                sprintf(newname, "%s%s_y", name, array);
-                               QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+1, referable, false);
+                               QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, false);
                                sprintf(newname, "%s%s_z", name, array);
-                               QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+2, referable, false);
+                               QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, false);
                        }
                }
+               first->deftail = pr.def_tail;
        }
 
        if (referable)
        {
                if (!pHash_Get(&globalstable, "end_sys_fields"))
                        first->references++;    //anything above needs to be left in, and so warning about not using it is just going to pee people off.
-               if (arraysize <= 1 && first->type->type != ev_field)
+               if (!arraysize && first->type->type != ev_field)
                        first->constant = false;
                if (scope)
                        pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
@@ -8010,7 +8085,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
                        pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
 
                if (!scope && asmfile)
-                       fprintf(asmfile, "%s %s; /* at %d */\n", TypeName(first->type), first->name, first->ofs);
+                       fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
        }
 
        return first;
@@ -8022,6 +8097,9 @@ PR_GetDef
 
 If type is NULL, it will match any type
 If allocate is true, a new def will be allocated if it can't be found
+If arraysize=0, its not an array and has 1 element.
+If arraysize>0, its an array and requires array notation
+If arraysize<0, its an array with undefined size - GetDef will fail if its not already allocated.
 ============
 */
 
@@ -8033,6 +8111,9 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
        unsigned int i;
        QCC_def_t *foundstatic = NULL;
 
+       if (!allocate)
+               arraysize = -1;
+
        if (scope)
        {
                def = Hash_Get(&localstable, name);
@@ -8047,7 +8128,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
 
                        if (type && typecmp(def->type, type))
                                QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
-                       if (def->arraysize != arraysize && arraysize)
+                       if (def->arraysize != arraysize && arraysize>=0)
                                QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
                        if (allocate && scope)
                        {
@@ -8083,7 +8164,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
                        if (!pr_scope)
                                QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
                }
-               if (def->arraysize != arraysize && arraysize)
+               if (def->arraysize != arraysize && arraysize>=0)
                        QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
                if (allocate && scope)
                {
@@ -8117,7 +8198,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
 
                                if (type && typecmp(def->type, type))
                                        QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
-                               if (def->arraysize != arraysize && arraysize)
+                               if (def->arraysize != arraysize && arraysize>=0)
                                        QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
                                if (allocate && scope)
                                {
@@ -8153,7 +8234,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
                                if (!pr_scope)
                                        QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
                        }
-                       if (def->arraysize != arraysize && arraysize)
+                       if (def->arraysize != arraysize && arraysize>=0)
                                QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
                        if (allocate && scope)
                        {
@@ -8181,7 +8262,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
        if (!allocate)
                return NULL;
 
-       if (arraysize < 1)
+       if (arraysize < 0)
        {
                QCC_PR_ParseError (ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name);
        }
@@ -8193,7 +8274,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
        }
 
        ofs = numpr_globals;
-       if (arraysize > 1)
+       if (arraysize)
        {       //write the array size
                ofs = QCC_GetFreeOffsetSpace(1 + (type->size    * arraysize));
 
@@ -8201,14 +8282,14 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
                ofs++;
        }
        else
-               ofs = QCC_GetFreeOffsetSpace(type->size * arraysize);
+               ofs = QCC_GetFreeOffsetSpace(type->size);
 
        def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, true, saved);
 
        //fix up fields.
        if (type->type == ev_field && allocate != 2)
        {
-               for (i = 0; i < type->size*arraysize; i++)      //make arrays of fields work.
+               for (i = 0; i < type->size*(arraysize?arraysize:1); i++)        //make arrays of fields work.
                        *(int *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i;
 
                pr.size_fields += i;
@@ -8235,7 +8316,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope,
        startfield = *fieldofs;
        maxfield = startfield;
 
-       for (a = 0; a < arraysize; a++)
+       for (a = 0; a < (arraysize?arraysize:1); a++)
        {
                if (a == 0)
                        *array = '\0';
@@ -8309,14 +8390,14 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope,
                                                sprintf(newname, "%s%s.%s", name, array, parttype->name);
                                        else
                                                sprintf(newname, "%s%s", parttype->name, array);
-                                       ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
+                                       ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
                                        ftype->aux_type = parttype;
                                        if (parttype->type == ev_vector)
                                                ftype->size = parttype->size;   //vector fields create a _y and _z too, so we need this still.
-                                       def = QCC_PR_GetDef(NULL, newname, scope, false, 1, saved);
+                                       def = QCC_PR_GetDef(NULL, newname, scope, false, 0, saved);
                                        if (!def)
                                        {
-                                               def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
+                                               def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
                                        }
                                        else
                                        {
@@ -8330,9 +8411,9 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope,
                                                sprintf(newname, "%s%s.%s", name, array, parttype->name);
                                        else
                                                sprintf(newname, "%s%s", parttype->name, array);
-                                       ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
+                                       ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
                                        ftype->aux_type = parttype;
-                                       def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
+                                       def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
                                        def->initialized = true;
                                        ((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
                                        *fieldofs += parttype->size;
@@ -8363,6 +8444,221 @@ void QCC_PR_ExpandUnionToFields(QCC_type_t *type, int *fields)
        QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields, true);
 }
 
+
+void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type, int offset)
+{
+       QCC_def_t *tmp;
+       int i;
+
+       if (arraysize)
+       {
+               //arrays go recursive
+               QCC_PR_Expect("{");
+               for (i = 0; i < arraysize; i++)
+               {
+                       QCC_PR_ParseInitializerType(0, def, type, offset + i*type->size);
+                       if (!QCC_PR_CheckToken(","))
+                               break;
+               }
+               QCC_PR_Expect("}");
+       }
+       else
+       {
+               if (type->type == ev_function && pr_token_type == tt_punct)
+               {
+                       /*begin function special case*/
+                       QCC_def_t *parentfunc = pr_scope;
+                       QCC_function_t *f;
+                       QCC_dfunction_t *df;
+                       QCC_type_t *parm;
+
+                       tmp = NULL;
+
+                       def->references++;
+                       pr_scope = def;
+                       if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":"))
+                       {
+                               int binum = 0;
+                               if (pr_token_type == tt_immediate
+                               && pr_immediate_type == type_float
+                               && pr_immediate._float == (int)pr_immediate._float)
+                                       binum = (int)pr_immediate._float;
+                               else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer)
+                                       binum = pr_immediate._int;
+                               else
+                                       QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
+                               QCC_PR_Lex();
+
+                               if (def->initialized)
+                               for (i = 0; i < numfunctions; i++)
+                               {
+                                       if (functions[i].first_statement == -binum)
+                                       {
+                                               tmp = QCC_MakeIntConst(i);
+                                               break;
+                                       }
+                               }
+
+                               if (!tmp)
+                               {
+                                       f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
+                                       f->builtin = binum;
+
+                                       locals_start = locals_end = OFS_PARM0; //hmm...
+                               }
+                               else
+                                       f = NULL;
+                       }
+                       else
+                               f = QCC_PR_ParseImmediateStatements (type);
+                       if (!tmp)
+                       {
+                               pr_scope = parentfunc;
+                               tmp = QCC_MakeIntConst(numfunctions);
+                               f->def = def;
+
+                               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_file2;
+                               df->numparms =  f->def->type->num_parms;
+                               df->locals = locals_end - locals_start;
+                               df->parm_start = locals_start;
+                               for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
+                               {
+                                       df->parm_size[i] = parm->size;
+                               }
+                               /*end function special case*/
+                       }
+               }
+               else if (type->type == ev_string && QCC_PR_CheckName("_"))
+               {
+                       char trname[128];
+                       QCC_PR_Expect("(");
+                       if (pr_token_type != tt_immediate || pr_immediate_type->type != ev_string)
+                               QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate");
+                       tmp = QCC_MakeStringConst(pr_immediate_string);
+                       QCC_PR_Lex();
+                       QCC_PR_Expect(")");
+
+                       if (!pr_scope || def->constant)
+                       {
+                               QCC_def_t *dt;
+                               sprintf(trname, "dotranslate_%i", ++dotranslate_count);
+                               dt = QCC_PR_DummyDef(type_string, trname, pr_scope, 0, offset, true, true);
+                               dt->references = 1;
+                               dt->constant = 1;
+                               dt->initialized = 1;
+                       }
+               }
+               else if (type->type == ev_struct || type->type == ev_union)
+               {
+                       //structs go recursive
+                       QCC_type_t *parttype;
+                       int partnum;
+                       int parms;
+                       pbool isunion;
+                       QCC_PR_Expect("{");
+
+                       isunion = ((type)->type == ev_union);
+                       for (partnum = 0, parttype = (type)->param, parms = (type)->num_parms; partnum < parms; partnum++, parttype = parttype->next)
+                       {
+                               QCC_PR_ParseInitializerType(parttype->arraysize, def, parttype, offset + parttype->ofs);
+                               if (isunion || !QCC_PR_CheckToken(","))
+                                       break;
+                       }
+                       QCC_PR_Expect("}");
+                       return;
+               }
+               else
+               {
+                       tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
+                       if (typecmp(type, tmp->type))
+                       {
+                               /*you can cast from const 0 to anything*/
+                               if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs))
+                               {
+                               }
+                               /*cast from int->float will convert*/
+                               else if (type->type == ev_float && tmp->type->type == ev_integer)
+                                       tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], tmp, 0, NULL);
+                               /*cast from float->int will convert*/
+                               else if (type->type == ev_integer && tmp->type->type == ev_float)
+                                       tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], tmp, 0, NULL);
+                               else
+                                       QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type");
+                       }
+               }
+
+               if (!pr_scope || def->constant)
+               {
+                       if (!tmp->constant)
+                               QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initializer is not constant");
+
+                       if (def->initialized)
+                       {
+                               for (i = 0; (unsigned)i < type->size; i++)
+                                       if (G_INT(offset+i) != G_INT(tmp->ofs+i))
+                                               QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "incompatible redeclaration");
+                       }
+                       else
+                       {
+                               for (i = 0; (unsigned)i < type->size; i++)
+                                       G_INT(offset+i) = G_INT(tmp->ofs+i);
+                       }
+               }
+               else
+               {
+                       QCC_def_t lhs, rhs;
+                       if (def->initialized)
+                               QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s initialised twice", def->name);
+
+                       memset(&lhs, 0, sizeof(lhs));
+                       memset(&rhs, 0, sizeof(rhs));
+                       def->references++;
+                       for (i = 0; (unsigned)i < type->size; )
+                       {
+                               rhs.type = lhs.type = type_float;
+                               lhs.ofs = offset+i;
+                               tmp->references++;
+                               rhs.ofs = tmp->ofs+i;
+
+                               if (type->size - i >= 3)
+                               {
+                                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &rhs, &lhs, NULL));
+                                       i+=3;
+                               }
+                               else
+                               {
+                                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &rhs, &lhs, NULL));
+                                       i++;
+                               }
+                       }
+               }
+               QCC_FreeTemp(tmp);
+       }
+}
+
+void QCC_PR_ParseInitializerDef(QCC_def_t *def, pbool isvar, pbool isconst)
+{
+       def->constant = (isconst || (!isvar && !pr_scope));
+       QCC_PR_ParseInitializerType(def->arraysize, def, def->type, def->ofs);
+       if (!def->initialized)
+               def->initialized = 1;
+}
+
 int accglobalsblock;   //0 = error, 1 = var, 2 = function, 3 = objdata
 /*
 ================
@@ -8388,10 +8684,12 @@ void QCC_PR_ParseDefs (char *classname)
        pbool nosave = false;
        pbool allocatenew = true;
        pbool inlinefunction = false;
-       int ispointer;
        gofs_t oldglobals;
        int arraysize;
 
+       while (QCC_PR_CheckToken(";"))
+               ;
+
        if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
        {
                if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
@@ -8424,7 +8722,7 @@ void QCC_PR_ParseDefs (char *classname)
                                                QCC_PR_Lex();
                                        }
                                }
-                               def = QCC_MakeIntDef(iv);
+                               def = QCC_MakeIntConst(iv);
                                pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
                                iv++;
 
@@ -8466,7 +8764,7 @@ void QCC_PR_ParseDefs (char *classname)
                                                QCC_PR_Lex();
                                        }
                                }
-                               def = QCC_MakeFloatDef(fv);
+                               def = QCC_MakeFloatConst(fv);
                                pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
                                fv++;
 
@@ -8528,11 +8826,11 @@ void QCC_PR_ParseDefs (char *classname)
                                                        bits++;
                                                i>>=1;
                                        }
-                                       if (bits != 1)
+                                       if (bits > 1)
                                                QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv);
                                }
 
-                               def = QCC_MakeIntDef(iv);
+                               def = QCC_MakeIntConst(iv);
                                pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
 
                                iv*=2;
@@ -8587,11 +8885,11 @@ void QCC_PR_ParseDefs (char *classname)
                                                        bits++;
                                                i>>=1;
                                        }
-                                       if (bits != 1)
+                                       if (bits > 1)
                                                QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv);
                                }
 
-                               def = QCC_MakeFloatDef(fv);
+                               def = QCC_MakeFloatConst(fv);
                                pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
 
                                fv*=2;
@@ -8607,12 +8905,13 @@ void QCC_PR_ParseDefs (char *classname)
 
        if (QCC_PR_CheckKeyword (keyword_typedef, "typedef"))
        {
-               type = QCC_PR_ParseType(true);
+               type = QCC_PR_ParseType(true, false);
                if (!type)
                {
                        QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens");
                }
                type->name = QCC_CopyString(pr_token)+strings;
+               type->typedefed = true;
                QCC_PR_Lex();
                QCC_PR_Expect(";");
                return;
@@ -8637,7 +8936,7 @@ void QCC_PR_ParseDefs (char *classname)
                        if (accglobalsblock == 3)
                        {
                                if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
-                                       QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
+                                       QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
                        }
 
                        QCC_PR_ParseName();
@@ -8656,11 +8955,11 @@ void QCC_PR_ParseDefs (char *classname)
                        if (accglobalsblock == 3)
                        {
                                if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
-                                       QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
+                                       QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
                        }
                        else
                                if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0, false))
-                                       QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 1, false);
+                                       QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 0, false);
                        accglobalsblock = 3;
                }
        }
@@ -8681,12 +8980,12 @@ void QCC_PR_ParseDefs (char *classname)
                        break;
                }
                if (QCC_PR_CheckKeyword(keyword_object, "object"))
-                       QCC_PR_GetDef(type_entity, name, NULL, true, 1, true);
+                       QCC_PR_GetDef(type_entity, name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_string, "string"))
-                       QCC_PR_GetDef(type_string, name, NULL, true, 1, true);
+                       QCC_PR_GetDef(type_string, name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_real, "real"))
                {
-                       def = QCC_PR_GetDef(type_float, name, NULL, true, 1, true);
+                       def = QCC_PR_GetDef(type_float, name, NULL, true, 0, true);
                        if (QCC_PR_CheckToken("="))
                        {
                                G_FLOAT(def->ofs) = pr_immediate._float;
@@ -8695,7 +8994,7 @@ void QCC_PR_ParseDefs (char *classname)
                }
                else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
                {
-                       def = QCC_PR_GetDef(type_vector, name, NULL, true, 1, true);
+                       def = QCC_PR_GetDef(type_vector, name, NULL, true, 0, true);
                        if (QCC_PR_CheckToken("="))
                        {
                                QCC_PR_Expect("[");
@@ -8709,7 +9008,7 @@ void QCC_PR_ParseDefs (char *classname)
                        }
                }
                else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
-                       QCC_PR_GetDef(type_function, name, NULL, true, 1, true);
+                       QCC_PR_GetDef(type_function, name, NULL, true, 0, true);
                else
                        QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
                QCC_PR_Expect (";");
@@ -8736,15 +9035,15 @@ void QCC_PR_ParseDefs (char *classname)
                        break;
                }
                if (QCC_PR_CheckKeyword(keyword_object, "object"))
-                       QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 1, true);
+                       QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_string, "string"))
-                       QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 1, true);
+                       QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_real, "real"))
-                       QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 1, true);
+                       QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
-                       QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 1, true);
+                       QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 0, true);
                else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
-                       QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 1, true);
+                       QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 0, true);
                else
                        QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
                QCC_PR_Expect (";");
@@ -8778,7 +9077,7 @@ void QCC_PR_ParseDefs (char *classname)
                        break;
        }
 
-       type = QCC_PR_ParseType (false);
+       type = QCC_PR_ParseType (false, false);
        if (type == NULL)       //ignore
                return;
 
@@ -8796,9 +9095,7 @@ void QCC_PR_ParseDefs (char *classname)
                QCC_PR_Expect("(");
                type = QCC_PR_ParseFunctionTypeReacc(false, type);
                QCC_PR_Expect(";");
-               if (!stricmp(name, "null"))
-                       printf("null!\n");
-               def = QCC_PR_GetDef (type, name, NULL, true, 1, false);
+               def = QCC_PR_GetDef (type, name, NULL, true, 0, false);
 
                if (autoprototype)
                {       //ignore the code and stuff
@@ -8850,6 +9147,9 @@ void QCC_PR_ParseDefs (char *classname)
 //                             if (pr_dumpasm)
 //                                     PR_PrintFunction (def);
 
+               if (numfunctions >= MAX_FUNCTIONS)
+                       QCC_Error(ERR_INTERNAL, "Too many function defs");
+
 // fill in the dfunction
                df = &functions[numfunctions];
                numfunctions++;
@@ -8878,15 +9178,8 @@ void QCC_PR_ParseDefs (char *classname)
 //             QCC_PR_ParseError ("Fields must be global");
 
        do
-       {
-               if (QCC_PR_CheckToken ("*"))
-               {
-                       ispointer = 1;
-                       while(QCC_PR_CheckToken ("*"))
-                               ispointer++;
-                       name = QCC_PR_ParseName ();
-               }
-               else if (QCC_PR_CheckToken (";"))
+       {               
+               if (QCC_PR_CheckToken (";"))
                {
                        if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct))
                        {
@@ -8899,12 +9192,10 @@ void QCC_PR_ParseDefs (char *classname)
 //                     }
                        QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name");
                        name = NULL;
-                       ispointer = false;
                }
                else
                {
                        name = QCC_PR_ParseName ();
-                       ispointer = false;
                }
 
                if (QCC_PR_CheckToken("::") && !classname)
@@ -8940,46 +9231,18 @@ void QCC_PR_ParseDefs (char *classname)
                        }
                        else
                        {
-                               def = QCC_PR_Expression(TOP_PRIORITY, 0);
-                               if (!def->constant)
-                                       QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
-                               else if (def->type->type == ev_integer)
-                                       arraysize = G_INT(def->ofs);
-                               else if (def->type->type == ev_float)
-                               {
-                                       arraysize = (int)G_FLOAT(def->ofs);
-                                       if ((float)arraysize != G_FLOAT(def->ofs))
-                                               QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
-                               }
-                               else
-                                       QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size must be of int value");
-/*                             if(pr_token_type == tt_name)
-                               {
-                                       def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), pr_scope, false, 0);
-                                       if (def && def->arraysize==1)
-                                       {
-                                               if (def->type->type == ev_integer)
-                                                       arraysize = G_INT(def->ofs);
-                                               else if (def->type->type == ev_float && (float)(int)G_FLOAT(def->ofs) == G_FLOAT(def->ofs))
-                                                       arraysize = (int)G_FLOAT(def->ofs);
-                                       }
-                               }
-                               else if (pr_token_type == tt_immediate)
-                               {
-                                       arraysize = atoi (pr_token);
-                                       QCC_PR_Lex();
-                               }
-*/                             QCC_PR_Expect("]");
+                               arraysize = QCC_PR_IntConstExpr();
+                               QCC_PR_Expect("]");
                        }
 
                        if (arraysize < 1)
                        {
                                QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name);
-                               arraysize=0;    //grrr...
+                               arraysize=1;    //grrr...
                        }
                }
                else
-                       arraysize = 1;
+                       arraysize = 0;
 
                if (QCC_PR_CheckToken("("))
                {
@@ -9007,19 +9270,7 @@ void QCC_PR_ParseDefs (char *classname)
 
                oldglobals = numpr_globals;
 
-               if (ispointer)
-               {
-                       parm = type;
-                       while(ispointer)
-                       {
-                               ispointer--;
-                               parm = QCC_PointerTypeTo(parm);
-                       }
-
-                       def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize, !nosave);
-               }
-               else
-                       def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
+               def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
 
                if (!def)
                        QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname);
@@ -9051,13 +9302,12 @@ void QCC_PR_ParseDefs (char *classname)
                                QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised");
                        }
 
-                       arraysize = def->arraysize;
-                       d = def;        //apply to ALL elements
-                       while(arraysize--)
+                       d = def;
+                       while (d != def->deftail)
                        {
+                               d = d->next;
                                d->initialized = 1;     //fake function
                                G_FUNCTION(d->ofs) = 0;
-                               d = d->next;
                        }
 
                        continue;
@@ -9074,14 +9324,14 @@ void QCC_PR_ParseDefs (char *classname)
                                QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);
                        if (def->initialized == 1)
                        {
-                               if (def->type->type == ev_function)
-                               {
-                                       i = G_FUNCTION(def->ofs);
-                                       df = &functions[i];
-                                       QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
-                               }
-                               else
-                                       QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
+//                             if (def->type->type == ev_function)
+//                             {
+//                                     i = G_FUNCTION(def->ofs);
+//                                     df = &functions[i];
+//                                     QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
+//                             }
+//                             else
+//                                     QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
                        }
 
                        if (autoprototype)
@@ -9119,588 +9369,7 @@ void QCC_PR_ParseDefs (char *classname)
                                continue;
                        }
 
-                       if (pr_scope)
-                       {
-                               d = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
-                               if (typecmp(def->type, d->type))
-                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-                               if (d->constant)
-                               {
-                                       for (i = 0; (unsigned)i < def->type->size; i++)
-                                               G_INT(def->ofs+i) = G_INT(d->ofs+i);
-                                       def->constant = !isvar;
-                                       def->initialized = 1;
-                                       continue;
-                               }
-                               else if (def->type->size >= 3)
-                               {
-                                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], d, def, NULL));
-                                       def->constant = false;
-                                       def->initialized = false;
-                                       continue;
-                               }
-                               else
-                               {
-                                       QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], d, def, NULL));
-                                       def->constant = false;
-                                       def->initialized = false;
-                                       continue;
-                               }
-                       }
-                       else
-                               if (pr_token_type == tt_name && strcmp(pr_token, "_"))
-                       {
-                               unsigned int i;
-
-                               if (def->arraysize>1)
-                                       QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly braces");
-
-                               d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
-                               if (!d)
-                                       QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
-                               if (typecmp(def->type, d->type))
-                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
-
-                               for (i = 0; i < d->type->size; i++)
-                                       G_INT(def->ofs) = G_INT(d->ofs);
-                               QCC_PR_Lex();
-
-                               if (type->type == ev_function)
-                               {
-                                       def->initialized = 1;
-                                       def->constant = !isvar;
-                               }
-                               continue;
-                       }
-
-                       else if (type->type == ev_function)
-                       {
-                               if (isvar)
-                                       def->constant = false;
-                               else
-                                       def->constant = true;
-                               if (QCC_PR_CheckImmediate("0") || QCC_PR_CheckImmediate("0i"))
-                               {
-                                       def->constant = 0;
-                                       def->initialized = 1;   //fake function
-                                       G_FUNCTION(def->ofs) = 0;
-                                       continue;
-                               }
-
-                               if (!def->constant && arraysize==1)
-                               {
-                                       def->constant = 0;
-                                       def->initialized = 1;   //fake function
-
-                                       name = QCC_PR_ParseName ();
-                                       d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
-                                       if (!d)
-                                               QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not previously defined", name);
-                                       G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
-                                       continue;
-                               }
-
-                               if (arraysize>1)
-                               {
-                                       int i;
-                                       def->initialized = 1;   //fake function
-                                       QCC_PR_Expect ("{");
-                                       i = 0;
-                                       do
-                                       {
-                                               if (pr_token_type == tt_immediate && (
-                                                       (pr_immediate_type == type_integer && pr_immediate._int == 0) ||
-                                                       (pr_immediate_type == type_float && pr_immediate._float == 0)))
-                                               {
-                                                       QCC_PR_Lex();
-                                                       G_FUNCTION(def->ofs+i) = 0;
-                                               }
-                                               else
-                                               {
-                                                       name = QCC_PR_ParseName ();
-
-                                                       d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
-                                                       if (!d)
-                                                               QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined", name);
-                                                       else
-                                                       {
-                                                               if (!d->initialized)
-                                                                       QCC_PR_ParseWarning(WARN_NOTDEFINED, "initialisation of function arrays must be placed after the body of all functions used (%s)", name);
-                                                               G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
-                                                       }
-                                               }
-
-                                               i++;
-                                       } while(QCC_PR_CheckToken(","));
-
-                                       arraysize = def->arraysize;
-                                       d = def;        //apply to ALL elements
-                                       while(arraysize--)
-                                       {
-                                               d->initialized = 1;     //fake function
-                                               d = d->next;
-                                       }
-
-                                       QCC_PR_Expect("}");
-                                       if (i > def->arraysize)
-                                               QCC_PR_ParseError(ERR_TOOMANYINITIALISERS, "Too many initializers");
-                                       continue;
-                               }
-                               if (!def->constant)
-                                       QCC_PR_ParseError(0, "Initialised functions must be constant");
-
-                               def->references++;
-                               pr_scope = def;
-                               f = QCC_PR_ParseImmediateStatements (type);
-                               pr_scope = NULL;
-                               def->initialized = 1;
-                               G_FUNCTION(def->ofs) = numfunctions;
-                               f->def = def;
-//                             if (pr_dumpasm)
-//                                     PR_PrintFunction (def);
-
-               // 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_file2;
-                               df->numparms =  f->def->type->num_parms;
-                               df->locals = locals_end - locals_start;
-                               df->parm_start = locals_start;
-                               for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
-                               {
-                                       df->parm_size[i] = parm->size;
-                               }
-
-                               continue;
-                       }
-
-                       else if (type->type == ev_struct)
-                       {
-                               int arraypart, partnum;
-                               QCC_type_t *parttype;
-                               def->initialized = 1;
-                               if (isvar)
-                                       def->constant = true;
-                               else
-                                       def->constant = false;
-//                             if (constant)
-//                                     QCC_PR_ParseError("const used on a struct isn't useful");
-
-                               //FIXME: should do this recursivly
-                               QCC_PR_Expect("{");
-                               for (arraypart = 0; arraypart < arraysize; arraypart++)
-                               {
-                                       parttype = type->param;
-                                       QCC_PR_Expect("{");
-                                       for (partnum = 0; partnum < type->num_parms; partnum++)
-                                       {
-                                               switch (parttype->type)
-                                               {
-                                               case ev_float:
-                                               case ev_integer:
-                                               case ev_vector:
-                                                       if (pr_token_type == tt_punct)
-                                                       {
-                                                               if (QCC_PR_CheckToken("{"))
-                                                               {
-                                                                       QCC_PR_Expect("}");
-                                                               }
-                                                               else
-                                                                       QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
-
-                                                       }
-                                                       else if (pr_token_type == tt_immediate)
-                                                       {
-                                                               if (pr_immediate_type->type == ev_float && parttype->type == ev_integer)
-                                                                       G_INT(def->ofs + arraypart*type->size + parttype->ofs) = (int)pr_immediate._float;
-                                                               else if (pr_immediate_type->type != parttype->type)
-                                                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
-                                                               else
-                                                                       memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
-                                                       }
-                                                       else if (pr_token_type == tt_name)
-                                                       {
-                                                               d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
-                                                               if (!d)
-                                                                       QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
-                                                               else if (d->type->type != parttype->type)
-                                                                       QCC_PR_ParseError (ERR_WRONGSUBTYPE, "wrong subtype for %s.%s", def->name, parttype->name);
-                                                               else if (!d->constant)
-                                                                       QCC_PR_ParseError(ERR_NOTACONSTANT, "%s isn't a constant\n", pr_token);
-
-                                                               memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, qcc_pr_globals + d->ofs, 4*d->type->size);
-                                                       }
-                                                       else
-                                                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
-                                                       QCC_PR_Lex ();
-
-                                                       break;
-                                               case ev_string:
-                                                       if (pr_token_type == tt_punct)
-                                                       {
-                                                               if (QCC_PR_CheckToken("{"))
-                                                               {
-                                                                       unsigned int i;
-                                                                       for (i = 0; i < parttype->size; i++)
-                                                                       {
-/*                                                                             //the executor defines strings as true c strings, but reads in index from string table.
-                                                                               //structures can hide these strings.
-                                                                               d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                                                               d->next = NULL;
-                                                                               pr.def_tail->next = d;
-                                                                               pr.def_tail = d;
-
-                                                                               d->type = parttype;
-                                                                               d->name = "STRUCTIMMEDIATE";
-                                                                               d->constant = constant;
-                                                                               d->initialized = 1;
-                                                                               d->scope = NULL;
-
-                                                                               d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
-*/
-                                                                               G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = QCC_CopyString(pr_immediate_string);
-                                                                               QCC_PR_Lex ();
-
-                                                                               if (!QCC_PR_CheckToken(","))
-                                                                               {
-                                                                                       i++;
-                                                                                       break;
-                                                                               }
-                                                                       }
-                                                                       for (; i < parttype->size; i++)
-                                                                       {
-/*                                                                             //the executor defines strings as true c strings, but reads in index from string table.
-                                                                               //structures can hide these strings.
-                                                                               d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                                                               d->next = NULL;
-                                                                               pr.def_tail->next = d;
-                                                                               pr.def_tail = d;
-
-                                                                               d->type = parttype;
-                                                                               d->name = "STRUCTIMMEDIATE";
-                                                                               d->constant = constant;
-                                                                               d->initialized = 1;
-                                                                               d->scope = NULL;
-
-                                                                               d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
-*/
-                                                                               G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0;
-                                                                       }
-                                                                       QCC_PR_Expect("}");
-                                                               }
-                                                               else
-                                                                       QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
-                                                       }
-                                                       else
-                                                       {
-/*                                                             //the executor defines strings as true c strings, but reads in index from string table.
-                                                               //structures can hide these strings.
-                                                               d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                                               d->next = NULL;
-                                                               pr.def_tail->next = d;
-                                                               pr.def_tail = d;
-
-                                                               d->type = parttype;
-                                                               d->name = "STRUCTIMMEDIATE";
-                                                               d->constant = constant;
-                                                               d->initialized = 1;
-                                                               d->scope = NULL;
-
-                                                               d->ofs = def->ofs+arraypart*type->size+parttype->ofs;
-*/
-                                                               G_INT(def->ofs+arraypart*type->size+parttype->ofs) = QCC_CopyString(pr_immediate_string);
-                                                               QCC_PR_Lex ();
-                                                       }
-                                                       break;
-                                               case ev_function:
-                                                       if (pr_token_type == tt_immediate)
-                                                       {
-                                                               if (pr_immediate._int != 0)
-                                                                       QCC_PR_ParseError(ERR_NOTFUNCTIONTYPE, "Expected function name or NULL");
-                                                               G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = 0;
-                                                               QCC_PR_Lex();
-                                                       }
-                                                       else
-                                                       {
-                                                               name = QCC_PR_ParseName ();
-
-                                                               d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
-                                                               if (!d)
-                                                                       QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", name);
-                                                               else
-                                                                       G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = G_FUNCTION(d->ofs);
-                                                       }
-                                                       break;
-                                               default:
-                                                       QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type);
-                                                       QCC_PR_Lex();
-                                                       break;
-                                               }
-                                               if (!QCC_PR_CheckToken(","))
-                                                       break;
-
-                                               parttype=parttype->next;
-                                       }
-                                       QCC_PR_Expect("}");
-                                       if (!QCC_PR_CheckToken(","))
-                                               break;
-                               }
-                               QCC_PR_Expect("}");
-                               continue;
-                       }
-
-                       else if (type->type == ev_integer)      //handle these differently, because they may need conversions
-                       {
-                               if (isvar)
-                                       def->constant = false;
-                               else
-                                       def->constant = true;
-
-                               def->initialized = 1;
-                               memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
-                               QCC_PR_Lex ();
-
-                               if (pr_immediate_type->type == ev_float)
-                                       G_INT(def->ofs) = (int)pr_immediate._float;
-                               else if (pr_immediate_type->type != ev_integer)
-                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
-                               continue;
-                       }
-                       else if (type->type == ev_string)
-                       {
-                               int dotranslate = 0;
-                               char buf[64];
-                               if (!strcmp(pr_token, "_"))
-                               {
-                                       dotranslate = 1;
-                                       QCC_PR_Lex();
-                               }
-                               if(dotranslate)
-                                       QCC_PR_Expect("(");
-
-                               if (arraysize>=1 && QCC_PR_CheckToken("{"))
-                               {
-                                       int i;
-                                       for (i = 0; i < arraysize; i++)
-                                       {
-                                               int dotranslate2;
-
-                                               //the executor defines strings as true c strings, but reads in index from string table.
-                                               //structures can hide these strings.
-                                               if (i != 0)     //not for the first entry - already a string def for that
-                                               {
-                                                       d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
-                                                       d->next = NULL;
-                                                       pr.def_tail->next = d;
-                                                       pr.def_tail = d;
-
-                                                       d->name = "IMMEDIATE";
-                                                       d->type = type_string;
-                                                       if (isvar)
-                                                               d->constant = false;
-                                                       else
-                                                               d->constant = true;
-                                                       d->initialized = 1;
-                                                       d->scope = NULL;
-
-                                                       d->ofs = def->ofs+i;
-                                                       if (d->ofs >= MAX_REGS)
-                                                               QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
-                                               }
-
-                                               if (!strcmp(pr_token, "_"))
-                                               {
-                                                       dotranslate2 = 1;
-                                                       QCC_PR_Lex();
-                                               }
-                                               if(dotranslate2)
-                                                       QCC_PR_Expect("(");
-
-                                               if(dotranslate || dotranslate2)
-                                               {
-                                                       sprintf(buf, "dotranslate_%d", ++dotranslate_count);
-                                                       d->name = strdup(buf);
-                                               }
-
-                                               (((int *)qcc_pr_globals)[def->ofs+i]) = QCC_CopyString(pr_immediate_string);
-                                               QCC_PR_Lex ();
-
-                                               if(dotranslate2)
-                                                       QCC_PR_Expect(")");
-
-                                               if (!QCC_PR_CheckToken(","))
-                                                       break;
-                                       }
-                                       QCC_PR_Expect("}");
-                               }
-                               else if (arraysize<=1)
-                               {
-                                       if (isvar)
-                                               def->constant = false;
-                                       else
-                                               def->constant = true;
-                                       def->initialized = 1;
-                                       (((int *)qcc_pr_globals)[def->ofs]) = QCC_CopyString(pr_immediate_string);
-                                       QCC_PR_Lex ();
-
-                                       if(dotranslate)
-                                       {
-                                               sprintf(buf, "dotranslate_%d", ++dotranslate_count);
-                                               def->name = strdup(buf);
-                                       }
-
-                                       if (pr_immediate_type->type == ev_float)
-                                               G_INT(def->ofs) = (int)pr_immediate._float;
-                                       else if (pr_immediate_type->type != ev_string)
-                                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-                               }
-                               else
-                                       QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
-
-                               if(dotranslate)
-                                       QCC_PR_Expect(")");
-                               continue;
-                       }
-                       else if (type->type == ev_float)
-                       {
-                               if (arraysize>=1 && QCC_PR_CheckToken("{"))
-                               {
-                                       int i;
-                                       for (i = 0; i < arraysize; i++)
-                                       {
-                                               if (pr_immediate_type->type != ev_float)
-                                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-                                               (((float *)qcc_pr_globals)[def->ofs+i]) = pr_immediate._float;
-                                               QCC_PR_Lex ();
-
-                                               if (!QCC_PR_CheckToken(","))
-                                                       break;
-                                       }
-                                       QCC_PR_Expect("}");
-
-                                       continue;
-                               }
-                               else if (arraysize<=1)
-                               {
-                                       if (isvar)
-                                               def->constant = false;
-                                       else
-                                               def->constant = true;
-
-                                       def->initialized = 1;
-
-                                       if (pr_immediate_type->type != ev_float)
-                                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-
-                                       if (def->constant && opt_dupconstdefs)
-                                       {
-                                               if (def->ofs == oldglobals)
-                                               {
-                                                       if (Hash_GetKey(&floatconstdefstable, *(int*)&pr_immediate._float))
-                                                               optres_dupconstdefs++;
-                                                       QCC_FreeOffset(def->ofs, def->type->size);
-                                                       d = QCC_MakeFloatDef(pr_immediate._float);
-                                                       d->references++;
-                                                       def->ofs = d->ofs;
-                                                       QCC_PR_Lex();
-                                                       continue;
-                                               }
-                                       }
-
-                                       (((float *)qcc_pr_globals)[def->ofs]) = pr_immediate._float;
-                                       QCC_PR_Lex ();
-
-                                       continue;
-                               }
-                               else
-                                       QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
-                       }
-                       else if (type->type == ev_vector)
-                       {
-                               if (arraysize>=1 && QCC_PR_CheckToken("{"))
-                               {
-                                       int i;
-                                       for (i = 0; i < arraysize; i++)
-                                       {
-                                               if (pr_immediate_type->type != ev_vector)
-                                                       QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-                                               (((float *)qcc_pr_globals)[def->ofs+i*3+0]) = pr_immediate.vector[0];
-                                               (((float *)qcc_pr_globals)[def->ofs+i*3+1]) = pr_immediate.vector[1];
-                                               (((float *)qcc_pr_globals)[def->ofs+i*3+2]) = pr_immediate.vector[2];
-                                               QCC_PR_Lex ();
-
-                                               if (!QCC_PR_CheckToken(","))
-                                                       break;
-                                       }
-                                       QCC_PR_Expect("}");
-
-                                       continue;
-                               }
-                               else if (arraysize<=1)
-                               {
-                                       if (isvar)
-                                               def->constant = false;
-                                       else
-                                               def->constant = true;
-                                       def->initialized = 1;
-
-                                       if (pr_immediate_type->type != ev_vector)
-                                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
-                                       (((float *)qcc_pr_globals)[def->ofs+0]) = pr_immediate.vector[0];
-                                       (((float *)qcc_pr_globals)[def->ofs+1]) = pr_immediate.vector[1];
-                                       (((float *)qcc_pr_globals)[def->ofs+2]) = pr_immediate.vector[2];
-                                       QCC_PR_Lex ();
-
-                                       continue;
-                               }
-                               else
-                                       QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
-                       }
-                       else if (pr_token_type == tt_name)
-                       {
-//                             if (pr_scope)//create a new instance, emit a copy op
-//                             {
-//                                     QCC_PR_ParseError ("name defined for local : %s", name);
-//                             }
-//                             else
-                               {
-                                       d = QCC_PR_GetDef (NULL, pr_token, pr_scope, false, 0, false);
-                                       if (!d)
-                                               QCC_PR_ParseError (ERR_NOTDEFINED, "initialisation name not defined : %s", pr_token);
-                                       if (!d->constant)
-                                       {
-                                               QCC_PR_ParseWarning (WARN_NOTCONSTANT, "initialisation name not a constant : %s", pr_token);
-                                               QCC_PR_ParsePrintDef(WARN_NOTCONSTANT, d);
-                                       }
-                                       memcpy (def, d, sizeof(*d));
-                                       def->name = name;
-                                       def->initialized = true;
-                               }
-                       }
-                       else if (pr_token_type != tt_immediate)
-                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "not an immediate for %s - %s", name, pr_token);
-                       else if (pr_immediate_type->type != type->type)
-                               QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s - %s", name, pr_token);
-                       else
-                               memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
-
-                       if (isvar)
-                               def->constant = false;
-                       else
-                               def->constant = true;
-                       def->initialized = true;
-                       QCC_PR_Lex ();
+                       QCC_PR_ParseInitializerDef(def, isvar, isconstant);
                }
                else
                {
@@ -9723,7 +9392,13 @@ void QCC_PR_ParseDefs (char *classname)
                                def->constant = isconstant;
                }
 
-
+               d = def;
+               while (d != def->deftail)
+               {
+                       d = d->next;
+                       d->constant = def->constant;
+                       d->initialized = def->initialized;
+               }
        } while (QCC_PR_CheckToken (","));
 
        if (type->type == ev_function)
@@ -9817,7 +9492,6 @@ pbool QCC_Include(char *filename)
        int opr_source_line;
        char *ocompilingfile;
        struct qcc_includechunk_s *oldcurrentchunk;
-       extern struct qcc_includechunk_s *currentchunk;
 
        ocompilingfile = compilingfile;
        os_file = s_file;