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