/* do not edit automatically generated by mc from IO. */ /* IO.mod provides Read, Write, Errors procedures mapping onto 0, 1 and 2. Copyright (C) 2001-2024 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 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 3, or (at your option) any later version. GNU Modula-2 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. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "config.h" #include "system.h" #include # if !defined (PROC_D) # define PROC_D typedef void (*PROC_t) (void); typedef struct { PROC_t proc; } PROC; # endif # if !defined (TRUE) # define TRUE (1==1) # endif # if !defined (FALSE) # define FALSE (1==0) # endif #define _IO_H #define _IO_C # include "GStrLib.h" # include "GSYSTEM.h" # include "Glibc.h" # include "GFIO.h" # include "Gerrno.h" # include "GASCII.h" # include "Gtermios.h" # define MaxDefaultFd 2 typedef struct IO_BasicFds_r IO_BasicFds; typedef struct IO__T1_a IO__T1; struct IO_BasicFds_r { bool IsEof; bool IsRaw; }; struct IO__T1_a { IO_BasicFds array[MaxDefaultFd+1]; }; static IO__T1 fdState; /* IsDefaultFd - returns TRUE if, fd, is 0, 1 or 2. */ extern "C" void IO_Read (char *ch); /* doWrite - performs the write of a single character, ch, onto fd or f. */ extern "C" void IO_Write (char ch); /* doWrite - performs the write of a single character, ch, onto fd or f. */ extern "C" void IO_Error (char ch); extern "C" void IO_UnBufferedMode (int fd, bool input); extern "C" void IO_BufferedMode (int fd, bool input); /* EchoOn - turns on echoing for file descriptor, fd. This only really makes sence for a file descriptor opened for terminal input or maybe some specific file descriptor which is attached to a particular piece of hardware. */ extern "C" void IO_EchoOn (int fd, bool input); /* EchoOff - turns off echoing for file descriptor, fd. This only really makes sence for a file descriptor opened for terminal input or maybe some specific file descriptor which is attached to a particular piece of hardware. */ extern "C" void IO_EchoOff (int fd, bool input); /* IsDefaultFd - returns TRUE if, fd, is 0, 1 or 2. */ static bool IsDefaultFd (int fd); /* doWrite - performs the write of a single character, ch, onto fd or f. */ static void doWrite (int fd, FIO_File f, char ch); /* setFlag - sets or unsets the appropriate flag in, t. */ static void setFlag (termios_TERMIOS t, termios_Flag f, bool b); /* doraw - sets all the flags associated with making this file descriptor into raw input/output. */ static void doraw (termios_TERMIOS term); /* dononraw - sets all the flags associated with making this file descriptor into non raw input/output. */ static void dononraw (termios_TERMIOS term); /* Init - */ static void Init (void); /* IsDefaultFd - returns TRUE if, fd, is 0, 1 or 2. */ static bool IsDefaultFd (int fd) { return (fd <= MaxDefaultFd) && (fd >= 0); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* doWrite - performs the write of a single character, ch, onto fd or f. */ static void doWrite (int fd, FIO_File f, char ch) { int r; if (fdState.array[fd].IsRaw) { /* avoid dangling else. */ if (! fdState.array[fd].IsEof) { for (;;) { r = static_cast (libc_write (FIO_GetUnixFileDescriptor (f), &ch, static_cast (1))); if (r == 1) { return ; } else if (r == -1) { /* avoid dangling else. */ r = errno_geterrno (); if ((r != errno_EAGAIN) && (r != errno_EINTR)) { fdState.array[fd].IsEof = true; return ; } } } } } else { FIO_WriteChar (f, ch); } } /* setFlag - sets or unsets the appropriate flag in, t. */ static void setFlag (termios_TERMIOS t, termios_Flag f, bool b) { if (termios_SetFlag (t, f, b)) {} /* empty. */ } /* doraw - sets all the flags associated with making this file descriptor into raw input/output. */ static void doraw (termios_TERMIOS term) { /* * from man 3 termios * termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP * | INLCR | IGNCR | ICRNL | IXON); * termios_p->c_oflag &= ~OPOST; * termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); * termios_p->c_cflag &= ~(CSIZE | PARENB); * termios_p->c_cflag |= CS8; */ setFlag (term, termios_ignbrk, false); setFlag (term, termios_ibrkint, false); setFlag (term, termios_iparmrk, false); setFlag (term, termios_istrip, false); setFlag (term, termios_inlcr, false); setFlag (term, termios_igncr, false); setFlag (term, termios_icrnl, false); setFlag (term, termios_ixon, false); setFlag (term, termios_opost, false); setFlag (term, termios_lecho, false); setFlag (term, termios_lechonl, false); setFlag (term, termios_licanon, false); setFlag (term, termios_lisig, false); setFlag (term, termios_liexten, false); setFlag (term, termios_parenb, false); setFlag (term, termios_cs8, true); } /* dononraw - sets all the flags associated with making this file descriptor into non raw input/output. */ static void dononraw (termios_TERMIOS term) { /* * we undo these settings, (although we leave the character size alone) * * from man 3 termios * termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP * | INLCR | IGNCR | ICRNL | IXON); * termios_p->c_oflag &= ~OPOST; * termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); * termios_p->c_cflag &= ~(CSIZE | PARENB); * termios_p->c_cflag |= CS8; */ setFlag (term, termios_ignbrk, true); setFlag (term, termios_ibrkint, true); setFlag (term, termios_iparmrk, true); setFlag (term, termios_istrip, true); setFlag (term, termios_inlcr, true); setFlag (term, termios_igncr, true); setFlag (term, termios_icrnl, true); setFlag (term, termios_ixon, true); setFlag (term, termios_opost, true); setFlag (term, termios_lecho, true); setFlag (term, termios_lechonl, true); setFlag (term, termios_licanon, true); setFlag (term, termios_lisig, true); setFlag (term, termios_liexten, true); } /* Init - */ static void Init (void) { unsigned int fdi; for (fdi=0; fdi<=MaxDefaultFd; fdi++) { fdState.array[fdi].IsEof = false; fdState.array[fdi].IsRaw = false; } } /* IsDefaultFd - returns TRUE if, fd, is 0, 1 or 2. */ extern "C" void IO_Read (char *ch) { int r; FIO_FlushBuffer (FIO_StdOut); FIO_FlushBuffer (FIO_StdErr); if (fdState.array[0].IsRaw) { if (fdState.array[0].IsEof) { (*ch) = ASCII_eof; } else { for (;;) { r = static_cast (libc_read (FIO_GetUnixFileDescriptor (FIO_StdIn), ch, static_cast (1))); if (r == 1) { return ; } else if (r == -1) { /* avoid dangling else. */ r = errno_geterrno (); if (r != errno_EAGAIN) { fdState.array[0].IsEof = true; (*ch) = ASCII_eof; return ; } } } } } else { (*ch) = FIO_ReadChar (FIO_StdIn); } } /* doWrite - performs the write of a single character, ch, onto fd or f. */ extern "C" void IO_Write (char ch) { doWrite (1, FIO_StdOut, ch); } /* doWrite - performs the write of a single character, ch, onto fd or f. */ extern "C" void IO_Error (char ch) { doWrite (2, FIO_StdErr, ch); } extern "C" void IO_UnBufferedMode (int fd, bool input) { termios_TERMIOS term; int result; if (IsDefaultFd (fd)) { fdState.array[fd].IsRaw = true; } term = termios_InitTermios (); if ((termios_tcgetattr (fd, term)) == 0) { doraw (term); if (input) { result = termios_tcsetattr (fd, termios_tcsflush (), term); } else { result = termios_tcsetattr (fd, termios_tcsdrain (), term); } } term = termios_KillTermios (term); } extern "C" void IO_BufferedMode (int fd, bool input) { termios_TERMIOS term; int r; if (IsDefaultFd (fd)) { fdState.array[fd].IsRaw = false; } term = termios_InitTermios (); if ((termios_tcgetattr (fd, term)) == 0) { dononraw (term); if (input) { r = termios_tcsetattr (fd, termios_tcsflush (), term); } else { r = termios_tcsetattr (fd, termios_tcsdrain (), term); } } term = termios_KillTermios (term); } /* EchoOn - turns on echoing for file descriptor, fd. This only really makes sence for a file descriptor opened for terminal input or maybe some specific file descriptor which is attached to a particular piece of hardware. */ extern "C" void IO_EchoOn (int fd, bool input) { termios_TERMIOS term; int result; term = termios_InitTermios (); if ((termios_tcgetattr (fd, term)) == 0) { setFlag (term, termios_lecho, true); if (input) { result = termios_tcsetattr (fd, termios_tcsflush (), term); } else { result = termios_tcsetattr (fd, termios_tcsdrain (), term); } } term = termios_KillTermios (term); } /* EchoOff - turns off echoing for file descriptor, fd. This only really makes sence for a file descriptor opened for terminal input or maybe some specific file descriptor which is attached to a particular piece of hardware. */ extern "C" void IO_EchoOff (int fd, bool input) { termios_TERMIOS term; int result; term = termios_InitTermios (); if ((termios_tcgetattr (fd, term)) == 0) { setFlag (term, termios_lecho, false); if (input) { result = termios_tcsetattr (fd, termios_tcsflush (), term); } else { result = termios_tcsetattr (fd, termios_tcsdrain (), term); } } term = termios_KillTermios (term); } extern "C" void _M2_IO_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) { Init (); } extern "C" void _M2_IO_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) { }