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