1 /** \file type.c
2  * split out of exppp.c 9/21/13
3  */
4 
5 #include <stdlib.h>
6 
7 #include <express/error.h>
8 #include <sc_memmgr.h>
9 
10 #include "exppp.h"
11 #include "pp.h"
12 #include "pretty_where.h"
13 #include "pretty_expr.h"
14 #include "pretty_type.h"
15 
16 /** print a type definition.  I.e., a TYPE statement */
TYPE_out(Type t,int level)17 void TYPE_out( Type t, int level ) {
18     first_newline();
19     exppp_ref_info( &t->symbol );
20 
21     raw( "%*sTYPE %s =", level, "", t->symbol.name );
22     if( TYPEget_head( t ) ) {
23         wrap( " %s", TYPEget_name( TYPEget_head( t ) ) );
24     } else {
25         TYPE_body_out( t, level + exppp_nesting_indent );
26     }
27 
28     raw( ";\n" );
29 
30     WHERE_out( t->where, level );
31 
32     raw( "%*sEND_TYPE;", level, "" );
33     tail_comment( t->symbol.name );
34 }
35 
36 /** prints type description (preceded by a space).
37  * I.e., the type of an attribute or other object
38  */
TYPE_head_out(Type t,int level)39 void TYPE_head_out( Type t, int level ) {
40     if( t->symbol.name ) {
41         int old_indent = indent2;
42         if( indent2 + ( int ) strlen( t->symbol.name ) > exppp_linelength ) {
43             indent2 = ( indent2 + level ) / 2;
44         }
45         wrap( " %s", t->symbol.name );
46         indent2 = old_indent;
47     } else {
48         TYPE_body_out( t, level );
49     }
50 }
51 
TYPEunique_or_optional_out(TypeBody tb)52 void TYPEunique_or_optional_out( TypeBody tb ) {
53     if( tb->flags.unique ) {
54         wrap( " UNIQUE" );
55     }
56     if( tb->flags.optional ) {
57         wrap( " OPTIONAL" );
58     }
59 }
60 
TYPE_body_out(Type t,int level)61 void TYPE_body_out( Type t, int level ) {
62     bool first_time = true;
63 
64     Expression expr;
65     DictionaryEntry de;
66 
67     TypeBody tb = TYPEget_body( t );
68 
69     switch( tb->type ) {
70         case integer_:
71             wrap( " INTEGER" );
72             break;
73         case real_:
74             wrap( " REAL" );
75             break;
76         case string_:
77             wrap( " STRING" );
78             break;
79         case binary_:
80             wrap( " BINARY" );
81             break;
82         case boolean_:
83             wrap( " BOOLEAN" );
84             break;
85         case logical_:
86             wrap( " LOGICAL" );
87             break;
88         case number_:
89             wrap( " NUMBER" );
90             break;
91         case entity_:
92             wrap( " %s", tb->entity->symbol.name );
93             break;
94         case aggregate_:
95         case array_:
96         case bag_:
97         case set_:
98         case list_:
99             switch( tb->type ) {
100                 /* ignore the aggregate bounds for now */
101                 case aggregate_:
102                     wrap( " AGGREGATE" );
103                     if( tb->tag ) {
104                         wrap( ":%s", tb->tag->symbol.name );
105                     }
106                     wrap( " OF" );
107                     break;
108 
109                 case array_:
110                     wrap( " ARRAY" );
111                     EXPRbounds_out( tb );
112                     wrap( " OF" );
113                     TYPEunique_or_optional_out( tb );
114                     break;
115 
116                 case bag_:
117                     wrap( " BAG" );
118                     EXPRbounds_out( tb );
119                     wrap( " OF" );
120                     break;
121 
122                 case set_:
123                     wrap( " SET" );
124                     EXPRbounds_out( tb );
125                     wrap( " OF" );
126                     break;
127 
128                 case list_:
129                     wrap( " LIST" );
130                     EXPRbounds_out( tb );
131                     wrap( " OF" );
132                     TYPEunique_or_optional_out( tb );
133                     break;
134                 default:
135                     fprintf( stderr, "exppp: Reached default case, %s:%d", __FILE__, __LINE__ );
136                     abort();
137             }
138 
139             TYPE_head_out( tb->base, level );
140             break;
141         case enumeration_: {
142             int i, count = 0;
143             char ** names;
144 
145             /*
146              * write names out in original order by first bucket sorting
147              * to a temporary array.  This is trivial since all buckets
148              * will get filled with one and only one object.
149              */
150             DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
151             while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
152                 count++;
153             }
154             names = ( char ** )sc_malloc( count * sizeof( char * ) );
155             DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
156             while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
157                 names[expr->u.integer - 1] = expr->symbol.name;
158             }
159 
160             wrap( " ENUMERATION OF\n" );
161 
162             for( i = 0; i < count; i++ ) {
163                 /* finish line from previous enum item */
164                 if( !first_time ) {
165                     raw( ",\n" );
166                 }
167 
168                 /* start new enum item */
169                 if( first_time ) {
170                     raw( "%*s( ", level, "" );
171                     first_time = false;
172                 } else {
173                     raw( "%*s ", level, "" );
174                 }
175                 raw( names[i] );
176             }
177             raw( " )" );
178             sc_free( ( char * )names );
179         }
180         break;
181         case select_:
182             wrap( " SELECT\n" );
183             LISTdo( tb->list, type, Type )
184             /* finish line from previous entity */
185             if( !first_time ) {
186                 raw( ",\n" );
187             }
188 
189             /* start new entity */
190             if( first_time ) {
191                 raw( "%*s( ", level, "" );
192                 first_time = false;
193             } else {
194                 raw( "%*s ", level, "" );
195             }
196             raw( type->symbol.name );
197             LISTod
198 
199             /* if empty, force a left paren */
200             if( first_time ) {
201                 ERRORreport_with_symbol( ERROR_select_empty, &error_sym, t->symbol.name );
202                 raw( "%*s( ", level, "" );
203             }
204             raw( " )" );
205             break;
206         case generic_:
207             wrap( " GENERIC" );
208             if( tb->tag ) {
209                 wrap( ":%s", tb->tag->symbol.name );
210             }
211             break;
212         default:
213             wrap( " (* unknown type %d *)", tb->type );
214     }
215 
216     if( tb->precision ) {
217         wrap( " ( " );
218         EXPR_out( tb->precision, 0 );
219         raw( " )" );
220     }
221     if( tb->flags.fixed ) {
222         wrap( " FIXED" );
223     }
224 }
225 
TYPEto_string(Type t)226 char * TYPEto_string( Type t ) {
227     if( prep_string() ) {
228         return placeholder;
229     }
230     TYPE_out( t, 0 );
231     return ( finish_string() );
232 }
233 
234 /** return length of buffer used */
TYPEto_buffer(Type t,char * buffer,int length)235 int TYPEto_buffer( Type t, char * buffer, int length ) {
236     if( prep_buffer( buffer, length ) ) {
237         return -1;
238     }
239     TYPE_out( t, 0 );
240     return( finish_buffer() );
241 }
242 
TYPEout(Type t)243 void TYPEout( Type t ) {
244     prep_file();
245     TYPE_out( t, 0 );
246     finish_file();
247 }
248 
TYPEhead_to_string(Type t)249 char * TYPEhead_to_string( Type t ) {
250     if( prep_string() ) {
251         return placeholder;
252     }
253     TYPE_head_out( t, 0 );
254     return ( finish_string() );
255 }
256 
257 /** return length of buffer used */
TYPEhead_to_buffer(Type t,char * buffer,int length)258 int TYPEhead_to_buffer( Type t, char * buffer, int length ) {
259     if( prep_buffer( buffer, length ) ) {
260         return -1;
261     }
262     TYPE_out( t, 0 );
263     return( finish_buffer() );
264 }
265 
TYPEhead_out(Type t)266 void TYPEhead_out( Type t ) {
267     prep_file();
268     TYPE_head_out( t, 0 );
269     finish_file();
270 }
271 
TYPEbody_to_string(Type t)272 char * TYPEbody_to_string( Type t ) {
273     if( prep_string() ) {
274         return placeholder;
275     }
276     TYPE_body_out( t, 0 );
277     return ( finish_string() );
278 }
279 
280 /** return length of buffer used */
TYPEbody_to_buffer(Type t,char * buffer,int length)281 int TYPEbody_to_buffer( Type t, char * buffer, int length ) {
282     if( prep_buffer( buffer, length ) ) {
283         return -1;
284     }
285     TYPE_body_out( t, 0 );
286     return( finish_buffer() );
287 }
288 
TYPEbody_out(Type t)289 void TYPEbody_out( Type t ) {
290     prep_file();
291     TYPE_body_out( t, 0 );
292     finish_file();
293 }
294