1 /*  see copyright notice in squirrel.h */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stdarg.h>
7 
8 #if defined(_MSC_VER) && defined(_DEBUG)
9 #include <crtdbg.h>
10 #include <conio.h>
11 #endif
12 #include <squirrel.h>
13 #include <sqstdblob.h>
14 #include <sqstdsystem.h>
15 #include <sqstdio.h>
16 #include <sqstdmath.h>
17 #include <sqstdstring.h>
18 #include <sqstdaux.h>
19 
20 #ifdef SQUNICODE
21 #define scfprintf fwprintf
22 #define scvprintf vfwprintf
23 #else
24 #define scfprintf fprintf
25 #define scvprintf vfprintf
26 #endif
27 
28 
29 void PrintVersionInfos();
30 
31 #if defined(_MSC_VER) && defined(_DEBUG)
MemAllocHook(int allocType,void * userData,size_t size,int blockType,long requestNumber,const unsigned char * filename,int lineNumber)32 int MemAllocHook( int allocType, void *userData, size_t size, int blockType,
33    long requestNumber, const unsigned char *filename, int lineNumber)
34 {
35     //if(requestNumber==769)_asm int 3;
36     return 1;
37 }
38 #endif
39 
40 
quit(HSQUIRRELVM v)41 SQInteger quit(HSQUIRRELVM v)
42 {
43     int *done;
44     sq_getuserpointer(v,-1,(SQUserPointer*)&done);
45     *done=1;
46     return 0;
47 }
48 
printfunc(HSQUIRRELVM SQ_UNUSED_ARG (v),const SQChar * s,...)49 void printfunc(HSQUIRRELVM SQ_UNUSED_ARG(v),const SQChar *s,...)
50 {
51     va_list vl;
52     va_start(vl, s);
53     scvprintf(stdout, s, vl);
54     va_end(vl);
55     (void)v; /* UNUSED */
56 }
57 
errorfunc(HSQUIRRELVM SQ_UNUSED_ARG (v),const SQChar * s,...)58 void errorfunc(HSQUIRRELVM SQ_UNUSED_ARG(v),const SQChar *s,...)
59 {
60     va_list vl;
61     va_start(vl, s);
62     scvprintf(stderr, s, vl);
63     va_end(vl);
64 }
65 
PrintVersionInfos()66 void PrintVersionInfos()
67 {
68     scfprintf(stdout,_SC("%s %s (%d bits)\n"),SQUIRREL_VERSION,SQUIRREL_COPYRIGHT,((int)(sizeof(SQInteger)*8)));
69 }
70 
PrintUsage()71 void PrintUsage()
72 {
73     scfprintf(stderr,_SC("usage: sq <options> <scriptpath [args]>.\n")
74         _SC("Available options are:\n")
75         _SC("   -c              compiles the file to bytecode(default output 'out.cnut')\n")
76         _SC("   -o              specifies output file for the -c option\n")
77         _SC("   -c              compiles only\n")
78         _SC("   -d              generates debug infos\n")
79         _SC("   -v              displays version infos\n")
80         _SC("   -h              prints help\n"));
81 }
82 
83 #define _INTERACTIVE 0
84 #define _DONE 2
85 #define _ERROR 3
86 //<<FIXME>> this func is a mess
getargs(HSQUIRRELVM v,int argc,char * argv[],SQInteger * retval)87 int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
88 {
89     int i;
90     int compiles_only = 0;
91 #ifdef SQUNICODE
92     static SQChar temp[500];
93 #endif
94     char * output = NULL;
95     *retval = 0;
96     if(argc>1)
97     {
98         int arg=1,exitloop=0;
99 
100         while(arg < argc && !exitloop)
101         {
102 
103             if(argv[arg][0]=='-')
104             {
105                 switch(argv[arg][1])
106                 {
107                 case 'd': //DEBUG(debug infos)
108                     sq_enabledebuginfo(v,1);
109                     break;
110                 case 'c':
111                     compiles_only = 1;
112                     break;
113                 case 'o':
114                     if(arg < argc) {
115                         arg++;
116                         output = argv[arg];
117                     }
118                     break;
119                 case 'v':
120                     PrintVersionInfos();
121                     return _DONE;
122 
123                 case 'h':
124                     PrintVersionInfos();
125                     PrintUsage();
126                     return _DONE;
127                 default:
128                     PrintVersionInfos();
129                     scprintf(_SC("unknown prameter '-%c'\n"),argv[arg][1]);
130                     PrintUsage();
131                     *retval = -1;
132                     return _ERROR;
133                 }
134             }else break;
135             arg++;
136         }
137 
138         // src file
139 
140         if(arg<argc) {
141             const SQChar *filename=NULL;
142 #ifdef SQUNICODE
143             mbstowcs(temp,argv[arg],strlen(argv[arg]));
144             filename=temp;
145 #else
146             filename=argv[arg];
147 #endif
148 
149             arg++;
150 
151             //sq_pushstring(v,_SC("ARGS"),-1);
152             //sq_newarray(v,0);
153 
154             //sq_createslot(v,-3);
155             //sq_pop(v,1);
156             if(compiles_only) {
157                 if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))){
158                     const SQChar *outfile = _SC("out.cnut");
159                     if(output) {
160 #ifdef SQUNICODE
161                         int len = (int)(strlen(output)+1);
162                         mbstowcs(sq_getscratchpad(v,len*sizeof(SQChar)),output,len);
163                         outfile = sq_getscratchpad(v,-1);
164 #else
165                         outfile = output;
166 #endif
167                     }
168                     if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,outfile)))
169                         return _DONE;
170                 }
171             }
172             else {
173                 //if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQFalse,SQTrue))) {
174                     //return _DONE;
175                 //}
176                 if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))) {
177                     int callargs = 1;
178                     sq_pushroottable(v);
179                     for(i=arg;i<argc;i++)
180                     {
181                         const SQChar *a;
182 #ifdef SQUNICODE
183                         int alen=(int)strlen(argv[i]);
184                         a=sq_getscratchpad(v,(int)(alen*sizeof(SQChar)));
185                         mbstowcs(sq_getscratchpad(v,-1),argv[i],alen);
186                         sq_getscratchpad(v,-1)[alen] = _SC('\0');
187 #else
188                         a=argv[i];
189 #endif
190                         sq_pushstring(v,a,-1);
191                         callargs++;
192                         //sq_arrayappend(v,-2);
193                     }
194                     if(SQ_SUCCEEDED(sq_call(v,callargs,SQTrue,SQTrue))) {
195                         SQObjectType type = sq_gettype(v,-1);
196                         if(type == OT_INTEGER) {
197                             *retval = type;
198                             sq_getinteger(v,-1,retval);
199                         }
200                         return _DONE;
201                     }
202                     else{
203                         return _ERROR;
204                     }
205 
206                 }
207             }
208             //if this point is reached an error occured
209             {
210                 const SQChar *err;
211                 sq_getlasterror(v);
212                 if(SQ_SUCCEEDED(sq_getstring(v,-1,&err))) {
213                     scprintf(_SC("Error [%s]\n"),err);
214                     *retval = -2;
215                     return _ERROR;
216                 }
217             }
218 
219         }
220     }
221 
222     return _INTERACTIVE;
223 }
224 
Interactive(HSQUIRRELVM v)225 void Interactive(HSQUIRRELVM v)
226 {
227 
228 #define MAXINPUT 1024
229     SQChar buffer[MAXINPUT];
230     SQInteger blocks =0;
231     SQInteger string=0;
232     SQInteger retval=0;
233     SQInteger done=0;
234     PrintVersionInfos();
235 
236     sq_pushroottable(v);
237     sq_pushstring(v,_SC("quit"),-1);
238     sq_pushuserpointer(v,&done);
239     sq_newclosure(v,quit,1);
240     sq_setparamscheck(v,1,NULL);
241     sq_newslot(v,-3,SQFalse);
242     sq_pop(v,1);
243 
244     while (!done)
245     {
246         SQInteger i = 0;
247         scprintf(_SC("\nsq>"));
248         for(;;) {
249             int c;
250             if(done)return;
251             c = getchar();
252             if (c == _SC('\n')) {
253                 if (i>0 && buffer[i-1] == _SC('\\'))
254                 {
255                     buffer[i-1] = _SC('\n');
256                 }
257                 else if(blocks==0)break;
258                 buffer[i++] = _SC('\n');
259             }
260             else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;}
261             else if(c==_SC('{') && !string){
262                     blocks++;
263                     buffer[i++] = (SQChar)c;
264             }
265             else if(c==_SC('"') || c==_SC('\'')){
266                     string=!string;
267                     buffer[i++] = (SQChar)c;
268             }
269             else if (i >= MAXINPUT-1) {
270                 scfprintf(stderr, _SC("sq : input line too long\n"));
271                 break;
272             }
273             else{
274                 buffer[i++] = (SQChar)c;
275             }
276         }
277         buffer[i] = _SC('\0');
278 
279         if(buffer[0]==_SC('=')){
280             scsprintf(sq_getscratchpad(v,MAXINPUT),(size_t)MAXINPUT,_SC("return (%s)"),&buffer[1]);
281             memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar));
282             retval=1;
283         }
284         i=scstrlen(buffer);
285         if(i>0){
286             SQInteger oldtop=sq_gettop(v);
287             if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){
288                 sq_pushroottable(v);
289                 if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) &&  retval){
290                     scprintf(_SC("\n"));
291                     sq_pushroottable(v);
292                     sq_pushstring(v,_SC("print"),-1);
293                     sq_get(v,-2);
294                     sq_pushroottable(v);
295                     sq_push(v,-4);
296                     sq_call(v,2,SQFalse,SQTrue);
297                     retval=0;
298                     scprintf(_SC("\n"));
299                 }
300             }
301 
302             sq_settop(v,oldtop);
303         }
304     }
305 }
306 
main(int argc,char * argv[])307 int main(int argc, char* argv[])
308 {
309     HSQUIRRELVM v;
310     SQInteger retval = 0;
311 #if defined(_MSC_VER) && defined(_DEBUG)
312     _CrtSetAllocHook(MemAllocHook);
313 #endif
314 
315     v=sq_open(1024);
316     sq_setprintfunc(v,printfunc,errorfunc);
317 
318     sq_pushroottable(v);
319 
320     sqstd_register_bloblib(v);
321     sqstd_register_iolib(v);
322     sqstd_register_systemlib(v);
323     sqstd_register_mathlib(v);
324     sqstd_register_stringlib(v);
325 
326     //aux library
327     //sets error handlers
328     sqstd_seterrorhandlers(v);
329 
330     //gets arguments
331     switch(getargs(v,argc,argv,&retval))
332     {
333     case _INTERACTIVE:
334         Interactive(v);
335         break;
336     case _DONE:
337     case _ERROR:
338     default:
339         break;
340     }
341 
342     sq_close(v);
343 
344 #if defined(_MSC_VER) && defined(_DEBUG)
345     _getch();
346     _CrtMemDumpAllObjectsSince( NULL );
347 #endif
348     return retval;
349 }
350 
351