sqstdaux.cpp 4.0 KB

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