You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

278 lines
4.4 KiB

  1. %{
  2. /*
  3. * cue_parse.y -- parser for cue files
  4. *
  5. * Copyright (C) 2004 Svend Sorensen
  6. * For license terms, see the file COPYING in this distribution.
  7. */
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "cd.h"
  12. #include "time.h"
  13. #define YYDEBUG 1
  14. extern int cue_yylex();
  15. void yyerror (char *s);
  16. static Cd *cd = NULL;
  17. static Track *track = NULL;
  18. static Track *prev_track = NULL;
  19. static Cdtext *cdtext = NULL;
  20. static char *prev_filename = NULL; /* last file in or before last track */
  21. static char *cur_filename = NULL; /* last file in the last track */
  22. static char *new_filename = NULL; /* last file in this track */
  23. %}
  24. %start cuefile
  25. %union {
  26. long ival;
  27. char *sval;
  28. }
  29. %token <ival> NUMBER
  30. %token <sval> STRING
  31. /* global (header) */
  32. %token CATALOG
  33. %token FFILE
  34. %token BINARY
  35. %token MOTOROLA
  36. %token AIFF
  37. %token WAVE
  38. %token MP3
  39. /* track */
  40. %token TRACK
  41. %token <ival> AUDIO
  42. %token <ival> MODE1_2048
  43. %token <ival> MODE1_2352
  44. %token <ival> MODE2_2336
  45. %token <ival> MODE2_2048
  46. %token <ival> MODE2_2342
  47. %token <ival> MODE2_2332
  48. %token <ival> MODE2_2352
  49. /* ISRC is with CD_TEXT */
  50. %token TRACK_ISRC
  51. %token FLAGS
  52. %token <ival> PRE
  53. %token <ival> DCP
  54. %token <ival> FOUR_CH
  55. %token <ival> SCMS
  56. %token PREGAP
  57. %token INDEX
  58. %token POSTGAP
  59. /* CD-TEXT */
  60. %token <ival> TITLE
  61. %token <ival> PERFORMER
  62. %token <ival> SONGWRITER
  63. %token <ival> COMPOSER
  64. %token <ival> ARRANGER
  65. %token <ival> MESSAGE
  66. %token <ival> DISC_ID
  67. %token <ival> GENRE
  68. %token <ival> TOC_INFO1
  69. %token <ival> TOC_INFO2
  70. %token <ival> UPC_EAN
  71. %token <ival> ISRC
  72. %token <ival> SIZE_INFO
  73. %type <ival> track_mode
  74. %type <ival> track_flag
  75. %type <ival> time
  76. %type <ival> cdtext_item
  77. %%
  78. cuefile
  79. : new_cd global_statements track_list
  80. ;
  81. new_cd
  82. : /* empty */ {
  83. cd = cd_init();
  84. cdtext = cd_get_cdtext(cd);
  85. }
  86. ;
  87. global_statements
  88. : /* empty */
  89. | global_statements global_statement
  90. ;
  91. global_statement
  92. : CATALOG STRING '\n' { cd_set_catalog(cd, $2); }
  93. | cdtext
  94. | track_data
  95. | error '\n'
  96. ;
  97. track_data
  98. : FFILE STRING file_format '\n' {
  99. if (NULL != new_filename) {
  100. yyerror("too many files specified\n");
  101. free(new_filename);
  102. }
  103. new_filename = strdup($2);
  104. }
  105. ;
  106. track_list
  107. : track
  108. | track_list track
  109. ;
  110. track
  111. : new_track track_def track_statements
  112. ;
  113. file_format
  114. : BINARY
  115. | MOTOROLA
  116. | AIFF
  117. | WAVE
  118. | MP3
  119. ;
  120. new_track
  121. : /*empty */ {
  122. /* save previous track, to later set length */
  123. prev_track = track;
  124. track = cd_add_track(cd);
  125. cdtext = track_get_cdtext(track);
  126. cur_filename = new_filename;
  127. if (NULL != cur_filename)
  128. prev_filename = cur_filename;
  129. if (NULL == prev_filename)
  130. yyerror("no file specified for track");
  131. else
  132. track_set_filename(track, prev_filename);
  133. new_filename = NULL;
  134. }
  135. ;
  136. track_def
  137. : TRACK NUMBER track_mode '\n' {
  138. track_set_mode(track, $3);
  139. }
  140. ;
  141. track_mode
  142. : AUDIO
  143. | MODE1_2048
  144. | MODE1_2352
  145. | MODE2_2336
  146. | MODE2_2048
  147. | MODE2_2342
  148. | MODE2_2332
  149. | MODE2_2352
  150. ;
  151. track_statements
  152. : track_statement
  153. | track_statements track_statement
  154. ;
  155. track_statement
  156. : cdtext
  157. | FLAGS track_flags '\n'
  158. | TRACK_ISRC STRING '\n' { track_set_isrc(track, $2); }
  159. | PREGAP time '\n' { track_set_zero_pre(track, $2); }
  160. | INDEX NUMBER time '\n' {
  161. int i = track_get_nindex(track);
  162. long prev_length;
  163. if (0 == i) {
  164. /* first index */
  165. track_set_start(track, $3);
  166. if (NULL != prev_track && NULL == cur_filename) {
  167. /* track shares file with previous track */
  168. prev_length = $3 - track_get_start(prev_track);
  169. track_set_length(prev_track, prev_length);
  170. }
  171. }
  172. for (; i <= $2; i++)
  173. track_add_index(track, \
  174. track_get_zero_pre(track) + $3 \
  175. - track_get_start(track));
  176. }
  177. | POSTGAP time '\n' { track_set_zero_post(track, $2); }
  178. | track_data
  179. | error '\n'
  180. ;
  181. track_flags
  182. : /* empty */
  183. | track_flags track_flag { track_set_flag(track, $2); }
  184. ;
  185. track_flag
  186. : PRE
  187. | DCP
  188. | FOUR_CH
  189. | SCMS
  190. ;
  191. cdtext
  192. : cdtext_item STRING '\n' { cdtext_set ($1, $2, cdtext); }
  193. ;
  194. cdtext_item
  195. : TITLE
  196. | PERFORMER
  197. | SONGWRITER
  198. | COMPOSER
  199. | ARRANGER
  200. | MESSAGE
  201. | DISC_ID
  202. | GENRE
  203. | TOC_INFO1
  204. | TOC_INFO2
  205. | UPC_EAN
  206. | ISRC
  207. | SIZE_INFO
  208. ;
  209. time
  210. : NUMBER
  211. | NUMBER ':' NUMBER ':' NUMBER { $$ = time_msf_to_frame($1, $3, $5); }
  212. ;
  213. %%
  214. /* lexer interface */
  215. extern int cue_lineno;
  216. extern int cue_yydebug;
  217. extern FILE *cue_yyin;
  218. void yyerror (char *s)
  219. {
  220. fprintf(stderr, "%d: %s\n", cue_lineno, s);
  221. }
  222. Cd *cue_parse (FILE *fp)
  223. {
  224. cue_yyin = fp;
  225. cue_yydebug = 0;
  226. if (0 == cue_yyparse())
  227. return cd;
  228. return NULL;
  229. }