1/* see copyright notice in squirrel.h */
2#include <squirrel.h>
3#include <sqstdaux.h>
4#include <stdio.h>
5#include <assert.h>
6#include <stdarg.h>
7
8void sqstd_printcallstack(HSQUIRRELVM v)
9{
10 SQPRINTFUNCTION pf = sq_geterrorfunc(v);
11 if(pf) {
12 SQStackInfos si;
13 SQInteger i;
14 SQFloat f;
15 const SQChar *s;
16 SQInteger level=1; //1 is to skip this function that is level 0
17 const SQChar *name=0;
18 SQInteger seq=0;
19 pf(v,_SC("\nCALLSTACK\n"));
20 while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
21 {
22 const SQChar *fn=_SC("unknown");
23 const SQChar *src=_SC("unknown");
24 if(si.funcname)fn=si.funcname;
25 if(si.source)src=si.source;
26 pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
27 level++;
28 }
29 level=0;
30 pf(v,_SC("\nLOCALS\n"));
31
32 for(level=0;level<10;level++){
33 seq=0;
34 while((name = sq_getlocal(v,level,seq)))
35 {
36 seq++;
37 switch(sq_gettype(v,-1))
38 {
39 case OT_NULL:
40 pf(v,_SC("[%s] NULL\n"),name);
41 break;
42 case OT_INTEGER:
43 sq_getinteger(v,-1,&i);
44 pf(v,_SC("[%s] %d\n"),name,i);
45 break;
46 case OT_FLOAT:
47 sq_getfloat(v,-1,&f);
48 pf(v,_SC("[%s] %.14g\n"),name,f);
49 break;
50 case OT_USERPOINTER:
51 pf(v,_SC("[%s] USERPOINTER\n"),name);
52 break;
53 case OT_STRING:
54 sq_getstring(v,-1,&s);
55 pf(v,_SC("[%s] \"%s\"\n"),name,s);
56 break;
57 case OT_TABLE:
58 pf(v,_SC("[%s] TABLE\n"),name);
59 break;
60 case OT_ARRAY:
61 pf(v,_SC("[%s] ARRAY\n"),name);
62 break;
63 case OT_CLOSURE:
64 pf(v,_SC("[%s] CLOSURE\n"),name);
65 break;
66 case OT_NATIVECLOSURE:
67 pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
68 break;
69 case OT_GENERATOR:
70 pf(v,_SC("[%s] GENERATOR\n"),name);
71 break;
72 case OT_USERDATA:
73 pf(v,_SC("[%s] USERDATA\n"),name);
74 break;
75 case OT_THREAD:
76 pf(v,_SC("[%s] THREAD\n"),name);
77 break;
78 case OT_CLASS:
79 pf(v,_SC("[%s] CLASS\n"),name);
80 break;
81 case OT_INSTANCE:
82 pf(v,_SC("[%s] INSTANCE\n"),name);
83 break;
84 case OT_WEAKREF:
85 pf(v,_SC("[%s] WEAKREF\n"),name);
86 break;
87 case OT_BOOL:{
88 SQBool bval;
89 sq_getbool(v,-1,&bval);
90 pf(v,_SC("[%s] %s\n"),name,bval == SQTrue ? _SC("true"):_SC("false"));
91 }
92 break;
93 default: assert(0); break;
94 }
95 sq_pop(v,1);
96 }
97 }
98 }
99}
100
101static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
102{
103 SQPRINTFUNCTION pf = sq_geterrorfunc(v);
104 if(pf) {
105 const SQChar *sErr = 0;
106 if(sq_gettop(v)>=1) {
107 if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
108 pf(v,_SC("\nAN ERROR HAS OCCURRED [%s]\n"),sErr);
109 }
110 else{
111 pf(v,_SC("\nAN ERROR HAS OCCURRED [unknown]\n"));
112 }
113 sqstd_printcallstack(v);
114 }
115 }
116 return 0;
117}
118
119void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column)
120{
121 SQPRINTFUNCTION pf = sq_geterrorfunc(v);
122 if(pf) {
123 pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);
124 }
125}
126
127void sqstd_seterrorhandlers(HSQUIRRELVM v)
128{
129 sq_setcompilererrorhandler(v,_sqstd_compiler_error);
130 sq_newclosure(v,_sqstd_aux_printerror,0);
131 sq_seterrorhandler(v);
132}
133
134SQRESULT sqstd_throwerrorf(HSQUIRRELVM v,const SQChar *err,...)
135{
136 SQInteger n=256;
137 va_list args;
138begin:
139 va_start(args,err);
140 SQChar *b=sq_getscratchpad(v,n);
141 SQInteger r=scvsprintf(b,n,err,args);
142 va_end(args);
143 if (r>=n) {
144 n=r+1;//required+null
145 goto begin;
146 } else if (r<0) {
147 return sq_throwerror(v,_SC("@failed to generate formatted error message"));
148 } else {
149 return sq_throwerror(v,b);
150 }
151}
152