Merging in new-syntax
authorWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 14 Nov 2012 20:39:16 +0000 (21:39 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 14 Nov 2012 20:39:16 +0000 (21:39 +0100)
1  2 
Makefile
exec.c
gmqcc.h
lexer.c
lexer.h
main.c
parser.c

diff --cc Makefile
index c800ecaf6200af9d98b8002999e290736522e713,a44b6ea6322af4c92148a32a813ed2610154f0c9..ce0bc8697702db02caf715af8c13360dfa3dd5d1
+++ b/Makefile
@@@ -29,7 -28,7 +29,7 @@@ OBJ     = 
  OBJ_A = test/ast-test.o
  OBJ_I = test/ir-test.o
  OBJ_C = main.o lexer.o parser.o
--OBJ_X = exec-standalone.o util.o
++OBJ_X = exec-standalone.o util.o con.o
  
  #default is compiler only
  default: gmqcc
diff --cc exec.c
index ee0fb1b38d149936bac8809779bc6c041b9ebf72,71b8eba2c1486f5ffe40f5f465362826333822b1..872475befa00ac994caef9d899db9fb6172db755
--- 1/exec.c
--- 2/exec.c
+++ b/exec.c
@@@ -1055,300 -1073,299 +1073,299 @@@ while (1) 
  
              break;
  
 -              case INSTR_MUL_F:
 -                      OPC->_float = OPA->_float * OPB->_float;
 -                      break;
 -              case INSTR_MUL_V:
 -                      OPC->_float = OPA->vector[0]*OPB->vector[0] +
 -                                    OPA->vector[1]*OPB->vector[1] +
 -                                    OPA->vector[2]*OPB->vector[2];
 -                      break;
 -              case INSTR_MUL_FV:
 -                      OPC->vector[0] = OPA->_float * OPB->vector[0];
 -                      OPC->vector[1] = OPA->_float * OPB->vector[1];
 -                      OPC->vector[2] = OPA->_float * OPB->vector[2];
 -                      break;
 -              case INSTR_MUL_VF:
 -                      OPC->vector[0] = OPB->_float * OPA->vector[0];
 -                      OPC->vector[1] = OPB->_float * OPA->vector[1];
 -                      OPC->vector[2] = OPB->_float * OPA->vector[2];
 -                      break;
 -              case INSTR_DIV_F:
 -                      if (OPB->_float != 0.0f)
 -                              OPC->_float = OPA->_float / OPB->_float;
 -                      else
 -                              OPC->_float = 0;
 -                      break;
 -
 -              case INSTR_ADD_F:
 -                      OPC->_float = OPA->_float + OPB->_float;
 -                      break;
 -              case INSTR_ADD_V:
 -                      OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
 -                      OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
 -                      OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
 -                      break;
 -              case INSTR_SUB_F:
 -                      OPC->_float = OPA->_float - OPB->_float;
 -                      break;
 -              case INSTR_SUB_V:
 -                      OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
 -                      OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
 -                      OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
 -                      break;
 -
 -              case INSTR_EQ_F:
 -                      OPC->_float = (OPA->_float == OPB->_float);
 -                      break;
 -              case INSTR_EQ_V:
 -                      OPC->_float = ((OPA->vector[0] == OPB->vector[0]) &&
 -                                         (OPA->vector[1] == OPB->vector[1]) &&
 -                                         (OPA->vector[2] == OPB->vector[2]) );
 -                      break;
 -              case INSTR_EQ_S:
 -                      OPC->_float = !strcmp(prog_getstring(prog, OPA->string),
 -                                            prog_getstring(prog, OPB->string));
 -                      break;
 -              case INSTR_EQ_E:
 -                      OPC->_float = (OPA->_int == OPB->_int);
 -                      break;
 -              case INSTR_EQ_FNC:
 -                      OPC->_float = (OPA->function == OPB->function);
 -                      break;
 -              case INSTR_NE_F:
 -                      OPC->_float = (OPA->_float != OPB->_float);
 -                      break;
 -              case INSTR_NE_V:
 -                      OPC->_float = ((OPA->vector[0] != OPB->vector[0]) ||
 -                                     (OPA->vector[1] != OPB->vector[1]) ||
 -                                     (OPA->vector[2] != OPB->vector[2]) );
 -                      break;
 -              case INSTR_NE_S:
 -                      OPC->_float = !!strcmp(prog_getstring(prog, OPA->string),
 -                                             prog_getstring(prog, OPB->string));
 -                      break;
 -              case INSTR_NE_E:
 -                      OPC->_float = (OPA->_int != OPB->_int);
 -                      break;
 -              case INSTR_NE_FNC:
 -                      OPC->_float = (OPA->function != OPB->function);
 -                      break;
 -
 -              case INSTR_LE:
 -                      OPC->_float = (OPA->_float <= OPB->_float);
 -                      break;
 -              case INSTR_GE:
 -                      OPC->_float = (OPA->_float >= OPB->_float);
 -                      break;
 -              case INSTR_LT:
 -                      OPC->_float = (OPA->_float < OPB->_float);
 -                      break;
 -              case INSTR_GT:
 -                      OPC->_float = (OPA->_float > OPB->_float);
 -                      break;
 -
 -              case INSTR_LOAD_F:
 -              case INSTR_LOAD_S:
 -              case INSTR_LOAD_FLD:
 -              case INSTR_LOAD_ENT:
 -              case INSTR_LOAD_FNC:
 -                      if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 -                          qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
 -                              goto cleanup;
 -                      }
 -                      if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields)) {
 -                              qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 -                                        prog->filename,
 -                                        OPB->_int);
 -                              goto cleanup;
 -                      }
 -                      ed = prog_getedict(prog, OPA->edict);
 -                      OPC->_int = ((qcany*)( ((qcint*)ed) + OPB->_int ))->_int;
 -                      break;
 -              case INSTR_LOAD_V:
 -                      if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 -                          qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
 -                              goto cleanup;
 -                      }
 -                      if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfields)
 -                      {
 -                              qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 -                                        prog->filename,
 -                                        OPB->_int + 2);
 -                              goto cleanup;
 -                      }
 -                      ed = prog_getedict(prog, OPA->edict);
 -                      OPC->ivector[0] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[0];
 -                      OPC->ivector[1] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[1];
 -                      OPC->ivector[2] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[2];
 -                      break;
 -
 -              case INSTR_ADDRESS:
 -                      if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 -                              qcvmerror(prog, "prog `%s` attempted to address an out of bounds entity %i", prog->filename, OPA->edict);
 -                              goto cleanup;
 -                      }
 -                      if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
 -                      {
 -                              qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 -                                        prog->filename,
 -                                        OPB->_int);
 -                              goto cleanup;
 -                      }
 -
 -                      ed = prog_getedict(prog, OPA->edict);
 -                      OPC->_int = ((qcint*)ed) - prog->entitydata + OPB->_int;
 -                      break;
 -
 -              case INSTR_STORE_F:
 -              case INSTR_STORE_S:
 -              case INSTR_STORE_ENT:
 -              case INSTR_STORE_FLD:
 -              case INSTR_STORE_FNC:
 -                      OPB->_int = OPA->_int;
 -                      break;
 -              case INSTR_STORE_V:
 -                      OPB->ivector[0] = OPA->ivector[0];
 -                      OPB->ivector[1] = OPA->ivector[1];
 -                      OPB->ivector[2] = OPA->ivector[2];
 -                      break;
 -
 -              case INSTR_STOREP_F:
 -              case INSTR_STOREP_S:
 -              case INSTR_STOREP_ENT:
 -              case INSTR_STOREP_FLD:
 -              case INSTR_STOREP_FNC:
 -                      if (OPB->_int < 0 || OPB->_int >= prog->entitydata_count) {
 -                              qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
 -                              goto cleanup;
 -                      }
 -                      if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
 -                              qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
 -                                        prog->filename,
 -                                        prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
 -                                        OPB->_int);
 -                      ptr = (qcany*)(prog->entitydata + OPB->_int);
 -                      ptr->_int = OPA->_int;
 -                      break;
 -              case INSTR_STOREP_V:
 -                      if (OPB->_int < 0 || OPB->_int + 2 >= prog->entitydata_count) {
 -                              qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
 -                              goto cleanup;
 -                      }
 -                      if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
 -                              qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
 -                                        prog->filename,
 -                                        prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
 -                                        OPB->_int);
 -                      ptr = (qcany*)(prog->entitydata + OPB->_int);
 -                      ptr->ivector[0] = OPA->ivector[0];
 -                      ptr->ivector[1] = OPA->ivector[1];
 -                      ptr->ivector[2] = OPA->ivector[2];
 -                      break;
 -
 -              case INSTR_NOT_F:
 -                      OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
 -                      break;
 -              case INSTR_NOT_V:
 -                      OPC->_float = !OPA->vector[0] &&
 -                                    !OPA->vector[1] &&
 -                                    !OPA->vector[2];
 -                      break;
 -              case INSTR_NOT_S:
 -                      OPC->_float = !OPA->string ||
 -                                    !*prog_getstring(prog, OPA->string);
 -                      break;
 -              case INSTR_NOT_ENT:
 -                      OPC->_float = (OPA->edict == 0);
 -                      break;
 -              case INSTR_NOT_FNC:
 -                      OPC->_float = !OPA->function;
 -                      break;
 -
 -              case INSTR_IF:
 -                  /* this is consistent with darkplaces' behaviour */
 -                      if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
 -                      {
 -                              st += st->o2.s1 - 1;    /* offset the s++ */
 -                              if (++jumpcount >= maxjumps)
 -                                      qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 -                      }
 -                      break;
 -              case INSTR_IFNOT:
 -                      if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
 -                      {
 -                              st += st->o2.s1 - 1;    /* offset the s++ */
 -                              if (++jumpcount >= maxjumps)
 -                                      qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 -                      }
 -                      break;
 -
 -              case INSTR_CALL0:
 -              case INSTR_CALL1:
 -              case INSTR_CALL2:
 -              case INSTR_CALL3:
 -              case INSTR_CALL4:
 -              case INSTR_CALL5:
 -              case INSTR_CALL6:
 -              case INSTR_CALL7:
 -              case INSTR_CALL8:
 -                      prog->argc = st->opcode - INSTR_CALL0;
 -                      if (!OPA->function)
 -                              qcvmerror(prog, "NULL function in `%s`", prog->filename);
 -
 -                      if(!OPA->function || OPA->function >= (unsigned int)prog->functions_count)
 -                      {
 -                              qcvmerror(prog, "CALL outside the program in `%s` (%i)", prog->filename, (int)OPA->function);
 -                              goto cleanup;
 -                      }
 -
 -                      newf = &prog->functions[OPA->function];
 -                      newf->profile++;
 -
 -                      prog->statement = (st - prog->code) + 1;
 -
 -                      if (newf->entry < 0)
 -                      {
 -                              /* negative statements are built in functions */
 -                              int builtinnumber = -newf->entry;
 -                              if (builtinnumber < prog->builtins_count && prog->builtins[builtinnumber])
 -                                      prog->builtins[builtinnumber](prog);
 -                              else
 -                                      qcvmerror(prog, "No such builtin #%i in %s! Try updating your gmqcc sources",
 -                                                builtinnumber, prog->filename);
 -                      }
 -                      else
 -                              st = prog->code + prog_enterfunction(prog, newf) - 1; /* offset st++ */
 -                      if (prog->vmerror)
 -                              goto cleanup;
 -                      break;
 -
 -              case INSTR_STATE:
 -                  qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename);
 -                      break;
 -
 -              case INSTR_GOTO:
 -                      st += st->o1.s1 - 1;    /* offset the s++ */
 -                      if (++jumpcount == 10000000)
 -                                      qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 -                      break;
 -
 -              case INSTR_AND:
 -                      OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) &&
 -                                    FLOAT_IS_TRUE_FOR_INT(OPB->_int);
 -                      break;
 -              case INSTR_OR:
 -                      OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) ||
 -                                    FLOAT_IS_TRUE_FOR_INT(OPB->_int);
 -                      break;
 -
 -              case INSTR_BITAND:
 -                      OPC->_float = ((int)OPA->_float) & ((int)OPB->_float);
 -                      break;
 -              case INSTR_BITOR:
 -                      OPC->_float = ((int)OPA->_float) | ((int)OPB->_float);
 -                      break;
 +        case INSTR_MUL_F:
 +            OPC->_float = OPA->_float * OPB->_float;
 +            break;
 +        case INSTR_MUL_V:
 +            OPC->_float = OPA->vector[0]*OPB->vector[0] +
 +                          OPA->vector[1]*OPB->vector[1] +
 +                          OPA->vector[2]*OPB->vector[2];
 +            break;
 +        case INSTR_MUL_FV:
 +            OPC->vector[0] = OPA->_float * OPB->vector[0];
 +            OPC->vector[1] = OPA->_float * OPB->vector[1];
 +            OPC->vector[2] = OPA->_float * OPB->vector[2];
 +            break;
 +        case INSTR_MUL_VF:
 +            OPC->vector[0] = OPB->_float * OPA->vector[0];
 +            OPC->vector[1] = OPB->_float * OPA->vector[1];
 +            OPC->vector[2] = OPB->_float * OPA->vector[2];
 +            break;
 +        case INSTR_DIV_F:
 +            if (OPB->_float != 0.0f)
 +                OPC->_float = OPA->_float / OPB->_float;
 +            else
 +                OPC->_float = 0;
 +            break;
 +
 +        case INSTR_ADD_F:
 +            OPC->_float = OPA->_float + OPB->_float;
 +            break;
 +        case INSTR_ADD_V:
 +            OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
 +            OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
 +            OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
 +            break;
 +        case INSTR_SUB_F:
 +            OPC->_float = OPA->_float - OPB->_float;
 +            break;
 +        case INSTR_SUB_V:
 +            OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
 +            OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
 +            OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
 +            break;
 +
 +        case INSTR_EQ_F:
 +            OPC->_float = (OPA->_float == OPB->_float);
 +            break;
 +        case INSTR_EQ_V:
 +            OPC->_float = ((OPA->vector[0] == OPB->vector[0]) &&
 +                           (OPA->vector[1] == OPB->vector[1]) &&
 +                           (OPA->vector[2] == OPB->vector[2]) );
 +            break;
 +        case INSTR_EQ_S:
 +            OPC->_float = !strcmp(prog_getstring(prog, OPA->string),
 +                                  prog_getstring(prog, OPB->string));
 +            break;
 +        case INSTR_EQ_E:
 +            OPC->_float = (OPA->_int == OPB->_int);
 +            break;
 +        case INSTR_EQ_FNC:
 +            OPC->_float = (OPA->function == OPB->function);
 +            break;
 +        case INSTR_NE_F:
 +            OPC->_float = (OPA->_float != OPB->_float);
 +            break;
 +        case INSTR_NE_V:
 +            OPC->_float = ((OPA->vector[0] != OPB->vector[0]) ||
 +                           (OPA->vector[1] != OPB->vector[1]) ||
 +                           (OPA->vector[2] != OPB->vector[2]) );
 +            break;
 +        case INSTR_NE_S:
 +            OPC->_float = !!strcmp(prog_getstring(prog, OPA->string),
 +                                   prog_getstring(prog, OPB->string));
 +            break;
 +        case INSTR_NE_E:
 +            OPC->_float = (OPA->_int != OPB->_int);
 +            break;
 +        case INSTR_NE_FNC:
 +            OPC->_float = (OPA->function != OPB->function);
 +            break;
 +
 +        case INSTR_LE:
 +            OPC->_float = (OPA->_float <= OPB->_float);
 +            break;
 +        case INSTR_GE:
 +            OPC->_float = (OPA->_float >= OPB->_float);
 +            break;
 +        case INSTR_LT:
 +            OPC->_float = (OPA->_float < OPB->_float);
 +            break;
 +        case INSTR_GT:
 +            OPC->_float = (OPA->_float > OPB->_float);
 +            break;
 +
 +        case INSTR_LOAD_F:
 +        case INSTR_LOAD_S:
 +        case INSTR_LOAD_FLD:
 +        case INSTR_LOAD_ENT:
 +        case INSTR_LOAD_FNC:
 +            if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 +                qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
 +                goto cleanup;
 +            }
 +            if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields)) {
 +                qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 +                          prog->filename,
 +                          OPB->_int);
 +                goto cleanup;
 +            }
 +            ed = prog_getedict(prog, OPA->edict);
 +            OPC->_int = ((qcany*)( ((qcint*)ed) + OPB->_int ))->_int;
 +            break;
 +        case INSTR_LOAD_V:
 +            if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 +                qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
 +                goto cleanup;
 +            }
 +            if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfields)
 +            {
 +                qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 +                          prog->filename,
 +                          OPB->_int + 2);
 +                goto cleanup;
 +            }
 +            ed = prog_getedict(prog, OPA->edict);
 +            OPC->ivector[0] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[0];
 +            OPC->ivector[1] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[1];
 +            OPC->ivector[2] = ((qcany*)( ((qcint*)ed) + OPB->_int ))->ivector[2];
 +            break;
 +
 +        case INSTR_ADDRESS:
 +            if (OPA->edict < 0 || OPA->edict >= prog->entities) {
 +                qcvmerror(prog, "prog `%s` attempted to address an out of bounds entity %i", prog->filename, OPA->edict);
 +                goto cleanup;
 +            }
 +            if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
 +            {
 +                qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
 +                          prog->filename,
 +                          OPB->_int);
 +                goto cleanup;
 +            }
 +
 +            ed = prog_getedict(prog, OPA->edict);
