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