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-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  //! 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    a68_bufcat (dst, str, BUFFER_SIZE);
  40    (*w) -= (int) 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 (A68 (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_COLLITEM) {
 121      add_to_moid_text (b, "COLLITEM", w);
 122    } else if (IS (n, IN_TYPE_MODE)) {
 123      add_to_moid_text (b, "\"SIMPLIN\"", w);
 124    } else if (IS (n, OUT_TYPE_MODE)) {
 125      add_to_moid_text (b, "\"SIMPLOUT\"", w);
 126    } else if (IS (n, ROWS_SYMBOL)) {
 127      add_to_moid_text (b, "\"ROWS\"", w);
 128    } else if (n == M_VACUUM) {
 129      add_to_moid_text (b, "\"VACUUM\"", w);
 130    } else if (IS (n, VOID_SYMBOL) || IS (n, STANDARD) || IS (n, INDICANT)) {
 131      if (DIM (n) > 0) {
 132        int k = DIM (n);
 133        if ((*w) >= k * (int) strlen ("LONG ") + (int) strlen (NSYMBOL (NODE (n)))) {
 134          while (k--) {
 135            add_to_moid_text (b, "LONG ", w);
 136          }
 137          add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 138        } else {
 139          add_to_moid_text (b, "..", w);
 140        }
 141      } else if (DIM (n) < 0) {
 142        int k = -DIM (n);
 143        if ((*w) >= k * (int) strlen ("LONG ") + (int) strlen (NSYMBOL (NODE (n)))) {
 144          while (k--) {
 145            add_to_moid_text (b, "LONG ", w);
 146          }
 147          add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 148        } else {
 149          add_to_moid_text (b, "..", w);
 150        }
 151      } else if (DIM (n) == 0) {
 152        add_to_moid_text (b, NSYMBOL (NODE (n)), w);
 153      }
 154  // Write compounded modes.
 155    } else if (IS_REF (n)) {
 156      if ((*w) >= (int) strlen ("REF ..")) {
 157        add_to_moid_text (b, "REF ", w);
 158        moid_to_string_2 (b, SUB (n), w, idf);
 159      } else {
 160        add_to_moid_text (b, "REF ..", w);
 161      }
 162    } else if (IS_FLEX (n)) {
 163      if ((*w) >= (int) strlen ("FLEX ..")) {
 164        add_to_moid_text (b, "FLEX ", w);
 165        moid_to_string_2 (b, SUB (n), w, idf);
 166      } else {
 167        add_to_moid_text (b, "FLEX ..", w);
 168      }
 169    } else if (IS_ROW (n)) {
 170      int j = (int) strlen ("[] ..") + (DIM (n) - 1) * (int) strlen (",");
 171      if ((*w) >= j) {
 172        int k = DIM (n) - 1;
 173        add_to_moid_text (b, "[", w);
 174        while (k-- > 0) {
 175          add_to_moid_text (b, ",", w);
 176        }
 177        add_to_moid_text (b, "] ", w);
 178        moid_to_string_2 (b, SUB (n), w, idf);
 179      } else if (DIM (n) == 1) {
 180        add_to_moid_text (b, "[] ..", w);
 181      } else {
 182        int k = DIM (n);
 183        add_to_moid_text (b, "[", w);
 184        while (k--) {
 185          add_to_moid_text (b, ",", w);
 186        }
 187        add_to_moid_text (b, "] ..", w);
 188      }
 189    } else if (IS_STRUCT (n)) {
 190      int j = (int) strlen ("STRUCT ()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 191      if ((*w) >= j) {
 192        POSTULATE_T *save = A68 (postulates);
 193        make_postulate (&A68 (postulates), n, NO_MOID);
 194        add_to_moid_text (b, "STRUCT (", w);
 195        pack_to_string (b, PACK (n), w, A68_TRUE, idf);
 196        add_to_moid_text (b, ")", w);
 197        free_postulate_list (A68 (postulates), save);
 198        A68 (postulates) = save;
 199      } else {
 200        int k = DIM (n);
 201        add_to_moid_text (b, "STRUCT (", w);
 202        while (k-- > 0) {
 203          add_to_moid_text (b, ",", w);
 204        }
 205        add_to_moid_text (b, ")", w);
 206      }
 207    } else if (IS_UNION (n)) {
 208      int j = (int) strlen ("UNION ()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 209      if ((*w) >= j) {
 210        POSTULATE_T *save = A68 (postulates);
 211        make_postulate (&A68 (postulates), n, NO_MOID);
 212        add_to_moid_text (b, "UNION (", w);
 213        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 214        add_to_moid_text (b, ")", w);
 215        free_postulate_list (A68 (postulates), save);
 216        A68 (postulates) = save;
 217      } else {
 218        int k = DIM (n);
 219        add_to_moid_text (b, "UNION (", w);
 220        while (k-- > 0) {
 221          add_to_moid_text (b, ",", w);
 222        }
 223        add_to_moid_text (b, ")", w);
 224      }
 225    } else if (IS (n, PROC_SYMBOL) && DIM (n) == 0) {
 226      if ((*w) >= (int) strlen ("PROC ..")) {
 227        add_to_moid_text (b, "PROC ", w);
 228        moid_to_string_2 (b, SUB (n), w, idf);
 229      } else {
 230        add_to_moid_text (b, "PROC ..", w);
 231      }
 232    } else if (IS (n, PROC_SYMBOL) && DIM (n) > 0) {
 233      int j = (int) strlen ("PROC () ..") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 234      if ((*w) >= j) {
 235        POSTULATE_T *save = A68 (postulates);
 236        make_postulate (&A68 (postulates), n, NO_MOID);
 237        add_to_moid_text (b, "PROC (", w);
 238        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 239        add_to_moid_text (b, ") ", w);
 240        moid_to_string_2 (b, SUB (n), w, idf);
 241        free_postulate_list (A68 (postulates), save);
 242        A68 (postulates) = save;
 243      } else {
 244        int k = DIM (n);
 245        add_to_moid_text (b, "PROC (", w);
 246        while (k-- > 0) {
 247          add_to_moid_text (b, ",", w);
 248        }
 249        add_to_moid_text (b, ") ..", w);
 250      }
 251    } else if (IS (n, SERIES_MODE) || IS (n, STOWED_MODE)) {
 252      int j = (int) strlen ("()") + (DIM (n) - 1) * (int) strlen (".., ") + (int) strlen ("..");
 253      if ((*w) >= j) {
 254        add_to_moid_text (b, "(", w);
 255        pack_to_string (b, PACK (n), w, A68_FALSE, idf);
 256        add_to_moid_text (b, ")", w);
 257      } else {
 258        int k = DIM (n);
 259        add_to_moid_text (b, "(", w);
 260        while (k-- > 0) {
 261          add_to_moid_text (b, ",", w);
 262        }
 263        add_to_moid_text (b, ")", w);
 264      }
 265    } else {
 266      char str[SMALL_BUFFER_SIZE];
 267      ASSERT (a68_bufprt (str, (size_t) SMALL_BUFFER_SIZE, "\\%d", ATTRIBUTE (n)) >= 0);
 268      add_to_moid_text (b, str, w);
 269    }
 270  }
 271  
 272  //! @brief Pretty-formatted mode "n"; "w" is a measure of width.
 273  
 274  char *moid_to_string (MOID_T * n, int w, NODE_T * idf)
 275  {
 276  #define MAX_MTS 8
 277  // We use a static buffer of MAX_MTS strings. This value 8 should be safe.
 278  // No more than MAX_MTS calls can be pending in for instance printf.
 279  // Instead we could allocate each string on the heap but that leaks memory. 
 280    static int mts_buff_ptr = 0;
 281    static char mts_buff[8][BUFFER_SIZE];
 282    char *a = &(mts_buff[mts_buff_ptr][0]);
 283    mts_buff_ptr++;
 284    if (mts_buff_ptr >= MAX_MTS) {
 285      mts_buff_ptr = 0;
 286    }
 287    a[0] = NULL_CHAR;
 288    if (w >= BUFFER_SIZE) {
 289      w = BUFFER_SIZE - 1;
 290    }
 291    A68 (postulates) = NO_POSTULATE;
 292    if (n != NO_MOID) {
 293      moid_to_string_2 (a, n, &w, idf);
 294    } else {
 295      a68_bufcat (a, "null", BUFFER_SIZE);
 296    }
 297    return a;
 298  #undef MAX_MTS
 299  }