]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/initlib.c
Better comment on my last change
[voretournament/voretournament.git] / misc / source / fteqcc-src / initlib.c
1 #define PROGSUSED
2 #include "progsint.h"
3 #include <stdlib.h>
4
5 typedef struct prmemb_s {
6         struct prmemb_s *prev;
7         int level;
8 } prmemb_t;
9 void *PRHunkAlloc(progfuncs_t *progfuncs, int ammount)
10 {
11         prmemb_t *mem;
12         ammount = sizeof(prmemb_t)+((ammount + 3)&~3);
13         mem = memalloc(ammount); 
14         memset(mem, 0, ammount);
15         mem->prev = memb;
16         if (!memb)
17                 mem->level = 1;
18         else
19                 mem->level = ((prmemb_t *)memb)->level+1;
20         memb = mem;
21
22         return ((char *)mem)+sizeof(prmemb_t);
23 }
24
25 int PRHunkMark(progfuncs_t *progfuncs)
26 {
27         return ((prmemb_t *)memb)->level;
28 }
29 void PRHunkFree(progfuncs_t *progfuncs, int mark)
30 {
31         prmemb_t *omem;
32         while(memb)
33         {
34                 if (memb->level <= mark)
35                         return;
36
37                 omem = memb;
38                 memb = memb->prev;
39                 memfree(omem);
40         }
41         return;
42 }
43
44 //for 64bit systems. :)
45 //addressable memory is memory available to the vm itself for writing.
46 //once allocated, it cannot be freed for the lifetime of the VM.
47 void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount)
48 {
49         ammount = (ammount + 4)&~3;     //round up to 4
50         if (addressableused + ammount > addressablesize)
51                 Sys_Error("Not enough addressable memory for progs VM");
52
53         addressableused += ammount;
54
55 #ifdef _WIN32
56         if (!VirtualAlloc (addressablehunk, addressableused, MEM_COMMIT, PAGE_READWRITE))
57                 Sys_Error("VirtualAlloc failed. Blame windows.");
58 #endif
59
60         return &addressablehunk[addressableused-ammount];
61 }
62
63 void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
64 {
65         addressableused = 0;
66         if (totalammount < 0)   //flush
67         {
68                 totalammount = addressablesize;
69 //              return;
70         }
71
72         if (addressablehunk)
73 #ifdef _WIN32
74         VirtualFree(addressablehunk, 0, MEM_RELEASE);   //doesn't this look complicated? :p
75         addressablehunk = VirtualAlloc (NULL, totalammount, MEM_RESERVE, PAGE_NOACCESS);
76 #else
77         free(addressablehunk);
78         addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
79 //      memset(addressablehunk, 0xff, totalammount);
80 #endif
81         if (!addressablehunk)
82                 Sys_Error("Out of memory\n");
83         addressablesize = totalammount;
84 }
85
86 int PR_InitEnts(progfuncs_t *progfuncs, int max_ents)
87 {
88         maxedicts = max_ents;
89
90         sv_num_edicts = 0;
91
92         max_fields_size = fields_size;
93
94         prinst->edicttable = PRHunkAlloc(progfuncs, maxedicts*sizeof(struct edicts_s *));
95         sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize);
96         prinst->edicttable[0] = sv_edicts;
97         ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableAlloc(progfuncs, max_fields_size);
98         QC_ClearEdict(progfuncs, sv_edicts);
99         sv_num_edicts = 1;
100
101         if (externs->entspawn)
102                 externs->entspawn((struct edict_s *)sv_edicts, false);
103
104         return max_fields_size;
105 }
106 edictrun_t tempedict;   //used as a safty buffer
107 float tempedictfields[2048];
108
109 void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs) //can be used to wipe all memory
110 {
111         unsigned int i;
112         edictrun_t *e;
113
114         max_fields_size=0;
115         fields_size = 0;
116         progfuncs->stringtable = 0;
117         QC_StartShares(progfuncs);
118         QC_InitShares(progfuncs);
119
120         for ( i=1 ; i<maxedicts; i++)
121         {
122                 e = (edictrun_t *)(prinst->edicttable[i]);
123                 prinst->edicttable[i] = NULL;
124 //              e->entnum = i;
125                 if (e)
126                         memfree(e);
127         }
128
129         PRHunkFree(progfuncs, 0);       //clear mem - our hunk may not be a real hunk.
130         if (addressable_size<0)
131                 addressable_size = 8*1024*1024;
132         PRAddressableFlush(progfuncs, addressable_size);
133
134         pr_progstate = PRHunkAlloc(progfuncs, sizeof(progstate_t) * max_progs);
135
136 /*              for(a = 0; a < max_progs; a++)
137                 {
138                         pr_progstate[a].progs = NULL;
139                 }               
140 */
141                 
142         maxprogs = max_progs;
143         pr_typecurrent=-1;
144
145         prinst->reorganisefields = false;
146
147         maxedicts = 1;
148         prinst->edicttable = &sv_edicts;
149         sv_num_edicts = 1;      //set up a safty buffer so things won't go horribly wrong too often
150         sv_edicts=(struct edict_s *)&tempedict;
151         tempedict.readonly = true;
152         tempedict.fields = tempedictfields;
153         tempedict.isfree = false;
154 }
155
156
157
158 struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum)
159 {
160         if (pnum < 0)
161         {
162                 if (!current_progstate)
163                         return NULL;    //err.. you've not loaded one yet.
164                 return (struct globalvars_s *)current_progstate->globals;
165         }
166         return (struct globalvars_s *)pr_progstate[pnum].globals;
167 }
168
169 struct entvars_s *PR_entvars (progfuncs_t *progfuncs, struct edict_s *ed)
170 {
171         if (((edictrun_t *)ed)->isfree)
172                 return NULL;
173
174         return (struct entvars_s *)edvars(ed);
175 }
176
177 int PR_GetFuncArgCount(progfuncs_t *progfuncs, func_t func)
178 {
179         unsigned int pnum;
180         unsigned int fnum;
181         dfunction_t *f;
182
183         pnum = (func & 0xff000000)>>24;
184         fnum = (func & 0x00ffffff);
185
186         if (pnum >= (unsigned)maxprogs || !pr_progstate[pnum].functions)
187                 return -1;
188         else if (fnum >= pr_progstate[pnum].progs->numfunctions)
189                 return -1;
190         else
191         {
192                 f = pr_progstate[pnum].functions + fnum;
193                 return f->numparms;
194         }
195 }
196
197 func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum)
198 {
199         dfunction_t *f=NULL;
200         if (pnum == PR_ANY)
201         {
202                 for (pnum = 0; (unsigned)pnum < maxprogs; pnum++)
203                 {
204                         if (!pr_progstate[pnum].progs)
205                                 continue;
206                         f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
207                         if (f)
208                                 break;
209                 }
210         }
211         else if (pnum == PR_ANYBACK)    //run backwards
212         {
213                 for (pnum = maxprogs-1; pnum >= 0; pnum--)
214                 {
215                         if (!pr_progstate[pnum].progs)
216                                 continue;
217                         f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
218                         if (f)
219                                 break;
220                 }
221         }
222         else
223                 f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
224         if (!f)
225                 return 0;
226
227         {
228         ddef16_t *var16;
229         ddef32_t *var32;
230         switch(pr_progstate[pnum].structtype)
231         {
232         case PST_KKQWSV:
233         case PST_DEFAULT:
234                 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.
235                 if (!var16)
236                         return (f - pr_progstate[pnum].functions) | (pnum << 24);
237                 return *(int *)&pr_progstate[pnum].globals[var16->ofs];
238         case PST_QTEST:
239         case PST_FTE32:
240                 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.
241                 if (!var32)
242                         return (f - pr_progstate[pnum].functions) | (pnum << 24);
243                 return *(int *)&pr_progstate[pnum].globals[var32->ofs]; 
244         }
245         Sys_Error("Error with def size (PR_FindFunc)"); 
246         }
247         return 0;
248 }
249
250 void QC_FindPrefixedGlobals(progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) )
251 {
252         unsigned int i;
253         ddef16_t                *def16;
254         ddef32_t                *def32;
255         int len = strlen(prefix);
256         unsigned int pnum;
257
258         for (pnum = 0; pnum < maxprogs; pnum++)
259         {
260                 if (!pr_progstate[pnum].progs)
261                         continue;
262
263                 switch(pr_progstate[pnum].structtype)
264                 {
265                 case PST_DEFAULT:
266                 case PST_KKQWSV:
267                         for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
268                         {
269                                 def16 = &pr_progstate[pnum].globaldefs16[i];
270                                 if (!strncmp(def16->s_name+progfuncs->stringtable,prefix, len))
271                                         found(progfuncs, def16->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type);
272                         }
273                         break;
274                 case PST_QTEST:
275                 case PST_FTE32:
276                         for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
277                         {
278                                 def32 = &pr_progstate[pnum].globaldefs32[i];
279                                 if (!strncmp(def32->s_name+progfuncs->stringtable,prefix, len))
280                                         found(progfuncs, def32->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type);
281                         }
282                         break;
283                 }
284         }
285 }
286
287 eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum, etype_t *type)
288 {
289         unsigned int i;
290         ddef16_t *var16;
291         ddef32_t *var32;
292         if (pnum == PR_CURRENT)
293                 pnum = pr_typecurrent;
294         if (pnum == PR_ANY)
295         {
296                 eval_t *ev;
297                 for (i = 0; i < maxprogs; i++)
298                 {
299                         if (!pr_progstate[i].progs)
300                                 continue;
301                         ev = PR_FindGlobal(progfuncs, globname, i, type);
302                         if (ev)
303                                 return ev;
304                 }
305                 return NULL;
306         }
307         if (pnum < 0 || (unsigned)pnum >= maxprogs || !pr_progstate[pnum].progs)
308                 return NULL;
309         switch(pr_progstate[pnum].structtype)
310         {
311         case PST_DEFAULT:
312         case PST_KKQWSV:
313                 if (!(var16 = ED_FindGlobalFromProgs16(progfuncs, globname, pnum)))
314                         return NULL;
315
316                 if (type)
317                         *type = var16->type;
318                 return (eval_t *)&pr_progstate[pnum].globals[var16->ofs];
319         case PST_QTEST:
320         case PST_FTE32:
321                 if (!(var32 = ED_FindGlobalFromProgs32(progfuncs, globname, pnum)))
322                         return NULL;
323
324                 if (type)
325                         *type = var32->type;
326                 return (eval_t *)&pr_progstate[pnum].globals[var32->ofs];
327         }
328         Sys_Error("Error with def size (PR_FindGlobal)");
329         return NULL;
330 }
331
332 void SetGlobalEdict(progfuncs_t *progfuncs, struct edict_s *ed, int ofs)
333 {
334         ((int*)pr_globals)[ofs] = EDICT_TO_PROG(progfuncs, ed);
335 }
336
337 char *PR_VarString (progfuncs_t *progfuncs, int first)
338 {
339         int             i;
340         static char out[1024];
341         char *s;
342         
343         out[0] = 0;
344         for (i=first ; i<pr_argc ; i++)
345         {
346                 if (G_STRING(OFS_PARM0+i*3))
347                 {
348                         s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable;
349                         if (strlen(out) + strlen(s) + 1 >= sizeof(out))
350                                 return out;
351                         strcat (out, s);
352                 }
353         }
354         return out;
355 }
356
357 int PR_QueryField (progfuncs_t *progfuncs, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache)
358 {
359         fdef_t *var;
360         var = ED_FieldAtOfs(progfuncs, fieldoffset);
361         if (!var)
362                 return false;
363
364         if (type)
365                 *type = var->type & ~(DEF_SAVEGLOBAL|DEF_SHARED);
366         if (name)
367                 *name = var->name;
368         if (fieldcache)
369         {
370                 fieldcache->ofs32 = var;
371                 fieldcache->varname = var->name;
372         }
373                 
374         return true;
375 }
376
377 eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *name, evalc_t *cache)
378 {
379         fdef_t *var;
380         if (!cache)
381         {
382                 var = ED_FindField(progfuncs, name);
383                 if (!var)
384                         return NULL;
385                 return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
386         }
387         if (!cache->varname)
388         {
389                 cache->varname = name;
390                 var = ED_FindField(progfuncs, name);            
391                 if (!var)
392                 {
393                         cache->ofs32 = NULL;
394                         return NULL;
395                 }
396                 cache->ofs32 = var;
397                 cache->varname = var->name;
398                 if (!ed)
399                         return (void*)~0;       //something not null
400                 return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
401         }
402         if (cache->ofs32 == NULL)
403                 return NULL;
404         return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[cache->ofs32->ofs]);
405 }
406
407 struct edict_s *ProgsToEdict (progfuncs_t *progfuncs, int progs)
408 {
409         if ((unsigned)progs >= (unsigned)maxedicts)
410         {
411                 printf("Bad entity index %i\n", progs);
412                 progs = 0;
413         }
414         return (struct edict_s *)PROG_TO_EDICT(progfuncs, progs);
415 }
416 int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed)
417 {
418         return EDICT_TO_PROG(progfuncs, ed);
419 }
420
421 string_t PR_StringToProgs                       (progfuncs_t *progfuncs, char *str)
422 {
423         char **ntable;
424         int i, free=-1;
425
426         if (!str)
427                 return 0;
428
429 //      if (str-progfuncs->stringtable < progfuncs->stringtablesize)
430 //              return str - progfuncs->stringtable;
431
432         for (i = prinst->numallocedstrings-1; i >= 0; i--)
433         {
434                 if (prinst->allocedstrings[i] == str)
435                         return (string_t)((unsigned int)i | 0x80000000);
436                 if (!prinst->allocedstrings[i])
437                         free = i;
438         }
439
440         if (free != -1)
441         {
442                 i = free;
443                 prinst->allocedstrings[i] = str;
444                 return (string_t)((unsigned int)i | 0x80000000);
445         }
446
447         prinst->maxallocedstrings += 1024;
448         ntable = memalloc(sizeof(char*) * prinst->maxallocedstrings); 
449         memcpy(ntable, prinst->allocedstrings, sizeof(char*) * prinst->numallocedstrings);
450         memset(ntable + prinst->numallocedstrings, 0, sizeof(char*) * (prinst->maxallocedstrings - prinst->numallocedstrings));
451         prinst->numallocedstrings = prinst->maxallocedstrings;
452         if (prinst->allocedstrings)
453                 memfree(prinst->allocedstrings);
454         prinst->allocedstrings = ntable;
455
456         for (i = prinst->numallocedstrings-1; i >= 0; i--)
457         {
458                 if (!prinst->allocedstrings[i])
459                 {
460                         prinst->allocedstrings[i] = str;
461                         return (string_t)((unsigned int)i | 0x80000000);
462                 }
463         }
464
465         return 0;
466 }
467
468 char *PR_RemoveProgsString                              (progfuncs_t *progfuncs, string_t str)
469 {
470         char *ret;
471
472         //input string is expected to be an allocated string
473         //if its a temp, or a constant, just return NULL.
474         if ((unsigned int)str & 0xc0000000)
475         {
476                 if ((unsigned int)str & 0x80000000)
477                 {
478                         int i = str & ~0x80000000;
479                         if (i >= prinst->numallocedstrings)
480                         {
481                                 pr_trace = 1;
482                                 return NULL;
483                         }
484                         if (prinst->allocedstrings[i])
485                         {
486                                 ret = prinst->allocedstrings[i];
487                                 prinst->allocedstrings[i] = NULL;       //remove it
488                                 return ret;
489                         }
490                         else
491                         {
492                                 pr_trace = 1;
493                                 return NULL;    //urm, was freed...
494                         }
495                 }
496         }
497         pr_trace = 1;
498         return NULL;
499 }
500
501 char *ASMCALL PR_StringToNative                         (progfuncs_t *progfuncs, string_t str)
502 {
503         if ((unsigned int)str & 0xc0000000)
504         {
505                 if ((unsigned int)str & 0x80000000)
506                 {
507                         int i = str & ~0x80000000;
508                         if (i >= prinst->numallocedstrings)
509                         {
510                                 pr_trace = 1;
511                                 return "";
512                         }
513                         if (prinst->allocedstrings[i])
514                                 return prinst->allocedstrings[i];
515                         else
516                         {
517                                 pr_trace = 1;
518                                 return "";      //urm, was freed...
519                         }
520                 }
521                 if ((unsigned int)str & 0x40000000)
522                 {
523                         int i = str & ~0x40000000;
524                         if (i >= prinst->numtempstrings)
525                         {
526                                 pr_trace = 1;
527                                 return "";
528                         }
529                         return prinst->tempstrings[i];
530                 }
531         }
532
533         if (str >= progfuncs->stringtablesize)
534         {
535                 pr_trace = 1;
536                 return "";
537         }
538         return progfuncs->stringtable + str;
539 }
540
541
542 string_t PR_AllocTempString                     (progfuncs_t *progfuncs, char *str)
543 {
544         char **ntable;
545         int newmax;
546         int i;
547
548         if (!str)
549                 return 0;
550
551         if (prinst->numtempstrings == prinst->maxtempstrings)
552         {
553                 newmax = prinst->maxtempstrings += 1024;
554                 prinst->maxtempstrings += 1024;
555                 ntable = memalloc(sizeof(char*) * newmax);
556                 memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings);
557                 prinst->maxtempstrings = newmax;
558                 if (prinst->tempstrings)
559                         memfree(prinst->tempstrings);
560                 prinst->tempstrings = ntable;
561         }
562
563         i = prinst->numtempstrings;
564         if (i == 0x10000000)
565                 return 0;
566
567         prinst->numtempstrings++;
568
569         prinst->tempstrings[i] = memalloc(strlen(str)+1);
570         strcpy(prinst->tempstrings[i], str);
571
572         return (string_t)((unsigned int)i | 0x40000000);
573 }
574
575 void PR_FreeTemps                       (progfuncs_t *progfuncs, int depth)
576 {
577         int i;
578         if (depth > prinst->numtempstrings)
579         {
580                 Sys_Error("QC Temp stack inverted\n");
581                 return;
582         }
583         for (i = depth; i < prinst->numtempstrings; i++)
584         {
585                 memfree(prinst->tempstrings[i]);
586         }
587
588         prinst->numtempstrings = depth;
589 }
590
591
592 struct qcthread_s *PR_ForkStack (progfuncs_t *progfuncs);
593 void PR_ResumeThread                    (progfuncs_t *progfuncs, struct qcthread_s *thread);
594 void    PR_AbortStack                   (progfuncs_t *progfuncs);
595
596
597 void RegisterBuiltin(progfuncs_t *progfncs, char *name, builtin_t func);
598
599 progfuncs_t deffuncs = {
600         PROGSTRUCT_VERSION,
601         PR_Configure,
602         PR_LoadProgs,
603         PR_InitEnts,
604         PR_ExecuteProgram,
605         PR_SwitchProgs,
606         PR_globals,
607         PR_entvars,
608         PR_RunError,
609         ED_Print,
610         ED_Alloc,
611         ED_Free,
612
613         EDICT_NUM,
614         NUM_FOR_EDICT,
615
616
617         SetGlobalEdict,
618
619         PR_VarString,
620
621         NULL,
622         PR_FindFunc,
623 #ifdef MINIMAL
624         NULL,
625         NULL,
626 #else
627         Comp_Begin,
628         Comp_Continue,
629 #endif
630
631         filefromprogs,
632         NULL,//filefromnewprogs,
633
634         SaveEnts,
635         LoadEnts,
636
637         SaveEnt,
638         RestoreEnt,
639
640         PR_FindGlobal,
641         ED_NewString,
642         (void*)PRHunkAlloc,
643
644         GetEdictFieldValue,
645         ProgsToEdict,
646         EdictToProgs,
647
648         EvaluateDebugString,
649
650         NULL,
651         PR_StackTrace,
652
653         PR_ToggleBreakpoint,
654         0,
655         NULL,
656 #ifdef MINIMAL
657         NULL,
658 #else
659         Decompile,
660 #endif
661         NULL,
662         NULL,
663         RegisterBuiltin,
664
665         0,
666         0,
667
668         PR_ForkStack,
669         PR_ResumeThread,
670         PR_AbortStack,
671
672         0,
673
674         QC_RegisterFieldVar,
675
676         0,
677         0,
678
679         PR_AllocTempString,
680
681         PR_StringToProgs,
682         PR_StringToNative,
683         0,
684         PR_QueryField,
685         QC_ClearEdict,
686         QC_FindPrefixedGlobals
687 };
688 #undef printf
689
690 //defs incase following structure is not passed.
691 struct edict_s *safesv_edicts;
692 int safesv_num_edicts;
693 double safetime=0;
694
695 progexterns_t defexterns = {
696         PROGSTRUCT_VERSION,             
697
698         NULL, //char *(*ReadFile) (char *fname, void *buffer, int len);
699         NULL, //int (*FileSize) (char *fname);  //-1 if file does not exist
700         NULL, //bool (*WriteFile) (char *name, void *data, int len);
701         printf, //void (*printf) (char *, ...);
702         (void*)exit, //void (*Sys_Error) (char *, ...);
703         NULL, //void (*Abort) (char *, ...);
704         sizeof(edictrun_t), //int edictsize;    //size of edict_t
705
706         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
707         NULL, //bool (*entcanfree) (struct edict_s *ent);       //return true to stop ent from being freed
708         NULL, //void (*stateop) (float var, func_t func);
709         NULL,
710         NULL,
711         NULL,
712
713         //used when loading a game
714         NULL, //builtin_t *(*builtinsfor) (int num);    //must return a pointer to the builtins that were used before the state was saved.
715         NULL, //void (*loadcompleate) (int edictsize);  //notification to reset any pointers.
716         NULL,
717
718         (void*)malloc, //void *(*memalloc) (int size);  //small string allocation       malloced and freed randomly by the executor. (use memalloc if you want)
719         free, //void (*memfree) (void * mem);
720
721
722         NULL, //builtin_t *globalbuiltins;      //these are available to all progs
723         0, //int numglobalbuiltins;
724
725         PR_NOCOMPILE,
726
727         &safetime, //double *gametime;
728
729         &safesv_edicts, //struct edict_s **sv_edicts;
730         &safesv_num_edicts, //int *sv_num_edicts;
731
732         NULL, //int (*useeditor) (char *filename, int line, int nump, char **parms);
733 };
734
735 //progfuncs_t *progfuncs = NULL;
736 #undef memfree
737 #undef prinst
738 #undef extensionbuiltin
739 #undef field
740 #undef shares
741 #undef sv_num_edicts
742
743
744 #ifdef QCLIBDLL_EXPORTS
745 __declspec(dllexport)
746 #endif 
747 void CloseProgs(progfuncs_t *inst)
748 {
749 //      extensionbuiltin_t *eb;
750         void (VARGS *f) (void *);
751
752         unsigned int i;
753         edictrun_t *e;
754
755         f = inst->parms->memfree;
756
757         for ( i=1 ; i<inst->maxedicts; i++)
758         {
759                 e = (edictrun_t *)(inst->prinst->edicttable[i]);
760                 inst->prinst->edicttable[i] = NULL;
761                 if (e)
762                 {
763 //                      e->entnum = i;
764                         f(e);
765                 }
766         }
767
768         PRHunkFree(inst, 0);
769
770 #ifdef _WIN32
771         VirtualFree(inst->addressablehunk, 0, MEM_RELEASE);     //doesn't this look complicated? :p
772 #else
773         free(inst->addressablehunk);
774 #endif
775
776         if (inst->prinst->allocedstrings)
777                 f(inst->prinst->allocedstrings);
778         inst->prinst->allocedstrings = NULL;
779         if (inst->prinst->tempstrings)
780                 f(inst->prinst->tempstrings);
781         inst->prinst->tempstrings = NULL;
782
783
784 /*
785         while(inst->prinst->extensionbuiltin)
786         {
787                 eb = inst->prinst->extensionbuiltin->prev;
788                 f(inst->prinst->extensionbuiltin);
789                 inst->prinst->extensionbuiltin = eb;
790         }
791 */
792         if (inst->prinst->field)
793                 f(inst->prinst->field);
794         if (inst->prinst->shares)
795                 f(inst->prinst->shares);        //free memory
796         f(inst->prinst);
797         f(inst);
798 }
799
800 void RegisterBuiltin(progfuncs_t *progfuncs, char *name, builtin_t func)
801 {
802 /*
803         extensionbuiltin_t *eb;
804         eb = memalloc(sizeof(extensionbuiltin_t));
805         eb->prev = progfuncs->prinst->extensionbuiltin;
806         progfuncs->prinst->extensionbuiltin = eb;
807         eb->name = name;
808         eb->func = func;
809 */
810 }
811
812 #ifndef WIN32
813 #define QCLIBINT        //don't use dllspecifications
814 #endif
815
816 #if defined(QCLIBDLL_EXPORTS)
817 __declspec(dllexport)
818 #endif
819 progfuncs_t * InitProgs(progexterns_t *ext)
820 {       
821         progfuncs_t *funcs;
822
823         if (!ext)
824                 ext = &defexterns;
825         else
826         {
827                 int i;
828                 if (ext->progsversion > PROGSTRUCT_VERSION)
829                         return NULL;
830
831                 for (i=0;i<sizeof(progexterns_t); i+=4) //make sure there are no items left out.
832                         if (!*(int *)((char *)ext+i))
833                                 *(int *)((char *)ext+i) = *(int *)((char *)&defexterns+i);              
834         }       
835 #undef memalloc
836 #undef pr_trace
837         funcs = ext->memalloc(sizeof(progfuncs_t));     
838         memcpy(funcs, &deffuncs, sizeof(progfuncs_t));
839
840         funcs->prinst = ext->memalloc(sizeof(prinst_t));
841         memset(funcs->prinst,0, sizeof(prinst_t));
842
843         funcs->pr_trace = &funcs->prinst->pr_trace;
844         funcs->progstate = &funcs->pr_progstate;
845         funcs->callargc = &funcs->pr_argc;
846
847         funcs->parms = ext;
848
849         SetEndian();
850         
851         return funcs;
852 }
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869 #ifdef QCC
870 void main (int argc, char **argv)
871 {
872         progexterns_t ext;
873
874         progfuncs_t *funcs;
875         funcs = InitProgs(&ext);
876         if (funcs->PR_StartCompile(argc, argv))
877                 while(funcs->PR_ContinueCompile());
878 }
879 #endif