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