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