4 * Copyright (C) 1998-2003 Jean-François Moine
5 * Adapted from abc2ps, Copyright (C) 1996, 1997 Michael Methfessel
7 * Contact: mailto:moinejf@free.fr
8 * Original site: http://moinejf.free.fr/
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 static void *(*alloc_f
)(int size
);
36 static void (*free_f
)(void *);
37 static void (*level_f
)(int level
);
39 static int keep_comment
;
41 static int abc_state
; /* parse state */
42 static int gulen
, ulen
; /* unit note length set by M: or L: */
43 static char *gchord
; /* guitar chord */
44 static int meter
; /* upper value of time sig for n-plets */
45 static struct deco dc
; /* decorations */
46 static int lyric_started
; /* lyric started */
47 static struct abcsym
*deco_start
; /* 1st note of the line for d: / s: */
48 static struct abcsym
*deco_cont
; /* current symbol when d: / s: continuation */
49 static int vover_bar
; /* in a simple voice overlay sequence */
51 #define VOICE_NAME_SZ 64 /* max size of a voice name */
53 static unsigned char *file
; /* remaining abc file */
54 static short linenum
; /* current line number */
55 static char *scratch_line
; /* parse line */
56 static int scratch_length
= 0; /* allocated length */
57 static int line_length
; /* current line length */
59 static short nvoice
; /* number of voices (0..n-1) */
60 static struct { /* voice table and current pointer */
61 char name
[32]; /* voice name */
62 struct abcsym
*last_note
; /* last note or rest */
63 struct abcsym
*tie
; /* last note with starting ties */
64 short ulen
; /* unit note length */
65 char slur
; /* number of slur starts */
66 unsigned char pplet
, qplet
, rplet
; /* nplet - fixme: may be global?*/
67 signed char add_pitch
; /* key transpose */
68 unsigned char mvoice
; /* main voice when voice overlay */
69 } voice_tb
[MAXVOICE
], *curvoice
;
71 /* char table for note line parsing */
91 static char char_tb
[256] = {
92 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAR_SPAC
, 0, 0, 0, 0, 0, 0, /* 00 - 0f */
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1f */
94 CHAR_SPAC
, CHAR_DECOS
, CHAR_GCHORD
, CHAR_BAD
, /* (sp) ! " # */
95 CHAR_BAD
, CHAR_BAD
, CHAR_VOV
, CHAR_BAD
, /* $ % & ' */
96 CHAR_OPAR
, CHAR_CPAR
, CHAR_IGN
, CHAR_DECOS
, /* ( ) * + */
97 CHAR_BAD
, CHAR_MINUS
, CHAR_DECO
, CHAR_BAD
, /* , - . / */
98 CHAR_BAD
, CHAR_BAD
, CHAR_BAD
, CHAR_BAD
, /* 0 1 2 3 */
99 CHAR_BAD
, CHAR_BAD
, CHAR_BAD
, CHAR_BAD
, /* 4 5 6 7 */
100 CHAR_BAD
, CHAR_BAD
, CHAR_BAR
, CHAR_BAD
, /* 8 9 : ; */
101 CHAR_BRHY
, CHAR_ACC
, CHAR_BRHY
, CHAR_BAD
, /* < = > ? */
102 CHAR_BAD
, CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, /* @ A B C */
103 CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, /* D E F G */
104 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* H I J K */
105 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* L M N O */
106 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* P Q R S */
107 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* T U V W */
108 CHAR_DECO
, CHAR_DECO
, CHAR_REST
, CHAR_OBRA
, /* X Y Z [ */
109 CHAR_BSLASH
, CHAR_BAR
, CHAR_ACC
, CHAR_ACC
, /* \ ] ^ _ */
110 CHAR_IGN
, CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, /* ` a b c */
111 CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, CHAR_NOTE
, /* d e f g */
112 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* h i j k */
113 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* l m n o */
114 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* p q r s */
115 CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, CHAR_DECO
, /* t u v w */
116 CHAR_REST
, CHAR_REST
, CHAR_REST
, CHAR_GRACE
, /* x y z { */
117 CHAR_BAR
, CHAR_BAD
, CHAR_DECO
, CHAR_BAD
, /* | } ~ (del) */
118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8f */
119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9f */
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a0 - af */
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b0 - bf */
122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c0 - cf */
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d0 - df */
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e0 - ef */
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f0 - ff */
128 static char all_notes
[] = "CDEFGABcdefgab^=_";
133 static unsigned char *get_line(void);
134 static unsigned char *parse_len(unsigned char *p
,
136 static char *parse_basic_note(char *p
,
141 static unsigned char *parse_clef(unsigned char *p
,
142 struct clef_s
*p_clef
);
143 static void parse_header(struct abctune
*t
,
146 static int parse_line(struct abctune
*t
,
148 static unsigned char *parse_note(struct abctune
*t
,
150 static void syntax(char *msg
, char *q
);
151 static void vover_new(void);
153 /* -- abcMIDI like errors -- */
154 static void print_error(char *s
,
158 fprintf(stderr
, "Error in line %d.%d: %s\n", linenum
, col
, s
);
159 else fprintf(stderr
, "Error in line %d: %s\n", linenum
, s
);
162 static void print_warning(char *s
)
164 fprintf(stderr
, "Warning in line %d: %s\n", linenum
, s
);
167 /* -- delete an ABC symbol -- */
168 void abc_delete(struct abcsym
*as
)
172 switch (as
->text
[0]) {
174 if (as
->u
.tempo
.str1
)
175 free_f(as
->u
.tempo
.str1
);
176 if (as
->u
.tempo
.str2
)
177 free_f(as
->u
.tempo
.str2
);
180 if (as
->u
.voice
.name
)
181 free_f(as
->u
.voice
.name
);
182 if (as
->u
.voice
.fname
)
183 free_f(as
->u
.voice
.fname
);
184 if (as
->u
.voice
.nname
)
185 free_f(as
->u
.voice
.nname
);
196 as
->prev
->next
= as
->next
;
198 as
->next
->prev
= as
->prev
;
199 if (as
->tune
->first_sym
== as
)
200 as
->tune
->first_sym
= as
->next
;
201 if (as
->tune
->last_sym
== as
)
202 if ((as
->tune
->last_sym
= as
->prev
) == 0)
206 /* -- free all tunes memory areas -- */
207 void abc_free(struct abctune
*first_tune
)
221 /* free the associated symbols */
242 /* -- initialize the parser -- */
243 void abc_init(void *alloc_f_api(int size
),
244 void free_f_api(void *ptr
),
245 void level_f_api(int level
),
247 int keep_comment_api
)
249 if (scratch_line
!= 0) {
250 fprintf(stderr
, "abc_init already initialized\n");
253 scratch_line
= malloc(256 + 1);
254 scratch_length
= 256;
255 alloc_f
= alloc_f_api
;
257 level_f
= level_f_api
;
258 client_sz
= client_sz_api
;
259 keep_comment
= keep_comment_api
;
262 /* -- insert an ABC description -- */
263 void abc_insert(char *file_api
,
272 level_f(abc_state
!= ABC_S_GLOBAL
);
273 abc_state
= ABC_S_TUNE
;
278 /* scan till end of description */
280 if ((p
= get_line()) == 0)
284 break; /* blank line --> done */
286 /*fixme-insert: don't accept X: nor T:*/
287 /* parse the music line */
288 if (!parse_line(t
, p
))
293 /* -- new symbol -- */
294 struct abcsym
*abc_new(struct abctune
*t
,
296 unsigned char *comment
)
300 s
= alloc_f(sizeof *s
+ client_sz
);
301 memset(s
, 0, sizeof *s
+ client_sz
);
304 s
->text
= alloc_f(strlen(p
) + 1);
308 s
->comment
= alloc_f(strlen(comment
) + 1);
309 strcpy(s
->comment
, comment
);
311 if (t
->last_sym
== 0)
312 t
->first_sym
= t
->last_sym
= s
;
314 if ((s
->next
= t
->last_sym
->next
) != 0)
316 t
->last_sym
->next
= s
;
317 s
->prev
= t
->last_sym
;
320 s
->linenum
= linenum
;
324 /* -- parse an ABC file -- */
325 struct abctune
*abc_parse(char *file_api
)
328 struct abctune
*first_tune
= 0;
329 struct abctune
*t
, *last_tune
;
334 abc_state
= ABC_S_GLOBAL
;
341 /* scan till end of file */
343 if ((p
= get_line()) == 0) {
344 if (abc_state
== ABC_S_HEAD
) {
345 print_error("unexpected EOF in header definition",
351 while (isspace(*p
)) /* skip starting blanks */
354 /* start a new tune if not done */
360 n
= alloc_f(sizeof *n
);
361 memset(n
, 0 , sizeof *n
);
372 /* parse the music line */
373 if (!parse_line(t
, p
))
379 /* -- cut off after % and remove trailing blanks -- */
380 static unsigned char *decomment_line(unsigned char *p
)
383 unsigned char c
, *comment
= 0;
387 if ((c
= *p
++) == '%') {
388 if (i
> 0 && p
[-2] != '\\') {
401 /* remove trailing blanks */
412 /* -- define a voice by name -- */
413 /* the voice is created if it does not exist */
414 static char *def_voice(unsigned char *p
,
422 while (isalnum(*p
) || *p
== '_')
427 if (voice_tb
[0].name
[0] == '\0')
428 voice
= 0; /* first voice */
430 for (voice
= 0; voice
<= nvoice
; voice
++) {
431 if (strcmp(name
, voice_tb
[voice
].name
) == 0)
434 if (voice
>= MAXVOICE
) {
435 syntax("Too many voices", name
);
440 strncpy(voice_tb
[voice
].name
, name
, sizeof voice_tb
[voice
].name
- 1);
441 voice_tb
[voice
].mvoice
= voice
;
448 /* -- treat the broken rhythm '>' and '<' -- */
449 static void broken_rhythm(struct note
*note
,
450 int num
) /* >0: do dot, <0: do half */
459 for (m
= 0; m
<= note
->nhd
; m
++)
460 note
->lens
[m
] = (note
->lens
[m
] * n
) / num
;
465 for (m
= 0; m
<= note
->nhd
; m
++)
469 for (m
= 1; m
<= note
->nhd
; m
++)
470 if (note
->lens
[m
] < l
)
474 /* -- check for the '!' as end of line (ABC2Win) -- */
475 static int check_nl(unsigned char *p
)
493 /* -- parse a decoration '[!|+]xxx[!|+]' -- */
494 static char *get_deco(unsigned char *p
,
495 unsigned char *p_deco
)
497 unsigned char *q
, sep
;
504 if (sep
!= '!' && sep
!= '+')
505 sep
= '\0'; /* Barfly U: */
508 syntax("Decoration not terminated", q
);
516 for (i
= 1, t
= &deco_tb
[1];
520 && strncmp(*t
, q
, l
) == 0) {
528 if (level_f
&& abc_state
!= ABC_S_GLOBAL
)
531 if (level_f
&& abc_state
!= ABC_S_GLOBAL
)
536 } else syntax("Too many decoration types", q
);
540 /* -- parse a list of accidentals (K:) -- */
541 static unsigned char *parse_acc(unsigned char *p
,
544 int pit
, len
, acc
, nostem
, nacc
;
546 nacc
= s
->u
.key
.nacc
;
548 if (nacc
>= sizeof s
->u
.key
.pits
) {
549 syntax("Too many accidentals", 0);
552 p
= parse_basic_note(p
, &pit
, &len
, &acc
, &nostem
);
553 s
->u
.key
.pits
[nacc
] = pit
- curvoice
->add_pitch
;
554 s
->u
.key
.accs
[nacc
++] = acc
;
557 if (*p
!= '^' && *p
!= '_' && *p
!= '=')
560 s
->u
.key
.nacc
= nacc
;
564 /* -- parse a 'K:' -- */
565 static void parse_key(unsigned char *p
,
571 /* check for clef alone */
572 memset(&clef
, 0, sizeof clef
);
574 p
= parse_clef(p
, &clef
);
578 case 'F': sf
= -1; break;
586 s
->u
.key
.bagpipe
= 1;
589 else if (*p
== 'p') {
592 } else syntax("Unknown bagpipe-like key", p
);
597 p
--; /* explicit accidentals */
604 syntax("Key not recognized", p
);
611 } else if (*p
== 'b') {
623 p
= parse_clef(p
, &clef
);
629 if (strncasecmp(p
, "aeo", 3) == 0) {
636 if (strncasecmp(p
, "dor", 3) == 0)
642 if (strncasecmp(p
, "ion", 3) == 0)
647 if (strncasecmp(p
, "loc", 3) == 0)
649 else if (strncasecmp(p
, "lyd", 3) == 0)
655 if (strncasecmp(p
, "maj", 3) == 0)
657 else if (strncasecmp(p
, "mix", 3) == 0)
659 else if (strncasecmp(p
, "min", 3) == 0
660 || !isalpha(p
[1])) { /* 'm' alone */
667 if (strncasecmp(p
, "octave", 6) == 0) { /* (abcMIDI) */
669 while (!isspace(*p
) && *p
!= '\0')
676 if (strncasecmp(p
, "phr", 3) == 0)
683 p
= parse_acc(p
, s
); /* explicit accidentals */
688 /* "+8" / "-8" (fixme: not standard) */
690 curvoice
->add_pitch
+= 7;
691 else curvoice
->add_pitch
-= 7;
698 syntax("Unknown token in key specifier", p
);
699 while (!isspace(*p
) && *p
!= '\0')
707 if (sf
> 7 || sf
< -7) {
708 syntax("Too many sharps/flats", p
);
715 if (clef
.type
>= 0) {
718 s2
= abc_new(s
->tune
, 0, 0);
719 s2
->type
= ABC_T_CLEF
;
720 memcpy(&s2
->u
.clef
, &clef
, sizeof s2
->u
.clef
);
724 /* -- set default length from 'L:' -- */
725 static char *get_len(unsigned char *p
,
733 if (sscanf(p
, "%d /%d ", &l1
, &l2
) != 2
735 s
->u
.length
.base_length
= ulen
? ulen
: BASE_LEN
/ 8;
736 return "Bad unit note length: unchanged";
740 if (d
* l2
!= BASE_LEN
) {
741 error_txt
= "Length incompatible with BASE, using 1/8";
746 || (l2
& (l2
- 1))) {
747 error_txt
= "Incorrect unit note length, using 1/8";
751 s
->u
.length
.base_length
= d
;
755 /* -- get a new line from the current file in memory -- */
756 static unsigned char *get_line(void)
765 line
= p
; /* (for syntax error) */
767 /* memorize the beginning of the next line */
777 if (p
[-1] == '\r' && *p
== '\n')
783 /* allocate space for the line */
784 if (scratch_line
!= 0
785 && l
>= scratch_length
) {
789 if (scratch_line
== 0) {
790 scratch_line
= malloc(l
+ 1);
796 line_length
= l
; /* for syntax error */
801 /* -- parse a 'M:' -- */
802 static char *parse_meter(unsigned char *p
,
805 int m1
, m2
, d
, wmeasure
;
810 return "Empty meter string";
814 if (*p
== 'N' || *p
== 'n')
816 else if (*p
== 'C') {
817 s
->u
.meter
.meter
[0].top
[0] = *p
++;
819 s
->u
.meter
.meter
[0].top
[1] = *p
++;
820 wmeasure
= 4 * BASE_LEN
/ 4;
822 } else while (*p
!= '\0') {
823 if (*p
== '(' || *p
== ')') {
827 s
->u
.meter
.meter
[nm
].top
[0] = *p
++;
831 if (sscanf(p
, "%d", &m1
) != 1
833 return "Cannot identify meter top";
835 m2
= 2; /* default when no bottom value */
838 && i
< sizeof s
->u
.meter
.meter
[0].top
)
839 s
->u
.meter
.meter
[nm
].top
[i
++] = *p
++;
842 if (sscanf(p
, "%d", &m2
) != 1
844 return "Cannot identify meter bottom";
847 && i
< sizeof s
->u
.meter
.meter
[0].bot
)
848 s
->u
.meter
.meter
[nm
].bot
[i
++] = *p
++;
851 if (*p
!= ' ' && *p
!= '+')
853 s
->u
.meter
.meter
[nm
].top
[i
++] = *p
++;
854 if (sscanf(p
, "%d", &d
) != 1
856 return "Cannot identify meter top";
863 wmeasure
+= m1
* BASE_LEN
/ m2
;
865 if (*p
== ' ' || *p
== '+') {
866 s
->u
.meter
.meter
[nm
].top
[0] = *p
++;
871 s
->u
.meter
.wmeasure
= wmeasure
;
872 s
->u
.meter
.nmeter
= nm
;
874 /* if in the header, change the unit note length */
875 if (abc_state
== ABC_S_HEAD
&& ulen
== 0) {
876 if (wmeasure
>= BASE_LEN
* 3 / 4
879 else ulen
= BASE_LEN
/ 16;
885 /* -- treat %%staves -- */
886 static void get_staves(unsigned char *p
,
891 struct staff_s
*staff
;
893 /* define the voices */
903 if (flags
& (OPEN_BRACKET
| OPEN_BRACE
| OPEN_PARENTH
))
905 flags
|= OPEN_BRACKET
;
911 staff
->flags
|= CLOSE_BRACKET
;
914 if (flags
& (OPEN_BRACKET
| OPEN_BRACE
| OPEN_PARENTH
))
922 staff
->flags
|= CLOSE_BRACE
;
925 if (flags
& OPEN_PARENTH
)
927 flags
|= OPEN_PARENTH
;
933 staff
->flags
|= CLOSE_PARENTH
;
938 staff
->flags
|= STOP_BAR
;
941 if (!isalnum(*p
) && *p
!= '_')
946 p
= def_voice(p
, &v
);
947 staff
= &s
->u
.staves
[voice
];
950 staff
->name
= alloc_f(strlen(voice_tb
[v
].name
) + 1);
951 strcpy(staff
->name
, voice_tb
[v
].name
);
953 staff
->flags
= flags
;
960 /* check for errors */
964 flags
= CLOSE_BRACKET
| CLOSE_BRACE
| CLOSE_PARENTH
; /* bad flags */
966 for (voice
= 0, staff
= s
->u
.staves
;
967 voice
<= MAXVOICE
&& staff
->name
;
969 if (staff
->flags
& flags
)
971 if (staff
->flags
& CLOSE_PARENTH
)
973 if (staff
->flags
& OPEN_BRACKET
) {
974 flags
&= ~CLOSE_BRACKET
;
975 flags
|= OPEN_BRACKET
| OPEN_BRACE
;
976 } else if (staff
->flags
& CLOSE_BRACKET
) {
977 flags
&= ~(OPEN_BRACKET
| OPEN_BRACE
);
978 flags
|= CLOSE_BRACKET
;
979 } else if (staff
->flags
& OPEN_BRACE
) {
980 flags
&= ~CLOSE_BRACE
;
981 flags
|= OPEN_BRACKET
| OPEN_BRACE
;
982 } else if (staff
->flags
& CLOSE_BRACE
) {
983 flags
&= ~(OPEN_BRACKET
| OPEN_BRACE
);
984 flags
|= CLOSE_BRACE
;
986 if (staff
->flags
& OPEN_PARENTH
) {
988 flags
&= ~CLOSE_PARENTH
;
994 syntax("%%%%staves error", p
);
997 /* -- get a possibly quoted string -- */
998 char *get_str(unsigned char *d
, /* destination */
999 unsigned char *s
, /* source */
1000 int maxlen
) /* max length */
1004 maxlen
--; /* have place for the EOS */
1012 while ((c
= *s
) != '\0') {
1014 || (c
== '\t' && sep
== ' ')) {
1021 || (c
== '\t' && sep
== ' '))) {
1035 /* -- parse a tempo (Q:) -- */
1036 static char *parse_tempo(unsigned char *p
,
1046 while (*p
!= '"' && *p
!= '\0')
1049 s
->u
.tempo
.str1
= alloc_f(l
+ 1);
1050 strncpy(s
->u
.tempo
.str1
, q
, l
);
1051 s
->u
.tempo
.str1
[l
] = '\0';
1059 if (*p
== 'C' || *p
== 'c'
1060 || *p
== 'L' || *p
== 'l') {
1063 p
= parse_len(p
+ 1, &len
);
1066 else s
->u
.tempo
.length
[0] = len
;
1069 } else if (isdigit(*p
) && strchr(p
, '/') != 0) {
1073 while (isdigit(*p
)) {
1076 if (sscanf(p
, "%d /%d%n", &top
, &bot
, &n
) != 2
1081 l
= (BASE_LEN
* top
) / bot
;
1083 || i
>= sizeof s
->u
.tempo
.length
1084 / sizeof s
->u
.tempo
.length
[0])
1086 else s
->u
.tempo
.length
[i
++] = l
;
1093 /* tempo value ('Q:beat=value' or 'Q:value') */
1102 else s
->u
.tempo
.value
= value
;
1103 while (isdigit(*p
) || isspace(*p
))
1110 while (*p
!= '"' && *p
!= '\0')
1113 s
->u
.tempo
.str2
= alloc_f(l
+ 1);
1114 strncpy(s
->u
.tempo
.str2
, q
, l
);
1115 s
->u
.tempo
.str2
[l
] = '\0';
1118 return have_error
? "Invalid tempo" : 0;
1121 /* -- get a user defined accent (U:) -- */
1122 static char *get_user(unsigned char *p
,
1125 /*fixme: may have 'U: <char> = "text" */
1126 if (char_tb
[*p
] != CHAR_DECO
) /* accept any character */
1127 /*fixme: should be for the current tune only */
1128 char_tb
[*p
] = CHAR_DECO
;
1129 s
->u
.user
.symbol
= *p
++;
1132 while (isspace(*p
) || *p
== '=')
1134 if (*p
== '!' || *p
== '+')
1136 get_deco(p
, &s
->u
.user
.value
);
1140 /* -- parse the voice parameters (V:) -- */
1141 static char *parse_voice(unsigned char *p
,
1145 char *error_txt
= 0;
1146 char name
[VOICE_NAME_SZ
];
1148 static struct kw_s
{
1165 /* save the unit note length of the previous voice */
1166 curvoice
->ulen
= ulen
;
1168 if (voice_tb
[0].name
[0] == '\0') {
1169 switch (s
->prev
->type
) {
1174 /* the previous voice was implicit (after K:) */
1175 voice_tb
[0].name
[0] = '1';
1182 p
= def_voice(p
, &voice2
);
1185 curvoice
= &voice_tb
[voice
];
1186 s
->u
.voice
.voice
= voice
;
1187 s
->u
.voice
.name
= alloc_f(strlen(curvoice
->name
) + 1);
1188 strcpy(s
->u
.voice
.name
, curvoice
->name
);
1190 /* if in tune, set the unit note length */
1191 if (abc_state
== ABC_S_TUNE
1192 && curvoice
->ulen
!= 0)
1193 ulen
= curvoice
->ulen
;
1195 /* parse the other parameters */
1196 memset(&clef
, 0, sizeof clef
);
1203 for (kw
= kw_tb
; kw
->name
; kw
++) {
1204 if (strncmp(p
, kw
->name
, kw
->len
) == 0)
1209 /* unknown keyword, try a clef */
1210 p
= parse_clef(p
, &clef
);
1213 while (!isspace(*p
) && *p
!= '\0')
1214 p
++; /* ignore unknown keywords */
1218 switch (kw
->index
) {
1220 p
= get_str(name
, p
, VOICE_NAME_SZ
);
1221 s
->u
.voice
.fname
= alloc_f(strlen(name
) + 1);
1222 strcpy(s
->u
.voice
.fname
, name
);
1224 case 1: /* subname */
1225 p
= get_str(name
, p
, VOICE_NAME_SZ
);
1226 s
->u
.voice
.nname
= alloc_f(strlen(name
) + 1);
1227 strcpy(s
->u
.voice
.nname
, name
);
1230 s
->u
.voice
.merge
= 1;
1233 s
->u
.voice
.stem
= 1;
1236 s
->u
.voice
.stem
= -1;
1240 if (clef
.type
>= 0) {
1243 s2
= abc_new(s
->tune
, 0, 0);
1244 s2
->type
= ABC_T_CLEF
;
1245 memcpy(&s2
->u
.clef
, &clef
, sizeof s2
->u
.clef
);
1250 /* -- parse a bar -- */
1251 static char *parse_bar(struct abctune
*t
,
1256 char repeat_value
[32];
1284 if ((bar_type
& 0x0f) == B_OBRA
&& bar_type
!= B_OBRA
) {
1285 bar_type
>>= 4; /* have an other bar for '[' */
1288 if (bar_type
== (B_OBRA
<< 8) + (B_BAR
<< 4) + B_CBRA
) /* [|] */
1289 bar_type
= (B_OBRA
<< 4) + B_CBRA
; /* [] */
1291 /* curvoice->last_note = 0; */
1293 curvoice
= &voice_tb
[curvoice
->mvoice
];
1296 s
= abc_new(t
, gchord
, 0);
1302 s
->type
= ABC_T_BAR
;
1303 s
->state
= ABC_S_TUNE
;
1304 s
->u
.bar
.type
= bar_type
;
1307 memcpy(&s
->u
.bar
.dc
, &dc
, sizeof s
->u
.bar
.dc
);
1310 if (!isdigit(*p
) /* if not a repeat bar */
1311 && (*p
!= '"' || p
[-1] != '[')) { /* ('["' only) */
1317 /* measure repeat */
1323 s
= abc_new(t
, 0, 0);
1324 s
->type
= ABC_T_MREP
;
1325 s
->state
= ABC_S_TUNE
;
1332 p
= get_str(repeat_value
, p
, sizeof repeat_value
);
1340 || (*p
== '.' && isdigit(p
[1]))) {
1341 if (q
< &repeat_value
[sizeof repeat_value
- 1])
1347 if (repeat_value
[0] != '1' || repeat_value
[1] != '\0')
1349 if (bar_type
!= B_OBRA
1351 s
= abc_new(t
, repeat_value
, 0);
1352 s
->type
= ABC_T_BAR
;
1353 s
->state
= ABC_S_TUNE
;
1354 s
->u
.bar
.type
= B_OBRA
;
1356 s
->text
= alloc_f(strlen(repeat_value
) + 1);
1357 strcpy(s
->text
, repeat_value
);
1359 s
->u
.bar
.repeat_bar
= 1;
1363 /* -- parse note or rest with pitch and length -- */
1364 static char *parse_basic_note(char *p
,
1370 int pit
, len
, acc
, nostem
;
1372 acc
= pit
= nostem
= 0;
1374 /* look for accidental sign */
1398 p_n
= strchr(all_notes
, *p
);
1400 || p_n
- all_notes
>= 14) {
1402 syntax("Missing note after accidental",
1404 else syntax("Not a note", p
);
1405 pit
= 16 + 7; /* 'c' */
1406 } else pit
= p_n
- all_notes
+ 16;
1410 while (*p
== '\'') { /* eat up following ' chars */
1415 while (*p
== ',') { /* eat up following , chars */
1425 p
= parse_len(p
, &len
);
1426 len
= len
* ulen
/ BASE_LEN
;
1428 *pitch
= pit
+ curvoice
->add_pitch
;
1436 /* -- parse a clef (K: or V:) -- */
1437 static unsigned char *parse_clef(unsigned char *p
,
1438 struct clef_s
*p_clef
)
1446 while (*p
!= '\0') {
1448 if (strncmp(p
, "clef=", 5) == 0) {
1485 while (*p
== '\'') {
1491 if (!strncmp(p
, "bass", 4)) {
1494 #ifdef CLEF_TRANSPOSE
1497 p_clef
->check_pitch
= 1;
1501 } else if (!strncmp(p
, "treble", 6)) {
1505 } else if (!strncmp(p
, "alto", 4)
1506 || !strncmp(p
, "tenor", 5)) {
1508 clef_line
= *p
== 'a' ? 3 : 4;
1509 #ifdef CLEF_TRANSPOSE
1512 p_clef
->check_pitch
= 1;
1518 } else if (!strncmp(p
, "perc", 4)) {
1521 } else if (strncmp(p
, "none", 4) == 0) {
1525 } else if (!strncmp(p
, "middle=", 7)) {
1528 while (!isspace(*p
) && *p
!= '\0')
1543 clef_line
= *p
++ - '0';
1548 p_clef
->octave
= -1;
1550 } else if (*p
== '+') {
1560 int pit
, len
, acc
, nostem
, l
;
1562 /* 'middle=<note pitch>' */
1565 curvoice
->add_pitch
= 0;
1566 parse_basic_note(middle
, &pit
, &len
, &acc
, &nostem
);
1576 l
= l
- pit
+ 4 + 14;
1577 clef_line
= (l
% 7) / 2 + 1;
1578 transpose
= l
/ 7 * 7 - 14;
1579 #ifndef CLEF_TRANSPOSE
1580 p_clef
->check_pitch
= 0;
1585 curvoice
->add_pitch
= transpose
;
1586 p_clef
->line
= clef_line
;
1587 p_clef
->transpose
= transpose
;
1588 if (p_clef
->type
>= 0)
1589 syntax("Double clef definition", p
);
1591 p_clef
->type
= clef
;
1595 /* -- parse for decoration on note/bar -- */
1596 unsigned char *parse_deco(unsigned char *p
,
1605 if (char_tb
[c
] != CHAR_DECO
&& char_tb
[c
] != CHAR_DECOS
)
1608 if (char_tb
[c
] == CHAR_DECOS
)
1609 p
= get_deco(p
, &d
);
1612 syntax("Too many decorations for the note", p
);
1620 /* -- parse a decoration line (d: or s:) -- */
1621 static char *parse_decoline(unsigned char *p
)
1627 if ((is
= deco_cont
) == 0)
1631 /* scan the decoration line */
1632 while (*p
!= '\0') {
1639 while (is
!= 0 && (is
->type
!= ABC_T_BAR
1640 || is
->u
.bar
.type
== B_OBRA
))
1643 syntax("Not enough bar lines for lyric line", p
);
1650 while (is
!= 0 && is
->type
!= ABC_T_NOTE
)
1653 syntax("Not enough notes for decoration line", p
);
1662 return "Not enough notes for decoration line";
1666 syntax("'\\' ignored", p
);
1671 p
= get_deco(p
+ 1, &d
);
1678 /* store the decoration in the next note */
1679 while (is
!= 0 && is
->type
!= ABC_T_NOTE
)
1682 return "Not enough notes for decoration line";
1684 n
= is
->u
.note
.dc
.n
;
1686 syntax("Too many decorations for the note", p
);
1688 is
->u
.note
.dc
.t
[n
] = d
;
1689 is
->u
.note
.dc
.n
= n
+ 1;
1696 /* -- parse a note length -- */
1697 static unsigned char *parse_len(unsigned char *p
,
1704 len
*= strtol(p
, 0, 10);
1712 fac
*= strtol(p
, 0, 10);
1717 syntax("Bad length divisor", p
- 1);
1726 /* -- parse a music line -- */
1727 /* return 0 at end of tune */
1728 static int parse_line(struct abctune
*t
,
1732 unsigned char *comment
;
1733 struct abcsym
*last_note_sav
= 0;
1734 unsigned char *q
, c
;
1737 static char qtb
[10] = {1, 1, 3, 2, 3, 0, 2, 0, 3, 0};
1739 again
: /* for history */
1742 switch (abc_state
) {
1744 case ABC_S_HEAD
: /*fixme: may have blank lines in headers*/
1746 s
= abc_new(t
, 0, 0);
1747 s
->type
= ABC_T_NULL
;
1748 s
->state
= abc_state
;
1752 abc_state
= ABC_S_GLOBAL
;
1758 comment
= decomment_line(p
+ 2);
1759 s
= abc_new(t
, p
, comment
);
1760 s
->type
= ABC_T_PSCOM
;
1761 s
->state
= abc_state
;
1762 p
+= 2; /* skip '%%' */
1763 if (strncasecmp(p
, "fmt ", 4) == 0)
1764 p
+= 4; /* skip 'fmt' */
1765 if (strncmp(p
, "begintext", 9) == 0) {
1767 if ((p
= get_line()) == 0) {
1768 syntax("EOF while parsing %%begintext pseudo-comment",
1772 s
= abc_new(t
, p
, 0);
1773 s
->type
= ABC_T_PSCOM
;
1774 s
->state
= abc_state
;
1775 if (*p
!= '%' || p
[1] != '%')
1778 if (strncasecmp(p
, "fmt ", 4) == 0)
1780 if (strncmp(p
, "endtext", 7) == 0)
1785 if (strncmp(p
, "staves ", 7) == 0)
1786 get_staves(p
+ 7, s
);
1790 s
= abc_new(t
, p
, 0);
1791 s
->type
= ABC_T_NULL
;
1792 s
->state
= abc_state
;
1794 return 1; /* skip comments */
1796 return 1; /* ignore abc2mtex specific lines */
1798 comment
= decomment_line(p
);
1802 && *p
!= '|' && *p
!= ':') { /* not '|:' nor '::' */
1803 parse_header(t
, p
, comment
);
1806 /* wait for an other 'x:' or any '%%' */
1808 if ((p
= get_line()) == 0)
1811 || (p
[1] == '%' && *p
== '%'))
1813 if (abc_state
== ABC_S_HEAD
) {
1814 s
= abc_new(t
, p
, 0);
1815 s
->type
= ABC_T_INFO2
;
1816 s
->state
= abc_state
;
1821 /* handle BarFly voice definition */
1822 /* 'V:n <note line ending with a bar>' */
1824 || abc_state
!= ABC_S_TUNE
)
1826 c
= p
[strlen(p
) - 1];
1827 if (c
!= '|' && c
!= ']')
1829 while (!isspace(*p
) && *p
!= '\0')
1834 if (abc_state
!= ABC_S_TUNE
) {
1836 s
= abc_new(t
, p
, comment
);
1837 s
->type
= ABC_T_NULL
;
1838 s
->state
= abc_state
;
1843 if (scratch_line
[0] == ' ' && curvoice
->last_note
!= 0)
1844 curvoice
->last_note
->u
.note
.word_end
= 1;
1847 deco_start
= deco_cont
= 0;
1848 while (*p
!= '\0') {
1849 switch (char_tb
[*p
++]) {
1850 case CHAR_GCHORD
: { /* " */
1869 /* many guitar chord: concatenate with '\n' */
1870 l2
= strlen(gchord
);
1871 gch
= alloc_f(l2
+ 1 + l
+ 1);
1872 strcpy(gch
, gchord
);
1874 strncpy(&gch
[l2
], q
, l
);
1880 gchord
= alloc_f(l
+ 1);
1881 strncpy(gchord
, q
, l
);
1886 else if (more_gch
) {
1887 if ((p
= get_line()) == 0) {
1888 syntax("EOF reached while parsing guitar chord",
1896 case CHAR_GRACE
: /* '{' or '}' */
1902 char_tb
['{'] = CHAR_BAD
;
1903 char_tb
['}'] = CHAR_GRACE
;
1904 last_note_sav
= curvoice
->last_note
;
1905 curvoice
->last_note
= 0;
1907 char_tb
['{'] = CHAR_GRACE
;
1908 char_tb
['}'] = CHAR_BAD
;
1910 t
->last_sym
->u
.note
.word_end
= 1;
1911 curvoice
->last_note
= last_note_sav
;
1916 if (p
[-1] == '!' && check_nl(p
)) {
1917 s
= abc_new(t
, 0, 0); /* abc2win EOL */
1918 s
->type
= ABC_T_EOLN
;
1919 s
->state
= abc_state
;
1922 if (p
[-1] == '.' && *p
== '|') {
1923 p
= parse_bar(t
, p
+ 1);
1924 /*fixme: should have other dashed bars, as '.||' */
1925 t
->last_sym
->u
.bar
.type
= B_COL
;
1928 p
= parse_deco(p
- 1, &dc
);
1933 p
= parse_note(t
, p
- 1);
1935 t
->last_sym
->u
.note
.sappo
= 1;
1938 curvoice
->last_note
= t
->last_sym
;
1940 case CHAR_BSLASH
: /* '\\' */
1941 /*fixme: KO if in grace note sequence*/
1944 syntax("'\\' ignored", p
- 1);
1946 case CHAR_OBRA
: /* '[' */
1947 if (*p
== '|' || *p
== ']'
1948 || isdigit(*p
) || *p
== '"') {
1949 p
= parse_bar(t
, p
);
1953 p
= parse_note(t
, p
- 1); /* chord */
1955 t
->last_sym
->u
.note
.sappo
= 1;
1958 curvoice
->last_note
= t
->last_sym
;
1962 /* embedded header */
1965 while (*p
!= '\0' && *p
!= c
)
1968 syntax("Escape sequence [..] not closed",
1972 abc_state
= ABC_S_EMBED
;
1973 parse_header(t
, q
, 0);
1974 abc_state
= ABC_S_TUNE
;
1977 case CHAR_BAR
: /* '|', ':' or ']' */
1978 p
= parse_bar(t
, p
);
1980 case CHAR_OPAR
: /* '(' */
1982 curvoice
->pplet
= *p
- '0';
1983 curvoice
->qplet
= qtb
[curvoice
->pplet
];
1984 curvoice
->rplet
= curvoice
->pplet
;
1989 curvoice
->qplet
= *p
- '0';
1995 curvoice
->rplet
= *p
- '0';
2000 if (curvoice
->qplet
== 0)
2001 curvoice
->qplet
= meter
% 3 == 0
2004 } else if (*p
== '&') {
2005 s
= abc_new(t
, 0, 0);
2006 s
->type
= ABC_T_V_OVER
;
2009 s
->u
.v_over
.type
= V_OVER_SD
;
2011 } else s
->u
.v_over
.type
= V_OVER_SS
;
2012 s
->u
.v_over
.voice
= curvoice
- voice_tb
;
2013 char_tb
[')'] = CHAR_VOVE
;
2014 } else curvoice
->slur
++;
2016 case CHAR_CPAR
: /* ')' */
2017 switch (t
->last_sym
->type
) {
2024 t
->last_sym
->u
.note
.slur_end
++;
2026 case CHAR_VOV
: /* '&' */
2027 s
= abc_new(t
, 0, 0);
2028 s
->type
= ABC_T_V_OVER
;
2030 s
->u
.v_over
.type
= V_OVER_D
;
2032 } /*else s->u.v_over.type = V_OVER_S; */
2034 s
->u
.v_over
.voice
= curvoice
- voice_tb
;
2035 if (char_tb
[')'] != CHAR_VOVE
)
2038 case CHAR_VOVE
: /* ')' after '(&' */
2039 s
= abc_new(t
, 0, 0);
2040 s
->type
= ABC_T_V_OVER
;
2041 s
->u
.v_over
.type
= V_OVER_E
;
2042 s
->u
.v_over
.voice
= curvoice
->mvoice
;
2043 char_tb
[')'] = CHAR_CPAR
;
2044 curvoice
->last_note
= 0; /* ?? */
2045 curvoice
= &voice_tb
[curvoice
->mvoice
];
2047 case CHAR_SPAC
: /* ' ' and '\t' */
2048 if (curvoice
->last_note
!= 0)
2049 curvoice
->last_note
->u
.note
.word_end
= 1;
2051 case CHAR_MINUS
: /* '-' */
2052 if ((curvoice
->tie
= curvoice
->last_note
) == 0
2053 || curvoice
->tie
->type
!= ABC_T_NOTE
)
2055 for (i
= 0; i
<= curvoice
->tie
->u
.note
.nhd
; i
++)
2056 curvoice
->tie
->u
.note
.ti1
[i
] = 1;
2058 case CHAR_BRHY
: /* '>' and '<' */
2059 if (curvoice
->last_note
== 0)
2062 while (*p
== p
[-1]) {
2067 syntax("Bad broken rhythm", p
- 1);
2072 broken_rhythm(&curvoice
->last_note
->u
.note
, i
);
2073 curvoice
->last_note
->u
.note
.brhythm
= i
;
2075 case CHAR_IGN
: /* '*' & '`' */
2079 syntax("Bad character", p
- 1);
2084 /*fixme: may we have grace notes across lines?*/
2085 if (char_tb
['{'] == CHAR_BAD
) {
2086 syntax("No end of grace note sequence", 0);
2087 char_tb
['{'] = CHAR_GRACE
;
2088 char_tb
['}'] = CHAR_BAD
;
2089 if (curvoice
->last_note
!= 0)
2090 curvoice
->last_note
->u
.note
.word_end
= 1;
2091 curvoice
->last_note
= last_note_sav
;
2095 s
= abc_new(t
, 0, 0);
2096 s
->type
= ABC_T_EOLN
;
2097 s
->state
= abc_state
;
2102 /* -- parse a note -- */
2103 static unsigned char *parse_note(struct abctune
*t
,
2108 int pit
, len
, acc
, nostem
;
2109 int chord
, sl1
, sl2
;
2112 signed char tie_pit
[MAXHD
];
2114 s
= abc_new(t
, gchord
, 0);
2115 s
->type
= ABC_T_NOTE
;
2116 s
->state
= ABC_S_TUNE
;
2117 if (gchord
&& free_f
)
2122 memcpy(&s
->u
.note
.dc
, &dc
, sizeof s
->u
.note
.dc
);
2126 if (char_tb
['{'] == CHAR_BAD
) /* in a grace note sequence */
2127 s
->u
.note
.grace
= 1;
2128 else if (curvoice
->rplet
) { /* start of n-plet */
2129 s
->u
.note
.p_plet
= curvoice
->pplet
;
2130 s
->u
.note
.q_plet
= curvoice
->qplet
;
2131 s
->u
.note
.r_plet
= curvoice
->rplet
;
2132 curvoice
->rplet
= 0;
2137 case 'Z': /* multi-rest */
2138 s
->type
= ABC_T_MREST
;
2142 len
= strtol(p
, 0, 10);
2149 case 'y': /* space (BarFly) */
2150 s
->type
= ABC_T_REST
;
2151 s
->u
.note
.invis
= 1;
2152 s
->u
.note
.slur_st
+= curvoice
->slur
;
2155 case 'x': /* invisible rest */
2156 s
->u
.note
.invis
= 1;
2159 s
->type
= ABC_T_REST
;
2160 p
= parse_len(p
+ 1, &len
);
2161 s
->u
.note
.lens
[0] = len
* ulen
/ BASE_LEN
;
2162 if (curvoice
->last_note
!= 0
2163 && curvoice
->last_note
->u
.note
.brhythm
!= 0)
2164 broken_rhythm(&s
->u
.note
,
2165 -curvoice
->last_note
->u
.note
.brhythm
);
2169 if (!s
->u
.note
.grace
&& !lyric_started
) {
2171 s
->u
.note
.lyric_start
= 1;
2177 if (*p
== '[') { /* accept only '[..]' for chord */
2182 /* prepare searching the end of ties */
2184 if (curvoice
->tie
!= 0) {
2185 for (m
= 0; m
<= curvoice
->tie
->u
.note
.nhd
; m
++) {
2186 if (curvoice
->tie
->u
.note
.ti1
[m
])
2187 tie_pit
[ntie
++] = curvoice
->tie
->u
.note
.pits
[m
];
2192 /* get pitch and length */
2199 if (chord
&& *p
== '(') {
2200 s
->u
.note
.sl1
[m
] = ++sl1
;
2203 p
= parse_deco(p
, &dc
); /* for extra decorations within chord */
2204 if (strchr(all_notes
, *p
) == 0) {
2205 syntax("Not a note", p
);
2208 p
= parse_basic_note(p
,
2213 if (s
->u
.note
.grace
) {
2214 len
= len
* BASE_LEN
/ 4 / ulen
;
2217 s
->u
.note
.pits
[m
] = pit
;
2218 s
->u
.note
.lens
[m
] = len
;
2219 s
->u
.note
.accs
[m
] = acc
;
2222 for (j
= 0; j
< ntie
; j
++) {
2223 if (tie_pit
[j
] == pit
) {
2224 s
->u
.note
.ti2
[m
] = 1;
2232 s
->u
.note
.ti1
[m
] = 1;
2237 s
->u
.note
.sl2
[m
] = ++sl2
;
2240 s
->u
.note
.ti1
[m
] = 1;
2252 if (*p
== '/' || isdigit(*p
)) {
2253 p
= parse_len(p
, &len
);
2254 for (j
= 0; j
< m
; j
++) {
2255 tmp
= len
* s
->u
.note
.lens
[j
];
2256 s
->u
.note
.lens
[j
] = tmp
/ BASE_LEN
;
2262 syntax("Chord not closed", q
);
2266 s
->u
.note
.stemless
= nostem
;
2268 /* warn about the bad ties */
2269 if (char_tb
['{'] != CHAR_BAD
) { /* if not in a grace note sequence */
2270 for (j
= 0; j
< ntie
; j
++) {
2271 if (tie_pit
[j
] != -128)
2272 syntax("Bad tie", p
);
2276 if (m
== 0) { /* if no note */
2277 if ((t
->last_sym
= s
->prev
) == 0)
2279 else s
->prev
->next
= 0;
2282 s
->u
.note
.nhd
= m
- 1;
2284 if (curvoice
->last_note
!= 0
2285 && curvoice
->last_note
->u
.note
.brhythm
!= 0)
2286 broken_rhythm(&s
->u
.note
,
2287 -curvoice
->last_note
->u
.note
.brhythm
);
2288 s
->u
.note
.slur_st
+= curvoice
->slur
;
2294 /* -- parse a header -- */
2295 static void parse_header(struct abctune
*t
,
2300 unsigned char header_type
= *p
;
2301 char *error_txt
= 0;
2303 s
= abc_new(t
, p
, comment
);
2304 s
->type
= ABC_T_INFO
;
2305 s
->state
= abc_state
;
2310 switch (header_type
) {
2313 if (deco_start
== 0) {
2314 error_txt
= "Erroneous 'd:'/'s:'";
2317 error_txt
= parse_decoline(p
);
2320 if (abc_state
== ABC_S_GLOBAL
)
2323 if (abc_state
== ABC_S_HEAD
) {
2325 ulen
= BASE_LEN
/ 8;
2326 abc_state
= ABC_S_TUNE
;
2330 error_txt
= get_len(p
, s
);
2331 ulen
= s
->u
.length
.base_length
;
2332 if (abc_state
== ABC_S_GLOBAL
)
2336 error_txt
= parse_meter(p
, s
);
2339 error_txt
= parse_tempo(p
, s
);
2342 error_txt
= get_user(p
, s
);
2345 if (abc_state
== ABC_S_GLOBAL
)
2347 error_txt
= parse_voice(p
, s
);
2350 if (abc_state
!= ABC_S_GLOBAL
)
2352 /* 'T:' may start a new tune without 'X:' */
2353 print_warning("T: without X:");
2356 if (abc_state
!= ABC_S_GLOBAL
) {
2357 error_txt
= "Previous tune not closed properly";
2358 /*??maybe call end_tune if ABC_S_TUNE??*/
2360 memset(voice_tb
, 0, sizeof voice_tb
);
2362 curvoice
= &voice_tb
[0];
2363 abc_state
= ABC_S_HEAD
;
2369 syntax(error_txt
, p
);
2372 /* -- sytax: print message for syntax errror -- */
2373 static void syntax(char *msg
,
2376 int n
, len
, m1
, m2
, pp
;
2380 n
= q
- scratch_line
;
2381 if ((unsigned) n
>= line_length
)
2383 print_error(msg
, n
);
2386 fprintf(stderr
, " (near '%s')\n", q
);
2389 /* printf("\n++++ %s in line %d.%d\n", msg, linenum, n + 1); */
2391 m2
= len
= line_length
- 1;
2403 fprintf(stderr
, "%4d ", linenum
);
2406 fprintf(stderr
, "...");
2409 fprintf(stderr
, "%*s", m2
- m1
, &scratch_line
[m1
]);
2411 fprintf(stderr
, "...");
2412 fprintf(stderr
, "\n");
2414 if ((unsigned) n
< 200)
2415 fprintf(stderr
, "%*s\n", n
+ pp
- m1
, "^");
2418 /* -- switch to a new voice overlay -- */
2419 static void vover_new(void)
2423 mvoice
= curvoice
- voice_tb
;
2424 for (voice
= mvoice
+ 1; voice
<= nvoice
; voice
++)
2425 if (voice_tb
[voice
].mvoice
== mvoice
)
2427 if (voice
> nvoice
) {
2428 if (nvoice
>= MAXVOICE
) {
2429 syntax("Too many voices", 0);
2433 voice_tb
[voice
].name
[0] = '&';
2434 voice_tb
[voice
].mvoice
= mvoice
;
2436 voice_tb
[voice
].ulen
= curvoice
->ulen
;
2437 voice_tb
[voice
].add_pitch
= curvoice
->add_pitch
;
2438 curvoice
= &voice_tb
[voice
];