-             OPC->_int = ((qcint*)ed) - prog->entitydata;
-             OPC->_int += OPB->_int;
++            OPC->_int = ((qcint*)ed) - prog->entitydata + OPB->_int;
 +            break;
 +
 +        case INSTR_STORE_F:
 +        case INSTR_STORE_S:
 +        case INSTR_STORE_ENT:
 +        case INSTR_STORE_FLD:
 +        case INSTR_STORE_FNC:
 +            OPB->_int = OPA->_int;
 +            break;
 +        case INSTR_STORE_V:
 +            OPB->ivector[0] = OPA->ivector[0];
 +            OPB->ivector[1] = OPA->ivector[1];
 +            OPB->ivector[2] = OPA->ivector[2];
 +            break;
 +
 +        case INSTR_STOREP_F:
 +        case INSTR_STOREP_S:
 +        case INSTR_STOREP_ENT:
 +        case INSTR_STOREP_FLD:
 +        case INSTR_STOREP_FNC:
 +            if (OPB->_int < 0 || OPB->_int >= prog->entitydata_count) {
 +                qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
 +                goto cleanup;
 +            }
 +            if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
 +                qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
 +                          prog->filename,
 +                          prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
 +                          OPB->_int);
 +            ptr = (qcany*)(prog->entitydata + OPB->_int);
 +            ptr->_int = OPA->_int;
 +            break;
 +        case INSTR_STOREP_V:
 +            if (OPB->_int < 0 || OPB->_int + 2 >= prog->entitydata_count) {
 +                qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
 +                goto cleanup;
 +            }
 +            if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
 +                qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
 +                          prog->filename,
 +                          prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
 +                          OPB->_int);
 +            ptr = (qcany*)(prog->entitydata + OPB->_int);
 +            ptr->ivector[0] = OPA->ivector[0];
 +            ptr->ivector[1] = OPA->ivector[1];
 +            ptr->ivector[2] = OPA->ivector[2];
 +            break;
 +
 +        case INSTR_NOT_F:
 +            OPC->_float = !FLOAT_IS_TRUE_FOR_INT(OPA->_int);
 +            break;
 +        case INSTR_NOT_V:
 +            OPC->_float = !OPA->vector[0] &&
 +                          !OPA->vector[1] &&
 +                          !OPA->vector[2];
 +            break;
 +        case INSTR_NOT_S:
 +            OPC->_float = !OPA->string ||
 +                          !*prog_getstring(prog, OPA->string);
 +            break;
 +        case INSTR_NOT_ENT:
 +            OPC->_float = (OPA->edict == 0);
 +            break;
 +        case INSTR_NOT_FNC:
 +            OPC->_float = !OPA->function;
 +            break;
 +
 +        case INSTR_IF:
 +            /* this is consistent with darkplaces' behaviour */
 +            if(FLOAT_IS_TRUE_FOR_INT(OPA->_int))
 +            {
 +                st += st->o2.s1 - 1;    /* offset the s++ */
 +                if (++jumpcount >= maxjumps)
 +                    qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 +            }
 +            break;
 +        case INSTR_IFNOT:
 +            if(!FLOAT_IS_TRUE_FOR_INT(OPA->_int))
 +            {
 +                st += st->o2.s1 - 1;    /* offset the s++ */
 +                if (++jumpcount >= maxjumps)
 +                    qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 +            }
 +            break;
 +
 +        case INSTR_CALL0:
 +        case INSTR_CALL1:
 +        case INSTR_CALL2:
 +        case INSTR_CALL3:
 +        case INSTR_CALL4:
 +        case INSTR_CALL5:
 +        case INSTR_CALL6:
 +        case INSTR_CALL7:
 +        case INSTR_CALL8:
 +            prog->argc = st->opcode - INSTR_CALL0;
 +            if (!OPA->function)
 +                qcvmerror(prog, "NULL function in `%s`", prog->filename);
 +
 +            if(!OPA->function || OPA->function >= (unsigned int)prog->functions_count)
 +            {
 +                qcvmerror(prog, "CALL outside the program in `%s`", prog->filename);
 +                goto cleanup;
 +            }
 +
 +            newf = &prog->functions[OPA->function];
 +            newf->profile++;
 +
 +            prog->statement = (st - prog->code) + 1;
 +
 +            if (newf->entry < 0)
 +            {
 +                /* negative statements are built in functions */
 +                int builtinnumber = -newf->entry;
 +                if (builtinnumber < prog->builtins_count && prog->builtins[builtinnumber])
 +                    prog->builtins[builtinnumber](prog);
 +                else
 +                    qcvmerror(prog, "No such builtin #%i in %s! Try updating your gmqcc sources",
 +                              builtinnumber, prog->filename);
 +            }
 +            else
 +                st = prog->code + prog_enterfunction(prog, newf) - 1; /* offset st++ */
 +            if (prog->vmerror)
 +                goto cleanup;
 +            break;
 +
 +        case INSTR_STATE:
 +            qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename);
 +            break;
 +
 +        case INSTR_GOTO:
 +            st += st->o1.s1 - 1;    /* offset the s++ */
 +            if (++jumpcount == 10000000)
 +                qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
 +            break;
 +
 +        case INSTR_AND:
 +            OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) &&
 +                          FLOAT_IS_TRUE_FOR_INT(OPB->_int);
 +            break;
 +        case INSTR_OR:
 +            OPC->_float = FLOAT_IS_TRUE_FOR_INT(OPA->_int) ||
 +                          FLOAT_IS_TRUE_FOR_INT(OPB->_int);
 +            break;
 +
 +        case INSTR_BITAND:
 +            OPC->_float = ((int)OPA->_float) & ((int)OPB->_float);
 +            break;
 +        case INSTR_BITOR:
 +            OPC->_float = ((int)OPA->_float) | ((int)OPB->_float);
 +            break;
      }
  }
  
