//
// Programmer:    John Howard <John.B.Howard@asu.edu>
// Creation Date: A long time ago (circa 1990)
// Filename:      rmusic.c
// Syntax:        C
//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Filename:      pe2score.c
// Last Modified: Tue Aug 15 01:18:37 PDT 2006
//                Extracted core portions of rmusic.c for converting
//                Plaine & Easie music notation into SCORE input data.
// 
// Description:   Converts RISM entries into SCORE input data which
//                can be used to create graphical PostScript music
//                notation of incipits.
//
//

/*
   From: John B Howard [mailto:John_Howard@harvard.edu]
   Sent: Tuesday, February 10, 2004 2:37 AM
   To: esfield@stanford.edu
   Subject: Source code for RISM P&E to Score converter


   I'm attaching a zipped file with a couple ANSI C source code files that
   I used to convert RISM's P&E code to a Score input file. Unfortunately
   the documentation for these files is not easily accessible, but it should
   be possible to figure out the program operation and logic. The critical
   issue is probably the format of the input file.


   There were two possible formats that had to be dealt with:

   (1) SPIRES standard format, and I have at least a sample input file
   in the zip file of that.

   (2) The format used by the sequential data file on the RISM A/II CDROM.
   This file had tagged data on sequential lines that would not exceed 256
   bytes. Syntax was: three-digit field code followed by data; if a field
   exceeded 256 characters it would continue on the next line, with three
   space characters occupying the first three bytes of the continuation.
   (It might still be possible to run this against the data on the CDROM --
   one of the problems I had, however, was that RISM constantly changed
   their data standard and made 'enhancements' to the P&E encoding(which
   was also notoriously non-syntactical)).


   Choose the appropriate command-line flags and it should output as you
   specify -- they're explained in the source or output if the compiled
   program is run with no arguments. I typically would run it with first with
   the verbose option to identify problems without actually writing an output
   file. Another command-line flag controles whether Score output EPS files

   ... I found that I had to specify an absolute length for the incipit,
   otherwise the tool I used to convert the EPS files to bitmaps
   would vary the relative size of the images ... which was really ugly 
   to look at on screen!

*/


#include <stdio.h>
#include <string.h>
#include "Options.h"

#ifndef OLDCPP
   #include <sstream>
   #define SSTREAM stringstream
   #define CSTRING str().c_str()
   using namespace std;
#else
   #ifdef VISUAL
      #include <strstrea.h>     /* for windows 95 */
   #else
      #include <strstream.h>
   #endif
   #define SSTREAM strstream
   #define CSTRING str()
#endif


Options options;

void   spires2rism(FILE * ifp, FILE * ofp);
int    MakeKeySignature(char *s);
int    MakeTimeSignature(char *s);
int    MakeClef(char *s);
void   MakeOctave(char *s);
void   MakeRhythm(char *s);
void   lstr(char *s, int n);
void   rstr(char *s, int n);

char*  convertPe2ScoreInput(char* output, const char* input);
void   checkOptions(Options& opts, int argc, char* argv[]);
void   usage(const char* command);
void   example(void);
void   convert(SSTREAM& output, const char* input);


///////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv) {

   // process the command-line options
   checkOptions(options, argc, argv);

   char *data = NULL;

   if (options.getArgCount() != 1) {
      usage(options.getCommand());
      exit(1);
   } else {
      convertPe2ScoreInput(data, options.getArg(1));
   }

   std::cout << data << endl;

   return 0;
}


///////////////////////////////////////////////////////////////////////////

//////////////////////////////
//
// convertPe2ScoreInput -- convert a Plaine & Easie string of music
//    into SCORE input data which will be converted to PostScript
//    graphical music notation.
//

char* convertPe2ScoreInput(char *data, const char* input) {
   SSTREAM output;

   convert(output, input);
   
   output << ends;
   int length = strlen(output.CSTRING);
   data = new char[length+1];
   strcpy(data, output.CSTRING);

   return data;
}





///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


