// // Programmer: Craig Stuart Sapp // Creation Date: Mon Jul 18 11:23:42 PDT 2005 // Last Modified: Tue Sep 1 13:54:42 PDT 2009 Added -f, and -p options // Last Modified: Wed Sep 2 13:26:58 PDT 2009 Added -t option // Last Modified: Sat Sep 5 15:21:29 PDT 2009 Added sub-spine features // Last Modified: Tue Sep 8 11:43:46 PDT 2009 Added co-spine extraction // Last Modified: Sat Apr 6 00:48:21 PDT 2013 Enabled multiple segment input // Last Modified: Thu Oct 24 12:32:47 PDT 2013 Switch to HumdrumStream class // Last Modified: Sat Mar 12 18:34:05 PST 2016 Switch to STL // Last Modified: Sat Mar 12 18:34:05 PST 2016 Add -k option // Filename: ...sig/examples/all/extractx.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/extractx.cpp // Syntax: C++; museinfo // // Description: C++ implementation of the Humdrum Toolkit extract command. // // To do: Allow *x records to be echoed when using -s 0 insertion // Currently spines with *x are unwrapped and the *x is changed // to *. #include "humdrum.h" #include "PerlRegularExpression.h" #include #include #include #include #include #include #include using namespace std; // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void processFile (HumdrumFile& infile); void excludeFields (HumdrumFile& infile, vector& field, vector& subfield, vector& model); void extractFields (HumdrumFile& infile, vector& field, vector& subfield, vector& model); void extractTrace (HumdrumFile& infile, const string& tracefile); void getInterpretationFields (vector& field, vector& subfield, vector& model, HumdrumFile& infile, string& interps, int state); //void extractInterpretations (HumdrumFile& infile, string& interps); void example (void); void usage (const char* command); void fillFieldData (vector& field, vector& subfield, vector& model, string& fieldstring, HumdrumFile& infile); void processFieldEntry (vector& field, vector& subfield, vector& model, const char* astring, HumdrumFile& infile); void removeDollarsFromString (string& buffer, int maxtrack); int isInList (int number, vector& listofnum); void getTraceData (vector& startline, vector >& fields, const string& tracefile, HumdrumFile& infile); void printTraceLine (HumdrumFile& infile, int line, vector& field); void dealWithSpineManipulators(HumdrumFile& infile, int line, vector& field, vector& subfield, vector& model); void storeToken (vector& storage, const char* string); void storeToken (vector& storage, int index, const char* string); void printMultiLines (vector& vsplit, vector& vserial, vector& tempout); void reverseSpines (vector& field, vector& subfield, vector& model, HumdrumFile& infile, const string& exinterp); void getSearchPat (string& spat, int target, const char* modifier); void expandSpines (vector& field, vector& subfield, vector& model, HumdrumFile& infile, string& interp); void dealWithSecondarySubspine(vector& field, vector& subfield, vector& model, int targetindex, HumdrumFile& infile, int line, int spine, int submodel); void dealWithCospine (vector& field, vector& subfield, vector& model, int targetindex, HumdrumFile& infile, int line, int cospine, int comodel, int submodel, const string& cointerp); void printCotokenInfo (int& start, HumdrumFile& infile, int line, int spine, vector& cotokens, vector& spineindex, vector& subspineindex); void fillFieldDataByGrep (vector& field, vector& subfield, vector& model, const string& grepString, HumdrumFile& infile, int state); // global variables Options options; // database for command-line arguments int excludeQ = 0; // used with -x option int expandQ = 0; // used with -e option string expandInterp = ""; // used with -E option int interpQ = 0; // used with -i option string interps = ""; // used with -i option int debugQ = 0; // used with --debug option int kernQ = 0; // used with -k option int fieldQ = 0; // used with -f or -p option string fieldstring = ""; // used with -f or -p option vector field; // used with -f or -p option vector subfield; // used with -f or -p option vector model; // used with -p, or -e options and similar int countQ = 0; // used with -C option int traceQ = 0; // used with -t option string tracefile = ""; // used with -t option int reverseQ = 0; // used with -r option string reverseInterp = "**kern"; // used with -r and -R options. // sub-spine "b" expansion model: how to generate data for a secondary // spine if the primary spine is not divided. Models are: // 'd': duplicate primary spine (or "a" subspine) data (default) // 'n': null = use a null token // 'r': rest = use a rest instead of a primary spine note (in **kern) // data. 'n' will be used for non-kern spines when 'r' is used. int submodel = 'd'; // used with -m option const char* editorialInterpretation = "yy"; string cointerp = "**kern"; // used with -c option int comodel = 0; // used with -M option const char* subtokenseparator = " "; // used with a future option int interpstate = 0; // used -I or with -i int grepQ = 0; // used with -g option string grepString = ""; // used with -g option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { checkOptions(options, argc, argv); HumdrumStream streamer(options); HumdrumFile infile; while (streamer.read(infile)) { //if (!streamer.eof()) { // cout << "!!!!SEGMENT: " << infile.getFileName() << endl; //} processFile(infile); } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // processFile -- // void processFile(HumdrumFile& infile) { if (countQ) { cout << infile.getMaxTracks() << endl; return; } if (expandQ) { expandSpines(field, subfield, model, infile, expandInterp); } else if (interpQ) { getInterpretationFields(field, subfield, model, infile, interps, interpstate); } else if (reverseQ) { reverseSpines(field, subfield, model, infile, reverseInterp); } else if (fieldQ || excludeQ) { fillFieldData(field, subfield, model, fieldstring, infile); } else if (grepQ) { fillFieldDataByGrep(field, subfield, model, grepString, infile, interpstate); } int j; if (debugQ && !traceQ) { cout << "!! Field Expansion List:"; for (j=0; j<(int)field.size(); j++) { cout << " " << field[j]; if (subfield[j]) { cout << (char)subfield[j]; } if (model[j]) { cout << (char)model[j]; } } cout << endl; } // preserve SEGMENT filename if present (now printed in main()) // infile.printNonemptySegmentLabel(cout); // analyze the input file according to command-line options if (fieldQ || grepQ) { extractFields(infile, field, subfield, model); } else if (excludeQ) { excludeFields(infile, field, subfield, model); } else if (traceQ) { extractTrace(infile, tracefile); } else { cout << infile; } } ////////////////////////////// // // fillFieldDataByGrep -- // void fillFieldDataByGrep(vector& field, vector& subfield, vector& model, const string& searchstring, HumdrumFile& infile, int state) { field.reserve(infile.getMaxTracks()+1); subfield.reserve(infile.getMaxTracks()+1); model.reserve(infile.getMaxTracks()+1); field.resize(0); subfield.resize(0); model.resize(0); vector tracks; tracks.resize(infile.getMaxTracks()+1); fill(tracks.begin(), tracks.end(), 0); PerlRegularExpression pre; int track; int i, j; for (i=0; i& field, vector& subfield, vector& model, HumdrumFile& infile, string& interps, int state) { vector sstrings; // search strings sstrings.reserve(100); sstrings.resize(0); int i, j, k; string buffer; buffer = interps; PerlRegularExpression pre; pre.sar(buffer, "\\s+", "", "g"); // remove spaces from the search string. while (pre.search(buffer, "^([^,]+)")) { string value = pre.getSubmatch(1); if (!value.empty()) { if (value[0] != '*') { value = "**" + value; } } sstrings.push_back(value); pre.sar(buffer, "^[^,]+,?", "", ""); } if (debugQ) { cout << "!! Interpretation strings to search for: " << endl; for (i=0; i<(int)sstrings.size(); i++) { cout << "!!\t" << sstrings[i] << endl; } } vector tracks; tracks.resize(infile.getMaxTracks()+1); fill(tracks.begin(), tracks.end(), 0); // Algorithm below could be made more efficient by // not searching the entire file... for (i=0; i& field, vector& subfield, vector& model, HumdrumFile& infile, string& interp) { vector splits; splits.resize(infile.getMaxTracks()+1); fill(splits.begin(), splits.end(), 0); int i, j; for (i=0; i dummyfield; vector dummysubfield; vector dummymodel; getInterpretationFields(dummyfield, dummysubfield, model, infile, interp, 1); vector interptracks; interptracks.resize(infile.getMaxTracks()+1); fill(interptracks.begin(), interptracks.end(), 0); for (i=0; i<(int)dummyfield.size(); i++) { interptracks[dummyfield[i]] = 1; } int aval = 'a'; int bval = 'b'; int zero = 0; for (i=1; i<(int)splits.size(); i++) { if (splits[i] && (allQ || interptracks[i])) { field.push_back(i); subfield.push_back(aval); model.push_back(zero); field.push_back(i); subfield.push_back(bval); model.push_back(zero); } else { field.push_back(i); subfield.push_back(zero); model.push_back(zero); } } if (debugQ) { cout << "!!expand: "; for (i=0; i<(int)field.size(); i++) { cout << field[i]; if (subfield[i]) { cout << (char)subfield[i]; } if (i < (int)field.size()-1) { cout << ","; } } cout << endl; } } ////////////////////////////// // // reverseSpines -- reverse the order of spines, grouped by the // given exclusive interpretation. // void reverseSpines(vector& field, vector& subfield, vector& model, HumdrumFile& infile, const string& exinterp) { vector target; target.resize(infile.getMaxTracks()+1); fill(target.begin(), target.end(), 0); int t; for (t=1; t<=infile.getMaxTracks(); t++) { if (infile.getTrackExInterp(t) == exinterp) { target[t] = 1; } } field.reserve(infile.getMaxTracks()*2); field.resize(0); int i, j; int lasti = target.size(); for (i=(int)target.size()-1; i>0; i--) { if (target[i]) { lasti = i; field.push_back(i); for (j=i+1; j<(int)target.size(); j++) { if (!target[j]) { field.push_back(j); } else { break; } } } } // if the grouping spine is not first, then preserve the // locations of the pre-spines. int extras = 0; if (lasti != 1) { extras = lasti - 1; field.resize(field.size()+extras); for (i=0; i<(int)field.size()-extras; i++) { field[(int)field.size()-1-i] = field[(int)field.size()-1-extras-i]; } for (i=0; i& field, vector& subfield, vector& model, string& fieldstring, HumdrumFile& infile) { int maxtrack = infile.getMaxTracks(); field.reserve(maxtrack); field.resize(0); subfield.reserve(maxtrack); subfield.resize(0); model.reserve(maxtrack); model.resize(0); PerlRegularExpression pre; string buffer = fieldstring; pre.sar(buffer, "\\s", "", "gs"); int start = 0; int value = 0; value = pre.search(buffer, "^([^,]+,?)"); string tempstr; while (value != 0) { start += value - 1; start += strlen(pre.getSubmatch(1)); processFieldEntry(field, subfield, model, pre.getSubmatch(), infile); tempstr = buffer.c_str() + start; value = pre.search(tempstr, "^([^,]+,?)"); } } ////////////////////////////// // // processFieldEntry -- // 3-6 expands to 3 4 5 6 // $ expands to maximum spine track // $-1 expands to maximum spine track minus 1, etc. // void processFieldEntry(vector& field, vector& subfield, vector& model, const char* astring, HumdrumFile& infile) { int maxtrack = infile.getMaxTracks(); vector ktracks; infile.getKernTracks(ktracks); if (kernQ) { maxtrack = ktracks.size(); } int modletter; int subletter; PerlRegularExpression pre; string buffer = astring; // remove any comma left at end of input astring (or anywhere else) pre.sar(buffer, ",", "", "g"); // first remove $ symbols and replace with the correct values removeDollarsFromString(buffer, maxtrack); int zero = 0; if (pre.search(buffer, "^(\\d+)-(\\d+)$")) { int firstone = strtol(pre.getSubmatch(1), NULL, 10); int lastone = strtol(pre.getSubmatch(2), NULL, 10); if ((firstone < 1) && (firstone != 0)) { cerr << "Error: range token: \"" << astring << "\"" << " contains too small a number at start: " << firstone << endl; cerr << "Minimum number allowed is " << 1 << endl; exit(1); } if ((lastone < 1) && (lastone != 0)) { cerr << "Error: range token: \"" << astring << "\"" << " contains too small a number at end: " << lastone << endl; cerr << "Minimum number allowed is " << 1 << endl; exit(1); } if (firstone > maxtrack) { cerr << "Error: range token: \"" << astring << "\"" << " contains number too large at start: " << firstone << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } if (lastone > maxtrack) { cerr << "Error: range token: \"" << astring << "\"" << " contains number too large at end: " << lastone << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } int i; if (firstone > lastone) { for (i=firstone; i>=lastone; i--) { field.push_back(i); subfield.push_back(zero); model.push_back(zero); } } else { for (i=firstone; i<=lastone; i++) { field.push_back(i); subfield.push_back(zero); model.push_back(zero); } } } else if (pre.search(buffer, "^(\\d+)([a-z]*)")) { int value = strtol(pre.getSubmatch(1), NULL, 10); modletter = 0; subletter = 0; if (strchr(pre.getSubmatch(2), 'a') != NULL) { subletter = 'a'; } if (strchr(pre.getSubmatch(), 'b') != NULL) { subletter = 'b'; } if (strchr(pre.getSubmatch(), 'c') != NULL) { subletter = 'c'; } if (strchr(pre.getSubmatch(), 'd') != NULL) { modletter = 'd'; } if (strchr(pre.getSubmatch(), 'n') != NULL) { modletter = 'n'; } if (strchr(pre.getSubmatch(), 'r') != NULL) { modletter = 'r'; } if ((value < 1) && (value != 0)) { cerr << "Error: range token: \"" << astring << "\"" << " contains too small a number at end: " << value << endl; cerr << "Minimum number allowed is " << 1 << endl; exit(1); } if (value > maxtrack) { cerr << "Error: range token: \"" << astring << "\"" << " contains number too large at start: " << value << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } field.push_back(value); if (value == 0) { subfield.push_back(zero); model.push_back(zero); } else { subfield.push_back(subletter); model.push_back(modletter); } } if (!kernQ) { return; } maxtrack = infile.getMaxTracks(); // Fields to next kern track. // Needs some more bug fixing // Most just needs a fix to preserve old field data // For secondary passes into thi function. vector newfield; vector newsubfield; vector newmodel; int i, j; for (i=0; i<(int)field.size(); i++) { if (field[i] != 0) { field[i] = ktracks[field[i] - 1]; } } int start, stop; for (i=0; i<(int)field.size(); i++) { newfield.push_back(field[i]); newsubfield.push_back(subfield[i]); newmodel.push_back(model[i]); start = field[i] + 1; if (i < (int)field.size()-1) { stop = field[i+1]; } else { stop = maxtrack+1; } for (j=start; j& field, vector& subfield, vector& model) { int i; int j; int start = 0; for (i=0; i& field, vector& subfield, vector& model) { PerlRegularExpression pre; int i; int j; int t; int start = 0; int target; int subtarget; int modeltarget; string spat; for (i=0; i& field, vector& subfield, vector& model, int targetindex, HumdrumFile& infile, int line, int cospine, int comodel, int submodel, const string& cointerp) { vector cotokens; cotokens.reserve(50); char buffer[1024]; int i, j, k; int index; if (infile[line].isInterpretation()) { cout << infile[line][cospine]; return; } if (infile[line].isMeasure()) { cout << infile[line][cospine]; return; } if (infile[line].isLocalComment()) { cout << infile[line][cospine]; return; } int count = infile[line].getTokenCount(cospine); for (k=0; k spineindex; vector subspineindex; spineindex.reserve(infile.getMaxTracks()*2); spineindex.resize(0); subspineindex.reserve(infile.getMaxTracks()*2); subspineindex.resize(0); for (j=0; j& cotokens, vector& spineindex, vector& subspineindex) { int i; int found = 0; for (i=0; i<(int)spineindex.size(); i++) { if (spineindex[i] == spine) { if (start == 0) { start++; } else { cout << subtokenseparator; } if (i<(int)cotokens.size()) { cout << cotokens[i]; } else { cout << "."; } found = 1; } } if (!found) { if (start == 0) { start++; } else { cout << subtokenseparator; } cout << "."; } } ////////////////////////////// // // dealWithSecondarySubspine -- what to print if a secondary spine // does not exist on a line. // void dealWithSecondarySubspine(vector& field, vector& subfield, vector& model, int targetindex, HumdrumFile& infile, int line, int spine, int submodel) { int& i = line; int& j = spine; PerlRegularExpression pre; string buffer; switch (infile[line].getType()) { case E_humrec_data_comment: if ((submodel == 'n') || (submodel == 'r')) { cout << "!"; } else { cout << infile[i][j]; } break; case E_humrec_data_kern_measure: cout << infile[i][j]; break; case E_humrec_interpretation: if ((submodel == 'n') || (submodel == 'r')) { cout << "*"; } else { cout << infile[i][j]; } break; case E_humrec_data: if (submodel == 'n') { cout << "."; } else if (submodel == 'r') { if (strcmp(infile[i][j], ".") == 0) { cout << "."; } else if (strchr(infile[i][j], 'q') != NULL) { cout << "."; } else if (strchr(infile[i][j], 'Q') != NULL) { cout << "."; } else { buffer = infile[i][j]; if (pre.search(buffer, "{")) { cout << "{"; } // remove secondary chord notes: pre.sar(buffer, " .*", "", ""); // remove unnecessary characters (such as stem direction): pre.sar(buffer, "[^}pPqQA-Ga-g0-9.;%#nr-]", "", "g"); // change pitch to rest: pre.sar(buffer, "[A-Ga-g#n-]+", "r", ""); // add editorial marking unless -Y option is given: if (strcmp(editorialInterpretation, "") != 0) { if (pre.search(buffer, "rr")) { pre.sar(buffer, "(?<=rr)", editorialInterpretation, ""); pre.sar(buffer, "rr", "r"); } else { pre.sar(buffer, "(?<=r)", editorialInterpretation, ""); } } cout << buffer; } } else { cout << infile[i][j]; } break; default: cerr << "Should not get to this line of code" << endl; exit(1); } } ////////////////////////////// // // getSearchPat -- // void getSearchPat(string& spat, int target, const char* modifier) { if (strlen(modifier) > 20) { cerr << "Error in GetSearchPat" << endl; exit(1); } spat.reserve(32); spat = "\\("; char buffer[32] = {0}; sprintf(buffer, "%d", target); spat += buffer; spat += "\\)"; spat += modifier; } ////////////////////////////// // // dealWithSpineManipulators -- check for proper Humdrum syntax of // spine manipulators (**, *-, *x, *v, *^) when creating the output. // void dealWithSpineManipulators(HumdrumFile& infile, int line, vector& field, vector& subfield, vector& model) { vector vmanip; // counter for *v records on line vmanip.resize(infile[line].getFieldCount()); fill(vmanip.begin(), vmanip.end(), 0); vector xmanip; // counter for *x record on line xmanip.resize(infile[line].getFieldCount()); fill(xmanip.begin(), xmanip.end(), 0); int i = 0; int j; for (j=0; j<(int)vmanip.size(); j++) { if (strcmp(infile[line][j], "*v") == 0) { vmanip[j] = 1; } if (strcmp(infile[line][j], "*x") == 0) { xmanip[j] = 1; } } int counter = 1; for (i=1; i<(int)xmanip.size(); i++) { if ((xmanip[i] == 1) && (xmanip[i-1] == 1)) { xmanip[i] = counter; xmanip[i-1] = counter; counter++; } } counter = 1; i = 0; while (i < (int)vmanip.size()) { if (vmanip[i] == 1) { while ((i < (int)vmanip.size()) && (vmanip[i] == 1)) { vmanip[i] = counter; i++; } counter++; } i++; } vector fieldoccur; // nth occurance of an input spine in the output fieldoccur.resize(field.size()); fill(fieldoccur.begin(), fieldoccur.end(), 0); vector trackcounter; // counter of input spines occurances in output trackcounter.resize(infile.getMaxTracks()+1); fill(trackcounter.begin(), trackcounter.end(), 0); for (i=0; i<(int)field.size(); i++) { if (field[i] != 0) { trackcounter[field[i]]++; fieldoccur[i] = trackcounter[field[i]]; } } vector tempout; vector vserial; vector xserial; vector fpos; // input column of output spine tempout.reserve(1000); tempout.resize(0); vserial.resize(1000); vserial.resize(0); xserial.resize(1000); xserial.resize(0); fpos.resize(1000); fpos.resize(0); string spat; string spinepat; PerlRegularExpression pre; int subtarget; int modeltarget; int xdebug = 0; int vdebug = 0; int suppress = 0; int t; int target; int tval; for (t=0; t<(int)field.size(); t++) { target = field[t]; subtarget = subfield[t]; modeltarget = model[t]; if (modeltarget == 0) { switch (subtarget) { case 'a': case 'b': modeltarget = submodel; break; case 'c': modeltarget = comodel; } } suppress = 0; if (target == 0) { if (strncmp(infile[line][0], "**", 2) == 0) { storeToken(tempout, "**blank"); tval = 0; vserial.push_back(tval); xserial.push_back(tval); fpos.push_back(tval); } else if (strcmp(infile[line][0], "*-") == 0) { storeToken(tempout, "*-"); tval = 0; vserial.push_back(tval); xserial.push_back(tval); fpos.push_back(tval); } else { storeToken(tempout, "*"); tval = 0; vserial.push_back(tval); xserial.push_back(tval); fpos.push_back(tval); } } else { for (j=0; j 1) { // check the last item in the list int index = (int)xserial.size()-1; if (tempout[index] == "*x") { if (xserial[index] != xserial[index-1]) { xserial[index] = 0; tempout[index] = "*"; } } } // check for proper *v syntax ///////////////////////////////// vector vsplit; vsplit.resize((int)vserial.size()); fill(vsplit.begin(), vsplit.end(), 0); // identify necessary line splits for (i=0; i<(int)vserial.size()-1; i++) { if (!vserial[i]) { continue; } while ((i<(int)vserial.size()-1) && (vserial[i]==vserial[i+1])) { i++; } if ((i<(int)vserial.size()-1) && vserial[i]) { if (vserial.size() > 1) { if (vserial[i+1]) { vsplit[i+1] = 1; } } } } // remove single *v spines: for (i=0; i<(int)vsplit.size()-1; i++) { if (vsplit[i] && vsplit[i+1]) { if (tempout[i] == "*v") { tempout[i] = "*"; vsplit[i] = 0; } } } if (debugQ) { cout << "!!vsplit array: "; for (i=0; i<(int)vsplit.size(); i++) { cout << " " << vsplit[i]; } cout << endl; } if (vsplit.size() > 0) { if (vsplit[(int)vsplit.size()-1]) { if (tempout[(int)tempout.size()-1] == "*v") { tempout[(int)tempout.size()-1] = "*"; vsplit[(int)vsplit.size()-1] = 0; } } } int vcount = 0; for (i=0; i<(int)vsplit.size(); i++) { vcount += vsplit[i]; } if (vcount) { printMultiLines(vsplit, vserial, tempout); } int start = 0; for (i=0; i<(int)tempout.size(); i++) { if (tempout[i] != "") { if (start != 0) { cout << "\t"; } cout << tempout[i]; start++; } } if (start) { cout << '\n'; } } ////////////////////////////// // // printMultiLines -- print separate *v lines. // void printMultiLines(vector& vsplit, vector& vserial, vector& tempout) { int i; int splitpoint = -1; for (i=0; i<(int)vsplit.size(); i++) { if (vsplit[i]) { splitpoint = i; break; } } if (debugQ) { cout << "!!tempout: "; for (i=0; i<(int)tempout.size(); i++) { cout << tempout[i] << " "; } cout << endl; } if (splitpoint == -1) { return; } int start = 0; int printv = 0; for (i=0; i& storage, const char* string) { storage.push_back(string); } void storeToken(vector& storage, int index, const char* string) { storage[index] = string; } ////////////////////////////// // // isInList -- returns true if first number found in list of numbers. // returns the matching index plus one. // int isInList(int number, vector& listofnum) { int i; for (i=0; i<(int)listofnum.size(); i++) { if (listofnum[i] == number) { return i+1; } } return 0; } ////////////////////////////// // // getTraceData -- // void getTraceData(vector& startline, vector >& fields, const string& tracefile, HumdrumFile& infile) { char buffer[1024] = {0}; PerlRegularExpression pre; int linenum; startline.reserve(10000); startline.resize(0); fields.reserve(10000); fields.resize(0); ifstream input; input.open(tracefile.c_str()); if (!input.is_open()) { cerr << "Error: cannot open file for reading: " << tracefile << endl; exit(1); } string temps; vector field; vector subfield; vector model; input.getline(buffer, 1024); while (!input.eof()) { if (pre.search(buffer, "^\\s*$")) { continue; } if (!pre.search(buffer, "(\\d+)")) { continue; } linenum = strtol(pre.getSubmatch(1), NULL, 10); linenum--; // adjust so that line 0 is the first line in the file temps = buffer; pre.sar(temps, "\\d+", "", ""); pre.sar(temps, "[^,\\s\\d\\$\\-].*", ""); // remove any possible comments pre.sar(temps, "\\s", "", "g"); if (pre.search(temps, "^\\s*$")) { // no field data to process online continue; } startline.push_back(linenum); string ttemp = temps; fillFieldData(field, subfield, model, ttemp, infile); fields.push_back(field); input.getline(buffer, 1024); } } ////////////////////////////// // // extractTrace -- // void extractTrace(HumdrumFile& infile, const string& tracefile) { vector startline; vector > fields; getTraceData(startline, fields, tracefile, infile); int i, j; if (debugQ) { for (i=0; i<(int)startline.size(); i++) { cout << "!!TRACE " << startline[i]+1 << ":\t"; for (j=0; j<(int)fields[i].size(); j++) { cout << fields[i][j] << " "; } cout << "\n"; } } if (startline.size() == 0) { for (i=0; i& field) { int j; int t; int start = 0; int target; start = 0; for (t=0; t<(int)field.size(); t++) { target = field[t]; for (j=0; j