diff --cc gmqcc.h
Simple merge
diff --cc lexer.c
Simple merge
diff --cc lexer.h
Simple merge
diff --cc main.c
index d8a097c446c5942c57b9b919479f937b8d36a3d0,773b08ed711e815c89da14e1c64235f649b49a2f..0b9d726744a4169220e92916c96899835ad3716f
--- 1/main.c
--- 2/main.c
+++ b/main.c
@@@ -175,16 -192,20 +192,20 @@@ static bool options_parse(int argc, cha
          if (argv[0][0] == '-') {
      /* All gcc-type long options */
              if (options_long_gcc("std", &argc, &argv, &argarg)) {
-                 if      (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default"))
+                 if      (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default")) {
+                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, true);
                      opts_standard = COMPILER_GMQCC;
-                 else if (!strcmp(argarg, "qcc"))
+                 } else if (!strcmp(argarg, "qcc")) {
+                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
                      opts_standard = COMPILER_QCC;
-                 else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc"))
+                 } else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc")) {
+                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
                      opts_standard = COMPILER_FTEQCC;
-                 else if (!strcmp(argarg, "qccx"))
+                 } else if (!strcmp(argarg, "qccx")) {
+                     options_set(opts_flags, ADJUST_VECTOR_FIELDS, false);
                      opts_standard = COMPILER_QCCX;
-                 else {
+                 else {
 -                    printf("Unknown standard: %s\n", argarg);
 +                    con_out("Unknown standard: %s\n", argarg);
                      return false;
                  }
                  continue;
diff --cc parser.c
index ce3c778a977a17418177af5545b6f337bf0170ec,0f354a7b1ce6c1605e971464bc3074dd43c664c1..534f007db4d2ba65d0071a8408088ec8e5346f2a
+++ b/parser.c
@@@ -1256,9 -1232,13 +1232,13 @@@ static ast_expression* parse_expression
              parseerror(parser, "internal error: '(' should be classified as operator");
              goto onerr;
          }
+         else if (parser->tok == '[') {
+             parseerror(parser, "internal error: '[' should be classified as operator");
+             goto onerr;
+         }
          else if (parser->tok == ')') {
              if (wantop) {
 -                DEBUGSHUNTDO(printf("do[op] )\n"));
 +                DEBUGSHUNTDO(con_out("do[op] )\n"));
                  --parens;
                  if (parens < 0)
                      break;
  
              if (op->id == opid1('(')) {
                  if (wantop) {
 -                    DEBUGSHUNTDO(printf("push [op] (\n"));
 +                    DEBUGSHUNTDO(con_out("push [op] (\n"));
                      ++parens;
                      /* we expected an operator, this is the function-call operator */
-                     if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 'f', sy.out_count-1))) {
+                     if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), SY_PAREN_FUNC, sy.out_count-1))) {
                          parseerror(parser, "out of memory");
                          goto onerr;
                      }
                          parseerror(parser, "out of memory");
                          goto onerr;
                      }
 -                    DEBUGSHUNTDO(printf("push [nop] (\n"));
 +                    DEBUGSHUNTDO(con_out("push [nop] (\n"));
                  }
                  wantop = false;
