parse.h - abc2ps - A powerful sheet setting tool using the simple abc notation
(HTM) git clone git://vernunftzentrum.de/abc2ps.git
(DIR) Log
(DIR) Files
(DIR) 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 length */
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 0; }
302 if (!strcmp(s,"treble+8")) {ks->ktype=TREBLE; ks->add_pitch=8; return 0; }
303 if (!strcmp(s,"alto+8")) {ks->ktype=ALTO; ks->add_pitch=8; return 0; }
304
305 if (!strcmp(s,"bass-8")) {ks->ktype=BASS; ks->add_pitch=-8; return 0; }
306 if (!strcmp(s,"treble-8")) {ks->ktype=TREBLE; ks->add_pitch=-8; return 0; }
307 if (!strcmp(s,"alto-8")) {ks->ktype=ALTO; ks->add_pitch=-8; return 0; }
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 %d\n",
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=+7;}
999 else if (!strcmp(t2,"treble-8")) {voice[j].key.ktype=TREBLE; ap=-7;}
1000 else if (!strcmp(t2,"treble+16")) {voice[j].key.ktype=TREBLE; ap=+14;}
1001 else if (!strcmp(t2,"treble-16")) {voice[j].key.ktype=TREBLE; ap=-14;}
1002 else if (!strcmp(t2,"bass")) voice[j].key.ktype=BASS;
1003 else if (!strcmp(t2,"bass+8")) {voice[j].key.ktype=BASS; ap=+7;}
1004 else if (!strcmp(t2,"bass-8")) {voice[j].key.ktype=BASS; ap=-7;}
1005 else if (!strcmp(t2,"bass+16")) {voice[j].key.ktype=BASS; ap=+14;}
1006 else if (!strcmp(t2,"bass-16")) {voice[j].key.ktype=BASS; ap=-14;}
1007 else if (!strcmp(t2,"alto")) voice[j].key.ktype=ALTO;
1008 else if (!strcmp(t2,"alto+8")) {voice[j].key.ktype=ALTO; ap=+7;}
1009 else if (!strcmp(t2,"alto-8")) {voice[j].key.ktype=ALTO; ap=-7;}
1010 else if (!strcmp(t2,"alto+16")) {voice[j].key.ktype=ALTO; ap=+14;}
1011 else if (!strcmp(t2,"alto-16")) {voice[j].key.ktype=ALTO; ap=-14;}
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 [|] invis */
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 bar */
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 ending */
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[i];
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)) isym++;
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.rhyth);
2429 else if (search_field==S_COMPOSER) printf (" %-15s", info.comp[0]);
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