sqrdbg.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <squirrel.h>
  2. #ifdef _WIN32
  3. # include <winsock.h>
  4. #else
  5. # include <sys/types.h>
  6. # include <sys/socket.h>
  7. # include <arpa/inet.h>
  8. # include <sys/time.h>
  9. # define SOCKET_ERROR (-1)
  10. # define TIMEVAL struct timeval
  11. #endif
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <squirrel.h>
  15. #include <squirrel.h>
  16. #include "sqrdbg.h"
  17. #include "sqdbgserver.h"
  18. SQInteger debug_hook(HSQUIRRELVM v);
  19. SQInteger error_handler(HSQUIRRELVM v);
  20. #include "serialize_state.inl"
  21. HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate)
  22. {
  23. struct sockaddr_in bindaddr;
  24. #ifdef _WIN32
  25. WSADATA wsadata;
  26. if (WSAStartup (MAKEWORD(2,2), &wsadata) != 0){
  27. return NULL;
  28. }
  29. #endif
  30. SQDbgServer *rdbg = new SQDbgServer(v);
  31. rdbg->_autoupdate = autoupdate?true:false;
  32. rdbg->_accept = socket(AF_INET,SOCK_STREAM,0);
  33. bindaddr.sin_family = AF_INET;
  34. bindaddr.sin_port = htons(port);
  35. bindaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  36. if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){
  37. delete rdbg;
  38. sq_throwerror(v,_SC("failed to bind the socket"));
  39. return NULL;
  40. }
  41. if(!rdbg->Init()) {
  42. delete rdbg;
  43. sq_throwerror(v,_SC("failed to initialize the debugger"));
  44. return NULL;
  45. }
  46. return rdbg;
  47. }
  48. SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg)
  49. {
  50. if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) {
  51. sq_throwerror(rdbg->_v,_SC("error compiling the serialization function"));
  52. }
  53. sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc);
  54. sq_addref(rdbg->_v,&rdbg->_serializefunc);
  55. sq_pop(rdbg->_v,1);
  56. sockaddr_in cliaddr;
  57. socklen_t addrlen=sizeof(cliaddr);
  58. if(listen(rdbg->_accept,0)==SOCKET_ERROR)
  59. return sq_throwerror(rdbg->_v,_SC("error on listen(socket)"));
  60. rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen);
  61. //do not accept any other connection
  62. sqdbg_closesocket(rdbg->_accept);
  63. rdbg->_accept = INVALID_SOCKET;
  64. if(rdbg->_endpoint==INVALID_SOCKET){
  65. return sq_throwerror(rdbg->_v,_SC("error accept(socket)"));
  66. }
  67. while(!rdbg->_ready){
  68. sq_rdbg_update(rdbg);
  69. }
  70. return SQ_OK;
  71. }
  72. SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg)
  73. {
  74. TIMEVAL time;
  75. time.tv_sec=0;
  76. time.tv_usec=0;
  77. fd_set read_flags;
  78. FD_ZERO(&read_flags);
  79. FD_SET(rdbg->_endpoint, &read_flags);
  80. select(NULL/*ignored*/, &read_flags, NULL, NULL, &time);
  81. if(FD_ISSET(rdbg->_endpoint,&read_flags)){
  82. char temp[1024];
  83. int size=0;
  84. char c,prev=NULL;
  85. memset(&temp,0,sizeof(temp));
  86. int res;
  87. FD_CLR(rdbg->_endpoint, &read_flags);
  88. while((res = recv(rdbg->_endpoint,&c,1,0))>0){
  89. if(c=='\n')break;
  90. if(c!='\r'){
  91. temp[size]=c;
  92. prev=c;
  93. size++;
  94. }
  95. if(size >= sizeof(temp)-2) break;
  96. }
  97. switch(res){
  98. case 0:
  99. return sq_throwerror(rdbg->_v,_SC("disconnected"));
  100. case SOCKET_ERROR:
  101. return sq_throwerror(rdbg->_v,_SC("socket error"));
  102. }
  103. temp[size]=NULL;
  104. temp[size+1]=NULL;
  105. rdbg->ParseMsg(temp);
  106. }
  107. return SQ_OK;
  108. }
  109. SQInteger debug_hook(HSQUIRRELVM v)
  110. {
  111. SQUserPointer up;
  112. SQInteger event_type,line;
  113. const SQChar *src,*func;
  114. sq_getinteger(v,2,&event_type);
  115. sq_getstring(v,3,&src);
  116. sq_getinteger(v,4,&line);
  117. sq_getstring(v,5,&func);
  118. sq_getuserpointer(v,-1,&up);
  119. HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up;
  120. rdbg->Hook(v,event_type,line,src,func);
  121. if(rdbg->_autoupdate) {
  122. if(SQ_FAILED(sq_rdbg_update(rdbg)))
  123. return sq_throwerror(v,_SC("socket failed"));
  124. }
  125. return 0;
  126. }
  127. SQInteger error_handler(HSQUIRRELVM v)
  128. {
  129. SQUserPointer up;
  130. const SQChar *sErr=NULL;
  131. const SQChar *fn=_SC("unknown");
  132. const SQChar *src=_SC("unknown");
  133. SQInteger line=-1;
  134. SQStackInfos si;
  135. sq_getuserpointer(v,-1,&up);
  136. HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up;
  137. if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si)))
  138. {
  139. if(si.funcname)fn=si.funcname;
  140. if(si.source)src=si.source;
  141. line=si.line;
  142. scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line);
  143. }
  144. if(sq_gettop(v)>=1){
  145. if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
  146. scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
  147. rdbg->Break(v,si.line,src,_SC("error"),sErr);
  148. }
  149. else{
  150. scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
  151. rdbg->Break(v,si.line,src,_SC("error"),_SC("unknown"));
  152. }
  153. }
  154. rdbg->BreakExecution();
  155. return 0;
  156. }
  157. SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg)
  158. {
  159. delete rdbg;
  160. #ifdef _WIN32
  161. WSACleanup();
  162. #endif
  163. return SQ_OK;
  164. }