1package GPS::Babel; 2 3use warnings; 4use strict; 5use Carp; 6use Geo::Gpx 0.15; 7use File::Which qw(which); 8use IO::Handle; 9use Scalar::Util qw(blessed); 10 11our $VERSION = '0.11'; 12 13my $EXENAME = 'gpsbabel'; 14 15sub new { 16 my $class = shift; 17 my $args = shift || {}; 18 my $self = bless {}, $class; 19 20 if ( exists $args->{exename} ) { 21 my $exename = delete $args->{exename}; 22 $exename = [$exename] unless ref $exename eq 'ARRAY'; 23 $self->set_exename( @$exename ); 24 } 25 else { 26 $self->set_exename( which( $EXENAME ) || () ); 27 } 28 29 return $self; 30} 31 32sub get_exename { 33 my $self = shift; 34 return @{ $self->{exepath} }; 35} 36 37sub set_exename { 38 my $self = shift; 39 $self->{exepath} = [@_]; 40} 41 42sub check_exe { 43 my $self = shift; 44 45 my @exe = $self->get_exename; 46 croak "$EXENAME not found" unless @exe; 47 return @exe; 48} 49 50sub _with_babel { 51 my $self = shift; 52 my ( $mode, $opts, $cb ) = @_; 53 54 my @exe = $self->check_exe; 55 my $exe_desc = "'" . join( "' '", @exe ) . "'"; 56 57 my @args = ( @exe, @{$opts} ); 58 59 if ( $^O =~ /MSWin32/ ) { 60 # Windows: shell escape and collapse to a single string 61 @args = ( '"' . join( '" "', map { s/"/""/g } @args ) . '"' ); 62 } 63 64 open( my $fh, $mode, @args ) 65 or die "Can't execute $exe_desc ($!)\n"; 66 $cb->( $fh ); 67 $fh->close or die "$exe_desc failed ($?)\n"; 68} 69 70sub _with_babel_reader { 71 my $self = shift; 72 my ( $opts, $cb ) = @_; 73 74 $self->_with_babel( '-|', $opts, $cb ); 75} 76 77sub _with_babel_lines { 78 my $self = shift; 79 my ( $opts, $cb ) = @_; 80 my @buf = (); 81 my $flush = sub { 82 my $line = join '', @buf; 83 $cb->( $line ) unless $line =~ /^\s*$/; 84 @buf = (); 85 }; 86 $self->_with_babel_reader( 87 $opts, 88 sub { 89 my $fh = shift; 90 while ( defined( my $line = <$fh> ) ) { 91 chomp $line; 92 $flush->() unless $line =~ /^\s+/; 93 push @buf, $line; 94 } 95 } 96 ); 97 $flush->(); 98} 99 100sub _with_babel_writer { 101 my $self = shift; 102 my ( $opts, $cb ) = @_; 103 104 $self->_with_babel( '|-', $opts, $cb ); 105} 106 107sub _tidy { 108 my $str = shift; 109 $str = '' unless defined $str; 110 $str =~ s/^\s+//; 111 $str =~ s/\s+$//; 112 $str =~ s/\s+/ /g; 113 return $str; 114} 115 116sub _find_info { 117 my $self = shift; 118 119 my $info = { 120 formats => {}, 121 filters => {}, 122 for_ext => {} 123 }; 124 125 # Read the version 126 $self->_with_babel_reader( 127 ['-V'], 128 sub { 129 my $fh = shift; 130 local $/; 131 $info->{banner} = _tidy( <$fh> ); 132 } 133 ); 134 135 if ( $info->{banner} =~ /([\d.]+)/ ) { 136 $info->{version} = $1; 137 } 138 else { 139 $info->{version} = '0.0.0'; 140 } 141 142 my $handle_extra = sub { 143 my @extra = @_; 144 return unless @extra; 145 my $doclink = shift @extra; 146 return ( 147 doclink => $doclink, 148 @extra ? ( extra => \@extra ) : () 149 ); 150 }; 151 152 # -^3 and -%1 are 1.2.8 and later 153 if ( _cmp_ver( $info->{version}, '1.2.8' ) >= 0 ) { 154 155 # File formats 156 $self->_with_babel_lines( 157 ['-^3'], 158 sub { 159 my $ln = shift; 160 my ( $type, @f ) = split( /\t/, $ln ); 161 if ( $type eq 'file' ) { 162 my ( $modes, $name, $ext, $desc, $parent, @extra, ) = @f; 163 ( my $nmodes = $modes ) =~ tr/rw-/110/; 164 $nmodes = oct( '0b' . $nmodes ); 165 $info->{formats}->{$name} = { 166 modes => $modes, 167 nmodes => $nmodes, 168 desc => $desc, 169 parent => $parent, 170 $handle_extra->( @extra ), 171 }; 172 if ( $ext ) { 173 $ext =~ s/^[.]//; # At least one format has a stray '.' 174 $ext = lc( $ext ); 175 $info->{formats}->{$name}->{ext} = $ext; 176 push @{ $info->{for_ext}->{$ext} }, $name; 177 } 178 } 179 elsif ( $type eq 'option' ) { 180 my ( $fname, $name, $desc, $type, $default, $min, $max, 181 @extra, ) 182 = @f; 183 $info->{formats}->{$fname}->{options}->{$name} = { 184 desc => $desc, 185 type => $type, 186 default => $default || '', 187 min => $min || '', 188 max => $max || '', 189 $handle_extra->( @extra ), 190 }; 191 } 192 else { 193 194 # Something we don't know about - so ignore it 195 } 196 } 197 ); 198 199 # Filters 200 $self->_with_babel_lines( 201 ['-%1'], 202 sub { 203 my $ln = shift; 204 my ( $name, @f ) = split( /\t/, $ln ); 205 if ( $name eq 'option' ) { 206 my ( $fname, $oname, $desc, $type, @extra ) = @f; 207 my @valid = splice @extra, 0, 3; 208 $info->{filters}->{$fname}->{options}->{$oname} = { 209 desc => $desc, 210 type => $type, 211 valid => \@valid, 212 $handle_extra->( @extra ), 213 }; 214 } 215 else { 216 $info->{filters}->{$name} = { desc => $f[0] }; 217 } 218 } 219 ); 220 } 221 222 return $info; 223} 224 225sub get_info { 226 my $self = shift; 227 228 return $self->{info} ||= $self->_find_info; 229} 230 231sub banner { 232 my $self = shift; 233 return $self->get_info->{banner}; 234} 235 236sub version { 237 my $self = shift; 238 return $self->get_info->{version}; 239} 240 241sub _cmp_ver { 242 my ( $v1, $v2 ) = @_; 243 my @v1 = split( /[.]/, $v1 ); 244 my @v2 = split( /[.]/, $v2 ); 245 246 while ( @v1 && @v2 ) { 247 my $cmp = ( shift @v1 <=> shift @v2 ); 248 return $cmp if $cmp; 249 } 250 251 return @v1 <=> @v2; 252} 253 254sub got_ver { 255 my $self = shift; 256 my $need = shift; 257 my $got = $self->version; 258 return _cmp_ver( $got, $need ) >= 0; 259} 260 261sub guess_format { 262 my $self = shift; 263 my $name = shift; 264 my $dfmt = shift; 265 266 croak( "Missing filename" ) 267 unless defined( $name ); 268 269 my $info = $self->get_info; 270 271 # Format specified 272 if ( defined( $dfmt ) ) { 273 croak( "Unknown format \"$dfmt\"" ) 274 if %{ $info->{formats} } 275 && !exists( $info->{formats}->{$dfmt} ); 276 return $dfmt; 277 } 278 279 croak( "Filename \"$name\" has no extension" ) 280 unless $name =~ /[.]([^.]+)$/; 281 282 my $ext = lc( $1 ); 283 my $fmt = $info->{for_ext}->{$ext}; 284 285 croak( "No format handles extension .$ext" ) 286 unless defined( $fmt ); 287 288 my @fmt = sort @{$fmt}; 289 290 return $fmt[0] if @fmt == 1; 291 292 my $last = pop @fmt; 293 my $list = join( ' and ', join( ', ', @fmt ), $last ); 294 295 croak( "Multiple formats ($list) handle extension .$ext" ); 296} 297 298sub _convert_opts { 299 my $self = shift; 300 my $inf = shift; 301 my $outf = shift; 302 my $opts = shift || {}; 303 304 croak "Must provide input and output filenames" 305 unless defined( $outf ); 306 307 my $infmt = $self->guess_format( $inf, $opts->{in_format} ); 308 my $outfmt = $self->guess_format( $outf, $opts->{out_format} ); 309 310 my $info = $self->get_info; 311 312 my $inmd = $info->{formats}->{$infmt}->{nmodes} || 0b111111; 313 my $outmd = $info->{formats}->{$outfmt}->{nmodes} || 0b111111; 314 315 # Work out which modes can be read by the input format /and/ written by 316 # the output format. 317 my $canmd = ( $inmd >> 1 ) & $outmd; 318 319 my @proc = (); 320 push @proc, '-r' if ( $canmd & 0x01 ); 321 push @proc, '-t' if ( $canmd & 0x04 ); 322 push @proc, '-w' if ( $canmd & 0x10 ); 323 324 croak 325 "Formats $infmt and $outfmt have no read/write capabilities in common" 326 unless @proc; 327 328 my @opts = ( 329 '-p', '', @proc, '-i', $infmt, '-f', 330 $inf, '-o', $outfmt, '-F', $outf 331 ); 332 333 return @opts; 334} 335 336sub convert { 337 my $self = shift; 338 339 my @opts = $self->_convert_opts( @_ ); 340 341 $self->direct( @opts ); 342} 343 344sub direct { 345 my $self = shift; 346 347 if ( system( $self->check_exe, @_ ) ) { 348 croak( "$EXENAME failed with error " . ( ( $? == -1 ) ? $! : $? ) ); 349 } 350} 351 352sub read { 353 my $self = shift; 354 my $inf = shift; 355 my $opts = shift || {}; 356 357 require Geo::Gpx; 358 359 croak "Must provide an input filename" 360 unless defined( $inf ); 361 362 $opts->{out_format} = 'gpx'; 363 364 my @opts = $self->_convert_opts( $inf, '-', $opts ); 365 my $gpx = undef; 366 367 $self->_with_babel_reader( 368 \@opts, 369 sub { 370 my $fh = shift; 371 $gpx = Geo::Gpx->new( input => $fh ); 372 } 373 ); 374 375 return $gpx; 376} 377 378sub write { 379 my $self = shift; 380 my $outf = shift; 381 my $gpx = shift; 382 my $opts = shift || {}; 383 384 croak "Must provide some data to output" 385 unless blessed( $gpx ) && $gpx->can( 'xml' ); 386 387 $opts->{in_format} = 'gpx'; 388 389 my $xml = $gpx->xml; 390 391 my @opts = $self->_convert_opts( '-', $outf, $opts ); 392 $self->_with_babel_writer( 393 \@opts, 394 sub { 395 my $fh = shift; 396 $fh->print( $xml ); 397 } 398 ); 399} 400 4011; 402__END__ 403 404=head1 NAME 405 406GPS::Babel - Perl interface to gpsbabel 407 408=head1 VERSION 409 410This document describes GPS::Babel version 0.11 411 412=head1 SYNOPSIS 413 414 use GPS::Babel; 415 416 my $babel = GPS::Babel->new(); 417 418 # Read an OZIExplorer file into a data structure 419 my $data = $babel->read('route.ozi', 'ozi'); 420 421 # Convert a file automatically choosing input and output 422 # format based on extension 423 $babel->convert('points.wpt', 'points.gpx'); 424 425 # Call gpsbabel directly 426 $babel->direct(qw(gpsbabel -i saroute,split 427 -f in.anr -f in2.anr -o an1,type=road -F out.an1)); 428 429=head1 DESCRIPTION 430 431From L<http://gpsbabel.org/>: 432 433 GPSBabel converts waypoints, tracks, and routes from one format to 434 another, whether that format is a common mapping format like 435 Delorme, Streets and Trips, or even a serial upload or download to a 436 GPS unit such as those from Garmin and Magellan. By flattening the 437 Tower of Babel that the authors of various programs for manipulating 438 GPS data have imposed upon us, it returns to us the ability to 439 freely move our own waypoint data between the programs and hardware 440 we choose to use. 441 442As I write this C<gpsbabel> supports 96 various GPS related data 443formats. In addition to file conversion it supports upload and 444download to a number of serial and USB devices. This module provides a 445(thin) wrapper around the gpsbabel binary making it easier to use in a 446perlish way. 447 448GPSBabel supports many options including arbitrary chains of filters, 449merging data from multiple files and many format specific parameters. 450This module doesn't attempt to provide an API wrapper around all these 451options. It does however provide for simple access to the most common 452operations. For more complex cases a passthrough method (C<direct>) 453passes its arguments directly to gpsbabel with minimal preprocessing. 454 455GPSBabel is able to describe its built in filters and formats and 456enumerate the options they accept. This information is available as a 457perl data structure which may be used to construct a dynamic user 458interface that reflects the options available from the gpsbabel binary. 459 460=head2 Format Guessing 461 462C<GPS::Babel> queries the capabilities of C<gpsbabel> and can use this 463information to automatically choose input and output formats based on 464the extensions of filenames. This makes it possible to, for example, 465create tools that bulk convert a batch of files choosing the correct 466format for each one. 467 468While this can be convenient there is an important caveat: if more than 469one format is associated with a particular extension GPS::Babel will 470fail rather than risking making the wrong guess. Because new formats are 471being added to gpsbabel all the time it's possible that a format that 472can be guessed today will become ambiguous tomorrow. That raises the 473spectre of a program that works now breaking in the future. 474 475Also some formats support a particular extension without explicitly 476saying so - for example the compegps format supports .wpt files but 477gpsbabel (currently) reports that the only format explicitly associated 478with the .wpt extension is xmap. This means that C<GPS::Babel> will 479confidently guess that the format for a file called something.wpt is 480xmap even if the file contains compegps data. 481 482In general then you should only use format guessing in applications 483where the user will have the opportunity to select a format explicitly 484if an unambiguous guess can't be made. For applications that must run 485unattended or where the user doesn't have this kind of control you 486should make the choice of filter explicit by passing C<in_format> and/or 487C<out_format> options to C<read>, C<write> and C<convert> as 488appropriate. 489 490=head1 INTERFACE 491 492=over 493 494=item C<new( { options } )> 495 496Create a new C<GPS::Babel> object. Optionally the exename option may 497be used to specify the full name of the gpsbabel executable 498 499 my $babel = GPS::Babel->new({ 500 exename => 'C:\GPSBabel\gpsbabel.exe' 501 }); 502 503=item C<check_exe()> 504 505Verify that the name of the gpsbabel executable is known throwing an 506error if it isn't. This is generally called by other methods but you may 507call it yourself to cause an error to be thrown early in your program if 508gpsbabel is not available. 509 510=item C<get_info()> 511 512Returns a reference to a hash that describes the capabilities of your 513gpsbabel binary. The format of this hash is probably best explored by 514running the following script and perusing its output: 515 516 #!/usr/bin/perl -w 517 518 use strict; 519 use GPS::Babel; 520 use Data::Dumper; 521 522 $| = 1; 523 524 my $babel = GPS::Babel->new(); 525 print Dumper($babel->get_info()); 526 527This script is provided in the distribution as C<scripts/babel_info.pl>. 528 529In general the returned hash has the following structure: 530 531 $info = { 532 version => $gpsbabel_version, 533 banner => $gpsbabel_banner, 534 filters => { 535 # big hash of filters 536 }, 537 formats => { 538 # big hash of formats 539 }, 540 for_ext => { 541 # hash mapping lower case extension name to a list 542 # of formats that use that extension 543 } 544 }; 545 546The C<filters>, C<formats> and C<for_ext> hashes are only present if you have 547gpsbabel 1.2.8 or later installed. 548 549=item C<banner()> 550 551Get the GPSBabel banner string - the same string that is output by the command 552 553 $ gpsbabel -V 554 555=item C<version()> 556 557Get the GPSBabel version number. The version is extracted from the banner string. 558 559 print $babel->version(), "\n"; 560 561=item C<got_ver( $ver )> 562 563Return true if the available version of gpsbabel is equal to or greater 564than the supplied version string. For example: 565 566 die "I need gpsbabel 1.3.0 or later\n" 567 unless $babel->got_ver('1.3.0'); 568 569=item C<guess_format( $filename )> 570 571Given a filename return the name of the gpsbabel format that handles 572files of that type. Croaks with a suitable message if the format can't 573be identified from the extension. If more than one format matches an 574error listing all of the matching formats will be thrown. 575 576Optionally a format name may be supplied as the second argument in which 577case an error will be thrown if the installed gpsbabel doesn't support 578that format. 579 580Format guessing only works with gpsbabel 1.2.8 or later. As mentioned 581above, the requirement that an extension maps unambiguously to a format 582means that installing a later version of gpsbabel which adds support for 583another format that uses the same extension can cause code that used to 584work to stop working. For this reason format guessing should only be 585used in interactive programs that give the user the opportunity to 586specify a format explicitly if such an ambiguity exists. 587 588=item C<get_exename()> 589 590Get the name of the gpsbabel executable that will be used. This defaults 591to whatever File::Which::which('gpsbabel') returns. To use a particular 592gpsbabel binary either pass the path to the constructor using the 593'exename' option or call C<set_exename( $path )>. 594 595=item C<set_exename( $path )> 596 597Set the path and name of the gpsbabel executable to use. The executable 598doesn't have to be called 'gpsbabel' - although naming any other program 599is unlikely to have pleasing results... 600 601 $babel->set_exename('/sw/bin/gpsbabel'); 602 603=item C<read( $filename [, { $options } ] )> 604 605Read a file in a format supported by gpsbabel into a C<Geo::Gpx> object. 606The input format is guessed from the filename unless supplied explicitly 607in the options like this 608 609 $data = $babel->read('hotels.wpt', { in_format => 'xmap' }); 610 611See C<Geo::Gpx> for documentation on the returned object. 612 613=item C<write( $filename, $gpx_data [, { $options }] )> 614 615Write GPX data (typically in the form of an instance of C<Geo::Gpx>) to 616a file in one of the formats gpsbabel supports. C<$gpx_data> must be a 617reference to an object that exposes a method called C<xml> that returns 618a GPX document. C<Geo::Gpx> satisfies this requirement. 619 620The format will be guessed from the filename (see caveats above) or may 621be explicitly specified by passing a hash containing C<out_format> as 622the third argument: 623 624 $babsel->write('points.kml', $my_points, { out_format => 'kml' }); 625 626For consistency the data is filtered through gpsbabel even if the desired 627output format is 'gpx'. If you will only be dealing with GPX files use 628C<Geo::Gpx> directly. 629 630=item C<convert( $infile, $outfile, [, { $options } ] )> 631 632Convert a file from one format to another. Both formats must be 633supported by gpsbabel. 634 635With no options C<convert> attempts to guess the input and output formats 636using C<guess_format> - see the caveats about that above. To specify the 637formats explicitly supply as a third argument a hash containing the keys 638C<in_format> and C<out_format> like this: 639 640 $babel->convert('infile.wpt', 'outfile.kml', 641 { in_format => 'compegps', out_format => 'kml' }); 642 643gpsbabel treats waypoints, tracks and routes as separate channels of 644information and not all formats support reading and writing all three. 645C<convert> attempts to convert anything that can be both read by the 646input format and written by the output format. If the formats have 647nothing in common an error will be thrown. 648 649=item C<direct( @options )> 650 651Invoke gpsbabel with the supplied options. The supplied options are passed 652unmodified to system(), for example: 653 654 $babel->direct(qw(-i gpx -f somefile.gpx -o kml -F somefile.kml)); 655 656Throws appropriate errors if gpsbabel fails. 657 658=back 659 660=head1 DIAGNOSTICS 661 662=for author to fill in: 663 List every single error and warning message that the module can 664 generate (even the ones that will "never happen"), with a full 665 explanation of each problem, one or more likely causes, and any 666 suggested remedies. 667 668=over 669 670=item C<< %s not found >> 671 672Can't find the gpsbabel executable. 673 674=item C<< Missing filename >> 675 676C<guess_format> (or a method that calls it) needs a filename from 677which to guess the format. 678 679=item C<< Unknown format "%s" >> 680 681An explicit format was passed to C<guess_format> that doesn't appear 682to be supported by the installed gpsbabel. 683 684=item C<< Filename "%s" has no extension >> 685 686Can't guess the format of a filename with no extension. 687 688=item C<< No format handles extension .%s >> 689 690The installed gpsbabel doesn't contain a format that explicitly supports 691the named extension. That doesn't necessarily mean that gpsbabel can't 692handle the file: many file formats use a number of different extensions 693and many gpsbabel input/output modules don't specify the extensions they 694support. If in doubt check the gpsbabel documentation and supply the 695format explicitly. 696 697=item C<< Multiple formats (%s) handle extension .%s >> 698 699C<guess_format> couldn't unambiguously guess the appropriate format 700from the extension. Check the gpsbabel documentation and supply an 701explicit format. 702 703=item C<< Must provide input and output filenames >> 704 705C<convert> needs input and output filenames. 706 707=item C<< Formats %s and %s have no read/write capabilities in common >> 708 709Some gpsbabel formats are read only, some are write only, some support only 710waypoints or only tracks. C<convert> couldn't find enough common ground 711between input and output formats to be able to convert any data. 712 713=item C<< %s failed with error %s >> 714 715A call to gpsbabel failed. 716 717=item C<< Must provide an input filename >> 718 719C<read> needs to know the name of the file to read. 720 721=item C<< Must provide some data to output >> 722 723C<write> needs data to output. The supplied object must expose a 724method called C<xml> that returns GPX data. Typically this is achieved 725by passing a C<Geo::Gpx>. 726 727=back 728 729=head1 CONFIGURATION AND ENVIRONMENT 730 731GPS::Babel requires no configuration files or environment variables. 732With the exception of C<direct()> all calls pass the argument -p '' to 733gpsbabel to inhibit reading of any inifile. See L<http://www.gpsbabel.org/htmldoc- 7341.3.2/inifile.html> for more details. 735 736=head1 DEPENDENCIES 737 738GPS::Babel needs gpsbabel, ideally installed on your PATH and ideally 739version 1.2.8 or later. 740 741In addition GPS::Babel requires the following Perl modules: 742 743 Geo::Gpx (for read, write) 744 File::Which 745 746=head1 INCOMPATIBILITIES 747 748GPS::Babel has only been tested with versions 1.3.0 and later of 749gpsbabel. It should work with earlier versions but it's advisable to 750upgrade to the latest version if possible. The gpsbabel developer 751community is extremely active so it's worth having the latest version 752installed. 753 754=head1 BUGS AND LIMITATIONS 755 756No bugs have been reported. 757 758Please report any bugs or feature requests to 759C<bug-gps-babel@rt.cpan.org>, or through the web interface at 760L<http://rt.cpan.org>. 761 762=head1 AUTHOR 763 764Andy Armstrong C<< <andy@hexten.net> >> 765 766Robert Lipe and numerous contributors did all the work by providing 767gpsbabel in the first place. This is just a wafer-thin layer on top of 768all their goodness. 769 770=head1 LICENCE AND COPYRIGHT 771 772Copyright (c) 2006, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved. 773 774This module is free software; you can redistribute it and/or 775modify it under the same terms as Perl itself. See L<perlartistic>. 776 777=head1 DISCLAIMER OF WARRANTY 778 779BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 780FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 781OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 782PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 783EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 784WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 785ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH 786YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 787NECESSARY SERVICING, REPAIR, OR CORRECTION. 788 789IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 790WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 791REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE 792LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, 793OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE 794THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 795RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 796FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 797SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 798SUCH DAMAGES. 799