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