summaryrefslogtreecommitdiff
path: root/sim/ucsim/fio.cc
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/fio.cc
downloadsdcc-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.cc1254
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 */