|
|
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-2026 J. Marcel van der Veer [algol68g@algol68genie.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 }
© 2001-2026 J.M. van der Veer
jmvdveer@algol68genie.nl