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)
|