Index: libcfa/src/collections/string.cfa
===================================================================
--- libcfa/src/collections/string.cfa	(revision 01510fefafb44ae9c0d334505d88759ca0fd9d42)
+++ libcfa/src/collections/string.cfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -157,19 +157,28 @@
 // Comparison
 
-bool ?==?(const string & s, const string & other) {
-    return *s.inner == *other.inner;
-}
-
-bool ?!=?(const string & s, const string & other) {
-    return *s.inner != *other.inner;
-}
-
-bool ?==?(const string & s, const char * other) {
-    return *s.inner == other;
-}
-
-bool ?!=?(const string & s, const char * other) {
-    return *s.inner != other;
-}
+int  cmp (const string &s1, const string &s2) { return cmp(*s1.inner ,  *s2.inner); }
+bool ?==?(const string &s1, const string &s2) { return     *s1.inner == *s2.inner ; }
+bool ?!=?(const string &s1, const string &s2) { return     *s1.inner != *s2.inner ; }
+bool ?>? (const string &s1, const string &s2) { return     *s1.inner >  *s2.inner ; }
+bool ?>=?(const string &s1, const string &s2) { return     *s1.inner >= *s2.inner ; }
+bool ?<=?(const string &s1, const string &s2) { return     *s1.inner <= *s2.inner ; }
+bool ?<? (const string &s1, const string &s2) { return     *s1.inner <  *s2.inner ; }
+
+int  cmp (const string &s1, const char*   s2) { return cmp(*s1.inner ,   s2      ); }
+bool ?==?(const string &s1, const char*   s2) { return     *s1.inner ==  s2       ; }
+bool ?!=?(const string &s1, const char*   s2) { return     *s1.inner !=  s2       ; }
+bool ?>? (const string &s1, const char*   s2) { return     *s1.inner >   s2       ; }
+bool ?>=?(const string &s1, const char*   s2) { return     *s1.inner >=  s2       ; }
+bool ?<=?(const string &s1, const char*   s2) { return     *s1.inner <=  s2       ; }
+bool ?<? (const string &s1, const char*   s2) { return     *s1.inner <   s2       ; }
+
+int  cmp (const char*   s1, const string &s2) { return cmp( s1       ,  *s2.inner); }
+bool ?==?(const char*   s1, const string &s2) { return      s1       == *s2.inner ; }
+bool ?!=?(const char*   s1, const string &s2) { return      s1       != *s2.inner ; }
+bool ?>? (const char*   s1, const string &s2) { return      s1       >  *s2.inner ; }
+bool ?>=?(const char*   s1, const string &s2) { return      s1       >= *s2.inner ; }
+bool ?<=?(const char*   s1, const string &s2) { return      s1       <= *s2.inner ; }
+bool ?<? (const char*   s1, const string &s2) { return      s1       <  *s2.inner ; }
+
 
 ////////////////////////////////////////////////////////
Index: libcfa/src/collections/string.hfa
===================================================================
--- libcfa/src/collections/string.hfa	(revision 01510fefafb44ae9c0d334505d88759ca0fd9d42)
+++ libcfa/src/collections/string.hfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -116,8 +116,28 @@
 
 // Comparisons
-bool ?==?(const string & s, const string & other);
-bool ?!=?(const string & s, const string & other);
-bool ?==?(const string & s, const char * other);
-bool ?!=?(const string & s, const char * other);
+int  cmp (const string &, const string &);
+bool ?==?(const string &, const string &);
+bool ?!=?(const string &, const string &);
+bool ?>? (const string &, const string &);
+bool ?>=?(const string &, const string &);
+bool ?<=?(const string &, const string &);
+bool ?<? (const string &, const string &);
+
+int  cmp (const string &, const char*);
+bool ?==?(const string &, const char*);
+bool ?!=?(const string &, const char*);
+bool ?>? (const string &, const char*);
+bool ?>=?(const string &, const char*);
+bool ?<=?(const string &, const char*);
+bool ?<? (const string &, const char*);
+
+int  cmp (const char*, const string &);
+bool ?==?(const char*, const string &);
+bool ?!=?(const char*, const string &);
+bool ?>? (const char*, const string &);
+bool ?>=?(const char*, const string &);
+bool ?<=?(const char*, const string &);
+bool ?<? (const char*, const string &);
+
 
 // Slicing
Index: libcfa/src/collections/string_res.cfa
===================================================================
--- libcfa/src/collections/string_res.cfa	(revision 01510fefafb44ae9c0d334505d88759ca0fd9d42)
+++ libcfa/src/collections/string_res.cfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -637,19 +637,42 @@
 // Comparisons
 