+             } else if (op->id == opid1('[')) {
+                 if (!wantop) {
+                     parseerror(parser, "unexpected array subscript");
+                     goto onerr;
+                 }
+                 ++parens;
+                 /* push both the operator and the paren, this makes life easier */
+                 if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
+                     goto onerr;
+                 if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), SY_PAREN_INDEX, 0)))
+                     goto onerr;
+                 wantop = false;
              } else {
 -                DEBUGSHUNTDO(printf("push operator %s\n", op->op));
 +                DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
                  if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
                      goto onerr;
                  wantop = false;
@@@ -3035,8 -3711,8 +3725,8 @@@ bool parser_finish(const char *output
              field = (ast_value*)parser->fields[i].var;
              isconst = field->isconst;
              field->isconst = false;
-             if (!ast_global_codegen((ast_value*)field, ir)) {
+             if (!ast_global_codegen((ast_value*)field, ir, true)) {
 -                printf("failed to generate field %s\n", field->name);
 +                con_out("failed to generate field %s\n", field->name);
                  ir_builder_delete(ir);
                  return false;
              }
                                                     "unused global: `%s`", asvalue->name);
                  }
              }
-             if (!ast_global_codegen(asvalue, ir)) {
+             if (!ast_global_codegen(asvalue, ir, false)) {
 -                printf("failed to generate global %s\n", parser->globals[i].name);
 +                con_out("failed to generate global %s\n", parser->globals[i].name);
                  ir_builder_delete(ir);
                  return false;
              }
          }
          for (i = 0; i < parser->imm_float_count; ++i) {
-             if (!ast_global_codegen(parser->imm_float[i], ir)) {
+             if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
 -                printf("failed to generate global %s\n", parser->imm_float[i]->name);
 +                con_out("failed to generate global %s\n", parser->imm_float[i]->name);
                  ir_builder_delete(ir);
                  return false;
              }
          }
          for (i = 0; i < parser->imm_string_count; ++i) {
-             if (!ast_global_codegen(parser->imm_string[i], ir)) {
+             if (!ast_global_codegen(parser->imm_string[i], ir, false)) {
 -                printf("failed to generate global %s\n", parser->imm_string[i]->name);
 +                con_out("failed to generate global %s\n", parser->imm_string[i]->name);
                  ir_builder_delete(ir);
                  return false;
              }
          }
          for (i = 0; i < parser->imm_vector_count; ++i) {
-             if (!ast_global_codegen(parser->imm_vector[i], ir)) {
+             if (!ast_global_codegen(parser->imm_vector[i], ir, false)) {
 -                printf("failed to generate global %s\n", parser->imm_vector[i]->name);
 +                con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
                  ir_builder_delete(ir);
                  return false;
              }
          }
+         for (i = 0; i < parser->globals_count; ++i) {
+             ast_value *asvalue;
+             if (!ast_istype(parser->globals[i].var, ast_value))
+                 continue;
+             asvalue = (ast_value*)(parser->globals[i].var);
+             if (asvalue->setter) {
+                 if (!ast_global_codegen(asvalue->setter, ir, false) ||
+                     !ast_function_codegen(asvalue->setter->constval.vfunc, ir) ||
+                     !ir_function_finalize(asvalue->setter->constval.vfunc->ir_func))
+                 {
+                     printf("failed to generate setter for %s\n", parser->globals[i].name);
+                     ir_builder_delete(ir);
+                     return false;
+                 }
+             }
+             if (asvalue->getter) {
+                 if (!ast_global_codegen(asvalue->getter, ir, false) ||
+                     !ast_function_codegen(asvalue->getter->constval.vfunc, ir) ||
+                     !ir_function_finalize(asvalue->getter->constval.vfunc->ir_func))
+                 {
+                     printf("failed to generate getter for %s\n", parser->globals[i].name);
+                     ir_builder_delete(ir);
+                     return false;
+                 }
+             }
+         }
+         for (i = 0; i < parser->fields_count; ++i) {
+             ast_value *asvalue;
+             asvalue = (ast_value*)(parser->fields[i].var->expression.next);
+             if (!ast_istype((ast_expression*)asvalue, ast_value))
+                 continue;
+             if (asvalue->expression.vtype != TYPE_ARRAY)
+                 continue;
+             if (asvalue->setter) {
+                 if (!ast_global_codegen(asvalue->setter, ir, false) ||
+                     !ast_function_codegen(asvalue->setter->constval.vfunc, ir) ||
+                     !ir_function_finalize(asvalue->setter->constval.vfunc->ir_func))
+                 {
+                     printf("failed to generate setter for %s\n", parser->fields[i].name);
+                     ir_builder_delete(ir);
+                     return false;
+                 }
+             }
+             if (asvalue->getter) {
+                 if (!ast_global_codegen(asvalue->getter, ir, false) ||
+                     !ast_function_codegen(asvalue->getter->constval.vfunc, ir) ||
+                     !ir_function_finalize(asvalue->getter->constval.vfunc->ir_func))
+                 {
+                     printf("failed to generate getter for %s\n", parser->fields[i].name);
+                     ir_builder_delete(ir);
+                     return false;
+                 }
+             }
+         }
          for (i = 0; i < parser->functions_count; ++i) {
              if (!ast_function_codegen(parser->functions[i], ir)) {
 -                printf("failed to generate function %s\n", parser->functions[i]->name);
 +                con_out("failed to generate function %s\n", parser->functions[i]->name);
                  ir_builder_delete(ir);
                  return false;
              }