1 %{ 2 /* 3 * CUE parser functions 4 * 5 * Copyright (C) 2010-2020, Joachim Metz <joachim.metz@gmail.com> 6 * 7 * Refer to AUTHORS for acknowledgements. 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as published by 11 * the Free Software Foundation, either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License 20 * along with this program. If not, see <https://www.gnu.org/licenses/>. 21 */ 22 23 #include <common.h> 24 #include <narrow_string.h> 25 #include <types.h> 26 27 #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) 28 #include <stdlib.h> 29 #endif 30 31 #include "libodraw_definitions.h" 32 #include "libodraw_handle.h" 33 #include "libodraw_libcerror.h" 34 #include "libodraw_libcnotify.h" 35 #include "libodraw_types.h" 36 37 #define YYMALLOC cue_scanner_alloc 38 #define YYREALLOC cue_scanner_realloc 39 #define YYFREE cue_scanner_free 40 41 #define YYLEX_PARAM NULL 42 #define YYPARSE_PARAM parser_state 43 44 #if defined( HAVE_DEBUG_OUTPUT ) 45 #define cue_parser_rule_print( string ) \ 46 if( libcnotify_verbose != 0 ) libcnotify_printf( "cue_parser: rule: %s\n", string ) 47 #else 48 #define cue_parser_rule_print( string ) 49 #endif 50 51 #if !defined( CD_SECS ) 52 /* seconds per minute */ 53 #define CD_SECS 60 54 #endif 55 56 #if !defined( CD_FRAMES ) 57 /* frames per second */ 58 #define CD_FRAMES 75 59 #endif 60 61 /* Note that the MSF are relative, so there is no need for the MSF offset correction 62 */ 63 #define cue_parser_copy_relative_msf_to_lba( msf_string, lba ) \ 64 lba = ( ( msf_string[ 0 ] - '0' ) * 10 ) + ( msf_string[ 1 ] - '0' ); \ 65 lba *= CD_SECS; \ 66 lba += ( ( msf_string[ 3 ] - '0' ) * 10 ) + ( msf_string[ 4 ] - '0' ); \ 67 lba *= CD_FRAMES; \ 68 lba += ( ( msf_string[ 6 ] - '0' ) * 10 ) + ( msf_string[ 7 ] - '0' ); 69 %} 70 71 /* %name-prefix="cue_scanner_" replaced by -p cue_scanner_ */ 72 /* %no-lines replaced by -l */ 73 74 %lex-param { (void *) NULL } 75 %parse-param { void *parser_state } 76 77 %start cue_main 78 79 %union 80 { 81 /* The numeric value 82 */ 83 uint32_t numeric_value; 84 85 /* The string value 86 */ 87 struct cue_string_value 88 { 89 /* The string data 90 */ 91 const char *data; 92 93 /* The string length 94 */ 95 size_t length; 96 97 } string_value; 98 } 99 100 %{ 101 102 typedef struct cue_parser_state cue_parser_state_t; 103 104 struct cue_parser_state 105 { 106 /* The file 107 */ 108 libodraw_handle_t *handle; 109 110 /* The error 111 */ 112 libcerror_error_t **error; 113 114 /* The previous file index 115 */ 116 int previous_file_index; 117 118 /* The current file index 119 */ 120 int current_file_index; 121 122 /* The file type 123 */ 124 uint8_t file_type; 125 126 /* Value to indicate a new file command was issued 127 */ 128 uint8_t new_file; 129 130 /* The previous file sector 131 */ 132 uint64_t previous_file_sector; 133 134 /* The file sector 135 */ 136 uint64_t file_sector; 137 138 /* The previous session start sector 139 */ 140 uint64_t previous_session_start_sector; 141 142 /* The previous lead-out start sector 143 */ 144 uint64_t previous_lead_out_start_sector; 145 146 /* The previous track start sector 147 */ 148 uint64_t previous_track_start_sector; 149 150 /* The current start sector 151 */ 152 uint64_t current_start_sector; 153 154 /* The session number of sectors 155 */ 156 uint64_t session_number_of_sectors; 157 158 /* The lead-out number of sectors 159 */ 160 uint64_t lead_out_number_of_sectors; 161 162 /* The track number of sectors 163 */ 164 uint64_t track_number_of_sectors; 165 166 /* The previous track type 167 */ 168 uint8_t previous_track_type; 169 170 /* The current track type 171 */ 172 uint8_t current_track_type; 173 174 /* The previous session 175 */ 176 int previous_session; 177 178 /* The current session 179 */ 180 int current_session; 181 182 /* The previous lead-out 183 */ 184 int previous_lead_out; 185 186 /* The current lead-out 187 */ 188 int current_lead_out; 189 190 /* The previous track 191 */ 192 int previous_track; 193 194 /* The current track 195 */ 196 int current_track; 197 198 /* The previous index 199 */ 200 int previous_index; 201 202 /* The current index 203 */ 204 int current_index; 205 }; 206 207 typedef size_t yy_size_t; 208 typedef struct yy_buffer_state* YY_BUFFER_STATE; 209 210 extern \ 211 int cue_scanner_suppress_error; 212 213 extern \ 214 int cue_scanner_lex_destroy( 215 void ); 216 217 extern \ 218 void *cue_scanner_alloc( 219 yy_size_t size ); 220 221 extern \ 222 void *cue_scanner_realloc( 223 void *buffer, 224 yy_size_t size ); 225 226 extern \ 227 void cue_scanner_free( 228 void *buffer ); 229 230 extern \ 231 int cue_scanner_lex( 232 void *user_data ); 233 234 extern \ 235 void cue_scanner_error( 236 void *parser_state, 237 const char *error_string ); 238 239 extern \ 240 YY_BUFFER_STATE cue_scanner__scan_buffer( 241 char *buffer, 242 yy_size_t buffer_size ); 243 244 extern \ 245 void cue_scanner__delete_buffer( 246 YY_BUFFER_STATE buffer_state ); 247 248 extern \ 249 size_t cue_scanner_buffer_offset; 250 251 static char *cue_parser_function = "cue_parser"; 252 253 int cue_parser_parse_buffer( 254 libodraw_handle_t *handle, 255 const uint8_t *buffer, 256 size_t buffer_size, 257 libcerror_error_t **error ); 258 259 %} 260 261 /* Associativity rules 262 */ 263 264 /* Token definitions 265 */ 266 %token CUE_END_OF_LINE 267 %token CUE_SEMI_COLON 268 269 %token <string_value> CUE_2DIGIT 270 %token <string_value> CUE_CATALOG_NUMBER 271 %token <string_value> CUE_ISRC_CODE 272 %token <string_value> CUE_KEYWORD_STRING 273 %token <string_value> CUE_MSF 274 %token <string_value> CUE_STRING 275 276 /* Reserved words 277 */ 278 %token CUE_CATALOG 279 %token CUE_CDTEXTFILE 280 %token CUE_FLAGS 281 %token CUE_FILE 282 %token CUE_INDEX 283 %token CUE_ISRC 284 %token CUE_POSTGAP 285 %token CUE_PREGAP 286 %token CUE_REMARK 287 %token CUE_TRACK 288 289 /* CD-text reserved words 290 */ 291 %token CUE_CDTEXT_ARRANGER 292 %token CUE_CDTEXT_COMPOSER 293 %token CUE_CDTEXT_DISC_ID 294 %token CUE_CDTEXT_GENRE 295 296 %token CUE_CDTEXT_MESSAGE 297 %token CUE_CDTEXT_PERFORMER 298 %token CUE_CDTEXT_SIZE_INFO 299 %token CUE_CDTEXT_SONGWRITER 300 %token CUE_CDTEXT_TITLE 301 %token CUE_CDTEXT_TOC_INFO1 302 %token CUE_CDTEXT_TOC_INFO2 303 %token CUE_CDTEXT_UPC_EAN 304 305 /* Remark reserved words 306 */ 307 %token CUE_REMARK_LEAD_OUT 308 %token CUE_REMARK_ORIGINAL_MEDIA_TYPE 309 %token CUE_REMARK_RUN_OUT 310 %token CUE_REMARK_SESSION 311 312 %% 313 314 /* Parser rules 315 */ 316 317 cue_main 318 : cue_main_items cue_file cue_main_items cue_main_tracks 319 ; 320 321 cue_main_items 322 : /* empty */ 323 | cue_main_item cue_main_items 324 ; 325 326 cue_main_item 327 : cue_catalog 328 | cue_cdtextfile 329 | cue_cdtext 330 | cue_remark_item 331 | cue_empty_line 332 ; 333 334 cue_main_tracks 335 : /* empty */ 336 | cue_main_track cue_main_tracks 337 ; 338 339 cue_main_track 340 : cue_main_track_preceding_items cue_track cue_main_track_leading_items cue_main_track_index_items cue_main_track_trailing_items 341 ; 342 343 cue_main_track_preceding_items 344 : /* empty */ 345 | cue_main_track_preceding_item cue_main_track_preceding_items 346 ; 347 348 cue_main_track_preceding_item 349 : cue_file 350 | cue_remark_item 351 | cue_empty_line 352 ; 353 354 cue_main_track_leading_items 355 : /* empty */ 356 | cue_main_track_leading_item cue_main_track_leading_items 357 ; 358 359 cue_main_track_leading_item 360 : cue_cdtext 361 | cue_flags 362 | cue_isrc 363 | cue_pregap 364 | cue_remark_item 365 | cue_empty_line 366 ; 367 368 cue_main_track_index_items 369 : /* empty */ 370 | cue_main_track_index_item cue_main_track_index_items 371 ; 372 373 cue_main_track_index_item 374 : cue_index 375 | cue_remark_item 376 | cue_empty_line 377 ; 378 379 cue_main_track_trailing_items 380 : /* empty */ 381 | cue_main_track_trailing_item cue_main_track_trailing_items 382 ; 383 384 cue_main_track_trailing_item 385 : cue_cdtext 386 | cue_postgap 387 | cue_remark_item 388 | cue_empty_line 389 ; 390 391 cue_catalog 392 : CUE_CATALOG CUE_CATALOG_NUMBER CUE_END_OF_LINE 393 { 394 cue_parser_rule_print( 395 "cue_catalog" ); 396 } 397 ; 398 399 cue_cdtext 400 : cue_cdtext_type CUE_STRING CUE_END_OF_LINE 401 { 402 cue_parser_rule_print( 403 "cue_cdtext" ); 404 } 405 ; 406 407 cue_cdtext_type 408 : CUE_CDTEXT_ARRANGER 409 | CUE_CDTEXT_COMPOSER 410 | CUE_CDTEXT_DISC_ID 411 | CUE_CDTEXT_GENRE 412 | CUE_CDTEXT_MESSAGE 413 | CUE_CDTEXT_PERFORMER 414 | CUE_CDTEXT_SIZE_INFO 415 | CUE_CDTEXT_SONGWRITER 416 | CUE_CDTEXT_TITLE 417 | CUE_CDTEXT_TOC_INFO1 418 | CUE_CDTEXT_TOC_INFO2 419 | CUE_CDTEXT_UPC_EAN 420 /* TODO IRSC definition */ 421 ; 422 423 cue_cdtextfile 424 : CUE_CDTEXTFILE CUE_STRING CUE_END_OF_LINE 425 { 426 cue_parser_rule_print( 427 "cue_cdtextfile" ); 428 } 429 ; 430 431 cue_file 432 : CUE_FILE CUE_STRING CUE_KEYWORD_STRING CUE_END_OF_LINE 433 { 434 cue_parser_rule_print( 435 "cue_file" ); 436 437 if( $2.data == NULL ) 438 { 439 libcerror_error_set( 440 ( (cue_parser_state_t *) parser_state )->error, 441 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 442 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 443 "%s: invalid filename.", 444 cue_parser_function ); 445 446 YYABORT; 447 } 448 /* TODO what about the string quotation marks */ 449 if( $3.data == NULL ) 450 { 451 libcerror_error_set( 452 ( (cue_parser_state_t *) parser_state )->error, 453 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 454 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 455 "%s: invalid file type.", 456 cue_parser_function ); 457 458 YYABORT; 459 } 460 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_UNKNOWN; 461 462 if( $3.length == 3 ) 463 { 464 if( narrow_string_compare( 465 $3.data, 466 "MP3", 467 3 ) == 0 ) 468 { 469 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_AUDIO_MPEG1_LAYER3; 470 } 471 } 472 else if( $3.length == 4 ) 473 { 474 if( narrow_string_compare( 475 $3.data, 476 "AIFF", 477 4 ) == 0 ) 478 { 479 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_AUDIO_AIFF; 480 } 481 else if( narrow_string_compare( 482 $3.data, 483 "WAVE", 484 4 ) == 0 ) 485 { 486 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_AUDIO_WAVE; 487 } 488 } 489 else if( $3.length == 6 ) 490 { 491 if( narrow_string_compare( 492 $3.data, 493 "BINARY", 494 6 ) == 0 ) 495 { 496 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_BINARY_LITTLE_ENDIAN; 497 } 498 } 499 else if( $3.length == 8 ) 500 { 501 if( narrow_string_compare( 502 $3.data, 503 "MOTOROLA", 504 8 ) == 0 ) 505 { 506 ( (cue_parser_state_t *) parser_state )->file_type = LIBODRAW_FILE_TYPE_BINARY_BIG_ENDIAN; 507 } 508 } 509 if( libodraw_handle_append_data_file( 510 ( (cue_parser_state_t *) parser_state )->handle, 511 $2.data, 512 $2.length, 513 ( (cue_parser_state_t *) parser_state )->file_type, 514 ( (cue_parser_state_t *) parser_state )->error ) != 1 ) 515 { 516 libcerror_error_set( 517 ( (cue_parser_state_t *) parser_state )->error, 518 LIBCERROR_ERROR_DOMAIN_RUNTIME, 519 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 520 "%s: unable to append data file.", 521 cue_parser_function ); 522 523 YYABORT; 524 } 525 ( (cue_parser_state_t *) parser_state )->current_file_index += 1; 526 } 527 ; 528 529 cue_flags 530 : CUE_FLAGS cue_flags_types CUE_END_OF_LINE 531 { 532 cue_parser_rule_print( 533 "cue_flags" ); 534 } 535 ; 536 537 cue_flags_types 538 : /* empty */ 539 | CUE_KEYWORD_STRING cue_flags_types 540 ; 541 542 cue_index 543 : CUE_INDEX CUE_2DIGIT CUE_MSF CUE_END_OF_LINE 544 { 545 cue_parser_rule_print( 546 "cue_index" ); 547 548 if( $2.data == NULL ) 549 { 550 libcerror_error_set( 551 ( (cue_parser_state_t *) parser_state )->error, 552 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 553 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 554 "%s: invalid index number.", 555 cue_parser_function ); 556 557 YYABORT; 558 } 559 ( (cue_parser_state_t *) parser_state )->previous_index = ( (cue_parser_state_t *) parser_state )->current_index; 560 561 if( ( ( $2.data )[ 0 ] < '0' ) 562 || ( ( $2.data )[ 0 ] > '9' ) ) 563 { 564 libcerror_error_set( 565 ( (cue_parser_state_t *) parser_state )->error, 566 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 567 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 568 "%s: unsupported index number.", 569 cue_parser_function ); 570 571 YYABORT; 572 } 573 ( (cue_parser_state_t *) parser_state )->current_index = ( $2.data )[ 0 ] - '0'; 574 575 if( $2.length == 2 ) 576 { 577 ( (cue_parser_state_t *) parser_state )->current_index *= 10; 578 579 if( ( ( $2.data )[ 1 ] < '0' ) 580 || ( ( $2.data )[ 1 ] > '9' ) ) 581 { 582 libcerror_error_set( 583 ( (cue_parser_state_t *) parser_state )->error, 584 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 585 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 586 "%s: unsupported index number.", 587 cue_parser_function ); 588 589 YYABORT; 590 } 591 ( (cue_parser_state_t *) parser_state )->current_index += ( $2.data )[ 1 ] - '0'; 592 } 593 if( ( ( (cue_parser_state_t *) parser_state )->current_index != 0 ) 594 && ( ( (cue_parser_state_t *) parser_state )->current_index != ( ( (cue_parser_state_t *) parser_state )->previous_index + 1 ) ) ) 595 { 596 libcerror_error_set( 597 ( (cue_parser_state_t *) parser_state )->error, 598 LIBCERROR_ERROR_DOMAIN_RUNTIME, 599 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, 600 "%s: unsupported index number - values are not sequential.", 601 cue_parser_function ); 602 603 YYABORT; 604 } 605 if( ( $3.data == NULL ) 606 || ( $3.length != 8 ) ) 607 { 608 libcerror_error_set( 609 ( (cue_parser_state_t *) parser_state )->error, 610 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 611 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 612 "%s: invalid index MSF.", 613 cue_parser_function ); 614 615 YYABORT; 616 } 617 if( ( ( $3.data )[ 0 ] < '0' ) 618 || ( ( $3.data )[ 0 ] > '9' ) 619 || ( ( $3.data )[ 1 ] < '0' ) 620 || ( ( $3.data )[ 1 ] > '9' ) 621 || ( ( $3.data )[ 2 ] != ':' ) 622 || ( ( $3.data )[ 3 ] < '0' ) 623 || ( ( $3.data )[ 3 ] > '9' ) 624 || ( ( $3.data )[ 4 ] < '0' ) 625 || ( ( $3.data )[ 4 ] > '9' ) 626 || ( ( $3.data )[ 5 ] != ':' ) 627 || ( ( $3.data )[ 6 ] < '0' ) 628 || ( ( $3.data )[ 6 ] > '9' ) 629 || ( ( $3.data )[ 7 ] < '0' ) 630 || ( ( $3.data )[ 7 ] > '9' ) ) 631 { 632 libcerror_error_set( 633 ( (cue_parser_state_t *) parser_state )->error, 634 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 635 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 636 "%s: unsupported index MSF.", 637 cue_parser_function ); 638 639 YYABORT; 640 } 641 cue_parser_copy_relative_msf_to_lba( 642 $3.data, 643 ( (cue_parser_state_t *) parser_state )->current_start_sector ); 644 645 /* The MSF can be relative to the start of the file 646 */ 647 if( ( (cue_parser_state_t *) parser_state )->current_start_sector != 0 ) 648 { 649 if( ( ( (cue_parser_state_t *) parser_state )->current_index == 0 ) 650 || ( ( (cue_parser_state_t *) parser_state )->current_index == 1 ) ) 651 { 652 if( ( ( (cue_parser_state_t *) parser_state )->session_number_of_sectors == 0 ) 653 || ( ( (cue_parser_state_t *) parser_state )->previous_track_type == LIBODRAW_TRACK_TYPE_AUDIO ) ) 654 { 655 if( ( (cue_parser_state_t *) parser_state )->current_start_sector < ( (cue_parser_state_t *) parser_state )->previous_session_start_sector ) 656 { 657 libcerror_error_set( 658 ( (cue_parser_state_t *) parser_state )->error, 659 LIBCERROR_ERROR_DOMAIN_RUNTIME, 660 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, 661 "%s: invalid session start sector value preceeds previous.", 662 cue_parser_function ); 663 664 YYABORT; 665 } 666 ( (cue_parser_state_t *) parser_state )->session_number_of_sectors = ( (cue_parser_state_t *) parser_state )->current_start_sector 667 - ( (cue_parser_state_t *) parser_state )->previous_session_start_sector; 668 } 669 if( ( ( (cue_parser_state_t *) parser_state )->lead_out_number_of_sectors == 0 ) 670 || ( ( (cue_parser_state_t *) parser_state )->previous_track_type == LIBODRAW_TRACK_TYPE_AUDIO ) ) 671 { 672 if( ( (cue_parser_state_t *) parser_state )->current_start_sector < ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector ) 673 { 674 libcerror_error_set( 675 ( (cue_parser_state_t *) parser_state )->error, 676 LIBCERROR_ERROR_DOMAIN_RUNTIME, 677 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, 678 "%s: invalid lead-out start sector value preceeds previous.", 679 cue_parser_function ); 680 681 YYABORT; 682 } 683 ( (cue_parser_state_t *) parser_state )->lead_out_number_of_sectors = ( (cue_parser_state_t *) parser_state )->current_start_sector 684 - ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector; 685 } 686 } 687 if( ( (cue_parser_state_t *) parser_state )->current_index == 1 ) 688 { 689 if( ( (cue_parser_state_t *) parser_state )->track_number_of_sectors == 0 ) 690 { 691 if( ( (cue_parser_state_t *) parser_state )->current_start_sector < ( (cue_parser_state_t *) parser_state )->previous_track_start_sector ) 692 { 693 libcerror_error_set( 694 ( (cue_parser_state_t *) parser_state )->error, 695 LIBCERROR_ERROR_DOMAIN_RUNTIME, 696 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, 697 "%s: invalid track start sector value preceeds previous.", 698 cue_parser_function ); 699 700 YYABORT; 701 } 702 ( (cue_parser_state_t *) parser_state )->track_number_of_sectors = ( (cue_parser_state_t *) parser_state )->current_start_sector 703 - ( (cue_parser_state_t *) parser_state )->previous_track_start_sector; 704 } 705 } 706 } 707 if( ( (cue_parser_state_t *) parser_state )->current_index == 1 ) 708 { 709 if( ( (cue_parser_state_t *) parser_state )->current_session > 1 ) 710 { 711 if( libodraw_handle_append_session( 712 ( (cue_parser_state_t *) parser_state )->handle, 713 ( (cue_parser_state_t *) parser_state )->previous_session_start_sector, 714 ( (cue_parser_state_t *) parser_state )->session_number_of_sectors, 715 ( (cue_parser_state_t *) parser_state )->error ) != 1 ) 716 { 717 libcerror_error_set( 718 ( (cue_parser_state_t *) parser_state )->error, 719 LIBCERROR_ERROR_DOMAIN_RUNTIME, 720 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 721 "%s: unable to append session.", 722 cue_parser_function ); 723 724 YYABORT; 725 } 726 ( (cue_parser_state_t *) parser_state )->previous_session_start_sector = ( (cue_parser_state_t *) parser_state )->current_start_sector; 727 ( (cue_parser_state_t *) parser_state )->session_number_of_sectors = 0; 728 } 729 if( ( (cue_parser_state_t *) parser_state )->current_lead_out > ( (cue_parser_state_t *) parser_state )->previous_lead_out ) 730 { 731 if( libodraw_handle_append_lead_out( 732 ( (cue_parser_state_t *) parser_state )->handle, 733 ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector, 734 ( (cue_parser_state_t *) parser_state )->lead_out_number_of_sectors, 735 ( (cue_parser_state_t *) parser_state )->error ) != 1 ) 736 { 737 libcerror_error_set( 738 ( (cue_parser_state_t *) parser_state )->error, 739 LIBCERROR_ERROR_DOMAIN_RUNTIME, 740 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 741 "%s: unable to append lead-out.", 742 cue_parser_function ); 743 744 YYABORT; 745 } 746 ( (cue_parser_state_t *) parser_state )->previous_lead_out = ( (cue_parser_state_t *) parser_state )->current_lead_out; 747 ( (cue_parser_state_t *) parser_state )->lead_out_number_of_sectors = 0; 748 } 749 if( ( (cue_parser_state_t *) parser_state )->current_track > 1 ) 750 { 751 if( ( (cue_parser_state_t *) parser_state )->previous_file_index < 0 ) 752 { 753 ( (cue_parser_state_t *) parser_state )->file_sector = ( (cue_parser_state_t *) parser_state )->previous_track_start_sector; 754 755 ( (cue_parser_state_t *) parser_state )->previous_file_index += 1; 756 } 757 ( (cue_parser_state_t *) parser_state )->previous_file_sector = ( (cue_parser_state_t *) parser_state )->previous_track_start_sector 758 - ( (cue_parser_state_t *) parser_state )->file_sector; 759 760 if( libodraw_handle_append_track( 761 ( (cue_parser_state_t *) parser_state )->handle, 762 ( (cue_parser_state_t *) parser_state )->previous_track_start_sector, 763 ( (cue_parser_state_t *) parser_state )->track_number_of_sectors, 764 ( (cue_parser_state_t *) parser_state )->previous_track_type, 765 ( (cue_parser_state_t *) parser_state )->previous_file_index, 766 ( (cue_parser_state_t *) parser_state )->previous_file_sector, 767 ( (cue_parser_state_t *) parser_state )->error ) != 1 ) 768 { 769 libcerror_error_set( 770 ( (cue_parser_state_t *) parser_state )->error, 771 LIBCERROR_ERROR_DOMAIN_RUNTIME, 772 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 773 "%s: unable to append track.", 774 cue_parser_function ); 775 776 YYABORT; 777 } 778 if( ( (cue_parser_state_t *) parser_state )->previous_file_index < ( (cue_parser_state_t *) parser_state )->current_file_index ) 779 { 780 ( (cue_parser_state_t *) parser_state )->file_sector = ( (cue_parser_state_t *) parser_state )->current_start_sector; 781 782 ( (cue_parser_state_t *) parser_state )->previous_file_index += 1; 783 } 784 ( (cue_parser_state_t *) parser_state )->previous_track_start_sector = ( (cue_parser_state_t *) parser_state )->current_start_sector; 785 ( (cue_parser_state_t *) parser_state )->track_number_of_sectors = 0; 786 } 787 } 788 } 789 ; 790 791 cue_isrc 792 : CUE_ISRC CUE_ISRC_CODE CUE_END_OF_LINE 793 { 794 cue_parser_rule_print( 795 "cue_isrc" ); 796 } 797 ; 798 799 cue_postgap 800 : CUE_POSTGAP CUE_MSF CUE_END_OF_LINE 801 { 802 cue_parser_rule_print( 803 "cue_postgap" ); 804 } 805 ; 806 807 cue_pregap 808 : CUE_PREGAP CUE_MSF CUE_END_OF_LINE 809 { 810 cue_parser_rule_print( 811 "cue_pregap" ); 812 } 813 ; 814 815 cue_remark_item 816 : cue_lead_out 817 | cue_original_media_type 818 | cue_remark 819 | cue_run_out 820 | cue_session 821 ; 822 823 cue_lead_out 824 : CUE_REMARK_LEAD_OUT CUE_MSF CUE_END_OF_LINE 825 { 826 cue_parser_rule_print( 827 "cue_lead_out" ); 828 829 if( ( $2.data == NULL ) 830 || ( $2.length != 8 ) ) 831 { 832 libcerror_error_set( 833 ( (cue_parser_state_t *) parser_state )->error, 834 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 835 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 836 "%s: invalid index MSF.", 837 cue_parser_function ); 838 839 YYABORT; 840 } 841 if( ( ( $2.data )[ 0 ] < '0' ) 842 || ( ( $2.data )[ 0 ] > '9' ) 843 || ( ( $2.data )[ 1 ] < '0' ) 844 || ( ( $2.data )[ 1 ] > '9' ) 845 || ( ( $2.data )[ 2 ] != ':' ) 846 || ( ( $2.data )[ 3 ] < '0' ) 847 || ( ( $2.data )[ 3 ] > '9' ) 848 || ( ( $2.data )[ 4 ] < '0' ) 849 || ( ( $2.data )[ 4 ] > '9' ) 850 || ( ( $2.data )[ 5 ] != ':' ) 851 || ( ( $2.data )[ 6 ] < '0' ) 852 || ( ( $2.data )[ 6 ] > '9' ) 853 || ( ( $2.data )[ 7 ] < '0' ) 854 || ( ( $2.data )[ 7 ] > '9' ) ) 855 { 856 libcerror_error_set( 857 ( (cue_parser_state_t *) parser_state )->error, 858 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 859 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 860 "%s: unsupported index MSF.", 861 cue_parser_function ); 862 863 YYABORT; 864 } 865 cue_parser_copy_relative_msf_to_lba( 866 $2.data, 867 ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector ); 868 869 if( ( (cue_parser_state_t *) parser_state )->track_number_of_sectors == 0 ) 870 { 871 if( ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector < ( (cue_parser_state_t *) parser_state )->previous_track_start_sector ) 872 { 873 libcerror_error_set( 874 ( (cue_parser_state_t *) parser_state )->error, 875 LIBCERROR_ERROR_DOMAIN_RUNTIME, 876 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, 877 "%s: invalid lead-out start sector value preceeds previous track start sector.", 878 cue_parser_function ); 879 880 YYABORT; 881 } 882 ( (cue_parser_state_t *) parser_state )->track_number_of_sectors = ( (cue_parser_state_t *) parser_state )->previous_lead_out_start_sector 883 - ( (cue_parser_state_t *) parser_state )->previous_track_start_sector; 884 } 885 ( (cue_parser_state_t *) parser_state )->current_lead_out += 1; 886 } 887 ; 888 889 cue_original_media_type 890 : CUE_REMARK_ORIGINAL_MEDIA_TYPE CUE_KEYWORD_STRING CUE_END_OF_LINE 891 { 892 cue_parser_rule_print( 893 "cue_original_media_type" ); 894 } 895 ; 896 897 cue_remark 898 : cue_remark_start error CUE_END_OF_LINE 899 { 900 cue_parser_rule_print( 901 "cue_remark" ); 902 903 cue_scanner_suppress_error = 0; 904 } 905 ; 906 907 cue_remark_start 908 : CUE_REMARK 909 { 910 /* The build-in rule error will gobble up all the tokens until the end-of-line 911 * because these are no syntax errors suppress the error output 912 */ 913 cue_scanner_suppress_error = 1; 914 } 915 ; 916 917 cue_run_out 918 : CUE_REMARK_RUN_OUT CUE_MSF CUE_END_OF_LINE 919 { 920 cue_parser_rule_print( 921 "cue_run_out" ); 922 923 if( ( $2.data == NULL ) 924 || ( $2.length != 8 ) ) 925 { 926 libcerror_error_set( 927 ( (cue_parser_state_t *) parser_state )->error, 928 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 929 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 930 "%s: invalid index MSF.", 931 cue_parser_function ); 932 933 YYABORT; 934 } 935 if( ( ( $2.data )[ 0 ] < '0' ) 936 || ( ( $2.data )[ 0 ] > '9' ) 937 || ( ( $2.data )[ 1 ] < '0' ) 938 || ( ( $2.data )[ 1 ] > '9' ) 939 || ( ( $2.data )[ 2 ] != ':' ) 940 || ( ( $2.data )[ 3 ] < '0' ) 941 || ( ( $2.data )[ 3 ] > '9' ) 942 || ( ( $2.data )[ 4 ] < '0' ) 943 || ( ( $2.data )[ 4 ] > '9' ) 944 || ( ( $2.data )[ 5 ] != ':' ) 945 || ( ( $2.data )[ 6 ] < '0' ) 946 || ( ( $2.data )[ 6 ] > '9' ) 947 || ( ( $2.data )[ 7 ] < '0' ) 948 || ( ( $2.data )[ 7 ] > '9' ) ) 949 { 950 libcerror_error_set( 951 ( (cue_parser_state_t *) parser_state )->error, 952 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 953 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 954 "%s: unsupported index MSF.", 955 cue_parser_function ); 956 957 YYABORT; 958 } 959 cue_parser_copy_relative_msf_to_lba( 960 $2.data, 961 ( (cue_parser_state_t *) parser_state )->current_start_sector ); 962 963 if( ( (cue_parser_state_t *) parser_state )->track_number_of_sectors == 0 ) 964 { 965 if( ( (cue_parser_state_t *) parser_state )->current_start_sector < ( (cue_parser_state_t *) parser_state )->previous_track_start_sector ) 966 { 967 libcerror_error_set( 968 ( (cue_parser_state_t *) parser_state )->error, 969 LIBCERROR_ERROR_DOMAIN_RUNTIME, 970 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, 971 "%s: invalid track start sector value preceeds previous.", 972 cue_parser_function ); 973 974 YYABORT; 975 } 976 ( (cue_parser_state_t *) parser_state )->track_number_of_sectors = ( (cue_parser_state_t *) parser_state )->current_start_sector 977 - ( (cue_parser_state_t *) parser_state )->previous_track_start_sector; 978 } 979 } 980 ; 981 982 cue_session 983 : CUE_REMARK_SESSION CUE_2DIGIT CUE_END_OF_LINE 984 { 985 cue_parser_rule_print( 986 "cue_session" ); 987 988 if( $2.data == NULL ) 989 { 990 libcerror_error_set( 991 ( (cue_parser_state_t *) parser_state )->error, 992 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 993 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 994 "%s: invalid session number.", 995 cue_parser_function ); 996 997 YYABORT; 998 } 999 ( (cue_parser_state_t *) parser_state )->previous_session = ( (cue_parser_state_t *) parser_state )->current_session; 1000 1001 if( ( ( $2.data )[ 0 ] < '0' ) 1002 || ( ( $2.data )[ 0 ] > '9' ) ) 1003 { 1004 libcerror_error_set( 1005 ( (cue_parser_state_t *) parser_state )->error, 1006 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1007 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 1008 "%s: unsupported session number.", 1009 cue_parser_function ); 1010 1011 YYABORT; 1012 } 1013 ( (cue_parser_state_t *) parser_state )->current_session = ( $2.data )[ 0 ] - '0'; 1014 1015 if( $2.length == 2 ) 1016 { 1017 ( (cue_parser_state_t *) parser_state )->current_session *= 10; 1018 1019 if( ( ( $2.data )[ 1 ] < '0' ) 1020 || ( ( $2.data )[ 1 ] > '9' ) ) 1021 { 1022 libcerror_error_set( 1023 ( (cue_parser_state_t *) parser_state )->error, 1024 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1025 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 1026 "%s: unsupported session number.", 1027 cue_parser_function ); 1028 1029 YYABORT; 1030 } 1031 ( (cue_parser_state_t *) parser_state )->current_session += ( $2.data )[ 1 ] - '0'; 1032 } 1033 if( ( ( (cue_parser_state_t *) parser_state )->current_session != 0 ) 1034 && ( ( (cue_parser_state_t *) parser_state )->current_session != ( ( (cue_parser_state_t *) parser_state )->previous_session + 1 ) ) ) 1035 { 1036 libcerror_error_set( 1037 ( (cue_parser_state_t *) parser_state )->error, 1038 LIBCERROR_ERROR_DOMAIN_RUNTIME, 1039 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, 1040 "%s: unsupported session number - values are not sequential.", 1041 cue_parser_function ); 1042 1043 YYABORT; 1044 } 1045 } 1046 ; 1047 1048 cue_track 1049 : CUE_TRACK CUE_2DIGIT CUE_KEYWORD_STRING CUE_END_OF_LINE 1050 { 1051 cue_parser_rule_print( 1052 "cue_track" ); 1053 1054 if( $2.data == NULL ) 1055 { 1056 libcerror_error_set( 1057 ( (cue_parser_state_t *) parser_state )->error, 1058 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1059 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 1060 "%s: invalid track number.", 1061 cue_parser_function ); 1062 1063 YYABORT; 1064 } 1065 ( (cue_parser_state_t *) parser_state )->previous_track = ( (cue_parser_state_t *) parser_state )->current_track; 1066 1067 if( ( ( $2.data )[ 0 ] < '0' ) 1068 || ( ( $2.data )[ 0 ] > '9' ) ) 1069 { 1070 libcerror_error_set( 1071 ( (cue_parser_state_t *) parser_state )->error, 1072 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1073 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 1074 "%s: unsupported track number.", 1075 cue_parser_function ); 1076 1077 YYABORT; 1078 } 1079 ( (cue_parser_state_t *) parser_state )->current_track = ( $2.data )[ 0 ] - '0'; 1080 1081 if( $2.length == 2 ) 1082 { 1083 ( (cue_parser_state_t *) parser_state )->current_track *= 10; 1084 1085 if( ( ( $2.data )[ 1 ] < '0' ) 1086 || ( ( $2.data )[ 1 ] > '9' ) ) 1087 { 1088 libcerror_error_set( 1089 ( (cue_parser_state_t *) parser_state )->error, 1090 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1091 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, 1092 "%s: unsupported track number.", 1093 cue_parser_function ); 1094 1095 YYABORT; 1096 } 1097 ( (cue_parser_state_t *) parser_state )->current_track += ( $2.data )[ 1 ] - '0'; 1098 } 1099 if( ( ( (cue_parser_state_t *) parser_state )->current_track != 0 ) 1100 && ( ( (cue_parser_state_t *) parser_state )->current_track != ( ( (cue_parser_state_t *) parser_state )->previous_track + 1 ) ) ) 1101 { 1102 libcerror_error_set( 1103 ( (cue_parser_state_t *) parser_state )->error, 1104 LIBCERROR_ERROR_DOMAIN_RUNTIME, 1105 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, 1106 "%s: unsupported track number - values are not sequential.", 1107 cue_parser_function ); 1108 1109 YYABORT; 1110 } 1111 if( $3.data == NULL ) 1112 { 1113 libcerror_error_set( 1114 ( (cue_parser_state_t *) parser_state )->error, 1115 LIBCERROR_ERROR_DOMAIN_ARGUMENTS, 1116 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, 1117 "%s: invalid track number.", 1118 cue_parser_function ); 1119 1120 YYABORT; 1121 } 1122 ( (cue_parser_state_t *) parser_state )->previous_track_type = ( (cue_parser_state_t *) parser_state )->current_track_type; 1123 1124 ( (cue_parser_state_t *) parser_state )->previous_index = 0; 1125 ( (cue_parser_state_t *) parser_state )->current_index = 0; 1126 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_UNKNOWN; 1127 1128 if( $3.length == 3 ) 1129 { 1130 if( narrow_string_compare( 1131 $3.data, 1132 "CDG", 1133 3 ) == 0 ) 1134 { 1135 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_CDG; 1136 } 1137 } 1138 else if( $3.length == 5 ) 1139 { 1140 if( narrow_string_compare( 1141 $3.data, 1142 "AUDIO", 1143 5 ) == 0 ) 1144 { 1145 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_AUDIO; 1146 } 1147 } 1148 else if( $3.length == 8 ) 1149 { 1150 if( narrow_string_compare( 1151 $3.data, 1152 "CDI", 1153 3 ) == 0 ) 1154 { 1155 if( ( $3.data )[ 3 ] == '/' ) 1156 { 1157 if( narrow_string_compare( 1158 &( ( $3.data )[ 4 ] ), 1159 "2336", 1160 4 ) == 0 ) 1161 { 1162 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_CDI_2336; 1163 } 1164 else if( narrow_string_compare( 1165 &( ( $3.data )[ 4 ] ), 1166 "2352", 1167 4 ) == 0 ) 1168 { 1169 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_CDI_2352; 1170 } 1171 } 1172 } 1173 } 1174 else if( $3.length == 10 ) 1175 { 1176 if( narrow_string_compare( 1177 $3.data, 1178 "MODE", 1179 4 ) == 0 ) 1180 { 1181 if( ( $3.data )[ 5 ] == '/' ) 1182 { 1183 if( ( $3.data )[ 4 ] == '1' ) 1184 { 1185 if( narrow_string_compare( 1186 &( ( $3.data )[ 6 ] ), 1187 "2048", 1188 4 ) == 0 ) 1189 { 1190 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE1_2048; 1191 } 1192 else if( narrow_string_compare( 1193 &( ( $3.data )[ 6 ] ), 1194 "2352", 1195 4 ) == 0 ) 1196 { 1197 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE1_2352; 1198 } 1199 } 1200 else if( ( $3.data )[ 4 ] == '2' ) 1201 { 1202 if( narrow_string_compare( 1203 &( ( $3.data )[ 6 ] ), 1204 "2048", 1205 4 ) == 0 ) 1206 { 1207 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE2_2048; 1208 } 1209 else if( narrow_string_compare( 1210 &( ( $3.data )[ 6 ] ), 1211 "2324", 1212 4 ) == 0 ) 1213 { 1214 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE2_2324; 1215 } 1216 else if( narrow_string_compare( 1217 &( ( $3.data )[ 6 ] ), 1218 "2336", 1219 4 ) == 0 ) 1220 { 1221 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE2_2336; 1222 } 1223 else if( narrow_string_compare( 1224 &( ( $3.data )[ 6 ] ), 1225 "2352", 1226 4 ) == 0 ) 1227 { 1228 ( (cue_parser_state_t *) parser_state )->current_track_type = LIBODRAW_TRACK_TYPE_MODE2_2352; 1229 } 1230 } 1231 } 1232 } 1233 } 1234 } 1235 ; 1236 1237 cue_empty_line 1238 : CUE_END_OF_LINE 1239 ; 1240 1241 %% 1242 1243 int cue_parser_parse_buffer( 1244 libodraw_handle_t *handle, 1245 const uint8_t *buffer, 1246 size_t buffer_size, 1247 libcerror_error_t **error ) 1248 { 1249 cue_parser_state_t parser_state; 1250 1251 YY_BUFFER_STATE buffer_state = NULL; 1252 size_t buffer_offset = 0; 1253 int result = -1; 1254 1255 if( buffer_size >= 3 ) 1256 { 1257 if( ( buffer[ 0 ] == 0x0ef ) 1258 && ( buffer[ 1 ] == 0x0bb ) 1259 && ( buffer[ 2 ] == 0x0bf ) ) 1260 { 1261 buffer_offset = 3; 1262 } 1263 } 1264 buffer_state = cue_scanner__scan_buffer( 1265 (char *) &( buffer[ buffer_offset ] ), 1266 buffer_size - buffer_offset ); 1267 1268 cue_scanner_buffer_offset = (size_t) buffer_offset; 1269 1270 if( buffer_state != NULL ) 1271 { 1272 parser_state.handle = handle; 1273 parser_state.error = error; 1274 parser_state.previous_file_index = -1; 1275 parser_state.current_file_index = -1; 1276 parser_state.file_type = 0; 1277 parser_state.previous_file_sector = 0; 1278 parser_state.file_sector = 0; 1279 parser_state.previous_session_start_sector = 0; 1280 parser_state.previous_lead_out_start_sector = 0; 1281 parser_state.previous_track_start_sector = 0; 1282 parser_state.current_start_sector = 0; 1283 parser_state.session_number_of_sectors = 0; 1284 parser_state.lead_out_number_of_sectors = 0; 1285 parser_state.track_number_of_sectors = 0; 1286 parser_state.previous_track_type = 0; 1287 parser_state.current_track_type = 0; 1288 parser_state.previous_session = 0; 1289 parser_state.current_session = 0; 1290 parser_state.previous_lead_out = 0; 1291 parser_state.current_lead_out = 0; 1292 parser_state.previous_track = 0; 1293 parser_state.current_track = 0; 1294 parser_state.previous_index = 0; 1295 parser_state.current_index = 0; 1296 1297 if( cue_scanner_parse( 1298 &parser_state ) == 0 ) 1299 { 1300 result = 1; 1301 } 1302 cue_scanner__delete_buffer( 1303 buffer_state ); 1304 1305 if( parser_state.current_session > 0 ) 1306 { 1307 if( libodraw_handle_append_session( 1308 parser_state.handle, 1309 parser_state.previous_session_start_sector, 1310 0, 1311 parser_state.error ) != 1 ) 1312 { 1313 libcerror_error_set( 1314 parser_state.error, 1315 LIBCERROR_ERROR_DOMAIN_RUNTIME, 1316 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 1317 "%s: unable to append session.", 1318 cue_parser_function ); 1319 1320 result = -1; 1321 } 1322 } 1323 if( parser_state.current_lead_out > parser_state.previous_lead_out ) 1324 { 1325 if( libodraw_handle_append_lead_out( 1326 parser_state.handle, 1327 parser_state.previous_lead_out_start_sector, 1328 0, 1329 parser_state.error ) != 1 ) 1330 { 1331 libcerror_error_set( 1332 parser_state.error, 1333 LIBCERROR_ERROR_DOMAIN_RUNTIME, 1334 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 1335 "%s: unable to append lead-out.", 1336 cue_parser_function ); 1337 1338 result = -1; 1339 } 1340 } 1341 if( parser_state.current_track > 0 ) 1342 { 1343 if( parser_state.previous_file_index < 0 ) 1344 { 1345 parser_state.file_sector = parser_state.previous_track_start_sector; 1346 1347 parser_state.previous_file_index += 1; 1348 } 1349 parser_state.previous_file_sector = parser_state.previous_track_start_sector 1350 - parser_state.file_sector; 1351 1352 if( libodraw_handle_append_track( 1353 parser_state.handle, 1354 parser_state.previous_track_start_sector, 1355 0, 1356 parser_state.current_track_type, 1357 parser_state.current_file_index, 1358 parser_state.previous_file_sector, 1359 parser_state.error ) != 1 ) 1360 { 1361 libcerror_error_set( 1362 parser_state.error, 1363 LIBCERROR_ERROR_DOMAIN_RUNTIME, 1364 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, 1365 "%s: unable to append track.", 1366 cue_parser_function ); 1367 1368 result = -1; 1369 } 1370 } 1371 } 1372 cue_scanner_lex_destroy(); 1373 1374 return( result ); 1375 } 1376 1377