moids-to-string.c

     
   1  //! @file moids-to-string.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-2023 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  //! Pretty-print a MOID.
  25  
  26  #include "a68g.h"
  27  #include "a68g-prelude.h"
  28  #include "a68g-mp.h"
  29  #include "a68g-genie.h"
  30  #include "a68g-postulates.h"
  31  
  32  // A pretty printer for moids.
  33  // For example "PROC (REF STRUCT (REF SELF, UNION (INT, VOID))) REF SELF"
  34  // for a procedure yielding a pointer to an object of its own mode.
  35  
  36  void moid_to_string_2 (char *, MOID_T *, int *, NODE_T *);
  37  
  38  //! @brief Add string to MOID text.
  39  
  40  void add_to_moid_text (char *dst, char *str, int *w)
  41  {
  42    bufcat (dst, str, BUFFER_SIZE);
  43    (*w) -= (int) strlen (str);
  44  }
  45  
  46  //! @brief Find a tag, searching symbol tables towards the root.
  47  
  48  TAG_T *find_indicant_global (TABLE_T * table, MOID_T * mode)
  49  {
  50    if (table != NO_TABLE) {
  51      TAG_T *s;
  52      for (s = INDICANTS (table); s != NO_TAG; FORWARD (s)) {
  53        if (MOID (s) == mode) {
  54          return s;
  55        }
  56      }
  57      return find_indicant_global (PREVIOUS (table), mode);
  58    } else {
  59      return NO_TAG;
  60    }
  61  }
  62  
  63  //! @brief Pack to string.
  64  
  65  void pack_to_string (char *b, PACK_T * p, int *w, BOOL_T text, NODE_T * idf)
  66  {
  67    for (; p != NO_PACK; FORWARD (p)) {
  68      moid_to_string_2 (b, MOID (p), w, idf);
  69      if (text) {
  70        if (TEXT (p) != NO_TEXT) {
  71          add_to_moid_text (b, " ", w);
  72          add_to_moid_text (b, TEXT (p), w);
  73        }
  74      }
  75      if (p != NO_PACK && NEXT (p) != NO_PACK) {
  76        add_to_moid_text (b, ", ", w);
  77      }
  78    }
  79  }
  80  
  81  //! @brief Moid to string 2.
  82  
  83  void moid_to_string_2 (char *b, MOID_T * n, int *w, NODE_T * idf)
  84  {
  85  // Oops. Should not happen.
  86    if (n == NO_MOID) {
  87      add_to_moid_text (b, "null", w);;
  88      return;
  89    }
  90  // Reference to self through REF or PROC.
  91    if (is_postulated (A68 (postulates), n)) {
  92      add_to_moid_text (b, "SELF", w);
  93      return;
  94    }
  95  // If declared by a mode-declaration, present the indicant.
  96    if (idf != NO_NODE && !IS (n, STANDARD)) {
  97      TAG_T *indy = find_indicant_global (TABLE (idf), n);
  98      if (indy != NO_TAG) {
  99        add_to_moid_text (b, NSYMBOL (NODE (indy)), w);
 100        return;
 101      }
 102    }
 103  // Write the standard modes.
 104    if (n == M_HIP) {
 105      add_to_moid_text (b, "HIP", w);
 106    } else if (n == M_ERROR) {
 107      add_to_moid_text (b, "ERROR", w);
 108    } else if (n == M_UNDEFINED) {
 109      add_to_moid_text (b, "unresolved mode", w);
 110    } else if (n == M_C_STRING) {
 111      add_to_moid_text (b, "C-STRING", w);
 112    } else if (n == M_COMPLEX || n == M_COMPL) {
 113      add_to_moid_text (b, "COMPLEX", w);
 114    } else if (n == M_LONG_COMPLEX || n == M_LONG_COMPL) {
 115      add_to_moid_text (b, "LONG COMPLEX", w);
 116    } else if (n == M_LONG_LONG_COMPLEX || n == M_LONG_LONG_COMPL) {
 117      add_to_moid_text (b, "LONG LONG COMPLEX", w);
 118    } else if (n == M_STRING) {
 119      add_to_moid_text (b, "STRING", w);
 120    } else if (n == M_PIPE) {
 121      add_to_moid_text (b, "PIPE", w);
 122    } else if (n == M_SOUND) {
 123      add_to_moid_text (b, "SOUND", w);
 124    } else if (n == M_COLLITEM) {
 125      add_to_moid_text (b, "COLLITEM", w);
 126    } else if (IS (n, IN_TYPE_MODE)) {
 127      add_to_moid_text (b, "\"SIMPLIN\"", w);
 128    } else if (IS (n, OUT_TYPE_MODE)) {
 129      add_to_moid_text (b, "\"SIMPLOUT\"", w);
 130    } else if (IS (n, ROWS_SYMBOL)) {
 131      add_to_moid_text (b, "\"ROWS\"", w);
 132    } else if (n == M_VACUUM) {
 133      add_to_moid_text (b, "\"VACUUM\"", w);
 134    } else if (IS (n, VOID_SYMBOL) || IS (n, STANDARD) || IS (n, INDICANT)) {
 135      if (DIM (n) > 0) {
 136        int k = DIM (n);
 137        if ((*w) >= k * (int) strlen ("LONG ") + (int) strlen (NSYMBOL (NODE (n)))) {
 138          while (k--) {
 139            add_to_moid_text (b, "LONG ", w);
 140          }
 141          add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 142        } else {
 143          add_to_moid_text (b, "..", w);
 144        }
 145      } else if (DIM (n) < 0) {
 146        int k = -DIM (n);
 147        if ((*w) >= k * (int) strlen ("LONG ") + (int) strlen (NSYMBOL (NODE (n)))) {
 148          while (k--) {
 149            add_to_moid_text (b, "LONG ", w);
 150          }
 151          add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 152        } else {
 153          add_to_moid_text (b, "..", w);
 154        }
 155      } else if (DIM (n) == 0) {
 156        add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 157      }
 158  // Write compounded modes.
 159    } else if (IS_REF (n)) {
 160      if ((*w) >= (int) strlen ("REF ..")) {
 161        add_to_moid_text (b, "REF ", w);
 162        moid_to_string_2 (b, SUB (n), w, idf);
 163      } else {
 164        add_to_moid_text (b, "REF ..", w);
 165      }
 166    } else if (IS_FLEX (n)) {
 167      if ((*w) >= (int) strlen ("FLEX ..")) {
 168        add_to_moid_text (b, "FLEX ", w);
 169        moid_to_string_2 (b, SUB (n), w, idf);
 170      } else {
 171        add_to_moid_text (b, "FLEX ..", w);
 172      }
 173    } else if (IS_ROW (n)) {
 174      int j = (int) strlen ("[] ..") + (DIM (n) - 1) * (int) strlen (",");
 175      if ((*w) >= j) {
 176        int k = DIM (n) - 1;
 177        add_to_moid_text (b, "[", w);
 178        while (k-- > 0) {
 179          add_to_moid_text (b, ",", w);
 180        }
 181        add_to_moid_text (b, "] ", w);
 182        moid_to_string_2 (b, SUB (n), w, idf);
 183      } else if (DIM (n) == 1) {
 184        add_to_moid_text (b, "[] ..", w);
 185      } else {
 186        int k = DIM (n);
 187        add_to_moid_text (b, "[", w);
 188        while (k--) {
 189          add_to_moid_text (b, ",", w);
 190        }
 191        add_to_moid_text (b, "] ..", w);
 192      }
 193    } else if (IS_STRUCT (n)) {
 194      int j = (int) strlen ("STRUCT ()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 195      if ((*w) >= j) {
 196        POSTULATE_T *save = A68 (postulates);
 197        make_postulate (&A68 (postulates), n, NO_MOID);
 198        add_to_moid_text (b, "STRUCT (", w);
 199        pack_to_string (b, PACK (n), w, A68_TRUE, idf);
 200        add_to_moid_text (b, ")", w);
 201        free_postulate_list (A68 (postulates), save);
 202        A68 (postulates) = save;
 203      } else {
 204        int k = DIM (n);
 205        add_to_moid_text (b, "STRUCT (", w);
 206        while (k-- > 0) {
 207          add_to_moid_text (b, ",", w);
 208        }
 209        add_to_moid_text (b, ")", w);
 210      }
 211    } else if (IS_UNION (n)) {
 212      int j = (int) strlen ("UNION ()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 213      if ((*w) >= j) {
 214        POSTULATE_T *save = A68 (postulates);
 215        make_postulate (&A68 (postulates), n, NO_MOID);
 216        add_to_moid_text (b, "UNION (", w);
 217        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 218        add_to_moid_text (b, ")", w);
 219        free_postulate_list (A68 (postulates), save);
 220        A68 (postulates) = save;
 221      } else {
 222        int k = DIM (n);
 223        add_to_moid_text (b, "UNION (", w);
 224        while (k-- > 0) {
 225          add_to_moid_text (b, ",", w);
 226        }
 227        add_to_moid_text (b, ")", w);
 228      }
 229    } else if (IS (n, PROC_SYMBOL) && DIM (n) == 0) {
 230      if ((*w) >= (int) strlen ("PROC ..")) {
 231        add_to_moid_text (b, "PROC ", w);
 232        moid_to_string_2 (b, SUB (n), w, idf);
 233      } else {
 234        add_to_moid_text (b, "PROC ..", w);
 235      }
 236    } else if (IS (n, PROC_SYMBOL) && DIM (n) > 0) {
 237      int j = (int) strlen ("PROC () ..") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 238      if ((*w) >= j) {
 239        POSTULATE_T *save = A68 (postulates);
 240        make_postulate (&A68 (postulates), n, NO_MOID);
 241        add_to_moid_text (b, "PROC (", w);
 242        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 243        add_to_moid_text (b, ") ", w);
 244        moid_to_string_2 (b, SUB (n), w, idf);
 245        free_postulate_list (A68 (postulates), save);
 246        A68 (postulates) = save;
 247      } else {
 248        int k = DIM (n);
 249        add_to_moid_text (b, "PROC (", w);
 250        while (k-- > 0) {
 251          add_to_moid_text (b, ",", w);
 252        }
 253        add_to_moid_text (b, ") ..", w);
 254      }
 255    } else if (IS (n, SERIES_MODE) || IS (n, STOWED_MODE)) {
 256      int j = (int) strlen ("()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 257      if ((*w) >= j) {
 258        add_to_moid_text (b, "(", w);
 259        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 260        add_to_moid_text (b, ")", w);
 261      } else {
 262        int k = DIM (n);
 263        add_to_moid_text (b, "(", w);
 264        while (k-- > 0) {
 265          add_to_moid_text (b, ",", w);
 266        }
 267        add_to_moid_text (b, ")", w);
 268      }
 269    } else {
 270      char str[SMALL_BUFFER_SIZE];
 271      ASSERT (snprintf (str, (size_t) SMALL_BUFFER_SIZE, "\\%d", ATTRIBUTE (n)) >= 0);
 272      add_to_moid_text (b, str, w);
 273    }
 274  }
 275  
 276  //! @brief Pretty-formatted mode "n"; "w" is a measure of width.
 277  
 278  char *moid_to_string (MOID_T * n, int w, NODE_T * idf)
 279  {
 280  #define MAX_MTS 8
 281  // We use a static buffer of MAX_MTS strings. This value 8 should be safe.
 282  // No more than MAX_MTS calls can be pending in for instance printf.
 283  // Instead we could allocate each string on the heap but that leaks memory. 
 284    static int mts_buff_ptr = 0;
 285    static char mts_buff[8][BUFFER_SIZE];
 286    char *a = &(mts_buff[mts_buff_ptr][0]);
 287    mts_buff_ptr++;
 288    if (mts_buff_ptr >= MAX_MTS) {
 289      mts_buff_ptr = 0;
 290    }
 291    a[0] = NULL_CHAR;
 292    if (w >= BUFFER_SIZE) {
 293      w = BUFFER_SIZE - 1;
 294    }
 295    A68 (postulates) = NO_POSTULATE;
 296    if (n != NO_MOID) {
 297      moid_to_string_2 (a, n, &w, idf);
 298    } else {
 299      bufcat (a, "null", BUFFER_SIZE);
 300    }
 301    return a;
 302  #undef MAX_MTS
 303  }