File: test.c

package info (click to toggle)
fteqcc 2666-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 980 kB
  • ctags: 1,999
  • sloc: ansic: 23,344; makefile: 46
file content (185 lines) | stat: -rw-r--r-- 4,770 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//This is basically a sample program.
//It deomnstrates the code required to get qclib up and running.
//This code does not demonstrate entities, however.
//It does demonstrate the built in qc compiler, and does demonstrate a globals-only progs interface.
//It also demonstrates basic builtin(s).



#include "progtype.h"
#include "progslib.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

//the only function that is required externally. :/
void SV_EndRedirect (void) {}




//builtins and builtin management.
void PF_print (progfuncs_t *prinst, struct globalvars_s *gvars)
{
	char *s;
	s = prinst->VarString(prinst, 0);

	printf("%s", s);
}

builtin_t builtins[] = {
	PF_print,
	PF_print
};




//Called when the qc library has some sort of serious error.
void Sys_Abort(char *s, ...)
{	//quake handles this with a longjmp.
	printf("%s", s);
	exit(1);
}
//Called when the library has something to say.
//Kinda required for the compiler...
//Not really that useful for the normal vm.
int Sys_Printf(char *s, ...)
{	//look up quake's va function to find out how to deal with variable arguments properly.
	return printf("%s", s);
}

#include <stdio.h>
//copy file into buffer. note that the buffer will have been sized to fit the file (obtained via FileSize)
unsigned char *Sys_ReadFile (char *fname, void *buffer, int buflen)
{
	int len;
	FILE *f;
	if (!strncmp(fname, "src/", 4))
		fname+=4;	//skip the src part
	f = fopen(fname, "rb");
	if (!f)
		return NULL;
	fseek(f, 0, SEEK_END);
	len = ftell(f);
	if (buflen < len)
		return NULL;
	fseek(f, 0, SEEK_SET);
	fread(buffer, 1, len, f);
	fclose(f);
	return buffer;
}
//Finds the size of a file.
int Sys_FileSize (char *fname)
{
	int len;
	FILE *f;
	if (!strncmp(fname, "src/", 4))
		fname+=4;	//skip the src part
	f = fopen(fname, "rb");
	if (!f)
		return -1;
	fseek(f, 0, SEEK_END);
	len = ftell(f);
	fclose(f);
	return len;
}
//Writes a file.
pbool Sys_WriteFile (char *fname, void *data, int len)
{
	FILE *f;
	f = fopen(fname, "wb");
	if (!f)
		return 0;
	fwrite(data, 1, len, f);
	fclose(f);
	return 1;
}

void runtest(void)
{
	progfuncs_t *pf;
	func_t func;
	progsnum_t pn;

	progparms_t ext;
	memset(&ext, 0, sizeof(ext));

	ext.progsversion = PROGSTRUCT_VERSION;
	ext.ReadFile = Sys_ReadFile;
	ext.FileSize= Sys_FileSize;
	ext.Abort = Sys_Abort;
	ext.printf = printf;

	pf = InitProgs(&ext);
	pf->Configure(pf, 1024*1024, 1);	//memory quantity of 1mb. Maximum progs loadable into the instance of 1
//If you support multiple progs types, you should tell the VM the offsets here, via RegisterFieldVar
	pn = pf->LoadProgs(pf, "testprogs.dat", 0, builtins, sizeof(builtins)/sizeof(builtins[0]));	//load the progs, don't care about the crc, and use those builtins.
	if (pn < 0)
		printf("Failed to load progs\n");
	else
	{
//allocate qc-acessable strings here for 64bit cpus. (allocate via AddString, tempstringbase is a holding area not used by the actual vm)
//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.

		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.

//now it's safe to ED_Alloc.

		func = pf->FindFunction(pf, "main", PR_ANY);	//find the function 'main' in the first progs that has it.
		if (!func)
			printf("Couldn't find function\n");
		else
			pf->ExecuteProgram(pf, func);			//call the function
	}
	CloseProgs(pf);
}


//Run a compiler and nothing else.
//Note that this could be done with an autocompile of PR_COMPILEALWAYS.
void compile(void)
{
	progfuncs_t *pf;

	progparms_t ext;

	char *testsrcfile =	//newstyle progs.src must start with a #.
					//it's newstyle to avoid using multiple source files.
			 	"#pragma PROGS_DAT \"testprogs.dat\"\r\n"
				"//INTERMEDIATE FILE - EDIT TEST.C INSTEAD\r\n"
				"\r\n"
				"void(...) print = #1;\r\n"
				"void() main =\r\n"
				"{\r\n"
				"	print(\"hello world\\n\");\r\n"
				"};\r\n";

	//so that the file exists. We could insert it via the callbacks instead
	Sys_WriteFile("progs.src", testsrcfile, strlen(testsrcfile));

	memset(&ext, 0, sizeof(ext));
	ext.progsversion = PROGSTRUCT_VERSION;
	ext.ReadFile = Sys_ReadFile;
	ext.FileSize= Sys_FileSize;
	ext.WriteFile= Sys_WriteFile;
	ext.Abort = Sys_Abort;
	ext.printf = printf;

	pf = InitProgs(&ext);
	if (pf->StartCompile(pf, 0, NULL))
	{
		while(pf->ContinueCompile(pf) == 1)
			;
	}
	CloseProgs(pf);
}

int main(void)
{
	compile();
	runtest();

	return 0;
}