1 /*
2     see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include <stdarg.h>
6 #include "sqvm.h"
7 #include "sqfuncproto.h"
8 #include "sqclosure.h"
9 #include "sqstring.h"
10 
sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo * fi)11 SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
12 {
13     SQInteger cssize = v->_callsstacksize;
14     if (cssize > level) {
15         SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
16         if(sq_isclosure(ci._closure)) {
17             SQClosure *c = _closure(ci._closure);
18             SQFunctionProto *proto = c->_function;
19             fi->funcid = proto;
20             fi->name = sqtype(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");
21             fi->source = sqtype(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
22             fi->line = proto->_lineinfos[0]._line;
23             return SQ_OK;
24         }
25     }
26     return sq_throwerror(v,_SC("the object is not a closure"));
27 }
28 
sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos * si)29 SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
30 {
31     SQInteger cssize = v->_callsstacksize;
32     if (cssize > level) {
33         memset(si, 0, sizeof(SQStackInfos));
34         SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
35         switch (sqtype(ci._closure)) {
36         case OT_CLOSURE:{
37             SQFunctionProto *func = _closure(ci._closure)->_function;
38             if (sqtype(func->_name) == OT_STRING)
39                 si->funcname = _stringval(func->_name);
40             if (sqtype(func->_sourcename) == OT_STRING)
41                 si->source = _stringval(func->_sourcename);
42             si->line = func->GetLine(ci._ip);
43                         }
44             break;
45         case OT_NATIVECLOSURE:
46             si->source = _SC("NATIVE");
47             si->funcname = _SC("unknown");
48             if(sqtype(_nativeclosure(ci._closure)->_name) == OT_STRING)
49                 si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
50             si->line = -1;
51             break;
52         default: break; //shutup compiler
53         }
54         return SQ_OK;
55     }
56     return SQ_ERROR;
57 }
58 
Raise_Error(const SQChar * s,...)59 void SQVM::Raise_Error(const SQChar *s, ...)
60 {
61     va_list vl;
62     va_start(vl, s);
63     SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2);
64     scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl);
65     va_end(vl);
66     _lasterror = SQString::Create(_ss(this),_spval,-1);
67 }
68 
Raise_Error(const SQObjectPtr & desc)69 void SQVM::Raise_Error(const SQObjectPtr &desc)
70 {
71     _lasterror = desc;
72 }
73 
PrintObjVal(const SQObjectPtr & o)74 SQString *SQVM::PrintObjVal(const SQObjectPtr &o)
75 {
76     switch(sqtype(o)) {
77     case OT_STRING: return _string(o);
78     case OT_INTEGER:
79         scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o));
80         return SQString::Create(_ss(this), _spval);
81         break;
82     case OT_FLOAT:
83         scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o));
84         return SQString::Create(_ss(this), _spval);
85         break;
86     default:
87         return SQString::Create(_ss(this), GetTypeName(o));
88     }
89 }
90 
Raise_IdxError(const SQObjectPtr & o)91 void SQVM::Raise_IdxError(const SQObjectPtr &o)
92 {
93     SQObjectPtr oval = PrintObjVal(o);
94     Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));
95 }
96 
Raise_CompareError(const SQObject & o1,const SQObject & o2)97 void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
98 {
99     SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
100     Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));
101 }
102 
103 
Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type)104 void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type)
105 {
106     SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);
107     SQInteger found = 0;
108     for(SQInteger i=0; i<16; i++)
109     {
110         SQInteger mask = 0x00000001 << i;
111         if(typemask & (mask)) {
112             if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes);
113             found ++;
114             StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
115         }
116     }
117     Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
118 }
119