[ucsim] Update email and file info, fix stm8 flash controller
[sdcc.git] / sdcc / sim / ucsim / src / core / utils.src / fwio.cc
blob23b5db2d6e9873a81e08e4545dd84b8adea545d5
1 /*
2 * Simulator of microcontrollers (fwio.cc)
4 * Copyright (C) 1997 Drotos Daniel
5 *
6 * To contact author send email to dr.dkdb@gmail.com
8 */
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
28 // Need to define _WIN32_WINNT as 0x500 or higher for GetConsoleWindow()
29 // _WIN32_WINNT will be indirectly defined from WINVER
30 #ifdef WINVER
31 #undef WINVER
32 #endif
33 #define WINVER 0x500
35 #include "ddconfig.h"
37 #ifdef SOCKET_AVAIL
38 # include HEADER_SOCKET
39 #endif
41 #include <stdio.h>
42 #include <wchar.h>
43 #include <windows.h>
44 #include <fileapi.h>
45 #ifdef HAVE_WINCON_H
46 #include <wincon.h>
47 #endif
48 #ifdef HAVE_WINSOCK2_H
49 #include <winsock2.h>
50 #endif
51 #include <io.h>
52 #include <fcntl.h>
53 #include <stdarg.h>
54 #include <sys/time.h>
55 #include <time.h>
57 #include "fwiocl.h"
60 cl_f *dd= NULL;
62 void deb(const char *format, ...)
64 return;
65 /*if (dd==NULL)
67 dd= cp_io(stdout,"w");
68 dd->init();
69 }*/
70 va_list ap;
71 va_start(ap, format);
72 //dd->vprintf(format, ap);
73 vprintf(format, ap);
74 va_end(ap);
78 static void
79 init_winsock(void)
81 static bool is_initialized = false;
83 if (!is_initialized)
85 WSADATA wsaData;
87 // Initialize Winsock
88 int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
89 if (iResult != 0)
91 fprintf(stderr, "WSAStartup failed: %d\n", iResult);
92 exit(1);
94 //fprintf(stderr, "WSAStartup called\n");
95 is_initialized = true;
99 cl_io::cl_io(): cl_f()
101 init_winsock();
104 cl_io::cl_io(chars fn, chars mode): cl_f(fn, mode)
108 cl_io::cl_io(int the_server_port): cl_f(the_server_port)
112 cl_io::~cl_io(void)
114 if (echo_of != NULL)
115 echo_of->echo(NULL);
116 if (/*file_f*/file_id>=0)
118 if (own)
119 close();
120 else
121 stop_use();
125 enum file_type
126 cl_io::determine_type()
128 DWORD _file_type = GetFileType(handle);
130 deb("wio determine type fid=%d\n", file_id);
131 switch (_file_type)
133 case FILE_TYPE_CHAR:
135 DWORD err, NumPending;
136 if (file_id > 2)
137 return F_FILE;
138 if ((err= GetNumberOfConsoleInputEvents(handle, &NumPending)) == 0)
140 deb("wio file_id=%d (handle=%p) type=console1\n", file_id, handle);
141 return F_CONSOLE;
143 else
144 deb("wio file_id=%d (handle=%p) cons_det1 err=%d\n", file_id, handle, (int)err);
145 if (GetConsoleWindow() != NULL)
147 deb("wio file_id=%d (handle=%p) type=console2\n", file_id, handle);
148 return F_CONSOLE;
150 else
151 deb("wio file_id=%d (handle=%p) cons_det2 NULL\n", file_id, handle);
152 if (!ClearCommError(handle, &err, NULL))
154 switch (GetLastError())
156 case ERROR_INVALID_HANDLE:
157 deb("wio file_id=%d (handle=%p) type=console3\n", file_id, handle);
158 return F_CONSOLE;
160 case ERROR_INVALID_FUNCTION:
162 * In case of NUL device return type F_FILE.
163 * Is this the correct way to test it?
165 deb("wio file_id=%d (handle=%p) type=file\n", file_id, handle);
166 return F_FILE;
168 default:
169 //assert(false);
170 deb("wio file_id=%d (handle=%p) type=unknown\n", file_id, handle);
171 return F_UNKNOWN;
175 deb("wio file_id=%d (handle=%p) type=serial\n", file_id, handle);
176 return F_SERIAL;
178 case FILE_TYPE_DISK:
179 deb("wio file_id=%d (handle=%p) type=file2\n", file_id, handle);
180 return F_FILE;
184 char sockbuf[256];
185 int optlen = sizeof(sockbuf);
186 int i;
188 i= getsockopt((SOCKET)handle, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
189 int e= WSAGetLastError();
190 deb("Checking if fid=%d handle=%p is a socket, i=%d e=%d\n", file_id, handle, i, e);
191 if ((i == 0) ||
192 (WSAENOTSOCK != e))
194 deb("wio file_id=%d (handle=%p) type=socket\n", file_id, handle);
195 return F_SOCKET;
198 //assert(false);
199 deb("wio file_id=%d (handle=%p) type=pipe\n", file_id, handle);
200 return F_PIPE;
204 cl_io::check_dev(void)
206 //e_handle_type type= F_UNKNOWN;
207 //if (F_UNKNOWN == type)
208 //type = get_handle_type();
210 switch (type)
212 case F_SOCKET:
213 case F_LISTENER:
215 struct timeval tv = {0, 0};
217 //assert(INVALID_HANDLE_VALUE != handle);
219 fd_set s;
220 FD_ZERO(&s);
221 FD_SET((SOCKET)handle, &s);
223 int ret = select(0, &s, NULL, NULL, &tv);
224 if (SOCKET_ERROR == ret)
226 fprintf(stderr, "Can't select: %d fid=%d handle=%p type=%d\n",
227 WSAGetLastError(), file_id, handle, type);
228 return 0;
230 if (type == F_LISTENER)
231 return ret;
233 if ((ret != SOCKET_ERROR) &&
234 (ret != 0))
236 pick();
238 return last_used != first_free;
241 case F_FILE:
242 case F_PIPE:
243 pick();
244 return last_used != first_free;
246 case F_CONSOLE:
248 INPUT_RECORD *pIRBuf;
249 INPUT_RECORD *p;
250 DWORD NumPending;
251 DWORD NumPeeked;
252 bool ret= last_used != first_free;
254 * Peek all pending console events
256 //printf("win input check on console id=%d handle=%p\n", file_id, handle);
257 if (INVALID_HANDLE_VALUE == handle)
258 return ret;
259 if (!GetNumberOfConsoleInputEvents(handle, &NumPending))
260 return ret;
261 if (NumPending <= 0)
262 return ret;
263 if (NULL == (pIRBuf = (PINPUT_RECORD)/*_*/malloc/*a*/(NumPending * sizeof(INPUT_RECORD))))
264 return ret;
266 if (ReadConsoleInput(handle, pIRBuf, NumPending, &NumPeeked) == 0)
267 return free(pIRBuf), ret;
268 if (NumPeeked == 0L)
269 return free(pIRBuf), ret;
270 if (NumPeeked > NumPending)
271 return free(pIRBuf), ret;
274 * Scan all of the peeked events to determine if any is a key event
275 * which should be recognized.
277 int key_presses= 0;
278 for (p= pIRBuf ; NumPeeked > 0 ; NumPeeked--, p++ )
280 if (KEY_EVENT == p->EventType &&
281 p->Event.KeyEvent.bKeyDown)
283 int vk= p->Event.KeyEvent.wVirtualKeyCode;
284 char c= p->Event.KeyEvent.uChar.AsciiChar;
285 unsigned long int ctrl= p->Event.KeyEvent.dwControlKeyState;
286 key_presses++;
287 if (vk == VK_BACK) pick(8);
288 else if (vk == VK_TAB) pick(9);
289 else if (vk == VK_RETURN) pick('\n');
290 else if (vk == VK_ESCAPE) pick(0x1b);
291 else if (vk == VK_SPACE) pick(' ');
292 else if (vk == VK_PRIOR) pick("\033[5~");
293 else if (vk == VK_NEXT) pick("\033[6~");
294 else if (vk == VK_END) pick("\033[4~");
295 else if (vk == VK_HOME) pick("\033[1~");
296 else if (vk == VK_LEFT) pick("\033[D");
297 else if (vk == VK_RIGHT) pick("\033[C");
298 else if (vk == VK_UP) pick("\033[A");
299 else if (vk == VK_DOWN) pick("\033[B");
300 else if (vk == VK_INSERT) pick("\033[2~");
301 else if (vk == VK_DELETE) pick("\033[3~");
302 else if ((vk >= 0x30) &&
303 (vk <= 0x39)) pick(c);
304 else if ((vk >= 0x41) &&
305 (vk <= 0x5a)) pick(c);
306 else if ((vk >= 0xb8) &&
307 (vk <= 0xd7)) pick(c);
308 else if ((vk >= 0xdb) &&
309 (vk <= 0xdf)) pick(c);
310 else if ((vk >= 0xe1) &&
311 (vk <= 0xe4)) pick(c);
312 else if ((vk >= 0xe6) &&
313 (vk <= 0xf5)) pick(c);
314 else if ((vk >= VK_NUMPAD0) &&
315 (vk <= VK_NUMPAD9))
317 if (ctrl & NUMLOCK_ON) pick(vk-VK_NUMPAD0+'0');
318 else
319 switch (vk) {
320 case VK_NUMPAD0: pick("\033[2~"); break;
321 case VK_NUMPAD1: pick("\033[4~"); break;
322 case VK_NUMPAD2: pick("\033[B"); break;
323 case VK_NUMPAD3: pick("\033[6~"); break;
324 case VK_NUMPAD4: pick("\033[D"); break;
325 case VK_NUMPAD5: break;
326 case VK_NUMPAD6: pick("\033[C"); break;
327 case VK_NUMPAD7: pick("\033[1~"); break;
328 case VK_NUMPAD8: pick("\033[A"); break;
329 case VK_NUMPAD9: pick("\033[5~"); break;
332 else if (vk == VK_MULTIPLY) pick('*');
333 else if (vk == VK_ADD) pick('+');
334 else if (vk == VK_SEPARATOR) ;
335 else if (vk == VK_SUBTRACT) pick('-');
336 else if (vk == VK_DECIMAL) pick('.');
337 else if (vk == VK_DIVIDE) pick('/');
338 else if ((vk >= VK_F1) &&
339 (vk <= VK_F12))
341 char s[3];
342 sprintf(s, "%d", vk-VK_F1+11);
343 pick("\033["),pick(s[0]);
344 if (s[1]) pick(s[1]);
345 pick('~');
347 else if ((vk >= VK_F13) &&
348 (vk <= VK_F24)) ;
349 //else printf("vk=%d 0x%x c='%c'\n",vk,vk,c);
353 free(pIRBuf);
354 return last_used != first_free;
357 case F_SERIAL:
359 DWORD err;
360 COMSTAT comStat;
362 bool res = ClearCommError(handle, &err, &comStat);
363 //assert(res);
364 if (!res)
365 return false;
366 while (res && (comStat.cbInQue > 0))
368 pick();
369 res = ClearCommError(handle, &err, &comStat);
371 return last_used != first_free;
374 default:
375 //assert(false);
376 return false;
380 void
381 cl_io::check(void)
383 if (type == F_CONSOLE)
384 input_avail();
387 bool
388 cl_io::writable(void)
390 // TODO
391 switch (type)
393 case F_UNKNOWN: break;
394 case F_CHAR:
395 break;
396 case F_LISTENER: return false;
397 case F_SOCKET:
399 struct timeval tv= {0,0};
400 fd_set s;
401 FD_ZERO(&s);
402 FD_SET((SOCKET)handle, &s);
403 int ret= select(0, NULL, &s, NULL, &tv);
404 if (!FD_ISSET((SOCKET)handle, &s))
405 return false;
406 break;
408 case F_FILE:
410 ULARGE_INTEGER s;
411 if (GetDiskFreeSpaceExA(NULL, NULL, &s, NULL))
412 return s.QuadPart>1024;
413 break;
415 case F_PIPE:
416 break;
417 case F_CONSOLE: return true;
418 case F_SERIAL:
419 DWORD err;
420 COMSTAT comStat;
421 bool res= ClearCommError(handle, &err, &comStat);
422 if (!res)
423 return false;
424 if (comStat.cbOutQue != 0)
425 return false;
426 break;
428 return true;
431 void
432 cl_io::changed(void)
434 //printf("win_f changed fid=%d\n", file_id);
435 if (file_id < 0)
437 // CLOSE
438 //printf("Closing fid=%d\n", file_id);
439 if ((F_SOCKET == type) ||
440 (F_LISTENER == type))
442 //printf("Closing sock, handle=%p\n", handle);
443 shutdown((SOCKET)handle, SD_BOTH);
444 closesocket((SOCKET)handle);
446 handle= INVALID_HANDLE_VALUE;
447 type= F_UNKNOWN;
448 return;
451 // OPEN
452 if (server_port > 0)
454 //printf("win opened socket id=%d\n", file_id);
455 handle= (void *)((ULONG_PTR)file_id);
456 type= F_SOCKET;
457 deb("assuming TTY on socket %d\n", file_id);
458 tty= true;
460 else
462 handle= (HANDLE)_get_osfhandle(file_id);
463 type= determine_type();
464 /*if (type == F_CONSOLE)
466 if (strcmp("r", file_mode) == 0)
468 printf("wio: console mode 0\n");
469 SetConsoleMode(handle, 0);
472 if (type == F_SOCKET)
474 deb("determined socket, assume TTY... id=%d\n", file_id);
475 tty= true;
478 //printf("win opened file id=%d\n", file_id);
479 //printf("win handle=%p type=%d\n", handle, type);
482 void
483 cl_io::prepare_terminal()
485 deb("wio set_attr fid=%d type=%d\n",file_id,type);
486 if (type == F_CONSOLE)
488 deb("wio: console mode 0 fid=%d handle=%p\n", file_id, handle);
489 SetConsoleMode(handle,0);
490 //ENABLE_PROCESSED_OUTPUT|4/*ENABLE_VIRTUAL_TERMINAL_PROCESSING*/);
492 else if (type == F_SOCKET)
494 char s[7];
495 sprintf(s, "%c%c%c%c%c%c", 0xff, 0xfb, 1, 0xff, 0xfb, 3 );
496 write(s, 7);
502 mk_srv_socket(int port)
504 struct sockaddr_in name;
506 init_winsock();
507 //fprintf(stderr, "make_server_socket(%d)\n", port);
508 /* Create the socket. */
509 /*SOCKET*/unsigned int sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
510 if (INVALID_SOCKET == sock)
512 fprintf(stderr, "socket: %d\n", WSAGetLastError());
513 return -1;/*INVALID_SOCKET*/;
516 name.sin_family = AF_INET;
517 name.sin_port = htons(port);
518 name.sin_addr.s_addr= htonl(INADDR_ANY);
519 if (SOCKET_ERROR == bind(sock, (struct sockaddr *)&name, sizeof(name)))
521 /*wchar_t*/LPWSTR s = NULL;
522 int e= WSAGetLastError();
523 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
524 FORMAT_MESSAGE_FROM_SYSTEM |
525 FORMAT_MESSAGE_IGNORE_INSERTS,
526 NULL, e,
527 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
528 (LPWSTR)&s, 0, NULL);
529 fprintf(stderr, "bind of port %d: %d %S\n", port, e, s);
530 LocalFree(s);
531 return -1/*INVALID_SOCKET*/;
534 //printf("socket=%d\n", sock);
535 return sock;
539 class cl_f *
540 mk_io(const char *fn, const char *mode)
542 class cl_io *io;
544 if (!fn || !*fn)
546 io= new cl_io();
547 io->init();
548 return io;
550 else if (strcmp(fn, "-") == 0)
552 if (strcmp(mode, "r") == 0)
554 return cp_io(fileno(stdin), mode);
556 else if (strcmp(mode, "w") == 0)
558 return cp_io(fileno(stdout), mode);
561 io= new cl_io(fn, mode);
562 io->init();
563 return io;
566 class cl_f *
567 cp_io(/*FILE *f*/int file_id, const char *mode)
569 class cl_io *io;
571 io= new cl_io();
572 if (/*f*/file_id>=0)
573 io->use_opened(/*fileno(f)*/file_id, mode);
574 return io;
577 class cl_f *
578 mk_srv(int server_port)
580 class cl_io *io;
582 //printf("mk_srv(%d)\n", server_port);
583 io= new cl_io(server_port);
584 io->init();
585 io->type= F_LISTENER;
586 return io;
590 srv_accept(class cl_f *listen_io,
591 class cl_f **fin, class cl_f **fout)
593 class cl_io *io;
594 //ACCEPT_SOCKLEN_T size;
595 //struct sockaddr_in sock_addr;
596 int new_sock;
598 //size= sizeof(struct sockaddr);
599 new_sock= accept(listen_io->file_id, /*(struct sockaddr *)sock_addr*/NULL, /*&size*/NULL);
600 //printf("win srv_accept(port=%d,new_sock=%d)\n", listen_io->server_port, new_sock);
601 int fh= _open_osfhandle((intptr_t)new_sock, _O_TEXT);
602 //printf("Accept, got fh=%d for new_socket %p\n", fh, (void*)new_sock);
604 if (fin)
606 io= new cl_io();
607 if (new_sock > 0)
609 if (fh > 0)
611 FILE *f= fdopen(fh, "r");
612 //printf("fdopened f=%p for fh=%d as input\n", f, fh);
613 io->own_opened(f, "r");
614 io->type= F_SOCKET;
615 io->server_port= listen_io->server_port;
618 *fin= io;
621 if (fout)
623 io= new cl_io();
624 if (new_sock > 0)
626 //int fh= _open_osfhandle((intptr_t)new_sock, _O_TEXT);
627 if (fh > 0)
629 FILE *f= fdopen(fh, "w");
630 //printf("fdopened f=%p for fh=%d as output\n", f, fh);
631 io->use_opened(f, "w");
632 io->type= F_SOCKET;
633 io->server_port= listen_io->server_port;
636 *fout= io;
639 return 0;
642 bool
643 check_inputs(class cl_list *active, class cl_list *avail)
645 int i;
646 bool ret= false;
648 if (!active)
649 return false;
651 if (avail)
652 avail->disconn_all();
654 for (i= 0; i < active->count; i++)
656 class cl_f *fio= (class cl_f *)active->at(i);
657 if (fio->input_avail())
659 if (avail)
660 avail->add(fio);
661 ret= true;
664 return ret;
667 void
668 msleep(int msec)
670 Sleep(msec);
673 void
674 loop_delay()
676 msleep(100);
680 void
681 sigpipe_off()
685 unsigned int cperiod_value() { return 10000; }
688 set_console_mode()
690 // Set output mode to handle virtual terminal sequences
691 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
692 if (hOut == INVALID_HANDLE_VALUE)
694 return false;
696 HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
697 if (hIn == INVALID_HANDLE_VALUE)
699 return false;
702 DWORD dwOriginalOutMode = 0;
703 DWORD dwOriginalInMode = 0;
704 if (!GetConsoleMode(hOut, &dwOriginalOutMode))
706 return false;
708 if (!GetConsoleMode(hIn, &dwOriginalInMode))
710 return false;
713 DWORD dwRequestedOutModes =
714 #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
715 ENABLE_VIRTUAL_TERMINAL_PROCESSING
716 #else
718 #endif
720 #ifdef DISABLE_NEWLINE_AUTO_RETURN
721 DISABLE_NEWLINE_AUTO_RETURN
722 #else
724 #endif
726 //DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT;
728 DWORD dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
729 if (!SetConsoleMode(hOut, dwOutMode))
731 // we failed to set both modes, try to step down mode gracefully.
732 dwRequestedOutModes =
733 #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
734 ENABLE_VIRTUAL_TERMINAL_PROCESSING
735 #else
737 #endif
739 dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
740 if (!SetConsoleMode(hOut, dwOutMode))
742 // Failed to set any VT mode, can't do anything here.
743 return -1;
747 DWORD dwInMode = dwOriginalInMode |
748 #ifdef ENABLE_VIRTUAL_TERMINAL_INPUT
749 ENABLE_VIRTUAL_TERMINAL_INPUT
750 #else
751 0x200
752 #endif
754 if (!SetConsoleMode(hIn, dwInMode))
756 // Failed to set VT input mode, can't do anything here.
757 return -1;
760 return 0;
764 double
765 dnow(void)
767 struct timeval tv;
768 gettimeofday(&tv, NULL);
769 return (double)tv.tv_sec + ((double)tv.tv_usec/1000000.0);
773 void
774 save_std_attribs()
778 void
779 restore_std_attribs()
784 /* End of utils.src/fwio.cc */