a68g-io.c

     
   1  //! @file a68g-io.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2025 J. Marcel van der Veer [algol68g@xs4all.nl].
   8  
   9  //! @section License
  10  //!
  11  //! This program is free software; you can redistribute it and/or modify it 
  12  //! under the terms of the GNU General Public License as published by the 
  13  //! Free Software Foundation; either version 3 of the License, or 
  14  //! (at your option) any later version.
  15  //!
  16  //! This program is distributed in the hope that it will be useful, but 
  17  //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  //! more details. You should have received a copy of the GNU General Public 
  20  //! License along with this program. If not, see [http://www.gnu.org/licenses/].
  21  
  22  //! @section Synopsis
  23  //!
  24  //! Low-level input-output routines.
  25  
  26  #include "a68g.h"
  27  #include "a68g-prelude.h"
  28  
  29  //! @brief Initialise output to STDOUT.
  30  
  31  void init_tty (void)
  32  {
  33    A68G (chars_in_stderr) = 0;
  34    A68G (chars_in_stdout) = 0;
  35    A68G (halt_typing) = A68G_FALSE;
  36    change_masks (TOP_NODE (&A68G_JOB), BREAKPOINT_INTERRUPT_MASK, A68G_FALSE);
  37  }
  38  
  39  //! @brief Terminate current line on STDOUT.
  40  
  41  void io_close_tty_line (void)
  42  {
  43    if (A68G (chars_in_stderr) > 0) {
  44      A68G (chars_in_stderr) = 0;
  45      io_write_string (A68G_STDERR, NEWLINE_STRING);
  46    }
  47    if (A68G (chars_in_stdout) > 0) {
  48      A68G (chars_in_stdout) = 0;
  49      io_write_string (A68G_STDOUT, NEWLINE_STRING);
  50    }
  51  }
  52  
  53  //! @brief Get a char from STDIN.
  54  
  55  char get_stdin_char (void)
  56  {
  57    char ch[4];
  58    errno = 0;
  59    ssize_t j = io_read_conv (A68G_STDIN, &(ch[0]), 1);
  60    ABEND (j < 0, ERROR_ACTION, __func__);
  61    return (char) (j == 1 ? ch[0] : EOF_CHAR);
  62  }
  63  
  64  //! @brief Read string from STDIN, until NEWLINE_STRING.
  65  
  66  char *read_string_from_tty (char *prompt)
  67  {
  68  #if defined (HAVE_READLINE)
  69    char *line = readline (prompt);
  70    if (line != NO_TEXT && strlen (line) > 0) {
  71      add_history (line);
  72    }
  73    a68g_bufcpy (A68G (input_line), line, BUFFER_SIZE);
  74    A68G (chars_in_stdout) = strlen (A68G (input_line));
  75    a68g_free (line);
  76    return A68G (input_line);
  77  #else
  78    if (prompt != NO_TEXT) {
  79      io_close_tty_line ();
  80      io_write_string (A68G_STDOUT, prompt);
  81    }
  82    int ch = get_stdin_char (), k= 0;
  83    while (ch != NEWLINE_CHAR && k < BUFFER_SIZE - 1) {
  84      if (ch == EOF_CHAR) {
  85        A68G (input_line)[0] = EOF_CHAR;
  86        A68G (input_line)[1] = NULL_CHAR;
  87        A68G (chars_in_stdout) = 1;
  88        return A68G (input_line);
  89      } else {
  90        A68G (input_line)[k++] = (char) ch;
  91        ch = get_stdin_char ();
  92      }
  93    }
  94    A68G (input_line)[k] = NULL_CHAR;
  95    size_t n = strlen (A68G (input_line));
  96    A68G (chars_in_stdout) = (ch == NEWLINE_CHAR ? 0 : (n > 0 ? n : 1));
  97    return A68G (input_line);
  98  #endif
  99  }
 100  
 101  //! @brief Write string to file.
 102  
 103  void io_write_string (FILE_T f, const char *z)
 104  {
 105    errno = 0;
 106    if (f != A68G_STDOUT && f != A68G_STDERR) {
 107  // Writing to file.
 108      ssize_t j = io_write_conv (f, z, strlen (z));
 109      ABEND (j < 0, ERROR_ACTION, __func__);
 110    } else {
 111  // Writing to TTY parts until end-of-string.
 112      int first = 0, k;
 113      do {
 114        k = first;
 115  // How far can we get?.
 116        while (z[k] != NULL_CHAR && z[k] != NEWLINE_CHAR) {
 117          k++;
 118        }
 119        if (k > first) {
 120  // Write these characters.
 121          int n = k - first;
 122          ssize_t j = io_write_conv (f, &(z[first]), (size_t) n);
 123          ABEND (j < 0, ERROR_ACTION, __func__);
 124          if (f == A68G_STDERR) {
 125            A68G (chars_in_stderr) += n;
 126          } else {
 127            A68G (chars_in_stdout) += n;
 128          }
 129        }
 130        if (z[k] == NEWLINE_CHAR) {
 131  // Pretty-print newline.
 132          k++;
 133          first = k;
 134          ssize_t j = io_write_conv (f, NEWLINE_STRING, 1);
 135          ABEND (j < 0, ERROR_ACTION, __func__);
 136          if (f == A68G_STDERR) {
 137            A68G (chars_in_stderr) = 0;
 138          } else {
 139            A68G (chars_in_stdout) = 0;
 140          }
 141        }
 142      } while (z[k] != NULL_CHAR);
 143    }
 144  }
 145  
 146  //! @brief Read bytes from file into buffer.
 147  
 148  ssize_t io_read (FILE_T fd, void *buf, size_t n)
 149  {
 150    size_t to_do = n;
 151    int restarts = 0;
 152    char *z = (char *) buf;
 153    while (to_do > 0) {
 154  #if defined (BUILD_WIN32)
 155      int bytes_read;
 156  #else
 157      ssize_t bytes_read;
 158  #endif
 159      errno = 0;
 160      bytes_read = read (fd, z, to_do);
 161      if (bytes_read < 0) {
 162        if (errno == EINTR) {
 163  // interrupt, retry.
 164          bytes_read = 0;
 165          if (restarts++ > MAX_RESTART) {
 166            return -1;
 167          }
 168        } else {
 169  // read error.
 170          return -1;
 171        }
 172      } else if (bytes_read == 0) {
 173        break;                    // EOF_CHAR
 174      }
 175      to_do -= (size_t) bytes_read;
 176      z += bytes_read;
 177    }
 178    return (ssize_t) n - (ssize_t) to_do; // return >= 0
 179  }
 180  
 181  //! @brief Writes n bytes from buffer to file.
 182  
 183  ssize_t io_write (FILE_T fd, const void *buf, size_t n)
 184  {
 185    size_t to_do = n;
 186    int restarts = 0;
 187    char *z = (char *) buf;
 188    while (to_do > 0) {
 189      ssize_t bytes_written;
 190      errno = 0;
 191      bytes_written = write (fd, z, to_do);
 192      if (bytes_written <= 0) {
 193        if (errno == EINTR) {
 194  // interrupt, retry.
 195          bytes_written = 0;
 196          if (restarts++ > MAX_RESTART) {
 197            return -1;
 198          }
 199        } else {
 200  // write error.
 201          return -1;
 202        }
 203      }
 204      to_do -= (size_t) bytes_written;
 205      z += bytes_written;
 206    }
 207    return (ssize_t) n;
 208  }
 209  
 210  //! @brief Read bytes from file into buffer.
 211  
 212  ssize_t io_read_conv (FILE_T fd, void *buf, size_t n)
 213  {
 214    size_t to_do = n;
 215    int restarts = 0;
 216    char *z = (char *) buf;
 217    while (to_do > 0) {
 218  #if defined (BUILD_WIN32)
 219      int bytes_read;
 220  #else
 221      ssize_t bytes_read;
 222  #endif
 223      errno = 0;
 224      bytes_read = read (fd, z, to_do);
 225      if (bytes_read < 0) {
 226        if (errno == EINTR) {
 227  // interrupt, retry.
 228          bytes_read = 0;
 229          if (restarts++ > MAX_RESTART) {
 230            return -1;
 231          }
 232        } else {
 233  // read error.
 234          return -1;
 235        }
 236      } else if (bytes_read == 0) {
 237        break;                    // EOF_CHAR
 238      }
 239      to_do -= (size_t) bytes_read;
 240      z += bytes_read;
 241    }
 242    return (ssize_t) n - (ssize_t) to_do;
 243  }
 244  
 245  //! @brief Writes n bytes from buffer to file.
 246  
 247  ssize_t io_write_conv (FILE_T fd, const void *buf, size_t n)
 248  {
 249    size_t to_do = n;
 250    int restarts = 0;
 251    char *z = (char *) buf;
 252    while (to_do > 0) {
 253      ssize_t bytes_written;
 254      errno = 0;
 255      bytes_written = write (fd, z, to_do);
 256      if (bytes_written <= 0) {
 257        if (errno == EINTR) {
 258  // interrupt, retry.
 259          bytes_written = 0;
 260          if (restarts++ > MAX_RESTART) {
 261            return -1;
 262          }
 263        } else {
 264  // write error.
 265          return -1;
 266        }
 267      }
 268      to_do -= (size_t) bytes_written;
 269      z += bytes_written;
 270    }
 271    return (ssize_t) n;
 272  }
     


© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)