]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - exec.c
Fix unary negation (-)
[xonotic/gmqcc.git] / exec.c
diff --git a/exec.c b/exec.c
index d614ebf58305351868c69f0c0dba0ad39a2960ba..b24cda17edf74a44cf540fcbf54a49aee7f6c878 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014, 2015
  *     Wolfgang Bumiller
  *     Dale Weiler
  *
  */
 #ifndef QCVM_LOOP
 #include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
 
 #include "gmqcc.h"
 
@@ -37,7 +36,7 @@ static void loaderror(const char *fmt, ...)
     va_start(ap, fmt);
     vprintf(fmt, ap);
     va_end(ap);
-    printf(": %s\n", platform_strerror(err));
+    printf(": %s\n", util_strerror(err));
 }
 
 static void qcvmerror(qc_program_t *prog, const char *fmt, ...)
@@ -54,9 +53,17 @@ static void qcvmerror(qc_program_t *prog, const char *fmt, ...)
 
 qc_program_t* prog_load(const char *filename, bool skipversion)
 {
-    qc_program_t   *prog;
     prog_header_t   header;
-    FILE         *file  = fs_file_open(filename, "rb");
+    qc_program_t   *prog;
+    size_t          i;
+    fs_file_t      *file  = fs_file_open(filename, "rb");
+
+    /* we need all those in order to support INSTR_STATE: */
+    bool            has_self      = false,
+                    has_time      = false,
+                    has_think     = false,
+                    has_nextthink = false,
+                    has_frame     = false;
 
     if (!file)
         return NULL;
@@ -67,6 +74,8 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
         return NULL;
     }
 
+    util_swap_header(&header);
+
     if (!skipversion && header.version != 6) {
         loaderror("header says this is a version %i progs, we need version 6\n", header.version);
         fs_file_close(file);
@@ -115,6 +124,12 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
     read_data1(strings);
     read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
 
+    util_swap_statements (prog->code);
+    util_swap_defs_fields(prog->defs);
+    util_swap_defs_fields(prog->fields);
+    util_swap_functions  (prog->functions);
+    util_swap_globals    (prog->globals);
+
     fs_file_close(file);
 
     /* profile counters */
@@ -130,6 +145,36 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
     memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
     prog->entities = 1;
 
+    /* cache some globals and fields from names */
+    for (i = 0; i < vec_size(prog->defs); ++i) {
+        const char *name = prog_getstring(prog, prog->defs[i].name);
+        if      (!strcmp(name, "self")) {
+            prog->cached_globals.self = prog->defs[i].offset;
+            has_self = true;
+        }
+        else if (!strcmp(name, "time")) {
+            prog->cached_globals.time = prog->defs[i].offset;
+            has_time = true;
+        }
+    }
+    for (i = 0; i < vec_size(prog->fields); ++i) {
+        const char *name = prog_getstring(prog, prog->fields[i].name);
+        if      (!strcmp(name, "think")) {
+            prog->cached_fields.think     = prog->fields[i].offset;
+            has_think = true;
+        }
+        else if (!strcmp(name, "nextthink")) {
+            prog->cached_fields.nextthink = prog->fields[i].offset;
+            has_nextthink = true;
+        }
+        else if (!strcmp(name, "frame")) {
+            prog->cached_fields.frame     = prog->fields[i].offset;
+            has_frame = true;
+        }
+    }
+    if (has_self && has_time && has_think && has_nextthink && has_frame)
+        prog->supports_state = true;
+
     return prog;
 
 error:
@@ -352,7 +397,7 @@ static void trace_print_global(qc_program_t *prog, unsigned int glob, int vtype)
 done:
     if (len < (int)sizeof(spaces)-1) {
         spaces[sizeof(spaces)-1-len] = 0;
-        fs_file_puts(stdout, spaces);
+        fs_file_puts((fs_file_t*)stdout, spaces);
         spaces[sizeof(spaces)-1-len] = ' ';
     }
 }
