source: libcfa/src/parseconfig.cfa@ 692db791

ADT ast-experimental enum forall-pointer-decay jacob/cs343-translation pthread-emulation qualifiedEnum
Last change on this file since 692db791 was 692db791, checked in by Jacob Prud'homme <jafprudhomme@…>, 4 years ago

Made little changes and added comments

  • Property mode set to 100644
File size: 5.7 KB
Line 
1#include <fstream.hfa>
2#include <parseargs.hfa>
3#include <stdlib.hfa>
4#include <string.h>
5#include "parseconfig.hfa"
6
7
8// *********************************** exceptions ***********************************
9
10
11static vtable(Missing_Config_Entries) Missing_Config_Entries_vt;
12
13void ?{}( Missing_Config_Entries & this, unsigned int num_missing ) {
14 this.virtual_table = &Missing_Config_Entries_vt;
15 this.num_missing = num_missing;
16}
17
18void msg( Missing_Config_Entries * ex ) {
19 serr | "The config file is missing " | ex->num_missing | " entries.";
20}
21
22
23static vtable(Parse_Failure) Parse_Failure_vt;
24
25void ?{}( Parse_Failure & this, char * failed_key, char * failed_value ) {
26 this.virtual_table = &Parse_Failure_vt;
27
28 this.failed_key = alloc( strlen( failed_key ) );
29 this.failed_value = alloc( strlen( failed_value ) );
30 strcpy( this.failed_key, failed_key );
31 strcpy( this.failed_value, failed_value );
32}
33
34void ^?{}( Parse_Failure & this ) with ( this ) {
35 free( failed_key );
36 free( failed_value );
37}
38
39void msg( Parse_Failure * ex ) {
40 serr | "Config entry " | ex->failed_key | " could not be parsed. It has value " | ex->failed_value | ".";
41}
42
43
44static vtable(Validation_Failure) Validation_Failure_vt;
45
46void ?{}( Validation_Failure & this, char * failed_key, char * failed_value ) {
47 this.virtual_table = &Validation_Failure_vt;
48
49 this.failed_key = alloc( strlen( failed_key ) );
50 this.failed_value = alloc( strlen( failed_value ) );
51 strcpy( this.failed_key, failed_key );
52 strcpy( this.failed_value, failed_value );
53}
54
55void ^?{}( Validation_Failure & this ) with ( this ) {
56 free( failed_key );
57 free( failed_value );
58}
59
60void msg( Validation_Failure * ex ) {
61 serr | "Config entry " | ex->failed_key | " could not be validated. It has value " | ex->failed_value | ".";
62}
63
64
65// *********************************** main code ***********************************
66
67
68// TODO: Replace KVPairs with vector2 when it's fully functional
69struct KVPairs {
70 size_t size, max_size;
71 * [ char *, char * ] data;
72};
73
74void ?{}( KVPairs & kvp ) with ( kvp ) { // default constructor
75 size = 0; max_size = 0; data = 0p;
76}
77
78void ?{}( KVPairs & kvp, size_t size ) { // initialization
79 kvp.[ size, max_size ] = [ 0, size ];
80 kvp.data = alloc( size );
81}
82
83void ^?{}( KVPairs & kvp ) with ( kvp ) { // destructor
84 for ( i; size ) free( data[i] );
85 free( data );
86 size = 0; max_size = 0; data = 0p;
87}
88
89void add_kv_pair( KVPairs & kv_pairs, char * k, char * v ) with ( kv_pairs ) {
90 if ( max_size == 0 ) {
91 max_size = 1;
92 data = alloc( max_size );
93 } else if ( size == max_size ) {
94 max_size *= 2;
95 data = alloc( max_size, data`realloc );
96 }
97
98 data[size].0 = alloc( strlen( k ) );
99 data[size].1 = alloc( strlen( v ) );
100 strcpy( data[size].0, k );
101 strcpy( data[size].1, v );
102 ++size;
103}
104
105
106bool comments( ifstream & in, char name[] ) {
107 while () {
108 in | name;
109 if ( eof( in ) ) return true;
110 if ( name[0] != '#' ) return false;
111 in | nl; // ignore remainder of line
112 } // while
113} // comments
114
115// Parse configuration from a file formatted in shell style
116KVPairs * parse_tabular_config_format( const char * config_file, size_t num_entries ) {
117 // TODO: Change this to a unique_ptr when we fully support returning them (move semantics)
118 * KVPairs kv_pairs = new( num_entries );
119
120 ifstream in;
121 try {
122 open( in, config_file ); // open the configuration file for input
123
124 char key[64];
125 char value[256];
126
127 while () { // parameter names can appear in any order
128 // Must add check to see if already read in a key-value pair,
129 // once we switch to using hash table as intermediate storage
130 if ( comments( in, key ) ) break; // eof ?
131 in | value;
132
133 add_kv_pair( *kv_pairs, key, value );
134
135 if ( eof( in ) ) break;
136 in | nl; // ignore remainder of line
137 } // for
138 } catch( Open_Failure * ex; ex->istream == &in ) {
139 delete( kv_pairs );
140 throw *ex;
141 } // try
142 close( in );
143
144 return kv_pairs;
145}
146
147// Parse configuration values from intermediate format
148void parse_config( const char * config_file, config_entry entries[], size_t num_entries, config_format format ) {
149 * KVPairs kv_pairs = 0p;
150 choose ( format ) {
151 case TABULAR_CONFIG:
152 kv_pairs = parse_tabular_config_format( config_file, num_entries );
153 }
154
155 int entries_so_far = 0;
156 for ( i; kv_pairs->size ) {
157 if ( entries_so_far == num_entries ) break;
158
159 char * src_key, * src_value;
160 [ src_key, src_value ] = kv_pairs->data[i];
161
162 for ( j; num_entries ) {
163 if ( strcmp( src_key, entries[j].key ) != 0 ) continue;
164 // Parse the data
165 if ( !entries[j].parse( src_value, entries[j].variable ) ) {
166 Parse_Failure * ex = new( src_key, src_value );
167 delete( kv_pairs );
168 throw *ex;
169 }
170
171 // Validate the data
172 if ( !entries[j].validate( entries[j].variable ) ) {
173 Validation_Failure * ex = new( src_key, src_value );
174 delete( kv_pairs );
175 throw *ex;
176 }
177
178 ++entries_so_far;
179
180 break;
181 }
182 }
183 // TODO: Once we get vector2+hash_table, we can more easily add the missing config keys to this error
184 if ( entries_so_far < num_entries ) {
185 delete( kv_pairs );
186 throw (Missing_Config_Entries){ num_entries - entries_so_far };
187 }
188
189 delete( kv_pairs );
190} // processConfigFile
191
192
193// *********************************** validation ***********************************
194
195
196forall(T | Relational( T ))
197bool is_nonnegative( T & value ) {
198 T zero_val = 0;
199 return value >= zero_val;
200}
201
202forall(T | Relational( T ))
203bool is_positive( T & value ) {
204 T zero_val = 0;
205 return value > zero_val;
206}
207
208forall(T | Relational( T ))
209bool is_nonpositive( T & value ) {
210 T zero_val = 0;
211 return value <= zero_val;
212}
213
214forall(T | Relational( T ))
215bool is_negative( T & value ) {
216 T zero_val = 0;
217 return value < zero_val;
218}
219
220
221// Local Variables: //
222// tab-width: 4 //
223// compile-command: "cfa parseconfig.cfa" //
224// End: //
Note: See TracBrowser for help on using the repository browser.