diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/fio.cc | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sim/ucsim/fio.cc')
| -rw-r--r-- | sim/ucsim/fio.cc | 1254 |
1 files changed, 1254 insertions, 0 deletions
diff --git a/sim/ucsim/fio.cc b/sim/ucsim/fio.cc new file mode 100644 index 0000000..8b18f69 --- /dev/null +++ b/sim/ucsim/fio.cc @@ -0,0 +1,1254 @@ +/* + * Simulator of microcontrollers (fio.cc) + * + * Copyright (C) 1997,16 Drotos Daniel, Talker Bt. + * + * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu + * + */ + +/* This file is part of microcontroller simulator: ucsim. + +UCSIM is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +UCSIM is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with UCSIM; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ +/*@1@*/ + +#include "ddconfig.h" + +#include <stdio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include HEADER_FD +#include <errno.h> +#include <string.h> +#if defined HAVE_SYS_SOCKET_H +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +#endif +#include <stdlib.h> +#include <ctype.h> +#include <stdarg.h> +#include <fcntl.h> +#include <sys/stat.h> + +// These two flags aren't defined on some platforms +#ifndef S_IRGRP +#define S_IRGRP 0 +#endif +#ifndef S_IROTH +#define S_IROTH 0 +#endif + +#include "fiocl.h" + +// prj +#include "utils.h" + + +cl_history::cl_history(char *aname): + cl_ustrings(100, 10, aname) +{ + nr= 0; + //actual_line= ""; +} + +cl_history::cl_history(const char *aname): +cl_ustrings(100, 10, aname) +{ + nr= 0; + //actual_line= ""; +} + +cl_history::~cl_history(void) +{ +} + +char * +cl_history::up(chars line) +{ + replace(line); + if (nr > 0) + nr--; + return (char*)(Items[nr]); +} + +char * +cl_history::down(chars line) +{ + replace(line); + if (nr < count) + nr++; + if (nr < count) + return (char*)(Items[nr]); + return NULL; +} + +char * +cl_history::enter(chars line) +{ + if (count > 1000) + { + free_at(0); + /*if (nr > count) + nr= count;*/ + } + if (!line.empty()) + { + add(strdup(line)); + nr= count; + } + return NULL; +} + +void +cl_history::replace(chars line) +{ + if (nr < count) + { + free(Items[nr]); + if (line.empty()) + Items[nr]= strdup(""); + else + Items[nr]= strdup(line); + } +} + + +/****************************************************************************/ + +cl_f::cl_f(void) +{ + file_id= -1; + own= false; + tty= false; + file_name= 0; + file_mode= 0; + server_port= -1; + echo_of= NULL; + echo_to= NULL; + echo_color= (char*)""; + at_end= 0; + last_used= first_free= 0; + cooking= 0; + line[0]= 0; + cursor= 0; + esc_buffer[0]= 0; + attributes_saved= 0; + hist= new cl_history("history"); + proc_telnet= false; + proc_escape= false; +} + +cl_f::cl_f(chars fn, chars mode): + cl_base() +{ + file_id= -1; + file_name= fn; + file_mode= mode; + tty= false; + own= false; + server_port= -1; + echo_of= NULL; + echo_to= NULL; + echo_color= (char*)""; + at_end= 0; + last_used= first_free= 0; + cooking= 0; + line[0]= 0; + cursor= 0; + esc_buffer[0]= 0; + attributes_saved= 0; + hist= new cl_history("history"); + proc_telnet= false; +} + +cl_f::cl_f(int the_server_port) +{ + file_id= -1; + own= false; + tty= false; + file_name= 0; + file_mode= 0; + server_port= the_server_port; + echo_of= NULL; + echo_to= NULL; + echo_color= (char*)""; + at_end= 0; + last_used= first_free= 0; + cooking= 0; + line[0]= 0; + cursor= 0; + esc_buffer[0]= 0; + attributes_saved= 0; + hist= new cl_history("history"); + proc_telnet= false; +} + +class cl_f * +cl_f::copy(chars mode) +{ + class cl_f *io= mk_io(chars(""), chars("")); + io->use_opened(file_id, mode); + return io; +} + +static int +open_flags(char *m) +{ + if (strcmp(m, "r") == 0) + return O_RDONLY; + else if (strcmp(m, "r+") == 0) + return O_RDWR | O_CREAT; + else if (strcmp(m, "w") == 0) + return O_WRONLY | O_TRUNC | O_CREAT; + else if (strcmp(m, "w+") == 0) + return O_RDWR | O_CREAT; + else if (strcmp(m, "a") == 0) + return O_APPEND | O_WRONLY | O_CREAT; + else if (strcmp(m, "a+") == 0) + return O_APPEND | O_RDWR | O_CREAT; + return O_RDWR; +} + +int +cl_f::init(void) +{ + if (server_port > 0) + { + file_id= mk_srv_socket(server_port); + listen(file_id, 50); + own= true; + tty= false; + changed(); + } + else if (!file_name.empty()) + { + if (file_mode.empty()) + file_mode= cchars("r+"); + if ((file_id= ::open(file_name, open_flags(file_mode), (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))) >= 0) + { + tty= isatty(file_id); + own= true; + save_attributes(); + changed(); + } + else + { + file_id= -1; + own= false; + } + } + return file_id; +} + +int +cl_f::use_opened(int opened_file_id, char *mode) +{ + close(); + if (mode) + file_mode= mode; + else + file_mode= cchars("r+"); + own= false; + if (opened_file_id >= 0) + { + file_id= opened_file_id; + tty= isatty(file_id); + changed(); + } + return file_id; +} + +int +cl_f::own_opened(int opened_file_id, char *mode) +{ + use_opened(opened_file_id, mode); + own= true; + return file_id; +} + +int +cl_f::use_opened(FILE *f, chars mode) +{ + close(); + if (f) + { + file_mode= mode; + if ((file_id= fileno(f)) >= 0) + { + tty= isatty(file_id); + own= false; + changed(); + } + else + file_id= -1; + } + return file_id; +} + +int +cl_f::own_opened(FILE *f, chars mode) +{ + use_opened(f, mode); + own= true; + return file_id; +} + +int +cl_f::open(char *fn) +{ + close(); + if (fn) + file_name= fn; + return init(); +} + +int +cl_f::open(char *fn, char *mode) +{ + close(); + if (mode) + file_mode= mode; + if (fn) + file_name= fn; + return init(); +} + +void +cl_f::changed(void) +{ +} + +int +cl_f::close(void) +{ + int i= 0; + + if (file_id >= 0) + ::close(file_id); + file_id= -1; + own= false; + file_name= 0; + file_mode= 0; + changed(); + return i; +} + +int +cl_f::stop_use(void) +{ + //printf("cl_f stop_use fid=%d\n", file_id); + file_id= -1; + own= false; + file_name= 0; + file_mode= 0; + attributes_saved= 0; + changed(); + return 0; +} + +cl_f::~cl_f(void) +{ + delete hist; +} + +/* Buffer handling */ + +int +cl_f::put(int c) +{ + int n= (first_free + 1) % 1024; + if (n == last_used) + { + printf("put: %d FULL!\n",c); + return -1; + } + buffer[first_free]= c; + first_free= n; + return 0; +} + +int +cl_f::get(void) +{ + if (last_used == first_free) + { + return -1; + } + int c= buffer[last_used] & 0xff; + last_used= (last_used + 1) % 1024; + return c; +} + +int +cl_f::free_place(void) +{ + if (first_free >= last_used) + return 1024 - (first_free - last_used) -1; + return last_used - first_free -1; +} + +int +cl_f::finish_esc(int k) +{ + esc_buffer[0]= 0; + return k; +} + +int +cl_f::process_telnet(unsigned char ci) +{ + int l= strlen(esc_buffer); + esc_buffer[l]= ci; + l++; + esc_buffer[l]= 0; + if ((ci == 0xff) && + (l == 2)) + { + return finish_esc(0xff); + } + if (l == 3) + { + return finish_esc(0); + } + return 0; +} + +int +cl_f::process_csi(void) +{ + int l= strlen(esc_buffer); + if (l < 3) + return 0; + int /*f,*/ ret= 0; + char c= esc_buffer[l-1]; + + switch (esc_buffer[2]) + { + case 'M': + if (l == 6) + { + switch (esc_buffer[3]) + { + case ' ': ret= TU_BTN1; break; + case '!': ret= TU_BTN2; break; + case '"': ret= TU_BTN3; break; + case '0': ret= TU_CBTN1; break; + case '1': ret= TU_CBTN2; break; + case '2': ret= TU_CBTN3; break; + case '(': ret= TU_ABTN1; break; + case ')': ret= TU_ABTN2; break; + case '*': ret= TU_ABTN3; break; + case '`': ret= TU_SUP; break; + case 'a': ret= TU_SDOWN; break; + case 'p': ret= TU_CSUP; break; + case 'q': ret= TU_CSDOWN; break; + } + //f= ret; + ret&= ~0xffff00; + int x= (esc_buffer[4] - 0x20) & 0xff; + int y= (esc_buffer[5] - 0x20) & 0xff; + ret|= x << 16; + ret|= y << 8; + //fprintf(stderr, "Mouse: 0x%0x (f=%d,0x%x)\n", ret, f, f); + return finish_esc(ret); + } + return 0; + break; + } + // first char not recognized, check the last + switch (c) + { + case 'A': return finish_esc(TU_UP); + case 'B': return finish_esc(TU_DOWN); + case 'C': return finish_esc(TU_RIGHT); + case 'D': return finish_esc(TU_LEFT); + case 'H': return finish_esc(TU_HOME); + case 'F': return finish_esc(TU_END); + case 'E': return finish_esc(0); // NumPad 5 + case '~': + { + int n; + n= strtol(&esc_buffer[2], 0, 0); + switch (n) + { + case 1: return finish_esc(TU_HOME); + case 2: return finish_esc(TU_INS); + case 3: return finish_esc(TU_DEL); + case 4: return finish_esc(TU_END); + case 5: return finish_esc(TU_PGUP); + case 6: return finish_esc(TU_PGDOWN); + case 11: return finish_esc(TU_F1); + case 12: return finish_esc(TU_F2); + case 13: return finish_esc(TU_F3); + case 14: return finish_esc(TU_F4); + case 15: return finish_esc(TU_F5); + case 17: return finish_esc(TU_F6); + case 18: return finish_esc(TU_F7); + case 19: return finish_esc(TU_F8); + case 20: return finish_esc(TU_F9); + case 21: return finish_esc(TU_F10); + case 23: return finish_esc(TU_F11); + case 24: return finish_esc(TU_F12); + default: return finish_esc(c); + } + } + } + return 0; +} + +int +cl_f::process_esc(char c) +{ + int l; + //char s[100]; + unsigned int ci= c&0xff, b0= esc_buffer[0]&0xff; + + if (b0 == '\033') + { + l= strlen(esc_buffer); + esc_buffer[l]= c; + l++; + esc_buffer[l]= 0; + switch (esc_buffer[1]) + { + case 'O': + if (l < 3) + return 0; + switch (c) + { + case 'P': return finish_esc(TU_F1); + case 'Q': return finish_esc(TU_F2); + case 'R': return finish_esc(TU_F3); + case 'S': return finish_esc(TU_F4); + case 'H': return finish_esc(TU_HOME); + case 'F': return finish_esc(TU_END); + default: return finish_esc(c); + } + break; + case 'N': + if (l < 3) + return 0; + switch (c) + { + default: return finish_esc(c); + } + break; + case '[': + return process_csi(); + break; + default: + return finish_esc(c); + } + } + else if (b0 == 0xff) + { + return process_telnet(ci); + } + else // start sequence + { + if (ci == '\033') + { + esc_buffer[0]= '\033', esc_buffer[1]= 0; + return 0; + } + if (ci == 0xff) + { + esc_buffer[0]= 0xff, esc_buffer[1]= 0; + return 0; + } + } + return c; +} + +int j= 0; + +int +cl_f::process(char c) +{ + int i; + unsigned int ci= c&0xff; + + if (!cooking) + { + if (proc_escape) + { + if ((ci == '\033') || + (esc_buffer[0] != 0)) + { + i= process_esc(ci); + if (i != 0) + return put(i); + else + return 0; + } + } + if (proc_telnet) + { + if ((ci == 0xff) || + (esc_buffer[0] != 0)) + { + ci= process_telnet(ci); + if (!ci) + { + return last_ln= 0; + } + } + + if ((ci == '\n') || + (ci == '\r') || + (ci == 0) || + (last_ln != 0)) + { + if ((last_ln == 0) && + (ci != 0)) + { + last_ln= ci; + } + else + { + if (last_ln != (int)ci) + { + return last_ln= 0; + } + if (ci == 0) + { + return last_ln= 0; + } + } + } + + } + if ((ci<31) && + (ci!='\n') && + (ci!='\r')) + { + char s[3]= "^ "; + s[1]= 'A'+ci-1; + echo_write_str(s); + } + else if (ci >= 127) + { + char s[100]; + sprintf(s, "\\%02x", ci); + echo_write_str(s); + } + else + { + echo_write(&c, 1); + } + last_ln= 0; + return put(c); + } + + int l= strlen(line); + int k= process_esc(c); + int ret= 0; + if (!k) + return last_ln= 0; + // CURSOR MOVEMENT + if (k == TU_LEFT) + { + if (cursor > 0) + { + cursor--; + echo_cursor_go_left(1); + } + } + else if (k == TU_RIGHT) + { + if (line[cursor] != 0) + { + cursor++; + echo_cursor_go_right(1); + } + } + else if ((k == TU_HOME) || + (k == 'A'-'A'+1)) + { + if (cursor > 0) + { + echo_cursor_go_left(cursor); + cursor= 0; + } + } + else if ((k == TU_END) || + (k == 'E'-'A'+1)) + { + if (line[cursor] != 0) + { + echo_cursor_go_right(l-cursor); + cursor= l; + } + } + // HISTORY + else if (k == TU_UP) + { + char *s= hist->up(line); + if (cursor > 0) + echo_cursor_go_left(cursor); + echo_cursor_save(); + while (l--) + echo_write_str(" "); + echo_cursor_restore(); + line[cursor= 0]= 0; + if (s != NULL) + { + strcpy(line, s); + echo_write_str(s); + cursor= strlen(s); + } + } + else if (k == TU_DOWN) + { + char *s= hist->down(line); + if (cursor > 0) + echo_cursor_go_left(cursor); + echo_cursor_save(); + while (l--) + echo_write_str(" "); + echo_cursor_restore(); + line[cursor= 0]= 0; + if (s != NULL) + { + strcpy(line, s); + echo_write_str(s); + cursor= strlen(s); + } + } + // FINISH EDITING + else if ((k == '\n') || + (k == '\r') || + (k == 0)) + { + if (last_ln && + (last_ln != k)) + { + last_ln= 0; + return 0; + } + last_ln= k; + for (i= 0; i<l; i++) + put(line[i]); + put('\n'); + hist->enter(line); + //tu_cooked(); + line[cursor= 0]= 0; + esc_buffer[0]= 0; + ret= l+1; + echo_write_str("\n"); + } + // DELETING + else if ((k == 127) || /*DEL*/ + (k == 8 /*BS*/)) + { + if (cursor > 0) + { + for (i= cursor; line[i]; i++) + line[i-1]= line[i]; + l--; + line[l]= 0; + cursor--; + echo_cursor_go_left(1); + echo_cursor_save(); + if (line[cursor]) + echo_write_str(&line[cursor]); + echo_write_str(" "); + echo_cursor_restore(); + } + } + else if (//(k == 127) || /*DEL*/ + (k == TU_DEL)) + { + if (line[cursor] != 0) + { + for (i= cursor+1; line[i]; i++) + line[i-1]= line[i]; + l--; + line[l]= 0; + echo_cursor_save(); + if (line[cursor]) + echo_write_str(&line[cursor]); + echo_write_str(" "); + echo_cursor_restore(); + } + } + else if (k == 'K'-'A'+1) + { + if (cursor > 0) + echo_cursor_go_left(cursor); + echo_cursor_save(); + while (l--) + //write(STDOUT_FILENO, " ", 1); + echo_write_str(" "); + echo_cursor_restore(); + line[cursor= 0]= 0; + } + else if (k < 0) + ; + else if (isprint(k)) + { + if (l < /*tu_buf_size*/1023) + { + if (line[cursor] == 0) + { + line[cursor++]= k; + line[cursor]= 0; + echo_write(&c, 1); + } + else + { + int j; + for (j= l; j>=cursor; j--) + line[j+1]= line[j]; + line[cursor++]= k; + echo_cursor_save(); + echo_write(&line[cursor-1], l-cursor+2); + echo_cursor_restore(); + echo_cursor_go_right(1); + } + } + } + return ret; +} + +int +cl_f::pick(void) +{ + char b[100]; + int fp= free_place(); + if (fp < 5) + return 0; + int i= ::read(file_id, b, (fp>101)?99:fp-1); + if (i > 0) + { + int j; + for (j= 0; j < i; j++) + { + process(b[j]); + } + } + if (i == 0) + { + at_end= 1; + } + if (i < 0) + ; + return i; +} + +int +cl_f::pick(char c) +{ + int i= /*put*/process(c); + return i; +} + +int +cl_f::pick(const char *s) +{ + int i, ret= 0; + + if (s) + for (i= 0; s[i]; i++) + ret= pick(s[i]); + return ret; +} + +int +cl_f::input_avail(void) +{ + int ret= check_dev(); + if (ret) + return ret; + return at_end; +} + +int +cl_f::read(int *buf, int max) +{ + return read_dev(buf, max); +} + +int +cl_f::get_c(void) +{ + int c; + while (!check_dev()) + ; + int i= read_dev(&c, 1); + if (i > 0) + return c; + else + return i; +} + +chars +cl_f::get_s(void) +{ + chars s= ""; + char c; + + if (eof()) + return s; + c= get_c(); + while ((c == '\n') || + (c == '\r')) + { + if (eof()) + return s; + c= get_c(); + } + if (eof()) + return s; + s+= c; + c= get_c(); + while (!eof() && + (c != '\n') && + (c != '\r')) + { + s+= c; + c= get_c(); + } + return s; +} + + +/* IO primitives */ + +int +cl_f::read_dev(int *buf, int max) +{ + int i= 0, c; + + if (max == 0) + return -1; + + while (i < max) + { + c= get(); + if (c == -1) + { + if (i>0) + // got something + return i; + if (at_end) + // no more data, and we are at the end + return 0; + // buffer is empty now, but no eof detected yet + return -1; + } + buf[i]= c; + i++; + } + if (i>0) + return i; + if (at_end) + return 0; + return -2; +} + + +int +cl_f::write(char *buf, int count) +{ + int i; + if (file_id >= 0) + { + if (type != F_SOCKET) + { + return ::write(file_id, buf, count); + } + // on socket, assume telnet + for (i= 0; i < count; i++) + { + int j; + if ((buf[i] == '\r') || + (buf[i] == '\n')) + { + j= ::write(file_id, "\r\n", 2); + if (j != 2) + ; + } + else + { + j= ::write(file_id, &buf[i], 1); + if (j != 1) + ; + } + } + return i; + } + return -1; +} + + +int +cl_f::write_str(char *s) +{ + if (!s || + !*s) + return 0; + return write(s, strlen(s)); +} + + +int +cl_f::write_str(const char *s) +{ + if (!s || + !*s) + return 0; + return write((char*)s, strlen((char*)s)); +} + +int +cl_f::vprintf(const char *format, va_list ap) +{ + char *s= vformat_string(format, ap); + int i= write_str(s); + free(s); + return i; +} + +int +cl_f::prntf(const char *format, ...) +{ + va_list ap; + int ret= 0; + + va_start(ap, format); + ret= vprintf(format, ap); + va_end(ap); + + return ret; +} + +bool +cl_f::eof(void) +{ + if (file_id < 0) + return true; + return at_end && (last_used == first_free); +} + + +/*void +cl_f::flush(void) +{ +}*/ + + +/* Echoing */ + +void +cl_f::echo_cursor_save() +{ + if (echo_to) + { + echo_to->write(cchars("\033[s"), 3); + //echo_to->flush(); + } +} + +void +cl_f::echo_cursor_restore() +{ + if (echo_to) + { + echo_to->write(cchars("\033[u"), 3); + //echo_to->flush(); + } +} + +void +cl_f::echo_cursor_go_left(int n) +{ + char b[100]; + if (echo_to) + { + snprintf(b, 99, "\033[%dD", n); + echo_to->write_str(b); + //echo_to->flush(); + } +} + +void +cl_f::echo_cursor_go_right(int n) +{ + char b[100]; + if (echo_to) + { + snprintf(b, 99, "\033[%dC", n); + echo_to->write_str(b); + //echo_to->flush(); + } +} + +void +cl_f::echo_write(char *b, int l) +{ + if (echo_to) + { + if (echo_color.nempty()) + echo_to->prntf("%s", (char*)echo_color); + echo_to->write(b, l); + //echo_to->flush(); + } +} + +void +cl_f::echo_write_str(char *s) +{ + if (echo_to) + { + if (echo_color.nempty()) + echo_to->prntf("%s", (char*)echo_color); + echo_to->write_str(s); + //echo_to->flush(); + } +} + +void +cl_f::echo_write_str(const char *s) +{ + if (echo_to) + { + if (echo_color.nempty()) + echo_to->prntf("%s", (char*)echo_color); + echo_to->write_str(s); + //echo_to->flush(); + } +} + +void +cl_f::set_echo_color(chars col) +{ + echo_color= col; +} + + +/* Device handling */ + +void +cl_f::prepare_terminal() +{ +} + +void +cl_f::save_attributes() +{ +} + +void +cl_f::restore_attributes() +{ +} + +int +cl_f::raw(void) +{ + if (cooking) + { + int l= strlen(line), i; + for (i= 0; i<l; i++) + put(line[i]); + } + cooking= 0; + return 0; +} + + +int +cl_f::cooked(void) +{ + line[cursor= 0]= 0; + esc_buffer[0]= 0; + last_ln= 0; + if (tty) + { + cooking= 1; + } + else if (type == F_SOCKET) + { + cooking= 1; + } + else + { + } + return 0; +} + +int +cl_f::echo(class cl_f *out) +{ + if (echo_to) + { + echo_to->echo_of= NULL; + echo_to= NULL; + } + if (out != NULL) + { + out->echo_of= this; + echo_to= out; + } + return 0; +} + + +void +cl_f::interactive(class cl_f *echo_out) +{ + save_attributes(); + echo(echo_out); + cooked(); + prepare_terminal(); +} + + +void +cl_f::set_telnet(bool val) +{ + proc_telnet= val; +} + +void +cl_f::set_escape(bool val) +{ + proc_escape= val; +} + + +chars +fio_type_name(enum file_type t) +{ + switch (t) + { + case F_UNKNOWN: return "unknown"; + case F_FILE: return "file"; + case F_CHAR: return "char"; + case F_SOCKET: return "socket"; + case F_LISTENER: return "listener"; + case F_PIPE: return "pipe"; + case F_CONSOLE: return "console"; + case F_SERIAL: return "serial"; + } + return "undef"; +} + + +/* End of fio.cc */ |