@@ -588,7 +633,6 @@ cleanup:
  * main for when building the standalone executor
  */
 
-#if defined(QCVM_EXECUTOR)
 #include <math.h>
 
 const char *type_name[TYPE_COUNT] = {
@@ -623,7 +667,7 @@ static qcvm_parameter *main_params = NULL;
     if (prog->argc != (num)) {                                                 \
         prog->vmerror++;                                                       \
         fprintf(stderr, "ERROR: invalid number of arguments for %s: %i, expected %i\n", \
-        __FUNCTION__, prog->argc, (num));                                      \
+        __func__, prog->argc, (num));                                      \
         return -1;                                                             \
     }                                                                          \
 } while (0)
@@ -661,7 +705,7 @@ static int qc_ftos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    platform_snprintf(buffer, sizeof(buffer), "%g", num->_float);
+    util_snprintf(buffer, sizeof(buffer), "%g", num->_float);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -683,7 +727,7 @@ static int qc_vtos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    platform_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]);
+    util_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -695,7 +739,7 @@ static int qc_etos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    platform_snprintf(buffer, sizeof(buffer), "%i", num->_int);
+    util_snprintf(buffer, sizeof(buffer), "%i", num->_int);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -816,6 +860,16 @@ static int qc_floor(qc_program_t *prog) {
     return 0;
 }
 
