removed libperl dependency by switching to bison/flex to parse calibration
file.
This commit is contained in:
parent
fb2bf948b2
commit
b950e1c63c
5 changed files with 492 additions and 204 deletions
16
lib/Makefile
16
lib/Makefile
|
@ -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
|
||||
|
|
260
lib/calib.c
260
lib/calib.c
|
@ -27,50 +27,16 @@
|
|||
#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}} );" );
|
||||
}
|
||||
int num_channels, i;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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 ];
|
||||
|
||||
snprintf( element, sizeof( element ),
|
||||
"$cal->{ calibrations }[ %i ]->{ subdevice };", cal_index );
|
||||
return extract_ph_integer( my_perl, element );
|
||||
}
|
||||
|
||||
static int valid_item( PerlInterpreter *my_perl, unsigned int cal_index,
|
||||
const char *item_type, unsigned int item )
|
||||
{
|
||||
int num_items, 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_channels = parsed_file->calibrations[ cal_index ].num_channels;
|
||||
if( num_channels == 0 ) return 1;
|
||||
for( i = 0; i < num_channels; i++ )
|
||||
{
|
||||
if( extract_array_element( my_perl, cal_index, item_type, i ) == item )
|
||||
if( parsed_file->calibrations[ cal_index ].channels[ i ] == channel )
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int valid_range( PerlInterpreter *my_perl, unsigned int cal_index,
|
||||
unsigned int range )
|
||||
static inline int valid_range( const struct calibration_file_contents *parsed_file,
|
||||
unsigned int cal_index, unsigned int range )
|
||||
{
|
||||
return valid_item( my_perl, cal_index, "ranges", range );
|
||||
int num_ranges, i;
|
||||
|
||||
num_ranges = parsed_file->calibrations[ cal_index ].num_ranges;
|
||||
if( num_ranges == 0 ) return 1;
|
||||
for( i = 0; i < num_ranges; i++ )
|
||||
{
|
||||
if( parsed_file->calibrations[ cal_index ].ranges[ i ] == range )
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int valid_channel( PerlInterpreter *my_perl, unsigned int cal_index,
|
||||
unsigned int channel )
|
||||
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, "channels", channel );
|
||||
int num_arefs, i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int valid_aref( PerlInterpreter *my_perl, unsigned int cal_index,
|
||||
unsigned int aref )
|
||||
{
|
||||
return valid_item( my_perl, cal_index, "arefs", aref );
|
||||
}
|
||||
|
||||
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;
|
||||
struct caldac_setting caldac;
|
||||
|
||||
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;
|
||||
}
|
||||
caldac = parsed_file->calibrations[ cal_index ].caldacs[ i ];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 );
|
||||
parsed_file = parse_calibration_file( cal_file );
|
||||
if( parsed_file == NULL ) return -1;
|
||||
|
||||
fclose( cal_file );
|
||||
|
||||
retval = check_cal_file( dev, parsed_file );
|
||||
if( retval < 0 )
|
||||
{
|
||||
cleanup_my_perl( my_perl );
|
||||
cleanup_calibration_parse();
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = check_cal_file( dev, my_perl );
|
||||
if( retval < 0 )
|
||||
{
|
||||
cleanup_my_perl( my_perl );
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
81
lib/calib_lex.l
Normal file
81
lib/calib_lex.l
Normal file
|
@ -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] ); }
|
||||
|
||||
|
||||
%%
|
||||
|
301
lib/calib_yacc.y
Normal file
301
lib/calib_yacc.y
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue