Switch to side-by-side view

--- a/src/smallut.cpp
+++ b/src/smallut.cpp
@@ -31,6 +31,16 @@
 #include <string.h>
 #include <math.h>
 
+// Older compilers don't support stdc++ regex, but Windows does not
+// have the Linux one. Have a simple class to solve the simple cases.
+#if defined(_WIN32)
+#define USE_STD_REGEX
+#include <regex>
+#else
+#define USE_LINUX_REGEX
+#include <regex.h>
+#endif
+
 #include <string>
 #include <iostream>
 #include <list>
@@ -87,6 +97,23 @@
     stringtolower(o);
     return o;
 }
+
+void stringtoupper(string& io)
+{
+    string::iterator it = io.begin();
+    string::iterator ite = io.end();
+    while (it != ite) {
+        *it = ::toupper(*it);
+        it++;
+    }
+}
+string stringtoupper(const string& i)
+{
+    string o = i;
+    stringtoupper(o);
+    return o;
+}
+
 extern int stringisuffcmp(const string& s1, const string& s2)
 {
     string::const_reverse_iterator r1 = s1.rbegin(), re1 = s1.rend(),
@@ -541,6 +568,34 @@
     return out;
 }
 
+// Escape value to be suitable as C++ source double-quoted string (for
+// generating a c++ program
+string makeCString(const string& in)
+{
+    string out;
+    out += "\"";
+    for (string::size_type pos = 0; pos < in.length(); pos++) {
+        switch (in.at(pos)) {
+        case '"':
+            out += "\\\"";
+            break;
+        case '\n':
+            out += "\\n";
+            break;
+        case '\r':
+            out += "\\r";
+            break;
+        case '\\':
+            out += "\\\\";
+            break;
+        default:
+            out += in.at(pos);
+        }
+    }
+    out += "\"";
+    return out;
+}
+
 
 // Substitute printf-like percent cmds inside a string
 bool pcSubst(const string& in, string& out, const map<char, string>& subs)
@@ -1107,6 +1162,7 @@
     errbuf[0] = 0;
     // We don't use ret, it's there to silence a cc warning
     char *ret = (char *)strerror_r(_errno, errbuf, ERRBUFSZ);
+    (void)ret;
     reason->append(errbuf);
 #endif
 }
@@ -1173,6 +1229,100 @@
         return locale;
     }
     return locale.substr(0, under);
+}
+
+#ifdef USE_STD_REGEX
+
+class SimpleRegexp::Internal {
+public:
+    Internal(const string& exp, int flags, int nm)
+        : expr(exp,
+               basic_regex<char>::flag_type(regex_constants::extended |
+                   ((flags&SRE_ICASE) ? regex_constants::icase : 0) |
+                   ((flags&SRE_NOSUB) ? regex_constants::nosubs : 0)
+                   )), ok(true), nmatch(nm) {
+    }
+    bool ok;
+    std::regex expr;
+    std::smatch res;
+    int nmatch;
+};
+
+bool SimpleRegexp::simpleMatch(const string& val) const
+{
+    if (!ok())
+        return false;
+    return regex_match(val, m->res, m->expr);
+}
+
+string SimpleRegexp::getMatch(const string& val, int i) const
+{
+    return m->res.str(i);
+}
+
+#else // -> !WIN32
+
+class SimpleRegexp::Internal {
+public:
+    Internal(const string& exp, int flags, int nm) : nmatch(nm) {
+        if (regcomp(&expr, exp.c_str(), REG_EXTENDED |
+                    ((flags&SRE_ICASE) ? REG_ICASE : 0) |
+                    ((flags&SRE_NOSUB) ? REG_NOSUB : 0)) == 0) {
+            ok = true;
+        } else {
+            ok = false;
+        }
+        matches.reserve(nmatch+1);
+    }
+    ~Internal() {
+        regfree(&expr);
+    }
+    bool ok;
+    regex_t expr;
+    int nmatch;
+    vector<regmatch_t> matches;
+};
+
+bool SimpleRegexp::simpleMatch(const string& val) const
+{
+    if (!ok())
+        return false;
+    if (regexec(&m->expr, val.c_str(), m->nmatch+1, &m->matches[0], 0) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+string SimpleRegexp::getMatch(const string& val, int i) const
+{
+    if (i > m->nmatch) {
+        return string();
+    }
+    return val.substr(m->matches[i].rm_so,
+                      m->matches[i].rm_eo - m->matches[i].rm_so);
+}
+
+#endif // win/notwinf
+
+SimpleRegexp::SimpleRegexp(const string& exp, int flags, int nmatch)
+    : m(new Internal(exp, flags, nmatch))
+{
+}
+
+SimpleRegexp::~SimpleRegexp()
+{
+    delete m;
+}
+
+bool SimpleRegexp::ok() const
+{
+    return m->ok;
+}
+
+bool SimpleRegexp::operator() (const string& val) const
+{
+    return simpleMatch(val);
 }
 
 // Initialization for static stuff to be called from main thread before going
@@ -1249,7 +1399,7 @@
     thisprog = *argv++;
     argc--;
 
-#if 1
+#if 0
     if (argc <= 0) {
         cerr << "Usage: smallut <stringtosplit>" << endl;
         exit(1);
@@ -1400,7 +1550,23 @@
         cout << it->first << " " << it->second << " " <<
              stringuppercmp(it->first, it->second) << endl;
     }
-
+#elif 0
+    SimpleRegexp exp("[ \t]*#[ \t]*([a-zA-Z0-9]+)[ \t]*=.*", 0, 1);
+    //SimpleRegexp exp(" # ([a-zA-Z0-9]+) =.*", 0, 10);
+    //SimpleRegexp exp(" # (varnm) = sdf sdf sdf ", 0, 10);
+    //SimpleRegexp exp(".*", 0);
+    string tomatch(" # varnm = sdf sdf sdf ");
+    if (exp.simpleMatch(tomatch)) {
+        cout << "Match !\n";
+        cout << "Submatch[0]: [" << exp.getMatch(tomatch, 0) << "]\n";
+        cout << "Submatch[1]: [" << exp.getMatch(tomatch, 1) << "]\n";
+        return 0;
+    } else {
+        cerr << "No match\n";
+        return 1;
+    }
+#elif 1
+    cout << makeCString("\"hello\" world\n2nd line") << endl;
 #endif
 }