// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Wed Jun 13 18:46:49 PDT 2001 // Last Modified: Wed Jun 13 18:46:49 PDT 2001 // Filename: ...museinfo/examples/all/parsepmx.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/parsepmx.cpp // Syntax: C++; museinfo // // Description: Basic PMX Parser. // #include <string.h> #include <stdio.h> #include <ctype.h> #include <stdlib.h> #ifndef OLDCPP #include <iostream> #include <fstream> using namespace std; #else #include <iostream.h> #include <fstream.h> #endif // line type defines #define LINE_UNKNOWN -1 #define LINE_BLANK 0 #define LINE_COMMENT 1 #define LINE_BOUNDARY 2 #define LINE_DEFINE 3 #define LINE_SETUP 4 #define LINE_INSTRUMENT 5 #define LINE_CLEF 6 // other defines: #define SPACES " \t\n\015" // function declarations: void parseSetup(fstream& infile); int getline(char* buffer, fstream& file); void displayOriginalLine(const char* buffer); int identifyline(const char* buffer, int stage); void printCommentary(const char* buffer); void printLineType(int type); void parseSetupLine(const char* buffer); void printSetupVariables(void); void parseBody(fstream& infile); void parseInstrumentLine(const char *inbuffer); void parseClefLine(const char *inbuffer); // global variables int stage = 0; // part of file being read: 0=start, 1=def, 2=setup, 3=body int line = 0; // number of the line being read. int namecount = 0; // number of instrument names read // setup variables read from header: int setupcount = 0; // number of setup variables read double setup[12] = {0}; // storage for setup variables double& nv = setup[0]; // number of staves in a system double& noinst = setup[1]; // number of instruments on a system double& mtrnuml = setup[2]; // logical meter numerator double& mtrdenl = setup[3]; // logical meter denominator double& mtrnump = setup[4]; // printed meter numerator double& mtrdenp = setup[5]; // printed meter denominator double& xmtrnum0 = setup[6]; // number of beats in the pickup measure double& isig = setup[7]; // key signature double& npages = setup[8]; // number of pages to create double& nsyst = setup[9]; // total number of systems to create double& musicsize = setup[10]; // point size of staves double& fracindent = setup[11]; // indentation of the first system ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { if (argc != 2) { cout << "Usage: " << argv[0] << " input-pmx-file" << endl; exit(1); } #ifndef OLDCPP fstream infile(argv[1], ios::in); #else fstream infile(argv[1], ios::in | ios::nocreate); #endif if (!infile.is_open()) { cout << "Error: cannot open " << argv[1] << " for reading" << endl; exit(1); } parseSetup(infile); printCommentary("This is the end of the SETUP section"); printCommentary("Now begins the body of the PMX file" ); parseBody(infile); return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // parseBody -- read the musical information section // void parseBody(fstream& infile) { } ////////////////////////////// // // parseSetup -- read up to the end of the setup section of the music. // void parseSetup(fstream& infile) { char inbuffer[2048] = {0}; char message[1024] = {0}; int done = 0; int lineid = 0; while (!done) { line = getline(inbuffer, infile); displayOriginalLine(inbuffer); if (infile.eof()) { cout << "Error: EOF when not finished parsing file" << endl; exit(1); } lineid = identifyline(inbuffer, stage); printLineType(lineid); switch(lineid) { case LINE_BOUNDARY: stage++; sprintf(message, "Going to stage %d", stage); printCommentary(message); break; case LINE_SETUP: parseSetupLine(inbuffer); break; case LINE_INSTRUMENT: parseInstrumentLine(inbuffer); break; case LINE_CLEF: parseClefLine(inbuffer); break; } if (stage >= 5) { done = 1; break; } } } ////////////////////////////// // // parseClefLine -- doesn't store the clefs for now. // void parseClefLine(const char *inbuffer) { char tbuffer[2048] = {0}; int len = strlen(inbuffer); strcpy(tbuffer, inbuffer); char * ptr = strtok(tbuffer, SPACES); len = strlen(ptr); if (len != (int)nv) { cout << "Error on line " << line << ": incorrect clef count" << endl; exit(1); } stage = 5; } ////////////////////////////// // // parseInstrumentLine -- // void parseInstrumentLine(const char *inbuffer) { char message[1024] = {0}; namecount++; sprintf(message, "Instrument name %d: %s", namecount, inbuffer); printCommentary(message); if (namecount >= noinst) { stage = 4; printCommentary("Next line is expected to be the clef indicator line"); } } ////////////////////////////// // // parseSetupLine -- // void parseSetupLine(const char* buffer) { char tbuffer[2048] = {0}; // int length = strlen(buffer); char message[1024] = {0}; strcpy(tbuffer, buffer); char* ptr = strtok(tbuffer, SPACES); while (ptr != NULL) { if (ptr[0] == '%') { return; } if (setupcount > 11) { cout << "Error on line " << line << ": too many setup values" << endl; exit(1); } setup[setupcount] = strtod(ptr, NULL); setupcount++; sprintf(message, "Read setup variable number %d", setupcount); printCommentary(message); if (setupcount >= 12) { stage = 3; printSetupVariables(); printCommentary("Finished reading setup variables"); printCommentary("Expecting next non-comment line to be inst. names"); } if (strchr(ptr, '%') != NULL) { return; } ptr = strtok(NULL, SPACES); } } ////////////////////////////// // // identifyline -- identify what type of line this is. // int identifyline(const char* buffer, int stage) { char tbuffer[2048] = {0}; int len = strlen(buffer); int plen; if (len == 0 && stage == 3) { return LINE_INSTRUMENT; } if (len == 0) { return LINE_BLANK; } strcpy(tbuffer, buffer); char* ptr = strtok(tbuffer, SPACES); if (ptr == NULL) { if (stage == 3) { return LINE_INSTRUMENT; } else { return LINE_BLANK; } } // determine if this is a comment line plen = strlen(ptr); if (plen == 0) { cout << "Error reading line: " << line << endl; exit(1); } if (ptr[0] == '%') { return LINE_COMMENT; } if (stage == 4) { return LINE_CLEF; } if (stage == 3) { return LINE_INSTRUMENT; } if (strcmp(ptr, "---") == 0) { return LINE_BOUNDARY; } if (stage == 1) { return LINE_DEFINE; } if (stage == 2 || stage == 0) { if (isdigit(ptr[0]) || ptr[0] == '-') { return LINE_SETUP; stage = 2; } } return LINE_UNKNOWN; } ////////////////////////////// // // displayOriginalLine -- print the original line with a special start char. // void displayOriginalLine(const char* buffer) { cout << "===>\t" << buffer << endl; } ////////////////////////////// // // getline -- get a line from the file and increment the current // line number // int getline(char* buffer, fstream& file) { static int linecounter = 0; file.getline(buffer, 1000, '\n'); linecounter++; return linecounter; } ////////////////////////////// // // printCommentary -- print a parser comment about the currentline // void printCommentary(const char* buffer) { cout << " <+++\t" << buffer << endl; } ////////////////////////////// // // printLineType -- print the type of line being processed // void printLineType(int type) { switch (type) { case LINE_UNKNOWN: printCommentary("Unknown line type"); break; case LINE_BLANK: printCommentary("Empty line"); break; case LINE_COMMENT: printCommentary("Comment line"); break; case LINE_BOUNDARY: printCommentary("Boundary line"); break; case LINE_DEFINE: printCommentary("Definition line"); break; case LINE_SETUP: printCommentary("Setup line"); break; case LINE_INSTRUMENT:printCommentary("Instrument name line");break; case LINE_CLEF: printCommentary("Clef line"); break; default: printCommentary("UNDOCUMENTED LINE"); break; } } ////////////////////////////// // // printSetupVariables -- // void printSetupVariables(void) { char message[1024] = {0}; sprintf(message, "1: nv = %f (number of staves per system)", nv); printCommentary(message); sprintf(message, "2: noinst = %f (number of instruments per system)", noinst); printCommentary(message); sprintf(message, "3: mtrnuml = %f (logical meter numerator)", mtrnuml); printCommentary(message); sprintf(message, "4: mtrdenl = %f (logical meter denominator)", mtrdenl); printCommentary(message); sprintf(message, "5: mtrnump = %f (printing meter denominator)", mtrnump); printCommentary(message); sprintf(message, "6: mtrdenp = %f (printing meter denominator)", mtrdenp); printCommentary(message); sprintf(message, "7: xmtrnum0 = %f (pickup measure beats)", xmtrnum0); printCommentary(message); sprintf(message, "8: isig = %f (key signature)", isig); printCommentary(message); sprintf(message, "9: npages = %f (number of pages)", npages); printCommentary(message); sprintf(message, "10: nsyst = %f (total number of systems)", nsyst); printCommentary(message); sprintf(message, "11: musicsize = %f (music size)", musicsize); printCommentary(message); sprintf(message, "12: fracindent = %f (first line indent)", fracindent); printCommentary(message); } // md5sum: e30a832d7bd503b7a4a2f56a4fdc7bac parsepmx.cpp [20050403]