cleaned up pr_builtins array (now uses NULL instead of PF_fixme) and now reports...
[divverent/darkplaces.git] / pr_execprogram.h
1
2 // This code isn't #ifdef/#define protectable, don't try.
3
4                 while (1)
5                 {
6                         st++;
7                         if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
8                         {
9                                 pr_xstatement = st - pr_statements;
10                                 Host_Error ("runaway loop error");
11                         }
12
13 #if PRTRACE
14                         PR_PrintStatement (st);
15 #endif
16
17                         switch (st->op)
18                         {
19                         case OP_ADD_F:
20                                 OPC->_float = OPA->_float + OPB->_float;
21                                 break;
22                         case OP_ADD_V:
23                                 OPC->vector[0] = OPA->vector[0] + OPB->vector[0];
24                                 OPC->vector[1] = OPA->vector[1] + OPB->vector[1];
25                                 OPC->vector[2] = OPA->vector[2] + OPB->vector[2];
26                                 break;
27                         case OP_SUB_F:
28                                 OPC->_float = OPA->_float - OPB->_float;
29                                 break;
30                         case OP_SUB_V:
31                                 OPC->vector[0] = OPA->vector[0] - OPB->vector[0];
32                                 OPC->vector[1] = OPA->vector[1] - OPB->vector[1];
33                                 OPC->vector[2] = OPA->vector[2] - OPB->vector[2];
34                                 break;
35                         case OP_MUL_F:
36                                 OPC->_float = OPA->_float * OPB->_float;
37                                 break;
38                         case OP_MUL_V:
39                                 OPC->_float = OPA->vector[0]*OPB->vector[0] + OPA->vector[1]*OPB->vector[1] + OPA->vector[2]*OPB->vector[2];
40                                 break;
41                         case OP_MUL_FV:
42                                 OPC->vector[0] = OPA->_float * OPB->vector[0];
43                                 OPC->vector[1] = OPA->_float * OPB->vector[1];
44                                 OPC->vector[2] = OPA->_float * OPB->vector[2];
45                                 break;
46                         case OP_MUL_VF:
47                                 OPC->vector[0] = OPB->_float * OPA->vector[0];
48                                 OPC->vector[1] = OPB->_float * OPA->vector[1];
49                                 OPC->vector[2] = OPB->_float * OPA->vector[2];
50                                 break;
51                         case OP_DIV_F:
52                                 OPC->_float = OPA->_float / OPB->_float;
53                                 break;
54                         case OP_BITAND:
55                                 OPC->_float = (int)OPA->_float & (int)OPB->_float;
56                                 break;
57                         case OP_BITOR:
58                                 OPC->_float = (int)OPA->_float | (int)OPB->_float;
59                                 break;
60                         case OP_GE:
61                                 OPC->_float = OPA->_float >= OPB->_float;
62                                 break;
63                         case OP_LE:
64                                 OPC->_float = OPA->_float <= OPB->_float;
65                                 break;
66                         case OP_GT:
67                                 OPC->_float = OPA->_float > OPB->_float;
68                                 break;
69                         case OP_LT:
70                                 OPC->_float = OPA->_float < OPB->_float;
71                                 break;
72                         case OP_AND:
73                                 OPC->_float = OPA->_float && OPB->_float;
74                                 break;
75                         case OP_OR:
76                                 OPC->_float = OPA->_float || OPB->_float;
77                                 break;
78                         case OP_NOT_F:
79                                 OPC->_float = !OPA->_float;
80                                 break;
81                         case OP_NOT_V:
82                                 OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
83                                 break;
84                         case OP_NOT_S:
85                                 OPC->_float = !OPA->string || !*PR_GetString(OPA->string);
86                                 break;
87                         case OP_NOT_FNC:
88                                 OPC->_float = !OPA->function;
89                                 break;
90                         case OP_NOT_ENT:
91                                 OPC->_float = (OPA->edict == 0);
92                                 break;
93                         case OP_EQ_F:
94                                 OPC->_float = OPA->_float == OPB->_float;
95                                 break;
96                         case OP_EQ_V:
97                                 OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
98                                 break;
99                         case OP_EQ_S:
100                                 OPC->_float = !strcmp(PR_GetString(OPA->string),PR_GetString(OPB->string));
101                                 break;
102                         case OP_EQ_E:
103                                 OPC->_float = OPA->_int == OPB->_int;
104                                 break;
105                         case OP_EQ_FNC:
106                                 OPC->_float = OPA->function == OPB->function;
107                                 break;
108                         case OP_NE_F:
109                                 OPC->_float = OPA->_float != OPB->_float;
110                                 break;
111                         case OP_NE_V:
112                                 OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
113                                 break;
114                         case OP_NE_S:
115                                 OPC->_float = strcmp(PR_GetString(OPA->string),PR_GetString(OPB->string));
116                                 break;
117                         case OP_NE_E:
118                                 OPC->_float = OPA->_int != OPB->_int;
119                                 break;
120                         case OP_NE_FNC:
121                                 OPC->_float = OPA->function != OPB->function;
122                                 break;
123
124                 //==================
125                         case OP_STORE_F:
126                         case OP_STORE_ENT:
127                         case OP_STORE_FLD:              // integers
128                         case OP_STORE_S:
129                         case OP_STORE_FNC:              // pointers
130                                 OPB->_int = OPA->_int;
131                                 break;
132                         case OP_STORE_V:
133                                 OPB->ivector[0] = OPA->ivector[0];
134                                 OPB->ivector[1] = OPA->ivector[1];
135                                 OPB->ivector[2] = OPA->ivector[2];
136                                 break;
137
138                         case OP_STOREP_F:
139                         case OP_STOREP_ENT:
140                         case OP_STOREP_FLD:             // integers
141                         case OP_STOREP_S:
142                         case OP_STOREP_FNC:             // pointers
143 #if PRBOUNDSCHECK
144                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
145                                 {
146                                         pr_xstatement = st - pr_statements;
147                                         Host_Error("Progs attempted to write to an out of bounds edict (%i)\n", OPB->_int);
148                                         return;
149                                 }
150 #endif
151                                 ptr = (eval_t *)((qbyte *)sv.edictsfields + OPB->_int);
152                                 ptr->_int = OPA->_int;
153                                 break;
154                         case OP_STOREP_V:
155 #if PRBOUNDSCHECK
156                                 if (OPB->_int < 0 || OPB->_int + 12 > pr_edictareasize)
157                                 {
158                                         pr_xstatement = st - pr_statements;
159                                         Host_Error("Progs attempted to write to an out of bounds edict (%i)\n", OPB->_int);
160                                         return;
161                                 }
162 #endif
163                                 ptr = (eval_t *)((qbyte *)sv.edictsfields + OPB->_int);
164                                 ptr->vector[0] = OPA->vector[0];
165                                 ptr->vector[1] = OPA->vector[1];
166                                 ptr->vector[2] = OPA->vector[2];
167                                 break;
168
169                         case OP_ADDRESS:
170                                 pr_xstatement = st - pr_statements;
171 #if PRBOUNDSCHECK
172                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(progs->entityfields))
173                                 {
174                                         Host_Error("Progs attempted to address an invalid field (%i) in an edict\n", OPB->_int);
175                                         return;
176                                 }
177 #endif
178                                 if (OPA->edict == 0 && sv.state == ss_active)
179                                 {
180                                         Host_Error ("assignment to world entity");
181                                         return;
182                                 }
183                                 ed = PROG_TO_EDICT(OPA->edict);
184                                 OPC->_int = (qbyte *)((int *)ed->v + OPB->_int) - (qbyte *)sv.edictsfields;
185                                 break;
186
187                         case OP_LOAD_F:
188                         case OP_LOAD_FLD:
189                         case OP_LOAD_ENT:
190                         case OP_LOAD_S:
191                         case OP_LOAD_FNC:
192                                 pr_xstatement = st - pr_statements;
193 #if PRBOUNDSCHECK
194                                 if ((unsigned int)(OPB->_int) >= (unsigned int)(progs->entityfields))
195                                 {
196                                         Host_Error("Progs attempted to read an invalid field in an edict (%i)\n", OPB->_int);
197                                         return;
198                                 }
199 #endif
200                                 ed = PROG_TO_EDICT(OPA->edict);
201                                 OPC->_int = ((eval_t *)((int *)ed->v + OPB->_int))->_int;
202                                 break;
203
204                         case OP_LOAD_V:
205                                 pr_xstatement = st - pr_statements;
206 #if PRBOUNDSCHECK
207                                 if (OPB->_int < 0 || OPB->_int + 2 >= progs->entityfields)
208                                 {
209                                         Host_Error("Progs attempted to read an invalid field in an edict (%i)\n", OPB->_int);
210                                         return;
211                                 }
212 #endif
213                                 ed = PROG_TO_EDICT(OPA->edict);
214                                 OPC->vector[0] = ((eval_t *)((int *)ed->v + OPB->_int))->vector[0];
215                                 OPC->vector[1] = ((eval_t *)((int *)ed->v + OPB->_int))->vector[1];
216                                 OPC->vector[2] = ((eval_t *)((int *)ed->v + OPB->_int))->vector[2];
217                                 break;
218
219                 //==================
220
221                         case OP_IFNOT:
222                                 if (!OPA->_int)
223                                         st += st->b - 1;        // offset the s++
224                                 break;
225
226                         case OP_IF:
227                                 if (OPA->_int)
228                                         st += st->b - 1;        // offset the s++
229                                 break;
230
231                         case OP_GOTO:
232                                 st += st->a - 1;        // offset the s++
233                                 break;
234
235                         case OP_CALL0:
236                         case OP_CALL1:
237                         case OP_CALL2:
238                         case OP_CALL3:
239                         case OP_CALL4:
240                         case OP_CALL5:
241                         case OP_CALL6:
242                         case OP_CALL7:
243                         case OP_CALL8:
244                                 pr_xfunction->profile += profile - startprofile;
245                                 startprofile = profile;
246                                 pr_xstatement = st - pr_statements;
247                                 pr_argc = st->op - OP_CALL0;
248                                 if (!OPA->function)
249                                         Host_Error ("NULL function");
250
251                                 newf = &pr_functions[OPA->function];
252
253                                 if (newf->first_statement < 0)
254                                 {
255                                         // negative statements are built in functions
256                                         int builtinnumber = -newf->first_statement;
257                                         pr_xfunction->builtinsprofile++;
258                                         if (builtinnumber < pr_numbuiltins && pr_builtins[builtinnumber])
259                                                 pr_builtins[builtinnumber] ();
260                                         else
261                                                 Host_Error ("No such builtin #%i", builtinnumber);
262                                 }
263                                 else
264                                         st = pr_statements + PR_EnterFunction(newf);
265                                 break;
266
267                         case OP_DONE:
268                         case OP_RETURN:
269                                 pr_globals[OFS_RETURN] = pr_globals[(unsigned short) st->a];
270                                 pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short) st->a+1];
271                                 pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short) st->a+2];
272
273                                 st = pr_statements + PR_LeaveFunction();
274                                 if (pr_depth <= exitdepth)
275                                         return;         // all done
276                                 if (pr_trace != cachedpr_trace)
277                                         goto chooseexecprogram;
278                                 break;
279
280                         case OP_STATE:
281                                 ed = PROG_TO_EDICT(pr_global_struct->self);
282                                 ed->v->nextthink = pr_global_struct->time + 0.1;
283                                 ed->v->frame = OPA->_float;
284                                 ed->v->think = OPB->function;
285                                 break;
286
287 // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
288 /*
289                         case OP_ADD_I:
290                                 OPC->_int = OPA->_int + OPB->_int;
291                                 break;
292                         case OP_ADD_IF:
293                                 OPC->_int = OPA->_int + (int) OPB->_float;
294                                 break;
295                         case OP_ADD_FI:
296                                 OPC->_float = OPA->_float + (float) OPB->_int;
297                                 break;
298                         case OP_SUB_I:
299                                 OPC->_int = OPA->_int - OPB->_int;
300                                 break;
301                         case OP_SUB_IF:
302                                 OPC->_int = OPA->_int - (int) OPB->_float;
303                                 break;
304                         case OP_SUB_FI:
305                                 OPC->_float = OPA->_float - (float) OPB->_int;
306                                 break;
307                         case OP_MUL_I:
308                                 OPC->_int = OPA->_int * OPB->_int;
309                                 break;
310                         case OP_MUL_IF:
311                                 OPC->_int = OPA->_int * (int) OPB->_float;
312                                 break;
313                         case OP_MUL_FI:
314                                 OPC->_float = OPA->_float * (float) OPB->_int;
315                                 break;
316                         case OP_MUL_VI:
317                                 OPC->vector[0] = (float) OPB->_int * OPA->vector[0];
318                                 OPC->vector[1] = (float) OPB->_int * OPA->vector[1];
319                                 OPC->vector[2] = (float) OPB->_int * OPA->vector[2];
320                                 break;
321                         case OP_DIV_VF:
322                                 {
323                                         float temp = 1.0f / OPB->_float;
324                                         OPC->vector[0] = temp * OPA->vector[0];
325                                         OPC->vector[1] = temp * OPA->vector[1];
326                                         OPC->vector[2] = temp * OPA->vector[2];
327                                 }
328                                 break;
329                         case OP_DIV_I:
330                                 OPC->_int = OPA->_int / OPB->_int;
331                                 break;
332                         case OP_DIV_IF:
333                                 OPC->_int = OPA->_int / (int) OPB->_float;
334                                 break;
335                         case OP_DIV_FI:
336                                 OPC->_float = OPA->_float / (float) OPB->_int;
337                                 break;
338                         case OP_CONV_IF:
339                                 OPC->_float = OPA->_int;
340                                 break;
341                         case OP_CONV_FI:
342                                 OPC->_int = OPA->_float;
343                                 break;
344                         case OP_BITAND_I:
345                                 OPC->_int = OPA->_int & OPB->_int;
346                                 break;
347                         case OP_BITOR_I:
348                                 OPC->_int = OPA->_int | OPB->_int;
349                                 break;
350                         case OP_BITAND_IF:
351                                 OPC->_int = OPA->_int & (int)OPB->_float;
352                                 break;
353                         case OP_BITOR_IF:
354                                 OPC->_int = OPA->_int | (int)OPB->_float;
355                                 break;
356                         case OP_BITAND_FI:
357                                 OPC->_float = (int)OPA->_float & OPB->_int;
358                                 break;
359                         case OP_BITOR_FI:
360                                 OPC->_float = (int)OPA->_float | OPB->_int;
361                                 break;
362                         case OP_GE_I:
363                                 OPC->_float = OPA->_int >= OPB->_int;
364                                 break;
365                         case OP_LE_I:
366                                 OPC->_float = OPA->_int <= OPB->_int;
367                                 break;
368                         case OP_GT_I:
369                                 OPC->_float = OPA->_int > OPB->_int;
370                                 break;
371                         case OP_LT_I:
372                                 OPC->_float = OPA->_int < OPB->_int;
373                                 break;
374                         case OP_AND_I:
375                                 OPC->_float = OPA->_int && OPB->_int;
376                                 break;
377                         case OP_OR_I:
378                                 OPC->_float = OPA->_int || OPB->_int;
379                                 break;
380                         case OP_GE_IF:
381                                 OPC->_float = (float)OPA->_int >= OPB->_float;
382                                 break;
383                         case OP_LE_IF:
384                                 OPC->_float = (float)OPA->_int <= OPB->_float;
385                                 break;
386                         case OP_GT_IF:
387                                 OPC->_float = (float)OPA->_int > OPB->_float;
388                                 break;
389                         case OP_LT_IF:
390                                 OPC->_float = (float)OPA->_int < OPB->_float;
391                                 break;
392                         case OP_AND_IF:
393                                 OPC->_float = (float)OPA->_int && OPB->_float;
394                                 break;
395                         case OP_OR_IF:
396                                 OPC->_float = (float)OPA->_int || OPB->_float;
397                                 break;
398                         case OP_GE_FI:
399                                 OPC->_float = OPA->_float >= (float)OPB->_int;
400                                 break;
401                         case OP_LE_FI:
402                                 OPC->_float = OPA->_float <= (float)OPB->_int;
403                                 break;
404                         case OP_GT_FI:
405                                 OPC->_float = OPA->_float > (float)OPB->_int;
406                                 break;
407                         case OP_LT_FI:
408                                 OPC->_float = OPA->_float < (float)OPB->_int;
409                                 break;
410                         case OP_AND_FI:
411                                 OPC->_float = OPA->_float && (float)OPB->_int;
412                                 break;
413                         case OP_OR_FI:
414                                 OPC->_float = OPA->_float || (float)OPB->_int;
415                                 break;
416                         case OP_NOT_I:
417                                 OPC->_float = !OPA->_int;
418                                 break;
419                         case OP_EQ_I:
420                                 OPC->_float = OPA->_int == OPB->_int;
421                                 break;
422                         case OP_EQ_IF:
423                                 OPC->_float = (float)OPA->_int == OPB->_float;
424                                 break;
425                         case OP_EQ_FI:
426                                 OPC->_float = OPA->_float == (float)OPB->_int;
427                                 break;
428                         case OP_NE_I:
429                                 OPC->_float = OPA->_int != OPB->_int;
430                                 break;
431                         case OP_NE_IF:
432                                 OPC->_float = (float)OPA->_int != OPB->_float;
433                                 break;
434                         case OP_NE_FI:
435                                 OPC->_float = OPA->_float != (float)OPB->_int;
436                                 break;
437                         case OP_STORE_I:
438                                 OPB->_int = OPA->_int;
439                                 break;
440                         case OP_STOREP_I:
441 #if PRBOUNDSCHECK
442                                 if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
443                                 {
444                                         pr_xstatement = st - pr_statements;
445                                         Host_Error("Progs attempted to write to an out of bounds edict\n");
446                                         return;
447                                 }
448 #endif
449                                 ptr = (eval_t *)((qbyte *)sv.edictsfields + OPB->_int);
450                                 ptr->_int = OPA->_int;
451                                 break;
452                         case OP_LOAD_I:
453 #if PRBOUNDSCHECK
454                                 if (OPA->edict < 0 || OPA->edict >= pr_edictareasize)
455                                 {
456                                         pr_xstatement = st - pr_statements;
457                                         Host_Error("Progs attempted to read an out of bounds edict number\n");
458                                         return;
459                                 }
460                                 if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
461                                 {
462                                         pr_xstatement = st - pr_statements;
463                                         Host_Error("Progs attempted to read an invalid field in an edict\n");
464                                         return;
465                                 }
466 #endif
467                                 ed = PROG_TO_EDICT(OPA->edict);
468                                 OPC->_int = ((eval_t *)((int *)ed->v + OPB->_int))->_int;
469                                 break;
470
471                         case OP_GSTOREP_I:
472                         case OP_GSTOREP_F:
473                         case OP_GSTOREP_ENT:
474                         case OP_GSTOREP_FLD:            // integers
475                         case OP_GSTOREP_S:
476                         case OP_GSTOREP_FNC:            // pointers
477 #if PRBOUNDSCHECK
478                                 if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
479                                 {
480                                         pr_xstatement = st - pr_statements;
481                                         Host_Error("Progs attempted to write to an invalid indexed global\n");
482                                         return;
483                                 }
484 #endif
485                                 pr_globals[OPB->_int] = OPA->_float;
486                                 break;
487                         case OP_GSTOREP_V:
488 #if PRBOUNDSCHECK
489                                 if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
490                                 {
491                                         pr_xstatement = st - pr_statements;
492                                         Host_Error("Progs attempted to write to an invalid indexed global\n");
493                                         return;
494                                 }
495 #endif
496                                 pr_globals[OPB->_int  ] = OPA->vector[0];
497                                 pr_globals[OPB->_int+1] = OPA->vector[1];
498                                 pr_globals[OPB->_int+2] = OPA->vector[2];
499                                 break;
500
501                         case OP_GADDRESS:
502                                 i = OPA->_int + (int) OPB->_float;
503 #if PRBOUNDSCHECK
504                                 if (i < 0 || i >= pr_globaldefs)
505                                 {
506                                         pr_xstatement = st - pr_statements;
507                                         Host_Error("Progs attempted to address an out of bounds global\n");
508                                         return;
509                                 }
510 #endif
511                                 OPC->_float = pr_globals[i];
512                                 break;
513
514                         case OP_GLOAD_I:
515                         case OP_GLOAD_F:
516                         case OP_GLOAD_FLD:
517                         case OP_GLOAD_ENT:
518                         case OP_GLOAD_S:
519                         case OP_GLOAD_FNC:
520 #if PRBOUNDSCHECK
521                                 if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
522                                 {
523                                         pr_xstatement = st - pr_statements;
524                                         Host_Error("Progs attempted to read an invalid indexed global\n");
525                                         return;
526                                 }
527 #endif
528                                 OPC->_float = pr_globals[OPA->_int];
529                                 break;
530
531                         case OP_GLOAD_V:
532 #if PRBOUNDSCHECK
533                                 if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
534                                 {
535                                         pr_xstatement = st - pr_statements;
536                                         Host_Error("Progs attempted to read an invalid indexed global\n");
537                                         return;
538                                 }
539 #endif
540                                 OPC->vector[0] = pr_globals[OPA->_int  ];
541                                 OPC->vector[1] = pr_globals[OPA->_int+1];
542                                 OPC->vector[2] = pr_globals[OPA->_int+2];
543                                 break;
544
545                         case OP_BOUNDCHECK:
546                                 if (OPA->_int < 0 || OPA->_int >= st->b)
547                                 {
548                                         pr_xstatement = st - pr_statements;
549                                         Host_Error("Progs boundcheck failed at line number %d, value is < 0 or >= %d\n", st->b, st->c);
550                                         return;
551                                 }
552                                 break;
553
554 */
555
556                         default:
557                                 pr_xstatement = st - pr_statements;
558                                 Host_Error ("Bad opcode %i", st->op);
559                         }
560                 }
561