// // Programmer: Craig Stuart Sapp // Creation Date: Sun Apr 19 20:03:05 PDT 2009 // Last Modified: Tue May 4 23:11:52 PDT 2009 (added -t, -c, -B, --sep options) // Last Modified: Tue May 5 09:54:01 PDT 2009 (added -p, -P, --and options) // Last Modified: Mon May 11 20:56:43 PDT 2009 (fix initial beat for comments) // Last Modified: Wed Apr 28 18:49:29 PDT 2010 (added -T and -D options) // Filename: ...sig/examples/all/hgrep.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/hgrep.cpp // Syntax: C++; museinfo // // Description: Grep with Humdrum intelligence built into it. // #include "humdrum.h" #include #include #include #ifndef OLDCPP #include #include #include using namespace std; #else #include #include #include #endif ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void usage (const char* command); void doSearch (const char* searchstring, HumdrumFile& infile, const char* filename); void printPreInfo (const char* filename, HumdrumFile& infile, double measure, int line, int spine = -1); char* searchAndReplace (char* buffer, const char* searchstring, const char* replacestring, const char* datastring); void displayFraction (double fraction); void fillAndSearches (Array& relist, Array >& exlist, const char* string); int tokenSearch (int& column, HumdrumFile& infile, int line, regex_t& re); int singleTokenSearch (int& column, HumdrumFile& infile, int line, regex_t& re, const char* exstring); void destroyAndSearches (Array& relist); double getBeatOfNextData (HumdrumFile& infile, int line); // User interface variables: Options options; const char* searchstring = ""; // first argument int kernQ = 0; // used with -k option int dataQ = 0; // used with -d option int tandemQ = 0; // used with -t option int commentQ = 0; // used with -C option int primaryQ = 0; // used with -p option int nonprimaryQ = 0; // used with -P option int bibliographicQ = 0; // used with -B option int absbeatQ = 0; // used with -a option int fracQ = 0; // used with -f option int spineQ = 0; // used with -s option int beatQ = 0; // used with -b option int measureQ = 0; // used with -m option int quietQ = 0; // used with -q option int exinterpQ = 0; // used with -x option int tokenizeQ = 0; // used with -T option int datastopQ = 0; // used with -D option const char* exinterps = ""; // used with -x option char separator[1024] = {0}; // used with --sep option Array Andlist; // used with --and option Array > Andexinterp; // used with --and option // standard grep option emulations: int fileQ = 0; // used with -H option int matchfilesQ = 0; // used with -l option int nomatchfilesQ = 0; // used with -L option int ignorecaseQ = 0; // used with -i option int basicQ = 0; // used with -G option int lineQ = 0; // used with -n option int invertQ = 0; // used with -v option ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); const char* filename = ""; int i; HumdrumFile infile; int numinputs = options.getArgCount() - 1; for (i=0; i 0) { for (int aa=0; aa= 0)) { cout << "spine " << spine+1 << separator; } /* else if (spineQ) { cout << "spine " << 1 << separator; } */ if (measureQ) { cout << "measure " << measure << separator; } if (beatQ) { if (infile[line].getBeat() == 0.0) { cout << "beat " << getBeatOfNextData(infile, line) << separator; } else { cout << "beat " << infile[line].getBeat() << separator; } } if (absbeatQ) { cout << "absbeat " << infile[line].getAbsBeat() << separator; } if (fracQ) { cout << "frac "; displayFraction(infile[line].getAbsBeat()/infile.getTotalDuration()); cout << separator; } } ////////////////////////////// // // getBeatOfNextData -- used to fix the beat position of comments // at the start of measures which would be labeled as // beat 0 instead of beat 1. // double getBeatOfNextData(HumdrumFile& infile, int line) { int i; double output = infile[line].getBeat(); for (i=line; i 0.0 && fraction < 1.0) { value = int(fraction * 1000.0 + 0.5); cout << "0."; if (value < 100) { cout << "0"; } if (value < 10) { cout << "0"; } cout << value; } else { cout << fraction; } } ////////////////////////////// // // checkOptions -- // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|absbeat=b", "display the absolute beat postion of a match"); opts.define("b|beat=b", "display the metrical beat postion of a match"); opts.define("B|bibliographic=b", "search only bibliographic records"); opts.define("C|comment=b", "search only comment records"); opts.define("d|data=b", "search only data records"); opts.define("f|fraction|frac=b", "disp. pos. as fraction of total length"); opts.define("k|kern=b", "search only **kern records"); opts.define("p|primary=b", "search only primary spines"); opts.define("P|nonprimary=b", "search only non-primary spines"); opts.define("q|quiet=b", "don't display matching lines (just pre markers)"); opts.define("t|tandem=b", "search only data records"); opts.define("s|spine=b", "display spine number of match"); opts.define("m|measure=b", "display measure number of match"); opts.define("x|exinterp=s", "search only listed exinterps"); opts.define("T|tokenize=b", "search tokens independently"); opts.define("D|data-stop=b", "stop search at first data record"); opts.define("sep|separator=s::", "data separator string"); opts.define("and=s:", "anded search strings"); // options which mimic regular grep program: opts.define("G|basic-regexp=b", "use basic regular expression syntax"); opts.define("H|with-filename=b", "display filename at start match line"); opts.define("h|no-filename=b","do not display filename on match line"); opts.define("L|files-without-match=b", "list files without match"); opts.define("l|files-with-match=b", "list files with match(es)"); opts.define("i|ignore-case=b", "ignore case in matches"); opts.define("n|line-number=b", "display line number of match"); opts.define("v|invert-match=b", "invert the matching criteria"); 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, April 2009" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 5 May 2009" << 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); } if (opts.getArgCount() < 1) { cerr << "Error: you must supply a search string\n"; exit(1); } searchstring = opts.getArg(1); basicQ = opts.getBoolean("basic-regexp"); fileQ = opts.getBoolean("with-filename"); matchfilesQ = opts.getBoolean("files-with-match"); nomatchfilesQ = opts.getBoolean("files-without-match"); ignorecaseQ = opts.getBoolean("ignore-case"); lineQ = opts.getBoolean("line-number"); invertQ = opts.getBoolean("invert-match"); absbeatQ = opts.getBoolean("absbeat"); beatQ = opts.getBoolean("beat"); quietQ = opts.getBoolean("quiet"); kernQ = opts.getBoolean("kern"); fracQ = opts.getBoolean("fraction"); dataQ = opts.getBoolean("data"); tandemQ = opts.getBoolean("tandem"); primaryQ = opts.getBoolean("primary"); commentQ = opts.getBoolean("comment"); nonprimaryQ = opts.getBoolean("nonprimary"); bibliographicQ= opts.getBoolean("bibliographic"); spineQ = opts.getBoolean("spine"); measureQ = opts.getBoolean("measure"); tokenizeQ = opts.getBoolean("tokenize"); datastopQ = opts.getBoolean("data-stop"); exinterpQ = opts.getBoolean("exinterp"); exinterps = opts.getString("exinterp"); char tempbuffer[1024] = {0}; searchAndReplace(tempbuffer, "[\\]t", " ", opts.getString("separator")); searchAndReplace(separator, "[\\]n", "\n", tempbuffer); if (matchfilesQ && nomatchfilesQ) { nomatchfilesQ = 0; } Andlist.setSize(0); Andexinterp.setSize(0); if (opts.getBoolean("and")) { fillAndSearches(Andlist, Andexinterp, opts.getString("and")); } } ////////////////////////////// // // fillAndSearches -- exinterp strings are sticky. // void fillAndSearches(Array& relist, Array >& exlist, const char* string) { int len = strlen(string); Array mybuffer(len*2+128); mybuffer.setAll('\0'); char *buffer = mybuffer.getBase(); relist.setSize(100); relist.setSize(0); char exbuff[1024] = {0}; int status; int compflags = 0; if (!basicQ) { compflags = compflags | REG_EXTENDED; } if (ignorecaseQ) { compflags = compflags | REG_ICASE; } searchAndReplace(buffer, "[\\]n", "\n", string); char* ptr = strtok(buffer, "\n"); while (ptr != NULL) { if (strncmp("**", ptr, 2) == 0) { strcpy(exbuff, ptr); ptr = strtok(NULL, "\n"); continue; } relist.setSize(relist.getSize()+1); //cout << "SEARCH STRING ADDED: " << ptr << endl; //cout << "ADDRESS IS " << (int)(&(relist[relist.getSize()-1])) << endl; status = regcomp(&(relist[relist.getSize()-1]), ptr, compflags); if (status !=0) { regerror(status, &(relist[relist.getSize()-1]), buffer, 1024); cerr << buffer << endl; exit(1); } exlist.setSize(exlist.getSize()+1); exlist[exlist.getSize()-1].setSize(strlen(exbuff)+1); strcpy(exlist[exlist.getSize()-1].getBase(), exbuff); ptr = strtok(NULL, "\n"); } } ////////////////////////////// // // destroyAndSearches -- // void destroyAndSearches(Array& relist) { for (int i=0; i