removed an unneeded debug message
[comedilib.git] / lib / calib_yacc.y
1 %{
2 /*
3     lib/calib_yacc.y
4     code for parsing calibration file, generated by bison
5
6     Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25 #include "libinternal.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #include "calib_yacc.h"
29
30 #define YYERROR_VERBOSE
31 #define YYPARSE_PARAM parse_arg
32
33 typedef struct
34 {
35         comedi_calibration_t *parsed_file;
36         comedi_caldac_t caldac;
37         int cal_index;
38 } calib_yyparse_private_t;
39
40 YY_DECL;
41
42 static inline calib_yyparse_private_t* priv( calib_yyparse_private_t *parse_arg)
43 {
44         return parse_arg;
45 }
46
47 static void free_calibration_setting( comedi_calibration_setting_t *setting )
48 {
49         if( setting->channels );
50         {
51                 free( setting->channels );
52                 setting->channels = NULL;
53                 setting->num_channels = 0;
54         }
55         if( setting->ranges );
56         {
57                 free( setting->ranges );
58                 setting->ranges = NULL;
59                 setting->num_ranges = 0;
60         }
61         setting->num_arefs = 0;
62         if( setting->caldacs );
63         {
64                 free( setting->caldacs );
65                 setting->caldacs = NULL;
66                 setting->num_caldacs = 0;
67         }
68 }
69
70 static void free_settings( comedi_calibration_t *file_contents )
71 {
72         int i;
73
74         if( file_contents->settings == NULL ) return;
75
76         for( i = 0; i < file_contents->num_settings; i++ )
77         {
78                 free_calibration_setting( &file_contents->settings[ i ] );
79         }
80         file_contents->settings = NULL;
81 }
82
83 static int add_calibration_setting( comedi_calibration_t *file_contents )
84 {
85         comedi_calibration_setting_t *temp;
86
87         temp = realloc( file_contents->settings,
88                 ( file_contents->num_settings + 1 ) * sizeof( comedi_calibration_setting_t ) );
89         if( temp == NULL ) return -1;
90         file_contents->settings = temp;
91         memset( &file_contents->settings[ file_contents->num_settings ],
92                 0, sizeof( comedi_calibration_setting_t ) );
93
94         file_contents->num_settings++;
95         return 0;
96 }
97
98 static comedi_calibration_setting_t* current_setting( calib_yyparse_private_t *priv )
99 {
100         int retval;
101
102         while( priv->cal_index >= priv->parsed_file->num_settings )
103         {
104                 retval = add_calibration_setting( priv->parsed_file );
105                 if( retval < 0 ) return NULL;
106         }
107         return &priv->parsed_file->settings[ priv->cal_index ];
108 }
109
110 static int add_channel( calib_yyparse_private_t *priv, int channel )
111 {
112         int *temp;
113         comedi_calibration_setting_t *setting;
114
115         setting = current_setting( priv );
116         if( setting == NULL ) return -1;
117
118         temp = realloc( setting->channels, ( setting->num_channels + 1 ) * sizeof( int ) );
119         if( temp == NULL ) return -1;
120         setting->channels = temp;
121         setting->channels[ setting->num_channels++ ] = channel;
122         return 0;
123 }
124
125 static int add_range( calib_yyparse_private_t *priv, int range )
126 {
127         int *temp;
128         comedi_calibration_setting_t *setting;
129
130         setting = current_setting( priv );
131         if( setting == NULL ) return -1;
132
133         temp = realloc( setting->ranges, ( setting->num_ranges + 1 ) * sizeof( int ) );
134         if( temp == NULL ) return -1;
135         setting->ranges = temp;
136         setting->ranges[ setting->num_ranges++ ] = range;
137         return 0;
138 }
139
140 static int add_aref( calib_yyparse_private_t *priv, int aref )
141 {
142         comedi_calibration_setting_t *setting;
143
144         setting = current_setting( priv );
145         if( setting == NULL ) return -1;
146
147         if( setting->num_arefs >= sizeof( setting->arefs ) /
148                 sizeof( setting->arefs[ 0 ] ) )
149                 return -1;
150         setting->arefs[ setting->num_arefs++ ] = aref;
151         return 0;
152 }
153
154 static int add_caldac( calib_yyparse_private_t *priv,
155         comedi_caldac_t caldac )
156 {
157         comedi_caldac_t *temp;
158         comedi_calibration_setting_t *setting;
159
160         setting = current_setting( priv );
161         if( setting == NULL ) return -1;
162
163         temp = realloc( setting->caldacs, ( setting->num_caldacs + 1 ) *
164                 sizeof( comedi_caldac_t ) );
165         if( temp == NULL ) return -1;
166         setting->caldacs = temp;
167         setting->caldacs[ setting->num_caldacs++ ] = caldac;
168         return 0;
169 }
170
171 static comedi_calibration_t* alloc_calib_parse( void )
172 {
173         comedi_calibration_t *file_contents;
174
175         file_contents = malloc( sizeof( *file_contents ) );
176         if( file_contents == NULL ) return file_contents;
177         memset( file_contents, 0, sizeof( *file_contents ) );
178         return file_contents;
179 }
180
181 EXPORT_ALIAS_DEFAULT(_comedi_cleanup_calibration,comedi_cleanup_calibration,0.7.20);
182 extern void _comedi_cleanup_calibration( comedi_calibration_t *file_contents )
183 {
184         if( file_contents->driver_name )
185         {
186                 free( file_contents->driver_name );
187                 file_contents->driver_name = NULL;
188         }
189         if( file_contents->board_name )
190         {
191                 free( file_contents->board_name );
192                 file_contents->board_name = NULL;
193         }
194         free_settings( file_contents );
195         free( file_contents );
196         file_contents = NULL;
197 }
198
199 EXPORT_ALIAS_DEFAULT(_comedi_parse_calibration_file,comedi_parse_calibration_file,0.7.20);
200 extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_file_path )
201 {
202         calib_yyparse_private_t priv;
203         FILE *file;
204
205         if( cal_file_path == NULL ) return NULL;
206         
207         priv.parsed_file = alloc_calib_parse();
208         if( priv.parsed_file == NULL ) return NULL;
209         priv.cal_index = 0;
210
211         file = fopen( cal_file_path, "r" );
212         if( file == NULL )
213         {
214                 COMEDILIB_DEBUG( 3, "failed to open file\n" );
215                 return NULL;
216         }
217         calib_yyrestart( file );
218         if( calib_yyparse( &priv ) )
219         {
220                 comedi_cleanup_calibration( priv.parsed_file );
221                 priv.parsed_file = NULL;
222         }
223         fclose( file );
224         return priv.parsed_file;
225 }
226
227 %}
228
229 %pure_parser
230
231 %union
232 {
233         int  ival;
234         char *sval;
235 }
236
237 %token T_DRIVER_NAME T_BOARD_NAME T_CALIBRATIONS T_SUBDEVICE T_CHANNELS
238 %token T_RANGES T_AREFS T_CALDACS T_CHANNEL T_VALUE T_NUMBER T_STRING
239 %token T_ASSIGN
240
241 %type <ival> T_NUMBER
242 %type <sval> T_STRING
243
244 %%
245
246         input: '{' hash '}'
247                 | error
248                         {
249                                 fprintf(stderr, "input error on line %i\n", @1.first_line );
250                                 YYABORT;
251                         }
252                 ;
253
254         hash: /* empty */
255                 | hash_element
256                 | hash_element ',' hash
257                 ;
258
259         hash_element: T_DRIVER_NAME T_ASSIGN T_STRING
260                 {
261                         if( priv(parse_arg)->parsed_file->driver_name != NULL ) YYABORT;
262                         priv(parse_arg)->parsed_file->driver_name = strdup( $3 );
263                 }
264                 | T_BOARD_NAME T_ASSIGN T_STRING
265                 {
266                         if( priv(parse_arg)->parsed_file->board_name != NULL ) YYABORT;
267                         priv(parse_arg)->parsed_file->board_name = strdup( $3 );
268                 }
269                 | T_CALIBRATIONS T_ASSIGN '[' calibrations_array ']'
270                 ;
271
272         calibrations_array: /* empty */
273                 | '{' calibration_setting '}'
274                 | '{' calibration_setting '}' ',' calibrations_array
275                 ;
276
277         calibration_setting: /* empty */ { priv(parse_arg)->cal_index++; }
278                 | calibration_setting_element { priv(parse_arg)->cal_index++; }
279                 | calibration_setting_element ',' calibration_setting
280                 ;
281
282         calibration_setting_element: T_SUBDEVICE T_ASSIGN T_NUMBER
283                 {
284                         comedi_calibration_setting_t *setting;
285                         setting = current_setting( parse_arg );
286                         if( setting == NULL ) YYABORT;
287                         setting->subdevice = $3;
288                 }
289                 | T_CHANNELS T_ASSIGN '[' channels_array ']'
290                 | T_RANGES T_ASSIGN '[' ranges_array ']'
291                 | T_AREFS T_ASSIGN '[' arefs_array ']'
292                 | T_CALDACS T_ASSIGN '[' caldacs_array ']'
293                 ;
294
295         channels_array: /* empty */
296                 | channel
297                 | channel ',' channels_array
298                 ;
299
300         channel: T_NUMBER { add_channel( parse_arg, $1 ); }
301                 ;
302
303         ranges_array: /* empty */
304                 | range
305                 | range ',' ranges_array
306                 ;
307
308         range: T_NUMBER { add_range( parse_arg, $1 ); }
309                 ;
310
311         arefs_array: /* empty */
312                 | aref
313                 | aref ',' arefs_array
314                 ;
315
316         aref: T_NUMBER { add_aref( parse_arg, $1 ); }
317                 ;
318
319         caldacs_array: /* empty */
320                 | '{' caldac '}'
321                 | '{' caldac '}' ',' caldacs_array
322                 ;
323
324         caldac: /* empty */ { add_caldac( parse_arg, priv(parse_arg)->caldac ); }
325                 | caldac_element { add_caldac( parse_arg, priv(parse_arg)->caldac ); }
326                 | caldac_element ',' caldac
327                 ;
328
329         caldac_element: T_SUBDEVICE T_ASSIGN T_NUMBER { priv(parse_arg)->caldac.subdevice = $3; }
330                 | T_CHANNEL T_ASSIGN T_NUMBER { priv(parse_arg)->caldac.channel = $3; }
331                 | T_VALUE T_ASSIGN T_NUMBER { priv(parse_arg)->caldac.value = $3; }
332                 ;
333
334 %%
335
336 void calib_yyerror(char *s)
337 {
338         fprintf(stderr, "%s\n", s);
339 }
340
341
342