5 typedef struct prmemb_s {
9 void *PRHunkAlloc(progfuncs_t *progfuncs, int ammount)
12 ammount = sizeof(prmemb_t)+((ammount + 3)&~3);
13 mem = memalloc(ammount);
14 memset(mem, 0, ammount);
19 mem->level = ((prmemb_t *)memb)->level+1;
22 return ((char *)mem)+sizeof(prmemb_t);
25 int PRHunkMark(progfuncs_t *progfuncs)
27 return ((prmemb_t *)memb)->level;
29 void PRHunkFree(progfuncs_t *progfuncs, int mark)
34 if (memb->level <= mark)
44 /*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/
45 void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen)
49 for (i=0 ; i<maxedicts; i++)
51 e = (edictrun_t *)(prinst->edicttable[i]);
52 if (e && (char*)e->fields >= oldb && (char*)e->fields < oldb+oldlen)
53 e->fields = ((char*)e->fields - oldb) + newb;
56 if (progfuncs->stringtable >= oldb && progfuncs->stringtable < oldb+oldlen)
57 progfuncs->stringtable = (progfuncs->stringtable - oldb) + newb;
59 for (i=0; i < maxprogs; i++)
61 if ((char*)prinst->progstate[i].globals >= oldb && (char*)prinst->progstate[i].globals < oldb+oldlen)
62 prinst->progstate[i].globals = (float*)(((char*)prinst->progstate[i].globals - oldb) + newb);
63 if (prinst->progstate[i].strings >= oldb && prinst->progstate[i].strings < oldb+oldlen)
64 prinst->progstate[i].strings = (prinst->progstate[i].strings - oldb) + newb;
67 for (i = 0; i < numfields; i++)
69 if (field[i].name >= oldb && field[i].name < oldb+oldlen)
70 field[i].name = (field[i].name - oldb) + newb;
73 externs->addressablerelocated(progfuncs, oldb, newb, oldlen);
76 //for 64bit systems. :)
77 //addressable memory is memory available to the vm itself for writing.
78 //once allocated, it cannot be freed for the lifetime of the VM.
79 void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount)
81 ammount = (ammount + 4)&~3; //round up to 4
82 if (prinst->addressableused + ammount > prinst->addressablesize)
84 /*only do this if the caller states that it can cope with addressable-block relocations/resizes*/
85 if (externs->addressablerelocated)
90 int oldtot = addressablesize;
92 int newsize = (prinst->addressableused + ammount + 4096) & ~(4096-1);
93 newblock = VirtualAlloc (NULL, prinst->addressablesize, MEM_RESERVE, PAGE_NOACCESS);
96 VirtualAlloc (newblock, prinst->addressableused, MEM_COMMIT, PAGE_READWRITE);
97 memcpy(newblock, prinst->addressablehunk, prinst->addressableused);
99 VirtualAlloc (prinst->addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS);
101 VirtualFree (prinst->addressablehunk, 0, MEM_RELEASE);
103 PRAddressableRelocate(progfuncs, prinst->addressablehunk, newblock, prinst->addressableused);
104 prinst->addressablehunk = newblock;
105 prinst->addressablesize = newsize;
109 int newsize = (prinst->addressableused + ammount + 1024*1024) & ~(1024*1024-1);
110 newblock = realloc(newblock, prinst->addressablesize);
113 PRAddressableRelocate(progfuncs, prinst->addressablehunk, newblock, prinst->addressableused);
114 prinst->addressablehunk = newblock;
115 prinst->addressablesize = newsize;
120 if (prinst->addressableused + ammount > prinst->addressablesize)
121 Sys_Error("Not enough addressable memory for progs VM");
124 prinst->addressableused += ammount;
127 if (!VirtualAlloc (prinst->addressablehunk, prinst->addressableused, MEM_COMMIT, PAGE_READWRITE))
128 Sys_Error("VirtualAlloc failed. Blame windows.");
131 return &prinst->addressablehunk[prinst->addressableused-ammount];
135 #define MARKER 0xF1E3E3E7u
147 static void PF_fmem_unlink(progfuncs_t *pr, qcmemfreeblock_t *p)
149 qcmemfreeblock_t *np;
152 np = (qcmemfreeblock_t*)(pr->stringtable + p->prev);
156 pr->inst->mfreelist = p->next;
159 np = (qcmemfreeblock_t*)(pr->stringtable + p->next);
163 static void *PR_memalloc (progfuncs_t *progfuncs, unsigned int size)
165 qcmemfreeblock_t *p, *np;
166 qcmemusedblock_t *ub = NULL;
169 size = (size+sizeof(qcmemusedblock_t) + 63) & ~63;
171 b = prinst->mfreelist;
174 if (b < 0 || b >= prinst->addressableused)
176 printf("PF_memalloc: memory corruption\n");
177 PR_StackTrace(progfuncs);
180 p = (qcmemfreeblock_t*)(progfuncs->stringtable + b);
183 if (p->next && p->next < b + p->size ||
184 p->next >= prinst->addressableused ||
185 b + p->size >= prinst->addressableused ||
188 printf("PF_memalloc: memory corruption\n");
189 PR_StackTrace(progfuncs);
193 ub = (qcmemusedblock_t*)p;
194 if (p->size > size + 63)
196 /*make a new header just after it, with basically the same properties, and shift the important fields over*/
198 np = (qcmemfreeblock_t*)(progfuncs->stringtable + b + size);
201 np->size = p->size - size;
204 p = (qcmemfreeblock_t*)(progfuncs->stringtable + np->prev);
208 prinst->mfreelist = n;
211 p = (qcmemfreeblock_t*)(progfuncs->stringtable + np->next);
217 size = p->size; /*alloc the entire block*/
218 /*unlink this entry*/
219 PF_fmem_unlink(progfuncs, p);
225 /*assign more space*/
228 ub = PRAddressableExtend(progfuncs, size);
231 printf("PF_memalloc: memory exausted\n");
232 PR_StackTrace(progfuncs);
241 static void PR_memfree (progfuncs_t *progfuncs, void *memptr)
243 qcmemusedblock_t *ub;
244 qcmemfreeblock_t *p, *np;
247 unsigned int ptr = memptr?((char*)memptr - progfuncs->stringtable):0;
249 /*freeing NULL is ignored*/
252 if (ptr < sizeof(qcmemusedblock_t) || ptr >= prinst->addressableused)
254 printf("PF_memfree: pointer invalid - out of range (%u >= %u)\n", ptr, prinst->addressableused);
255 PR_StackTrace(progfuncs);
259 ub = (qcmemusedblock_t*)(progfuncs->stringtable + ptr);
261 ptr = (char*)ub - progfuncs->stringtable;
262 if (ub->marker != MARKER || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst->addressableused)
264 printf("PF_memfree: memory corruption or double free\n");
265 PR_StackTrace(progfuncs);
271 for (ln = prinst->mfreelist, l = 0; ;)
273 if (ln < 0 || ln >= prinst->addressableused)
275 printf("PF_memfree: memory corruption\n");
276 PR_StackTrace(progfuncs);
279 if (!ln || ln >= ptr)
281 np = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
282 if (l && l+np->size>ptr)
284 printf("PF_memfree: double free\n");
285 PR_StackTrace(progfuncs);
289 /*generate the free block, now we know its proper values*/
290 p = (qcmemfreeblock_t*)(progfuncs->stringtable + ptr);
295 /*update the next's previous*/
298 np = (qcmemfreeblock_t*)(progfuncs->stringtable + p->next);
301 /*extend this block and kill the next if they are adjacent*/
302 if (p->next == ptr + size)
305 PF_fmem_unlink(progfuncs, np);
309 /*update the link to get here*/
311 prinst->mfreelist = ptr;
314 np = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
317 /*we're adjacent to the previous block, so merge them by killing the newly freed region*/
318 if (l + np->size == ptr)
321 PF_fmem_unlink(progfuncs, p);
328 p = (qcmemfreeblock_t*)(progfuncs->stringtable + l);
333 void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
335 prinst->addressableused = 0;
336 if (totalammount < 0) //flush
338 totalammount = prinst->addressablesize;
343 if (prinst->addressablehunk && prinst->addressablesize != totalammount)
345 VirtualFree(prinst->addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
346 prinst->addressablehunk = NULL;
348 if (!prinst->addressablehunk)
349 prinst->addressablehunk = VirtualAlloc (prinst->addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS);
351 if (prinst->addressablehunk && prinst->addressablesize != totalammount)
353 free(prinst->addressablehunk);
354 prinst->addressablehunk = NULL;
356 if (!prinst->addressablehunk)
357 prinst->addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
358 // memset(prinst->addressablehunk, 0xff, totalammount);
360 if (!prinst->addressablehunk)
361 Sys_Error("Out of memory\n");
362 prinst->addressablesize = totalammount;
365 int PR_InitEnts(progfuncs_t *progfuncs, int max_ents)
367 maxedicts = max_ents;
371 max_fields_size = fields_size;
373 prinst->edicttable = PRHunkAlloc(progfuncs, maxedicts*sizeof(struct edicts_s *));
374 sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize);
375 prinst->edicttable[0] = sv_edicts;
376 ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableExtend(progfuncs, max_fields_size);
377 QC_ClearEdict(progfuncs, sv_edicts);
380 if (externs->entspawn)
381 externs->entspawn((struct edict_s *)sv_edicts, false);
383 return max_fields_size;
385 edictrun_t tempedict; //used as a safty buffer
386 float tempedictfields[2048];
388 void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs) //can be used to wipe all memory
395 progfuncs->stringtable = 0;
396 QC_StartShares(progfuncs);
397 QC_InitShares(progfuncs);
399 for ( i=1 ; i<maxedicts; i++)
401 e = (edictrun_t *)(prinst->edicttable[i]);
402 prinst->edicttable[i] = NULL;
408 PRHunkFree(progfuncs, 0); //clear mem - our hunk may not be a real hunk.
409 if (addressable_size<0)
410 addressable_size = 8*1024*1024;
411 PRAddressableFlush(progfuncs, addressable_size);
413 pr_progstate = PRHunkAlloc(progfuncs, sizeof(progstate_t) * max_progs);
415 /* for(a = 0; a < max_progs; a++)
417 pr_progstate[a].progs = NULL;
421 maxprogs = max_progs;
424 prinst->reorganisefields = false;
427 prinst->edicttable = &sv_edicts;
428 sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often
429 sv_edicts=(struct edict_s *)&tempedict;
430 tempedict.readonly = true;
431 tempedict.fields = tempedictfields;
432 tempedict.isfree = false;
437 struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum)
441 if (!current_progstate)
443 static float fallback[RESERVED_OFS];
444 return (struct globalvars_s *)fallback; //err.. you've not loaded one yet.
446 return (struct globalvars_s *)current_progstate->globals;
448 return (struct globalvars_s *)pr_progstate[pnum].globals;
451 struct entvars_s *PR_entvars (progfuncs_t *progfuncs, struct edict_s *ed)
453 if (((edictrun_t *)ed)->isfree)
456 return (struct entvars_s *)edvars(ed);
459 int PR_GetFuncArgCount(progfuncs_t *progfuncs, func_t func)
465 pnum = (func & 0xff000000)>>24;
466 fnum = (func & 0x00ffffff);
468 if (pnum >= (unsigned)maxprogs || !pr_progstate[pnum].functions)
470 else if (fnum >= pr_progstate[pnum].progs->numfunctions)
474 f = pr_progstate[pnum].functions + fnum;
479 func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum)
484 for (pnum = 0; (unsigned)pnum < maxprogs; pnum++)
486 if (!pr_progstate[pnum].progs)
488 f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
493 else if (pnum == PR_ANYBACK) //run backwards
495 for (pnum = maxprogs-1; pnum >= 0; pnum--)
497 if (!pr_progstate[pnum].progs)
499 f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
505 f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
512 switch(pr_progstate[pnum].structtype)
516 var16 = ED_FindTypeGlobalFromProgs16(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
518 return (f - pr_progstate[pnum].functions) | (pnum << 24);
519 return *(int *)&pr_progstate[pnum].globals[var16->ofs];
522 var32 = ED_FindTypeGlobalFromProgs32(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
524 return (f - pr_progstate[pnum].functions) | (pnum << 24);
525 return *(int *)&pr_progstate[pnum].globals[var32->ofs];
527 Sys_Error("Error with def size (PR_FindFunc)");
532 void QC_FindPrefixedGlobals(progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) )
537 int len = strlen(prefix);
540 for (pnum = 0; pnum < maxprogs; pnum++)
542 if (!pr_progstate[pnum].progs)
545 switch(pr_progstate[pnum].structtype)
549 for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
551 def16 = &pr_progstate[pnum].globaldefs16[i];
552 if (!strncmp(def16->s_name+progfuncs->stringtable,prefix, len))
553 found(progfuncs, def16->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type);
558 for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
560 def32 = &pr_progstate[pnum].globaldefs32[i];
561 if (!strncmp(def32->s_name+progfuncs->stringtable,prefix, len))
562 found(progfuncs, def32->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type);
569 eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum, etype_t *type)
574 if (pnum == PR_CURRENT)
575 pnum = pr_typecurrent;
579 for (i = 0; i < maxprogs; i++)
581 if (!pr_progstate[i].progs)
583 ev = PR_FindGlobal(progfuncs, globname, i, type);
589 if (pnum < 0 || (unsigned)pnum >= maxprogs || !pr_progstate[pnum].progs)
591 switch(pr_progstate[pnum].structtype)
595 if (!(var16 = ED_FindGlobalFromProgs16(progfuncs, globname, pnum)))
600 return (eval_t *)&pr_progstate[pnum].globals[var16->ofs];
603 if (!(var32 = ED_FindGlobalFromProgs32(progfuncs, globname, pnum)))
608 return (eval_t *)&pr_progstate[pnum].globals[var32->ofs];
610 Sys_Error("Error with def size (PR_FindGlobal)");
614 void SetGlobalEdict(progfuncs_t *progfuncs, struct edict_s *ed, int ofs)
616 ((int*)pr_globals)[ofs] = EDICT_TO_PROG(progfuncs, ed);
619 char *PR_VarString (progfuncs_t *progfuncs, int first)
622 static char out[1024];
626 for (i=first ; i<pr_argc ; i++)
628 if (G_STRING(OFS_PARM0+i*3))
630 s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable;
631 if (strlen(out) + strlen(s) + 1 >= sizeof(out))
639 int PR_QueryField (progfuncs_t *progfuncs, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache)
642 var = ED_FieldAtOfs(progfuncs, fieldoffset);
647 *type = var->type & ~(DEF_SAVEGLOBAL|DEF_SHARED);
652 fieldcache->ofs32 = var;
653 fieldcache->varname = var->name;
659 eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *name, evalc_t *cache)
664 var = ED_FindField(progfuncs, name);
667 return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
671 cache->varname = name;
672 var = ED_FindField(progfuncs, name);
679 cache->varname = var->name;
681 return (void*)~0; //something not null
682 return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
684 if (cache->ofs32 == NULL)
686 return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[cache->ofs32->ofs]);
689 struct edict_s *ProgsToEdict (progfuncs_t *progfuncs, int progs)
691 if ((unsigned)progs >= (unsigned)maxedicts)
693 printf("Bad entity index %i\n", progs);
696 return (struct edict_s *)PROG_TO_EDICT(progfuncs, progs);
698 int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed)
700 return EDICT_TO_PROG(progfuncs, ed);
703 string_t PR_StringToProgs (progfuncs_t *progfuncs, char *str)
711 if (str >= progfuncs->stringtable && str < progfuncs->stringtable + prinst->addressableused)
712 return str - progfuncs->stringtable;
714 for (i = prinst->numallocedstrings-1; i >= 0; i--)
716 if (prinst->allocedstrings[i] == str)
717 return (string_t)((unsigned int)i | 0x80000000);
718 if (!prinst->allocedstrings[i])
725 prinst->allocedstrings[i] = str;
726 return (string_t)((unsigned int)i | 0x80000000);
729 prinst->maxallocedstrings += 1024;
730 ntable = memalloc(sizeof(char*) * prinst->maxallocedstrings);
731 memcpy(ntable, prinst->allocedstrings, sizeof(char*) * prinst->numallocedstrings);
732 memset(ntable + prinst->numallocedstrings, 0, sizeof(char*) * (prinst->maxallocedstrings - prinst->numallocedstrings));
733 prinst->numallocedstrings = prinst->maxallocedstrings;
734 if (prinst->allocedstrings)
735 memfree(prinst->allocedstrings);
736 prinst->allocedstrings = ntable;
738 for (i = prinst->numallocedstrings-1; i >= 0; i--)
740 if (!prinst->allocedstrings[i])
742 prinst->allocedstrings[i] = str;
743 return (string_t)((unsigned int)i | 0x80000000);
750 char *PR_RemoveProgsString (progfuncs_t *progfuncs, string_t str)
754 //input string is expected to be an allocated string
755 //if its a temp, or a constant, just return NULL.
756 if ((unsigned int)str & 0xc0000000)
758 if ((unsigned int)str & 0x80000000)
760 int i = str & ~0x80000000;
761 if (i >= prinst->numallocedstrings)
766 if (prinst->allocedstrings[i])
768 ret = prinst->allocedstrings[i];
769 prinst->allocedstrings[i] = NULL; //remove it
775 return NULL; //urm, was freed...
783 char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str)
785 if ((unsigned int)str & 0xc0000000)
787 if ((unsigned int)str & 0x80000000)
789 int i = str & ~0x80000000;
790 if (i >= prinst->numallocedstrings)
792 printf("invalid string %x\n", str);
793 PR_StackTrace(progfuncs);
797 if (prinst->allocedstrings[i])
798 return prinst->allocedstrings[i];
801 printf("invalid string %x\n", str);
802 PR_StackTrace(progfuncs);
804 return ""; //urm, was freed...
807 if ((unsigned int)str & 0x40000000)
809 int i = str & ~0x40000000;
810 if (i >= prinst->numtempstrings)
812 printf("invalid temp string %x\n", str);
813 PR_StackTrace(progfuncs);
817 return prinst->tempstrings[i];
821 if ((unsigned int)str >= (unsigned int)prinst->addressableused)
823 printf("invalid string offset %x\n", str);
824 PR_StackTrace(progfuncs);
828 return progfuncs->stringtable + str;
832 string_t PR_AllocTempString (progfuncs_t *progfuncs, char *str)
841 if (prinst->numtempstrings == prinst->maxtempstrings)
843 newmax = prinst->maxtempstrings += 1024;
844 prinst->maxtempstrings += 1024;
845 ntable = memalloc(sizeof(char*) * newmax);
846 memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings);
847 prinst->maxtempstrings = newmax;
848 if (prinst->tempstrings)
849 memfree(prinst->tempstrings);
850 prinst->tempstrings = ntable;
853 i = prinst->numtempstrings;
857 prinst->numtempstrings++;
859 prinst->tempstrings[i] = memalloc(strlen(str)+1);
860 strcpy(prinst->tempstrings[i], str);
862 return (string_t)((unsigned int)i | 0x40000000);
864 string_t PR_AllocTempStringLen (progfuncs_t *progfuncs, char **str, unsigned int len)
873 if (prinst->numtempstrings == prinst->maxtempstrings)
875 newmax = prinst->maxtempstrings += 1024;
876 prinst->maxtempstrings += 1024;
877 ntable = memalloc(sizeof(char*) * newmax);
878 memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings);
879 prinst->maxtempstrings = newmax;
880 if (prinst->tempstrings)
881 memfree(prinst->tempstrings);
882 prinst->tempstrings = ntable;
885 i = prinst->numtempstrings;
889 prinst->numtempstrings++;
891 prinst->tempstrings[i] = memalloc(len);
892 *str = prinst->tempstrings[i];
894 return (string_t)((unsigned int)i | 0x40000000);
897 void PR_FreeTemps (progfuncs_t *progfuncs, int depth)
900 if (depth > prinst->numtempstrings)
902 Sys_Error("QC Temp stack inverted\n");
905 for (i = depth; i < prinst->numtempstrings; i++)
907 memfree(prinst->tempstrings[i]);
910 prinst->numtempstrings = depth;
914 struct qcthread_s *PR_ForkStack (progfuncs_t *progfuncs);
915 void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread);
916 void PR_AbortStack (progfuncs_t *progfuncs);
919 void RegisterBuiltin(progfuncs_t *progfncs, char *name, builtin_t func);
921 progfuncs_t deffuncs = {
954 NULL,//filefromnewprogs,
1008 QC_FindPrefixedGlobals,
1010 PR_AllocTempStringLen,
1015 //defs incase following structure is not passed.
1016 struct edict_s *safesv_edicts;
1017 int safesv_num_edicts;
1020 progexterns_t defexterns = {
1023 NULL, //char *(*ReadFile) (char *fname, void *buffer, int len);
1024 NULL, //int (*FileSize) (char *fname); //-1 if file does not exist
1025 NULL, //bool (*WriteFile) (char *name, void *data, int len);
1026 printf, //void (*printf) (char *, ...);
1027 (void*)exit, //void (*Sys_Error) (char *, ...);
1028 NULL, //void (*Abort) (char *, ...);
1029 sizeof(edictrun_t), //int edictsize; //size of edict_t
1031 NULL, //void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
1032 NULL, //bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
1033 NULL, //void (*stateop) (float var, func_t func);
1038 //used when loading a game
1039 NULL, //builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
1040 NULL, //void (*loadcompleate) (int edictsize); //notification to reset any pointers.
1043 (void*)malloc, //void *(*memalloc) (int size); //small string allocation malloced and freed randomly by the executor. (use memalloc if you want)
1044 free, //void (*memfree) (void * mem);
1047 NULL, //builtin_t *globalbuiltins; //these are available to all progs
1048 0, //int numglobalbuiltins;
1052 &safetime, //double *gametime;
1054 &safesv_edicts, //struct edict_s **sv_edicts;
1055 &safesv_num_edicts, //int *sv_num_edicts;
1057 NULL, //int (*useeditor) (char *filename, int line, int nump, char **parms);
1060 //progfuncs_t *progfuncs = NULL;
1063 #undef extensionbuiltin
1067 #undef sv_num_edicts
1070 #ifdef QCLIBDLL_EXPORTS
1071 __declspec(dllexport)
1073 void CloseProgs(progfuncs_t *inst)
1075 // extensionbuiltin_t *eb;
1076 void (VARGS *f) (void *);
1081 f = inst->parms->memfree;
1083 for ( i=1 ; i<inst->inst->maxedicts; i++)
1085 e = (edictrun_t *)(inst->inst->edicttable[i]);
1086 inst->inst->edicttable[i] = NULL;
1094 PRHunkFree(inst, 0);
1097 VirtualFree(inst->inst->addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p
1099 free(inst->inst->addressablehunk);
1102 if (inst->inst->allocedstrings)
1103 f(inst->inst->allocedstrings);
1104 inst->inst->allocedstrings = NULL;
1105 if (inst->inst->tempstrings)
1106 f(inst->inst->tempstrings);
1107 inst->inst->tempstrings = NULL;
1111 while(inst->prinst->extensionbuiltin)
1113 eb = inst->prinst->extensionbuiltin->prev;
1114 f(inst->prinst->extensionbuiltin);
1115 inst->prinst->extensionbuiltin = eb;
1118 if (inst->inst->field)
1119 f(inst->inst->field);
1120 if (inst->inst->shares)
1121 f(inst->inst->shares); //free memory
1126 void RegisterBuiltin(progfuncs_t *progfuncs, char *name, builtin_t func)
1129 extensionbuiltin_t *eb;
1130 eb = memalloc(sizeof(extensionbuiltin_t));
1131 eb->prev = progfuncs->prinst->extensionbuiltin;
1132 progfuncs->prinst->extensionbuiltin = eb;
1139 #define QCLIBINT //don't use dllspecifications
1142 #if defined(QCLIBDLL_EXPORTS)
1143 __declspec(dllexport)
1145 progfuncs_t * InitProgs(progexterns_t *ext)
1154 if (ext->progsversion > PROGSTRUCT_VERSION)
1157 for (i=0;i<sizeof(progexterns_t); i+=4) //make sure there are no items left out.
1158 if (!*(int *)((char *)ext+i))
1159 *(int *)((char *)ext+i) = *(int *)((char *)&defexterns+i);
1165 funcs = ext->memalloc(sizeof(progfuncs_t));
1166 memcpy(funcs, &deffuncs, sizeof(progfuncs_t));
1168 funcs->inst = ext->memalloc(sizeof(prinst_t));
1169 memset(funcs->inst,0, sizeof(prinst_t));
1171 funcs->pr_trace = &funcs->inst->pr_trace;
1172 funcs->progstate = &funcs->inst->progstate;
1173 funcs->callargc = &funcs->inst->pr_argc;
1198 void main (int argc, char **argv)
1203 funcs = InitProgs(&ext);
1204 if (funcs->PR_StartCompile(argc, argv))
1205 while(funcs->PR_ContinueCompile());