* sim/ucsim/cmd.src/newcmdposix.cc, sim/ucsim/cmd.src/newcmdposixcl.h,
[fw/sdcc] / sim / ucsim / cmd.src / cmdutil.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/cmdutil.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * Copyright (C) 2006, Borut Razem - borut.razem@siol.net
6  *
7  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
8  *
9  */
10
11 /* This file is part of microcontroller simulator: ucsim.
12
13 UCSIM is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 UCSIM is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with UCSIM; see the file COPYING.  If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27 /*@1@*/
28
29 #include "ddconfig.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <assert.h>
35 #include <sys/types.h>
36 #ifdef SOCKET_AVAIL
37 # include HEADER_SOCKET
38 # if defined HAVE_SYS_SOCKET_H
39 #  include <netinet/in.h>
40 #  include <arpa/inet.h>
41 # endif
42 #endif
43 #ifdef _WIN32
44 #include <malloc.h>
45 #endif
46
47 #include "i_string.h"
48
49 #include "stypes.h"
50 #include "globals.h"
51 #include "uccl.h"
52 #include "cmdutil.h"
53
54
55 /*
56  * Making a socket which can be used to listen for a specified port
57  */
58
59 #ifdef SOCKET_AVAIL
60 #ifdef _WIN32
61 static void
62 init_winsock(void)
63 {
64   static bool is_initialized = false;
65
66   if (!is_initialized)
67     {
68       WSADATA wsaData;
69
70       // Initialize Winsock
71       int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
72       if (iResult != 0)
73         {
74           printf("WSAStartup failed: %d\n", iResult);
75           exit(1);
76         }
77     }
78 }
79
80 SOCKET
81 make_server_socket(unsigned short int port)
82 {
83   init_winsock();
84
85   struct sockaddr_in name;
86
87   /* Create the socket. */
88   SOCKET sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
89   if (INVALID_SOCKET == sock)
90     {
91       fprintf(stderr, "socket: %d\n", WSAGetLastError());
92       return INVALID_SOCKET;
93     }
94
95   name.sin_family     = AF_INET;
96   name.sin_port       = htons(port);
97   name.sin_addr.s_addr= htonl(INADDR_ANY);
98   if (SOCKET_ERROR == bind(sock, (struct sockaddr *)&name, sizeof(name)))
99     {
100       fprintf(stderr, "bind: %d\n", WSAGetLastError());
101       return INVALID_SOCKET;
102     }
103
104   return sock;
105 }
106 #else
107 int
108 make_server_socket(unsigned short int port)
109 {
110   int sock, i;
111   struct sockaddr_in name;
112
113   /* Create the socket. */
114   sock= socket(PF_INET, SOCK_STREAM, 0);
115   if (sock < 0)
116     {
117       perror("socket");
118       return(0);
119     }
120
121   /* Give the socket a name. */
122   i= 1;
123   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i)) < 0)
124     {
125       perror("setsockopt");
126     }
127   name.sin_family     = AF_INET;
128   name.sin_port       = htons(port);
129   name.sin_addr.s_addr= htonl(INADDR_ANY);
130   if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0)
131     {
132       perror("bind");
133       return(0);
134     }
135
136   return(sock);
137 }
138 #endif
139 #endif
140
141 #if _WIN32
142 enum e_handle_type
143 get_handle_type(HANDLE handle)
144 {
145   DWORD file_type = GetFileType(handle);
146
147   switch (file_type)
148     {
149     case FILE_TYPE_CHAR:
150       {
151               DWORD err;
152
153         if (!ClearCommError(handle, &err, NULL))
154           { 
155             if (ERROR_INVALID_HANDLE == GetLastError())
156               return CH_CONSOLE;
157           }
158       }
159       return CH_SERIAL;
160
161     case FILE_TYPE_DISK:
162       return CH_FILE;
163     }
164
165   char sockbuf[256];
166   int optlen = sizeof(sockbuf);
167
168   if (SOCKET_ERROR != getsockopt((SOCKET)handle, SOL_SOCKET, SO_TYPE, sockbuf, &optlen) ||
169     WSAENOTSOCK != WSAGetLastError())
170     return CH_SOCKET;
171
172   assert(false);
173   return CH_UNDEF;
174 }
175
176 bool
177 input_avail(HANDLE handle, e_handle_type type)
178 {
179   if (CH_UNDEF == type)
180       type = get_handle_type(handle);
181
182   switch (type)
183     {
184     case CH_SOCKET:
185       {
186         struct timeval tv = {0, 0};
187
188         assert(INVALID_HANDLE_VALUE != handle);
189
190         fd_set s;
191         FD_ZERO(&s);
192         FD_SET((SOCKET)handle, &s);
193
194         int ret = select(0, &s, NULL, NULL, &tv);
195         if (SOCKET_ERROR == ret)
196           fprintf(stderr, "Can't select: %d\n", WSAGetLastError());
197
198         return ret != SOCKET_ERROR && ret != 0;
199       }
200
201     case CH_FILE:
202       return true;
203
204     case CH_CONSOLE:
205       {
206         PINPUT_RECORD pIRBuf;
207         DWORD NumPending;
208         DWORD NumPeeked;
209
210         /*
211          * Peek all pending console events
212          */
213         if (INVALID_HANDLE_VALUE == handle ||
214           !GetNumberOfConsoleInputEvents(handle, &NumPending) ||
215           NumPending == 0 ||
216           NULL == (pIRBuf = (PINPUT_RECORD)_alloca(NumPending * sizeof(INPUT_RECORD))))
217           return FALSE;
218
219         if (PeekConsoleInput(handle, pIRBuf, NumPending, &NumPeeked) &&
220           NumPeeked != 0L &&
221           NumPeeked <= NumPending)
222           {
223
224             /*
225              * Scan all of the peeked events to determine if any is a key event
226              * which should be recognized.
227              */
228             for ( ; NumPeeked > 0 ; NumPeeked--, pIRBuf++ )
229               {
230                 if (KEY_EVENT == pIRBuf->EventType &&
231                   pIRBuf->Event.KeyEvent.bKeyDown &&
232                   pIRBuf->Event.KeyEvent.uChar.AsciiChar)
233                   return true;
234               }
235           }
236
237         return false;
238       }
239
240     case CH_SERIAL:
241       {
242         DWORD err;
243         COMSTAT comStat;
244
245         bool res = ClearCommError(handle, &err, &comStat);
246         assert(res);
247
248         return res ? comStat.cbInQue > 0 : false;
249       }
250
251     default:
252       assert(false);
253       return false;
254     }
255 }
256 #else
257 bool
258 input_avail(UCSOCKET_T fd)
259 {
260   assert(0 <= fd);
261
262   fd_set s;
263   FD_ZERO(&s);
264   FD_SET(fd, &s);
265
266   struct timeval tv = {0, 0};
267
268   int i = select(fd + 1, &s, NULL, NULL, &tv);
269   if (i < 0)
270     perror("select");
271
272   return i > 0;
273 }
274 #endif
275
276 /*
277  * Searching for a name in the specified table
278  */
279
280 struct name_entry *
281 get_name_entry(struct name_entry tabl[], char *name, class cl_uc *uc)
282 {
283   int i= 0;
284   char *p;
285
286   if (!tabl ||
287       !name ||
288       !(*name))
289     return(0);
290   for (p= name; *p; *p= toupper(*p), p++);
291   while (tabl[i].name &&
292          (!(tabl[i].cpu_type & uc->type) ||
293          (strcmp(tabl[i].name, name) != 0)))
294     {
295       //printf("tabl[%d].name=%s <-> %s\n",i,tabl[i].name,name);
296       i++;
297     }
298   if (tabl[i].name != NULL)
299     return(&tabl[i]);
300   else
301     return(0);
302 }
303
304
305 /*
306  * Interpreting a bitname
307  */
308
309 /*bool
310 interpret_bitname(char *name, class cl_uc *uc,
311                   uchar **cell, uchar *celladdr,
312                   uchar *bitaddr, uchar *bitmask,
313                   char **symname)
314 {
315   char *dot, *p;
316   char *sym, bitnumstr[2];
317   struct name_entry *ne;
318   int bitnum, i;
319
320   if ((dot= strchr(name, '.')) != NULL)
321     {
322       *dot++= '\0';
323       if ((ne= get_name_entry(uc->sfr_tbl(), name, uc)) == NULL)
324         {
325           *celladdr= strtol(name, &p, 0);
326           if (p && *p)
327             {
328               dot--;
329               *dot= '.';
330               return(DD_FALSE);
331             }
332         }
333       else
334         *celladdr= ne->addr;
335       if ((*celladdr < 0x20) ||
336           ((*celladdr > 0x2f) && (*celladdr < 0x80)) ||
337           ((*celladdr > 0x7f) && (*celladdr & 0x07)))
338         return(DD_FALSE);
339       bitnum= strtol(dot, &p, 0);
340       if ((p && *p) ||
341           (bitnum < 0) ||
342           (bitnum > 7))
343         return(DD_FALSE);
344       if (*celladdr > 0x7f)
345         *bitaddr= *celladdr + bitnum;
346       else
347         *bitaddr= (*celladdr - 0x20)*8 + bitnum;
348       dot--;
349       *dot= '.';
350     }
351   else
352     {
353       if ((ne= get_name_entry(uc->bit_tbl(), name, uc)) == NULL)
354         {
355           *bitaddr= strtol(name, &p, 0);
356           if ((p && *p) ||
357               (*bitaddr > 0xff))
358             return(DD_FALSE);
359         }
360       else
361         *bitaddr= ne->addr;
362       if (*bitaddr > 0x7f)
363         *celladdr= *bitaddr & 0xf8;
364       else
365         *celladdr= (*bitaddr >> 3) + 0x20;
366     }
367   // *bitaddr, *celladdr now OK
368   *cell= uc->get_bit//FIXME
369     (*bitaddr);
370   *bitmask= BIT_MASK(*bitaddr);
371   // making symbolic name
372   if (!symname)
373     return(DD_TRUE);
374   i= 0;
375   while (uc->bit_tbl()[i].name &&
376          (uc->bit_tbl()[i].addr != *bitaddr))
377     i++;
378   if (uc->bit_tbl()[i].name)
379     {
380       sym= strdup(uc->bit_tbl()[i].name);
381       *symname= sym;
382       return(DD_TRUE);
383     }
384   i= 0;
385   while (uc->sfr_tbl()[i].name &&
386          (uc->sfr_tbl()[i].addr != *celladdr))
387     i++;
388   if (uc->sfr_tbl()[i].name)
389     sym= strdup(uc->sfr_tbl()[i].name);
390   else
391     {
392       sym= (char *)malloc(3);
393       sprintf(sym, "%02x", *celladdr);
394     }
395   sym= (char *)realloc(sym, strlen(sym)+2);
396   strcat(sym, ".");
397   sprintf(bitnumstr, "%1d", *bitaddr & 0x07);
398   strcat(sym, bitnumstr);
399   *symname= sym;
400   return(DD_TRUE);
401 }*/
402
403
404 /*
405  * Processing escape sequencies in a string
406  */
407
408 char *
409 proc_escape(char *string, int *len)
410 {
411   char  spec_chars[]= "fnrtvab\"";
412   char  spec[]= "\f\n\r\t\v\a\b\"";
413   char  *s, *str, *p;
414
415   s  = string;
416   str= (char *)malloc(strlen(string)+1);
417   p  = str;
418   while (*s)
419     {
420       char *spec_c;
421
422       if (*s == '\\' &&
423           *(s+1))
424         {
425           s++;
426           if (*s == '0')
427             {
428               if (!isdigit(*(s+1)))
429                 {
430                   *p++= '\0';
431                   s++;
432                 }
433               else
434                 {
435                   char *octal, *chk, data;
436                   int i, j;
437                   i= strspn(s, "01234567");
438                   octal= (char *)malloc(i+1);
439                   j= 0;
440                   while (*s &&
441                          (j < i))
442                     octal[j++]= *s++;
443                   octal[j]= '\0';
444                   data= strtol(octal, &chk, 8);
445                   if (!chk || !(*chk))
446                     *p++= data;
447                 }
448             }
449           else
450             if ((spec_c= strchr(spec_chars, *s)) != NULL)
451               {
452                 *p++= spec[spec_c-spec_chars];
453                 s++;
454               }
455             else
456               *p++= *s++;
457         }
458       else
459         *p++= *s++;
460     }
461   *p= '\0';
462   *len= p-str;
463   return(str);
464 }
465
466
467 /* End of cmd.src/cmdutil.cc */