+static int qc_pow(qc_program_t *prog) {
+    qcany_t *base, *exp, out;
+    CheckArgs(2);
+    base = GetArg(0);
+    exp = GetArg(1);
+    out._float = powf(base->_float, exp->_float);
+    Return(out);
+    return 0;
+}
+
 static prog_builtin_t qc_builtins[] = {
     NULL,
     &qc_print,       /*   1   */
@@ -831,7 +885,8 @@ static prog_builtin_t qc_builtins[] = {
     &qc_strcmp,      /*   11  */
     &qc_normalize,   /*   12  */
     &qc_sqrt,        /*   13  */
-    &qc_floor        /*   14  */
+    &qc_floor,       /*   14  */
+    &qc_pow          /*   15  */
 };
 
 static const char *arg0 = NULL;
@@ -877,7 +932,7 @@ static void prog_main_setparams(qc_program_t *prog) {
         arg->vector[2] = 0;
         switch (main_params[i].vtype) {
             case TYPE_VECTOR:
-                (void)platform_sscanf(main_params[i].value, " %f %f %f ",
+                (void)util_sscanf(main_params[i].value, " %f %f %f ",
                                        &arg->vector[0],
                                        &arg->vector[1],
                                        &arg->vector[2]);
@@ -895,7 +950,7 @@ static void prog_main_setparams(qc_program_t *prog) {
     }
 }
 
-void prog_disasm_function(qc_program_t *prog, size_t id);
+static void prog_disasm_function(qc_program_t *prog, size_t id);
 
 int main(int argc, char **argv) {
     size_t      i;
@@ -916,7 +971,7 @@ int main(int argc, char **argv) {
 
     if (argc < 2) {
         usage();
-        exit(1);
+        exit(EXIT_FAILURE);
     }
 
     while (argc > 1) {
@@ -925,7 +980,7 @@ int main(int argc, char **argv) {
             !strcmp(argv[1], "--help"))
         {
             usage();
-            exit(0);
+            exit(EXIT_SUCCESS);
         }
         else if (!strcmp(argv[1], "-v")) {
             ++opts_v;
@@ -939,7 +994,7 @@ int main(int argc, char **argv) {
                     ++opts_v;
                 else {
                     usage();
-                    exit(1);
+                    exit(EXIT_FAILURE);
                 }
             }
             --argc;
@@ -949,7 +1004,7 @@ int main(int argc, char **argv) {
                  !strcmp(argv[1], "--version"))
         {
             version();
-            exit(0);
+            exit(EXIT_SUCCESS);
         }
         else if (!strcmp(argv[1], "-trace")) {
             --argc;
@@ -978,7 +1033,7 @@ int main(int argc, char **argv) {
             ++argv;
             if (argc <= 1) {
                 usage();
-                exit(1);
+                exit(EXIT_FAILURE);
             }
             vec_push(dis_list, argv[1]);
             --argc;
@@ -1021,7 +1076,7 @@ int main(int argc, char **argv) {
             ++argv;
             if (argc < 2) {
                 usage();
-                exit(1);
+                exit(EXIT_FAILURE);
             }
             p.value = argv[1];
 
@@ -1038,7 +1093,7 @@ int main(int argc, char **argv) {
             if (progsfile) {
                 fprintf(stderr, "only 1 program file may be specified\n");
                 usage();
-                exit(1);
+                exit(EXIT_FAILURE);
             }
             progsfile = argv[1];
             --argc;
@@ -1048,7 +1103,7 @@ int main(int argc, char **argv) {
         {
             fprintf(stderr, "unknown parameter: %s\n", argv[1]);
             usage();
-            exit(1);
+            exit(EXIT_FAILURE);
         }
     }
 
@@ -1061,13 +1116,13 @@ int main(int argc, char **argv) {
     if (!progsfile) {
         fprintf(stderr, "must specify a program to execute\n");
         usage();
-        exit(1);
+        exit(EXIT_FAILURE);
     }
 
     prog = prog_load(progsfile, noexec);
     if (!prog) {
         fprintf(stderr, "failed to load program '%s'\n", progsfile);
-        exit(1);
+        exit(EXIT_FAILURE);
     }
 
     prog->builtins       = qc_builtins;
@@ -1157,7 +1212,7 @@ int main(int argc, char **argv) {
     if (opts_printfuns) {
         for (i = 0; i < vec_size(prog->functions); ++i) {
             int32_t a;
-            printf("Function: %-16s taking %i parameters:(",
+            printf("Function: %-16s taking %u parameters:(",
                    prog_getstring(prog, prog->functions[i].name),
                    (unsigned int)prog->functions[i].nargs);
             for (a = 0; a < prog->functions[i].nargs; ++a) {
@@ -1210,7 +1265,7 @@ int main(int argc, char **argv) {
     return 0;
 }
 
-void prog_disasm_function(qc_program_t *prog, size_t id) {
+static void prog_disasm_function(qc_program_t *prog, size_t id) {
     prog_section_function_t *fdef = prog->functions + id;
     prog_section_statement_t *st;
 
@@ -1227,7 +1282,6 @@ void prog_disasm_function(qc_program_t *prog, size_t id) {
         ++st;
     }
 }
-#endif
 #else /* !QCVM_LOOP */
 /*
  * Everything from here on is not including into the compilation of the
@@ -1558,8 +1612,24 @@ while (prog->vmerror == 0) {
             break;
 
         case INSTR_STATE:
-            qcvmerror(prog, "`%s` tried to execute a STATE operation", prog->filename);
+        {
+            qcfloat_t *nextthink;
+            qcfloat_t *time;
+            qcfloat_t *frame;
+            if (!prog->supports_state) {
+                qcvmerror(prog, "`%s` tried to execute a STATE operation but misses its defs!", prog->filename);
+                goto cleanup;
+            }
+            ed = prog_getedict(prog, prog->globals[prog->cached_globals.self]);
+            ((qcint_t*)ed)[prog->cached_fields.think] = OPB->function;
+
+            frame     = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.frame];
+            *frame    = OPA->_float;
+            nextthink = (qcfloat_t*)&((qcint_t*)ed)[prog->cached_fields.nextthink];
+            time      = (qcfloat_t*)(prog->globals + prog->cached_globals.time);
+            *nextthink = *time + 0.1;
             break;
+        }
 
         case INSTR_GOTO:
             st += st->o1.s1 - 1;    /* offset the s++ */