Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
4.9 KiB

  1. /*
  2. see copyright notice in sqrdbg.h
  3. */
  4. local currentscope;
  5. if ( ::getroottable().parent )
  6. {
  7. currentscope = ::getroottable();
  8. ::setroottable( ::getroottable().parent );
  9. }
  10. try {
  11. local objs_reg = { maxid=0 ,refs={} }
  12. complex_types <- {
  13. ["table"] = null,
  14. ["array"] = null,
  15. ["class"] = null,
  16. ["instance"] = null,
  17. ["weakref"] = null,
  18. }
  19. function build_refs(t):(objs_reg)
  20. {
  21. if(t == ::getroottable())
  22. return;
  23. local otype = ::type(t);
  24. if(otype in complex_types)
  25. {
  26. if(!(t in objs_reg.refs)) {
  27. objs_reg.refs[t] <- objs_reg.maxid++;
  28. iterateobject(t,function(o,i,val):(objs_reg)
  29. {
  30. build_refs(val);
  31. build_refs(i);
  32. })
  33. }
  34. }
  35. }
  36. function getvalue(v):(objs_reg)
  37. {
  38. switch(::type(v))
  39. {
  40. case "table":
  41. case "array":
  42. case "class":
  43. case "instance":
  44. return objs_reg.refs[v].tostring();
  45. case "integer":
  46. case "float":
  47. return v;
  48. case "bool":
  49. return v.tostring();
  50. case "string":
  51. return v;
  52. case "null":
  53. return "null";
  54. default:
  55. return pack_type(::type(v));
  56. }
  57. }
  58. local packed_types={
  59. ["null"]="n",
  60. ["string"]="s",
  61. ["integer"]="i",
  62. ["float"]="f",
  63. ["userdata"]="u",
  64. ["function"]="fn",
  65. ["table"]="t",
  66. ["array"]="a",
  67. ["generator"]="g",
  68. ["thread"]="h",
  69. ["instance"]="x",
  70. ["class"]="y",
  71. ["bool"]="b",
  72. ["weakref"]="w"
  73. }
  74. function pack_type(type):(packed_types)
  75. {
  76. if(type in packed_types)return packed_types[type]
  77. return type
  78. }
  79. function iterateobject(obj,func)
  80. {
  81. local ty = ::type(obj);
  82. if(ty == "instance") {
  83. try { //TRY TO USE _nexti
  84. foreach(idx,val in obj)
  85. {
  86. func(obj,idx,val);
  87. }
  88. }
  89. catch(e) {
  90. foreach(idx,val in obj.getclass())
  91. {
  92. func(obj,idx,obj[idx]);
  93. }
  94. }
  95. }
  96. else if(ty == "weakref") {
  97. func(obj,"@ref",obj.ref());
  98. }
  99. else {
  100. foreach(idx,val in obj)
  101. {
  102. func(obj,idx,val);
  103. }
  104. }
  105. }
  106. function build_tree():(objs_reg)
  107. {
  108. foreach(i,o in objs_reg.refs)
  109. {
  110. beginelement("o");
  111. attribute("type",(i==::getroottable()?"r":pack_type(::type(i))));
  112. local _typeof = typeof i;
  113. if(_typeof != ::type(i)) {
  114. attribute("typeof",_typeof);
  115. }
  116. attribute("ref",o.tostring());
  117. if(i != ::getroottable()){
  118. iterateobject(i,function (obj,idx,val) {
  119. if(::type(val) == "function")
  120. return;
  121. if ( ::type(idx) == "string" && idx.find( "__" ) == 0 )
  122. return;
  123. beginelement("e");
  124. emitvalue("kt","kv",idx);
  125. emitvalue("vt","v",obj[idx]);
  126. endelement("e");
  127. })
  128. }
  129. endelement("o");
  130. }
  131. }
  132. function evaluate_watch(locals,id,expression)
  133. {
  134. local func_src="return function ("
  135. local params=[];
  136. params.append(locals["this"])
  137. local first=1;
  138. foreach(i,v in locals){
  139. if(i!="this" && i[0] != '@'){ //foreach iterators start with @
  140. if(!first){
  141. func_src=func_src+","
  142. }
  143. first=null
  144. params.append(v)
  145. func_src=func_src+i
  146. }
  147. }
  148. func_src=func_src+"){\n"
  149. func_src=func_src+"return ("+expression+")\n}"
  150. try {
  151. local func=::compilestring(func_src);
  152. return {status="ok" , val=func().acall(params)};
  153. }
  154. catch(e)
  155. {
  156. return {status="error"}
  157. }
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. /////////////////////////////////////////////////////////////////////////////
  161. function emitvalue(type_attrib,value_attrib,val)
  162. {
  163. attribute(type_attrib,pack_type(::type(val)));
  164. attribute(value_attrib,getvalue(val).tostring());
  165. }
  166. local stack=[]
  167. local level=3;
  168. local si;
  169. //ENUMERATE THE STACK WATCHES
  170. while(si=::getstackinfos(level))
  171. {
  172. stack.append(si);
  173. level++;
  174. }
  175. //EVALUATE ALL WATCHES
  176. objs_reg.refs[::getroottable()] <- objs_reg.maxid++;
  177. foreach(i,val in stack)
  178. {
  179. if(val.src!="NATIVE") {
  180. if("watches" in this) {
  181. val.watches <- {}
  182. foreach(i,watch in watches)
  183. {
  184. if(val.src!="NATIVE"){
  185. val.watches[i] <- evaluate_watch(val.locals,i,watch);
  186. if(val.watches[i].status!="error")
  187. build_refs(val.watches[i].val);
  188. }
  189. else{
  190. val.watches[i] <- {status="error"}
  191. }
  192. val.watches[i].exp <- watch;
  193. }
  194. }
  195. }
  196. foreach(i,l in val.locals)
  197. build_refs(l);
  198. }
  199. beginelement("objs");
  200. build_tree();
  201. endelement("objs");
  202. beginelement("calls");
  203. foreach(i,val in stack)
  204. {
  205. beginelement("call");
  206. attribute("fnc",val.func);
  207. attribute("src",val.src);
  208. attribute("line",val.line.tostring());
  209. foreach(i,v in val.locals)
  210. {
  211. beginelement("l");
  212. attribute("name",getvalue(i).tostring());
  213. emitvalue("type","val",v);
  214. endelement("l");
  215. }
  216. if("watches" in val) {
  217. foreach(i,v in val.watches)
  218. {
  219. beginelement("w");
  220. attribute("id",i.tostring());
  221. attribute("exp",v.exp);
  222. attribute("status",v.status);
  223. if(v.status!="error") {
  224. emitvalue("type","val",v.val);
  225. }
  226. endelement("w");
  227. }
  228. }
  229. endelement("call");
  230. }
  231. endelement("calls");
  232. objs_reg = null;
  233. stack = null;
  234. if("collectgarbage" in ::getroottable()) ::collectgarbage();
  235. }catch(e)
  236. {
  237. ::print("ERROR"+e+"\n");
  238. }
  239. if ( currentscope )
  240. {
  241. ::setroottable( currentscope );
  242. }