-
-bool ?==?(const string_res &s1, const string_res &s2) {
-    return ByteCmp( s1.Handle.s, 0, s1.Handle.lnth, s2.Handle.s, 0, s2.Handle.lnth) == 0;
-}
-
-bool ?!=?(const string_res &s1, const string_res &s2) {
-    return !(s1 == s2);
-}
-bool ?==?(const string_res &s, const char* other) {
-    string_res sother = other;
-    return s == sother;
-}
-bool ?!=?(const string_res &s, const char* other) {
-    return !(s == other);
-}
+int cmp(const string_res &s1, const string_res &s2) {
+    // return 0;
+    int ans1 = memcmp(s1.Handle.s, s2.Handle.s, min(s1.Handle.lnth, s2.Handle.lnth));
+    if (ans1 != 0) return ans1;
+    return s1.Handle.lnth - s2.Handle.lnth;
+}
+
+bool ?==?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) == 0; }
+bool ?!=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) != 0; }
+bool ?>? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) >  0; }
+bool ?>=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
+bool ?<=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
+bool ?<? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) <  0; }
+
+int cmp (const string_res &s1, const char* s2) {
+    string_res s2x = s2;
+    return cmp(s1, s2x);
+}
+
+bool ?==?(const string_res &s1, const char* s2) { return cmp(s1, s2) == 0; }
+bool ?!=?(const string_res &s1, const char* s2) { return cmp(s1, s2) != 0; }
+bool ?>? (const string_res &s1, const char* s2) { return cmp(s1, s2) >  0; }
+bool ?>=?(const string_res &s1, const char* s2) { return cmp(s1, s2) >= 0; }
+bool ?<=?(const string_res &s1, const char* s2) { return cmp(s1, s2) <= 0; }
+bool ?<? (const string_res &s1, const char* s2) { return cmp(s1, s2) <  0; }
+
+int cmp (const char* s1, const string_res & s2) {
+    string_res s1x = s1;
+    return cmp(s1x, s2);
+}
+
+bool ?==?(const char* s1, const string_res &s2) { return cmp(s1, s2) == 0; }
+bool ?!=?(const char* s1, const string_res &s2) { return cmp(s1, s2) != 0; }
+bool ?>? (const char* s1, const string_res &s2) { return cmp(s1, s2) >  0; }
+bool ?>=?(const char* s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
+bool ?<=?(const char* s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
+bool ?<? (const char* s1, const string_res &s2) { return cmp(s1, s2) <  0; }
+
 
 
Index: libcfa/src/collections/string_res.hfa
===================================================================
--- libcfa/src/collections/string_res.hfa	(revision 01510fefafb44ae9c0d334505d88759ca0fd9d42)
+++ libcfa/src/collections/string_res.hfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -142,8 +142,27 @@
 
 // Comparisons
-bool ?==?(const string_res &s, const string_res &other);
-bool ?!=?(const string_res &s, const string_res &other);
-bool ?==?(const string_res &s, const char* other);
-bool ?!=?(const string_res &s, const char* other);
+int  cmp (const string_res &, const string_res &);
+bool ?==?(const string_res &, const string_res &);
+bool ?!=?(const string_res &, const string_res &);
+bool ?>? (const string_res &, const string_res &);
+bool ?>=?(const string_res &, const string_res &);
+bool ?<=?(const string_res &, const string_res &);
+bool ?<? (const string_res &, const string_res &);
+
+int  cmp (const string_res &, const char*);
+bool ?==?(const string_res &, const char*);
+bool ?!=?(const string_res &, const char*);
+bool ?>? (const string_res &, const char*);
+bool ?>=?(const string_res &, const char*);
+bool ?<=?(const string_res &, const char*);
+bool ?<? (const string_res &, const char*);
+
+int  cmp (const char*, const string_res &);
+bool ?==?(const char*, const string_res &);
+bool ?!=?(const char*, const string_res &);
+bool ?>? (const char*, const string_res &);
+bool ?>=?(const char*, const string_res &);
+bool ?<=?(const char*, const string_res &);
+bool ?<? (const char*, const string_res &);
 
 // String search
Index: tests/collections/.expect/string-compare.txt
===================================================================
--- tests/collections/.expect/string-compare.txt	(revision 416b44361690d969b5d06bb054b6451776e1f181)
+++ tests/collections/.expect/string-compare.txt	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -0,0 +1,800 @@
+------- string -------
+(cmp(s_, s_) == 0) ok
+(s_ == s_) ok
+!(s_ != s_) ok
+!(s_ > s_) ok
+(s_ >= s_) ok
+(s_ <= s_) ok
+!(s_ < s_) ok
+(cmp("", s_) == 0) ok
+("" == s_) ok
+!("" != s_) ok
+!("" > s_) ok
+("" >= s_) ok
+("" <= s_) ok
+!("" < s_) ok
+(cmp(s_, "") == 0) ok
+(s_ == "") ok
+!(s_ != "") ok
+!(s_ > "") ok
+(s_ >= "") ok
+(s_ <= "") ok
+!(s_ < "") ok
+(cmp(s_, s_a) < 0) ok
+!(s_ == s_a) ok
+(s_ != s_a) ok
+!(s_ > s_a) ok
+!(s_ >= s_a) ok
+(s_ <= s_a) ok
+(s_ < s_a) ok
+(cmp("", s_a) < 0) ok
+!("" == s_a) ok
+("" != s_a) ok
+!("" > s_a) ok
+!("" >= s_a) ok
+("" <= s_a) ok
+("" < s_a) ok
+(cmp(s_, "a") < 0) ok
+!(s_ == "a") ok
+(s_ != "a") ok
+!(s_ > "a") ok
+!(s_ >= "a") ok
+(s_ <= "a") ok
+(s_ < "a") ok
+(cmp(s_a, s_) > 0) ok
+!(s_a == s_) ok
+(s_a != s_) ok
+(s_a > s_) ok
+(s_a >= s_) ok
+!(s_a <= s_) ok
+!(s_a < s_) ok
+(cmp("a", s_) > 0) ok
+!("a" == s_) ok
+("a" != s_) ok
+("a" > s_) ok
+("a" >= s_) ok
+!("a" <= s_) ok
+!("a" < s_) ok
+(cmp(s_a, "") > 0) ok
+!(s_a == "") ok
+(s_a != "") ok
+(s_a > "") ok
+(s_a >= "") ok
+!(s_a <= "") ok
+!(s_a < "") ok
+(cmp(s_, s_aa) < 0) ok
+!(s_ == s_aa) ok
+(s_ != s_aa) ok
+!(s_ > s_aa) ok
+!(s_ >= s_aa) ok
+(s_ <= s_aa) ok
+(s_ < s_aa) ok
+(cmp("", s_aa) < 0) ok
+!("" == s_aa) ok
+("" != s_aa) ok
+!("" > s_aa) ok
+!("" >= s_aa) ok
+("" <= s_aa) ok
+("" < s_aa) ok
+(cmp(s_, "aa") < 0) ok
+!(s_ == "aa") ok
+(s_ != "aa") ok
+!(s_ > "aa") ok
+!(s_ >= "aa") ok
+(s_ <= "aa") ok
+(s_ < "aa") ok
+(cmp(s_aa, s_) > 0) ok
+!(s_aa == s_) ok
+(s_aa != s_) ok
+(s_aa > s_) ok
+(s_aa >= s_) ok
+!(s_aa <= s_) ok
+!(s_aa < s_) ok
+(cmp("aa", s_) > 0) ok
+!("aa" == s_) ok
+("aa" != s_) ok
+("aa" > s_) ok
+("aa" >= s_) ok
+!("aa" <= s_) ok
+!("aa" < s_) ok
+(cmp(s_aa, "") > 0) ok
+!(s_aa == "") ok
+(s_aa != "") ok
+(s_aa > "") ok
+(s_aa >= "") ok
+!(s_aa <= "") ok
+!(s_aa < "") ok
+(cmp(s_a, s_aa) < 0) ok
+!(s_a == s_aa) ok
+(s_a != s_aa) ok
+!(s_a > s_aa) ok
+!(s_a >= s_aa) ok
+(s_a <= s_aa) ok
+(s_a < s_aa) ok
+(cmp("a", s_aa) < 0) ok
+!("a" == s_aa) ok
+("a" != s_aa) ok
+!("a" > s_aa) ok
+!("a" >= s_aa) ok
+("a" <= s_aa) ok
+("a" < s_aa) ok
+(cmp(s_a, "aa") < 0) ok
+!(s_a == "aa") ok
+(s_a != "aa") ok
+!(s_a > "aa") ok
+!(s_a >= "aa") ok
+(s_a <= "aa") ok
+(s_a < "aa") ok
+(cmp(s_aa, s_a) > 0) ok
+!(s_aa == s_a) ok
+(s_aa != s_a) ok
+(s_aa > s_a) ok
+(s_aa >= s_a) ok
+!(s_aa <= s_a) ok
+!(s_aa < s_a) ok
+(cmp("aa", s_a) > 0) ok
+!("aa" == s_a) ok
+("aa" != s_a) ok
+("aa" > s_a) ok
+("aa" >= s_a) ok
+!("aa" <= s_a) ok
+!("aa" < s_a) ok
+(cmp(s_aa, "a") > 0) ok
+!(s_aa == "a") ok
+(s_aa != "a") ok
+(s_aa > "a") ok
+(s_aa >= "a") ok
+!(s_aa <= "a") ok
+!(s_aa < "a") ok
+(cmp(s_a, s_a) == 0) ok
+(s_a == s_a) ok
+!(s_a != s_a) ok
+!(s_a > s_a) ok
+(s_a >= s_a) ok
+(s_a <= s_a) ok
+!(s_a < s_a) ok
+(cmp("a", s_a) == 0) ok
+("a" == s_a) ok
+!("a" != s_a) ok
+!("a" > s_a) ok
+("a" >= s_a) ok
+("a" <= s_a) ok
+!("a" < s_a) ok
+(cmp(s_a, "a") == 0) ok
+(s_a == "a") ok
+!(s_a != "a") ok
+!(s_a > "a") ok
+(s_a >= "a") ok
+(s_a <= "a") ok
+!(s_a < "a") ok
+(cmp(s_aa, s_aa) == 0) ok
+(s_aa == s_aa) ok
+!(s_aa != s_aa) ok
+!(s_aa > s_aa) ok
+(s_aa >= s_aa) ok
+(s_aa <= s_aa) ok
+!(s_aa < s_aa) ok
+(cmp("aa", s_aa) == 0) ok
+("aa" == s_aa) ok
+!("aa" != s_aa) ok
+!("aa" > s_aa) ok
+("aa" >= s_aa) ok
+("aa" <= s_aa) ok
+!("aa" < s_aa) ok
+(cmp(s_aa, "aa") == 0) ok
+(s_aa == "aa") ok
+!(s_aa != "aa") ok
+!(s_aa > "aa") ok
+(s_aa >= "aa") ok
+(s_aa <= "aa") ok
+!(s_aa < "aa") ok
+(cmp(s_a, s_b) < 0) ok
+!(s_a == s_b) ok
+(s_a != s_b) ok
+!(s_a > s_b) ok
+!(s_a >= s_b) ok
+(s_a <= s_b) ok
+(s_a < s_b) ok
+(cmp("a", s_b) < 0) ok
+!("a" == s_b) ok
+("a" != s_b) ok
+!("a" > s_b) ok
+!("a" >= s_b) ok
+("a" <= s_b) ok
+("a" < s_b) ok
+(cmp(s_a, "b") < 0) ok
+!(s_a == "b") ok
+(s_a != "b") ok
+!(s_a > "b") ok
+!(s_a >= "b") ok
+(s_a <= "b") ok
+(s_a < "b") ok
+(cmp(s_b, s_a) > 0) ok
+!(s_b == s_a) ok
+(s_b != s_a) ok
+(s_b > s_a) ok
+(s_b >= s_a) ok
+!(s_b <= s_a) ok
+!(s_b < s_a) ok
+(cmp("b", s_a) > 0) ok
+!("b" == s_a) ok
+("b" != s_a) ok
+("b" > s_a) ok
+("b" >= s_a) ok
+!("b" <= s_a) ok
+!("b" < s_a) ok
+(cmp(s_b, "a") > 0) ok
+!(s_b == "a") ok
+(s_b != "a") ok
+(s_b > "a") ok
+(s_b >= "a") ok
+!(s_b <= "a") ok
+!(s_b < "a") ok
+(cmp(s_a, s_ba) < 0) ok
+!(s_a == s_ba) ok
+(s_a != s_ba) ok
+!(s_a > s_ba) ok
+!(s_a >= s_ba) ok
+(s_a <= s_ba) ok
+(s_a < s_ba) ok
+(cmp("a", s_ba) < 0) ok
+!("a" == s_ba) ok
+("a" != s_ba) ok
+!("a" > s_ba) ok
+!("a" >= s_ba) ok
+("a" <= s_ba) ok
+("a" < s_ba) ok
+(cmp(s_a, "ba") < 0) ok
+!(s_a == "ba") ok
+(s_a != "ba") ok
+!(s_a > "ba") ok
+!(s_a >= "ba") ok
+(s_a <= "ba") ok
+(s_a < "ba") ok
+(cmp(s_ba, s_a) > 0) ok
+!(s_ba == s_a) ok
+(s_ba != s_a) ok
+(s_ba > s_a) ok
+(s_ba >= s_a) ok
+!(s_ba <= s_a) ok
+!(s_ba < s_a) ok
+(cmp("ba", s_a) > 0) ok
+!("ba" == s_a) ok
+("ba" != s_a) ok
+("ba" > s_a) ok
+("ba" >= s_a) ok
+!("ba" <= s_a) ok
+!("ba" < s_a) ok
+(cmp(s_ba, "a") > 0) ok
+!(s_ba == "a") ok
+(s_ba != "a") ok
+(s_ba > "a") ok
+(s_ba >= "a") ok
+!(s_ba <= "a") ok
+!(s_ba < "a") ok
+(cmp(s_aa, s_ab) < 0) ok
+!(s_aa == s_ab) ok
+(s_aa != s_ab) ok
+!(s_aa > s_ab) ok
+!(s_aa >= s_ab) ok
+(s_aa <= s_ab) ok
+(s_aa < s_ab) ok
+(cmp("aa", s_ab) < 0) ok
+!("aa" == s_ab) ok
+("aa" != s_ab) ok
+!("aa" > s_ab) ok
+!("aa" >= s_ab) ok
+("aa" <= s_ab) ok
+("aa" < s_ab) ok
+(cmp(s_aa, "ab") < 0) ok
+!(s_aa == "ab") ok
+(s_aa != "ab") ok
+!(s_aa > "ab") ok
+!(s_aa >= "ab") ok
+(s_aa <= "ab") ok
+(s_aa < "ab") ok
+(cmp(s_ab, s_aa) > 0) ok
+!(s_ab == s_aa) ok
+(s_ab != s_aa) ok
+(s_ab > s_aa) ok
+(s_ab >= s_aa) ok
+!(s_ab <= s_aa) ok
+!(s_ab < s_aa) ok
+(cmp("ab", s_aa) > 0) ok
+!("ab" == s_aa) ok
+("ab" != s_aa) ok
+("ab" > s_aa) ok
+("ab" >= s_aa) ok
+!("ab" <= s_aa) ok
+!("ab" < s_aa) ok
+(cmp(s_ab, "aa") > 0) ok
+!(s_ab == "aa") ok
+(s_ab != "aa") ok
+(s_ab > "aa") ok
+(s_ab >= "aa") ok
+!(s_ab <= "aa") ok
+!(s_ab < "aa") ok
+(cmp(s_ba, s_bb) < 0) ok
+!(s_ba == s_bb) ok
+(s_ba != s_bb) ok
+!(s_ba > s_bb) ok
+!(s_ba >= s_bb) ok
+(s_ba <= s_bb) ok
+(s_ba < s_bb) ok
+(cmp("ba", s_bb) < 0) ok
+!("ba" == s_bb) ok
+("ba" != s_bb) ok
+!("ba" > s_bb) ok
+!("ba" >= s_bb) ok
+("ba" <= s_bb) ok
+("ba" < s_bb) ok
+(cmp(s_ba, "bb") < 0) ok
+!(s_ba == "bb") ok
+(s_ba != "bb") ok
+!(s_ba > "bb") ok
+!(s_ba >= "bb") ok
+(s_ba <= "bb") ok
+(s_ba < "bb") ok
+(cmp(s_bb, s_ba) > 0) ok
+!(s_bb == s_ba) ok
+(s_bb != s_ba) ok
+(s_bb > s_ba) ok
+(s_bb >= s_ba) ok
+!(s_bb <= s_ba) ok
+!(s_bb < s_ba) ok
+(cmp("bb", s_ba) > 0) ok
+!("bb" == s_ba) ok
+("bb" != s_ba) ok
+("bb" > s_ba) ok
+("bb" >= s_ba) ok
+!("bb" <= s_ba) ok
+!("bb" < s_ba) ok
+(cmp(s_bb, "ba") > 0) ok
+!(s_bb == "ba") ok
+(s_bb != "ba") ok
+(s_bb > "ba") ok
+(s_bb >= "ba") ok
+!(s_bb <= "ba") ok
+!(s_bb < "ba") ok
+(cmp(s_aa, s_b) < 0) ok
+!(s_aa == s_b) ok
+(s_aa != s_b) ok
+!(s_aa > s_b) ok
+!(s_aa >= s_b) ok
+(s_aa <= s_b) ok
+(s_aa < s_b) ok
+(cmp("aa", s_b) < 0) ok
+!("aa" == s_b) ok
+("aa" != s_b) ok
+!("aa" > s_b) ok
+!("aa" >= s_b) ok
+("aa" <= s_b) ok
+("aa" < s_b) ok
+(cmp(s_aa, "b") < 0) ok
+!(s_aa == "b") ok
+(s_aa != "b") ok
+!(s_aa > "b") ok
+!(s_aa >= "b") ok
+(s_aa <= "b") ok
+(s_aa < "b") ok
+(cmp(s_b, s_aa) > 0) ok
+!(s_b == s_aa) ok
+(s_b != s_aa) ok
+(s_b > s_aa) ok
+(s_b >= s_aa) ok
+!(s_b <= s_aa) ok
+!(s_b < s_aa) ok
+(cmp("b", s_aa) > 0) ok
+!("b" == s_aa) ok
+("b" != s_aa) ok
+("b" > s_aa) ok
+("b" >= s_aa) ok
+!("b" <= s_aa) ok
+!("b" < s_aa) ok
+(cmp(s_b, "aa") > 0) ok
+!(s_b == "aa") ok
+(s_b != "aa") ok
+(s_b > "aa") ok
+(s_b >= "aa") ok
+!(s_b <= "aa") ok
+!(s_b < "aa") ok
+------- string_res -------
+(cmp(s_, s_) == 0) ok
+(s_ == s_) ok
+!(s_ != s_) ok
+!(s_ > s_) ok
+(s_ >= s_) ok
+(s_ <= s_) ok
+!(s_ < s_) ok
+(cmp("", s_) == 0) ok
+("" == s_) ok
+!("" != s_) ok
+!("" > s_) ok
+("" >= s_) ok
+("" <= s_) ok
+!("" < s_) ok
+(cmp(s_, "") == 0) ok
+(s_ == "") ok
+!(s_ != "") ok
+!(s_ > "") ok
+(s_ >= "") ok
+(s_ <= "") ok
+!(s_ < "") ok
+(cmp(s_, s_a) < 0) ok
+!(s_ == s_a) ok
+(s_ != s_a) ok
+!(s_ > s_a) ok
+!(s_ >= s_a) ok
+(s_ <= s_a) ok
+(s_ < s_a) ok
+(cmp("", s_a) < 0) ok
+!("" == s_a) ok
+("" != s_a) ok
+!("" > s_a) ok
+!("" >= s_a) ok
+("" <= s_a) ok
+("" < s_a) ok
+(cmp(s_, "a") < 0) ok
+!(s_ == "a") ok
+(s_ != "a") ok
+!(s_ > "a") ok
+!(s_ >= "a") ok
+(s_ <= "a") ok
+(s_ < "a") ok
+(cmp(s_a, s_) > 0) ok
+!(s_a == s_) ok
+(s_a != s_) ok
+(s_a > s_) ok
+(s_a >= s_) ok
+!(s_a <= s_) ok
+!(s_a < s_) ok
+(cmp("a", s_) > 0) ok
+!("a" == s_) ok
+("a" != s_) ok
+("a" > s_) ok
+("a" >= s_) ok
+!("a" <= s_) ok
+!("a" < s_) ok
+(cmp(s_a, "") > 0) ok
+!(s_a == "") ok
+(s_a != "") ok
+(s_a > "") ok
+(s_a >= "") ok
+!(s_a <= "") ok
+!(s_a < "") ok
+(cmp(s_, s_aa) < 0) ok
+!(s_ == s_aa) ok
+(s_ != s_aa) ok
+!(s_ > s_aa) ok
+!(s_ >= s_aa) ok
+(s_ <= s_aa) ok
+(s_ < s_aa) ok
+(cmp("", s_aa) < 0) ok
+!("" == s_aa) ok
+("" != s_aa) ok
+!("" > s_aa) ok
+!("" >= s_aa) ok
+("" <= s_aa) ok
+("" < s_aa) ok
+(cmp(s_, "aa") < 0) ok
+!(s_ == "aa") ok
+(s_ != "aa") ok
+!(s_ > "aa") ok
+!(s_ >= "aa") ok
+(s_ <= "aa") ok
+(s_ < "aa") ok
+(cmp(s_aa, s_) > 0) ok
+!(s_aa == s_) ok
+(s_aa != s_) ok
+(s_aa > s_) ok
+(s_aa >= s_) ok
+!(s_aa <= s_) ok
+!(s_aa < s_) ok
+(cmp("aa", s_) > 0) ok
+!("aa" == s_) ok
+("aa" != s_) ok
+("aa" > s_) ok
+("aa" >= s_) ok
+!("aa" <= s_) ok
+!("aa" < s_) ok
+(cmp(s_aa, "") > 0) ok
+!(s_aa == "") ok
+(s_aa != "") ok
+(s_aa > "") ok
+(s_aa >= "") ok
+!(s_aa <= "") ok
+!(s_aa < "") ok
+(cmp(s_a, s_aa) < 0) ok
+!(s_a == s_aa) ok
+(s_a != s_aa) ok
+!(s_a > s_aa) ok
+!(s_a >= s_aa) ok
+(s_a <= s_aa) ok
+(s_a < s_aa) ok
+(cmp("a", s_aa) < 0) ok
+!("a" == s_aa) ok
+("a" != s_aa) ok
+!("a" > s_aa) ok
+!("a" >= s_aa) ok
+("a" <= s_aa) ok
+("a" < s_aa) ok
+(cmp(s_a, "aa") < 0) ok
+!(s_a == "aa") ok
+(s_a != "aa") ok
+!(s_a > "aa") ok
+!(s_a >= "aa") ok
+(s_a <= "aa") ok
+(s_a < "aa") ok
+(cmp(s_aa, s_a) > 0) ok
+!(s_aa == s_a) ok
+(s_aa != s_a) ok
+(s_aa > s_a) ok
+(s_aa >= s_a) ok
+!(s_aa <= s_a) ok
+!(s_aa < s_a) ok
+(cmp("aa", s_a) > 0) ok
+!("aa" == s_a) ok
+("aa" != s_a) ok
+("aa" > s_a) ok
+("aa" >= s_a) ok
+!("aa" <= s_a) ok
+!("aa" < s_a) ok
+(cmp(s_aa, "a") > 0) ok
+!(s_aa == "a") ok
+(s_aa != "a") ok
+(s_aa > "a") ok
+(s_aa >= "a") ok
+!(s_aa <= "a") ok
+!(s_aa < "a") ok
+(cmp(s_a, s_a) == 0) ok
+(s_a == s_a) ok
+!(s_a != s_a) ok
+!(s_a > s_a) ok
+(s_a >= s_a) ok
+(s_a <= s_a) ok
+!(s_a < s_a) ok
+(cmp("a", s_a) == 0) ok
+("a" == s_a) ok
+!("a" != s_a) ok
+!("a" > s_a) ok
+("a" >= s_a) ok
+("a" <= s_a) ok
+!("a" < s_a) ok
+(cmp(s_a, "a") == 0) ok
+(s_a == "a") ok
+!(s_a != "a") ok
+!(s_a > "a") ok
+(s_a >= "a") ok
+(s_a <= "a") ok
+!(s_a < "a") ok
+(cmp(s_aa, s_aa) == 0) ok
+(s_aa == s_aa) ok
+!(s_aa != s_aa) ok
+!(s_aa > s_aa) ok
+(s_aa >= s_aa) ok
+(s_aa <= s_aa) ok
+!(s_aa < s_aa) ok
+(cmp("aa", s_aa) == 0) ok
+("aa" == s_aa) ok
+!("aa" != s_aa) ok
+!("aa" > s_aa) ok
+("aa" >= s_aa) ok
+("aa" <= s_aa) ok
+!("aa" < s_aa) ok
+(cmp(s_aa, "aa") == 0) ok
+(s_aa == "aa") ok
+!(s_aa != "aa") ok
+!(s_aa > "aa") ok
+(s_aa >= "aa") ok
+(s_aa <= "aa") ok
+!(s_aa < "aa") ok
+(cmp(s_a, s_b) < 0) ok
+!(s_a == s_b) ok
+(s_a != s_b) ok
+!(s_a > s_b) ok
+!(s_a >= s_b) ok
+(s_a <= s_b) ok
+(s_a < s_b) ok
+(cmp("a", s_b) < 0) ok
+!("a" == s_b) ok
+("a" != s_b) ok
+!("a" > s_b) ok
+!("a" >= s_b) ok
+("a" <= s_b) ok
+("a" < s_b) ok
+(cmp(s_a, "b") < 0) ok
+!(s_a == "b") ok
+(s_a != "b") ok
+!(s_a > "b") ok
+!(s_a >= "b") ok
+(s_a <= "b") ok
+(s_a < "b") ok
+(cmp(s_b, s_a) > 0) ok
+!(s_b == s_a) ok
+(s_b != s_a) ok
+(s_b > s_a) ok
+(s_b >= s_a) ok
+!(s_b <= s_a) ok
+!(s_b < s_a) ok
+(cmp("b", s_a) > 0) ok
+!("b" == s_a) ok
+("b" != s_a) ok
+("b" > s_a) ok
+("b" >= s_a) ok
+!("b" <= s_a) ok
+!("b" < s_a) ok
+(cmp(s_b, "a") > 0) ok
+!(s_b == "a") ok
+(s_b != "a") ok
+(s_b > "a") ok
+(s_b >= "a") ok
+!(s_b <= "a") ok
+!(s_b < "a") ok
+(cmp(s_a, s_ba) < 0) ok
+!(s_a == s_ba) ok
+(s_a != s_ba) ok
+!(s_a > s_ba) ok
+!(s_a >= s_ba) ok
+(s_a <= s_ba) ok
+(s_a < s_ba) ok
+(cmp("a", s_ba) < 0) ok
+!("a" == s_ba) ok
+("a" != s_ba) ok
+!("a" > s_ba) ok
+!("a" >= s_ba) ok
+("a" <= s_ba) ok
+("a" < s_ba) ok
+(cmp(s_a, "ba") < 0) ok
+!(s_a == "ba") ok
+(s_a != "ba") ok
+!(s_a > "ba") ok
+!(s_a >= "ba") ok
+(s_a <= "ba") ok
+(s_a < "ba") ok
+(cmp(s_ba, s_a) > 0) ok
+!(s_ba == s_a) ok
+(s_ba != s_a) ok
+(s_ba > s_a) ok
+(s_ba >= s_a) ok
+!(s_ba <= s_a) ok
+!(s_ba < s_a) ok
+(cmp("ba", s_a) > 0) ok
+!("ba" == s_a) ok
+("ba" != s_a) ok
+("ba" > s_a) ok
+("ba" >= s_a) ok
+!("ba" <= s_a) ok
+!("ba" < s_a) ok
+(cmp(s_ba, "a") > 0) ok
+!(s_ba == "a") ok
+(s_ba != "a") ok
+(s_ba > "a") ok
+(s_ba >= "a") ok
+!(s_ba <= "a") ok
+!(s_ba < "a") ok
+(cmp(s_aa, s_ab) < 0) ok
+!(s_aa == s_ab) ok
+(s_aa != s_ab) ok
+!(s_aa > s_ab) ok
+!(s_aa >= s_ab) ok
+(s_aa <= s_ab) ok
+(s_aa < s_ab) ok
+(cmp("aa", s_ab) < 0) ok
+!("aa" == s_ab) ok
+("aa" != s_ab) ok
+!("aa" > s_ab) ok
+!("aa" >= s_ab) ok
+("aa" <= s_ab) ok
+("aa" < s_ab) ok
+(cmp(s_aa, "ab") < 0) ok
+!(s_aa == "ab") ok
+(s_aa != "ab") ok
+!(s_aa > "ab") ok
+!(s_aa >= "ab") ok
+(s_aa <= "ab") ok
+(s_aa < "ab") ok
+(cmp(s_ab, s_aa) > 0) ok
+!(s_ab == s_aa) ok
+(s_ab != s_aa) ok
+(s_ab > s_aa) ok
+(s_ab >= s_aa) ok
+!(s_ab <= s_aa) ok
+!(s_ab < s_aa) ok
+(cmp("ab", s_aa) > 0) ok
+!("ab" == s_aa) ok
+("ab" != s_aa) ok
+("ab" > s_aa) ok
+("ab" >= s_aa) ok
+!("ab" <= s_aa) ok
+!("ab" < s_aa) ok
+(cmp(s_ab, "aa") > 0) ok
+!(s_ab == "aa") ok
+(s_ab != "aa") ok
+(s_ab > "aa") ok
+(s_ab >= "aa") ok
+!(s_ab <= "aa") ok
+!(s_ab < "aa") ok
+(cmp(s_ba, s_bb) < 0) ok
+!(s_ba == s_bb) ok
+(s_ba != s_bb) ok
+!(s_ba > s_bb) ok
+!(s_ba >= s_bb) ok
+(s_ba <= s_bb) ok
+(s_ba < s_bb) ok
+(cmp("ba", s_bb) < 0) ok
+!("ba" == s_bb) ok
+("ba" != s_bb) ok
+!("ba" > s_bb) ok
+!("ba" >= s_bb) ok
+("ba" <= s_bb) ok
+("ba" < s_bb) ok
+(cmp(s_ba, "bb") < 0) ok
+!(s_ba == "bb") ok
+(s_ba != "bb") ok
+!(s_ba > "bb") ok
+!(s_ba >= "bb") ok
+(s_ba <= "bb") ok
+(s_ba < "bb") ok
+(cmp(s_bb, s_ba) > 0) ok
+!(s_bb == s_ba) ok
+(s_bb != s_ba) ok
+(s_bb > s_ba) ok
+(s_bb >= s_ba) ok
+!(s_bb <= s_ba) ok
+!(s_bb < s_ba) ok
+(cmp("bb", s_ba) > 0) ok
+!("bb" == s_ba) ok
+("bb" != s_ba) ok
+("bb" > s_ba) ok
+("bb" >= s_ba) ok
+!("bb" <= s_ba) ok
+!("bb" < s_ba) ok
+(cmp(s_bb, "ba") > 0) ok
+!(s_bb == "ba") ok
+(s_bb != "ba") ok
+(s_bb > "ba") ok
+(s_bb >= "ba") ok
+!(s_bb <= "ba") ok
+!(s_bb < "ba") ok
+(cmp(s_aa, s_b) < 0) ok
+!(s_aa == s_b) ok
+(s_aa != s_b) ok
+!(s_aa > s_b) ok
+!(s_aa >= s_b) ok
+(s_aa <= s_b) ok
+(s_aa < s_b) ok
+(cmp("aa", s_b) < 0) ok
+!("aa" == s_b) ok
+("aa" != s_b) ok
+!("aa" > s_b) ok
+!("aa" >= s_b) ok
+("aa" <= s_b) ok
+("aa" < s_b) ok
+(cmp(s_aa, "b") < 0) ok
+!(s_aa == "b") ok
+(s_aa != "b") ok
+!(s_aa > "b") ok
+!(s_aa >= "b") ok
+(s_aa <= "b") ok
+(s_aa < "b") ok
+(cmp(s_b, s_aa) > 0) ok
+!(s_b == s_aa) ok
+(s_b != s_aa) ok
+(s_b > s_aa) ok
+(s_b >= s_aa) ok
+!(s_b <= s_aa) ok
+!(s_b < s_aa) ok
+(cmp("b", s_aa) > 0) ok
+!("b" == s_aa) ok
+("b" != s_aa) ok
+("b" > s_aa) ok
+("b" >= s_aa) ok
+!("b" <= s_aa) ok
+!("b" < s_aa) ok
+(cmp(s_b, "aa") > 0) ok
+!(s_b == "aa") ok
+(s_b != "aa") ok
+(s_b > "aa") ok
+(s_b >= "aa") ok
+!(s_b <= "aa") ok
+!(s_b < "aa") ok
Index: tests/collections/string-compare.cfa
===================================================================
--- tests/collections/string-compare.cfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
+++ tests/collections/string-compare.cfa	(revision 416b44361690d969b5d06bb054b6451776e1f181)
@@ -0,0 +1,76 @@
+#define chk(X) \
+    printf( #X " %s\n", ((X)?"ok":"WRONG") );
+
+#define test_eq_(l, r) \
+    chk( (cmp(l, r) == 0) ) \
+    chk(  (l == r) ) \
+    chk( !(l != r) ) \
+    chk( !(l >  r) ) \
+    chk(  (l >= r) ) \
+    chk(  (l <= r) ) \
+    chk( !(l <  r) )
+
+#define test_eq(l, r) \
+    test_eq_(s_ ## l, s_ ## r) \
+    test_eq_(    # l, s_ ## r) \
+    test_eq_(s_ ## l,     # r)
+
+#define test_lt_(l, r) \
+    chk( (cmp(l, r) < 0) ) \
+    chk( !(l == r) ) \
+    chk(  (l != r) ) \
+    chk( !(l >  r) ) \
+    chk( !(l >= r) ) \
+    chk(  (l <= r) ) \
+    chk(  (l <  r) )
+
+#define test_gt_(l, r) \
+    chk( (cmp(l, r) > 0) ) \
+    chk( !(l == r) ) \
+    chk(  (l != r) ) \
+    chk(  (l >  r) ) \
+    chk(  (l >= r) ) \
+    chk( !(l <= r) ) \
+    chk( !(l <  r) )
+
+#define test_lt(l, r) \
+    test_lt_(s_ ## l, s_ ## r) \
+    test_lt_(    # l, s_ ## r) \
+    test_lt_(s_ ## l,     # r) \
+    test_gt_(s_ ## r, s_ ## l) \
+    test_gt_(    # r, s_ ## l) \
+    test_gt_(s_ ## r,     # l)
+
+#define define_run(STR_T) \
+    void run_ ## STR_T (void) {    \
+        printf("------- %s -------\n", #STR_T); \
+        STR_T s_   = ""  ;        \
+        STR_T s_a  = "a" ;        \
+        STR_T s_aa = "aa";        \
+        STR_T s_ab = "ab";        \
+        STR_T s_b  = "b" ;        \
+        STR_T s_ba = "ba";        \
+        STR_T s_bb = "bb";        \
+        test_eq(,)                \
+        test_lt(,a)               \
+        test_lt(,aa)              \
+        test_lt(a,aa)             \
+        test_eq(a,a)              \
+        test_eq(aa,aa)            \
+        test_lt(a,b)              \
+        test_lt(a,ba)             \
+        test_lt(aa,ab)            \
+        test_lt(ba,bb)            \
+        test_lt(aa,b)             \
+    }
+
+#include <collections/string.hfa>
+define_run(string)
+
+#include <collections/string_res.hfa>
+define_run(string_res)
+
+int main() {
+    run_string();
+    run_string_res();
+}
