removed libperl dependency by switching to bison/flex to parse calibration
authorFrank Mori Hess <fmhess@speakeasy.net>
Wed, 5 Mar 2003 00:30:00 +0000 (00:30 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Wed, 5 Mar 2003 00:30:00 +0000 (00:30 +0000)
file.

lib/Makefile
lib/calib.c
lib/calib_lex.l [new file with mode: 0644]
lib/calib_yacc.y [new file with mode: 0644]
lib/libinternal.h

index dea449b3246e337b65454f2febd0d87286204b3a..7da559b7a2fc3439fb09a037f8348d428fbb7698 100644 (file)
@@ -2,23 +2,25 @@
 include ../Config
 include ../version
 
-PERL_LDFLAGS := -lperl $(shell perl -MConfig -e 'print $$Config{perllibs}')
-PERL_INC := $(shell perl -MConfig -e 'print $$Config{archlib}')/CORE
-
-CFLAGS += -fPIC -I../include -I. -I$(PERL_INC)
+CFLAGS += -fPIC -I../include -I.
 
 OBJS=comedi.o timer.o sv.o range.o ioctl.o filler.o timed.o error.o \
-       dio.o data.o get.o cmd.o buffer.o calib.o
+       dio.o data.o get.o cmd.o buffer.o calib.o calib_lex.o calib_yacc.o
 
 SONAME=libcomedi$(SONAME_SUFFIX).so.0
 
 libcomedi.a: $(OBJS) version_script
        #$(CC) -shared -Wl,-soname,libcomedi.so,-T,version_script -o libcomedi.so.${VERSION_CODE} $(OBJS) -lm
-       $(CC) -shared -Wl,-soname,$(SONAME) -Wl,--version-script,version_script -o libcomedi.so.${version} $(OBJS) -lm $(PERL_LDFLAGS)
+       $(CC) -shared -Wl,-soname,$(SONAME) -Wl,--version-script,version_script -o libcomedi.so.${version} $(OBJS) -lm
        $(AR) rs libcomedi.a $(OBJS)
        ln -sf libcomedi.so.${version} libcomedi.so
        ln -sf libcomedi.so.${version} libcomedi.so.0
 
 clean:
-       rm -f libcomedi.a libcomedi.so* *.o
+       rm -f libcomedi.a libcomedi.so* *.o calib_lex.c calib_yacc.c calib_yacc.h
+
+calib_lex.c:  calib_lex.l calib_yacc.h
+       flex -Pcalib_yy -o$@ $<
 
+calib_yacc.c + calib_yacc.h: calib_yacc.y
+       bison -d -y -p calib_yy -o calib_yacc.c calib_yacc.y
index c99433a805de1dd511b9309ab784c2941e7d4724..c6cce94dd75b6b3cc59e6334cf261863d38e5cfb 100644 (file)
 #include <string.h>
 #include <comedilib.h>
 #include <libinternal.h>
-#include <EXTERN.h>
-#include <perl.h>
 
-static int extract_ph_string( PerlInterpreter *my_perl, const char *perl_statement,
-       char *result, unsigned int result_size )
+static int check_cal_file( comedi_t *dev, const struct calibration_file_contents *parsed_file )
 {
-       SV *perl_retval;
-       STRLEN len;
-
-       perl_retval = eval_pv( perl_statement, FALSE );
-       strncpy( result, SvPV( perl_retval, len ), result_size );
-       return 0;
-}
-
-static int extract_ph_integer( PerlInterpreter *my_perl, const char *perl_statement )
-{
-       SV *perl_retval;
-       int result;
-
-       perl_retval = eval_pv( perl_statement, FALSE );
-       result = SvIV( perl_retval );
-       return result;
-}
-
-static int check_cal_file( comedi_t *dev, PerlInterpreter *my_perl )
-{
-       char result[ 100 ];
-       int retval;
-
-       retval = extract_ph_string( my_perl, "$cal->{driver_name};",
-               result, sizeof( result ) );
-       if( retval < 0 ) return retval;
-
-       if( strcmp( comedi_get_driver_name( dev ), result ) )
+       if( strcmp( comedi_get_driver_name( dev ), parsed_file->driver_name ) )
        {
                fprintf( stderr, "driver name does not match calibration file\n" );
                return -1;
        }
 
-       retval = extract_ph_string( my_perl, "$cal->{board_name};",
-               result, sizeof( result ) );
-       if( retval < 0 ) return retval;
-
-       if( strcmp( comedi_get_board_name( dev ), result ) )
+       if( strcmp( comedi_get_board_name( dev ), parsed_file->board_name ) )
        {
                fprintf( stderr, "board name does not match calibration file\n" );
                return -1;
@@ -79,89 +45,67 @@ static int check_cal_file( comedi_t *dev, PerlInterpreter *my_perl )
        return 0;
 }
 
-static inline int num_calibrations( PerlInterpreter *my_perl )
+static inline int valid_channel( const struct calibration_file_contents *parsed_file,
+       unsigned int cal_index, unsigned int channel )
 {
-       return extract_ph_integer( my_perl, "scalar( @{$cal->{calibrations}} );" );
-}
-
-static int extract_array_element( PerlInterpreter *my_perl, unsigned int cal_index,
-       const char *array_name, unsigned int array_index )
-{
-       char element[ 100 ];
-
-       snprintf( element, sizeof( element ),
-               "$cal->{ calibrations }[ %i ]->{ %s }[ %i ];", cal_index, array_name, array_index );
-       return extract_ph_integer( my_perl, element );
-}
+       int num_channels, i;
 
-static int extract_array_length( PerlInterpreter *my_perl, unsigned int cal_index,
-       const char *array_name )
-{
-       char element[ 100 ];
-
-       snprintf( element, sizeof( element ),
-               "scalar( @{ $cal->{ calibrations }[ %i ]->{ %s } } );", cal_index, array_name );
-       return extract_ph_integer( my_perl, element );
-}
-
-static int extract_subdevice( PerlInterpreter *my_perl, unsigned int cal_index )
-{
-       char element[ 100 ];
+       num_channels = parsed_file->calibrations[ cal_index ].num_channels;
+       if( num_channels == 0 ) return 1;
+       for( i = 0; i < num_channels; i++ )
+       {
+               if( parsed_file->calibrations[ cal_index ].channels[ i ] == channel )
+                       return 1;
+       }
 
-       snprintf( element, sizeof( element ),
-               "$cal->{ calibrations }[ %i ]->{ subdevice };", cal_index );
-       return extract_ph_integer( my_perl, element );
+       return 0;
 }
 
-static int valid_item( PerlInterpreter *my_perl, unsigned int cal_index,
-       const char *item_type, unsigned int item )
+static inline int valid_range( const struct calibration_file_contents *parsed_file,
+       unsigned int cal_index, unsigned int range )
 {
-       int num_items, i;
+       int num_ranges, i;
 
-       num_items = extract_array_length( my_perl, cal_index, item_type );
-       if( num_items < 0 ) return 0;
-       if( num_items == 0 ) return 1;
-       for( i = 0; i < num_items; i++ )
+       num_ranges = parsed_file->calibrations[ cal_index ].num_ranges;
+       if( num_ranges == 0 ) return 1;
+       for( i = 0; i < num_ranges; i++ )
        {
-               if( extract_array_element( my_perl, cal_index, item_type, i ) == item )
+               if( parsed_file->calibrations[ cal_index ].ranges[ i ] == range )
                        return 1;
        }
 
        return 0;
 }
 
-static inline int valid_range( PerlInterpreter *my_perl, unsigned int cal_index,
-       unsigned int range )
+static inline int valid_aref( const struct calibration_file_contents *parsed_file,
+       unsigned int cal_index, unsigned int aref )
 {
-       return valid_item( my_perl, cal_index, "ranges", range );
-}
+       int num_arefs, i;
 
-static inline int valid_channel( PerlInterpreter *my_perl, unsigned int cal_index,
-       unsigned int channel )
-{
-       return valid_item( my_perl, cal_index, "channels", channel );
-}
+       num_arefs = parsed_file->calibrations[ cal_index ].num_arefs;
+       if( num_arefs == 0 ) return 1;
+       for( i = 0; i < num_arefs; i++ )
+       {
+               if( parsed_file->calibrations[ cal_index ].arefs[ i ] == aref )
+                       return 1;
+       }
 
-static inline int valid_aref( PerlInterpreter *my_perl, unsigned int cal_index,
-       unsigned int aref )
-{
-       return valid_item( my_perl, cal_index, "arefs", aref );
+       return 0;
 }
 
-static int find_calibration( PerlInterpreter *my_perl, unsigned int subdev,
-       unsigned int channel, unsigned int range, unsigned int aref )
+static int find_calibration( const struct calibration_file_contents *parsed_file,
+       unsigned int subdev, unsigned int channel, unsigned int range, unsigned int aref )
 {
        int num_cals, i;
 
-       num_cals = num_calibrations( my_perl );
-       if( num_cals < 0 ) return num_cals;
+       num_cals = parsed_file->num_calibrations;
 
        for( i = 0; i < num_cals; i++ )
        {
-               if( extract_subdevice( my_perl, i ) != subdev ) continue;
-               if( valid_range( my_perl, i, range ) == 0 ) continue;
-               if( valid_channel( my_perl, i, channel ) == 0 ) continue;
-               if( valid_aref( my_perl, i, aref ) == 0 ) continue;
+               if( parsed_file->calibrations[ i ].subdevice != subdev ) continue;
+               if( valid_range( parsed_file, i, range ) == 0 ) continue;
+               if( valid_channel( parsed_file, i, channel ) == 0 ) continue;
+               if( valid_aref( parsed_file, i, aref ) == 0 ) continue;
                break;
        }
        if( i == num_cals ) return -1;
@@ -169,101 +113,27 @@ static int find_calibration( PerlInterpreter *my_perl, unsigned int subdev,
        return i;
 }
 
-static int set_calibration( comedi_t *dev, PerlInterpreter *my_perl,
+static int set_calibration( comedi_t *dev, const struct calibration_file_contents *parsed_file,
        unsigned int cal_index )
 {
        int i, retval, num_caldacs;
 
-       num_caldacs = extract_array_length( my_perl, cal_index, "caldacs" );
-       if( num_caldacs < 0 ) return num_caldacs;
+       num_caldacs = parsed_file->calibrations[ cal_index ].num_caldacs;
 
        for( i = 0; i < num_caldacs; i++ )
        {
-               int subdev, channel, value;
-               char *element;
-
-               asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{subdevice};",
-                       cal_index, i );
-               subdev = extract_ph_integer( my_perl, element );
-               free( element );
-               if( subdev < 0 )
-               {
-                       fprintf( stderr, "failed to extract subdev\n" );
-                       return subdev;
-               }
+               struct caldac_setting caldac;
 
-               asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{channel};",
-                       cal_index, i );
-               channel = extract_ph_integer( my_perl, element );
-               free( element );
-               if( channel < 0 )
-               {
-                       fprintf( stderr, "failed to extract channel\n" );
-                       return channel;
-               }
+               caldac = parsed_file->calibrations[ cal_index ].caldacs[ i ];
 
-               asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{value};",
-                       cal_index, i );
-               value = extract_ph_integer( my_perl, element );
-               free( element );
-               if( value < 0 )
-               {
-                       fprintf( stderr, "failed to extract value\n" );
-                       return value;
-               }
-
-               retval = comedi_data_write( dev, subdev, channel, 0, 0, value );
+               retval = comedi_data_write( dev, caldac.subdevice, caldac.channel,
+                       0, 0, caldac.value );
                if( retval < 0 ) return retval;
        }
 
        return 0;
 }
 
-static PerlInterpreter* alloc_my_perl( void )
-{
-       PerlInterpreter *my_perl;
-       char *embedding[] = { "", "-e", "0" };
-
-       my_perl = perl_alloc();
-       if( my_perl == NULL )
-       {
-               fprintf( stderr, "failed to alloc perl interpreter\n");
-               return my_perl;
-       }
-       perl_construct( my_perl );
-       perl_parse(my_perl, NULL, 3, embedding, NULL);
-
-       return my_perl;
-}
-
-static int startup_my_perl( PerlInterpreter *my_perl, const char *file_path )
-{
-       int retval;
-       char perl_prog[ 1024 ];
-
-       snprintf( perl_prog, sizeof( perl_prog ),
-               "
-               my $hash = `cat '%s'`;
-               eval \"\\$cal = $hash;\";
-               ", file_path );
-
-       retval = perl_run( my_perl );
-       if( retval )
-       {
-               fprintf( stderr, "nonzero exit from perl_run\n");
-               return -1;
-       }
-       eval_pv( perl_prog, FALSE );
-
-       return 0;
-}
-
-static void cleanup_my_perl( PerlInterpreter *my_perl )
-{
-       perl_destruct( my_perl );
-       perl_free( my_perl );
-}
-
 EXPORT_SYMBOL(comedi_apply_calibration,0.7.20);
 int comedi_apply_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel,
        unsigned int range, unsigned int aref, const char *cal_file_path )
@@ -272,7 +142,8 @@ int comedi_apply_calibration( comedi_t *dev, unsigned int subdev, unsigned int c
        char file_path[ 1024 ];
        int retval;
        int cal_index;
-       PerlInterpreter *my_perl;
+       FILE *cal_file;
+       const struct calibration_file_contents *parsed_file;
 
        if( cal_file_path )
        {
@@ -290,35 +161,32 @@ int comedi_apply_calibration( comedi_t *dev, unsigned int subdev, unsigned int c
                        ( unsigned long ) file_stats.st_ino );
        }
 
-       my_perl = alloc_my_perl();
-       if( my_perl == NULL )
-               return -1;
+       cal_file = fopen( file_path, "r" );
+       if( cal_file == NULL ) return -1;
 
-       retval = startup_my_perl( my_perl, file_path );
-       if( retval < 0 )
-       {
-               cleanup_my_perl( my_perl );
-               return retval;
-       }
+       parsed_file = parse_calibration_file( cal_file );
+       if( parsed_file == NULL ) return -1;
+
+       fclose( cal_file );
 
-       retval = check_cal_file( dev, my_perl );
+       retval = check_cal_file( dev, parsed_file );
        if( retval < 0 )
        {
-               cleanup_my_perl( my_perl );
+               cleanup_calibration_parse();
                return retval;
        }
 
-       cal_index = find_calibration( my_perl, subdev, channel, range, aref );
+       cal_index = find_calibration( parsed_file, subdev, channel, range, aref );
        if( cal_index < 0 )
        {
-               cleanup_my_perl( my_perl );
+               cleanup_calibration_parse();
                return cal_index;
        }
 
-       retval = set_calibration( dev, my_perl, cal_index );
+       retval = set_calibration( dev, parsed_file, cal_index );
        if( retval < 0 );
        {
-               cleanup_my_perl( my_perl );
+               cleanup_calibration_parse();
                return retval;
        }
 
diff --git a/lib/calib_lex.l b/lib/calib_lex.l
new file mode 100644 (file)
index 0000000..9e2dab4
--- /dev/null
@@ -0,0 +1,81 @@
+%option noyywrap
+
+%{
+
+/*
+    lib/calib_lex.l
+    code for parsing calibration file, generated by flex
+
+    Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation, version 2.1
+    of the License.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+    USA.
+*/
+
+#include "libinternal.h"
+#include "calib_yacc.h"
+
+YYLTYPE yylloc;
+char string_buf[ 100 ];
+char *string_buf_ptr;
+
+%}
+
+%x COMMENT
+%x STRING
+
+%%
+
+<STRING,INITIAL>\n { yylloc.first_line++; }
+
+"#" BEGIN(COMMENT);
+<COMMENT>\n { yylloc.first_line++; BEGIN(INITIAL); }
+
+\" { string_buf_ptr = string_buf; BEGIN(STRING); }
+<STRING>\" {
+               *string_buf_ptr = 0;
+               BEGIN(INITIAL);
+               calib_yylval.sval = string_buf;
+               return ( T_STRING );
+       }
+<STRING>[^\n\"]+ {
+               char *yptr = yytext;
+
+               while ( *yptr && ( string_buf_ptr - string_buf ) < sizeof( string_buf ) - 1 )
+                       *string_buf_ptr++ = *yptr++;
+       }
+
+driver_name    { return ( T_DRIVER_NAME ); }
+board_name     { return ( T_BOARD_NAME ); }
+calibrations   { return ( T_CALIBRATIONS ); }
+subdevice      { return ( T_SUBDEVICE); }
+channels       { return (T_CHANNELS); }
+ranges { return ( T_RANGES ); }
+arefs  { return ( T_AREFS ); }
+caldacs        { return ( T_CALDACS ); }
+channel        { return ( T_CHANNEL ); }
+value  { return ( T_VALUE ); }
+=>     { return ( T_ASSIGN ); };
+
+(0x)?(00)?[0-9a-fA-F]+ { calib_yylval.ival = strtol( calib_yytext, NULL, 0 );
+       return( T_NUMBER ); }
+
+[ \t]
+
+.      { return( calib_yytext[0] ); }
+
+
+%%
+
diff --git a/lib/calib_yacc.y b/lib/calib_yacc.y
new file mode 100644 (file)
index 0000000..b7f7657
--- /dev/null
@@ -0,0 +1,301 @@
+%{
+/*
+    lib/calib_yacc.y
+    code for parsing calibration file, generated by bison
+
+    Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation, version 2.1
+    of the License.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+    USA.
+*/
+
+#include <stdio.h>
+#include "libinternal.h"
+#include <string.h>
+#include <stdlib.h>
+
+#define YYERROR_VERBOSE
+
+struct calibration_file_contents file_contents;
+static struct caldac_setting caldac;
+static int cal_index;
+
+static void free_calibration_setting( struct calibration_setting *setting )
+{
+       if( setting->channels );
+       {
+               free( setting->channels );
+               setting->channels = NULL;
+               setting->num_channels = 0;
+       }
+       if( setting->ranges );
+       {
+               free( setting->ranges );
+               setting->ranges = NULL;
+               setting->num_ranges = 0;
+       }
+       setting->num_arefs = 0;
+       if( setting->caldacs );
+       {
+               free( setting->caldacs );
+               setting->caldacs = NULL;
+               setting->num_caldacs = 0;
+       }
+}
+
+static void free_calibrations( struct calibration_file_contents *file_contents )
+{
+       int i;
+
+       if( file_contents->calibrations == NULL ) return;
+
+       for( i = 0; i < file_contents->num_calibrations; i++ )
+       {
+               free_calibration_setting( &file_contents->calibrations[ i ] );
+       }
+       file_contents->calibrations = NULL;
+}
+
+static int add_calibration_setting( struct calibration_file_contents *file_contents )
+{
+       struct calibration_setting *temp;
+
+       temp = realloc( file_contents->calibrations,
+               ( file_contents->num_calibrations + 1 ) * sizeof( struct calibration_setting ) );
+       if( temp == NULL ) return -1;
+       file_contents->calibrations = temp;
+       memset( &file_contents->calibrations[ file_contents->num_calibrations ],
+               0, sizeof( struct calibration_setting ) );
+
+       file_contents->num_calibrations++;
+       return 0;
+}
+
+static struct calibration_setting* current_setting( struct calibration_file_contents *file_contents )
+{
+       int retval;
+
+       while( cal_index >= file_contents->num_calibrations )
+       {
+               retval = add_calibration_setting( file_contents );
+               if( retval < 0 ) return NULL;
+       }
+       return &file_contents->calibrations[ cal_index ];
+}
+
+static int add_channel( struct calibration_file_contents *file_contents, int channel )
+{
+       int *temp;
+       struct calibration_setting *setting;
+
+       setting = current_setting( file_contents );
+       if( setting == NULL ) return -1;
+
+       temp = realloc( setting->channels, ( setting->num_channels + 1 ) * sizeof( int ) );
+       if( temp == NULL ) return -1;
+       setting->channels = temp;
+       setting->channels[ setting->num_channels++ ] = channel;
+       return 0;
+}
+
+static int add_range( struct calibration_file_contents *file_contents, int range )
+{
+       int *temp;
+       struct calibration_setting *setting;
+
+       setting = current_setting( file_contents );
+       if( setting == NULL ) return -1;
+
+       temp = realloc( setting->ranges, ( setting->num_ranges + 1 ) * sizeof( int ) );
+       if( temp == NULL ) return -1;
+       setting->ranges = temp;
+       setting->ranges[ setting->num_ranges++ ] = range;
+       return 0;
+}
+
+static int add_aref( struct calibration_file_contents *file_contents, int aref )
+{
+       struct calibration_setting *setting;
+
+       setting = current_setting( file_contents );
+       if( setting == NULL ) return -1;
+
+       if( setting->num_arefs >= sizeof( setting->arefs ) /
+               sizeof( setting->arefs[ 0 ] ) )
+               return -1;
+       setting->arefs[ setting->num_arefs++ ] = aref;
+       return 0;
+}
+
+static int add_caldac( struct calibration_file_contents *file_contents,
+       struct caldac_setting caldac )
+{
+       struct caldac_setting *temp;
+       struct calibration_setting *setting;
+
+       setting = current_setting( file_contents );
+       if( setting == NULL ) return -1;
+
+       temp = realloc( setting->caldacs, ( setting->num_caldacs + 1 ) *
+               sizeof( struct caldac_setting ) );
+       if( temp == NULL ) return -1;
+       setting->caldacs = temp;
+       setting->caldacs[ setting->num_caldacs++ ] = caldac;
+       return 0;
+}
+
+static void init_calib_parse( void )
+{
+       memset( &file_contents, 0, sizeof( file_contents ) );
+       cal_index = 0;
+}
+
+extern void cleanup_calibration_parse( void )
+{
+       if( file_contents.driver_name )
+       {
+               free( file_contents.driver_name );
+               file_contents.driver_name = NULL;
+       }
+       if( file_contents.board_name )
+       {
+               free( file_contents.board_name );
+               file_contents.board_name = NULL;
+       }
+       free_calibrations( &file_contents );
+}
+
+extern const struct calibration_file_contents* parse_calibration_file( FILE *file )
+{
+       calib_yyrestart( file );
+       init_calib_parse();
+       if( calib_yyparse() ) return NULL;
+       return &file_contents;
+}
+
+%}
+
+%union
+{
+       int  ival;
+       char *sval;
+}
+
+%token T_DRIVER_NAME T_BOARD_NAME T_CALIBRATIONS T_SUBDEVICE T_CHANNELS
+%token T_RANGES T_AREFS T_CALDACS T_CHANNEL T_VALUE T_NUMBER T_STRING
+%token T_ASSIGN
+
+%type <ival> T_NUMBER
+%type <sval> T_STRING
+
+%%
+
+       input: '{' hash '}'
+               | error
+                       {
+                               fprintf(stderr, "input error on line %i\n", @1.first_line );
+                               return -1;
+                       }
+               ;
+
+       hash: /* empty */
+               | hash_element
+               | hash_element ',' hash
+               ;
+
+       hash_element: T_DRIVER_NAME T_ASSIGN T_STRING
+               {
+                       if( file_contents.driver_name != NULL ) YYABORT;
+                       file_contents.driver_name = strdup( $3 );
+               }
+               | T_BOARD_NAME T_ASSIGN T_STRING
+               {
+                       if( file_contents.board_name != NULL ) YYABORT;
+                       file_contents.board_name = strdup( $3 );
+               }
+               | T_CALIBRATIONS T_ASSIGN '[' calibrations_array ']'
+               ;
+
+       calibrations_array: /* empty */
+               | '{' calibration_setting '}'
+               | '{' calibration_setting '}' ',' calibrations_array
+               ;
+
+       calibration_setting: /* empty */ { cal_index++; }
+               | calibration_setting_element
+               | calibration_setting_element ',' calibration_setting
+               ;
+
+       calibration_setting_element: T_SUBDEVICE T_ASSIGN T_NUMBER
+               {
+                       struct calibration_setting *setting;
+                       setting = current_setting( &file_contents );
+                       if( setting == NULL ) YYABORT;
+                       setting->subdevice = $3;
+               }
+               | T_CHANNELS T_ASSIGN '[' channels_array ']'
+               | T_RANGES T_ASSIGN '[' ranges_array ']'
+               | T_AREFS T_ASSIGN '[' arefs_array ']'
+               | T_CALDACS T_ASSIGN '[' caldacs_array ']'
+               ;
+
+       channels_array: /* empty */
+               | channel
+               | channel ',' channels_array
+               ;
+
+       channel: T_NUMBER { add_channel( &file_contents, $1 ); }
+               ;
+
+       ranges_array: /* empty */
+               | range
+               | range ',' ranges_array
+               ;
+
+       range: T_NUMBER { add_range( &file_contents, $1 ); }
+               ;
+
+       arefs_array: /* empty */
+               | aref
+               | aref ',' arefs_array
+               ;
+
+       aref: T_NUMBER { add_aref( &file_contents, $1 ); }
+               ;
+
+       caldacs_array: /* empty */
+               | '{' caldac '}'
+               | '{' caldac '}' ',' caldacs_array
+               ;
+
+       caldac: /* empty */ { add_caldac( &file_contents, caldac ); }
+               | caldac_element
+               | caldac_element ',' caldac
+               ;
+
+       caldac_element: T_SUBDEVICE T_ASSIGN T_NUMBER { caldac.subdevice = $3; }
+               | T_CHANNEL T_ASSIGN T_NUMBER { caldac.channel = $3; }
+               | T_VALUE T_ASSIGN T_NUMBER { caldac.value = $3; }
+               ;
+
+%%
+
+void calib_yyerror(char *s)
+{
+       fprintf(stderr, "%s\n", s);
+}
+
+
+
index 139ba55d915969fc70ae5787f7785316ccf659cd..9c1bcb006d52738c667ffe0b0591e9173e5f6229 100644 (file)
@@ -151,8 +151,44 @@ enum{
        COMEDILIB_BADCHAN,
 };
 
-// used by range.c, was in comedilib.h but apparently deprecated so I put it here - fmhess
+/* used by range.c, was in comedilib.h but apparently deprecated so I put it here - fmhess */
 int comedi_get_rangetype(comedi_t *it,unsigned int subdevice,unsigned int chan);
 
+/* structs and functions used for parsing calibration files */
+struct caldac_setting
+{
+       unsigned int subdevice;
+       unsigned int channel;
+       unsigned int value;
+};
+
+struct calibration_setting
+{
+       unsigned int subdevice;
+       unsigned int *channels;
+       unsigned int num_channels;
+       unsigned int *ranges;
+       unsigned int num_ranges;
+       unsigned int arefs[ 4 ];
+       unsigned int num_arefs;
+       struct caldac_setting *caldacs;
+       unsigned int num_caldacs;
+};
+
+struct calibration_file_contents
+{
+       char *driver_name;
+       char *board_name;
+       struct calibration_setting *calibrations;
+       unsigned int num_calibrations;
+};
+
+int calib_yylex( void );
+void calib_yyerror( char *s );
+int calib_yyparse( void );
+void calib_yyrestart( FILE *calibration_file );
+const struct calibration_file_contents* parse_calibration_file( FILE *file );
+void cleanup_calibration_parse( void );
+
 #endif