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 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|