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).
20 //builtins and builtin management.
21 void PF_prints (progfuncs_t *prinst, struct globalvars_s *gvars)
24 s = prinst->VarString(prinst, 0);
29 void PF_printv (progfuncs_t *prinst, struct globalvars_s *pr_globals)
31 printf("%f %f %f\n", G_FLOAT(OFS_PARM0+0), G_FLOAT(OFS_PARM0+1), G_FLOAT(OFS_PARM0+2));
34 void PF_printf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
36 printf("%f\n", G_FLOAT(OFS_PARM0));
40 void PF_bad (progfuncs_t *prinst, struct globalvars_s *gvars)
42 printf("bad builtin\n");
45 builtin_t builtins[] = {
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.
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);
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)
78 if (!strncmp(fname, "src/", 4))
79 fname+=4; //skip the src part
80 f = fopen(fname, "rb");
83 fseek(f, 0, SEEK_END);
87 fseek(f, 0, SEEK_SET);
88 fread(buffer, 1, len, f);
92 //Finds the size of a file.
93 int Sys_FileSize (char *fname)
97 if (!strncmp(fname, "src/", 4))
98 fname+=4; //skip the src part
99 f = fopen(fname, "rb");
102 fseek(f, 0, SEEK_END);
108 pbool Sys_WriteFile (char *fname, void *data, int len)
111 f = fopen(fname, "wb");
114 fwrite(data, 1, len, f);
119 void runtest(char *progsname)
126 memset(&ext, 0, sizeof(ext));
128 ext.progsversion = PROGSTRUCT_VERSION;
129 ext.ReadFile = Sys_ReadFile;
130 ext.FileSize= Sys_FileSize;
131 ext.Abort = Sys_Abort;
134 ext.numglobalbuiltins = sizeof(builtins)/sizeof(builtins[0]);
135 ext.globalbuiltins = builtins;
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.
142 printf("test: Failed to load progs \"%s\"\n", progsname);
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.
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.
150 //now it's safe to ED_Alloc.
152 func = pf->FindFunction(pf, "main", PR_ANY); //find the function 'main' in the first progs that has it.
154 printf("Couldn't find function\n");
156 pf->ExecuteProgram(pf, func); //call the function
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)
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"
177 "void(...) print = #1;\r\n"
180 " print(\"hello world\\n\");\r\n"
183 //so that the file exists. We could insert it via the callbacks instead
184 Sys_WriteFile("progs.src", testsrcfile, strlen(testsrcfile));
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;
195 pf = InitProgs(&ext);
196 if (pf->StartCompile)
198 if (pf->StartCompile(pf, argc, argv))
200 while(pf->ContinueCompile(pf) == 1)
205 printf("no compiler in this qcvm build\n");
209 int main(int argc, char **argv)
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]);
217 compile(argc-1, argv+1);