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


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