void convert(SSTREAM& output, const char* input) {

   char id[13], incipit_id[15];
   int verbose = 0;
   int tclef_flag;

   int  field_cnt = 0; 
   int  next_flag = 0; 
   int  startpos = 0;
   int  i = 0; 
   int  rc = 1; 
   int  err_cnt = 0; 
   int  w; 
   int  rism = 0; 
   int  beam_cnt = 0; 
   int  proof = 0;
   int  print_flag = 0; 
   int  beam_flag = 0; 
   int  format = 0;
   // extern int tclef_flag;
   int  wmn_flag = 0;
   char tmp[2056]; 
   char key_signature[26];
   int  TotalIncipits = 0; 
   int  TotalRecords = 0; 
   int  TotalErrors = 0;
   int  TotalErrorRecords = 0;
   char MusicOut[1028];
   char RhythmOut[562];
   char BeamsOut[256];
   char SlursOut[256];
   char ur_clef[18];
   char ur_timesig[18];
   char ur_keysig[18];
   char start_clef[18];
   char start_timesig[18];
   char start_keysig[18];
   char FileName[17];
   char MarksOut[128];
   char subdir[128];
   char library[56];
   char country[12];

   int c;

   strcpy(incipit_id, "1.1.1");
   strcpy(key_signature, "");

   i = 0;

   ++TotalRecords;
   i = 0;
   field_cnt = 1;
   next_flag = 0;

   // char* country = country code
   // char* library = library code

   // 789: Component incipit (music) 

   int incno = 0;
   int m_flag = 0;
   int Serr_flag = 0;
   char instrumentation[562];
   char role[256];
   char tempo[562];
   char text[1062];
   char clef[18];
   char timesig[18];
   char ur_music[1062];
   char music[1062];
   char comment[562];
   char inclen[5];
   char ex_music[1062];
   char keysig[24];
   char stitle[2056];
   char value[2056];

   strcpy(instrumentation, "");
   strcpy(role, "");
   strcpy(tempo, "");
   strcpy(text, "");
   strcpy(clef, "");
   strcpy(timesig, "");
   strcpy(music, "");
   strcpy(comment, "");
   strcpy(keysig, "");
   strcpy(stitle, "");
   strcpy(value, "");

   incno = 0;

   strcpy(timesig, "4/4");
   strcpy(clef, "G2");
   strcpy(ur_clef, clef);
   strcpy(start_clef, clef);
   strcpy(music, input);
   strcpy(ur_music, music);



/*- begin processing of incipits -*/

/*- process Score notes stage ... -*/

   int n, j, o, bar_cnt, cue_flag = 0, chord_flag =
      0, rep_flag = 0;
   char octave[3], note[3], accidental[3];
   char RepFigure[356]; 
   char LastClef[6]; 
   char symbol[12];
   char lastsymbol[12];

   wmn_flag = 0;

   strcpy(LastClef, clef);
   strcpy(ur_timesig, timesig);
   if ((w = MakeTimeSignature(timesig)) < 0) {
      printf
          ("RISM %s (%s): invalid time signature \"%s\"\n",
           id, incipit_id, timesig);
      ++err_cnt;
      Serr_flag = 1;
   }
   strcpy(start_timesig, timesig);
   strcpy(accidental, "");
   strcpy(MusicOut, "");
   strcpy(symbol, "");
   strcpy(lastsymbol, "");
   strcpy(keysig, "");
   strcpy(ur_keysig, "");

/*- But first, some proofreading ... -*/

   int t, beams, exclam, octaves, parens, graces, zrhythm;
   char rests[4];
   char reg[6];
   char duration[6];
   char temp[1028];

   strcpy(temp, "");
   strcpy(reg, "");
   strcpy(duration, "");
   strcpy(rests, "");
   zrhythm = 'z';
   exclam = 0;
   parens = 0;
   graces = 0;
   octaves = 0;
   beams = 0;
   bar_cnt = 1;

   int musiclength = strlen(music);
   for (n=0; n<musiclength; n++) {
      if (music[n] == '*' || music[n] == '%' ||        /* skip change of */
          music[n] == '@' || music[n] == '$') {        /* clef, etc.     */
         n++;
         while (music[n] != '*' || music[n] == ' ') {
            n++;
         }
         continue;
      }

      if (music[n] == ',' || music[n] == '\'') {
         octaves = 1;
         temp[0] = music[n];
         t = 1;
         while (music[n + 1] == ',' || music[n + 1] == '\'') {
            temp[t++] = music[n++];
         }
         temp[t] = '\0';
         if (strcmp(temp, reg) == 0 && (verbose == 1)) {
            cerr << "WARNING: redundant octave register symbol" 
                 << "( measure " << bar_cnt << ")"
                 << endl;
            continue;
         } else {
            strcpy(reg, temp);
            continue;
         }
      }

      if (music[n] == '{') ++beams;
      if (music[n] == '}') --beams;
      if (music[n] == '(') ++parens;
      if (music[n] == ')') --parens;
      if (music[n] == 'q' && music[n + 1] == 'q') {
         ++n;
         ++graces;
      }
      if (music[n] == 'r') --graces;
      if (music[n] == '!') {
         if (exclam == 0) ++exclam;
         else --exclam;
      }
      if (isdigit(music[n]) || music[n] == 'g') {
         zrhythm = music[n];
         temp[0] = music[n];
         t = 1;
         while (music[n + 1] == '.') temp[t++] = music[n++];
         temp[t] = '\0';
         if (strcmp(temp, duration) == 0
             && (verbose == 1)) {
            printf
                ("RISM %s (%s, measure %d): redundant duration "
                 "symbol\n", id, incipit_id, bar_cnt);
         } else strcpy(duration, temp);
         continue;
      }
      if (isupper(music[n]) || music[n] == '-') {
         if (zrhythm == 'z') {
            printf
                ("RISM %s (%s, measure %d): 1st note or rest "
                 "has no rhythm\n", id, incipit_id,
                 bar_cnt);
             zrhythm = '4';
             ++err_cnt;
             continue;
          }
          if (octaves == 0 && isupper(music[n])) {
            printf
                ("RISM %s (%s, measure %d): no octave register "
                 "at start of incipit\n", id,
                 incipit_id, bar_cnt);
            octaves = 4;
            err_cnt++;
            continue;
         }
      }
      if (music[n] == '/') {
         ++bar_cnt;
         if (parens > 0) {
            printf
                ("RISM %s (%s measure %d): chain brackets not "
                 "closed\n", id, incipit_id, bar_cnt);
            Serr_flag = 1;
            parens = 0;
            err_cnt++;
            continue;
         }
         if (parens < 0) {
            printf
                ("RISM %s (%s measure %d): open chain bracket "
                 "missing\n", id, incipit_id,
                 bar_cnt);
            Serr_flag = 1;
            parens = 0;
            err_cnt++;
            continue;
         }
         if (graces > 0) {
            printf
                ("RISM %s (%s measure %d): grace-note figure not "
                 "closed\n", id, incipit_id, bar_cnt);
            Serr_flag = 1;
            graces = 0;
            err_cnt++;
            continue;
         }
         if (graces < 0) {
            printf
                ("RISM %s (%s measure %d): improper start of grace-"
                 "note figure\n", id, incipit_id,
                 bar_cnt);
            /* Serr_flag = 1; */
            graces = 0;
            err_cnt++;
            continue;
         }

         if (exclam != 0) {
            printf
                ("RISM %s (%s measure %d): unexpected specification "
                 "of repeated figure\n", id,
                 incipit_id, bar_cnt);
            /* Serr_flag = 1; */
            exclam = 0;
            err_cnt++;
            continue;
         }
         if (music[n + 1] == '/')
            ++n;
         continue;
      }
      if (music[n] == '=') {
         int z;
         for (z = 0; isdigit(music[n + 1]); n++)
            rests[z++] = music[n + 1];
         if (z > 0) {
            rests[z] = '\0';
            bar_cnt = ((bar_cnt - 1) + (atoi(rests)));
            z = 0;
         }
      }
   } // end of proofreading loop 


   ///
   /// Score notes output stage ... 
   ///

   bar_cnt = 1;
   if (music[0] == '<') {   // other notation type 
      n = 3;
      // white mensural notation:
      if (music[0] == 'w') {
         wmn_flag = 1;
      }
   } else {
      n = 0;
   }

   for (; n <= (int)strlen(music); n++) {
      if (isdigit(music[n]) || music[n] == 't' ||
            music[n] == 'g' || music[n] == '.' ||
            music[n] == '{' || music[n] == '}'
            || music[n] == ')') {
         continue;
      }

      switch (music[n]) {
      case '!':                              // ! = repeated figures 
         strcpy(lastsymbol, "");
         if (rep_flag == 0) {                // start of figure
            strcpy(RepFigure, "");
            rep_flag = 1;
            continue;
         } else {                            // end figure 
            strcpy(lastsymbol, "");
            if (music[n + 1] != 'f') {       // error condition 
               Serr_flag = 1;
               err_cnt++;
               printf
                   ("RISM %s (%s, measure %d): repeated figure not "
                    "followed by \"f\"\n", id,
                    incipit_id, bar_cnt);
            } else {                         // expand figure 
               strcat(MusicOut, RepFigure);
               while (music[n + 1] == 'f') {
                  strcat(MusicOut, RepFigure);
                  ++n;
               }
               rep_flag = 0;
            }
         }
         continue;

      case ':':
         if (music[n + 3] == ':') {
            strcat(MusicOut, "/MRD");
            strcpy(lastsymbol, "/MRD");
            n = n + 3;
            continue;
         }
         if (music[n + 2] != '\x2f') {
            printf("RISM %s (%s, measure %d): invalid "
                   "encoding of repeat sign\n", id,
                   incipit_id, bar_cnt);
            err_cnt++;
            Serr_flag = 1;
         }
         strcat(MusicOut, "/ML");            // JBH change to /ML
         strcpy(lastsymbol, "/MxiLR");
         n = n + 2;
         continue;

      case '-':                              // rests 
         chord_flag = 0;
         if (rep_flag == 1) strcat(RepFigure, "/R");
         else {
            strcat(MusicOut, "/R");
            strcpy(lastsymbol, "/R");
         }
         continue;

      case '\x2f':                           // barlines 
         chord_flag = 0;
         ++bar_cnt;
         if (music[n + 1] == '\x2f'
             && music[n + 2] != ':') {
            strcat(MusicOut, "/MD");
            strcpy(lastsymbol, "/MD");
            n = n + 1;
            continue;
         }
         if (music[n + 1] == '\x2f'
             && music[n + 2] == ':') {
            strcat(MusicOut, "/MR");         // JBH change to MR
            strcpy(lastsymbol, "/MR");
            n = n + 2;
            continue;
         }
         if (rep_flag == 1) {
            printf
                ("RISM %s (%s, measure %d): repeated figure "
                 "spans the barline\n", id, incipit_id,
                 bar_cnt);
            err_cnt++;
            Serr_flag = 1;
         }
         strcat(MusicOut, "/M");
         strcpy(lastsymbol, "/M");
         continue;

      case 'q':                              // cue-sized notes 
         if (music[n + 1] == 'q') {
            ++n;
            cue_flag = 1;
            if (rep_flag == 1)
               strcat(RepFigure, "/SU/Q+");
            else {
               strcat(MusicOut, "/SU/Q+");
               strcpy(lastsymbol, "/SU/Q+");
            }
         }
         continue;

      case 'r':                              // end cue-sized notes
         cue_flag = 0;
         if (rep_flag == 1)
            strcat(RepFigure, "/Q0/SO");
         else {
            strcat(MusicOut, "/Q0/SO");
            strcpy(lastsymbol, "/Q0/SO");
         }
         continue;

      case '\'':
         for (j = 0; music[n] == '\''; n++) {
            octave[j++] = music[n];
         }
         octave[j] = '\0';
         --n;
         MakeOctave(octave);
         continue;

      case ',':
         for (j = 0; music[n] == ','; n++) {
            octave[j++] = music[n];
         }
         octave[j] = '\0';
         --n;
         MakeOctave(octave);
         continue;

      case 'n':
         accidental[0] = 'N';
         accidental[1] = '\0';
         continue;

      case 'b':
         accidental[0] = 'F';
         if (music[n + 1] == 'b') {
            ++n;
            accidental[1] = 'F';
            accidental[2] = '\0';
         } else {
            accidental[1] = '\0';
         }
         continue;

      case 'x':
         accidental[0] = 'S';
         if (music[n + 1] == 'x') {
            ++n;
            accidental[1] = 'S';
            accidental[2] = '\0';
         } else {
            accidental[1] = '\0';
         }
         continue;

      case '=':
         chord_flag = 0;
         if (music[n + 1] == '\x2f') {
            strcat(MusicOut, "/RW");
            strcpy(lastsymbol, "/RW");
            continue;
         }
         for (o = 0; isdigit(music[n + 1]);) {
            tmp[o++] = music[++n];
         }
         tmp[o] = '\0';
         strcat(strcat(MusicOut, "/R"), tmp);
         strcat(strcpy(lastsymbol, "/R"), tmp);
         bar_cnt = (bar_cnt + (atoi(tmp) - 1));
         continue;

      case 'i':
         chord_flag = 0;
         strcat(MusicOut, "/RP");
         strcpy(lastsymbol, "/RP");
         continue;

      case '(':
         if (music[n + 1] == '=' && music[n + 2] == ')') {
            strcat(MusicOut, "/RF");
            strcpy(lastsymbol, "/RF");
            n = n + 2;
            continue;
         }
         if (music[n + 1] == '-' && music[n + 2] == ')') {
            strcat(MusicOut, "/RF");
            strcpy(lastsymbol, "/RF");
            n = n + 2;
            continue;
         }
         continue;

      case ';':                                // tuplet number
         while (isdigit(music[++n]));
         continue;

      case '^':                                // U.S. RISM chords
         if (rep_flag == 1) {
            strcat(RepFigure, ":");
            chord_flag = 1;
         } else {
            chord_flag = 1;
            strcat(MusicOut, ":");
            strcat(lastsymbol, ":");           // chg from strcpy -- JBH
         }                                     // so chords won't repeat
         continue;

      case '%':                                // change of clef
         chord_flag = 0;
         for (o = 0; music[++n] != ' ';) {
            clef[o++] = music[n];
         }
         clef[o] = '\0';
         if (MakeClef(clef) < 0) {
            printf
                ("RISM %s (%s, measure %d): invalid clef \"%s\"\n",
                 id, incipit_id, bar_cnt, clef);
            ++err_cnt;
            Serr_flag = 1;
            continue;
         }
         if (strcmp(clef, LastClef) != 0) {
            strcpy(LastClef, clef);
            if (rep_flag == 1)
               strcat(strcat(RepFigure, "/"), clef);
            else {
               strcat(strcat(MusicOut, "/"), clef);
               strcpy(lastsymbol, clef);
            }
         }
         continue;

      case '@':                                // change of time signature
         chord_flag = 0;
         for (o = 0; music[++n] != ' ';) {
            timesig[o++] = music[n];
         }
         timesig[o] = '\0';
         if ((w = MakeTimeSignature(timesig)) < 0) {
            printf("RISM %s (%s): invalid time signature \"%s\"\n", 
			id, incipit_id, timesig);
            ++err_cnt;
            Serr_flag = 1;
         }
         if (rep_flag == 1)
            strcat(RepFigure, timesig);
         else {
            strcat(MusicOut, timesig);
            strcpy(lastsymbol, "XXX");
         }
         continue;

      case '$':                                // change of key signature
         chord_flag = 0;
         for (o = 0; music[++n] != ' ';) {
            keysig[o++] = music[n];
         }
         keysig[o] = '\0';
         MakeKeySignature(keysig);
         if (strlen(keysig) > 0) {             // if there's a key signature
            if (rep_flag == 1)
               /* August 1996: don't need the slash */
               /* strcat(strcat(RepFigure,"/"),keysig); */
               strcat(RepFigure, keysig);
            else {
               strcat(MusicOut, keysig);
               strcpy(lastsymbol, keysig);
            }
         }
         continue;

      case '[':
              /*- used with barlines only! -*/
         if (music[n + 2] != ']' && music[n + 1] != '/') {
            printf
                ("RISM %s: unexpected use of brackets\n",
                 id);
            err_cnt++;
            continue;
         }
         if (rep_flag == 1) {
            printf("RISM %s (%s, measure %d): repeated "
                   "figure spans more than one measure\n",
                   id, incipit_id, bar_cnt);
            err_cnt++;
            Serr_flag = 1;
         }
         strcat(MusicOut, "/MS");
         strcpy(lastsymbol, "/MS");
         ++n;
         continue;
      } // end of switch 

      if (isupper(music[n])) {       // notes
         note[0] = music[n];
         note[1] = '\0';
         if (rep_flag == 0) {
            strcat(strcat (strcpy(symbol, note), accidental), octave);
            if (strcmp(symbol, lastsymbol) == 0 && music[n + 1] != '^'
                && chord_flag == 0) {
               strcat(MusicOut, "/");
            } else {
               if (chord_flag == 0) {
                  strcat(strcat(MusicOut, "/"), symbol);
                  strcat(lastsymbol, "");              // JBH
               } else {
                  strcat(MusicOut, symbol);
                  chord_flag = 0;
                  strcpy(lastsymbol, "XXX");           // JBH - chg fr symbol
               }
            }
            strcpy(accidental, "");
         } else {
            if (chord_flag == 0) {
               strcat(strcat(RepFigure, "/"), note);
            } else {
               strcat(RepFigure, note);
               chord_flag = 0;
            }
            strcat(strcat(RepFigure, accidental),
                   octave);
            strcpy(accidental, "");
         }
      }
   }


   // now clean pitch stage data ...

   int LastOctave = 0;
   strcpy(tmp, MusicOut);
   strcpy(MusicOut, "");
   for (n = 0, j = 0; n <= (int)strlen(tmp); n++) { // avoid counting rests as 
                                               // octave registers 
      if (tmp[n] == 'R' && isdigit(tmp[n + 1])) {
         MusicOut[j++] = tmp[n++];
         while (isdigit(tmp[n]))
            MusicOut[j++] = tmp[n++];
         --n;
         continue;
      }
      if (isdigit(tmp[n])) {
         if (tmp[n + 1] == ' ' || tmp[n - 1] == ' '
             || tmp[n + 2] == ' ') {
            MusicOut[j++] = tmp[n];
            continue;
         }
         if (tmp[n] == LastOctave) {
            continue;
         } else {
            LastOctave = tmp[n];
         }
      }
      MusicOut[j++] = tmp[n];
   }


   MusicOut[j] = '\0';
   strcat(strcat(strcpy(tmp, start_clef), start_keysig),
          start_timesig);
   strcat(tmp, MusicOut);
   strcat(strcpy(MusicOut, tmp), "/MI;");


   // end Score notes stage 

   // process Score rhythm stage ... 




   cue_flag = 0;
   rep_flag = 0; 
   int TupletCnt = 0;

   int grace_flag = 0;
   int tuplet_flag = 0; 
   int pc = 0;

   char rhythm[6][6];

   strcpy(RhythmOut, "");
   for (n = 0; n <= (int)strlen(music); n++) {
      if (music[n] == 't' ||
          music[n] == '{' || music[n] == '}'
          || music[n] == ':' || music[n] == 'x'
          || music[n] == 'b' || music[n] == 'n'
          || music[n] == '+' || music[n] == '\''
          || music[n] == ',' || music[n] == '['
          || music[n] == ']' || music[n] == '\x2f') {
         continue;
      }
      /* if (isdigit(music[n])) { */
      if (rc == 1)
         pc = 0;
      if (rc > 1 && pc < rc)
         ++pc;
      if (rc > 1 && pc == rc)
         pc = 0;
      if (isdigit(music[n])) {
         for (pc = 0, rc = 0; isdigit(music[n]);
              pc++, rc++, n++) {
            if (music[n + 1] == '(' && music[n + 3] != ')' && music[n + 4] != ')') {
                              /*- tuplets -*/
               TupletCnt = music[n];
               pc = 0;
               continue;
            }
            rhythm[pc][0] = music[n];
            rhythm[pc][1] = '\0';
            MakeRhythm(rhythm[pc]);
            while (music[n + 1] == '.') {
               strcat(rhythm[pc], ".");
               ++n;
            }
         }
         --n;
         continue;
      }

      if (isupper(music[n]) || music[n] == '-') {
                                      /*- note values -*/
         if (rep_flag == 0) {
            if (tuplet_flag == 0) {
               if (grace_flag == 0) {
                  if (cue_flag == 1)
                     strcat(strcat(RhythmOut, "/"), "G");
                  else
                     strcat(strcat(RhythmOut, "/"),
                            rhythm[pc]);
               } else {
                  if (cue_flag == 0)
                     grace_flag = 0;
                  strcat(RhythmOut, "/G");
               }
               continue;
            } else {
              /*- tuplet_flag == 1 -*/
               if (grace_flag == 0) {
                  if (rhythm[pc][0] == '3'
                      && rhythm[pc][1] == '2')
                     strcat(RhythmOut, "/48");
                  else
                     strcat(strcat(RhythmOut, "/T"),
                            rhythm[pc]);
               } else {
                  if (cue_flag == 0)
                     grace_flag = 0;
                  strcat(RhythmOut, "/G");
               }
               continue;
            }
         } else {
            if (tuplet_flag == 0) {
               if (grace_flag == 0)
                  strcat(strcat(RepFigure, "/"),
                         rhythm[pc]);
               else {
                  if (cue_flag == 0)
                     grace_flag = 0;
                  strcat(RepFigure, "/G");
               }
            } else {
               strcat(strcat(RepFigure, "/T"),
                      rhythm[pc]);
            }
            continue;
         }
      }
      if (music[n] == '%' || music[n] == '@'
          || music[n] == '$') {
         while (music[++n] != ' ');
         continue;
      }

      switch (music[n]) {
      case '^':
         for (; n <= (int)strlen(music); n++) {
            if (isupper(music[n]))
               break;
         }
         continue;

      case 'g':
         grace_flag = 1;
         continue;

      case '!':                                        // repeated figures 
             ;
         if (rep_flag == 0) {                          // start figure 
            strcpy(RepFigure, "");
            rep_flag = 1;
         } else {                                      // end figure 
                                                       // expand figure 
            strcat(RhythmOut, RepFigure);
            while (music[n + 1] == 'f') {
               strcat(RhythmOut, RepFigure);
               ++n;
            }
            rep_flag = 0;
         }
         continue;

      case '(':
         if (music[n + 1] == '-') {
            if (rep_flag == 0) {
               strcat(strcat(RhythmOut, "/"),
                      rhythm[pc]);
               n = n + 2;
               continue;
            } else {
               strcat(strcat(RepFigure, "/"),
                      rhythm[pc]);
               n = n + 2;
               continue;
            }
         } else if (music[n + 1] == '=') {
            strcat(RhythmOut, "/H");
            n = n + 2;
            continue;
         }   // so it must be a tuplet figure ... 
         if (music[n + 2] != ')' && music[n + 3] != ')')
            tuplet_flag = 1;
         continue;

      case 'q': // cue-sized notes 
         if (music[n + 1] != 'q') { // appogiatura 
            if (rep_flag == 0) {
               strcat(RhythmOut, "/G");
            } else {
               strcat(RepFigure, "/G");
            }
            // move to the note it applies to ... 
            // Dec. 24, 1995: this code prevents value
            // of the appogiature from being passed on ... 

            for (++n, j = 0; n <= (int)strlen(music); n++) {
               if (isdigit(music[n])) {
                  rhythm[pc][0] = music[n];
                  rhythm[pc][1] = '\0';
                  MakeRhythm(rhythm[pc]);
                  while (music[n + 1] == '.') {
                     strcat(rhythm[pc], ".");
                     n++;
                  }
               }
               if (isupper(music[n])) {
                  break;
               }
            }
            continue;
         } else {                        // qq ... r construction 
            ++n;
            grace_flag = 1;              // JBH98
            cue_flag = 1;
         }
         continue;

      case 'r':                         // end cue-sized notes
         cue_flag = 0;
         grace_flag = 0; // JBH98 
         continue;

      case '=':
         while (isdigit(music[n + 1]))
            ++n;
         strcat(RhythmOut, "/W");
         continue;

      case 'i':
         strcat(RhythmOut, "/W");
         continue;

      case ';':                              // tuplet number 
         tuplet_flag = 0;
         while (isdigit(music[++n]));
         continue;

      case ')':
         if (tuplet_flag == 1)
            tuplet_flag = 0;
         continue;

      case '[':                             // used with barlines only! 
         continue;

      } // end of switch 

   }

   for (o = 0, j = 0; o <= (int)strlen(RhythmOut); o++) {
      if (o > 0) {
         temp[j++] = RhythmOut[o];
      }
   }
   temp[j] = '\0';
   strcpy(RhythmOut, temp);
   strcat(RhythmOut, ";");



   // end Score rhythm stage 


   // expand the incipit 

printf("GOT HERE J9\n");

   int p, q, r;

   for (n = 0, o = 0, p = 0; n <= (int)strlen(music); n++) {
      if (music[n] == '^') {
         for (; n <= (int)strlen(music); n++) {
            if (isupper(music[n])) {
               break;
            }
         }
         continue;
      }
      if (music[n] == '!') {
         for (++n, p = 0; n <= (int)strlen(music); n++) {
            if (music[n] == '!') {
               break;
            } else {
               if (music[n] == '%' || music[n] == '@' ||
                   music[n] == '$') {
                  while (music[++n] != ' ');
                  continue;
               }
               if (music[n] == '^') {                // JBH, Jan 2 1996 
                  for (; n <= (int)strlen(music) && music[n] != '!'; n++) {
                     if (isupper(music[n])) {
                     ++n;
                     break;
                  }
               }
            }  /*= IF -*/
            RepFigure[p++] = music[n];
            ex_music[o++] = music[n];
         }
      }
      RepFigure[p] = '\0';
      while (music[++n] == 'f') {
         for (r = 0; r < (int)strlen(RepFigure); r++) {
            ex_music[o++] = RepFigure[r];
         }
      }
      strcpy(RepFigure, "");
      --n;                                           // bug fix, Dec 16 1995
      continue;
   }
   if (music[n] == '%' || music[n] == '@' ||
       music[n] == '$' || music[n] == '*') {
      ++n;
      while (music[n] != ' ' && music[n] != '*'
             && music[n] != '\0')
         ++n;
      continue;
   }
   ex_music[o++] = music[n];

} /*- FOR -*/


   ex_music[o] = '\0';
   strcpy(tmp, music);
   strcpy(music, ex_music);
   strcpy(ex_music, tmp);




   // process Score marks stage (fermatas, trills, etc.) 


   int NoteCnt = 0;
   char place[6];

         /*- keep only notes and marks -*/

   strcpy(MarksOut, "");
   for (n = 0, o = 0; n <= (int)strlen(music); n++) {
      if (isupper(music[n]) || music[n] == '('
          || music[n] == 't' || music[n] == ')'
          || music[n] == '-' || music[n] == '=') {
         temp[o++] = music[n];
      }
   }
   temp[o] = '\0';
   for (n = 0; n <= (int)strlen(temp); n++) {
      if (isupper(temp[n])) {
         ++NoteCnt;
         continue;
      }
      if (temp[n] == 't') {
         if ((int)strlen(MarksOut) > 0) {
            strcat(MarksOut, "/");
         }
         strcat(MarksOut, "TR ");
         sprintf(place, "%d", NoteCnt);
         strcat(MarksOut, place);
         continue;
      }
      if (temp[n] == '(') {
         if (temp[n + 1] == '-' || temp[n + 1] == '=') {
            continue;
         }
         if (temp[n + 2] == ')') {
            if ((int)strlen(MarksOut) > 0) {
               strcat(MarksOut, "/");
            }
            strcat(MarksOut, "FE ");
            sprintf(place, "%d", NoteCnt + 1);
            strcat(MarksOut, place);
         }
      }
   }
   strcat(MarksOut, ";");

   // end Score marks stage 

   // process Score beams stage 


   int beams_flag = 0; 
   cue_flag = 0;
   NoteCnt = 0;
   char CueBeamsOut[256];

   beam_cnt = 0;
   bar_cnt = 1;
   strcpy(BeamsOut, "");
   strcpy(CueBeamsOut, "");
   for (n = 0, o = 0; n <= (int)strlen(music); n++) {
      if (isupper(music[n]) || music[n] == '{'
          || music[n] == '/' || isdigit(music[n])
          || music[n] == '=' || music[n] == '}'
          || music[n] == 'r' || music[n] == 'q') {
         temp[o++] = music[n];
      }
   }
   temp[o] = '\0';
   for (n = 0; n <= (int)strlen(temp); n++) {
      if (isdigit(temp[n])) {
         zrhythm = temp[n];
         continue;
      }
         
      if (temp[n] == '/') {
         if (beams_flag < 0) {
            printf
                ("RISM %s (%s, measure %d): start beam symbol "
                 "\"{\" wanting\n", id, incipit_id,
                 bar_cnt);
            err_cnt++;
            /* Serr_flag = 1; *//* changed to accommodate 20th-cent. */
         } /* December 1996 -- JBH */
         else if (beams_flag > 0) {
            printf("RISM %s (%s, measure %d): end beam "
                   "symbol \"}\" wanting\n", id,
                   incipit_id, bar_cnt);
            err_cnt++;
            /* Serr_flag - 1; */
         }
         if (temp[n + 1] == '/')
            ++n;
         beams_flag = 0;
         ++bar_cnt;
         continue;
        
         if (temp[n] == 'q' && temp[n + 1] == 'q') {
            cue_flag = 1;
            if ((int)strlen(CueBeamsOut) > 0) {
               strcat(CueBeamsOut, "/");
            }
            sprintf(place, "%d", NoteCnt + 1);
            strcat(strcat(CueBeamsOut, place), " ");
            beams_flag++;
            beam_cnt++;
            continue;
         }
         if (temp[n] == 'r') {
            cue_flag = 0;
            beams_flag--;
            sprintf(place, "%d", NoteCnt);
            strcat(CueBeamsOut, place);
            continue;
         }
         if (isupper(temp[n])) {
            ++NoteCnt;
            if (beams_flag > 0) {
               if (zrhythm == '1' || zrhythm == '2'
                   || zrhythm == '4' || zrhythm == '9'
                   || zrhythm == '0') {
                  printf
                      ("RISM %s (%s, measure %d): invalid rhythm "
                       "in beamed group\n", id, incipit_id,
                       bar_cnt);
                  Serr_flag = 1;
                  err_cnt++;
                  zrhythm = '8';
               }
            }
            continue;
         }
         if (temp[n] == '=') {
            int z;
            for (z = 0; isdigit(temp[n + 1]); n++)
               rests[z++] = temp[n + 1];
            if (z > 0) {
               rests[z] = '\0';
               bar_cnt = ((bar_cnt - 1) + (atoi(rests)));
               z = 0;
            }
            continue;
         }
         if (temp[n] == '{') {
            if (cue_flag == 0) {
               if ((int)strlen(BeamsOut) > 0) {
                  strcat(BeamsOut, "/");
               }
               sprintf(place, "%d", NoteCnt + 1);
               strcat(strcat(BeamsOut, place), " ");
               beams_flag++;
               beam_cnt++;
               continue;
            } else {
               continue;
            }
         }
         if (temp[n] == '}') {
            if (cue_flag == 0) {
               sprintf(place, "%d", NoteCnt);
               strcat(BeamsOut, place);
               beams_flag--;
               continue;
            } else {
               continue;
            }
            
      }


      if (beams_flag > 0) {
         printf
             ("RISM %s (%s): end beam symbol \"}\" wanting in "
              "last measure\n", id, incipit_id);
         err_cnt++;
         // Serr_flag = 1; -- JBH98
      } else if (beams_flag < 0) {
         printf
             ("RISM %s (%s): start beam symbol \"{\" wanting in "
              "last measure\n", id, incipit_id);
         err_cnt++;
         // Serr_flag = 1; --JBH98 
      }
      if ((int)strlen(BeamsOut) > 0 && (int)strlen(CueBeamsOut) > 0) {
         strcat(BeamsOut, "/");
      }
      strcat(strcat(BeamsOut, CueBeamsOut), ";");

   // end Score beams stage 

   // process Score slurs stage (ties & tuplets) 


   int n, o, NoteCnt = 0, f_flag = 0, r_flag = 0;
   char place[6], temp[562], StartTuplet[6],
      EndTuplet[6], TupletType[3];

   strcpy(SlursOut, "");
   for (n = 0, o = 0; n <= (int)strlen(music); n++) {
      if (isdigit(music[n]) || isupper(music[n]) ||
         music[n] == '+' || music[n] == '('
         || music[n] == '-' || music[n] == ')'
         || music[n] == ';' || music[n] == '=') {
         temp[o++] = music[n];
      }
   }
   temp[o] = '\0';



   // process ties 

   for (n = 0; n <= (int)strlen(temp); n++) {
      if (isupper(temp[n])) {
         ++NoteCnt;
         continue;
      }
      if (temp[n] == '+') {                                // a tie 
         if (strlen(SlursOut) > 0) {
            strcat(SlursOut, "/");
         }
         sprintf(place, "%d", NoteCnt);
         strcat(strcat(SlursOut, place), " ");
         if (n + 1 == (int)strlen(temp) || n == (int)strlen(temp)) {
            strcat(strcat(SlursOut, place), ".99");
         } else {
            sprintf(place, "%d", NoteCnt + 1);
            strcat(SlursOut, place);
         }
      }
   } 


   // process tuplets 

   NoteCnt = 0;
   for (n = 0; n <= (int)strlen(temp); n++) {
      if (isupper(temp[n])) {
         ++NoteCnt;
         continue;
      }
      if (temp[n] == '(') {
         if (temp[n + 2] == ')' || temp[n + 1] == '=') {
            f_flag = 1;
            continue;
         }
         if (temp[n + 1] == '-' || (isdigit(temp[n + 1]) && temp[n + 2] == '-')
               || (isdigit(temp[n + 1]) && temp[n + 2] == '.'
               && temp[n + 3] == '-')) {
            r_flag = 1;
         }
         if (r_flag == 0) {
            sprintf(StartTuplet, "%d", NoteCnt + 1);
         } else {
            const char *fraction = ".9";
            /*- JBH: 2 Jan 96, was ".8" -*/
            printf ("RISM %s: tuplet figure begins with a rest !!\n", id);
            sprintf(StartTuplet, "%d%s", NoteCnt - 1, fraction);
            r_flag = 0;
         }
         continue;
      }

      if (temp[n] == ';') {
                      /*- tuplet type -*/
         TupletType[0] = temp[n + 1];
         TupletType[1] = '\0';
      }
      if (temp[n] == ')') {
         if (f_flag == 1) {
            f_flag = 0;
            continue;
         }
         sprintf(EndTuplet, "%d", NoteCnt);

         // write the output

         if ((int)strlen(SlursOut) > 0) {
            strcat(SlursOut, "/");
         }
         if ((int)strlen(TupletType) == 0) {
            strcat(SlursOut, "3");
         } else {
            strcat(SlursOut, TupletType);
            strcpy(TupletType, "");
         }
         if (atoi(StartTuplet) < 10) {
            strcat(SlursOut, "0");
         }
         strcat(SlursOut, StartTuplet);
         if (r_flag == 1) {
            strcat(SlursOut, ".8");
         }
         strcat(SlursOut, " ");
         strcat(strcat(SlursOut, "+"), EndTuplet);
         r_flag = 0;
      }

   }

   strcat(SlursOut, ";");

   // end Score slurs stage 


   // determine width of musical notation on staff 

   for (n = 0, o = 0; n <= (int)strlen(music); n++) {
      if (isupper(music[n])) {
         tmp[o++] = music[n];
      }
   }
   tmp[o] = '\0';
   n = strlen(tmp);
   if (n > 24) strcpy(inclen, "195");
   else if (n > 22) strcpy(inclen, "185");
   else if (n > 20) strcpy(inclen, "175");
   else if (n > 17) strcpy(inclen, "160");
   else if (n > 15) strcpy(inclen, "150");
   else if (n > 13) strcpy(inclen, "140");
   else if (n > 10) strcpy(inclen, "130");
   else if (n > 7)  strcpy(inclen, "120");
   else if (n > 5)  strcpy(inclen, "110");
   else             strcpy(inclen, "100");




   TotalErrors = (TotalErrors + err_cnt);
   if (err_cnt > 0 || Serr_flag == 1)
      ++TotalErrorRecords;
   if (Serr_flag == 1) {
      printf("- processing aborted\n");
      Serr_flag = 0;
      goto vinit;
   }

   if (rism == 0) {
      strcpy(FileName, id);
      if (incno < 100)            /*- August 1996: allow for > 99 incipits */
         sprintf(tmp, "%.2d", incno);
      else
         sprintf(tmp, "%.3d", incno);
      strcat(FileName, tmp);
      rstr(FileName, 5);
      strcpy(subdir, library);
   } else {                /*- data from Zentralredaktion -*/
      strcpy(tmp, id);
      lstr(tmp, 3);
      strcat(strcpy(subdir, library), "\\");
      strcat(subdir, tmp);
      strcpy(tmp, id);
      rstr(tmp, 3);
      strcpy(FileName, tmp);
      if (incno < 100)
         sprintf(tmp, "%.2d", incno);
      else
         sprintf(tmp, "%.3d", incno);
      strcat(FileName, tmp);
   }

   if (proof == 0) {
      output << "-- RISM " << id << " (" << incipit_id
             << ") -----------------------------------------\n";

      output << "-> [clef:] " << ur_clef 
             << "\t [key signature:] " << ur_keysig 
             << "\t [time signature:] " << ur_timesig << "\n";

      output << "-> " << ur_music << "\n";
      output << "IN 1\n";
      output << "1.5 " << inclen << " 1\n";
      output << MusicOut  << "\n";
      output << RhythmOut << "\n";
      output << MarksOut  << "\n";
      output << BeamsOut  << "\n";
      output << SlursOut  << "\n";

      if (beam_flag == 1) {        // add score info to thin beams 
         int u = 0;
         output << "ST 1 6\n";
         for (; u < beam_cnt; u++) output << "17/.8\n\n";
         output << "\n";
      }

      if (tclef_flag == 1) {        // make the vocal tenor clef
         output << "ST 1 3\n5/.8\n\n";
         tclef_flag = 0;
      }
      if (format > 0) {
         /* August 1996: get rid of CW1 in output */
         output << "J\n1\n\n\nCW1\nSTM\nZ\n";
         output << "CD \\" << country << "\\" << subdir << "\n";
         output << "SA " << FileName << "\n";

         if (print_flag == 0) {
            output << "RS\nY\n";
         }
      } else {

         output << "ST 1 8\n6/" << atoi(inclen)+2 << "\n";
         output << "\nJ\n1\n\n\nCW1\nSTM\nZ\n";
         output << "CD \\rism\\" << country << "\\" << subdir << "\n";
         output << "SA " << FileName << "\n";

         if (print_flag == 0) {
            output <<  "RS\nY\n";
         }
      }
      if (print_flag == 1) {
         if (rism == 0) output << "CD \\RISM\\temp\nPR\n";
         else output << "PR\n";

         if (format == 0) {
            output << ".42\n";
         } else if (format == 1) {
            output << ".65\n";
         } else {
            output << ".5\n";
         }
         output << "\n\n1 -2\nP\n" << FileName << "\nRS\nY\n";
      }
   }

   // end of "if (proof == 0)" block 

   // reset varibles 

vinit:
   m_flag = 0;
   strcpy(instrumentation, "");
   strcpy(role, "");
   strcpy(tempo, "");
   strcpy(text, "");
   strcpy(clef, "");
   strcpy(timesig, "");
   strcpy(music, "");
   strcpy(comment, "");
   strcpy(keysig, "");
   strcpy(stitle, "");
   strcpy(start_keysig, "");
   strcpy(ur_keysig, "");
   strcpy(value, "");


   // end processing of incipits 

   // re-initialize selected variables 

   startpos = 0;
   err_cnt = 0;


   printf("==========================================================================\n");
   printf("\n        **** Statistics for RMUSIC processing run ****\n\n");
   printf("\tRecords processed:\t%d\n", TotalRecords);
   printf("\tIncipits processed:\t%d\n", TotalIncipits);
   printf("\tErrors detected:\t%d in %d records\n", TotalErrors,
             TotalErrorRecords);


   return  the data string here
}     



////////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// spires2rism --
//

void spires2rism(FILE * ifp, FILE * ofp) {

   int c, q_flag = 0, s_flag = 0;
   int i = 0;
   int rc = 0;

   while ((c = getc(ifp)) != EOF) {
      if (c == ' ') {
         if (s_flag == 0) {
            continue;
         } else {
            putc(' ', ofp);
            while ((c = getc(ifp)) == ' ') {
               ;
            }
         }
      }
      if (c == '\"') {
         if (q_flag == 1) {
            if ((c = getc(ifp)) == '\"') {
               putc(c, ofp);
               s_flag = 1;
            } else {
               q_flag = 0;
               s_flag = 0;
               putc('\n', ofp);
               (c = getc(ifp));
            }
         } else {
            q_flag = 1;
            s_flag = 1;
         }
         continue;
      }
      if (c == ';') {
         if (q_flag == 1) {
            putc(c, ofp);
            s_flag = 1;
         } else {
            putc('\n', ofp);
            s_flag = 0;
            (c = getc(ifp));
         }
         continue;
      }
      if (c == '\n') {
         putc(' ', ofp);
         continue;
      }
      putc(c, ofp);
      s_flag = 1;
   }

}



//////////////////////////////
//
// MakeOctave --
//

void MakeOctave(char *s) {
   char *octavein[] = {
      "\'", "\'\'", "\'\'\'", "\'\'\'\'", "\'\'\'\'\'",
      ",", ",,", ",,,", ",,,,"
   };
   char *octaveout[] = {
      "4", "5", "6", "7", "8",
      "3", "2", "1", "0"
   };
   extern char id[];
   int i;

   for (i = 0; i <= 8; i++) {
      if (strcmp(s, octavein[i]) == 0) {
         strcpy(s, octaveout[i]);
         return;
      }
   }
   printf("RISM %s: strange octave register symbol -> %s\n", id, s);
   return;

}



//////////////////////////////
//
// MakeRhythm --
//

void MakeRhythm(char *s) {
   char *rhythmin[] = {
      "1", "2", "4", "8", "6", "3", "5", "7", "9", "0"
   };
   char *rhythmout[] = {
      "W", "H", "Q", "E", "S", "32", "64", "128", "DW", ".25"
   };
   extern char id[];
   int i;

   for (i = 0; i <= 9; i++) {
      if (strcmp(s, rhythmin[i]) == 0) {
         strcpy(s, rhythmout[i]);
         return;
      }
   }
   return;

}



//////////////////////////////
//
// MakeKeySignature --
//

int MakeKeySignature(char *s) {
   char *keyin[] = {
      "bB", "bBE", "bBEA", "bBEAD", "bBEADG", "bBEADGC", "bBEADGCF",
      "xF", "xFC", "xFCG", "xFCGD", "xFCGDA", "xFCGDAE", "xFCGDAEB"
   };
   char *keyout[] = {
      "/K1F", "/K2F", "/K3F", "/K4F", "/K5F", "/K6F", "/K7F",
      "/K1S", "/K2S", "/K3S", "/K4S", "/K5S", "/K6S", "/K7S"
   };

   int i, o;
   extern char id[];
   char tmp[12];

        /*- eliminate brackets and ampersand -*/

   for (i = 0, o = 0; i <= (int)strlen(s); i++) {
      if (s[i] == '[' || s[i] == ']' || s[i] == '&') {
         continue;
      }
      tmp[o++] = s[i];
   }
   tmp[o] = '\0';
   strcpy(s, tmp);

   if (tmp[0] == 'n') {                /* make natural signs */
      strcpy(s, "");
      return;
   }

   for (i = 0; i <= 14; i++) {
      if (strcmp(s, keyin[i]) == 0) {
         strcpy(s, keyout[i]);
         return 1;
      }
   }
   return -1;


}   


//////////////////////////////
//
// MakeClef --
//

int MakeClef(char *s) {
   char *clefin[] = {
      "G-2", "C-1", "F-4", "C-3", "C-4", "G-1", "F-3", "F-2",
      "C-2", "C-5", "G-3"
   };
   char *clefout[] = {
      "TR", "TR", "BA", "AL", "TE", "TR", "BA", "BA",
      "TR", "BA", "TE"
   };

   int i, o;
   extern char id[];
   extern int tclef_flag;
   char tmp[12];

   // eliminate brackets 

   for (i = 0, o = 0; i <= (int)strlen(s); i++) {
      if (s[i] == '[' || s[i] == ']') {
         continue;
      }
      tmp[o++] = s[i];
   }
   tmp[o] = '\0';
   strcpy(s, tmp);

   if (s[0] == 'g') {                // vocal tenor clef
      tclef_flag = 1;
      strcpy(s, "G-2");
   }

   if (s[1] == '+') {                // mensural notation 
      s[1] = '-';
      if (s[2] == '5')
         s[2] = '4';
      if (verbose == 1) {
         printf("RISM %s: mensural notation is called for!\n", id);
      }
   }

   for (i = 0; i <= 10; i++) {
      if (strcmp(s, clefin[i]) == 0) {
         strcpy(s, clefout[i]);
         return 1;
      }
   }
   return -1;


}



//////////////////////////////
//
// MakeTimeSignature --
//

int MakeTimeSignature(char *s) {
   char *timein[] = {
      "c", "c/", "o", "o/", "&C", "&alla;",
      "3/1", "2/1", "4/1", "6/1", "8/1", "2/2", "3/2", "4/2",
      "6/2", "8/2", "2/4", "3/4", "4/4", "5/4", "6/4",
      "7/4", "8/4", "9/4", "10/4", "2/8", "3/8", "4/8",
      "5/8", "6/8", "8/8", "9/8", "12/8", "16/8", "8/16",
      "6/16", "9/16", "12/16", "16/16", "20/4", "20/16", "24/16",
      "12/4", "1/4", "10/2", "c3/2", "c3", "c/3",
      "38/4", "c2", "c/2", "1/2", "3", "2", "4", "1", "0",
      "c/3/1", "c/3/2", "c/6/4", "c6/4", ""
   };
   char *timeout[] = {
      "/COM", "/CUT", "/3 1", "/3 2", "/COM", "/CUT",
      "/3 1", "/2 1", "/4 1", "/6 1", "/8 1", "/2 2", "/3 2", "/4 2",
      "/6 2", "/8 2", "/2 4", "/3 4", "/4 4", "/5 4", "/6 4",
      "/7 4", "/8 4", "/9 4", "/10 4", "/2 8", "/3 8", "/4 8",
      "/5 8", "/6 8", "/8 8", "/9 8", "/12 8", "/16 8", "/8 16",
      "/6 16", "/9 16", "/12 16", "/16 16", "/20 4", "/20 16", "/24 16",
      "/12 4", "/1 4", "/10 2", "/COM/3 2", "/COM/3", "/COM/3",
      "/38 4", "/COM/2", "/COM/2", "/1 2", "/3", "/2", "/4", "/1", "",
      "/COM/3 1", "/COM/3 2", "/COM/6 4", "/COM/6 4", ""
   };

   int i, o;
   extern char id[];
   char tmp[12];

        /*- eliminate brackets -*/

   for (i = 0, o = 0; i <= (int)strlen(s); i++) {
      if (s[i] == '[' || s[i] == ']') {
         continue;
      }
      tmp[o++] = s[i];
   }
   tmp[o] = '\0';
   strcpy(s, tmp);

   for (i = 0; i <= 61; i++) {
      if (strcmp(s, timein[i]) == 0) {
         strcpy(s, timeout[i]);
         return 1;
      }
   }
        /*- try to catch other time sigs -*/

   printf("RISM %s (%s): unusual time signature \"%s\"\n", id, incipit_id,
          s);

   for (i = 0; i <= (int)strlen(s); i++) {
      if (s[i] == '/')
         tmp[i] = ' ';
      else
         tmp[i] = s[i];
   }
   tmp[o] = '\0';
   strcpy(s, "/");
   strcat(s, tmp);
   return;

        /*- assuming nothing gets past here, the following not necessary -*/

   return -1;
}



//////////////////////////////
//
// lstr --
//

void lstr(char *s, int n) {
   int i;
   char tmp[2056];

   for (i = 0; i < n; i++)
      tmp[i] = s[i];
   tmp[i] = '\0';
   strcpy(s, tmp);
   return;
}



//////////////////////////////
//
// rstr --
//

void rstr(char *s, int n) {
   int i, o = 0;
   char tmp[2056];

   for (i = 0; i <= (int)strlen(s); i++) {
      if (i >= n)
         tmp[o++] = s[i];
   }
   tmp[o] = '\0';
   strcpy(s, tmp);
   return;
}



//////////////////////////////
//
// readline -- read a line of text from the input file
//      simulating the fgets function but better behaved
//      at the end of a file where there is no newline.
//

int readline(char * storage, int max, FILE* fr) {
   int i;
   int inchar;
   for (i=0; i<max-2; i++) {
      inchar = fgetc(fr);
      if (inchar == EOF) {
         if (i == 0) {
         }
         break;
      } else {
         storage[i] = (char)inchar;
      }
      if (storage[i] == '\n') {
         break;
      }
   }

   if (i==0 && inchar == EOF) {
      return 0;
   }

   if (storage[i-1] != '\n') {
      storage[i] = '\n';
      i++;
   }

   storage[i] = '\0';

   return 1;
}




////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////



//////////////////////////////
//
// usage -- gives the usage statement for the program
//

void usage(const char* command) {
   cout << "               " << endl;

// original usage statement
//      if (a == 0) {
//         printf("rmusic: prepare input file for Score music typesetting "
//                "program from RISM A/II SPIRES standard format\n\n");
//         printf("Input file not specified\nUsage: rmusic "
//                "fn_in {fn_out} -lMpr\n");
//         printf("\n   -p = prepare EPS printing instructions\n");
//         printf("   -l = print with long staves (for WWW site)\n");
//         printf("   -M = omit music input files (use with -p)\n");
//         printf("   -r = Score output will be written to \\rism\\temp\n");
//         printf("   -P = output proofreading information only\n");
//         printf("   -R = source file is from RISM Zentralredaktion\n");
//         printf
//             ("   -s = Score output file prints with size factor of .5\n");
//         printf("   -b = Score output thins beams by factor of .8\n");
//         return;


}



//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//

void checkOptions(Options& opts, int argc, char* argv[]) {

   // original options:
   // p => print_flag = 1;
   // M => music_flat = 1;
   // l => format = 1;
   // r => directory = 1;
   // R => rism = 1;
   // s => format = 2;
   // p => proof = 1;
   // b => beam_flat = 1;   set beam thickness to 0.8 (thin) in SCORE.
   // v => verbose = 1;

   opts.define("debug=b");           // determine bad input line num
   opts.define("author=b");          // author of program
   opts.define("version=b");         // compilation info
   opts.define("example=b");         // example usages
   opts.define("h|help=b");          // short description
   opts.process(argc, argv);



   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, August 2006" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 15 August 2006" << endl;
      cout << "compiled: " << __DATE__ << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }

}



//////////////////////////////
//
// example -- example usage of the program
//

void example(void) {
   cout << "    " << endl;
}


// md5sum: 1281b5755490cb9b169487a9cb440f43 pe2score.cpp [20110711]