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