rts.c

     
   1  //! @file rts.c
   2  //! @author J. Marcel van der Veer
   3  //
   4  //! @section Copyright
   5  //
   6  // This file is part of VIF - vintage FORTRAN compiler.
   7  // Copyright 2020-2024 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  //! Runtime support.
  25  
  26  #include <vif.h>
  27  #include <execinfo.h>
  28  
  29  void _vif_backtr (int_4 signal) 
  30  {
  31    void *array[10];
  32    (void) signal;
  33    fprintf (stderr, "\n** exception  ** f%d: address error: generating stack dump\n", 3201);
  34    size_t size = backtrace(array, 10);
  35    backtrace_symbols_fd(array, size, STDERR_FILENO);
  36    exit (EXIT_FAILURE);
  37  }
  38  
  39  void *f_malloc (size_t size)
  40  {
  41    void *p = malloc (size);
  42    if (p == NULL) {
  43      OVERFLOW (3202, "f_malloc");
  44    }
  45    return p;
  46  }
  47  
  48  void *f_realloc (void *q, size_t size)
  49  {
  50    void *p = realloc (q, size);
  51    if (p == NULL) {
  52      OVERFLOW (3203, "f_realloc");
  53    }
  54    return p;
  55  }
  56  
  57  char *strlower (char *s)
  58  {
  59  // We use a circular buffer for collateral calls.
  60  #define BUFS 10
  61    static int_4 buf = 0;
  62    static RECORD zb[BUFS];
  63    if (buf == BUFS) {
  64      buf = 0;
  65    }
  66    char *z = (char *) &zb[buf++];
  67    strncpy (z, s, RECLN);
  68    for (int_4 k = 0; k < (int_4) strlen (z); k++) {
  69      z[k] = tolower (z[k]);
  70    }
  71    return z;
  72  #undef BUFS
  73  }
  74  
  75  char *_strupper (char *s)
  76  {
  77  // We use a circular buffer for collateral calls.
  78  #define BUFS 10
  79    static int_4 buf = 0;
  80    static RECORD zb[BUFS];
  81    if (buf == BUFS) {
  82      buf = 0;
  83    }
  84    char *z = (char *) &zb[buf++];
  85    strncpy (z, s, RECLN);
  86    for (int_4 k = 0; k < (int_4) strlen (z); k++) {
  87      z[k] = toupper (z[k]);
  88    }
  89    return z;
  90  #undef BUFS
  91  }
  92  
  93  void RTE (const char *where, const char *text)
  94  {
  95    if (where != NULL) {
  96      fprintf (stderr, "%s: ", where);
  97    }
  98    if (errno == 0) {
  99      fprintf (stderr, "runtime error: %s.\n", text);
 100    } else {
 101      fprintf (stderr, "runtime error: %s: %s.\n", text, strerror (errno));
 102    }
 103    _vif_exit ();
 104    exit (EXIT_FAILURE);
 105  }
 106  
 107  void RTW (const char *where, const char *text)
 108  {
 109    if (where != NULL) {
 110      fprintf (stderr, "%s: ", where);
 111    }
 112    if (errno == 0) {
 113      fprintf (stderr, "runtime warning: %s.\n", text);
 114    } else {
 115      fprintf (stderr, "runtime warning: %s: %s.\n", text, strerror (errno));
 116    }
 117  }
 118  
 119  void _vif_init (void)
 120  {
 121    signal (SIGSEGV, _vif_backtr);
 122    for (int_4 k = 0; k < MAX_FILES; k++) {
 123      _ffile[k] = (FTNFILE) {
 124      .unit = NULL,.name = NULL,.form = NULL,.action = NULL,.disp = NULL,.vers = 0,.buff = NULL,.buff_init = FALSE,.buff_pos = 0,.buff_len = 0};
 125    }
 126  }
 127  
 128  void _vif_exit (void)
 129  {
 130    for (int_4 k = 0; k < MAX_FILES; k++) {
 131      if (_ffile[k].unit == NULL) {
 132      } else if (_ffile[k].unit == stdin) {
 133      } else if (_ffile[k].unit == stdout) {
 134      } else if (_ffile[k].unit == stderr) {
 135      } else {
 136        fclose (_ffile[k].unit);
 137      }
 138    }
 139  }
 140  
 141  void _cputim (real_8 *s)
 142  {
 143    struct timeval t;
 144    static real_8 start_cpu_time = -1;
 145    real_8 hand;
 146    gettimeofday (&t, NULL);
 147    hand = (real_8) t.tv_sec + t.tv_usec * 1e-6;
 148    if (start_cpu_time < 0) {
 149      start_cpu_time = hand;
 150    }
 151    *s = hand - start_cpu_time;
 152  }
 153  
 154  void _cputyd (int_4 *i)
 155  {
 156  // In a resolution of 100 us
 157    struct timeval t;
 158    static real_8 start_cpu_time = -1;
 159    real_8 hand;
 160    gettimeofday (&t, NULL);
 161    hand = (real_8) t.tv_sec + t.tv_usec * 1e-6;
 162    if (start_cpu_time < 0) {
 163      start_cpu_time = hand;
 164    }
 165    *i = (int_4) (10000 * (hand - start_cpu_time));
 166  }
 167  
 168  void _vif_freq (CALLS *c)
 169  {
 170    for (int_4 k = 0; c[k].name != NULL; k++) {
 171      printf ("%s %ld\n", c[k].name, c[k].calls);
 172    }
 173  }
 174  
 175  char *__strtok_r (char *s, const char *delim, char **save_ptr)
 176  {
 177  // Based on code from the GNU C library.
 178    char *end;
 179    if (s == NULL) {
 180      s = *save_ptr;
 181    }
 182    if (*s == '\0') {
 183      *save_ptr = s;
 184      return NULL;
 185    }
 186  // Scan leading delimiters.
 187    s += strspn (s, delim);
 188    if (*s == '\0') {
 189      *save_ptr = s;
 190      return NULL;
 191    }
 192  // Find the end of the token.
 193    end = s + strcspn (s, delim);
 194    if (*end == '\0') {
 195      *save_ptr = end;
 196      return s;
 197    }
 198  // Terminate the token and make *SAVE_PTR point_4 past it.
 199    *end = '\0';
 200    *save_ptr = end + 1;
 201    return s;
 202  }
 203  
 204  // CHARACTER*n
 205  
 206  int_4 _srecordf (char *s, const char *format, ...)
 207  {
 208    size_t N = RECLN;
 209    va_list ap;
 210    va_start (ap, format);
 211    int_4 vsnprintf (char *, size_t, const char *, va_list);
 212  // Print in new string, just in case 's' is also an argument!
 213    int_4 M = N + 16; // A bit longer so we trap too long prints.
 214    char *t = f_malloc (M);
 215    int_4 Np = vsnprintf (t, M, format, ap);
 216    va_end (ap);
 217    if (Np >= N) {
 218      free (t);
 219      OVERFLOW (3204, "_srecordf");
 220    } else {
 221      strcpy (s, t);
 222      free (t);
 223    }
 224    return Np;
 225  }
 226  
 227  char *bufcpy (char *dst, char *src, int_4 len)
 228  {
 229  // Fortran string lengths are len+1, last one is for null.
 230    memset (dst, 0, len + 1);
 231    strncpy (dst, src, len + 1);
 232    return dst;
 233  }
 234  
 235  char *bufcat (char *dst, char *src, int_4 len)
 236  {
 237  // Fortran string lengths are len+1, last one is for null.
 238    int_4 N = len - (int_4) strlen (dst);
 239    if (N > 0) {
 240      strncat (dst, src, N);
 241      dst[len] = '\0';
 242    }
 243    return dst;
 244  }
 245  
 246  char *bufrep (char *dst, char *src)
 247  {
 248  // Replace first chars of dst with src without its null char.
 249  // A(I:J) = B
 250    while (src[0] != 0 && dst[0] != 0) {
 251      (dst++)[0] = (src++)[0];
 252    }
 253    return dst;
 254  }
 255  
 256  char *_bufsub(char *dst, char *src, int_4 i, int_4 f)
 257  { 
 258    int_4 N = f - i + 1;
 259    if (N > 0 && i >= 1) {
 260      bufcpy (dst, &src[i - 1], N);
 261      dst[N] = '\0';
 262    } else {
 263      dst[0] = '\0';
 264    }
 265    return dst;
 266  }
 267  
 268  char *concat (char *dst, char *lhs, char *rhs)
 269  {
 270  // Fortran // operator.
 271    strcpy (dst, lhs);
 272    strcat (dst, rhs);
 273    return dst;
 274  }
 275  
 276  char *_char (int c)
 277  {
 278  #define N_CHARS 256
 279    static char _ch[N_CHARS][2];
 280    int N = c % N_CHARS;
 281    _ch[N][0] = (char) N;
 282    _ch[N][1] = '\0';
 283    return &_ch[N][0];
 284  #undef N_CHARS
 285  }
 286  
 287  void _srand48 (int_4 *seed)
 288  {
 289    srand48 (*seed);  
 290  }
 291  
 292  real_8 _drand48 (void)
 293  {
 294    return drand48 ();
 295  }
     


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