#
#
# add_file "mangle.cc"
# content [004a0da4eb54257a40e5b33b45e3cecfccae36e3]
#
============================================================
--- mangle.cc 004a0da4eb54257a40e5b33b45e3cecfccae36e3
+++ mangle.cc 004a0da4eb54257a40e5b33b45e3cecfccae36e3
@@ -0,0 +1,125 @@
+// 2006-04-13 Timothy Brownawell
+// GPL v2 or greater
+//
+// link with boost_program_options
+//
+// mangle -p pattern -d delim [-d delim...] -f fieldspec [-f fieldspec...]
+// pattern is a printf-style pattern
+// delim is the stanza delimiter
+// fieldspec is key,num , where key is a key name and values are numbered
+// 1 to n, and -n to -1
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "io.hh"
+
+using std::string;
+using std::vector;
+using std::cin;
+using std::cout;
+using std::pair;
+using std::make_pair;
+using basic_io::stanza;
+using basic_io::stanza_reader;
+using boost::lexical_cast;
+
+namespace po = boost::program_options;
+
+int main(int argc, char **argv)
+{
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "print this message")
+ ("pattern,p", po::value(), "output pattern, like printf")
+ ("field,f", po::value >(), "key,num field specifier")
+ ("delim,d", po::value >(), "key that begins a stanza")
+ ("reverse,V", "output non-matching stanzas")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help") || !vm.count("pattern") || !vm.count("delim"))
+ {
+ cout << desc << "\n";
+ cout << "--pattern is required, "
+ << "and --delim must be given at least once.\n";
+ cout << "field 0 is the key name\n";
+ cout << "other fields are numberd 1 to n, and -n to -1\n";
+ return 1;
+ }
+ string pattern = vm["pattern"].as();
+ {
+ unsigned int p=pattern.find('\\');
+ unsigned int pbase = p;
+ while (p < pattern.size()-1)
+ {
+ switch(pattern[p+1])
+ {
+ case 'n': pattern.replace(p, 2, "\n"); break;
+ case 'r': pattern.replace(p, 2, "\r"); break;
+ case 't': pattern.replace(p, 2, "\t"); break;
+ case 'v': pattern.replace(p, 2, "\v"); break;
+ case '"': pattern.replace(p, 2, "\""); break;
+ case '\'': pattern.replace(p, 2, "\'"); break;
+ case '?': pattern.replace(p, 2, "\?"); break;
+ case 'a': pattern.replace(p, 2, "\a"); break;
+ case 'b': pattern.replace(p, 2, "\b"); break;
+ case 'f': pattern.replace(p, 2, "\f"); break;
+ case '\\': pattern.replace(p, 2, "\\"); break;
+ default:
+ pbase = p+1;
+ }
+ p = pattern.find('\\', pbase);
+ }
+ }
+
+ vector > fields;
+ {
+ vector f = vm["field"].as >();
+ for (vector::iterator i = f.begin(); i != f.end(); ++i)
+ {
+ unsigned int n = i->rfind(',');
+ string key = i->substr(0, n);
+ int pos = lexical_cast(i->substr(n+1));
+ fields.push_back(make_pair(key, pos));
+ }
+ }
+
+ stanza st;
+ stanza_reader sr(cin, vm["delim"].as >());
+ bool first = true;
+ while (sr.get(st))
+ {
+ boost::format f(pattern);
+ for (vector >::iterator i = fields.begin();
+ i != fields.end(); ++i)
+ {
+ using basic_io::item;
+ string s;
+ for (vector- ::iterator j = st.items.begin();
+ j != st.items.end(); ++j)
+ {
+ if (j->key == i->first)
+ {
+ if (!i->second)
+ s = j->key;
+ else if (i->second < 0 && -i->second <= j->values.size())
+ s = j->values[j->values.size() + i->second].parsed;
+ else if (i->second <= j->values.size())
+ s = j->values[i->second-1].parsed;
+ break;
+ }
+ }
+ f % s;
+ }
+ cout<