parse.h - abc2ps - A powerful sheet setting tool using the simple abc notation | |
git clone git://vernunftzentrum.de/abc2ps.git | |
Log | |
Files | |
Refs | |
--- | |
parse.h (58108B) | |
--- | |
1 /* | |
2 * This file is part of abc2ps, | |
3 * Copyright (C) 1996,1997,1998 Michael Methfessel | |
4 * See file abc2ps.c for details. | |
5 */ | |
6 | |
7 /* subroutines connected with parsing the input file */ | |
8 | |
9 /* ----- sytax: print message for syntax errror -------- */ | |
10 void syntax (msg, q) | |
11 char msg[]; | |
12 char *q; | |
13 { | |
14 int i,n,len,m1,m2,pp,qq,maxcol=65; | |
15 | |
16 if (verbose<=2) printf ("\n"); | |
17 qq=q-p0+1; | |
18 if (qq<0) qq=0; | |
19 printf ("+++ %s in line %d.%d \n", msg, linenum, qq); | |
20 m1=0; | |
21 m2=len=strlen(p0); | |
22 n=q-p0; | |
23 if (m2>maxcol) { | |
24 if (n<maxcol) | |
25 m2=maxcol; | |
26 else { | |
27 m1=n-10; | |
28 m2=m1+maxcol; | |
29 if (m2>len) m2=len; | |
30 } | |
31 } | |
32 | |
33 printf ("%4d ", linenum); | |
34 pp=5; | |
35 if (m1>0) { printf ("..."); pp+=3; } | |
36 for (i=m1;i<m2;i++) printf ("%c", p0[i]); | |
37 if (m2<len) printf ("..."); | |
38 printf ("\n"); | |
39 | |
40 if (n>=0 && n<200) { | |
41 for (i=0;i<n+pp-m1;i++) printf(" "); | |
42 printf ("^\n"); | |
43 } | |
44 } | |
45 | |
46 /* ----- isnote: checks char for valid note symbol ----- */ | |
47 int isnote (c) | |
48 char c; | |
49 { | |
50 if (c == '\0') return 0; | |
51 if (strchr("CDEFGABcdefgab^=_",c)) return 1; | |
52 return 0; | |
53 } | |
54 | |
55 /* ----- zero_sym: init global zero SYMBOL struct ----- */ | |
56 void zero_sym () | |
57 { | |
58 int j; | |
59 zsym.type = 0; | |
60 zsym.npitch = 0; | |
61 zsym.word_st = 0; | |
62 zsym.word_end = 0; | |
63 zsym.slur_st = 0; | |
64 zsym.slur_end = 0; | |
65 zsym.len = 0; | |
66 zsym.fullmes = 0; | |
67 zsym.yadd = 0; | |
68 zsym.xs = 0; | |
69 zsym.ys = 0; | |
70 zsym.stem = 0; | |
71 zsym.eoln = 0; | |
72 zsym.ylo = 12; | |
73 zsym.yhi = 12; | |
74 zsym.u = 0; | |
75 zsym.v = 0; | |
76 zsym.w = 0; | |
77 zsym.t = 0; | |
78 zsym.q = 0; | |
79 zsym.invis = 0; | |
80 zsym.wl = 0; | |
81 zsym.wr = 0; | |
82 zsym.pr = 0; | |
83 zsym.pl = 0; | |
84 zsym.p_plet = 0; | |
85 zsym.q_plet = 0; | |
86 zsym.r_plet = 0; | |
87 zsym.gchy = 0; | |
88 zsym.gr.n = 0; | |
89 zsym.dc.n = 0; | |
90 zsym.dc.top = 0; | |
91 zsym.p = -1; | |
92 strcpy (zsym.text, ""); | |
93 for (j=0;j<MAXHD;j++) zsym.sl1[j]=zsym.sl2[j]=0; | |
94 | |
95 for (j=0;j<NWLINE;j++) zsym.wordp[j] = 0; | |
96 } | |
97 | |
98 /* ----- add_sym: returns index for new symbol at end of list ---- */ | |
99 int add_sym (type) | |
100 int type; | |
101 { | |
102 int k; | |
103 | |
104 k=voice[ivc].nsym; | |
105 if (k>=maxSyms) rxi("Too many symbols; increase maxSyms, now ",maxSyms… | |
106 voice[ivc].nsym++; | |
107 symv[ivc][k]=zsym; | |
108 symv[ivc][k].type = type; | |
109 return k; | |
110 | |
111 } | |
112 | |
113 /* ----- insert_sym: returns index for new symbol inserted at k --- */ | |
114 int insert_sym (type,k) | |
115 int type,k; | |
116 { | |
117 int i,n; | |
118 | |
119 n=voice[ivc].nsym; | |
120 if (n>=maxSyms) rxi("insert_sym: maxSyms exceeded: ",maxSyms); | |
121 for (i=n;i>k;i--) symv[ivc][i]=symv[ivc][i-1]; | |
122 n++; | |
123 symv[ivc][k]=zsym; | |
124 symv[ivc][k].type = type; | |
125 voice[ivc].nsym=n; | |
126 return k; | |
127 } | |
128 | |
129 /* ----- get_xref: get xref from string ----- */ | |
130 int get_xref (str) | |
131 char str[]; | |
132 { | |
133 | |
134 int a,ok; | |
135 char *q; | |
136 | |
137 if (strlen(str)==0) { | |
138 wng ("xref string is empty", ""); | |
139 return 0; | |
140 } | |
141 q=str; | |
142 ok=1; | |
143 while (*q != '\0') { | |
144 if (!isdig(*q)) ok=0; | |
145 q++; | |
146 } | |
147 if (!ok) { | |
148 wng ("xref string has invalid symbols: ", str); | |
149 return 0; | |
150 } | |
151 | |
152 sscanf (str, "%d", &a); | |
153 | |
154 return a; | |
155 } | |
156 | |
157 /* ----- set_meter: interpret meter string, store in struct ---- */ | |
158 void set_meter (str,meter) | |
159 char str[]; | |
160 struct METERSTR *meter; | |
161 { | |
162 | |
163 int m1,m2,m1a,m1b,m1c,d,l; | |
164 char *q; | |
165 int meter1,meter2,dlen,mflag,lflag; | |
166 char meter_top[31]; | |
167 | |
168 l=strlen(str); | |
169 if (l==0) { wng("Empty meter string", ""); return; } | |
170 if (str[0]=='C') { | |
171 if (str[1]=='|') { | |
172 meter1=4; | |
173 meter2=4; | |
174 dlen=EIGHTH; | |
175 mflag=2; | |
176 strcpy(meter_top,"C"); | |
177 } | |
178 else { | |
179 meter1=4; | |
180 meter2=4; | |
181 dlen=EIGHTH; | |
182 mflag=1; | |
183 strcpy(meter_top,"C"); | |
184 } | |
185 } | |
186 else { | |
187 m1=m2=m1a=m1b=m1c=0; | |
188 strcpy (meter_top, str); | |
189 q=strchr(meter_top,'/'); | |
190 if (!q) { | |
191 wng("Cannot identify meter, missing /: ", str); | |
192 m1=m2=1; | |
193 return; | |
194 } | |
195 *q='\0'; | |
196 if (strchr(meter_top,'+')) { | |
197 sscanf(str,"%d+%d+%d/", &m1a, &m1b, &m1c); | |
198 m1=m1a+m1b+m1c; | |
199 } | |
200 else { | |
201 sscanf(str,"%d %d %d/", &m1a, &m1b, &m1c); | |
202 m1=m1a; if (m1b>m1) m1=m1b; if (m1c>m1) m1=m1c; | |
203 if (m1>30) { /* handle things like 78/8 */ | |
204 m1a=m1/100; | |
205 m1c=m1-100*m1a; | |
206 m1b=m1c/10; | |
207 m1c=m1c-10*m1b; | |
208 m1=m1a; if (m1b>m1) m1=m1b; if (m1c>m1) m1=m1c; | |
209 } | |
210 } | |
211 | |
212 q++; | |
213 sscanf (q, "%d", &m2); | |
214 if (m1*m2 == 0) wng("Cannot identify meter: ", str); | |
215 d=BASE/m2; | |
216 if (d*m2 != BASE) wng("Meter not recognized: ", str); | |
217 meter1=m1; | |
218 meter2=m2; | |
219 dlen=EIGHTH; | |
220 if (4*meter1 < 3*meter2) dlen=SIXTEENTH; | |
221 mflag=0; | |
222 } | |
223 | |
224 if (verbose>=4) | |
225 printf ("Meter <%s> is %d over %d with default length 1/%d\n", | |
226 str, meter1, meter2, BASE/dlen); | |
227 | |
228 /* handle old-style change of default length */ | |
229 lflag=0; | |
230 if (str[l-1]=='s') { dlen=dlen*2; lflag=1; } | |
231 if (str[l-1]=='l') { dlen=dlen/2; lflag=-1; } | |
232 | |
233 /* store parsed data in struct */ | |
234 meter->meter1 = meter1; | |
235 meter->meter2 = meter2; | |
236 meter->mflag = mflag; | |
237 meter->dlen = dlen; | |
238 meter->lflag = lflag; | |
239 strcpy(meter->top, meter_top); | |
240 } | |
241 | |
242 | |
243 /* ----- set_dlen: set default length for parsed notes ---- */ | |
244 void set_dlen (str,meter) | |
245 char str[]; | |
246 struct METERSTR *meter; | |
247 { | |
248 int l1,l2,d,dlen; | |
249 | |
250 l1=0; | |
251 l2=1; | |
252 sscanf(str,"%d/%d ", &l1, &l2); | |
253 if (l1 == 0) return; /* empty string.. don't change default leng… | |
254 else { | |
255 d=BASE/l2; | |
256 if (d*l2 != BASE) { | |
257 wng("Length incompatible with BASE, using 1/8: ",str); | |
258 dlen=BASE/8; | |
259 } | |
260 else | |
261 dlen = d*l1; | |
262 } | |
263 if (verbose>=4) | |
264 printf ("Dlen <%s> sets default note length to %d/%d = 1/%d\n", | |
265 str, dlen, BASE, BASE/dlen); | |
266 | |
267 meter->dlen=dlen; | |
268 | |
269 } | |
270 | |
271 /* ----- set_keysig: interpret keysig string, store in struct ---- */ | |
272 /* This part was adapted from abc2mtex by Chris Walshaw */ | |
273 /* updated 03 Oct 1997 Wil Macaulay - support all modes */ | |
274 /* Returns 1 if key was actually specified, because then we want | |
275 to transpose. Returns zero if this is just a clef change. */ | |
276 int set_keysig(s,ks,init) | |
277 char s[]; | |
278 struct KEYSTR *ks; | |
279 int init; | |
280 { | |
281 int c,sf,j,ok; | |
282 char w[81]; | |
283 int ktype,add_pitch,root,root_acc; | |
284 | |
285 /* maybe initialize with key C (used for K field in header) */ | |
286 if (init) { | |
287 ks->sf = 0; | |
288 ks->ktype = TREBLE; | |
289 ks->add_pitch = 0; | |
290 ks->root = 2; | |
291 ks->root_acc = A_NT; | |
292 } | |
293 | |
294 /* check for "treble" "bass" "alto" with no other information */ | |
295 ktype=ks->ktype; | |
296 add_pitch=0; | |
297 if (!strcmp(s,"bass")) {ks->ktype=BASS; return 0; } | |
298 if (!strcmp(s,"treble")) {ks->ktype=TREBLE; return 0; } | |
299 if (!strcmp(s,"alto")) {ks->ktype=ALTO; return 0; } | |
300 | |
301 if (!strcmp(s,"bass+8")) {ks->ktype=BASS; ks->add_pitch=8; return … | |
302 if (!strcmp(s,"treble+8")) {ks->ktype=TREBLE; ks->add_pitch=8; return … | |
303 if (!strcmp(s,"alto+8")) {ks->ktype=ALTO; ks->add_pitch=8; return … | |
304 | |
305 if (!strcmp(s,"bass-8")) {ks->ktype=BASS; ks->add_pitch=-8; return… | |
306 if (!strcmp(s,"treble-8")) {ks->ktype=TREBLE; ks->add_pitch=-8; return… | |
307 if (!strcmp(s,"alto-8")) {ks->ktype=ALTO; ks->add_pitch=-8; return… | |
308 | |
309 c=0; | |
310 bagpipe=0; | |
311 switch (s[c]) { | |
312 case 'F': | |
313 sf = -1; root=5; | |
314 break; | |
315 case 'C': | |
316 sf = 0; root=2; | |
317 break; | |
318 case 'G': | |
319 sf = 1; root=6; | |
320 break; | |
321 case 'D': | |
322 sf = 2; root=3; | |
323 break; | |
324 case 'A': | |
325 sf = 3; root=0; | |
326 break; | |
327 case 'E': | |
328 sf = 4; root=4; | |
329 break; | |
330 case 'B': | |
331 sf = 5; root=1; | |
332 break; | |
333 case 'H': | |
334 bagpipe=1; | |
335 c++; | |
336 if (s[c] == 'P') { sf=0; root=2; } | |
337 else if (s[c] == 'p') { sf=2; root=3; } | |
338 else wng("unknown bagpipe-like key: ",s); | |
339 break; | |
340 default: | |
341 wng ("Using C because key not recognised: ", s); | |
342 sf = 0; root=2; | |
343 } | |
344 c++; | |
345 | |
346 root_acc=A_NT; | |
347 if (s[c] == '#') { | |
348 sf += 7; | |
349 c += 1; | |
350 root_acc=A_SH; | |
351 } else if (s[c] == 'b') { | |
352 sf -= 7; | |
353 c += 1; | |
354 root_acc=A_FT; | |
355 } | |
356 | |
357 /* loop over blank-delimited words: get the next token in lower case */ | |
358 for (;;) { | |
359 while (s[c] == ' ') c++; | |
360 if (s[c]=='\0') break; | |
361 | |
362 j=0; | |
363 while ((s[c]!=' ') && (s[c]!='\0')) { w[j]=tolower(s[c]); c++; j++; } | |
364 w[j]='\0'; | |
365 | |
366 /* now identify this word */ | |
367 | |
368 /* first check for mode specifier */ | |
369 if ((strncmp(w,"mix",3)) == 0) { | |
370 sf -= 1; | |
371 ok = 1; | |
372 /* dorian mode on the second note (D in C scale) */ | |
373 } else if ((strncmp(w,"dor",3)) == 0) { | |
374 sf -= 2; | |
375 ok = 1; | |
376 /* phrygian mode on the third note (E in C scale) */ | |
377 } else if ((strncmp(w,"phr",3)) == 0) { | |
378 sf -= 4; | |
379 ok = 1; | |
380 /* lydian mode on the fourth note (F in C scale) */ | |
381 } else if ((strncmp(w,"lyd",3)) == 0) { | |
382 sf += 1; | |
383 ok = 1; | |
384 /* locrian mode on the seventh note (B in C scale) */ | |
385 } else if ((strncmp(w,"loc",3)) == 0) { | |
386 sf -= 5; | |
387 ok = 1; | |
388 /* major and ionian are the same ks */ | |
389 } else if ((strncmp(w,"maj",3)) == 0) { | |
390 ok = 1; | |
391 } else if ((strncmp(w,"ion",3)) == 0) { | |
392 ok = 1; | |
393 /* aeolian, m, minor are the same ks - sixth note (A in C scale) */ | |
394 } else if ((strncmp(w,"aeo",3)) == 0) { | |
395 sf -= 3; | |
396 ok = 1; | |
397 } else if ((strncmp(w,"min",3)) == 0) { | |
398 sf -= 3; | |
399 ok = 1; | |
400 } else if ((strcmp(w,"m")) == 0) { | |
401 sf -= 3; | |
402 ok = 1; | |
403 } | |
404 | |
405 /* check for trailing "bass" "treble" "alto" */ | |
406 else if (!strcmp(w,"bass")) { | |
407 ktype=BASS; | |
408 } | |
409 else if (!strcmp(w,"treble")) { | |
410 ktype=TREBLE; | |
411 } | |
412 else if (!strcmp(w,"alto")) { | |
413 ktype=ALTO; | |
414 } | |
415 | |
416 /* check for "+8" or "-8" */ | |
417 else if (!strcmp(w,"+8")) { | |
418 add_pitch=7; | |
419 } | |
420 else if (!strcmp(w,"-8")) { | |
421 add_pitch=-7; | |
422 } | |
423 else wng("Unknown token in key specifier: ",w); | |
424 | |
425 } /* end of loop over blank-delimted words */ | |
426 | |
427 if (verbose>=4) printf ("Key <%s> gives sharpsflats %d, type %d\n", | |
428 s, sf, ktype); | |
429 | |
430 /* copy to struct */ | |
431 ks->sf = sf; | |
432 ks->ktype = ktype; | |
433 ks->add_pitch = add_pitch; | |
434 ks->root = root; | |
435 ks->root_acc = root_acc; | |
436 | |
437 return 1; | |
438 | |
439 } | |
440 | |
441 /* ----- get_halftones: figure out how by many halftones to transpose --… | |
442 /* In the transposing routines: pitches A..G are coded as with 0..7 */ | |
443 int get_halftones (key, transpose) | |
444 struct KEYSTR key; | |
445 char transpose[]; | |
446 { | |
447 int pit_old,pit_new,direction,stype,root_new,racc_new,nht; | |
448 int root_old, racc_old; | |
449 char *q; | |
450 /* pit_tab associates true pitches 0-11 with letters A-G */ | |
451 int pit_tab[] = {0,2,3,5,7,8,10}; | |
452 | |
453 if (strlen(transpose)==0) return 0; | |
454 root_old=key.root; | |
455 racc_old=key.root_acc; | |
456 | |
457 /* parse specification for target key */ | |
458 q=transpose; | |
459 direction=0; | |
460 | |
461 if (*q=='^') { | |
462 direction=1; q++; | |
463 } else if (*q=='_') { | |
464 direction=-1; q++; | |
465 } | |
466 stype=1; | |
467 if (strchr("ABCDEFG",*q)) { | |
468 root_new=*q-'A'; q++; stype=2; | |
469 } else if (strchr("abcdefg",*q)) { | |
470 root_new=*q-'a'; q++; stype=2; | |
471 } | |
472 | |
473 /* first case: offset was given directly as numeric argument */ | |
474 if (stype==1) { | |
475 sscanf(q,"%d", &nht); | |
476 if (direction<0) nht=-nht; | |
477 if (nht==0) { | |
478 if (direction<0) nht=-12; | |
479 if (direction>0) nht=+12; | |
480 } | |
481 return nht; | |
482 } | |
483 | |
484 /* second case: root of target key was specified explicitly */ | |
485 racc_new=0; | |
486 if (*q=='b') { | |
487 racc_new=A_FT; q++; | |
488 } else if (*q=='#') { | |
489 racc_new=A_SH; q++; | |
490 } else if (*q!='\0') | |
491 wng ("expecting accidental in transpose spec: ", transpose); | |
492 | |
493 /* get pitch as number from 0-11 for root of old key */ | |
494 pit_old=pit_tab[root_old]; | |
495 if (racc_old==A_FT) pit_old--; | |
496 if (racc_old==A_SH) pit_old++; | |
497 if (pit_old<0) pit_old+=12; | |
498 if (pit_old>11) pit_old-=12; | |
499 | |
500 /* get pitch as number from 0-11 for root of new key */ | |
501 pit_new=pit_tab[root_new]; | |
502 if (racc_new==A_FT) pit_new--; | |
503 if (racc_new==A_SH) pit_new++; | |
504 if (pit_new<0) pit_new+=12; | |
505 if (pit_new>11) pit_new-=12; | |
506 | |
507 /* number of halftones is difference */ | |
508 nht=pit_new-pit_old; | |
509 if (direction==0) { | |
510 if (nht>6) nht-=12; | |
511 if (nht<-5) nht+=12; | |
512 } | |
513 if (direction>0 && nht<=0) nht+=12; | |
514 if (direction<0 && nht>=0) nht-=12; | |
515 | |
516 return nht; | |
517 | |
518 } | |
519 | |
520 | |
521 | |
522 /* ----- shift_key: make new key by shifting nht halftones --- */ | |
523 void shift_key (sf_old,nht,sfnew,addt) | |
524 int sf_old,nht,*sfnew,*addt; | |
525 { | |
526 int sf_new,r_old,r_new,add_t, dh,dr; | |
527 int skey_tab[] = {2,6,3,0,4,1,5,2}; | |
528 int fkey_tab[] = {2,5,1,4,0,3,6,2}; | |
529 char root_tab[]={'A','B','C','D','E','F','G'}; | |
530 | |
531 /* get sf_new by adding 7 for each halftone, then reduce mod 12 */ | |
532 sf_new=sf_old+nht*7; | |
533 sf_new=(sf_new+240)%12; | |
534 if (sf_new>=6) sf_new=sf_new-12; | |
535 | |
536 /* get old and new root in ionian mode, shift is difference */ | |
537 r_old=2; | |
538 if (sf_old>0) r_old=skey_tab[sf_old]; | |
539 if (sf_old<0) r_old=fkey_tab[-sf_old]; | |
540 r_new=2; | |
541 if (sf_new>0) r_new=skey_tab[sf_new]; | |
542 if (sf_new<0) r_new=fkey_tab[-sf_new]; | |
543 add_t=r_new-r_old; | |
544 | |
545 /* fix up add_t to get same "decade" as nht */ | |
546 dh=(nht+120)/12; dh=dh-10; | |
547 dr=(add_t+70)/7; dr=dr-10; | |
548 add_t=add_t+7*(dh-dr); | |
549 | |
550 if (verbose>=8) | |
551 printf ("shift_key: sf_old=%d new %d root: old %c new %c shift by… | |
552 sf_old, sf_new, root_tab[r_old], root_tab[r_new], add_t); | |
553 | |
554 *sfnew=sf_new; | |
555 *addt=add_t; | |
556 | |
557 } | |
558 | |
559 | |
560 /* ----- set_transtab: setup for transposition by nht halftones --- */ | |
561 void set_transtab (nht,key) | |
562 int nht; | |
563 struct KEYSTR *key; | |
564 { | |
565 int a,b,sf_old,sf_new,add_t,i,j,acc_old,acc_new,root_old,root_acc; | |
566 /* for each note A..G, these tables tell how many sharps (resp. flats) | |
567 the keysig must have to get the accidental on this note. Phew. */ | |
568 int sh_tab[] = {5,7,2,4,6,1,3}; | |
569 int fl_tab[] = {3,1,6,4,2,7,5}; | |
570 /* tables for pretty printout only */ | |
571 char root_tab[]={'A','B','C','D','E','F','G'}; | |
572 char acc_tab[][3] ={"bb","b "," ","# ","x "}; | |
573 char c1[6],c2[6],c3[6]; | |
574 | |
575 /* nop if no transposition is wanted */ | |
576 if (nht==0) { | |
577 key->add_transp=0; | |
578 for (i=0;i<7;i++) key->add_acc[i]=0; | |
579 return; | |
580 } | |
581 | |
582 /* get new sharps_flats and shift of numeric pitch; copy to key */ | |
583 sf_old = key->sf; | |
584 root_old = key->root; | |
585 root_acc = key->root_acc; | |
586 shift_key (sf_old, nht, &sf_new, &add_t); | |
587 key->sf = sf_new; | |
588 key->add_transp = add_t; | |
589 | |
590 /* set up table for conversion of accidentals */ | |
591 for (i=0;i<7;i++) { | |
592 j=i+add_t; | |
593 j=(j+70)%7; | |
594 acc_old=0; | |
595 if ( sf_old >= sh_tab[i]) acc_old=1; | |
596 if (-sf_old >= fl_tab[i]) acc_old=-1; | |
597 acc_new=0; | |
598 if ( sf_new >= sh_tab[j]) acc_new=1; | |
599 if (-sf_new >= fl_tab[j]) acc_new=-1; | |
600 key->add_acc[i]=acc_new-acc_old; | |
601 } | |
602 | |
603 /* printout keysig change */ | |
604 if (verbose>=3) { | |
605 i=root_old; | |
606 j=i+add_t; | |
607 j=(j+70)%7; | |
608 acc_old=0; | |
609 if ( sf_old >= sh_tab[i]) acc_old=1; | |
610 if (-sf_old >= fl_tab[i]) acc_old=-1; | |
611 acc_new=0; | |
612 if ( sf_new >= sh_tab[j]) acc_new=1; | |
613 if (-sf_new >= fl_tab[j]) acc_new=-1; | |
614 strcpy(c3,"s"); if (nht==1 || nht==-1) strcpy(c3,""); | |
615 strcpy(c1,""); strcpy(c2,""); | |
616 if (acc_old==-1) strcpy(c1,"b"); if (acc_old==1) strcpy(c1,"#"); | |
617 if (acc_new==-1) strcpy(c2,"b"); if (acc_new==1) strcpy(c2,"#"); | |
618 printf ("Transpose root from %c%s to %c%s (shift by %d halftone%s)\n… | |
619 root_tab[i],c1,root_tab[j],c2,nht,c3); | |
620 } | |
621 | |
622 /* printout full table of transformations */ | |
623 if (verbose>=4) { | |
624 printf ("old & new keysig conversions\n"); | |
625 for (i=0;i<7;i++) { | |
626 j=i+add_t; | |
627 j=(j+70)%7; | |
628 acc_old=0; | |
629 if ( sf_old >= sh_tab[i]) acc_old=1; | |
630 if (-sf_old >= fl_tab[i]) acc_old=-1; | |
631 acc_new=0; | |
632 if ( sf_new >= sh_tab[j]) acc_new=1; | |
633 if (-sf_new >= fl_tab[j]) acc_new=-1; | |
634 printf("%c%s-> %c%s ", root_tab[i],acc_tab[acc_old+2], | |
635 root_tab[j],acc_tab[acc_new+2]); | |
636 for (a=-1;a<=1;a++) { | |
637 b=a+key->add_acc[i]; | |
638 printf ("%c%s-> %c%s ", root_tab[i],acc_tab[a+2], | |
639 root_tab[j],acc_tab[b+2]); | |
640 } | |
641 printf ("\n"); | |
642 } | |
643 } | |
644 | |
645 } | |
646 | |
647 /* ----- do_transpose: transpose numeric pitch and accidental --- */ | |
648 void do_transpose (key,pitch,acc) | |
649 struct KEYSTR key; | |
650 int *pitch, *acc; | |
651 { | |
652 int pitch_old,pitch_new,sf_old,sf_new,acc_old,acc_new,i,j; | |
653 | |
654 pitch_old = *pitch; | |
655 acc_old = *acc; | |
656 pitch_new=pitch_old+key.add_transp; | |
657 i=(pitch_old+70)%7; | |
658 j=(pitch_new+70)%7; | |
659 | |
660 if (acc_old) { | |
661 if (acc_old==A_DF) sf_old=-2; | |
662 if (acc_old==A_FT) sf_old=-1; | |
663 if (acc_old==A_NT) sf_old=0 ; | |
664 if (acc_old==A_SH) sf_old=1; | |
665 if (acc_old==A_DS) sf_old=2; | |
666 sf_new=sf_old+key.add_acc[i]; | |
667 if (sf_new==-2) acc_new=A_DF; | |
668 if (sf_new==-1) acc_new=A_FT; | |
669 if (sf_new== 0) acc_new=A_NT; | |
670 if (sf_new== 1) acc_new=A_SH; | |
671 if (sf_new== 2) acc_new=A_DS; | |
672 } | |
673 else { | |
674 acc_new=0; | |
675 } | |
676 *pitch = pitch_new; | |
677 *acc = acc_new; | |
678 } | |
679 | |
680 | |
681 /* ----- gch_transpose: transpose guitar chord string in gch --- */ | |
682 void gch_transpose (key) | |
683 struct KEYSTR key; | |
684 { | |
685 char *q,*r; | |
686 char str[201]; | |
687 int root_old,root_new,sf_old,sf_new,ok; | |
688 char root_tab[]={'A','B','C','D','E','F','G'}; | |
689 char root_tub[]={'a','b','c','d','e','f','g'}; | |
690 | |
691 if (halftones==0) return; | |
692 | |
693 /* try to avoid some common abuses of gchord string */ | |
694 if (strstr(gch,"capo")) return; | |
695 if (strstr(gch,"Capo")) return; | |
696 if (strstr(gch,"Fine")) return; | |
697 if (strstr(gch,"fine")) return; | |
698 | |
699 q=gch; | |
700 r=str; | |
701 | |
702 for (;;) { | |
703 while (*q==' ' || *q=='(') { *r=*q; q++; r++; } | |
704 if (*q=='\0') break; | |
705 ok=0; | |
706 if (strchr("ABCDEFG",*q)) { | |
707 root_old=*q-'A'; q++; ok=1; | |
708 } else if (strchr("abcdefg",*q)) { | |
709 root_old=*q-'a'; q++; ok=2; | |
710 } | |
711 | |
712 if (ok) { | |
713 sf_old=0; | |
714 if (*q=='b') { sf_old=-1; q++; } | |
715 if (*q=='#') { sf_old= 1; q++; } | |
716 root_new=root_old+key.add_transp; | |
717 root_new=(root_new+28)%7; | |
718 sf_new=sf_old+key.add_acc[root_old]; | |
719 if (ok==1) { *r=root_tab[root_new]; r++; } | |
720 if (ok==2) { *r=root_tub[root_new]; r++; } | |
721 if (sf_new==-1) { *r='b'; r++; } | |
722 if (sf_new== 1) { *r='#'; r++; } | |
723 } | |
724 | |
725 while (*q!=' ' && *q!='/' && *q!='\0') {*r=*q; q++; r++; } | |
726 if (*q=='/') {*r=*q; q++; r++; } | |
727 | |
728 } | |
729 | |
730 *r='\0'; | |
731 /*| printf("tr_ch: <%s> <%s>\n", gch, str); |*/ | |
732 | |
733 strcpy (gch,str); | |
734 | |
735 } | |
736 | |
737 | |
738 /* ----- init_parse_params: initialize variables for parsing --- */ | |
739 void init_parse_params () | |
740 { | |
741 int i; | |
742 | |
743 slur=0; | |
744 voice[0].end_slur=0; | |
745 nwpool=nwline=0; | |
746 ntinext=0; | |
747 | |
748 /* for continuation after output: reset nsym, switch to first voice */ | |
749 for (i=0;i<nvoice;i++) { | |
750 voice[i].nsym=0; | |
751 voice[i].insert_btype=0; | |
752 voice[i].end_slur=0; | |
753 } | |
754 | |
755 ivc=0; | |
756 | |
757 word=0; | |
758 carryover=0; | |
759 last_note=last_real_note=-1; | |
760 pplet=qplet=rplet=0; | |
761 num_ending=0; | |
762 mes1=mes2=0; | |
763 strcpy (gch, ""); | |
764 | |
765 } | |
766 | |
767 /* ----- add_text ---- */ | |
768 void add_text (str,type) | |
769 char str[]; | |
770 int type; | |
771 { | |
772 if (do_mode!=DO_OUTPUT) return; | |
773 if (ntext>=NTEXT) { | |
774 wng ("No more room for text line <%s>", str); | |
775 return; | |
776 } | |
777 strcpy (text[ntext], str); | |
778 text_type[ntext]=type; | |
779 ntext++; | |
780 } | |
781 | |
782 /* ----- reset_info ---- */ | |
783 void reset_info (inf) | |
784 struct ISTRUCT *inf; | |
785 { | |
786 | |
787 /* reset all info fields except info.xref */ | |
788 | |
789 strcpy(inf->parts, ""); | |
790 strcpy(inf->area, ""); | |
791 strcpy(inf->book, ""); | |
792 inf->ncomp=0; | |
793 strcpy(inf->disc, ""); | |
794 strcpy(inf->group, ""); | |
795 strcpy(inf->hist, ""); | |
796 strcpy(inf->info, ""); | |
797 strcpy(inf->key, "C"); | |
798 strcpy(inf->meter, "4/4"); | |
799 strcpy(inf->notes, ""); | |
800 strcpy(inf->orig, ""); | |
801 strcpy(inf->rhyth, ""); | |
802 strcpy(inf->src, ""); | |
803 /* strcpy(inf->title, "(untitled)"); */ | |
804 strcpy(inf->title, ""); | |
805 strcpy(inf->title2, ""); | |
806 strcpy(inf->title3, ""); | |
807 strcpy(inf->trans, ""); | |
808 strcpy(inf->tempo, ""); | |
809 } | |
810 | |
811 /* ----- get_default_info: set info to default, except xref field --- */ | |
812 void get_default_info () | |
813 { | |
814 char savestr[STRL]; | |
815 | |
816 strcpy (savestr, info.xref); | |
817 info=default_info; | |
818 strcpy (info.xref, savestr); | |
819 | |
820 } | |
821 | |
822 /* ----- is_info_field: identify any type of info field ---- */ | |
823 int is_info_field (str) | |
824 char str[]; | |
825 { | |
826 if (strlen(str)<2) return 0; | |
827 if (str[1]!=':') return 0; | |
828 if (str[0]=='|') return 0; /* |: at start of music line */ | |
829 return 1; | |
830 } | |
831 | |
832 /* ----- is_end_line: identify eof ----- */ | |
833 int is_end_line (str) | |
834 char str[]; | |
835 { | |
836 if (strlen(str)<3) return 0; | |
837 if (str[0]=='E' && str[1]=='N' && str[2]=='D') return 1; | |
838 return 0; | |
839 } | |
840 | |
841 /* ----- is_pseudocomment ----- */ | |
842 int is_pseudocomment (str) | |
843 char str[]; | |
844 { | |
845 if (strlen(str)<2) return 0; | |
846 if ((str[0]=='%')&&(str[1]=='%')) return 1; | |
847 return 0; | |
848 } | |
849 | |
850 /* ----- is_comment ----- */ | |
851 int is_comment (str) | |
852 char str[]; | |
853 { | |
854 if (strlen(str)<1) return 0; | |
855 if (str[0]=='%') return 1; | |
856 if (str[0]=='\\') return 1; | |
857 return 0; | |
858 } | |
859 | |
860 | |
861 /* ----- trim_title: move trailing "The" to front ------------ */ | |
862 void trim_title (s,s0) | |
863 char s[],s0[]; | |
864 { | |
865 char *q; | |
866 char rest[81],str[301]; | |
867 int done; | |
868 | |
869 strcpy (str, s0); | |
870 done=0; | |
871 | |
872 if ((q=strchr(str,','))) { | |
873 if (*q != '\0') { | |
874 strip (rest,q+1); | |
875 if (!strcmp(rest,"The")) { | |
876 strcpy (s, rest); | |
877 *q = '\0'; | |
878 strcat (s, " "); | |
879 strcat (s, str); | |
880 done=1; | |
881 } | |
882 } | |
883 } | |
884 | |
885 if (!done) strcpy (s,s0); | |
886 | |
887 } | |
888 | |
889 | |
890 /* ----- find_voice ----- */ | |
891 int find_voice (vid,new) | |
892 char vid[]; | |
893 int *new; | |
894 { | |
895 int i; | |
896 | |
897 for (i=0;i<nvoice;i++) | |
898 if (!strcmp(vid,voice[i].id)) { | |
899 *new=0; | |
900 return i; | |
901 } | |
902 | |
903 i=nvoice; | |
904 if (i>=maxVc) | |
905 rxi("Too many voices; use -maxv to increase limit, now ",maxVc); | |
906 | |
907 strcpy(voice[i].id, vid); | |
908 strcpy(voice[i].name, ""); | |
909 strcpy(voice[i].sname, ""); | |
910 voice[i].stems = 0; | |
911 voice[i].staves = 0; | |
912 voice[i].brace = 0; | |
913 voice[i].bracket = 0; | |
914 voice[i].do_gch = 1; | |
915 voice[i].select = 1; | |
916 voice[i].sep=0.0; | |
917 voice[i].meter = default_meter; | |
918 voice[i].key = default_key; | |
919 voice[i].nsym = 0; | |
920 nvoice++; | |
921 if (verbose>5) | |
922 printf ("Make new voice %d with id \"%s\"\n", i,voice[i].id); | |
923 *new=1; | |
924 return i; | |
925 | |
926 } | |
927 | |
928 /* ----- switch_voice: read spec for a voice, return voice number ----- … | |
929 int switch_voice (str) | |
930 char str[]; | |
931 { | |
932 int j,np,new,ap; | |
933 char *r,*q; | |
934 char t1[201],t2[201]; | |
935 | |
936 if (!do_this_tune) return 0; | |
937 | |
938 j=-1; | |
939 | |
940 /* start loop over vioce options: parse t1=t2 */ | |
941 r=str; | |
942 np=0; | |
943 for (;;) { | |
944 while (*r == ' ') r++; | |
945 if (*r=='\0') break; | |
946 strcpy(t1,""); | |
947 strcpy(t2,""); | |
948 q=t1; | |
949 while (*r!=' ' && *r!='\0' && *r!='=') { *q=*r; r++; q++; } | |
950 *q='\0'; | |
951 if (*r=='=') { | |
952 r++; | |
953 q=t2; | |
954 if (*r=='"') { | |
955 r++; | |
956 while (*r!='"' && *r!='\0') { *q=*r; r++; q++; } | |
957 if (*r=='"') r++; | |
958 } | |
959 else { | |
960 while (*r!=' ' && *r!='\0') { *q=*r; r++; q++; } | |
961 } | |
962 *q='\0'; | |
963 } | |
964 np++; | |
965 | |
966 /* interpret the parsed option. First case is identifier. */ | |
967 if (np==1) j=find_voice (t1,&new); | |
968 | |
969 else { /* interpret option */ | |
970 if (j<0) bug("j invalid in switch_voice",1); | |
971 if (!strcmp(t1,"name") || !strcmp(t1,"nm")) | |
972 strcpy(voice[j].name, t2); | |
973 | |
974 else if (!strcmp(t1,"sname") || !strcmp(t1,"snm")) | |
975 strcpy(voice[j].sname, t2); | |
976 | |
977 else if (!strcmp(t1,"staves") || !strcmp(t1,"stv")) | |
978 voice[j].staves = atoi(t2); | |
979 | |
980 else if (!strcmp(t1,"brace") || !strcmp(t1,"brc")) | |
981 voice[j].brace = atoi(t2); | |
982 | |
983 else if (!strcmp(t1,"bracket") || !strcmp(t1,"brk")) | |
984 voice[j].bracket = atoi(t2); | |
985 | |
986 else if (!strcmp(t1,"gchords") || !strcmp(t1,"gch")) | |
987 g_logv (str,t2,&voice[j].do_gch); | |
988 | |
989 /* for sspace: add 2000 as flag if not incremental */ | |
990 else if (!strcmp(t1,"space") || !strcmp(t1,"spc")) { | |
991 g_unum (str,t2,&voice[j].sep); | |
992 if (t2[0]!='+' && t2[0]!='-') voice[j].sep += 2000.0; | |
993 } | |
994 | |
995 else if (!strcmp(t1,"clef") || !strcmp(t1,"cl")) { | |
996 ap=0; | |
997 if (!strcmp(t2,"treble")) voice[j].key.ktype=TREBLE; | |
998 else if (!strcmp(t2,"treble+8")) {voice[j].key.ktype=TREBLE; ap… | |
999 else if (!strcmp(t2,"treble-8")) {voice[j].key.ktype=TREBLE; ap… | |
1000 else if (!strcmp(t2,"treble+16")) {voice[j].key.ktype=TREBLE; ap… | |
1001 else if (!strcmp(t2,"treble-16")) {voice[j].key.ktype=TREBLE; ap… | |
1002 else if (!strcmp(t2,"bass")) voice[j].key.ktype=BASS; | |
1003 else if (!strcmp(t2,"bass+8")) {voice[j].key.ktype=BASS; ap=+… | |
1004 else if (!strcmp(t2,"bass-8")) {voice[j].key.ktype=BASS; ap=-… | |
1005 else if (!strcmp(t2,"bass+16")) {voice[j].key.ktype=BASS; ap=+… | |
1006 else if (!strcmp(t2,"bass-16")) {voice[j].key.ktype=BASS; ap=-… | |
1007 else if (!strcmp(t2,"alto")) voice[j].key.ktype=ALTO; | |
1008 else if (!strcmp(t2,"alto+8")) {voice[j].key.ktype=ALTO; ap=+… | |
1009 else if (!strcmp(t2,"alto-8")) {voice[j].key.ktype=ALTO; ap=-… | |
1010 else if (!strcmp(t2,"alto+16")) {voice[j].key.ktype=ALTO; ap=+… | |
1011 else if (!strcmp(t2,"alto-16")) {voice[j].key.ktype=ALTO; ap=-… | |
1012 else wng("Unknown clef in voice spec: ",t2); | |
1013 voice[j].key.add_pitch=ap; | |
1014 } | |
1015 else if (!strcmp(t1,"stems") || !strcmp(t1,"stm")) { | |
1016 if (!strcmp(t2,"up")) voice[j].stems=1; | |
1017 else if (!strcmp(t2,"down")) voice[j].stems=-1; | |
1018 else if (!strcmp(t2,"free")) voice[j].stems=0; | |
1019 else wng("Unknown stem setting in voice spec: ",t2); | |
1020 } | |
1021 else wng("Unknown option in voice spec: ",t1); | |
1022 } | |
1023 | |
1024 } | |
1025 | |
1026 /* if new voice was initialized, save settings im meter0, key0 */ | |
1027 if (new) { | |
1028 voice[j].meter0 = voice[j].meter; | |
1029 voice[j].key0 = voice[j].key; | |
1030 } | |
1031 | |
1032 if (verbose>7) | |
1033 printf ("Switch to voice %d <%s> <%s> <%s> clef=%d\n", | |
1034 j,voice[j].id,voice[j].name,voice[j].sname, | |
1035 voice[j].key.ktype); | |
1036 | |
1037 nsym0=voice[j].nsym; /* set nsym0 to decide about eoln later.. ugly */ | |
1038 return j; | |
1039 | |
1040 } | |
1041 | |
1042 | |
1043 /* ----- info_field: identify info line, store in proper place ---- */ | |
1044 /* switch within_block: either goes to default_info or info. | |
1045 Only xref ALWAYS goes to info. */ | |
1046 int info_field (str) | |
1047 char str[]; | |
1048 { | |
1049 char t[STRL]; | |
1050 struct ISTRUCT *inf; | |
1051 int i; | |
1052 | |
1053 for (i=0;i<strlen(str);i++) if (str[i]=='%') str[i]='\0'; | |
1054 | |
1055 if (within_block) { | |
1056 inf=&info; | |
1057 } | |
1058 else { | |
1059 inf=&default_info; | |
1060 } | |
1061 | |
1062 if (strlen(str)<2) return 0; | |
1063 if (str[1]!=':') return 0; | |
1064 if (str[0]=='|') return 0; /* |: at start of music line */ | |
1065 | |
1066 if (str[0]=='X') { | |
1067 strip (info.xref, &str[2]); | |
1068 xrefnum=get_xref(info.xref); | |
1069 return XREF; | |
1070 } | |
1071 | |
1072 else if (str[0]=='A') strip (inf->area, &str[2]); | |
1073 else if (str[0]=='B') strip (inf->book, &str[2]); | |
1074 else if (str[0]=='C') { | |
1075 if (inf->ncomp>=NCOMP) | |
1076 wng("Too many composer lines",""); | |
1077 else { | |
1078 strip (inf->comp[inf->ncomp],&str[2]); | |
1079 inf->ncomp++; | |
1080 } | |
1081 } | |
1082 else if (str[0]=='D') { | |
1083 strip (inf->disc, &str[2]); | |
1084 add_text (&str[2], TEXT_D); | |
1085 } | |
1086 | |
1087 else if (str[0]=='G') strip (inf->group, &str[2]); | |
1088 else if (str[0]=='H') { | |
1089 strip (inf->hist, &str[2]); | |
1090 add_text (&str[2], TEXT_H); | |
1091 return HISTORY; | |
1092 } | |
1093 else if (str[0]=='W') { | |
1094 add_text (&str[2], TEXT_W); | |
1095 return WORDS; | |
1096 } | |
1097 else if (str[0]=='I') strip (inf->info, &str[2]); | |
1098 else if (str[0]=='K') { | |
1099 strip (inf->key, &str[2]); | |
1100 return KEY; | |
1101 } | |
1102 else if (str[0]=='L') { | |
1103 strip (inf->len, &str[2]); | |
1104 return DLEN; | |
1105 } | |
1106 else if (str[0]=='M') { | |
1107 strip (inf->meter, &str[2]); | |
1108 return METER; | |
1109 } | |
1110 else if (str[0]=='N') { | |
1111 strip (inf->notes, &str[2]); | |
1112 add_text (&str[2], TEXT_N); | |
1113 } | |
1114 else if (str[0]=='O') strip (inf->orig, &str[2]); | |
1115 else if (str[0]=='R') strip (inf->rhyth, &str[2]); | |
1116 else if (str[0]=='P') { | |
1117 strip (inf->parts, &str[2]); | |
1118 return PARTS; | |
1119 } | |
1120 else if (str[0]=='S') strip (inf->src, &str[2]); | |
1121 else if (str[0]=='T') { | |
1122 strip (t, &str[2]); | |
1123 numtitle++; | |
1124 if (numtitle>3) numtitle=3; | |
1125 if (numtitle==1) trim_title (inf->title, t); | |
1126 else if (numtitle==2) trim_title (inf->title2, t); | |
1127 else if (numtitle==3) trim_title (inf->title3, t); | |
1128 return TITLE; | |
1129 } | |
1130 else if (str[0]=='V') { | |
1131 strip (lvoiceid, &str[2]); | |
1132 return VOICE; | |
1133 } | |
1134 else if (str[0]=='Z') { | |
1135 strip (inf->trans, &str[2]); | |
1136 add_text (&str[2], TEXT_Z); | |
1137 } | |
1138 else if (str[0]=='Q') { | |
1139 strip (inf->tempo, &str[2]); | |
1140 return TEMPO; | |
1141 } | |
1142 | |
1143 else if (str[0]=='E') ; | |
1144 | |
1145 else { | |
1146 return 0; | |
1147 } | |
1148 | |
1149 return INFO; | |
1150 } | |
1151 | |
1152 /* ----- append_meter: add meter to list of symbols -------- */ | |
1153 void append_meter (meter) | |
1154 struct METERSTR meter; | |
1155 { | |
1156 int kk; | |
1157 | |
1158 kk=add_sym(TIMESIG); | |
1159 symv[ivc][kk]=zsym; | |
1160 symv[ivc][kk].type = TIMESIG; | |
1161 symv[ivc][kk].u = meter.meter1; | |
1162 symv[ivc][kk].v = meter.meter2; | |
1163 symv[ivc][kk].w = meter.mflag; | |
1164 strcpy(symv[ivc][kk].text,meter.top); | |
1165 | |
1166 } | |
1167 | |
1168 /* ----- append_key_change: append change of key to sym list ------ */ | |
1169 void append_key_change(oldkey,newkey) | |
1170 struct KEYSTR oldkey,newkey; | |
1171 { | |
1172 int n1,n2,t1,t2,kk; | |
1173 | |
1174 n1=oldkey.sf; | |
1175 t1=A_SH; | |
1176 if (n1<0) { n1=-n1; t1=A_FT; } | |
1177 n2=newkey.sf; | |
1178 t2=A_SH; | |
1179 | |
1180 if (newkey.ktype != oldkey.ktype) { /* clef change */ | |
1181 kk=add_sym(CLEF); | |
1182 symv[ivc][kk].u=newkey.ktype; | |
1183 symv[ivc][kk].v=1; | |
1184 } | |
1185 | |
1186 if (n2<0) { n2=-n2; t2=A_FT; } | |
1187 if (t1==t2) { /* here if old and new have same type */ | |
1188 if (n2>n1) { /* more new symbols ..*/ | |
1189 kk=add_sym(KEYSIG); /* draw all of them */ | |
1190 symv[ivc][kk].u=1; | |
1191 symv[ivc][kk].v=n2; | |
1192 symv[ivc][kk].w=100; | |
1193 symv[ivc][kk].t=t1; | |
1194 } | |
1195 else if (n2<n1) { /* less new symbols .. */ | |
1196 kk=add_sym(KEYSIG); /* draw all new symbols and neutrals … | |
1197 symv[ivc][kk].u=1; | |
1198 symv[ivc][kk].v=n1; | |
1199 symv[ivc][kk].w=n2+1; | |
1200 symv[ivc][kk].t=t2; | |
1201 } | |
1202 else return; | |
1203 } | |
1204 else { /* here for change s->f or f->s */ | |
1205 kk=add_sym(KEYSIG); /* neutralize all old symbols */ | |
1206 symv[ivc][kk].u=1; | |
1207 symv[ivc][kk].v=n1; | |
1208 symv[ivc][kk].w=1; | |
1209 symv[ivc][kk].t=t1; | |
1210 kk=add_sym(KEYSIG); /* add all new symbols */ | |
1211 symv[ivc][kk].u=1; | |
1212 symv[ivc][kk].v=n2; | |
1213 symv[ivc][kk].w=100; | |
1214 symv[ivc][kk].t=t2; | |
1215 } | |
1216 | |
1217 } | |
1218 | |
1219 | |
1220 | |
1221 /* ----- numeric_pitch ------ */ | |
1222 /* adapted from abc2mtex by Chris Walshaw */ | |
1223 int numeric_pitch(note) | |
1224 char note; | |
1225 { | |
1226 | |
1227 if (note=='z') | |
1228 return 14; | |
1229 if (note >= 'C' && note <= 'G') | |
1230 return(note-'C'+16+voice[ivc].key.add_pitch); | |
1231 else if (note >= 'A' && note <= 'B') | |
1232 return(note-'A'+21+voice[ivc].key.add_pitch); | |
1233 else if (note >= 'c' && note <= 'g') | |
1234 return(note-'c'+23+voice[ivc].key.add_pitch); | |
1235 else if (note >= 'a' && note <= 'b') | |
1236 return(note-'a'+28+voice[ivc].key.add_pitch); | |
1237 printf ("numeric_pitch: cannot identify <%c>\n", note); | |
1238 return(0); | |
1239 } | |
1240 | |
1241 /* ----- symbolic_pitch: translate numeric pitch back to symbol ------ */ | |
1242 int symbolic_pitch(pit,str) | |
1243 int pit; | |
1244 char str[]; | |
1245 { | |
1246 int p,r,s; | |
1247 char ltab1[7] = {'C','D','E','F','G','A','B'}; | |
1248 char ltab2[7] = {'c','d','e','f','g','a','b'}; | |
1249 | |
1250 p=pit-16; | |
1251 r=(p+700)%7; | |
1252 s=(p-r)/7; | |
1253 | |
1254 if (p<7) { | |
1255 sprintf (str,"%c,,,,,",ltab1[r]); | |
1256 str[1-s]='\0'; | |
1257 } | |
1258 else { | |
1259 sprintf (str,"%c'''''",ltab2[r]); | |
1260 str[s]='\0'; | |
1261 } | |
1262 } | |
1263 | |
1264 /* ----- handle_inside_field: act on info field inside body of tune --- … | |
1265 void handle_inside_field(type) | |
1266 int type; | |
1267 { | |
1268 struct KEYSTR oldkey; | |
1269 int rc; | |
1270 | |
1271 if (type==METER) { | |
1272 if (nvoice==0) ivc=switch_voice (DEFVOICE); | |
1273 set_meter (info.meter,&voice[ivc].meter); | |
1274 append_meter (voice[ivc].meter); | |
1275 } | |
1276 | |
1277 else if (type==DLEN) { | |
1278 if (nvoice==0) ivc=switch_voice (DEFVOICE); | |
1279 set_dlen (info.len, &voice[ivc].meter); | |
1280 } | |
1281 | |
1282 else if (type==KEY) { | |
1283 if (nvoice==0) ivc=switch_voice (DEFVOICE); | |
1284 oldkey=voice[ivc].key; | |
1285 rc=set_keysig(info.key,&voice[ivc].key,0); | |
1286 if (rc) set_transtab (halftones,&voice[ivc].key); | |
1287 append_key_change(oldkey,voice[ivc].key); | |
1288 } | |
1289 | |
1290 else if (type==VOICE) { | |
1291 ivc=switch_voice (lvoiceid); | |
1292 } | |
1293 | |
1294 } | |
1295 | |
1296 | |
1297 | |
1298 /* ----- parse_uint: parse for unsigned integer ----- */ | |
1299 int parse_uint () | |
1300 { | |
1301 int number,ndig; | |
1302 char num[21]; | |
1303 | |
1304 if (!isdig(*p)) return 0; | |
1305 ndig=0; | |
1306 while (isdig(*p)) { | |
1307 num[ndig]=*p; | |
1308 ndig++; | |
1309 num[ndig]=0; | |
1310 p++; | |
1311 } | |
1312 sscanf (num, "%d", &number); | |
1313 if (db>3) printf (" parsed unsigned int %d\n", number); | |
1314 return number; | |
1315 | |
1316 } | |
1317 | |
1318 /* ----- parse_bar: parse for some kind of bar ---- */ | |
1319 int parse_bar () | |
1320 { | |
1321 int k; | |
1322 | |
1323 parse_gchord (); | |
1324 | |
1325 /* special cases: [1 or [2 without a preceeding bar, [| */ | |
1326 if (*p=='[') { | |
1327 if ((*(p+1)=='1') || (*(p+1)=='2')) { | |
1328 k=add_sym (BAR); | |
1329 symv[ivc][k].u=B_INVIS; | |
1330 symv[ivc][k].v=1; | |
1331 if (*(p+1)=='2') symv[ivc][k].v=2; | |
1332 p=p+2; | |
1333 return 1; | |
1334 } | |
1335 } | |
1336 | |
1337 /* identify valid standard bar types */ | |
1338 if (*p == '|') { | |
1339 p++; | |
1340 if (*p == '|') { | |
1341 k=add_sym (BAR); | |
1342 symv[ivc][k].u=B_DBL; | |
1343 p++; | |
1344 } | |
1345 else if (*p == ':') { | |
1346 k=add_sym(BAR); | |
1347 symv[ivc][k].u=B_LREP; | |
1348 p++; | |
1349 } | |
1350 else if (*p==']') { /* code |] for fat end bar */ | |
1351 k=add_sym(BAR); | |
1352 symv[ivc][k].u=B_FAT2; | |
1353 p=p+1; | |
1354 } | |
1355 else { | |
1356 k=add_sym(BAR); | |
1357 symv[ivc][k].u=B_SNGL; | |
1358 } | |
1359 } | |
1360 else if (*p == ':') { | |
1361 p++; | |
1362 if (*p == '|') { | |
1363 k=add_sym(BAR); | |
1364 symv[ivc][k].u=B_RREP; | |
1365 p++; | |
1366 } | |
1367 else if (*p == ':') { | |
1368 k=add_sym(BAR); | |
1369 symv[ivc][k].u=B_DREP; | |
1370 p++; } | |
1371 else { | |
1372 syntax ("Syntax error parsing bar", p-1); | |
1373 return 0; | |
1374 } | |
1375 } | |
1376 | |
1377 else if ((*p=='[') && (*(p+1)=='|') && (*(p+2)==']')) { /* code [|] i… | |
1378 k=add_sym(BAR); | |
1379 symv[ivc][k].u=B_INVIS; | |
1380 p=p+3; | |
1381 } | |
1382 | |
1383 else if ((*p=='[') && (*(p+1)=='|')) { /* code [| for thick-thin ba… | |
1384 k=add_sym(BAR); | |
1385 symv[ivc][k].u=B_FAT1; | |
1386 p=p+2; | |
1387 } | |
1388 | |
1389 else return 0; | |
1390 | |
1391 strcpy(symv[ivc][k].text,""); | |
1392 if (strlen(gch)>0) { | |
1393 strcpy (symv[ivc][k].text, gch); | |
1394 strcpy (gch, ""); | |
1395 } | |
1396 | |
1397 /* see if valid bar is followed by specifier for first or second endin… | |
1398 if (*p=='1') { symv[ivc][k].v=1; p++; } | |
1399 else if (*p=='2') { symv[ivc][k].v=2; p++; } | |
1400 else if ((*p=='[') && (*(p+1)=='1')) { symv[ivc][k].v=1; p=p+2; } | |
1401 else if ((*p=='[') && (*(p+1)=='2')) { symv[ivc][k].v=2; p=p+2; } | |
1402 else if ((*p==' ') && (*(p+1)=='[') && (*(p+2)=='1')) | |
1403 { symv[ivc][k].v=1; p=p+3; } | |
1404 else if ((*p==' ') && (*(p+1)=='[') && (*(p+2)=='2')) | |
1405 { symv[ivc][k].v=2; p=p+3; } | |
1406 | |
1407 return 1; | |
1408 } | |
1409 | |
1410 /* ----- parse_space: parse for whitespace ---- */ | |
1411 int parse_space () | |
1412 { | |
1413 int rc; | |
1414 | |
1415 rc=0; | |
1416 while ((*p==' ')||(*p=='\t')) { | |
1417 rc=1; | |
1418 p++; | |
1419 } | |
1420 if (db>3) if (rc) printf (" parsed whitespace\n"); | |
1421 return rc; | |
1422 } | |
1423 | |
1424 /* ----- parse_esc: parse for escape sequence ----- */ | |
1425 int parse_esc () | |
1426 { | |
1427 | |
1428 int nseq; | |
1429 char *pp; | |
1430 | |
1431 if (*p == '\\') { /* try for \...\ sequence */ | |
1432 p++; | |
1433 nseq=0; | |
1434 while ((*p!='\\') && (*p!=0)) { | |
1435 escseq[nseq]=*p; | |
1436 nseq++; | |
1437 p++; | |
1438 } | |
1439 if (*p == '\\') { | |
1440 p++; | |
1441 escseq[nseq]=0; | |
1442 if (db>3) printf (" parsed esc sequence <%s>\n", escseq); | |
1443 return ESCSEQ; | |
1444 } | |
1445 else { | |
1446 if (cfmt.breakall) return DUMMY; | |
1447 if (db>3) printf (" parsed esc to EOL.. continuation\n"); | |
1448 } | |
1449 return CONTINUE; | |
1450 } | |
1451 | |
1452 /* next, try for [..] sequence */ | |
1453 if ((*p=='[') && (*(p+1)>='A') && (*(p+1)<='Z') && (*(p+2)==':')) { | |
1454 pp=p; | |
1455 p++; | |
1456 nseq=0; | |
1457 while ((*p!=']') && (*p!=0)) { | |
1458 escseq[nseq]=*p; | |
1459 nseq++; | |
1460 p++; | |
1461 } | |
1462 if (*p == ']') { | |
1463 p++; | |
1464 escseq[nseq]=0; | |
1465 if (db>3) printf (" parsed esc sequence <%s>\n", escseq); | |
1466 return ESCSEQ; | |
1467 } | |
1468 syntax ("Escape sequence [..] not closed", pp); | |
1469 return ESCSEQ; | |
1470 } | |
1471 return 0; | |
1472 } | |
1473 | |
1474 | |
1475 /* ----- parse_nl: parse for newline ----- */ | |
1476 int parse_nl () | |
1477 { | |
1478 | |
1479 if ((*p == '\\')&&(*(p+1)=='\\')) { | |
1480 p+=2; | |
1481 return 1; | |
1482 } | |
1483 else | |
1484 return 0; | |
1485 } | |
1486 | |
1487 /* ----- parse_gchord: parse guitar chord, save in buffer ----- */ | |
1488 int parse_gchord () | |
1489 { | |
1490 char *q; | |
1491 int n; | |
1492 | |
1493 if (*p != '"') return 0; | |
1494 | |
1495 q=p; | |
1496 p++; | |
1497 n=strlen(gch); | |
1498 if (n > 0) syntax ("Overwrite unused guitar chord", q); | |
1499 | |
1500 while ((*p != '"') && (*p != 0)) { | |
1501 gch[n]=*p; | |
1502 n++; | |
1503 if (n >= 200) { | |
1504 syntax ("String for guitar chord too long", q); | |
1505 return 1; | |
1506 } | |
1507 p++; | |
1508 } | |
1509 if (*p == 0) { | |
1510 syntax ("EOL reached while parsing guitar chord", q); | |
1511 return 1; | |
1512 } | |
1513 p++; | |
1514 gch[n]=0; | |
1515 if (db>3) printf(" parse guitar chord <%s>\n", gch); | |
1516 | |
1517 /*| gch_transpose (voice[ivc].key); |*/ | |
1518 | |
1519 return 1; | |
1520 } | |
1521 | |
1522 | |
1523 /* ----- parse_deco: parse for decoration on note ----- */ | |
1524 int parse_deco (dtype) | |
1525 int dtype[10]; | |
1526 { | |
1527 int deco,n; | |
1528 | |
1529 n=0; | |
1530 | |
1531 for (;;) { | |
1532 deco=0; | |
1533 if (*p == '~') { | |
1534 if (DECO_IS_ROLL) deco=D_ROLL; | |
1535 else deco=D_GRACE; | |
1536 } | |
1537 if (*p == '.') deco=D_STACC; | |
1538 if (*p == 'J') deco=D_SLIDE; | |
1539 if (*p == 'M') deco=D_EMBAR; | |
1540 if (*p == 'H') deco=D_HOLD; | |
1541 if (*p == 'R') deco=D_ROLL; | |
1542 if (*p == 'T') deco=D_TRILL; | |
1543 if (*p == 'u') deco=D_UPBOW; | |
1544 if (*p == 'v') deco=D_DOWNBOW; | |
1545 if (*p == 'K') deco=D_HAT; | |
1546 if (*p == 'k') deco=D_ATT; | |
1547 | |
1548 if (deco) { | |
1549 p++; | |
1550 dtype[n]=deco; | |
1551 n++; | |
1552 } | |
1553 else | |
1554 break; | |
1555 } | |
1556 | |
1557 return n; | |
1558 } | |
1559 | |
1560 | |
1561 /* ----- parse_length: parse length specifer for note or rest --- */ | |
1562 int parse_length () | |
1563 { | |
1564 int len,fac; | |
1565 | |
1566 len=voice[ivc].meter.dlen; /* start with default length */ | |
1567 | |
1568 if (len<=0) printf ("!!! parse_len: got len=%d\n", len); | |
1569 | |
1570 | |
1571 if (isdig(*p)) { /* multiply note length */ | |
1572 fac=parse_uint (); | |
1573 if (fac==0) fac=1; | |
1574 len *= fac; | |
1575 } | |
1576 | |
1577 if (*p=='/') { /* divide note length */ | |
1578 while (*p=='/') { | |
1579 p++; | |
1580 if (isdig(*p)) | |
1581 fac=parse_uint(); | |
1582 else | |
1583 fac=2; | |
1584 if (len%fac) { | |
1585 syntax ("Bad length divisor", p-1); | |
1586 return len; | |
1587 } | |
1588 len=len/fac; | |
1589 } | |
1590 } | |
1591 | |
1592 return len; | |
1593 | |
1594 } | |
1595 | |
1596 /* ----- parse_grace_sequence --------- */ | |
1597 int parse_grace_sequence (pgr,agr) | |
1598 int pgr[],agr[]; | |
1599 { | |
1600 | |
1601 char *p0; | |
1602 int n,len; | |
1603 | |
1604 p0=p; | |
1605 if (*p != '{') return 0; | |
1606 p++; | |
1607 | |
1608 n=0; | |
1609 while (*p != '}') { | |
1610 if (*p == '\0') { | |
1611 syntax ("Unbalanced grace note sequence", p0); | |
1612 return 0; | |
1613 } | |
1614 if (!isnote(*p)) { | |
1615 syntax ("Unexpected symbol in grace note sequence", p); | |
1616 p++; | |
1617 } | |
1618 agr[n]=0; | |
1619 if (*p == '=') agr[n]=A_NT; | |
1620 if (*p == '^') { | |
1621 if (*(p+1)=='^') { agr[n]=A_DS; p++; } | |
1622 else agr[n]=A_SH; | |
1623 } | |
1624 if (*p == '_') { | |
1625 if (*(p+1)=='_') { agr[n]=A_DF; p++; } | |
1626 else agr[n]=A_FT; | |
1627 } | |
1628 if (agr[n]) p++; | |
1629 | |
1630 pgr[n] = numeric_pitch(*p); | |
1631 p++; | |
1632 while (*p == '\'') { pgr[n] += 7; p++; } | |
1633 while (*p == ',') { pgr[n] -= 7; p++; } | |
1634 | |
1635 do_transpose (voice[ivc].key, &pgr[n], &agr[n]); | |
1636 | |
1637 len=parse_length (); /* ignore any length specifier */ | |
1638 n++; | |
1639 } | |
1640 | |
1641 p++; | |
1642 return n; | |
1643 } | |
1644 | |
1645 | |
1646 /* ----- idfy_note: set head type, dots, flags for one note --- */ | |
1647 int idfy_note (s) | |
1648 struct SYMBOL *s; | |
1649 { | |
1650 int head,base,len,flags,dots; | |
1651 | |
1652 if (s->len==0) s->len=s->lens[0]; | |
1653 len=s->len; | |
1654 | |
1655 base=WHOLE; | |
1656 if (len>=WHOLE) base=WHOLE; | |
1657 else if (len>=HALF) base=HALF; | |
1658 else if (len>=QUARTER) base=QUARTER; | |
1659 else if (len>=EIGHTH) base=EIGHTH; | |
1660 else if (len>=SIXTEENTH) base=SIXTEENTH; | |
1661 else if (len>=THIRTYSECOND) base=THIRTYSECOND; | |
1662 else if (len>=SIXTYFOURTH) base=SIXTYFOURTH; | |
1663 else return 1; | |
1664 | |
1665 if (base==WHOLE) head=H_OVAL; | |
1666 else if (base==HALF) head=H_EMPTY; | |
1667 else head=H_FULL; | |
1668 | |
1669 if (base==SIXTYFOURTH) flags=4; | |
1670 else if (base==THIRTYSECOND) flags=3; | |
1671 else if (base==SIXTEENTH) flags=2; | |
1672 else if (base==EIGHTH) flags=1; | |
1673 else flags=0; | |
1674 | |
1675 dots=0; | |
1676 if (len==base) dots=0; | |
1677 else if (2*len==3*base) dots=1; | |
1678 else if (4*len==7*base) dots=2; | |
1679 else if (8*len==15*base) dots=3; | |
1680 else return 2; | |
1681 | |
1682 /*| printf ("idfy_note: length %d gives head %d, dots %d, flags %d\n",… | |
1683 /*| len,head,dots,flags); |*/ | |
1684 | |
1685 s->head=head; | |
1686 s->dots=dots; | |
1687 s->flags=flags; | |
1688 return 0; | |
1689 } | |
1690 | |
1691 | |
1692 | |
1693 /* ----- identify_note ----- */ | |
1694 void identify_note (s,q) | |
1695 struct SYMBOL *s; | |
1696 char *q; | |
1697 { | |
1698 int rc; | |
1699 | |
1700 rc = idfy_note (s); | |
1701 if (rc==1) syntax("Cannot identify head for note",q); | |
1702 if (rc==2) syntax("Cannot handle note length for note",q); | |
1703 | |
1704 /* set flag if duration equals length of one measure */ | |
1705 if (nvoice>0) { | |
1706 if (s->len==(WHOLE*voice[ivc].meter.meter1)/voice[ivc].meter.meter2) | |
1707 s->fullmes=1; | |
1708 } | |
1709 } | |
1710 | |
1711 | |
1712 /* ----- double_note: change note length for > or < char --- */ | |
1713 /* Note: if symv[ivc][i] is a chord, the length shifted to the following | |
1714 note is taken from the first note head. Problem: the crazy syntax | |
1715 permits different lengths within a chord. */ | |
1716 void double_note (i,num,sign,q) | |
1717 int i,num,sign; | |
1718 char *q; | |
1719 { | |
1720 int m,shift,j,len; | |
1721 | |
1722 if ((symv[ivc][i].type!=NOTE) && (symv[ivc][i].type!=REST)) | |
1723 bug("sym is not NOTE or REST in double_note", 1); | |
1724 | |
1725 shift=0; | |
1726 len=symv[ivc][i].lens[0]; | |
1727 for (j=0;j<num;j++) { | |
1728 len=len/2; | |
1729 shift -= sign*len; | |
1730 symv[ivc][i].len += sign*len; | |
1731 for (m=0;m<symv[ivc][i].npitch;m++) symv[ivc][i].lens[m] += sign*len; | |
1732 } | |
1733 identify_note (&symv[ivc][i],q); | |
1734 carryover += shift; | |
1735 } | |
1736 | |
1737 /* ----- parse_basic_note: parse note or rest with pitch and length --*/ | |
1738 int parse_basic_note (pitch,length,accidental) | |
1739 int *pitch,*length,*accidental; | |
1740 { | |
1741 int pit,len,acc; | |
1742 | |
1743 acc=pit=0; /* look for accidental sign */ | |
1744 if (*p == '=') acc=A_NT; | |
1745 if (*p == '^') { | |
1746 if (*(p+1)=='^') { acc=A_DS; p++; } | |
1747 else acc=A_SH; | |
1748 } | |
1749 if (*p == '_') { | |
1750 if (*(p+1)=='_') { acc=A_DF; p++; } | |
1751 else acc=A_FT; | |
1752 } | |
1753 | |
1754 if (acc) { | |
1755 p++; | |
1756 if (!strchr("CDEFGABcdefgab",*p)) { | |
1757 syntax("Missing note after accidental", p-1); | |
1758 return 0; | |
1759 } | |
1760 } | |
1761 if (!isnote(*p)) { | |
1762 syntax ("Expecting note", p); | |
1763 p++; | |
1764 return 0; | |
1765 } | |
1766 | |
1767 pit= numeric_pitch(*p); /* basic pitch */ | |
1768 p++; | |
1769 | |
1770 while (*p == '\'') { /* eat up following ' chars */ | |
1771 pit += 7; | |
1772 p++; | |
1773 } | |
1774 | |
1775 while (*p == ',') { /* eat up following , chars */ | |
1776 pit -= 7; | |
1777 p++; | |
1778 } | |
1779 | |
1780 len=parse_length(); | |
1781 | |
1782 do_transpose (voice[ivc].key, &pit, &acc); | |
1783 | |
1784 *pitch=pit; | |
1785 *length=len; | |
1786 *accidental=acc; | |
1787 | |
1788 if (db>3) printf (" parsed basic note," | |
1789 "length %d/%d = 1/%d, pitch %d\n", | |
1790 len,BASE,BASE/len,pit); | |
1791 | |
1792 return 1; | |
1793 | |
1794 } | |
1795 | |
1796 | |
1797 /* ----- parse_note: parse for one note or rest with all trimmings --- */ | |
1798 int parse_note () | |
1799 { | |
1800 int k,deco,i,chord,m,type,rc,sl1,sl2,j; | |
1801 int pitch,length,accidental,invis; | |
1802 int ngr,pgr[30],agr[30],dtype[30]; | |
1803 char *q,*q0; | |
1804 | |
1805 ngr=parse_grace_sequence(pgr,agr); /* grace notes */ | |
1806 | |
1807 parse_gchord(); /* permit chord after graces */ | |
1808 | |
1809 deco=parse_deco(dtype); /* decorations */ | |
1810 | |
1811 parse_gchord(); /* permit chord after deco */ | |
1812 | |
1813 chord=0; /* determine if chord */ | |
1814 q=p; | |
1815 if ((*p=='+') || (*p=='[')) { chord=1; p++; } | |
1816 | |
1817 type=invis=0; | |
1818 if (isnote(*p)) type=NOTE; | |
1819 if (chord && (*p=='(')) type=NOTE; | |
1820 if (chord && (*p==')')) type=NOTE; /* this just for better error msg… | |
1821 if ((*p=='z')||(*p=='Z')) type=REST; | |
1822 if ((*p=='x')||(*p=='X')) {type=REST; invis=1; } | |
1823 if (!type) return 0; | |
1824 | |
1825 k=add_sym(type); /* add new symbol to list */ | |
1826 | |
1827 | |
1828 symv[ivc][k].dc.n=deco; /* copy over pre-parsed stuff */ | |
1829 for (i=0;i<deco;i++) | |
1830 symv[ivc][k].dc.t[i]=dtype[i]; | |
1831 symv[ivc][k].gr.n=ngr; | |
1832 for (i=0;i<ngr;i++) { | |
1833 symv[ivc][k].gr.p[i]=pgr[i]; | |
1834 symv[ivc][k].gr.a[i]=agr[i]; | |
1835 } | |
1836 if (strlen(gch)>0) { | |
1837 gch_transpose (voice[ivc].key); | |
1838 strcpy (symv[ivc][k].text, gch); | |
1839 strcpy (gch, ""); | |
1840 } | |
1841 | |
1842 q0=p; | |
1843 if (type==REST) { | |
1844 p++; | |
1845 symv[ivc][k].lens[0] = parse_length(); | |
1846 symv[ivc][k].npitch=1; | |
1847 symv[ivc][k].invis=invis; | |
1848 if (db>3) printf (" parsed rest, length %d/%d = 1/%d\n", | |
1849 symv[ivc][k].lens[0],BASE,BASE/symv[ivc][k].lens[0… | |
1850 } | |
1851 else { | |
1852 m=0; /* get pitch and length */ | |
1853 sl1=sl2=0; | |
1854 for (;;) { | |
1855 if (chord && (*p=='(')) { | |
1856 sl1++; | |
1857 symv[ivc][k].sl1[m]=sl1; | |
1858 p++; | |
1859 } | |
1860 deco=parse_deco(dtype); /* for extra decorations within chord … | |
1861 for (i=0;i<deco;i++) symv[ivc][k].dc.t[i+symv[ivc][k].dc.n]=dtype[… | |
1862 symv[ivc][k].dc.n += deco; | |
1863 | |
1864 rc=parse_basic_note (&pitch,&length,&accidental); | |
1865 if (rc==0) { voice[ivc].nsym--; return 0; } | |
1866 symv[ivc][k].pits[m] = pitch; | |
1867 symv[ivc][k].lens[m] = length; | |
1868 symv[ivc][k].accs[m] = accidental; | |
1869 symv[ivc][k].ti1[m] = symv[ivc][k].ti2[m] = 0; | |
1870 for (j=0;j<ntinext;j++) | |
1871 if (tinext[j]==symv[ivc][k].pits[m]) symv[ivc][k].ti2[m]=1; | |
1872 | |
1873 if (chord && (*p=='-')) {symv[ivc][k].ti1[m]=1; p++;} | |
1874 | |
1875 if (chord && (*p==')')) { | |
1876 sl2++; | |
1877 symv[ivc][k].sl2[m]=sl2; | |
1878 p++; | |
1879 } | |
1880 | |
1881 if (chord && (*p=='-')) {symv[ivc][k].ti1[m]=1; p++;} | |
1882 | |
1883 m++; | |
1884 | |
1885 if (!chord) break; | |
1886 if ((*p=='+')||(*p==']')) { | |
1887 p++; | |
1888 break; | |
1889 } | |
1890 if (*p=='\0') { | |
1891 if (chord) syntax ("Chord not closed", q); | |
1892 return type; | |
1893 } | |
1894 } | |
1895 ntinext=0; | |
1896 for (j=0;j<m;j++) | |
1897 if (symv[ivc][k].ti1[j]) { | |
1898 tinext[ntinext]=symv[ivc][k].pits[j]; | |
1899 ntinext++; | |
1900 } | |
1901 symv[ivc][k].npitch=m; | |
1902 } | |
1903 | |
1904 for (m=0;m<symv[ivc][k].npitch;m++) { /* add carryover from > or < */ | |
1905 if (symv[ivc][k].lens[m]+carryover<=0) { | |
1906 syntax("> leads to zero or negative note length",q0); | |
1907 } | |
1908 else | |
1909 symv[ivc][k].lens[m] += carryover; | |
1910 } | |
1911 carryover=0; | |
1912 | |
1913 if (db>3) printf (" parsed note, decos %d, text <%s>\n", | |
1914 symv[ivc][k].dc.n, symv[ivc][k].text); | |
1915 | |
1916 | |
1917 symv[ivc][k].yadd=0; | |
1918 if (voice[ivc].key.ktype==BASS) symv[ivc][k].yadd=-6; | |
1919 if (voice[ivc].key.ktype==ALTO) symv[ivc][k].yadd=-3; | |
1920 identify_note (&symv[ivc][k],q0); | |
1921 return type; | |
1922 } | |
1923 | |
1924 | |
1925 /* ----- parse_sym: parse a symbol and return its type -------- */ | |
1926 int parse_sym () | |
1927 { | |
1928 int i; | |
1929 | |
1930 if (parse_gchord()) return GCHORD; | |
1931 if (parse_bar()) return BAR; | |
1932 if (parse_space()) return SPACE; | |
1933 if (parse_nl()) return NEWLINE; | |
1934 if ((i=parse_esc())) return i; | |
1935 if ((i=parse_note())) return i; | |
1936 if (parse_nl()) return NEWLINE; | |
1937 return 0; | |
1938 } | |
1939 | |
1940 /* ----- add_wd ----- */ | |
1941 char *add_wd(str) | |
1942 char str[]; | |
1943 { | |
1944 char *rp; | |
1945 int l; | |
1946 | |
1947 l=strlen(str); | |
1948 if (l==0) return 0; | |
1949 if (nwpool+l+1>NWPOOL) | |
1950 rx ("Overflow while parsing vocals; increase NWPOOL and recompile.",… | |
1951 | |
1952 strcpy(wpool+nwpool, str); | |
1953 rp=wpool+nwpool; | |
1954 nwpool=nwpool+l+1; | |
1955 return rp; | |
1956 } | |
1957 | |
1958 /* ----- parse_vocals: parse words below a line of music ----- */ | |
1959 /* Use '^' to mark a '-' between syllables - hope nobody needs '^' ! */ | |
1960 int parse_vocals (line) | |
1961 char line[]; | |
1962 { | |
1963 int isym; | |
1964 char *c,*c1,*w; | |
1965 char word[81]; | |
1966 | |
1967 if ((line[0]!='w') || (line[1]!=':')) return 0; | |
1968 p0=line; | |
1969 | |
1970 isym=nsym0-1; | |
1971 c=line+2; | |
1972 for (;;) { | |
1973 while(*c==' ') c++; | |
1974 if (*c=='\0') break; | |
1975 c1=c; | |
1976 if ((*c=='_') || (*c=='*') || (*c=='|') || (*c=='-')) { | |
1977 word[0]=*c; | |
1978 if (*c=='-') word[0]='^'; | |
1979 word[1]='\0'; | |
1980 c++; | |
1981 } | |
1982 else { | |
1983 w=word; | |
1984 *w='\0'; | |
1985 while ((*c!=' ') && (*c!='\0')) { | |
1986 if ((*c=='_') || (*c=='*') || (*c=='|')) break; | |
1987 if (*c=='-') { | |
1988 if (*(c-1) != '\\') break; | |
1989 w--; | |
1990 *w='-'; | |
1991 } | |
1992 *w=*c; w++; c++; | |
1993 } | |
1994 if (*c=='-') { *w='^' ; w++; c++; } | |
1995 *w='\0'; | |
1996 } | |
1997 | |
1998 /* now word contains a word, possibly with trailing '^', | |
1999 or one of the special characters * | _ - */ | |
2000 | |
2001 if (!strcmp(word,"|")) { /* skip forward to next bar */ | |
2002 isym++; | |
2003 while ((symv[ivc][isym].type!=BAR) && (isym<voice[ivc].nsym)) isym… | |
2004 if (isym>=voice[ivc].nsym) | |
2005 { syntax("Not enough bar lines for |",c1); break; } | |
2006 } | |
2007 | |
2008 else { /* store word in next note */ | |
2009 w=word; | |
2010 while (*w!='\0') { /* replace * and ~ by space */ | |
2011 if ((*w=='*') || (*w=='~')) *w=' '; | |
2012 w++; | |
2013 } | |
2014 isym++; | |
2015 while ((symv[ivc][isym].type!=NOTE) && (isym<voice[ivc].nsym)) isy… | |
2016 if (isym>=voice[ivc].nsym) | |
2017 { syntax ("Not enough notes for words",c1); break; } | |
2018 symv[ivc][isym].wordp[nwline]=add_wd(word); | |
2019 } | |
2020 | |
2021 if (*c=='\0') break; | |
2022 } | |
2023 | |
2024 nwline++; | |
2025 return 1; | |
2026 } | |
2027 | |
2028 | |
2029 /* ----- parse_music_line: parse a music line into symbols ----- */ | |
2030 int parse_music_line (line) | |
2031 char line[]; | |
2032 { | |
2033 int type,num,nbr,n,itype,i,nsym00; | |
2034 char msg[81]; | |
2035 char *p1,*pmx; | |
2036 | |
2037 if (nvoice==0) ivc=switch_voice (DEFVOICE); | |
2038 if (ivc>=nvoice) bug ("Trying to parse undefined voice",1); | |
2039 | |
2040 nwline=0; | |
2041 nsym0=voice[ivc].nsym; | |
2042 nsym00=nsym0; | |
2043 | |
2044 nbr=0; | |
2045 p=p0=line; | |
2046 pmx=p+strlen(p); | |
2047 | |
2048 while (*p != 0) { | |
2049 if (p>pmx) break; /* emergency exit */ | |
2050 type=parse_sym(); | |
2051 n=voice[ivc].nsym; | |
2052 i=n-1; | |
2053 if ((db>4) && type) | |
2054 printf (" sym[%d] code (%d,%d)\n", | |
2055 n-1,symv[ivc][n-1].type,symv[ivc][n-1].u); | |
2056 | |
2057 if (type==NEWLINE) { | |
2058 if ((n>0) && !cfmt.continueall && !cfmt.barsperstaff) { | |
2059 symv[ivc][i].eoln=1; | |
2060 if (word) { | |
2061 symv[ivc][last_note].word_end=1; | |
2062 word=0; | |
2063 } | |
2064 } | |
2065 } | |
2066 | |
2067 if (type==ESCSEQ) { | |
2068 if (db>3) | |
2069 printf ("Handle escape sequence <%s>\n", escseq); | |
2070 itype=info_field (escseq); | |
2071 handle_inside_field (itype); | |
2072 } | |
2073 | |
2074 if (type==REST) { | |
2075 if (pplet) { /* n-plet can start on rest */ | |
2076 symv[ivc][i].p_plet=pplet; | |
2077 symv[ivc][i].q_plet=qplet; | |
2078 symv[ivc][i].r_plet=rplet; | |
2079 pplet=0; | |
2080 } | |
2081 last_note=i; /* need this so > and < work */ | |
2082 p1=p; | |
2083 } | |
2084 | |
2085 if (type==NOTE) { | |
2086 if (!word) { | |
2087 symv[ivc][i].word_st=1; | |
2088 word=1; | |
2089 } | |
2090 symv[ivc][i].slur_st+=nbr; | |
2091 nbr=0; | |
2092 if (voice[ivc].end_slur) symv[ivc][i].slur_end++; | |
2093 voice[ivc].end_slur=0; | |
2094 | |
2095 if (pplet) { /* start of n-plet */ | |
2096 symv[ivc][i].p_plet=pplet; | |
2097 symv[ivc][i].q_plet=qplet; | |
2098 symv[ivc][i].r_plet=rplet; | |
2099 pplet=0; | |
2100 } | |
2101 last_note=last_real_note=i; | |
2102 p1=p; | |
2103 } | |
2104 | |
2105 if (word && ((type==BAR)||(type==SPACE))) { | |
2106 if (last_real_note>=0) symv[ivc][last_real_note].word_end=1; | |
2107 word=0; | |
2108 } | |
2109 | |
2110 if (!type) { | |
2111 | |
2112 if (*p == '-') { /* a-b tie */ | |
2113 symv[ivc][last_note].slur_st++; | |
2114 voice[ivc].end_slur=1; | |
2115 p++; | |
2116 } | |
2117 | |
2118 else if (*p == '(') { | |
2119 p++; | |
2120 if (isdig(*p)) { | |
2121 pplet=*p-'0'; qplet=0; rplet=pplet; | |
2122 p++; | |
2123 if (*p == ':') { | |
2124 p++; | |
2125 if (isdig(*p)) { qplet=*p-'0'; p++; } | |
2126 if (*p == ':') { | |
2127 p++; | |
2128 if (isdig(*p)) { rplet=*p-'0'; p++; } | |
2129 } | |
2130 } | |
2131 } | |
2132 else { | |
2133 nbr++; | |
2134 } | |
2135 } | |
2136 else if (*p == ')') { | |
2137 if (last_note>0) | |
2138 symv[ivc][last_note].slur_end++; | |
2139 else | |
2140 syntax ("Unexpected symbol",p); | |
2141 p++; | |
2142 } | |
2143 else if (*p == '>') { | |
2144 num=1; | |
2145 p++; | |
2146 while (*p == '>') { num++; p++; } | |
2147 if (last_note<0) | |
2148 syntax ("No note before > sign", p); | |
2149 else | |
2150 double_note (last_note, num, 1, p1); | |
2151 } | |
2152 else if (*p == '<') { | |
2153 num=1; | |
2154 p++; | |
2155 while (*p == '<') { num++; p++; } | |
2156 if (last_note<0) | |
2157 syntax ("No note before < sign", p); | |
2158 else | |
2159 double_note (last_note, num, -1, p1); | |
2160 } | |
2161 else if (*p == '*') /* ignore stars for now */ | |
2162 p++; | |
2163 else if (*p == '!') /* ditto for '!' */ | |
2164 p++; | |
2165 else { | |
2166 if (*p != '\0') | |
2167 sprintf (msg, "Unexpected symbol \'%c\'", *p); | |
2168 else | |
2169 sprintf (msg, "Unexpected end of line"); | |
2170 syntax (msg, p); | |
2171 p++; | |
2172 } | |
2173 } | |
2174 } | |
2175 | |
2176 /* maybe set end-of-line marker, if symbols were added */ | |
2177 n=voice[ivc].nsym; | |
2178 | |
2179 if (n>nsym0) { | |
2180 symv[ivc][n-1].eoln=1; | |
2181 if (type==CONTINUE) symv[ivc][n-1].eoln=0; | |
2182 if (cfmt.barsperstaff) symv[ivc][n-1].eoln=0; | |
2183 if (cfmt.continueall) symv[ivc][n-1].eoln=0; | |
2184 } | |
2185 | |
2186 | |
2187 | |
2188 /* break words at end of line */ | |
2189 if (word && (symv[ivc][n-1].eoln==1)) { | |
2190 symv[ivc][last_note].word_end=1; | |
2191 word=0; | |
2192 } | |
2193 | |
2194 if (vb>9) | |
2195 printf ("Parsed music symbols %d to %d for voice %d\n", | |
2196 nsym00,voice[ivc].nsym-1,ivc); | |
2197 | |
2198 return MUSIC; | |
2199 | |
2200 } | |
2201 | |
2202 /* ----- is_selected: check selection for current info fields ---- */ | |
2203 int is_selected (xref_str,npat,pat,select_all,search_field) | |
2204 int npat,select_all,search_field; | |
2205 char xref_str[],pat[][STRL1]; | |
2206 { | |
2207 int i,j,a,b,m; | |
2208 | |
2209 /* true if select_all or if no selectors given */ | |
2210 if (select_all) return 1; | |
2211 if (str_isblank(xref_str) && (npat==0)) return 1; | |
2212 | |
2213 for (i=0;i<npat;i++) { /*patterns */ | |
2214 if (search_field==S_COMPOSER) { | |
2215 for (j=0;j<info.ncomp;j++) { | |
2216 if (!m) m=match(info.comp[j],pat[i]); | |
2217 } | |
2218 } | |
2219 else if (search_field==S_SOURCE) | |
2220 m=match(info.src,pat[i]); | |
2221 else if (search_field==S_RHYTHM) | |
2222 m=match(info.rhyth,pat[i]); | |
2223 else { | |
2224 m=match(info.title,pat[i]); | |
2225 if ((!m) && (numtitle>=2)) m=match(info.title2,pat[i]); | |
2226 if ((!m) && (numtitle>=3)) m=match(info.title3,pat[i]); | |
2227 } | |
2228 if (m) return 1; | |
2229 } | |
2230 | |
2231 /* check xref against string of numbers */ | |
2232 p=xref_str; | |
2233 while (*p != 0) { | |
2234 parse_space(); | |
2235 a=parse_uint(); | |
2236 if (!a) return 0; /* can happen if invalid chars in string … | |
2237 parse_space(); | |
2238 if (*p == '-') { | |
2239 p++; | |
2240 parse_space(); | |
2241 b=parse_uint(); | |
2242 if (!b) { | |
2243 if (xrefnum>=a) return 1; | |
2244 } | |
2245 else | |
2246 for (i=a;i<=b;i++) if (xrefnum==i) return 1; | |
2247 } | |
2248 else { | |
2249 if (xrefnum==a) return 1; | |
2250 } | |
2251 if (*p == ',') p++; | |
2252 } | |
2253 | |
2254 return 0; | |
2255 | |
2256 } | |
2257 | |
2258 /* ----- rehash_selectors: split selectors into patterns and xrefs -- */ | |
2259 int rehash_selectors (sel_str, xref_str, pat) | |
2260 char sel_str[], xref_str[]; | |
2261 char pat[][STRL1]; | |
2262 { | |
2263 char *q; | |
2264 char arg[501]; | |
2265 int i,npat; | |
2266 | |
2267 npat=0; | |
2268 strcpy (xref_str, ""); | |
2269 q=sel_str; | |
2270 | |
2271 i=0; | |
2272 while (1) { | |
2273 if ((*q==' ') || (*q=='\0')) { | |
2274 arg[i]='\0'; | |
2275 i=0; | |
2276 if (!str_isblank(arg)) { | |
2277 if (arg[0]=='-') /* skip any flags */ | |
2278 ; | |
2279 else if (is_xrefstr(arg)) { | |
2280 strcat(xref_str, arg); | |
2281 strcat(xref_str, " "); | |
2282 } | |
2283 else { /* pattern with * or + */ | |
2284 if ((strchr(arg,'*')) || (strchr(arg,'+'))) { | |
2285 strcpy(pat[npat],arg); | |
2286 } | |
2287 else { /* simple pattern */ | |
2288 strcpy(pat[npat],"*"); | |
2289 strcat(pat[npat],arg); | |
2290 strcat(pat[npat],"*"); | |
2291 } | |
2292 npat++; | |
2293 } | |
2294 } | |
2295 } | |
2296 else { | |
2297 arg[i]=*q; | |
2298 i++; | |
2299 } | |
2300 if (*q=='\0') break; | |
2301 q++; | |
2302 } | |
2303 return npat; | |
2304 } | |
2305 | |
2306 | |
2307 /* ----- decomment_line: cut off after % ----- */ | |
2308 void decomment_line (ln) | |
2309 char ln[]; | |
2310 { | |
2311 int i; | |
2312 | |
2313 for (i=0;i<strlen(ln);i++) if (ln[i]=='%') ln[i]='\0'; | |
2314 | |
2315 } | |
2316 | |
2317 | |
2318 /* ----- get_line: read line, do first operations on it ----- */ | |
2319 int get_line (fp,ln) | |
2320 FILE *fp; | |
2321 char ln[]; | |
2322 { | |
2323 int l; | |
2324 | |
2325 strcpy (ln, ""); | |
2326 if (feof(fp)) return 0; | |
2327 | |
2328 abc2ps_getline(ln, BSIZE, fp); | |
2329 /*| fgets(ln, BSIZE, fp); |*/ | |
2330 linenum++; | |
2331 l=strlen(ln); | |
2332 if (l>STRL) { | |
2333 if (verbose<=2) printf ("\n"); | |
2334 printf ("+++ Line %d too long, truncate from %d to %d chars\n", | |
2335 linenum, l, STRL); | |
2336 l=STRL-1; | |
2337 ln[l]='\0'; | |
2338 } | |
2339 if (is_end_line(ln)) return 0; | |
2340 if (ln[l-1]=='\n') ln[l-1]='\0'; | |
2341 | |
2342 if ((verbose>=7) || (vb>=10) ) printf ("%3d %s \n", linenum, ln); | |
2343 | |
2344 return 1; | |
2345 | |
2346 } | |
2347 | |
2348 | |
2349 /* ----- read_line: returns type of line scanned --- */ | |
2350 int read_line (fp,line) | |
2351 FILE *fp; | |
2352 char line[BSIZE]; | |
2353 { | |
2354 int type,nsym0; | |
2355 | |
2356 if (!get_line(fp,line)) return E_O_F; | |
2357 | |
2358 if (str_isblank(line)) return BLANK; | |
2359 if (is_pseudocomment(line)) return PSCOMMENT; | |
2360 if (is_comment(line)) return COMMENT; | |
2361 decomment_line (line); | |
2362 | |
2363 if ((type=info_field(line))) { | |
2364 /* skip after history field. Nightmarish syntax, that. */ | |
2365 if (type != HISTORY) | |
2366 return type; | |
2367 else { | |
2368 for (;;) { | |
2369 if (! get_line(fp,line)) return E_O_F; | |
2370 if (str_isblank(line)) return BLANK; | |
2371 if (is_info_field(line)) break; | |
2372 add_text (line, TEXT_H); | |
2373 } | |
2374 type=info_field (line); | |
2375 return type; | |
2376 } | |
2377 } | |
2378 | |
2379 if (do_this_tune) { | |
2380 if (parse_vocals(line)) return MWORDS; | |
2381 } | |
2382 | |
2383 return MUSIC; | |
2384 | |
2385 } | |
2386 | |
2387 /* ----- do_index: print index of abc file ------ */ | |
2388 void do_index(fp,xref_str,npat,pat,select_all,search_field) | |
2389 FILE *fp; | |
2390 int npat,select_all,search_field; | |
2391 char xref_str[],pat[][STRL1]; | |
2392 { | |
2393 int type,within_tune; | |
2394 char line[BSIZE]; | |
2395 | |
2396 linenum=0; | |
2397 verbose=vb; | |
2398 numtitle=0; | |
2399 write_history=0; | |
2400 within_tune=within_block=do_this_tune=0; | |
2401 reset_info (&default_info); | |
2402 info=default_info; | |
2403 | |
2404 for (;;) { | |
2405 if (!get_line(fp,line)) break; | |
2406 if (is_comment(line)) continue; | |
2407 decomment_line (line); | |
2408 type=info_field (line); | |
2409 | |
2410 switch (type) { | |
2411 | |
2412 case XREF: | |
2413 if (within_block) | |
2414 printf ("+++ Tune %d not closed properly \n", xrefnum); | |
2415 numtitle=0; | |
2416 within_tune=0; | |
2417 within_block=1; | |
2418 ntext=0; | |
2419 break; | |
2420 | |
2421 case KEY: | |
2422 if (!within_block) break; | |
2423 if (!within_tune) { | |
2424 tnum2++; | |
2425 if (is_selected (xref_str,npat,pat,select_all,search_field)) { | |
2426 printf (" %-4d %-5s %-4s", xrefnum, info.key, info.meter); | |
2427 if (search_field==S_SOURCE) printf (" %-15s", info.src… | |
2428 else if (search_field==S_RHYTHM) printf (" %-8s", info.rhy… | |
2429 else if (search_field==S_COMPOSER) printf (" %-15s", info.com… | |
2430 if (numtitle==3) | |
2431 printf (" %s - %s - %s", info.title,info.title2,info.title3… | |
2432 if (numtitle==2) printf (" %s - %s", info.title, info.title2); | |
2433 if (numtitle==1) printf (" %s", info.title); | |
2434 | |
2435 printf ("\n"); | |
2436 tnum1++; | |
2437 } | |
2438 within_tune=1; | |
2439 } | |
2440 break; | |
2441 | |
2442 } | |
2443 | |
2444 if (str_isblank(line)) { | |
2445 if (within_block && !within_tune) | |
2446 printf ("+++ Header not closed in tune %d\n", xrefnum); | |
2447 within_tune=0; | |
2448 within_block=0; | |
2449 info=default_info; | |
2450 } | |
2451 } | |
2452 if (within_block && !within_tune) | |
2453 printf ("+++ Header not closed in for tune %d\n", xrefnum); | |
2454 | |
2455 } | |
2456 | |
2457 | |
2458 | |
2459 | |
2460 |