add option for generating partial collation key
diff --git a/UTS10/collation_key.c b/UTS10/collation_key.c
index 8d3ed62..c1ffa9a 100644
--- a/UTS10/collation_key.c
+++ b/UTS10/collation_key.c
@@ -50,12 +50,23 @@
     return (collation | UNICOLL_CONTRACTIONS_MASK);
 }
 
+/* If PARTIAL_KEY_ENABLED is non-zero, u*_make_collation_key does not
+   re-allocate RESULTBUF and will return a partial key (null-terminated)
+   if the full result would be longer than *LENGTHP bytes. */
+Collation_choice unicoll_enable_partial (Collation_choice collation,
+                                         int partial_key_enabled)
+{
+  if (!partial_key_enabled)
+    return (collation & ~UNICOLL_PARTIAL_MASK);
+  else
+    return (collation | UNICOLL_PARTIAL_MASK);
+}
+
 /* forward declaration */
 static char *make_key_internal (char *psort_key,
-                   struct collation_unit *elements,
-                   size_t elements_count,
-                   int variable_shifted_or_blanked,
-                   int variable_shifted);
+                   struct collation_unit *elements, size_t elements_count,
+                   int variable_shifted_or_blanked, int variable_shifted,
+                   char *limit);
 
 char *
 u32_make_collation_key (Collation_choice collation,
@@ -78,6 +89,8 @@
 
   int disable_sequence_lookup = (collation & UNICOLL_CONTRACTIONS_MASK);
 
+  int fix_length = 0;
+
   char32_t *codepoints;
   size_t length;
 
@@ -199,21 +212,31 @@
     sort_key = resultbuf;
   else
     {
-      sort_key = malloc (sort_key_alloc);
-      if (!sort_key)
+      int partial_key_enabled = (collation & UNICOLL_PARTIAL_MASK);
+      if (!partial_key_enabled)
         {
-          errno = ENOMEM;
-          return 0;
+          sort_key = malloc (sort_key_alloc);
+          if (!sort_key)
+            {
+              errno = ENOMEM;
+              return 0;
+            }
+        }
+      else
+        {
+          sort_key = resultbuf;
+          fix_length = 1;
         }
     }
 
   psort_key = sort_key;
   psort_key = make_key_internal (psort_key, elements, elements_count,
                                  variable_shifted_or_blanked,
-                                 variable_shifted);
+                                 variable_shifted,
+                                 fix_length ? &sort_key[*lengthp] : NULL);
 
   *psort_key = '\0';
-  *lengthp = psort_key - sort_key;
+  *lengthp = psort_key - sort_key + 1;
 
   free (elements);
   free (codepoints);
@@ -225,11 +248,16 @@
 make_key_internal (char *psort_key,
                    struct collation_unit *elements,
                    size_t elements_count,
-                   int variable_shifted_or_blanked,
-                   int variable_shifted)
+                   int variable_shifted_or_blanked, int variable_shifted,
+                   char *limit)
 {
 
-#define cat(c) (*psort_key++ = (c))
+#define cat(c) { \
+  if (psort_key == limit) return psort_key; \
+  else *psort_key++ = (c); \
+}
+  /* Note that we do not call malloc in this function so no clean-up
+     is required at function exit. */
 
   /* Output collation key without any null bytes.
      See UTS#10 s.9.4 "Avoiding Zero Bytes". */
@@ -397,6 +425,7 @@
         }
     }
   return psort_key;
+#undef cat
 }
 
 char *
diff --git a/UTS10/collation_key.h b/UTS10/collation_key.h
index f1b735a..1be02f8 100644
--- a/UTS10/collation_key.h
+++ b/UTS10/collation_key.h
@@ -11,6 +11,7 @@
 #define UNICOLL_VARIABLE_MASK 0x3
 #define UNICOLL_NORMALIZATION_MASK 0x4
 #define UNICOLL_CONTRACTIONS_MASK 0x8
+#define UNICOLL_PARTIAL_MASK 0x10
 
 typedef uint_fast32_t Collation_choice;
 
@@ -21,6 +22,8 @@
                                             int normalization_on);
 Collation_choice unicoll_set_contractions (Collation_choice collation,
                                             int use_contractions);
+Collation_choice unicoll_enable_partial (Collation_choice collation,
+                                         int partial_key_enabled);
 
 
 char *u8_make_collation_key (Collation_choice collation,