rabbit/cmdLine/rabbit.cpp

296 lines
5.7 KiB
C++

/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if defined(_MSC_VER) && defined(_DEBUG)
#include <crtdbg.h>
#include <conio.h>
#endif
#include <rabbit/rabbit.hpp>
#include <rabbit-std/sqstdblob.hpp>
#include <rabbit-std/sqstdsystem.hpp>
#include <rabbit-std/sqstdio.hpp>
#include <rabbit-std/sqstdmath.hpp>
#include <rabbit-std/sqstdstring.hpp>
#include <rabbit-std/sqstdaux.hpp>
void PrintVersionInfos();
#if defined(_MSC_VER) && defined(_DEBUG)
int MemAllocHook(int allocType,
void *userData,
size_t size,
int blockType,
long requestNumber,
const unsigned char *filename,
int lineNumber) {
//if(requestNumber==769)_asm int 3;
return 1;
}
#endif
int64_t quit(rabbit::VirtualMachine* v)
{
int *done;
sq_getuserpointer(v,-1,(rabbit::UserPointer*)&done);
*done=1;
return 0;
}
void printfunc(rabbit::VirtualMachine* SQ_UNUSED_ARG(v),const char *s,...)
{
va_list vl;
va_start(vl, s);
vfprintf(stdout, s, vl);
va_end(vl);
}
void errorfunc(rabbit::VirtualMachine* SQ_UNUSED_ARG(v),const char *s,...)
{
va_list vl;
va_start(vl, s);
vfprintf(stderr, s, vl);
va_end(vl);
}
void PrintVersionInfos()
{
fprintf(stdout,"%s %s (%d bits)\n",RABBIT_VERSION,RABBIT_COPYRIGHT,((int)(sizeof(int64_t)*8)));
}
void PrintUsage()
{
fprintf(stderr,"usage: sq <options> <scriptpath [args]>.\n"
"Available options are:\n"
" -d generates debug infos\n"
" -v displays version infos\n"
" -h prints help\n");
}
#define _INTERACTIVE 0
#define _DONE 2
#define _ERROR 3
//<<FIXME>> this func is a mess
int getargs(rabbit::VirtualMachine* v,int argc, char* argv[],int64_t *retval)
{
int i;
*retval = 0;
if(argc>1)
{
int arg=1,exitloop=0;
while(arg < argc && !exitloop)
{
if(argv[arg][0]=='-')
{
switch(argv[arg][1])
{
case 'd':
sq_enabledebuginfo(v,1);
break;
break;
case 'v':
PrintVersionInfos();
return _DONE;
case 'h':
PrintVersionInfos();
PrintUsage();
return _DONE;
default:
PrintVersionInfos();
printf("unknown prameter '-%c'\n",argv[arg][1]);
PrintUsage();
*retval = -1;
return _ERROR;
}
}else break;
arg++;
}
// src file
if(arg<argc) {
const char *filename=NULL;
filename=argv[arg];
arg++;
if(SQ_SUCCEEDED(rabbit::std::loadfile(v,filename,SQTrue))) {
int callargs = 1;
sq_pushroottable(v);
for(i=arg;i<argc;i++)
{
const char *a;
a=argv[i];
sq_pushstring(v,a,-1);
callargs++;
}
if(SQ_SUCCEEDED(sq_call(v,callargs,SQTrue,SQTrue))) {
rabbit::ObjectType type = sq_gettype(v,-1);
if(type == rabbit::OT_INTEGER) {
*retval = type;
sq_getinteger(v,-1,retval);
}
return _DONE;
}
else{
return _ERROR;
}
}
//if this point is reached an error occurred
{
const char *err;
sq_getlasterror(v);
if(SQ_SUCCEEDED(sq_getstring(v,-1,&err))) {
printf("error [%s]\n",err);
*retval = -2;
return _ERROR;
}
}
}
}
return _INTERACTIVE;
}
void Interactive(rabbit::VirtualMachine* v)
{
#define MAXINPUT 1024
char buffer[MAXINPUT];
int64_t blocks =0;
int64_t string=0;
int64_t retval=0;
int64_t done=0;
PrintVersionInfos();
sq_pushroottable(v);
sq_pushstring(v,"quit",-1);
sq_pushuserpointer(v,&done);
sq_newclosure(v,quit,1);
sq_setparamscheck(v,1,NULL);
sq_newslot(v,-3,SQFalse);
sq_pop(v,1);
while (!done)
{
int64_t i = 0;
printf("\nrabbit> ");
for(;;) {
int c;
if(done)return;
c = getchar();
if (c == '\n') {
if (i>0 && buffer[i-1] == '\\')
{
buffer[i-1] = '\n';
}
else if(blocks==0)break;
buffer[i++] = '\n';
}
else if (c=='}') {blocks--; buffer[i++] = (char)c;}
else if(c=='{' && !string){
blocks++;
buffer[i++] = (char)c;
}
else if(c=='"' || c=='\''){
string=!string;
buffer[i++] = (char)c;
}
else if (i >= MAXINPUT-1) {
fprintf(stderr, "rabbit: input line too long\n");
break;
}
else{
buffer[i++] = (char)c;
}
}
buffer[i] = '\0';
if(buffer[0]=='='){
snprintf(sq_getscratchpad(v,MAXINPUT),(size_t)MAXINPUT,"return (%s)",&buffer[1]);
memcpy(buffer,sq_getscratchpad(v,-1),(strlen(sq_getscratchpad(v,-1))+1)*sizeof(char));
retval=1;
}
i=strlen(buffer);
if(i>0){
int64_t oldtop=sq_gettop(v);
if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,"interactive console",SQTrue))){
sq_pushroottable(v);
if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){
printf("\n");
sq_pushroottable(v);
sq_pushstring(v,"print",-1);
sq_get(v,-2);
sq_pushroottable(v);
sq_push(v,-4);
sq_call(v,2,SQFalse,SQTrue);
retval=0;
printf("\n");
}
}
sq_settop(v,oldtop);
}
}
}
int main(int argc, char* argv[])
{
rabbit::VirtualMachine* v;
int64_t retval = 0;
#if defined(_MSC_VER) && defined(_DEBUG)
_CrtsetAllocHook(MemAllocHook);
#endif
v=rabbit::sq_open(1024);
sq_setprintfunc(v,printfunc,errorfunc);
sq_pushroottable(v);
rabbit::std::register_bloblib(v);
rabbit::std::register_iolib(v);
rabbit::std::register_systemlib(v);
rabbit::std::register_mathlib(v);
rabbit::std::register_stringlib(v);
//aux library
//sets error handlers
rabbit::std::seterrorhandlers(v);
//gets arguments
switch(getargs(v,argc,argv,&retval))
{
case _INTERACTIVE:
Interactive(v);
break;
case _DONE:
case _ERROR:
default:
break;
}
sq_close(v);
#if defined(_MSC_VER) && defined(_DEBUG)
_getch();
_CrtMemdumpAllObjectsSince( NULL );
#endif
return retval;
}