// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Mon Nov 23 05:24:14 PST 2009 // Last Modified: Tue Nov 23 09:54:40 PST 2010 added more features // Last Modified: Wed Jan 12 07:00:38 PST 2011 added ending note marking // Last Modified: Tue Jan 18 11:10:38 PST 2011 added --mstart option // Last Modified: Sun Feb 20 18:38:07 PST 2011 added --percent option // Last Modified: Thu Feb 24 17:10:34 PST 2011 added --file option // Filename: ...sig/examples/all/theloc.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/theloc.cpp // Syntax: C++; museinfo // // Description: Identify the location of an index note in a files as // output from "themax --location". // // Todo: If a mark is added with -m or --mchar, the program should // complain and exit if the mark already exists. But probably allow // the -m to have the !!!RDF be overwritten with the same marker. #include "humdrum.h" #include "PerlRegularExpression.h" #include <string.h> #include <stdio.h> #include <unistd.h> #ifndef OLDCPP #include <iostream> #include <fstream> #else #include <iostream.h> #include <fstream.h> #endif // Function declarations: void checkOptions(Options& opts, int argc, char** argv); void example(void); void usage(const char* command); void processData(istream& input); void extractDataFromInputLine(Array<char>& filename, Array<char>& voicename, int& track, int& subtrack, Array<int>& starts, Array<int>& endings, char* inputline); void prepareSearchPaths(Array<Array<char> >& paths, const char* pathlist); int fileexists(Array<char>& jointname, Array<char>& filename, Array<char>& path); void getFileAndPath(Array<char>& fileandpath, Array<char>& filename, Array<Array<char> >& paths); int findNote(int nth, HumdrumFile& infile, int& cur, int& row, int& col, int track, int subtrack, int& measure); void fillMeterInfo(HumdrumFile& infile, Array<RationalNumber>& meterbot, int track); void markNotes(HumdrumFile& infile, int row, int col, int track, int subtrack, int matchlen, const char* marker); void processDataLine(HumdrumFile& infile, const char* inputline, Array<char>& filename, Array<char>& lastfilename, Array<char>& voicename, int track, int subtrack, Array<int>& starts, Array<int>& endings); void printDash(void); void displayNoteLocationInfo(HumdrumFile& infile, int num, int row, int col, int measure, Array<RationalNumber>& meterbot); // User interface variables: Options options; Array<Array<char> > paths; int debugQ = 0; // used with --debug option int percentQ = 0; // used with -P option int dirdropQ = 0; // used with -D option int dispLineQ = 0; // used with -l option int dispColumnQ = 0; // used with -c option int dispNoteQ = 1; // used with -N option int dispAbsBeatQ = 0; // used with -a option int dispMeasureQ = 1; // used with -M option int dispQBeatQ = 0; // used with -q option int dispBeatQ = 1; // used with -B option int rationalQ = 0; // used with -r option int markQ = 0; // used with --mark option int matchlistQ = 0; // used with --matchlist option int mark2Q = 0; // used with --mark2 option int tieQ = 0; // used with --tie option int graceQ = 1; // used with -G option int doubleQ = 0; // used with --mstart option int fileQ = 0; // used with --file option const char* Filename = ""; // used with --file option int matchlen = 1; // used with --mark option const char* marker = "@"; // used with --marker option ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); ifstream input; int numinputs = options.getArgumentCount(); for (int i=0; i<numinputs || i==0; i++) { // if no command-line arguments read data file from standard input if (numinputs < 1) { processData(cin); } else { input.open(options.getArg(i+1)); processData(input); input.close(); } } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // processData -- // void processData(istream& input) { #define LINESIZE 100000 Array<char> filename; Array<char> lastfilename; lastfilename.setSize(1); lastfilename[0] = '\0'; Array<int> starts; Array<int> endings; Array<char> voicename; voicename.setSize(1); voicename[0] = '\0'; int track; int subtrack; HumdrumFile infile; char inputline[LINESIZE] = {0}; do { input.getline(inputline, LINESIZE); if (input.eof()) { break; } if (strncmp(inputline, "#NOGRACE", strlen("#NOGRACE")) == 0) { graceQ = 0; continue; } else if (strncmp(inputline, "#GRACE", strlen("#GRACE")) == 0) { graceQ = 1; continue; } else if (strncmp(inputline, "#", strlen("#")) == 0) { // unknown control message, just ignore and don't try to process. continue; } extractDataFromInputLine(filename, voicename, track, subtrack, starts, endings, inputline); if (track > 0) { processDataLine(infile, inputline, filename, lastfilename, voicename, track, subtrack, starts, endings); lastfilename = filename; } else { // echo input lines which are not understood (comments?) cout << inputline << endl; } } while (!input.eof()); while (!input.eof()) { } // flush any data needing to be printed (such as for markQ): filename.setSize(1); filename[0] = '\0'; processDataLine(infile, "", filename, lastfilename, voicename, track, subtrack, starts, endings); } ////////////////////////////// // // processDataLine -- // void processDataLine(HumdrumFile& infile, const char* inputline, Array<char>& filename, Array<char>& lastfilename, Array<char>& voicename, int track, int subtrack, Array<int>& starts, Array<int>& endings) { PerlRegularExpression pre; PerlRegularExpression pre2; PerlRegularExpression pre3; Array<char> fileandpath; if (fileQ) { filename.setSize(strlen(Filename)+1); strcpy(filename.getBase(), Filename); pre.sar(filename, ":", ":", "g"); } if (strcmp(filename.getBase(), "") != 0) { getFileAndPath(fileandpath, filename, paths); if (debugQ) { cout << "FOUND FILE: " << fileandpath << endl; } if (strlen(fileandpath.getBase()) == 0) { // print original line without processing content since file not found cout << inputline << endl; return; } } Array<char> tempstr; tempstr.setSize(1); tempstr[0] = '\0'; if (strcmp(filename.getBase(), lastfilename.getBase()) != 0) { if (strcmp(lastfilename.getBase(), "") != 0) { if (markQ) { cout << infile; if (pre.search(marker, "^\\s*([^\\s])\\s+", "") || pre.search(marker, "^\\s*([^\\s])$", "") ) { cout << "!!!RDF**kern: " << pre.getSubmatch(1); cout << "= matched note"; if (pre.search(marker, "color\\s*=\\s*\"?([^\\s\"\\)\\(,;]+)\"?", "")) { tempstr.setSize(strlen(marker) + 1); strcpy(tempstr.getBase(), marker); pre3.sar(tempstr, "^\\s*[^\\s]\\s+", "", ""); pre3.sar(tempstr, "color\\s*=\\s*\"?[^\\s\"\\)\\(,;]+\"?", "", "g"); pre3.sar(tempstr, "^[\\s:,;-=]+", "", ""); pre3.sar(tempstr, "[\\s,:;-=]+$", "", ""); if (!pre2.search(pre.getSubmatch(1), "#", "")) { if (pre2.search(pre.getSubmatch(1), "^[0-9a-f]+$", "i")) { if (strlen(pre.getSubmatch(1)) == 6) { cout << ", color=\"#" << pre.getSubmatch(1) << "\""; } else { cout << ", color=\"" << pre.getSubmatch(1) << "\""; } } else { cout << ", color=\"" << pre.getSubmatch(1) << "\""; } } else { cout << ", color=\"" << pre.getSubmatch(1) << "\""; } } if (strlen(tempstr.getBase()) > 0) { cout << " " << tempstr; } cout << endl; } if (!mark2Q) { cout << "!!!MATCHLEN:\t" << matchlen << endl; } if (strcmp(filename.getBase(), "") == 0) { // empty filename is a dummy to force last line of // input to be processed correctly if markQ or similar is used. return; } } } if (strcmp(filename.getBase(), "") != 0) { infile.clear(); infile.read(fileandpath.getBase()); infile.analyzeRhythm("4"); // only by quarter-note beats for now } } if (strcmp(filename.getBase(), "") == 0) { // empty filename is a dummy, but shouldn't ever get here. return; } if (matchlistQ && markQ) { cout << "!!MATCHES:\t"; } if (fileQ) { fileandpath.setSize(strlen(Filename)+1); strcpy(fileandpath.getBase(), Filename); } if (matchlistQ) { cout << fileandpath; cout << ":"; cout << voicename; cout << ":"; cout << track; cout << "\t"; } int row = 0; int col = 0; int cur = 0; // current nth numbered note in the given track int erow = 0; int ecol = 0; int ecur = 0; // current nth numbered note in the given track int measure = 1; int emeasure = 1; if (infile.getPickupDuration() > 0.0) { measure = 0; emeasure = 0; } Array<RationalNumber> meterbot; meterbot.setSize(0); if (dispBeatQ) { fillMeterInfo(infile, meterbot, track); } int i; int state; int estate; for (i=0; i<starts.getSize(); i++) { state = findNote(starts[i], infile, cur, row, col, track, subtrack, measure); if (state == 0) { continue; } if ((endings.getSize() >0) && (endings[i] >= 0)) { estate = findNote(endings[i], infile, ecur, erow, ecol, track, subtrack, emeasure); } else { estate = 0; } if (markQ) { if ((endings.getSize() > 0) && (endings[i] >= 0)) { markNotes(infile, row, col, track, subtrack, endings[i]-starts[i]+1, marker); } else { markNotes(infile, row, col, track, subtrack, matchlen, marker); } } if (matchlistQ) { displayNoteLocationInfo(infile, starts[i], row, col, measure, meterbot); if ((endings.getSize() > 0) && (endings[i] >= 0) && estate) { printDash(); displayNoteLocationInfo(infile, endings[i], erow, ecol, emeasure, meterbot); } } if (matchlistQ) { if (i < starts.getSize()-1) { cout << " "; } } } if (matchlistQ) { cout << endl; } } ////////////////////////////// // // printDash -- have to do a complicated system, since markQ would not // involve a dash being printed. // void printDash(void) { if (dispNoteQ || dispLineQ || dispColumnQ || dispAbsBeatQ || dispMeasureQ || dispBeatQ || percentQ || dispQBeatQ) { cout << "-"; } } ////////////////////////////// // // displayNoteLocationInfo -- // void displayNoteLocationInfo(HumdrumFile& infile, int num, int row, int col, int measure, Array<RationalNumber>& meterbot) { RationalNumber four(4, 1); if (dispNoteQ) { cout << num; } if (dispLineQ) { cout << "L" << row+1; } if (dispColumnQ) { cout << "C" << col+1; } if (dispAbsBeatQ) { if (rationalQ) { cout << "A" << infile[row].getAbsBeatR(); } else { cout << "A" << infile[row].getAbsBeat(); } } if (percentQ) { double percent = infile.getTotalDuration(); if (percent > 0.0) { percent = int(infile[row].getAbsBeat() / percent * 1000.0 + 0.5) / 10.0; } cout << "P" << percent; } if (dispMeasureQ) { cout << "=" << measure; } if (dispBeatQ) { if (rationalQ) { RationalNumber tval = (infile[row].getBeatR()-1) * (meterbot[row] / four) + 1; cout << "B"; tval.printTwoPart(cout); } else { cout << "B" << (infile[row].getBeat()-1) * (meterbot[row].getFloat() / 4.0) + 1; } } if (dispQBeatQ) { if (rationalQ) { cout << "Q" << infile[row].getBeatR(); } else { cout << "Q" << infile[row].getBeat(); } } } ////////////////////////////// // // markNotes -- mark notes in match sequence (for possible later output as HTML // with colors). // void markNotes(HumdrumFile& infile, int row, int col, int track, int subtrack, int matchlen, const char* marker) { PerlRegularExpression pre; char markchar[2] = {0}; if (pre.search(marker, "^\\s*([^\\s])\\s+", "") || pre.search(marker, "^\\s*([^\\s])$", "")) { markchar[0] = pre.getSubmatch(1)[0]; } int tiestate = 0; Array<char> newdata; newdata.setSize(1000); newdata.setGrowth(1000); newdata.setSize(0); int foundcount = 0; int i, j; int scount = 0; for (i=row; i<infile.getNumLines(); i++) { if (!infile[i].isData()) { continue; } if (foundcount >= matchlen) { break; } scount = 0; for (j=0; j<infile[i].getFieldCount(); j++) { if (track != infile[i].getPrimaryTrack(j)) { // ignore the current spine if not the correct one continue; } scount++; if (subtrack != scount) { continue; } if (strcmp(infile[i][j], ".") == 0) { // don't count null tokens break; } if (strchr(infile[i][j], 'r') != NULL) { // don't count rests break; } if ((!graceQ) && ((strchr(infile[i][j], 'q') != NULL) || (strchr(infile[i][j], 'Q') != NULL)) ) { // ignore grace notes if not supposed to count break; } if (strchr(infile[i][j], '[') != NULL) { if (tieQ) { foundcount--; // suppress from count later on tiestate = 1; } } else if (strchr(infile[i][j], ']') != NULL) { if (tieQ) { // don't subtract one from foundcount (this is the last note) tiestate = 1; } else { // don't color tied note unless asked to break; } } else if (strchr(infile[i][j], '_') != NULL) { if (tieQ) { foundcount--; // suppress from count later on if (tiestate == 0) { // a weird case where the tie starts with a medial // tie. This is can legally occur when there is a // multiple ending which a slur crosses. foundcount++; } tiestate = 1; } else { // don't color tied note unless asked to continue; } } else { tiestate = 0; } foundcount++; if (strstr(infile[i][j], markchar) != NULL) { // already marked (perhaps overlapping match) break; } newdata.setSize(strlen(infile[i][j]) + strlen(markchar) + 1); strcpy(newdata.getBase(), infile[i][j]); strcat(newdata.getBase(), markchar); if (doubleQ && (foundcount == 1)) { strcat(newdata.getBase(), markchar); } infile[i].changeField(j, newdata.getBase()); break; if (foundcount >= matchlen) { goto veryend; // if (tieQ && (strchr(infile[i][j], '[') != NULL)) { // foundcount--; // } else if (tieQ && (strchr(infile[i][j], '_') != NULL)) { // foundcount--; // } } } } veryend: ; } ////////////////////////////// // // fillMeterInfo -- // void fillMeterInfo(HumdrumFile& infile, Array<RationalNumber>& meterbot, int track) { int top; int bot; meterbot.setSize(infile.getNumLines()); RationalNumber current(4, 1); RationalNumber compound(3, 2); int i, j; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isInterpretation()) { meterbot[i] = current; continue; } for (j=0; j<infile[i].getFieldCount(); j++) { if (track != infile[i].getPrimaryTrack(j)) { continue; } if (sscanf(infile[i][j], "*M%d/%d", &top, &bot) == 2) { current = bot; if ((top != 3) && ((top % 3) == 0)) { current *= compound; } } meterbot[i] = current; break; } } } ////////////////////////////// // // findNote -- Search for the row and column of the nth note in the // track. The current position of row and col is on the cur'th // note in the track (if all are 0, then haven't started looking). // returns 0 if nth note cannot be found in track. // int findNote(int nth, HumdrumFile& infile, int& cur, int& row, int& col, int track, int subtrack, int& measure) { int direction = 1; if (nth > cur) { direction = 1; } else if (nth < cur) { direction = -1; } else { // Already have the match (for some strange reason) so just return. return 1; } int scount; int mval; int i, j; for (i=row+direction; (i<infile.getNumLines()) && (i>=0); i+=direction) { if (infile[i].isMeasure()) { if (sscanf(infile[i][0], "=%d", &mval)) { measure = mval; if (direction < 0) { measure--; } } } if (!infile[i].isData()) { continue; } scount = 0; for (j=0; j<infile[i].getFieldCount(); j++) { if (track != infile[i].getPrimaryTrack(j)) { continue; } scount++; if (subtrack == scount) { if (strcmp(infile[i][j], ".") == 0) { // skip null tokens (could make search faster // if null token references were utilized). break; } // currently only considering tracks to be **kern data, // but should be generalized later (so don't exit from "r" // or "]" or "_" for non **kern data. if (strchr(infile[i][j], 'r') != NULL) { // skip null tokens (could make search faster // if null token references were utilized). break; } if ((!graceQ) && ((strchr(infile[i][j], 'q') != NULL) || (strchr(infile[i][j], 'Q') != NULL)) ) { // ignore grace notes if requested break; } // the following statements are not quite right (consider // chords with only some notes being tied?) // but this will be dependent on tindex's behavior. if (strchr(infile[i][j], ']') != NULL) { // skip endings of ties. break; } if (strchr(infile[i][j], '_') != NULL) { // skip continuation ties. break; } // now have a note which is to be counted: cur += direction; if (cur == nth) { row = i; col = j; return 1; } break; } } } // if get here, then note not found: row = 0; col = 0; cur = 0; return 0; } ////////////////////////////// // // getFileAndPath -- given a particular filename and a list of directory // paths to search, return the first file which is found which matches // the filename in the list of directory paths. First search using // the complete filename. Then if the filename with any attached // directory information is not found, then remove the directory // information and search again. // void getFileAndPath(Array<char>& fileandpath, Array<char>& filename, Array<Array<char> >& paths) { PerlRegularExpression pre; pre.sar(filename, ":", ":", "g"); if (pre.search(filename, "://")) { // either a URL or a URI, so no path. fileandpath = filename; paths.setSize(1); paths[0] = '\0'; return; } int i; for (i=0; i<paths.getSize(); i++) { if (fileexists(fileandpath, filename, paths[i])) { return; } } if (!pre.search(filename, "/")) { fileandpath.setSize(1); fileandpath[0] = '\0'; } // check to see if removing the directory name already attached // to the filename helps: Array<char> tempfilename = filename; pre.sar(tempfilename, ".*/", "", ""); for (i=0; i<paths.getSize(); i++) { if (fileexists(fileandpath, tempfilename, paths[i])) { return; } } fileandpath.setSize(1); fileandpath[0] = '\0'; } ////////////////////////////// // // JoinDirToPath -- The temporary buffer used to // create the filename is given back to the calling function. // void JoinDirToPath(Array<char>& jointname, Array<char>& path, Array<char>& filename) { PerlRegularExpression pre; int len = strlen(filename.getBase()); if (pre.search(path, "^\\./*$")) { // if searching in the current directory, then don't // add the current directory marker. jointname.setSize(len+1); strcpy(jointname.getBase(), filename.getBase()); } else { // append "/" to directory name and then filename len += strlen(path.getBase()); if (pre.search(path, "/$", "")) { // don't need to add "/" to separate dir and file names. jointname.setSize(len+1); strcpy(jointname.getBase(), path.getBase()); strcat(jointname.getBase(), filename.getBase()); } else { // need to add "/" to separate dir and file names. jointname.setSize(len+2); strcpy(jointname.getBase(), path.getBase()); strcat(jointname.getBase(), "/"); strcat(jointname.getBase(), filename.getBase()); } } } ////////////////////////////// // // fileexists -- // int fileexists(Array<char>& jointname, Array<char>& filename, Array<char>& path) { JoinDirToPath(jointname, path, filename); if (access(jointname.getBase(), F_OK) != -1) { return 1; } else { return 0; } // or another way: // struct stat buffer; // return stat(filename, &buffer) == 0; } ////////////////////////////// // // extractDataFromInputLine -- // void extractDataFromInputLine(Array<char>& filename, Array<char>& voicename, int& track, int& subtrack, Array<int>& starts, Array<int>& endings, char* inputline) { filename.setSize(1); filename[0] = '\0'; track = 0; subtrack = 1; starts.setSize(1000); starts.setGrowth(1000); starts.setSize(0); endings.setSize(1000); endings.setGrowth(1000); endings.setSize(0); int negone = -1; char* ptr = inputline; int len; int value; PerlRegularExpression pre; PerlRegularExpression pre2; PerlRegularExpression prefilename; if (pre.search(ptr, "^([^\\t:]+)[^\\t]*:(\\d+)\\.?(\\d+)?\\t(\\d+)([^\\s]*\\s*)")) { if (fileQ) { len = strlen(Filename); filename.setSize(len + 1); strcpy(filename.getBase(), Filename); } else { len = strlen(pre.getSubmatch(1)); filename.setSize(len + 1); strcpy(filename.getBase(), pre.getSubmatch()); } track = atoi(pre.getSubmatch(2)); if (strlen(pre.getSubmatch(3)) > 0) { subtrack = atoi(pre.getSubmatch(3)); } else { subtrack = 1; } value = atoi(pre.getSubmatch(4)); starts.append(value); if (pre2.search(pre.getSubmatch(5), "-(\\d+)", "")) { value = atoi(pre2.getSubmatch(1)); endings.append(value); } else { endings.append(negone); } ptr = ptr + pre.getSubmatchEnd(5); while (pre.search(ptr, "^(\\d+)([^\\s]*\\s*)")) { value = atoi(pre.getSubmatch(1)); starts.append(value); if (pre2.search(pre.getSubmatch(2), "-(\\d+)", "")) { value = atoi(pre2.getSubmatch(1)); endings.append(value); } else { endings.append(negone); } ptr = ptr + pre.getSubmatchEnd(2); } if (pre.search(inputline, "^[^\\t:]*:([^\\t:]*):")) { voicename.setSize(strlen(pre.getSubmatch(1))+1); strcpy(voicename.getBase(), pre.getSubmatch()); } } else if (pre.search(ptr, "^([^\\t:]+)\\t(\\d+)([^\\s]*\\s*)")) { // monophonic label (no spine information available). // search only on the first **kern column in the file. if (fileQ) { len = strlen(Filename); filename.setSize(len + 1); strcpy(filename.getBase(), Filename); } else { len = strlen(pre.getSubmatch(1)); filename.setSize(len + 1); strcpy(filename.getBase(), pre.getSubmatch()); } track = 1; value = atoi(pre.getSubmatch(2)); starts.append(value); if (pre2.search(pre.getSubmatch(3), "-(\\d+)", "")) { value = atoi(pre2.getSubmatch(1)); endings.append(value); } else { endings.append(negone); } ptr = ptr + pre.getSubmatchEnd(3); while (pre.search(ptr, "^(\\d+)([^\\s]*\\s*)")) { value = atoi(pre.getSubmatch(1)); starts.append(value); if (pre2.search(pre.getSubmatch(2), "-(\\d+)", "")) { value = atoi(pre2.getSubmatch(1)); endings.append(value); } else { endings.append(negone); } ptr = ptr + pre.getSubmatchEnd(2); } if (pre.search(inputline, "^[^\\t:]*:([^\\t:]*):")) { // won't occur in this case voicename.setSize(strlen(pre.getSubmatch(1))+1); strcpy(voicename.getBase(), pre.getSubmatch()); } } if(dirdropQ) { // remove directory names from filename if the -D option was used. pre.sar(filename, ".*/", "", ""); } prefilename.sar(filename, ":", ":", "g"); } ////////////////////////////// // // checkOptions -- // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("p|path=s:.", "colon-separated search patch for data files"); opts.define("D|nodir=b", "remove directory information from input data"); opts.define("l|L|line=b", "display line in file on which match found"); opts.define("c|col=b", "display column in file on which match found"); opts.define("N|nonth=b", "don't display nth note number in file"); opts.define("P|percent=b", "display percentage into file"); opts.define("M|nomeasure=b", "don't display measure number in file"); opts.define("a|abs=b", "display absolute beat number of note in file"); opts.define("q|qbeat=b", "display quarter note duration for start of bar"); opts.define("B|nobeat=b", "don't display beat of start of match"); opts.define("r|rational=b", "display metric info as rational numbers"); opts.define("m|mark=b", "mark matches in first input file"); opts.define("mstart|double=b", "double-mark first note in match"); opts.define("G|no-grace|nograce=b", "do not count grace notes"); opts.define("fixedmark=i:1", "mark matches in first input file"); opts.define("matchlist=b", "list matches in output Humdurm file"); opts.define("file=s:", "filename to use as basis for search information"); opts.define("mchar|markchar=s:@", "character to mark matches with"); opts.define("all=b", "display all location formats"); opts.define("tie|ties=b", "display search markers on tie middle/end notes"); opts.define("debug=b", "author of program"); opts.define("author=b", "author of program"); opts.define("version=b", "compilation info"); opts.define("example=b", "example usages"); opts.define("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, Nov 2010" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 10 Nov 2010" << endl; cout << "compiled: " << __DATE__ << endl; cout << MUSEINFO_VERSION << endl; exit(0); } else if (opts.getBoolean("help")) { usage(opts.getCommand()); exit(0); } else if (opts.getBoolean("example")) { example(); exit(0); } dispLineQ = opts.getBoolean("line"); dispAbsBeatQ= opts.getBoolean("abs"); dispColumnQ = opts.getBoolean("col"); dispNoteQ =!opts.getBoolean("nonth"); dispMeasureQ=!opts.getBoolean("nomeasure"); dispQBeatQ = opts.getBoolean("qbeat"); dispBeatQ =!opts.getBoolean("nobeat"); rationalQ = opts.getBoolean("rational"); dirdropQ = opts.getBoolean("nodir"); debugQ = opts.getBoolean("debug"); percentQ = opts.getBoolean("percent"); tieQ = opts.getBoolean("tie"); doubleQ = opts.getBoolean("mstart"); fileQ = opts.getBoolean("file"); if(fileQ) { Filename = opts.getString("file"); } markQ = opts.getBoolean("fixedmark"); matchlen = opts.getInteger("fixedmark"); matchlistQ = opts.getBoolean("matchlist"); if (opts.getBoolean("mark")) { markQ = 1; matchlen = 1; mark2Q = 1; } else { mark2Q = 0; } if(!markQ) { matchlistQ = 1; } marker = opts.getString("markchar"); graceQ = !opts.getString("no-grace"); if (opts.getBoolean("all")) { dispLineQ = 1; // used with -l option dispColumnQ = 1; // used with -c option dispNoteQ = 1; // used with -N option dispAbsBeatQ = 1; // used with -a option percentQ = 1; // used with -P option dispMeasureQ = 1; // used with -M option dispQBeatQ = 1; // used with -q option dispBeatQ = 1; // used with -B option } prepareSearchPaths(paths, opts.getString("path")); } ////////////////////////////// // // prepareSearchPaths -- get a list of search paths for looking for data files. // The list of paths is colon separated. // void prepareSearchPaths(Array<Array<char> >& paths, const char* pathlist) { paths.setSize(100); paths.setSize(0); paths.setGrowth(1000); PerlRegularExpression pre; int len; const char* ptr = pathlist; while (pre.search(ptr, "([^:]+):?")) { len = strlen(pre.getSubmatch(1)); paths.setSize(paths.getSize()+1); paths.last().setSize(len+1); strcpy(paths[paths.getSize()-1].getBase(), pre.getSubmatch()); ptr = ptr + pre.getSubmatchEnd(1); } if(debugQ) { cout << "Search Paths:" << endl; for (int i=0; i<paths.getSize(); i++) { cout << "search path " << i + 1 << ":\t" << paths[i] << endl; } } } ////////////////////////////// // // example -- // void example(void) { } ////////////////////////////// // // usage -- // void usage(const char* command) { } // md5sum: 964b0c692a0188b02222267b966e494e theloc.cpp [20130420]