%{ /* * toc_parse.y -- parser for toc files * * Copyright (C) 2004 Svend Sorensen * For license terms, see the file COPYING in this distribution. */ #include #include #include #include "cd.h" #include "time.h" #include "toc_parse_prefix.h" #define YYDEBUG 1 extern int yylex(); void yyerror (char *s); static Cd *cd = NULL; static Track *track = NULL; static Cdtext *cdtext = NULL; %} %start tocfile %union { long ival; char *sval; } %token NUMBER %token STRING /* global (header) */ %token CATALOG %token CD_DA %token CD_ROM %token CD_ROM_XA /* track */ %token TRACK %token AUDIO %token MODE1 %token MODE1_RAW %token MODE2 %token MODE2_FORM1 %token MODE2_FORM2 %token MODE2_FORM_MIX %token MODE2_RAW %token RW %token RW_RAW %token NO %token COPY %token PRE_EMPHASIS %token TWO_CHANNEL_AUDIO %token FOUR_CHANNEL_AUDIO %token ISRC %token SILENCE %token ZERO %token AUDIOFILE %token DATAFILE %token FIFO %token START %token PREGAP %token INDEX /* CD-TEXT */ %token CD_TEXT %token LANGUAGE_MAP %token LANGUAGE %token TITLE %token PERFORMER %token SONGWRITER %token COMPOSER %token ARRANGER %token MESSAGE %token DISC_ID %token GENRE %token TOC_INFO1 %token TOC_INFO2 %token UPC_EAN %token ISRC %token SIZE_INFO %type disc_mode %type track_modes %type track_mode %type track_sub_mode %type track_set_flag %type track_clear_flag %type time %type cdtext_item %% tocfile : new_cd global_statements track_list ; new_cd : /* empty */ { cd = cd_init(); cdtext = cd_get_cdtext(cd); } ; global_statements : /* empty */ | global_statements global_statement ; global_statement : CATALOG STRING '\n' { cd_set_catalog(cd, $2); } | disc_mode '\n' { cd_set_mode(cd, $1); } | CD_TEXT '{' opt_nl language_map cdtext_langs '}' '\n' | error '\n' ; disc_mode : CD_DA | CD_ROM | CD_ROM_XA ; track_list : track | track_list track ; track : new_track track_def track_statements { while (2 > track_get_nindex(track)) track_add_index(track, 0); } ; new_track : /* empty */ { track = cd_add_track(cd); cdtext = track_get_cdtext(track); /* add 0 index */ track_add_index(track, 0); } ; track_def : TRACK track_modes '\n' { track_set_mode(track, $2); } ; track_modes : track_mode | track_mode track_sub_mode { track_set_sub_mode(track, $2); } ; track_mode : AUDIO | MODE1 | MODE1_RAW | MODE2 | MODE2_FORM1 | MODE2_FORM2 | MODE2_FORM_MIX | MODE2_RAW ; track_sub_mode : RW | RW_RAW ; track_statements : track_statement | track_statements track_statement ; track_statement : track_flags | ISRC STRING '\n' { track_set_isrc(track, $2); } | CD_TEXT '{' opt_nl cdtext_langs '}' '\n' | track_data | track_pregap | track_index | error '\n' ; track_flags : track_set_flag { track_set_flag(track, $1); } | track_clear_flag { track_clear_flag(track, $1); } ; track_set_flag : COPY '\n' | PRE_EMPHASIS '\n' | FOUR_CHANNEL_AUDIO '\n' ; track_clear_flag : NO PRE_EMPHASIS '\n' { $$ = $2; } | NO COPY '\n' { $$ = $2; } | TWO_CHANNEL_AUDIO '\n' ; track_data : zero_data time '\n' { if (NULL == track_get_filename(track)) track_set_zero_pre(track, $2); else track_set_zero_post(track, $2); } | AUDIOFILE STRING time '\n' { track_set_filename(track, $2); track_set_start(track, $3); } | AUDIOFILE STRING time time '\n' { track_set_filename(track, $2); track_set_start(track, $3); track_set_length(track, $4); } | DATAFILE STRING '\n' { track_set_filename(track, $2); } | DATAFILE STRING time '\n' { track_set_filename(track, $2); track_set_start(track, $3); } | FIFO STRING time '\n' { track_set_filename(track, $2); track_set_start(track, $3); } ; zero_data : SILENCE | ZERO ; track_pregap : START '\n' | START time '\n' { track_add_index(track, $2); } | PREGAP time '\n' { track_set_zero_pre(track, $2); track_add_index(track, $2); } ; track_index : INDEX time '\n' { track_add_index(track, $2); } ; language_map : LANGUAGE_MAP '{' opt_nl languages '}' '\n' ; languages : language | languages language ; language : NUMBER ':' NUMBER opt_nl { /* not implemented */ } ; cdtext_langs : cdtext_lang | cdtext_langs cdtext_lang ; cdtext_lang : LANGUAGE NUMBER '{' opt_nl cdtext_defs '}' '\n' ; cdtext_defs : /* empty */ | cdtext_defs cdtext_def ; cdtext_def : cdtext_item STRING '\n' { cdtext_set ($1, $2, cdtext); } | cdtext_item '{' bytes '}' '\n' { yyerror("binary CD-TEXT data not supported\n"); } ; cdtext_item : TITLE | PERFORMER | SONGWRITER | COMPOSER | ARRANGER | MESSAGE | DISC_ID | GENRE | TOC_INFO1 | TOC_INFO2 | UPC_EAN | ISRC | SIZE_INFO ; bytes : /* empty */ | bytes ',' NUMBER ; time : NUMBER | NUMBER ':' NUMBER ':' NUMBER { $$ = time_msf_to_frame($1, $3, $5); } ; opt_nl : /* empty */ | '\n' ; %% /* lexer interface */ extern int toc_lineno; extern int yydebug; extern FILE *toc_yyin; void yyerror (char *s) { fprintf(stderr, "%d: %s\n", toc_lineno, s); } Cd *toc_parse (FILE *fp) { toc_yyin = fp; yydebug = 0; if (0 == yyparse()) return cd; return NULL; }