]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/fteqcc-src/test.c
Move the netradiant and fteqcc sources
[voretournament/voretournament.git] / misc / mediasource / fteqcc-src / test.c
1 //This is basically a sample program.
2 //It deomnstrates the code required to get qclib up and running.
3 //This code does not demonstrate entities, however.
4 //It does demonstrate the built in qc compiler, and does demonstrate a globals-only progs interface.
5 //It also demonstrates basic builtin(s).
6
7
8
9 #include "progtype.h"
10 #include "progslib.h"
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdarg.h>
16
17
18
19
20 //builtins and builtin management.
21 void PF_prints (progfuncs_t *prinst, struct globalvars_s *gvars)
22 {
23         char *s;
24         s = prinst->VarString(prinst, 0);
25
26         printf("%s", s);
27 }
28
29 void PF_printv (progfuncs_t *prinst, struct globalvars_s *pr_globals)
30 {
31         printf("%f %f %f\n", G_FLOAT(OFS_PARM0+0), G_FLOAT(OFS_PARM0+1), G_FLOAT(OFS_PARM0+2));
32 }
33
34 void PF_printf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
35 {
36         printf("%f\n", G_FLOAT(OFS_PARM0));
37 }
38
39
40 void PF_bad (progfuncs_t *prinst, struct globalvars_s *gvars)
41 {
42         printf("bad builtin\n");
43 }
44
45 builtin_t builtins[] = {
46         PF_bad,
47         PF_prints,
48         PF_printv,
49         PF_printf
50 };
51
52
53
54
55 //Called when the qc library has some sort of serious error.
56 void Sys_Abort(char *s, ...)
57 {       //quake handles this with a longjmp.
58         va_list ap;
59         va_start(ap, s);
60         vprintf(s, ap);
61         va_end(ap);
62         exit(1);
63 }
64 //Called when the library has something to say.
65 //Kinda required for the compiler...
66 //Not really that useful for the normal vm.
67 int Sys_Printf(char *s, ...)
68 {       //look up quake's va function to find out how to deal with variable arguments properly.
69         return printf("%s", s);
70 }
71
72 #include <stdio.h>
73 //copy file into buffer. note that the buffer will have been sized to fit the file (obtained via FileSize)
74 unsigned char *Sys_ReadFile (char *fname, void *buffer, int buflen)
75 {
76         int len;
77         FILE *f;
78         if (!strncmp(fname, "src/", 4))
79                 fname+=4;       //skip the src part
80         f = fopen(fname, "rb");
81         if (!f)
82                 return NULL;
83         fseek(f, 0, SEEK_END);
84         len = ftell(f);
85         if (buflen < len)
86                 return NULL;
87         fseek(f, 0, SEEK_SET);
88         fread(buffer, 1, len, f);
89         fclose(f);
90         return buffer;
91 }
92 //Finds the size of a file.
93 int Sys_FileSize (char *fname)
94 {
95         int len;
96         FILE *f;
97         if (!strncmp(fname, "src/", 4))
98                 fname+=4;       //skip the src part
99         f = fopen(fname, "rb");
100         if (!f)
101                 return -1;
102         fseek(f, 0, SEEK_END);
103         len = ftell(f);
104         fclose(f);
105         return len;
106 }
107 //Writes a file.
108 pbool Sys_WriteFile (char *fname, void *data, int len)
109 {
110         FILE *f;
111         f = fopen(fname, "wb");
112         if (!f)
113                 return 0;
114         fwrite(data, 1, len, f);
115         fclose(f);
116         return 1;
117 }
118
119 void runtest(char *progsname)
120 {
121         progfuncs_t *pf;
122         func_t func;
123         progsnum_t pn;
124
125         progparms_t ext;
126         memset(&ext, 0, sizeof(ext));
127
128         ext.progsversion = PROGSTRUCT_VERSION;
129         ext.ReadFile = Sys_ReadFile;
130         ext.FileSize= Sys_FileSize;
131         ext.Abort = Sys_Abort;
132         ext.printf = printf;
133
134         ext.numglobalbuiltins = sizeof(builtins)/sizeof(builtins[0]);
135         ext.globalbuiltins = builtins;
136
137         pf = InitProgs(&ext);
138         pf->Configure(pf, 1024*1024, 1);        //memory quantity of 1mb. Maximum progs loadable into the instance of 1
139 //If you support multiple progs types, you should tell the VM the offsets here, via RegisterFieldVar
140         pn = pf->LoadProgs(pf, progsname, 0, NULL, 0);  //load the progs, don't care about the crc, and use those builtins.
141         if (pn < 0)
142                 printf("test: Failed to load progs \"%s\"\n", progsname);
143         else
144         {
145 //allocate qc-acessable strings here for 64bit cpus. (allocate via AddString, tempstringbase is a holding area not used by the actual vm)
146 //you can call functions before InitEnts if you want. it's not really advised for anything except naming additional progs. This sample only allows one max.
147
148                 pf->InitEnts(pf, 10);           //Now we know how many fields required, we can say how many maximum ents we want to allow. 10 in this case. This can be huge without too many problems.
149
150 //now it's safe to ED_Alloc.
151
152                 func = pf->FindFunction(pf, "main", PR_ANY);    //find the function 'main' in the first progs that has it.
153                 if (!func)
154                         printf("Couldn't find function\n");
155                 else
156                         pf->ExecuteProgram(pf, func);                   //call the function
157         }
158         CloseProgs(pf);
159 }
160
161
162 //Run a compiler and nothing else.
163 //Note that this could be done with an autocompile of PR_COMPILEALWAYS.
164 void compile(int argc, char **argv)
165 {
166         progfuncs_t *pf;
167
168         progparms_t ext;
169
170         if (0)
171         {
172                 char *testsrcfile =     //newstyle progs.src must start with a #.
173                                                 //it's newstyle to avoid using multiple source files.
174                                         "#pragma PROGS_DAT \"testprogs.dat\"\r\n"
175                                         "//INTERMEDIATE FILE - EDIT TEST.C INSTEAD\r\n"
176                                         "\r\n"
177                                         "void(...) print = #1;\r\n"
178                                         "void() main =\r\n"
179                                         "{\r\n"
180                                         "       print(\"hello world\\n\");\r\n"
181                                         "};\r\n";
182
183                 //so that the file exists. We could insert it via the callbacks instead
184                 Sys_WriteFile("progs.src", testsrcfile, strlen(testsrcfile));
185         }
186
187         memset(&ext, 0, sizeof(ext));
188         ext.progsversion = PROGSTRUCT_VERSION;
189         ext.ReadFile = Sys_ReadFile;
190         ext.FileSize= Sys_FileSize;
191         ext.WriteFile= Sys_WriteFile;
192         ext.Abort = Sys_Abort;
193         ext.printf = printf;
194
195         pf = InitProgs(&ext);
196         if (pf->StartCompile)
197         {
198                 if (pf->StartCompile(pf, argc, argv))
199                 {
200                         while(pf->ContinueCompile(pf) == 1)
201                                 ;
202                 }
203         }
204         else
205                 printf("no compiler in this qcvm build\n");
206         CloseProgs(pf);
207 }
208
209 int main(int argc, char **argv)
210 {
211         if (argc < 2)
212         {
213                 printf("Invalid arguments!\nPlease run as, for example:\n%s testprogs.dat -srcfile progs.src\nThe first argument is the name of the progs.dat to run, the remaining arguments are the qcc args to use", argv[0]);
214                 return 0;
215         }
216
217         compile(argc-1, argv+1);
218         runtest(argv[1]);
219
220         return 0;
221 }