Implement PEP 393.
diff --git a/Objects/stringlib/count.h b/Objects/stringlib/count.h
index de34f96..f48500b 100644
--- a/Objects/stringlib/count.h
+++ b/Objects/stringlib/count.h
@@ -1,14 +1,11 @@
 /* stringlib: count implementation */
 
-#ifndef STRINGLIB_COUNT_H
-#define STRINGLIB_COUNT_H
-
 #ifndef STRINGLIB_FASTSEARCH_H
 #error must include "stringlib/fastsearch.h" before including this module
 #endif
 
 Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_count(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
+STRINGLIB(count)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                 Py_ssize_t maxcount)
 {
@@ -19,7 +16,7 @@
     if (sub_len == 0)
         return (str_len < maxcount) ? str_len + 1 : maxcount;
 
-    count = fastsearch(str, str_len, sub, sub_len, maxcount, FAST_COUNT);
+    count = FASTSEARCH(str, str_len, sub, sub_len, maxcount, FAST_COUNT);
 
     if (count < 0)
         return 0; /* no match */
@@ -27,4 +24,4 @@
     return count;
 }
 
-#endif
+
diff --git a/Objects/stringlib/eq.h b/Objects/stringlib/eq.h
index 3e7f5e8..dd67128 100644
--- a/Objects/stringlib/eq.h
+++ b/Objects/stringlib/eq.h
@@ -9,13 +9,26 @@
     register PyUnicodeObject *a = (PyUnicodeObject *)aa;
     register PyUnicodeObject *b = (PyUnicodeObject *)bb;
 
-    if (a->length != b->length)
+    if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
+        assert(0 && "unicode_eq ready fail");
         return 0;
-    if (a->length == 0)
-        return 1;
-    if (a->str[0] != b->str[0])
+    }
+
+    if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b))
         return 0;
-    if (a->length == 1)
+    if (PyUnicode_GET_LENGTH(a) == 0)
         return 1;
-    return memcmp(a->str, b->str, a->length * sizeof(Py_UNICODE)) == 0;
+    if (PyUnicode_KIND(a) != PyUnicode_KIND(b))
+        return 0;
+    /* Just comparing the first byte is enough to see if a and b differ.
+     * If they are 2 byte or 4 byte character most differences will happen in
+     * the lower bytes anyways.
+     */
+    if (PyUnicode_1BYTE_DATA(a)[0] != PyUnicode_1BYTE_DATA(b)[0])
+        return 0;
+    if (PyUnicode_KIND(a) == PyUnicode_1BYTE_KIND &&
+        PyUnicode_GET_LENGTH(a) == 1)
+        return 1;
+    return memcmp(PyUnicode_1BYTE_DATA(a), PyUnicode_1BYTE_DATA(b),
+                  PyUnicode_GET_LENGTH(a) * PyUnicode_CHARACTER_SIZE(a)) == 0;
 }
diff --git a/Objects/stringlib/fastsearch.h b/Objects/stringlib/fastsearch.h
index e231c58..d35cba3 100644
--- a/Objects/stringlib/fastsearch.h
+++ b/Objects/stringlib/fastsearch.h
@@ -1,6 +1,5 @@
 /* stringlib: fastsearch implementation */
 
-#ifndef STRINGLIB_FASTSEARCH_H
 #define STRINGLIB_FASTSEARCH_H
 
 /* fast search/count implementation, based on a mix between boyer-
@@ -34,7 +33,7 @@
     ((mask &  (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))
 
 Py_LOCAL_INLINE(Py_ssize_t)
-fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n,
+FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n,
            const STRINGLIB_CHAR* p, Py_ssize_t m,
            Py_ssize_t maxcount, int mode)
 {
@@ -157,4 +156,3 @@
     return count;
 }
 
-#endif
diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h
index ce615dc..7cce156 100644
--- a/Objects/stringlib/find.h
+++ b/Objects/stringlib/find.h
@@ -1,14 +1,11 @@
 /* stringlib: find/index implementation */
 
-#ifndef STRINGLIB_FIND_H
-#define STRINGLIB_FIND_H
-
 #ifndef STRINGLIB_FASTSEARCH_H
 #error must include "stringlib/fastsearch.h" before including this module
 #endif
 
 Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
+STRINGLIB(find)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                Py_ssize_t offset)
 {
@@ -19,7 +16,7 @@
     if (sub_len == 0)
         return offset;
 
-    pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
+    pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_SEARCH);
 
     if (pos >= 0)
         pos += offset;
@@ -28,7 +25,7 @@
 }
 
 Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
+STRINGLIB(rfind)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                 Py_ssize_t offset)
 {
@@ -39,7 +36,7 @@
     if (sub_len == 0)
         return str_len + offset;
 
-    pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
+    pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
 
     if (pos >= 0)
         pos += offset;
@@ -63,29 +60,29 @@
     }
 
 Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
+STRINGLIB(find_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                      const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                      Py_ssize_t start, Py_ssize_t end)
 {
     ADJUST_INDICES(start, end, str_len);
-    return stringlib_find(str + start, end - start, sub, sub_len, start);
+    return STRINGLIB(find)(str + start, end - start, sub, sub_len, start);
 }
 
 Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
+STRINGLIB(rfind_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                       const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                       Py_ssize_t start, Py_ssize_t end)
 {
     ADJUST_INDICES(start, end, str_len);
-    return stringlib_rfind(str + start, end - start, sub, sub_len, start);
+    return STRINGLIB(rfind)(str + start, end - start, sub, sub_len, start);
 }
 
 #ifdef STRINGLIB_WANT_CONTAINS_OBJ
 
 Py_LOCAL_INLINE(int)
-stringlib_contains_obj(PyObject* str, PyObject* sub)
+STRINGLIB(contains_obj)(PyObject* str, PyObject* sub)
 {
-    return stringlib_find(
+    return STRINGLIB(find)(
         STRINGLIB_STR(str), STRINGLIB_LEN(str),
         STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
         ) != -1;
@@ -105,7 +102,7 @@
 #define FORMAT_BUFFER_SIZE 50
 
 Py_LOCAL_INLINE(int)
-stringlib_parse_args_finds(const char * function_name, PyObject *args,
+STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
                            PyObject **subobj,
                            Py_ssize_t *start, Py_ssize_t *end)
 {
@@ -153,13 +150,13 @@
 */
 
 Py_LOCAL_INLINE(int)
-stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
+STRINGLIB(parse_args_finds_unicode)(const char * function_name, PyObject *args,
                                    PyUnicodeObject **substring,
                                    Py_ssize_t *start, Py_ssize_t *end)
 {
     PyObject *tmp_substring;
 
-    if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
+    if(STRINGLIB(parse_args_finds)(function_name, args, &tmp_substring,
                                   start, end)) {
         tmp_substring = PyUnicode_FromObject(tmp_substring);
         if (!tmp_substring)
@@ -171,5 +168,3 @@
 }
 
 #endif /* STRINGLIB_IS_UNICODE */
-
-#endif /* STRINGLIB_FIND_H */
diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h
deleted file mode 100644
index 139b56c..0000000
--- a/Objects/stringlib/formatter.h
+++ /dev/null
@@ -1,1516 +0,0 @@
-/* implements the string, long, and float formatters.  that is,
-   string.__format__, etc. */
-
-#include <locale.h>
-
-/* Before including this, you must include either:
-   stringlib/unicodedefs.h
-   stringlib/stringdefs.h
-
-   Also, you should define the names:
-   FORMAT_STRING
-   FORMAT_LONG
-   FORMAT_FLOAT
-   FORMAT_COMPLEX
-   to be whatever you want the public names of these functions to
-   be.  These are the only non-static functions defined here.
-*/
-
-/* Raises an exception about an unknown presentation type for this
- * type. */
-
-static void
-unknown_presentation_type(STRINGLIB_CHAR presentation_type,
-                          const char* type_name)
-{
-#if STRINGLIB_IS_UNICODE
-    /* If STRINGLIB_CHAR is Py_UNICODE, %c might be out-of-range,
-       hence the two cases. If it is char, gcc complains that the
-       condition below is always true, hence the ifdef. */
-    if (presentation_type > 32 && presentation_type < 128)
-#endif
-        PyErr_Format(PyExc_ValueError,
-                     "Unknown format code '%c' "
-                     "for object of type '%.200s'",
-                     (char)presentation_type,
-                     type_name);
-#if STRINGLIB_IS_UNICODE
-    else
-        PyErr_Format(PyExc_ValueError,
-                     "Unknown format code '\\x%x' "
-                     "for object of type '%.200s'",
-                     (unsigned int)presentation_type,
-                     type_name);
-#endif
-}
-
-static void
-invalid_comma_type(STRINGLIB_CHAR presentation_type)
-{
-#if STRINGLIB_IS_UNICODE
-    /* See comment in unknown_presentation_type */
-    if (presentation_type > 32 && presentation_type < 128)
-#endif
-        PyErr_Format(PyExc_ValueError,
-                     "Cannot specify ',' with '%c'.",
-                     (char)presentation_type);
-#if STRINGLIB_IS_UNICODE
-    else
-        PyErr_Format(PyExc_ValueError,
-                     "Cannot specify ',' with '\\x%x'.",
-                     (unsigned int)presentation_type);
-#endif
-}
-
-/*
-    get_integer consumes 0 or more decimal digit characters from an
-    input string, updates *result with the corresponding positive
-    integer, and returns the number of digits consumed.
-
-    returns -1 on error.
-*/
-static int
-get_integer(STRINGLIB_CHAR **ptr, STRINGLIB_CHAR *end,
-                  Py_ssize_t *result)
-{
-    Py_ssize_t accumulator, digitval;
-    int numdigits;
-    accumulator = numdigits = 0;
-    for (;;(*ptr)++, numdigits++) {
-        if (*ptr >= end)
-            break;
-        digitval = STRINGLIB_TODECIMAL(**ptr);
-        if (digitval < 0)
-            break;
-        /*
-           Detect possible overflow before it happens:
-
-              accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
-              accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
-        */
-        if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
-            PyErr_Format(PyExc_ValueError,
-                         "Too many decimal digits in format string");
-            return -1;
-        }
-        accumulator = accumulator * 10 + digitval;
-    }
-    *result = accumulator;
-    return numdigits;
-}
-
-/************************************************************************/
-/*********** standard format specifier parsing **************************/
-/************************************************************************/
-
-/* returns true if this character is a specifier alignment token */
-Py_LOCAL_INLINE(int)
-is_alignment_token(STRINGLIB_CHAR c)
-{
-    switch (c) {
-    case '<': case '>': case '=': case '^':
-        return 1;
-    default:
-        return 0;
-    }
-}
-
-/* returns true if this character is a sign element */
-Py_LOCAL_INLINE(int)
-is_sign_element(STRINGLIB_CHAR c)
-{
-    switch (c) {
-    case ' ': case '+': case '-':
-        return 1;
-    default:
-        return 0;
-    }
-}
-
-
-typedef struct {
-    STRINGLIB_CHAR fill_char;
-    STRINGLIB_CHAR align;
-    int alternate;
-    STRINGLIB_CHAR sign;
-    Py_ssize_t width;
-    int thousands_separators;
-    Py_ssize_t precision;
-    STRINGLIB_CHAR type;
-} InternalFormatSpec;
-
-
-#if 0
-/* Occassionally useful for debugging. Should normally be commented out. */
-static void
-DEBUG_PRINT_FORMAT_SPEC(InternalFormatSpec *format)
-{
-    printf("internal format spec: fill_char %d\n", format->fill_char);
-    printf("internal format spec: align %d\n", format->align);
-    printf("internal format spec: alternate %d\n", format->alternate);
-    printf("internal format spec: sign %d\n", format->sign);
-    printf("internal format spec: width %zd\n", format->width);
-    printf("internal format spec: thousands_separators %d\n",
-           format->thousands_separators);
-    printf("internal format spec: precision %zd\n", format->precision);
-    printf("internal format spec: type %c\n", format->type);
-    printf("\n");
-}
-#endif
-
-
-/*
-  ptr points to the start of the format_spec, end points just past its end.
-  fills in format with the parsed information.
-  returns 1 on success, 0 on failure.
-  if failure, sets the exception
-*/
-static int
-parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
-                                  Py_ssize_t format_spec_len,
-                                  InternalFormatSpec *format,
-                                  char default_type,
-                                  char default_align)
-{
-    STRINGLIB_CHAR *ptr = format_spec;
-    STRINGLIB_CHAR *end = format_spec + format_spec_len;
-
-    /* end-ptr is used throughout this code to specify the length of
-       the input string */
-
-    Py_ssize_t consumed;
-    int align_specified = 0;
-
-    format->fill_char = '\0';
-    format->align = default_align;
-    format->alternate = 0;
-    format->sign = '\0';
-    format->width = -1;
-    format->thousands_separators = 0;
-    format->precision = -1;
-    format->type = default_type;
-
-    /* If the second char is an alignment token,
-       then parse the fill char */
-    if (end-ptr >= 2 && is_alignment_token(ptr[1])) {
-        format->align = ptr[1];
-        format->fill_char = ptr[0];
-        align_specified = 1;
-        ptr += 2;
-    }
-    else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
-        format->align = ptr[0];
-        align_specified = 1;
-        ++ptr;
-    }
-
-    /* Parse the various sign options */
-    if (end-ptr >= 1 && is_sign_element(ptr[0])) {
-        format->sign = ptr[0];
-        ++ptr;
-    }
-
-    /* If the next character is #, we're in alternate mode.  This only
-       applies to integers. */
-    if (end-ptr >= 1 && ptr[0] == '#') {
-        format->alternate = 1;
-        ++ptr;
-    }
-
-    /* The special case for 0-padding (backwards compat) */
-    if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') {
-        format->fill_char = '0';
-        if (!align_specified) {
-            format->align = '=';
-        }
-        ++ptr;
-    }
-
-    consumed = get_integer(&ptr, end, &format->width);
-    if (consumed == -1)
-        /* Overflow error. Exception already set. */
-        return 0;
-
-    /* If consumed is 0, we didn't consume any characters for the
-       width. In that case, reset the width to -1, because
-       get_integer() will have set it to zero. -1 is how we record
-       that the width wasn't specified. */
-    if (consumed == 0)
-        format->width = -1;
-
-    /* Comma signifies add thousands separators */
-    if (end-ptr && ptr[0] == ',') {
-        format->thousands_separators = 1;
-        ++ptr;
-    }
-
-    /* Parse field precision */
-    if (end-ptr && ptr[0] == '.') {
-        ++ptr;
-
-        consumed = get_integer(&ptr, end, &format->precision);
-        if (consumed == -1)
-            /* Overflow error. Exception already set. */
-            return 0;
-
-        /* Not having a precision after a dot is an error. */
-        if (consumed == 0) {
-            PyErr_Format(PyExc_ValueError,
-                         "Format specifier missing precision");
-            return 0;
-        }
-
-    }
-
-    /* Finally, parse the type field. */
-
-    if (end-ptr > 1) {
-        /* More than one char remain, invalid conversion spec. */
-        PyErr_Format(PyExc_ValueError, "Invalid conversion specification");
-        return 0;
-    }
-
-    if (end-ptr == 1) {
-        format->type = ptr[0];
-        ++ptr;
-    }
-
-    /* Do as much validating as we can, just by looking at the format
-       specifier.  Do not take into account what type of formatting
-       we're doing (int, float, string). */
-
-    if (format->thousands_separators) {
-        switch (format->type) {
-        case 'd':
-        case 'e':
-        case 'f':
-        case 'g':
-        case 'E':
-        case 'G':
-        case '%':
-        case 'F':
-        case '\0':
-            /* These are allowed. See PEP 378.*/
-            break;
-        default:
-            invalid_comma_type(format->type);
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-/* Calculate the padding needed. */
-static void
-calc_padding(Py_ssize_t nchars, Py_ssize_t width, STRINGLIB_CHAR align,
-             Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding,
-             Py_ssize_t *n_total)
-{
-    if (width >= 0) {
-        if (nchars > width)
-            *n_total = nchars;
-        else
-            *n_total = width;
-    }
-    else {
-        /* not specified, use all of the chars and no more */
-        *n_total = nchars;
-    }
-
-    /* Figure out how much leading space we need, based on the
-       aligning */
-    if (align == '>')
-        *n_lpadding = *n_total - nchars;
-    else if (align == '^')
-        *n_lpadding = (*n_total - nchars) / 2;
-    else if (align == '<' || align == '=')
-        *n_lpadding = 0;
-    else {
-        /* We should never have an unspecified alignment. */
-        *n_lpadding = 0;
-        assert(0);
-    }
-
-    *n_rpadding = *n_total - nchars - *n_lpadding;
-}
-
-/* Do the padding, and return a pointer to where the caller-supplied
-   content goes. */
-static STRINGLIB_CHAR *
-fill_padding(STRINGLIB_CHAR *p, Py_ssize_t nchars, STRINGLIB_CHAR fill_char,
-             Py_ssize_t n_lpadding, Py_ssize_t n_rpadding)
-{
-    /* Pad on left. */
-    if (n_lpadding)
-        STRINGLIB_FILL(p, fill_char, n_lpadding);
-
-    /* Pad on right. */
-    if (n_rpadding)
-        STRINGLIB_FILL(p + nchars + n_lpadding, fill_char, n_rpadding);
-
-    /* Pointer to the user content. */
-    return p + n_lpadding;
-}
-
-#if defined FORMAT_FLOAT || defined FORMAT_LONG || defined FORMAT_COMPLEX
-/************************************************************************/
-/*********** common routines for numeric formatting *********************/
-/************************************************************************/
-
-/* Locale type codes. */
-#define LT_CURRENT_LOCALE 0
-#define LT_DEFAULT_LOCALE 1
-#define LT_NO_LOCALE 2
-
-/* Locale info needed for formatting integers and the part of floats
-   before and including the decimal. Note that locales only support
-   8-bit chars, not unicode. */
-typedef struct {
-    char *decimal_point;
-    char *thousands_sep;
-    char *grouping;
-} LocaleInfo;
-
-/* describes the layout for an integer, see the comment in
-   calc_number_widths() for details */
-typedef struct {
-    Py_ssize_t n_lpadding;
-    Py_ssize_t n_prefix;
-    Py_ssize_t n_spadding;
-    Py_ssize_t n_rpadding;
-    char sign;
-    Py_ssize_t n_sign;      /* number of digits needed for sign (0/1) */
-    Py_ssize_t n_grouped_digits; /* Space taken up by the digits, including
-                                    any grouping chars. */
-    Py_ssize_t n_decimal;   /* 0 if only an integer */
-    Py_ssize_t n_remainder; /* Digits in decimal and/or exponent part,
-                               excluding the decimal itself, if
-                               present. */
-
-    /* These 2 are not the widths of fields, but are needed by
-       STRINGLIB_GROUPING. */
-    Py_ssize_t n_digits;    /* The number of digits before a decimal
-                               or exponent. */
-    Py_ssize_t n_min_width; /* The min_width we used when we computed
-                               the n_grouped_digits width. */
-} NumberFieldWidths;
-
-
-/* Given a number of the form:
-   digits[remainder]
-   where ptr points to the start and end points to the end, find where
-    the integer part ends. This could be a decimal, an exponent, both,
-    or neither.
-   If a decimal point is present, set *has_decimal and increment
-    remainder beyond it.
-   Results are undefined (but shouldn't crash) for improperly
-    formatted strings.
-*/
-static void
-parse_number(STRINGLIB_CHAR *ptr, Py_ssize_t len,
-             Py_ssize_t *n_remainder, int *has_decimal)
-{
-    STRINGLIB_CHAR *end = ptr + len;
-    STRINGLIB_CHAR *remainder;
-
-    while (ptr<end && isdigit(*ptr))
-        ++ptr;
-    remainder = ptr;
-
-    /* Does remainder start with a decimal point? */
-    *has_decimal = ptr<end && *remainder == '.';
-
-    /* Skip the decimal point. */
-    if (*has_decimal)
-        remainder++;
-
-    *n_remainder = end - remainder;
-}
-
-/* not all fields of format are used.  for example, precision is
-   unused.  should this take discrete params in order to be more clear
-   about what it does?  or is passing a single format parameter easier
-   and more efficient enough to justify a little obfuscation? */
-static Py_ssize_t
-calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
-                   STRINGLIB_CHAR sign_char, STRINGLIB_CHAR *number,
-                   Py_ssize_t n_number, Py_ssize_t n_remainder,
-                   int has_decimal, const LocaleInfo *locale,
-                   const InternalFormatSpec *format)
-{
-    Py_ssize_t n_non_digit_non_padding;
-    Py_ssize_t n_padding;
-
-    spec->n_digits = n_number - n_remainder - (has_decimal?1:0);
-    spec->n_lpadding = 0;
-    spec->n_prefix = n_prefix;
-    spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0;
-    spec->n_remainder = n_remainder;
-    spec->n_spadding = 0;
-    spec->n_rpadding = 0;
-    spec->sign = '\0';
-    spec->n_sign = 0;
-
-    /* the output will look like:
-       |                                                                                         |
-       | <lpadding> <sign> <prefix> <spadding> <grouped_digits> <decimal> <remainder> <rpadding> |
-       |                                                                                         |
-
-       sign is computed from format->sign and the actual
-       sign of the number
-
-       prefix is given (it's for the '0x' prefix)
-
-       digits is already known
-
-       the total width is either given, or computed from the
-       actual digits
-
-       only one of lpadding, spadding, and rpadding can be non-zero,
-       and it's calculated from the width and other fields
-    */
-
-    /* compute the various parts we're going to write */
-    switch (format->sign) {
-    case '+':
-        /* always put a + or - */
-        spec->n_sign = 1;
-        spec->sign = (sign_char == '-' ? '-' : '+');
-        break;
-    case ' ':
-        spec->n_sign = 1;
-        spec->sign = (sign_char == '-' ? '-' : ' ');
-        break;
-    default:
-        /* Not specified, or the default (-) */
-        if (sign_char == '-') {
-            spec->n_sign = 1;
-            spec->sign = '-';
-        }
-    }
-
-    /* The number of chars used for non-digits and non-padding. */
-    n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal +
-        spec->n_remainder;
-
-    /* min_width can go negative, that's okay. format->width == -1 means
-       we don't care. */
-    if (format->fill_char == '0' && format->align == '=')
-        spec->n_min_width = format->width - n_non_digit_non_padding;
-    else
-        spec->n_min_width = 0;
-
-    if (spec->n_digits == 0)
-        /* This case only occurs when using 'c' formatting, we need
-           to special case it because the grouping code always wants
-           to have at least one character. */
-        spec->n_grouped_digits = 0;
-    else
-        spec->n_grouped_digits = STRINGLIB_GROUPING(NULL, 0, NULL,
-                                                    spec->n_digits,
-                                                    spec->n_min_width,
-                                                    locale->grouping,
-                                                    locale->thousands_sep);
-
-    /* Given the desired width and the total of digit and non-digit
-       space we consume, see if we need any padding. format->width can
-       be negative (meaning no padding), but this code still works in
-       that case. */
-    n_padding = format->width -
-                        (n_non_digit_non_padding + spec->n_grouped_digits);
-    if (n_padding > 0) {
-        /* Some padding is needed. Determine if it's left, space, or right. */
-        switch (format->align) {
-        case '<':
-            spec->n_rpadding = n_padding;
-            break;
-        case '^':
-            spec->n_lpadding = n_padding / 2;
-            spec->n_rpadding = n_padding - spec->n_lpadding;
-            break;
-        case '=':
-            spec->n_spadding = n_padding;
-            break;
-        case '>':
-            spec->n_lpadding = n_padding;
-            break;
-        default:
-            /* Shouldn't get here, but treat it as '>' */
-            spec->n_lpadding = n_padding;
-            assert(0);
-            break;
-        }
-    }
-    return spec->n_lpadding + spec->n_sign + spec->n_prefix +
-        spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +
-        spec->n_remainder + spec->n_rpadding;
-}
-
-/* Fill in the digit parts of a numbers's string representation,
-   as determined in calc_number_widths().
-   No error checking, since we know the buffer is the correct size. */
-static void
-fill_number(STRINGLIB_CHAR *buf, const NumberFieldWidths *spec,
-            STRINGLIB_CHAR *digits, Py_ssize_t n_digits,
-            STRINGLIB_CHAR *prefix, STRINGLIB_CHAR fill_char,
-            LocaleInfo *locale, int toupper)
-{
-    /* Used to keep track of digits, decimal, and remainder. */
-    STRINGLIB_CHAR *p = digits;
-
-#ifndef NDEBUG
-    Py_ssize_t r;
-#endif
-
-    if (spec->n_lpadding) {
-        STRINGLIB_FILL(buf, fill_char, spec->n_lpadding);
-        buf += spec->n_lpadding;
-    }
-    if (spec->n_sign == 1) {
-        *buf++ = spec->sign;
-    }
-    if (spec->n_prefix) {
-        memmove(buf,
-                prefix,
-                spec->n_prefix * sizeof(STRINGLIB_CHAR));
-        if (toupper) {
-            Py_ssize_t t;
-            for (t = 0; t < spec->n_prefix; ++t)
-                buf[t] = STRINGLIB_TOUPPER(buf[t]);
-        }
-        buf += spec->n_prefix;
-    }
-    if (spec->n_spadding) {
-        STRINGLIB_FILL(buf, fill_char, spec->n_spadding);
-        buf += spec->n_spadding;
-    }
-
-    /* Only for type 'c' special case, it has no digits. */
-    if (spec->n_digits != 0) {
-        /* Fill the digits with InsertThousandsGrouping. */
-#ifndef NDEBUG
-        r =
-#endif
-            STRINGLIB_GROUPING(buf, spec->n_grouped_digits, digits,
-                               spec->n_digits, spec->n_min_width,
-                               locale->grouping, locale->thousands_sep);
-#ifndef NDEBUG
-        assert(r == spec->n_grouped_digits);
-#endif
-        p += spec->n_digits;
-    }
-    if (toupper) {
-        Py_ssize_t t;
-        for (t = 0; t < spec->n_grouped_digits; ++t)
-            buf[t] = STRINGLIB_TOUPPER(buf[t]);
-    }
-    buf += spec->n_grouped_digits;
-
-    if (spec->n_decimal) {
-        Py_ssize_t t;
-        for (t = 0; t < spec->n_decimal; ++t)
-            buf[t] = locale->decimal_point[t];
-        buf += spec->n_decimal;
-        p += 1;
-    }
-
-    if (spec->n_remainder) {
-        memcpy(buf, p, spec->n_remainder * sizeof(STRINGLIB_CHAR));
-        buf += spec->n_remainder;
-        p += spec->n_remainder;
-    }
-
-    if (spec->n_rpadding) {
-        STRINGLIB_FILL(buf, fill_char, spec->n_rpadding);
-        buf += spec->n_rpadding;
-    }
-}
-
-static char no_grouping[1] = {CHAR_MAX};
-
-/* Find the decimal point character(s?), thousands_separator(s?), and
-   grouping description, either for the current locale if type is
-   LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or
-   none if LT_NO_LOCALE. */
-static void
-get_locale_info(int type, LocaleInfo *locale_info)
-{
-    switch (type) {
-    case LT_CURRENT_LOCALE: {
-        struct lconv *locale_data = localeconv();
-        locale_info->decimal_point = locale_data->decimal_point;
-        locale_info->thousands_sep = locale_data->thousands_sep;
-        locale_info->grouping = locale_data->grouping;
-        break;
-    }
-    case LT_DEFAULT_LOCALE:
-        locale_info->decimal_point = ".";
-        locale_info->thousands_sep = ",";
-        locale_info->grouping = "\3"; /* Group every 3 characters.  The
-                                         (implicit) trailing 0 means repeat
-                                         infinitely. */
-        break;
-    case LT_NO_LOCALE:
-        locale_info->decimal_point = ".";
-        locale_info->thousands_sep = "";
-        locale_info->grouping = no_grouping;
-        break;
-    default:
-        assert(0);
-    }
-}
-
-#endif /* FORMAT_FLOAT || FORMAT_LONG || FORMAT_COMPLEX */
-
-/************************************************************************/
-/*********** string formatting ******************************************/
-/************************************************************************/
-
-static PyObject *
-format_string_internal(PyObject *value, const InternalFormatSpec *format)
-{
-    Py_ssize_t lpad;
-    Py_ssize_t rpad;
-    Py_ssize_t total;
-    STRINGLIB_CHAR *p;
-    Py_ssize_t len = STRINGLIB_LEN(value);
-    PyObject *result = NULL;
-
-    /* sign is not allowed on strings */
-    if (format->sign != '\0') {
-        PyErr_SetString(PyExc_ValueError,
-                        "Sign not allowed in string format specifier");
-        goto done;
-    }
-
-    /* alternate is not allowed on strings */
-    if (format->alternate) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Alternate form (#) not allowed in string format "
-                        "specifier");
-        goto done;
-    }
-
-    /* '=' alignment not allowed on strings */
-    if (format->align == '=') {
-        PyErr_SetString(PyExc_ValueError,
-                        "'=' alignment not allowed "
-                        "in string format specifier");
-        goto done;
-    }
-
-    /* if precision is specified, output no more that format.precision
-       characters */
-    if (format->precision >= 0 && len >= format->precision) {
-        len = format->precision;
-    }
-
-    calc_padding(len, format->width, format->align, &lpad, &rpad, &total);
-
-    /* allocate the resulting string */
-    result = STRINGLIB_NEW(NULL, total);
-    if (result == NULL)
-        goto done;
-
-    /* Write into that space. First the padding. */
-    p = fill_padding(STRINGLIB_STR(result), len,
-                     format->fill_char=='\0'?' ':format->fill_char,
-                     lpad, rpad);
-
-    /* Then the source string. */
-    memcpy(p, STRINGLIB_STR(value), len * sizeof(STRINGLIB_CHAR));
-
-done:
-    return result;
-}
-
-
-/************************************************************************/
-/*********** long formatting ********************************************/
-/************************************************************************/
-
-#if defined FORMAT_LONG || defined FORMAT_INT
-typedef PyObject*
-(*IntOrLongToString)(PyObject *value, int base);
-
-static PyObject *
-format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
-                            IntOrLongToString tostring)
-{
-    PyObject *result = NULL;
-    PyObject *tmp = NULL;
-    STRINGLIB_CHAR *pnumeric_chars;
-    STRINGLIB_CHAR numeric_char;
-    STRINGLIB_CHAR sign_char = '\0';
-    Py_ssize_t n_digits;       /* count of digits need from the computed
-                                  string */
-    Py_ssize_t n_remainder = 0; /* Used only for 'c' formatting, which
-                                   produces non-digits */
-    Py_ssize_t n_prefix = 0;   /* Count of prefix chars, (e.g., '0x') */
-    Py_ssize_t n_total;
-    STRINGLIB_CHAR *prefix = NULL;
-    NumberFieldWidths spec;
-    long x;
-
-    /* Locale settings, either from the actual locale or
-       from a hard-code pseudo-locale */
-    LocaleInfo locale;
-
-    /* no precision allowed on integers */
-    if (format->precision != -1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Precision not allowed in integer format specifier");
-        goto done;
-    }
-
-    /* special case for character formatting */
-    if (format->type == 'c') {
-        /* error to specify a sign */
-        if (format->sign != '\0') {
-            PyErr_SetString(PyExc_ValueError,
-                            "Sign not allowed with integer"
-                            " format specifier 'c'");
-            goto done;
-        }
-
-        /* taken from unicodeobject.c formatchar() */
-        /* Integer input truncated to a character */
-/* XXX: won't work for int */
-        x = PyLong_AsLong(value);
-        if (x == -1 && PyErr_Occurred())
-            goto done;
-#ifdef Py_UNICODE_WIDE
-        if (x < 0 || x > 0x10ffff) {
-            PyErr_SetString(PyExc_OverflowError,
-                            "%c arg not in range(0x110000) "
-                            "(wide Python build)");
-            goto done;
-        }
-#else
-        if (x < 0 || x > 0xffff) {
-            PyErr_SetString(PyExc_OverflowError,
-                            "%c arg not in range(0x10000) "
-                            "(narrow Python build)");
-            goto done;
-        }
-#endif
-        numeric_char = (STRINGLIB_CHAR)x;
-        pnumeric_chars = &numeric_char;
-        n_digits = 1;
-
-        /* As a sort-of hack, we tell calc_number_widths that we only
-           have "remainder" characters. calc_number_widths thinks
-           these are characters that don't get formatted, only copied
-           into the output string. We do this for 'c' formatting,
-           because the characters are likely to be non-digits. */
-        n_remainder = 1;
-    }
-    else {
-        int base;
-        int leading_chars_to_skip = 0;  /* Number of characters added by
-                                           PyNumber_ToBase that we want to
-                                           skip over. */
-
-        /* Compute the base and how many characters will be added by
-           PyNumber_ToBase */
-        switch (format->type) {
-        case 'b':
-            base = 2;
-            leading_chars_to_skip = 2; /* 0b */
-            break;
-        case 'o':
-            base = 8;
-            leading_chars_to_skip = 2; /* 0o */
-            break;
-        case 'x':
-        case 'X':
-            base = 16;
-            leading_chars_to_skip = 2; /* 0x */
-            break;
-        default:  /* shouldn't be needed, but stops a compiler warning */
-        case 'd':
-        case 'n':
-            base = 10;
-            break;
-        }
-
-        /* The number of prefix chars is the same as the leading
-           chars to skip */
-        if (format->alternate)
-            n_prefix = leading_chars_to_skip;
-
-        /* Do the hard part, converting to a string in a given base */
-        tmp = tostring(value, base);
-        if (tmp == NULL)
-            goto done;
-
-        pnumeric_chars = STRINGLIB_STR(tmp);
-        n_digits = STRINGLIB_LEN(tmp);
-
-        prefix = pnumeric_chars;
-
-        /* Remember not to modify what pnumeric_chars points to.  it
-           might be interned.  Only modify it after we copy it into a
-           newly allocated output buffer. */
-
-        /* Is a sign character present in the output?  If so, remember it
-           and skip it */
-        if (pnumeric_chars[0] == '-') {
-            sign_char = pnumeric_chars[0];
-            ++prefix;
-            ++leading_chars_to_skip;
-        }
-
-        /* Skip over the leading chars (0x, 0b, etc.) */
-        n_digits -= leading_chars_to_skip;
-        pnumeric_chars += leading_chars_to_skip;
-    }
-
-    /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
-
-    /* Calculate how much memory we'll need. */
-    n_total = calc_number_widths(&spec, n_prefix, sign_char, pnumeric_chars,
-                       n_digits, n_remainder, 0, &locale, format);
-
-    /* Allocate the memory. */
-    result = STRINGLIB_NEW(NULL, n_total);
-    if (!result)
-        goto done;
-
-    /* Populate the memory. */
-    fill_number(STRINGLIB_STR(result), &spec, pnumeric_chars, n_digits,
-                prefix, format->fill_char == '\0' ? ' ' : format->fill_char,
-                &locale, format->type == 'X');
-
-done:
-    Py_XDECREF(tmp);
-    return result;
-}
-#endif /* defined FORMAT_LONG || defined FORMAT_INT */
-
-/************************************************************************/
-/*********** float formatting *******************************************/
-/************************************************************************/
-
-#ifdef FORMAT_FLOAT
-#if STRINGLIB_IS_UNICODE
-static void
-strtounicode(Py_UNICODE *buffer, const char *charbuffer, Py_ssize_t len)
-{
-    Py_ssize_t i;
-    for (i = 0; i < len; ++i)
-        buffer[i] = (Py_UNICODE)charbuffer[i];
-}
-#endif
-
-/* much of this is taken from unicodeobject.c */
-static PyObject *
-format_float_internal(PyObject *value,
-                      const InternalFormatSpec *format)
-{
-    char *buf = NULL;       /* buffer returned from PyOS_double_to_string */
-    Py_ssize_t n_digits;
-    Py_ssize_t n_remainder;
-    Py_ssize_t n_total;
-    int has_decimal;
-    double val;
-    Py_ssize_t precision = format->precision;
-    Py_ssize_t default_precision = 6;
-    STRINGLIB_CHAR type = format->type;
-    int add_pct = 0;
-    STRINGLIB_CHAR *p;
-    NumberFieldWidths spec;
-    int flags = 0;
-    PyObject *result = NULL;
-    STRINGLIB_CHAR sign_char = '\0';
-    int float_type; /* Used to see if we have a nan, inf, or regular float. */
-
-#if STRINGLIB_IS_UNICODE
-    Py_UNICODE *unicode_tmp = NULL;
-#endif
-
-    /* Locale settings, either from the actual locale or
-       from a hard-code pseudo-locale */
-    LocaleInfo locale;
-
-    if (format->alternate)
-        flags |= Py_DTSF_ALT;
-
-    if (type == '\0') {
-        /* Omitted type specifier.  Behaves in the same way as repr(x)
-           and str(x) if no precision is given, else like 'g', but with
-           at least one digit after the decimal point. */
-        flags |= Py_DTSF_ADD_DOT_0;
-        type = 'r';
-        default_precision = 0;
-    }
-
-    if (type == 'n')
-        /* 'n' is the same as 'g', except for the locale used to
-           format the result. We take care of that later. */
-        type = 'g';
-
-    val = PyFloat_AsDouble(value);
-    if (val == -1.0 && PyErr_Occurred())
-        goto done;
-
-    if (type == '%') {
-        type = 'f';
-        val *= 100;
-        add_pct = 1;
-    }
-
-    if (precision < 0)
-        precision = default_precision;
-    else if (type == 'r')
-        type = 'g';
-
-    /* Cast "type", because if we're in unicode we need to pass a
-       8-bit char. This is safe, because we've restricted what "type"
-       can be. */
-    buf = PyOS_double_to_string(val, (char)type, precision, flags,
-                                &float_type);
-    if (buf == NULL)
-        goto done;
-    n_digits = strlen(buf);
-
-    if (add_pct) {
-        /* We know that buf has a trailing zero (since we just called
-           strlen() on it), and we don't use that fact any more. So we
-           can just write over the trailing zero. */
-        buf[n_digits] = '%';
-        n_digits += 1;
-    }
-
-    /* Since there is no unicode version of PyOS_double_to_string,
-       just use the 8 bit version and then convert to unicode. */
-#if STRINGLIB_IS_UNICODE
-    unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_digits)*sizeof(Py_UNICODE));
-    if (unicode_tmp == NULL) {
-        PyErr_NoMemory();
-        goto done;
-    }
-    strtounicode(unicode_tmp, buf, n_digits);
-    p = unicode_tmp;
-#else
-    p = buf;
-#endif
-
-    /* Is a sign character present in the output?  If so, remember it
-       and skip it */
-    if (*p == '-') {
-        sign_char = *p;
-        ++p;
-        --n_digits;
-    }
-
-    /* Determine if we have any "remainder" (after the digits, might include
-       decimal or exponent or both (or neither)) */
-    parse_number(p, n_digits, &n_remainder, &has_decimal);
-
-    /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
-
-    /* Calculate how much memory we'll need. */
-    n_total = calc_number_widths(&spec, 0, sign_char, p, n_digits,
-                                 n_remainder, has_decimal, &locale, format);
-
-    /* Allocate the memory. */
-    result = STRINGLIB_NEW(NULL, n_total);
-    if (result == NULL)
-        goto done;
-
-    /* Populate the memory. */
-    fill_number(STRINGLIB_STR(result), &spec, p, n_digits, NULL,
-                format->fill_char == '\0' ? ' ' : format->fill_char, &locale,
-                0);
-
-done:
-    PyMem_Free(buf);
-#if STRINGLIB_IS_UNICODE
-    PyMem_Free(unicode_tmp);
-#endif
-    return result;
-}
-#endif /* FORMAT_FLOAT */
-
-/************************************************************************/
-/*********** complex formatting *****************************************/
-/************************************************************************/
-
-#ifdef FORMAT_COMPLEX
-
-static PyObject *
-format_complex_internal(PyObject *value,
-                        const InternalFormatSpec *format)
-{
-    double re;
-    double im;
-    char *re_buf = NULL;       /* buffer returned from PyOS_double_to_string */
-    char *im_buf = NULL;       /* buffer returned from PyOS_double_to_string */
-
-    InternalFormatSpec tmp_format = *format;
-    Py_ssize_t n_re_digits;
-    Py_ssize_t n_im_digits;
-    Py_ssize_t n_re_remainder;
-    Py_ssize_t n_im_remainder;
-    Py_ssize_t n_re_total;
-    Py_ssize_t n_im_total;
-    int re_has_decimal;
-    int im_has_decimal;
-    Py_ssize_t precision = format->precision;
-    Py_ssize_t default_precision = 6;
-    STRINGLIB_CHAR type = format->type;
-    STRINGLIB_CHAR *p_re;
-    STRINGLIB_CHAR *p_im;
-    NumberFieldWidths re_spec;
-    NumberFieldWidths im_spec;
-    int flags = 0;
-    PyObject *result = NULL;
-    STRINGLIB_CHAR *p;
-    STRINGLIB_CHAR re_sign_char = '\0';
-    STRINGLIB_CHAR im_sign_char = '\0';
-    int re_float_type; /* Used to see if we have a nan, inf, or regular float. */
-    int im_float_type;
-    int add_parens = 0;
-    int skip_re = 0;
-    Py_ssize_t lpad;
-    Py_ssize_t rpad;
-    Py_ssize_t total;
-
-#if STRINGLIB_IS_UNICODE
-    Py_UNICODE *re_unicode_tmp = NULL;
-    Py_UNICODE *im_unicode_tmp = NULL;
-#endif
-
-    /* Locale settings, either from the actual locale or
-       from a hard-code pseudo-locale */
-    LocaleInfo locale;
-
-    /* Zero padding is not allowed. */
-    if (format->fill_char == '0') {
-        PyErr_SetString(PyExc_ValueError,
-                        "Zero padding is not allowed in complex format "
-                        "specifier");
-        goto done;
-    }
-
-    /* Neither is '=' alignment . */
-    if (format->align == '=') {
-        PyErr_SetString(PyExc_ValueError,
-                        "'=' alignment flag is not allowed in complex format "
-                        "specifier");
-        goto done;
-    }
-
-    re = PyComplex_RealAsDouble(value);
-    if (re == -1.0 && PyErr_Occurred())
-        goto done;
-    im = PyComplex_ImagAsDouble(value);
-    if (im == -1.0 && PyErr_Occurred())
-        goto done;
-
-    if (format->alternate)
-        flags |= Py_DTSF_ALT;
-
-    if (type == '\0') {
-        /* Omitted type specifier. Should be like str(self). */
-        type = 'r';
-        default_precision = 0;
-        if (re == 0.0 && copysign(1.0, re) == 1.0)
-            skip_re = 1;
-        else
-            add_parens = 1;
-    }
-
-    if (type == 'n')
-        /* 'n' is the same as 'g', except for the locale used to
-           format the result. We take care of that later. */
-        type = 'g';
-
-    if (precision < 0)
-        precision = default_precision;
-    else if (type == 'r')
-        type = 'g';
-
-    /* Cast "type", because if we're in unicode we need to pass a
-       8-bit char. This is safe, because we've restricted what "type"
-       can be. */
-    re_buf = PyOS_double_to_string(re, (char)type, precision, flags,
-                                   &re_float_type);
-    if (re_buf == NULL)
-        goto done;
-    im_buf = PyOS_double_to_string(im, (char)type, precision, flags,
-                                   &im_float_type);
-    if (im_buf == NULL)
-        goto done;
-
-    n_re_digits = strlen(re_buf);
-    n_im_digits = strlen(im_buf);
-
-    /* Since there is no unicode version of PyOS_double_to_string,
-       just use the 8 bit version and then convert to unicode. */
-#if STRINGLIB_IS_UNICODE
-    re_unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_re_digits)*sizeof(Py_UNICODE));
-    if (re_unicode_tmp == NULL) {
-        PyErr_NoMemory();
-        goto done;
-    }
-    strtounicode(re_unicode_tmp, re_buf, n_re_digits);
-    p_re = re_unicode_tmp;
-
-    im_unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_im_digits)*sizeof(Py_UNICODE));
-    if (im_unicode_tmp == NULL) {
-        PyErr_NoMemory();
-        goto done;
-    }
-    strtounicode(im_unicode_tmp, im_buf, n_im_digits);
-    p_im = im_unicode_tmp;
-#else
-    p_re = re_buf;
-    p_im = im_buf;
-#endif
-
-    /* Is a sign character present in the output?  If so, remember it
-       and skip it */
-    if (*p_re == '-') {
-        re_sign_char = *p_re;
-        ++p_re;
-        --n_re_digits;
-    }
-    if (*p_im == '-') {
-        im_sign_char = *p_im;
-        ++p_im;
-        --n_im_digits;
-    }
-
-    /* Determine if we have any "remainder" (after the digits, might include
-       decimal or exponent or both (or neither)) */
-    parse_number(p_re, n_re_digits, &n_re_remainder, &re_has_decimal);
-    parse_number(p_im, n_im_digits, &n_im_remainder, &im_has_decimal);
-
-    /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
-
-    /* Turn off any padding. We'll do it later after we've composed
-       the numbers without padding. */
-    tmp_format.fill_char = '\0';
-    tmp_format.align = '<';
-    tmp_format.width = -1;
-
-    /* Calculate how much memory we'll need. */
-    n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, p_re,
-                                    n_re_digits, n_re_remainder,
-                                    re_has_decimal, &locale, &tmp_format);
-
-    /* Same formatting, but always include a sign, unless the real part is
-     * going to be omitted, in which case we use whatever sign convention was
-     * requested by the original format. */
-    if (!skip_re)
-        tmp_format.sign = '+';
-    n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, p_im,
-                                    n_im_digits, n_im_remainder,
-                                    im_has_decimal, &locale, &tmp_format);
-
-    if (skip_re)
-        n_re_total = 0;
-
-    /* Add 1 for the 'j', and optionally 2 for parens. */
-    calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,
-                 format->width, format->align, &lpad, &rpad, &total);
-
-    result = STRINGLIB_NEW(NULL, total);
-    if (result == NULL)
-        goto done;
-
-    /* Populate the memory. First, the padding. */
-    p = fill_padding(STRINGLIB_STR(result),
-                     n_re_total + n_im_total + 1 + add_parens * 2,
-                     format->fill_char=='\0' ? ' ' : format->fill_char,
-                     lpad, rpad);
-
-    if (add_parens)
-        *p++ = '(';
-
-    if (!skip_re) {
-        fill_number(p, &re_spec, p_re, n_re_digits, NULL, 0, &locale, 0);
-        p += n_re_total;
-    }
-    fill_number(p, &im_spec, p_im, n_im_digits, NULL, 0, &locale, 0);
-    p += n_im_total;
-    *p++ = 'j';
-
-    if (add_parens)
-        *p++ = ')';
-
-done:
-    PyMem_Free(re_buf);
-    PyMem_Free(im_buf);
-#if STRINGLIB_IS_UNICODE
-    PyMem_Free(re_unicode_tmp);
-    PyMem_Free(im_unicode_tmp);
-#endif
-    return result;
-}
-#endif /* FORMAT_COMPLEX */
-
-/************************************************************************/
-/*********** built in formatters ****************************************/
-/************************************************************************/
-PyObject *
-FORMAT_STRING(PyObject *obj,
-              STRINGLIB_CHAR *format_spec,
-              Py_ssize_t format_spec_len)
-{
-    InternalFormatSpec format;
-    PyObject *result = NULL;
-
-    /* check for the special case of zero length format spec, make
-       it equivalent to str(obj) */
-    if (format_spec_len == 0) {
-        result = STRINGLIB_TOSTR(obj);
-        goto done;
-    }
-
-    /* parse the format_spec */
-    if (!parse_internal_render_format_spec(format_spec, format_spec_len,
-                                           &format, 's', '<'))
-        goto done;
-
-    /* type conversion? */
-    switch (format.type) {
-    case 's':
-        /* no type conversion needed, already a string.  do the formatting */
-        result = format_string_internal(obj, &format);
-        break;
-    default:
-        /* unknown */
-        unknown_presentation_type(format.type, obj->ob_type->tp_name);
-        goto done;
-    }
-
-done:
-    return result;
-}
-
-#if defined FORMAT_LONG || defined FORMAT_INT
-static PyObject*
-format_int_or_long(PyObject* obj,
-                   STRINGLIB_CHAR *format_spec,
-                   Py_ssize_t format_spec_len,
-                   IntOrLongToString tostring)
-{
-    PyObject *result = NULL;
-    PyObject *tmp = NULL;
-    InternalFormatSpec format;
-
-    /* check for the special case of zero length format spec, make
-       it equivalent to str(obj) */
-    if (format_spec_len == 0) {
-        result = STRINGLIB_TOSTR(obj);
-        goto done;
-    }
-
-    /* parse the format_spec */
-    if (!parse_internal_render_format_spec(format_spec,
-                                           format_spec_len,
-                                           &format, 'd', '>'))
-        goto done;
-
-    /* type conversion? */
-    switch (format.type) {
-    case 'b':
-    case 'c':
-    case 'd':
-    case 'o':
-    case 'x':
-    case 'X':
-    case 'n':
-        /* no type conversion needed, already an int (or long).  do
-           the formatting */
-            result = format_int_or_long_internal(obj, &format, tostring);
-        break;
-
-    case 'e':
-    case 'E':
-    case 'f':
-    case 'F':
-    case 'g':
-    case 'G':
-    case '%':
-        /* convert to float */
-        tmp = PyNumber_Float(obj);
-        if (tmp == NULL)
-            goto done;
-        result = format_float_internal(tmp, &format);
-        break;
-
-    default:
-        /* unknown */
-        unknown_presentation_type(format.type, obj->ob_type->tp_name);
-        goto done;
-    }
-
-done:
-    Py_XDECREF(tmp);
-    return result;
-}
-#endif /* FORMAT_LONG || defined FORMAT_INT */
-
-#ifdef FORMAT_LONG
-/* Need to define long_format as a function that will convert a long
-   to a string.  In 3.0, _PyLong_Format has the correct signature.  In
-   2.x, we need to fudge a few parameters */
-#if PY_VERSION_HEX >= 0x03000000
-#define long_format _PyLong_Format
-#else
-static PyObject*
-long_format(PyObject* value, int base)
-{
-    /* Convert to base, don't add trailing 'L', and use the new octal
-       format. We already know this is a long object */
-    assert(PyLong_Check(value));
-    /* convert to base, don't add 'L', and use the new octal format */
-    return _PyLong_Format(value, base, 0, 1);
-}
-#endif
-
-PyObject *
-FORMAT_LONG(PyObject *obj,
-            STRINGLIB_CHAR *format_spec,
-            Py_ssize_t format_spec_len)
-{
-    return format_int_or_long(obj, format_spec, format_spec_len,
-                              long_format);
-}
-#endif /* FORMAT_LONG */
-
-#ifdef FORMAT_INT
-/* this is only used for 2.x, not 3.0 */
-static PyObject*
-int_format(PyObject* value, int base)
-{
-    /* Convert to base, and use the new octal format. We already
-       know this is an int object */
-    assert(PyInt_Check(value));
-    return _PyInt_Format((PyIntObject*)value, base, 1);
-}
-
-PyObject *
-FORMAT_INT(PyObject *obj,
-           STRINGLIB_CHAR *format_spec,
-           Py_ssize_t format_spec_len)
-{
-    return format_int_or_long(obj, format_spec, format_spec_len,
-                              int_format);
-}
-#endif /* FORMAT_INT */
-
-#ifdef FORMAT_FLOAT
-PyObject *
-FORMAT_FLOAT(PyObject *obj,
-             STRINGLIB_CHAR *format_spec,
-             Py_ssize_t format_spec_len)
-{
-    PyObject *result = NULL;
-    InternalFormatSpec format;
-
-    /* check for the special case of zero length format spec, make
-       it equivalent to str(obj) */
-    if (format_spec_len == 0) {
-        result = STRINGLIB_TOSTR(obj);
-        goto done;
-    }
-
-    /* parse the format_spec */
-    if (!parse_internal_render_format_spec(format_spec,
-                                           format_spec_len,
-                                           &format, '\0', '>'))
-        goto done;
-
-    /* type conversion? */
-    switch (format.type) {
-    case '\0': /* No format code: like 'g', but with at least one decimal. */
-    case 'e':
-    case 'E':
-    case 'f':
-    case 'F':
-    case 'g':
-    case 'G':
-    case 'n':
-    case '%':
-        /* no conversion, already a float.  do the formatting */
-        result = format_float_internal(obj, &format);
-        break;
-
-    default:
-        /* unknown */
-        unknown_presentation_type(format.type, obj->ob_type->tp_name);
-        goto done;
-    }
-
-done:
-    return result;
-}
-#endif /* FORMAT_FLOAT */
-
-#ifdef FORMAT_COMPLEX
-PyObject *
-FORMAT_COMPLEX(PyObject *obj,
-               STRINGLIB_CHAR *format_spec,
-               Py_ssize_t format_spec_len)
-{
-    PyObject *result = NULL;
-    InternalFormatSpec format;
-
-    /* check for the special case of zero length format spec, make
-       it equivalent to str(obj) */
-    if (format_spec_len == 0) {
-        result = STRINGLIB_TOSTR(obj);
-        goto done;
-    }
-
-    /* parse the format_spec */
-    if (!parse_internal_render_format_spec(format_spec,
-                                           format_spec_len,
-                                           &format, '\0', '>'))
-        goto done;
-
-    /* type conversion? */
-    switch (format.type) {
-    case '\0': /* No format code: like 'g', but with at least one decimal. */
-    case 'e':
-    case 'E':
-    case 'f':
-    case 'F':
-    case 'g':
-    case 'G':
-    case 'n':
-        /* no conversion, already a complex.  do the formatting */
-        result = format_complex_internal(obj, &format);
-        break;
-
-    default:
-        /* unknown */
-        unknown_presentation_type(format.type, obj->ob_type->tp_name);
-        goto done;
-    }
-
-done:
-    return result;
-}
-#endif /* FORMAT_COMPLEX */
diff --git a/Objects/stringlib/localeutil.h b/Objects/stringlib/localeutil.h
index f548133..ddce69d 100644
--- a/Objects/stringlib/localeutil.h
+++ b/Objects/stringlib/localeutil.h
@@ -1,8 +1,5 @@
 /* stringlib: locale related helpers implementation */
 
-#ifndef STRINGLIB_LOCALEUTIL_H
-#define STRINGLIB_LOCALEUTIL_H
-
 #include <locale.h>
 
 #define MAX(x, y) ((x) < (y) ? (y) : (x))
@@ -12,10 +9,10 @@
     const char *grouping;
     char previous;
     Py_ssize_t i; /* Where we're currently pointing in grouping. */
-} GroupGenerator;
+} STRINGLIB(GroupGenerator);
 
 static void
-_GroupGenerator_init(GroupGenerator *self, const char *grouping)
+STRINGLIB(GroupGenerator_init)(STRINGLIB(GroupGenerator) *self, const char *grouping)
 {
     self->grouping = grouping;
     self->i = 0;
@@ -24,7 +21,7 @@
 
 /* Returns the next grouping, or 0 to signify end. */
 static Py_ssize_t
-_GroupGenerator_next(GroupGenerator *self)
+STRINGLIB(GroupGenerator_next)(STRINGLIB(GroupGenerator) *self)
 {
     /* Note that we don't really do much error checking here. If a
        grouping string contains just CHAR_MAX, for example, then just
@@ -48,13 +45,11 @@
 /* Fill in some digits, leading zeros, and thousands separator. All
    are optional, depending on when we're called. */
 static void
-fill(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
+STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
      Py_ssize_t n_chars, Py_ssize_t n_zeros, const char* thousands_sep,
      Py_ssize_t thousands_sep_len)
 {
-#if STRINGLIB_IS_UNICODE
     Py_ssize_t i;
-#endif
 
     if (thousands_sep) {
         *buffer_end -= thousands_sep_len;
@@ -76,7 +71,8 @@
     memcpy(*buffer_end, *digits_end, n_chars * sizeof(STRINGLIB_CHAR));
 
     *buffer_end -= n_zeros;
-    STRINGLIB_FILL(*buffer_end, '0', n_zeros);
+    for (i = 0; i < n_zeros; i++)
+        (*buffer_end)[i] = '0';
 }
 
 /**
@@ -133,15 +129,15 @@
                                         be looked at */
     /* A generator that returns all of the grouping widths, until it
        returns 0. */
-    GroupGenerator groupgen;
-    _GroupGenerator_init(&groupgen, grouping);
+    STRINGLIB(GroupGenerator) groupgen;
+    STRINGLIB(GroupGenerator_init)(&groupgen, grouping);
 
     if (buffer) {
         buffer_end = buffer + n_buffer;
         digits_end = digits + n_digits;
     }
 
-    while ((l = _GroupGenerator_next(&groupgen)) > 0) {
+    while ((l = STRINGLIB(GroupGenerator_next)(&groupgen)) > 0) {
         l = MIN(l, MAX(MAX(remaining, min_width), 1));
         n_zeros = MAX(0, l - remaining);
         n_chars = MAX(0, MIN(remaining, l));
@@ -153,7 +149,7 @@
 
         if (buffer) {
             /* Copy into the output buffer. */
-            fill(&digits_end, &buffer_end, n_chars, n_zeros,
+            STRINGLIB(fill)(&digits_end, &buffer_end, n_chars, n_zeros,
                  use_separator ? thousands_sep : NULL, thousands_sep_len);
         }
 
@@ -180,7 +176,7 @@
         count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
         if (buffer) {
             /* Copy into the output buffer. */
-            fill(&digits_end, &buffer_end, n_chars, n_zeros,
+            STRINGLIB(fill)(&digits_end, &buffer_end, n_chars, n_zeros,
                  use_separator ? thousands_sep : NULL, thousands_sep_len);
         }
     }
@@ -209,4 +205,3 @@
         return _Py_InsertThousandsGrouping(buffer, n_buffer, digits, n_digits,
                                            min_width, grouping, thousands_sep);
 }
-#endif /* STRINGLIB_LOCALEUTIL_H */
diff --git a/Objects/stringlib/partition.h b/Objects/stringlib/partition.h
index 0170bdd..40cb512 100644
--- a/Objects/stringlib/partition.h
+++ b/Objects/stringlib/partition.h
@@ -1,14 +1,11 @@
 /* stringlib: partition implementation */
 
-#ifndef STRINGLIB_PARTITION_H
-#define STRINGLIB_PARTITION_H
-
 #ifndef STRINGLIB_FASTSEARCH_H
 #error must include "stringlib/fastsearch.h" before including this module
 #endif
 
 Py_LOCAL_INLINE(PyObject*)
-stringlib_partition(PyObject* str_obj,
+STRINGLIB(partition)(PyObject* str_obj,
                     const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                     PyObject* sep_obj,
                     const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
@@ -25,7 +22,7 @@
     if (!out)
         return NULL;
 
-    pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_SEARCH);
+    pos = FASTSEARCH(str, str_len, sep, sep_len, -1, FAST_SEARCH);
 
     if (pos < 0) {
 #if STRINGLIB_MUTABLE
@@ -58,7 +55,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject*)
-stringlib_rpartition(PyObject* str_obj,
+STRINGLIB(rpartition)(PyObject* str_obj,
                      const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                      PyObject* sep_obj,
                      const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
@@ -75,7 +72,7 @@
     if (!out)
         return NULL;
 
-    pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_RSEARCH);
+    pos = FASTSEARCH(str, str_len, sep, sep_len, -1, FAST_RSEARCH);
 
     if (pos < 0) {
 #if STRINGLIB_MUTABLE
@@ -107,4 +104,3 @@
     return out;
 }
 
-#endif
diff --git a/Objects/stringlib/split.h b/Objects/stringlib/split.h
index 60e7767..947dd28 100644
--- a/Objects/stringlib/split.h
+++ b/Objects/stringlib/split.h
@@ -1,8 +1,5 @@
 /* stringlib: split implementation */
 
-#ifndef STRINGLIB_SPLIT_H
-#define STRINGLIB_SPLIT_H
-
 #ifndef STRINGLIB_FASTSEARCH_H
 #error must include "stringlib/fastsearch.h" before including this module
 #endif
@@ -54,7 +51,7 @@
 #define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_split_whitespace(PyObject* str_obj,
+STRINGLIB(split_whitespace)(PyObject* str_obj,
                            const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                            Py_ssize_t maxcount)
 {
@@ -102,7 +99,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_split_char(PyObject* str_obj,
+STRINGLIB(split_char)(PyObject* str_obj,
                      const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                      const STRINGLIB_CHAR ch,
                      Py_ssize_t maxcount)
@@ -145,7 +142,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_split(PyObject* str_obj,
+STRINGLIB(split)(PyObject* str_obj,
                 const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                 const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,
                 Py_ssize_t maxcount)
@@ -158,7 +155,7 @@
         return NULL;
     }
     else if (sep_len == 1)
-        return stringlib_split_char(str_obj, str, str_len, sep[0], maxcount);
+        return STRINGLIB(split_char)(str_obj, str, str_len, sep[0], maxcount);
 
     list = PyList_New(PREALLOC_SIZE(maxcount));
     if (list == NULL)
@@ -166,7 +163,7 @@
 
     i = j = 0;
     while (maxcount-- > 0) {
-        pos = fastsearch(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH);
+        pos = FASTSEARCH(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH);
         if (pos < 0)
             break;
         j = i + pos;
@@ -193,7 +190,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_rsplit_whitespace(PyObject* str_obj,
+STRINGLIB(rsplit_whitespace)(PyObject* str_obj,
                             const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                             Py_ssize_t maxcount)
 {
@@ -243,7 +240,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_rsplit_char(PyObject* str_obj,
+STRINGLIB(rsplit_char)(PyObject* str_obj,
                       const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                       const STRINGLIB_CHAR ch,
                       Py_ssize_t maxcount)
@@ -287,7 +284,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_rsplit(PyObject* str_obj,
+STRINGLIB(rsplit)(PyObject* str_obj,
                  const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                  const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,
                  Py_ssize_t maxcount)
@@ -300,7 +297,7 @@
         return NULL;
     }
     else if (sep_len == 1)
-        return stringlib_rsplit_char(str_obj, str, str_len, sep[0], maxcount);
+        return STRINGLIB(rsplit_char)(str_obj, str, str_len, sep[0], maxcount);
 
     list = PyList_New(PREALLOC_SIZE(maxcount));
     if (list == NULL)
@@ -308,7 +305,7 @@
 
     j = str_len;
     while (maxcount-- > 0) {
-        pos = fastsearch(str, j, sep, sep_len, -1, FAST_RSEARCH);
+        pos = FASTSEARCH(str, j, sep, sep_len, -1, FAST_RSEARCH);
         if (pos < 0)
             break;
         SPLIT_ADD(str, pos + sep_len, j);
@@ -336,7 +333,7 @@
 }
 
 Py_LOCAL_INLINE(PyObject *)
-stringlib_splitlines(PyObject* str_obj,
+STRINGLIB(splitlines)(PyObject* str_obj,
                      const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                      int keepends)
 {
@@ -391,4 +388,3 @@
     return NULL;
 }
 
-#endif
diff --git a/Objects/stringlib/stringdefs.h b/Objects/stringlib/stringdefs.h
index 1c49426..9619332 100644
--- a/Objects/stringlib/stringdefs.h
+++ b/Objects/stringlib/stringdefs.h
@@ -6,6 +6,8 @@
    compiled as unicode. */
 #define STRINGLIB_IS_UNICODE     0
 
+#define FASTSEARCH fastsearch
+#define STRINGLIB(F) stringlib_##F
 #define STRINGLIB_OBJECT         PyBytesObject
 #define STRINGLIB_CHAR           char
 #define STRINGLIB_TYPE_NAME      "string"
diff --git a/Objects/stringlib/ucs1lib.h b/Objects/stringlib/ucs1lib.h
new file mode 100644
index 0000000..4685c17
--- /dev/null
+++ b/Objects/stringlib/ucs1lib.h
@@ -0,0 +1,35 @@
+/* this is sort of a hack.  there's at least one place (formatting
+   floats) where some stringlib code takes a different path if it's
+   compiled as unicode. */
+#define STRINGLIB_IS_UNICODE     1
+
+#define FASTSEARCH               ucs1lib_fastsearch
+#define STRINGLIB(F)             ucs1lib_##F
+#define STRINGLIB_OBJECT         PyUnicodeObject
+#define STRINGLIB_CHAR           Py_UCS1
+#define STRINGLIB_TYPE_NAME      "unicode"
+#define STRINGLIB_PARSE_CODE     "U"
+#define STRINGLIB_EMPTY          unicode_empty
+#define STRINGLIB_ISSPACE        Py_UNICODE_ISSPACE
+#define STRINGLIB_ISLINEBREAK    BLOOM_LINEBREAK
+#define STRINGLIB_ISDECIMAL      Py_UNICODE_ISDECIMAL
+#define STRINGLIB_TODECIMAL      Py_UNICODE_TODECIMAL
+#define STRINGLIB_TOUPPER        Py_UNICODE_TOUPPER
+#define STRINGLIB_TOLOWER        Py_UNICODE_TOLOWER
+#define STRINGLIB_FILL           Py_UNICODE_FILL
+#define STRINGLIB_STR            PyUnicode_1BYTE_DATA
+#define STRINGLIB_LEN            PyUnicode_GET_LENGTH
+#define STRINGLIB_NEW            PyUnicode_FromUCS1
+#define STRINGLIB_RESIZE         not_supported
+#define STRINGLIB_CHECK          PyUnicode_Check
+#define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
+#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
+#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
+
+#define STRINGLIB_TOSTR          PyObject_Str
+#define STRINGLIB_TOASCII        PyObject_ASCII
+
+#define _Py_InsertThousandsGrouping _PyUnicode_ucs1_InsertThousandsGrouping
+#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs1_InsertThousandsGroupingLocale
+
+
diff --git a/Objects/stringlib/ucs2lib.h b/Objects/stringlib/ucs2lib.h
new file mode 100644
index 0000000..1bb9c27
--- /dev/null
+++ b/Objects/stringlib/ucs2lib.h
@@ -0,0 +1,34 @@
+/* this is sort of a hack.  there's at least one place (formatting
+   floats) where some stringlib code takes a different path if it's
+   compiled as unicode. */
+#define STRINGLIB_IS_UNICODE     1
+
+#define FASTSEARCH               ucs2lib_fastsearch
+#define STRINGLIB(F)             ucs2lib_##F
+#define STRINGLIB_OBJECT         PyUnicodeObject
+#define STRINGLIB_CHAR           Py_UCS2
+#define STRINGLIB_TYPE_NAME      "unicode"
+#define STRINGLIB_PARSE_CODE     "U"
+#define STRINGLIB_EMPTY          unicode_empty
+#define STRINGLIB_ISSPACE        Py_UNICODE_ISSPACE
+#define STRINGLIB_ISLINEBREAK    BLOOM_LINEBREAK
+#define STRINGLIB_ISDECIMAL      Py_UNICODE_ISDECIMAL
+#define STRINGLIB_TODECIMAL      Py_UNICODE_TODECIMAL
+#define STRINGLIB_TOUPPER        Py_UNICODE_TOUPPER
+#define STRINGLIB_TOLOWER        Py_UNICODE_TOLOWER
+#define STRINGLIB_FILL           Py_UNICODE_FILL
+#define STRINGLIB_STR            PyUnicode_1BYTE_DATA
+#define STRINGLIB_LEN            PyUnicode_GET_LENGTH
+#define STRINGLIB_NEW            PyUnicode_FromUCS2
+#define STRINGLIB_RESIZE         not_supported
+#define STRINGLIB_CHECK          PyUnicode_Check
+#define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
+#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
+#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
+
+#define STRINGLIB_TOSTR          PyObject_Str
+#define STRINGLIB_TOASCII        PyObject_ASCII
+
+#define _Py_InsertThousandsGrouping _PyUnicode_ucs2_InsertThousandsGrouping
+#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs2_InsertThousandsGroupingLocale
+
diff --git a/Objects/stringlib/ucs4lib.h b/Objects/stringlib/ucs4lib.h
new file mode 100644
index 0000000..776d65f
--- /dev/null
+++ b/Objects/stringlib/ucs4lib.h
@@ -0,0 +1,34 @@
+/* this is sort of a hack.  there's at least one place (formatting
+   floats) where some stringlib code takes a different path if it's
+   compiled as unicode. */
+#define STRINGLIB_IS_UNICODE     1
+
+#define FASTSEARCH               ucs4lib_fastsearch
+#define STRINGLIB(F)             ucs4lib_##F
+#define STRINGLIB_OBJECT         PyUnicodeObject
+#define STRINGLIB_CHAR           Py_UCS4
+#define STRINGLIB_TYPE_NAME      "unicode"
+#define STRINGLIB_PARSE_CODE     "U"
+#define STRINGLIB_EMPTY          unicode_empty
+#define STRINGLIB_ISSPACE        Py_UNICODE_ISSPACE
+#define STRINGLIB_ISLINEBREAK    BLOOM_LINEBREAK
+#define STRINGLIB_ISDECIMAL      Py_UNICODE_ISDECIMAL
+#define STRINGLIB_TODECIMAL      Py_UNICODE_TODECIMAL
+#define STRINGLIB_TOUPPER        Py_UNICODE_TOUPPER
+#define STRINGLIB_TOLOWER        Py_UNICODE_TOLOWER
+#define STRINGLIB_FILL           Py_UNICODE_FILL
+#define STRINGLIB_STR            PyUnicode_1BYTE_DATA
+#define STRINGLIB_LEN            PyUnicode_GET_LENGTH
+#define STRINGLIB_NEW            PyUnicode_FromUCS4
+#define STRINGLIB_RESIZE         not_supported
+#define STRINGLIB_CHECK          PyUnicode_Check
+#define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
+#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
+#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
+
+#define STRINGLIB_TOSTR          PyObject_Str
+#define STRINGLIB_TOASCII        PyObject_ASCII
+
+#define _Py_InsertThousandsGrouping _PyUnicode_ucs4_InsertThousandsGrouping
+#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs4_InsertThousandsGroupingLocale
+
diff --git a/Objects/stringlib/undef.h b/Objects/stringlib/undef.h
new file mode 100644
index 0000000..40b4391
--- /dev/null
+++ b/Objects/stringlib/undef.h
@@ -0,0 +1,10 @@
+#undef  FASTSEARCH
+#undef  STRINGLIB
+#undef  STRINGLIB_CHAR
+#undef  STRINGLIB_STR
+#undef  STRINGLIB_LEN
+#undef  STRINGLIB_NEW
+#undef  STRINGLIB_RESIZE
+#undef  _Py_InsertThousandsGrouping
+#undef  _Py_InsertThousandsGroupingLocale
+
diff --git a/Objects/stringlib/string_format.h b/Objects/stringlib/unicode_format.h
similarity index 81%
rename from Objects/stringlib/string_format.h
rename to Objects/stringlib/unicode_format.h
index d992b6f..81a1ff2 100644
--- a/Objects/stringlib/string_format.h
+++ b/Objects/stringlib/unicode_format.h
@@ -1,16 +1,8 @@
 /*
-    string_format.h -- implementation of string.format().
-
-    It uses the Objects/stringlib conventions, so that it can be
-    compiled for both unicode and string objects.
+    unicode_format.h -- implementation of str.format().
 */
 
 
-/* Defines for Python 2.6 compatibility */
-#if PY_VERSION_HEX < 0x03000000
-#define PyLong_FromSsize_t _PyLong_FromSsize_t
-#endif
-
 /* Defines for more efficiently reallocating the string buffer */
 #define INITIAL_SIZE_INCREMENT 100
 #define SIZE_MULTIPLIER 2
@@ -26,8 +18,8 @@
    unicode pointers.
 */
 typedef struct {
-    STRINGLIB_CHAR *ptr;
-    STRINGLIB_CHAR *end;
+    PyObject *str; /* borrowed reference */
+    Py_ssize_t start, end;
 } SubString;
 
 
@@ -64,34 +56,32 @@
 
 /* fill in a SubString from a pointer and length */
 Py_LOCAL_INLINE(void)
-SubString_init(SubString *str, STRINGLIB_CHAR *p, Py_ssize_t len)
+SubString_init(SubString *str, PyObject *s, int start, int end)
 {
-    str->ptr = p;
-    if (p == NULL)
-        str->end = NULL;
-    else
-        str->end = str->ptr + len;
+    str->str = s;
+    str->start = start;
+    str->end = end;
 }
 
-/* return a new string.  if str->ptr is NULL, return None */
+/* return a new string.  if str->str is NULL, return None */
 Py_LOCAL_INLINE(PyObject *)
 SubString_new_object(SubString *str)
 {
-    if (str->ptr == NULL) {
+    if (str->str == NULL) {
         Py_INCREF(Py_None);
         return Py_None;
     }
-    return STRINGLIB_NEW(str->ptr, str->end - str->ptr);
+    return PyUnicode_Substring(str->str, str->start, str->end);
 }
 
-/* return a new string.  if str->ptr is NULL, return None */
+/* return a new string.  if str->str is NULL, return None */
 Py_LOCAL_INLINE(PyObject *)
 SubString_new_object_or_empty(SubString *str)
 {
-    if (str->ptr == NULL) {
-        return STRINGLIB_NEW(NULL, 0);
+    if (str->str == NULL) {
+        return PyUnicode_FromUnicode(NULL, 0);
     }
-    return STRINGLIB_NEW(str->ptr, str->end - str->ptr);
+    return SubString_new_object(str);
 }
 
 /* Return 1 if an error has been detected switching between automatic
@@ -125,9 +115,10 @@
 /************************************************************************/
 
 typedef struct {
-    STRINGLIB_CHAR *ptr;
-    STRINGLIB_CHAR *end;
-    PyObject *obj;
+    char *data;
+    Py_UCS4 maxchar;
+    unsigned int kind;
+    Py_ssize_t pos, size;
     Py_ssize_t size_increment;
 } OutputString;
 
@@ -135,12 +126,16 @@
 static int
 output_initialize(OutputString *output, Py_ssize_t size)
 {
-    output->obj = STRINGLIB_NEW(NULL, size);
-    if (output->obj == NULL)
+    output->data = PyMem_Malloc(size);
+    if (output->data == NULL) {
+        PyErr_NoMemory();
         return 0;
+    }
 
-    output->ptr = STRINGLIB_STR(output->obj);
-    output->end = STRINGLIB_LEN(output->obj) + output->ptr;
+    output->maxchar = 127;
+    output->kind = PyUnicode_1BYTE_KIND;
+    output->pos = 0;
+    output->size = size;
     output->size_increment = INITIAL_SIZE_INCREMENT;
 
     return 1;
@@ -155,20 +150,51 @@
 static int
 output_extend(OutputString *output, Py_ssize_t count)
 {
-    STRINGLIB_CHAR *startptr = STRINGLIB_STR(output->obj);
-    Py_ssize_t curlen = output->ptr - startptr;
-    Py_ssize_t maxlen = curlen + count + output->size_increment;
+    Py_ssize_t maxlen = output->size + count + output->size_increment;
 
-    if (STRINGLIB_RESIZE(&output->obj, maxlen) < 0)
+    output->data = PyMem_Realloc(output->data, maxlen << (output->kind-1));
+    output->size = maxlen;
+    if (output->data == 0) {
+        PyErr_NoMemory();
         return 0;
-    startptr = STRINGLIB_STR(output->obj);
-    output->ptr = startptr + curlen;
-    output->end = startptr + maxlen;
+    }
     if (output->size_increment < MAX_SIZE_INCREMENT)
         output->size_increment *= SIZE_MULTIPLIER;
     return 1;
 }
 
+static int
+output_widen(OutputString *output, Py_UCS4 maxchar)
+{
+    int kind;
+    void *data; 
+    Py_ssize_t i;
+    if (maxchar <= output->maxchar)
+        return 1;
+    if (maxchar < 256) {
+        output->maxchar = 255;
+        return 1;
+    }
+    if (maxchar < 65536) {
+        output->maxchar = 65535;
+        kind = 2;
+    }
+    else {
+        output->maxchar = 1<<21;
+        kind = 3;
+    }
+    data = PyMem_Malloc(output->size << (kind-1));
+    if (data == 0)
+        return 0;
+    for (i = 0; i < output->size; i++)
+        PyUnicode_WRITE(kind, data, i,
+                        PyUnicode_READ(output->kind, output->data, i));
+    PyMem_Free(output->data);
+    output->data = data;
+    output->kind = kind;
+    return 1;
+}
+
 /*
     output_data dumps characters into our output string
     buffer.
@@ -179,12 +205,25 @@
     1 for success.
 */
 static int
-output_data(OutputString *output, const STRINGLIB_CHAR *s, Py_ssize_t count)
+output_data(OutputString *output, PyObject *s, Py_ssize_t start, Py_ssize_t end)
 {
-    if ((count > output->end - output->ptr) && !output_extend(output, count))
+    Py_ssize_t i;
+    int kind;
+    if ((output->pos + end - start > output->size) && 
+        !output_extend(output, end - start))
         return 0;
-    memcpy(output->ptr, s, count * sizeof(STRINGLIB_CHAR));
-    output->ptr += count;
+    kind = PyUnicode_KIND(s);
+    if (PyUnicode_MAX_CHAR_VALUE(s) > output->maxchar) {
+        Py_UCS4 maxchar = output->maxchar;
+        for (i = start; i < end; i++)
+            if (PyUnicode_READ(kind, PyUnicode_DATA(s), i) > maxchar)
+                maxchar = PyUnicode_READ(kind, PyUnicode_DATA(s), i);
+        if (!output_widen(output, maxchar))
+            return 0;
+    }
+    for (i = start; i < end; i++)
+        PyUnicode_WRITE(output->kind, output->data, output->pos++,
+                        PyUnicode_READ(kind, PyUnicode_DATA(s), i));
     return 1;
 }
 
@@ -197,15 +236,14 @@
 {
     Py_ssize_t accumulator = 0;
     Py_ssize_t digitval;
-    Py_ssize_t oldaccumulator;
-    STRINGLIB_CHAR *p;
+    Py_ssize_t i;
 
     /* empty string is an error */
-    if (str->ptr >= str->end)
+    if (str->start >= str->end)
         return -1;
 
-    for (p = str->ptr; p < str->end; p++) {
-        digitval = STRINGLIB_TODECIMAL(*p);
+    for (i = str->start; i < str->end; i++) {
+        digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ_CHAR(str->str, i));
         if (digitval < 0)
             return -1;
         /*
@@ -280,34 +318,36 @@
        lifetime of the iterator.  can be empty */
     SubString str;
 
-    /* pointer to where we are inside field_name */
-    STRINGLIB_CHAR *ptr;
+    /* index to where we are inside field_name */
+    Py_ssize_t index;
 } FieldNameIterator;
 
 
 static int
-FieldNameIterator_init(FieldNameIterator *self, STRINGLIB_CHAR *ptr,
-                       Py_ssize_t len)
+FieldNameIterator_init(FieldNameIterator *self, PyObject *s,
+                       Py_ssize_t start, Py_ssize_t end)
 {
-    SubString_init(&self->str, ptr, len);
-    self->ptr = self->str.ptr;
+    SubString_init(&self->str, s, start, end);
+    self->index = start;
     return 1;
 }
 
 static int
 _FieldNameIterator_attr(FieldNameIterator *self, SubString *name)
 {
-    STRINGLIB_CHAR c;
+    Py_UCS4 c;
 
-    name->ptr = self->ptr;
+    name->str = self->str.str;
+    name->start = self->index;
 
     /* return everything until '.' or '[' */
-    while (self->ptr < self->str.end) {
-        switch (c = *self->ptr++) {
+    while (self->index < self->str.end) {
+        c = PyUnicode_READ_CHAR(self->str.str, self->index++);
+        switch (c) {
         case '[':
         case '.':
             /* backup so that we this character will be seen next time */
-            self->ptr--;
+            self->index--;
             break;
         default:
             continue;
@@ -315,7 +355,7 @@
         break;
     }
     /* end of string is okay */
-    name->end = self->ptr;
+    name->end = self->index;
     return 1;
 }
 
@@ -323,13 +363,15 @@
 _FieldNameIterator_item(FieldNameIterator *self, SubString *name)
 {
     int bracket_seen = 0;
-    STRINGLIB_CHAR c;
+    Py_UCS4 c;
 
-    name->ptr = self->ptr;
+    name->str = self->str.str;
+    name->start = self->index;
 
     /* return everything until ']' */
-    while (self->ptr < self->str.end) {
-        switch (c = *self->ptr++) {
+    while (self->index < self->str.end) {
+        c = PyUnicode_READ_CHAR(self->str.str, self->index++);
+        switch (c) {
         case ']':
             bracket_seen = 1;
             break;
@@ -346,7 +388,7 @@
 
     /* end of string is okay */
     /* don't include the ']' */
-    name->end = self->ptr-1;
+    name->end = self->index-1;
     return 1;
 }
 
@@ -356,10 +398,10 @@
                        Py_ssize_t *name_idx, SubString *name)
 {
     /* check at end of input */
-    if (self->ptr >= self->str.end)
+    if (self->index >= self->str.end)
         return 1;
 
-    switch (*self->ptr++) {
+    switch (PyUnicode_READ_CHAR(self->str.str, self->index++)) {
     case '.':
         *is_attribute = 1;
         if (_FieldNameIterator_attr(self, name) == 0)
@@ -382,7 +424,7 @@
     }
 
     /* empty string is an error */
-    if (name->ptr == name->end) {
+    if (name->start == name->end) {
         PyErr_SetString(PyExc_ValueError, "Empty attribute in format string");
         return 0;
     }
@@ -398,24 +440,23 @@
            'rest' is an iterator to return the rest
 */
 static int
-field_name_split(STRINGLIB_CHAR *ptr, Py_ssize_t len, SubString *first,
+field_name_split(PyObject *str, Py_ssize_t start, Py_ssize_t end, SubString *first,
                  Py_ssize_t *first_idx, FieldNameIterator *rest,
                  AutoNumber *auto_number)
 {
-    STRINGLIB_CHAR c;
-    STRINGLIB_CHAR *p = ptr;
-    STRINGLIB_CHAR *end = ptr + len;
+    Py_UCS4 c;
+    Py_ssize_t i = start;
     int field_name_is_empty;
     int using_numeric_index;
 
     /* find the part up until the first '.' or '[' */
-    while (p < end) {
-        switch (c = *p++) {
+    while (i < end) {
+        switch (c = PyUnicode_READ_CHAR(str, i++)) {
         case '[':
         case '.':
             /* backup so that we this character is available to the
                "rest" iterator */
-            p--;
+            i--;
             break;
         default:
             continue;
@@ -424,15 +465,15 @@
     }
 
     /* set up the return values */
-    SubString_init(first, ptr, p - ptr);
-    FieldNameIterator_init(rest, p, end - p);
+    SubString_init(first, str, start, i);
+    FieldNameIterator_init(rest, str, i, end);
 
     /* see if "first" is an integer, in which case it's used as an index */
     *first_idx = get_integer(first);
     if (*first_idx == -1 && PyErr_Occurred())
         return 0;
 
-    field_name_is_empty = first->ptr >= first->end;
+    field_name_is_empty = first->start >= first->end;
 
     /* If the field name is omitted or if we have a numeric index
        specified, then we're doing numeric indexing into args. */
@@ -487,7 +528,7 @@
     Py_ssize_t index;
     FieldNameIterator rest;
 
-    if (!field_name_split(input->ptr, input->end - input->ptr, &first,
+    if (!field_name_split(input->str, input->start, input->end, &first,
                           &index, &rest, auto_number)) {
         goto error;
     }
@@ -576,12 +617,8 @@
     int ok = 0;
     PyObject *result = NULL;
     PyObject *format_spec_object = NULL;
-    PyObject *(*formatter)(PyObject *, STRINGLIB_CHAR *, Py_ssize_t) = NULL;
-    STRINGLIB_CHAR* format_spec_start = format_spec->ptr ?
-            format_spec->ptr : NULL;
-    Py_ssize_t format_spec_len = format_spec->ptr ?
-            format_spec->end - format_spec->ptr : 0;
-
+    PyObject *(*formatter)(PyObject *, PyObject *, Py_ssize_t, Py_ssize_t) = NULL;
+    
     /* If we know the type exactly, skip the lookup of __format__ and just
        call the formatter directly. */
     if (PyUnicode_CheckExact(fieldobj))
@@ -597,39 +634,28 @@
     if (formatter) {
         /* we know exactly which formatter will be called when __format__ is
            looked up, so call it directly, instead. */
-        result = formatter(fieldobj, format_spec_start, format_spec_len);
+        result = formatter(fieldobj, format_spec->str,
+                           format_spec->start, format_spec->end);
     }
     else {
         /* We need to create an object out of the pointers we have, because
            __format__ takes a string/unicode object for format_spec. */
-        format_spec_object = STRINGLIB_NEW(format_spec_start,
-                                           format_spec_len);
+        if (format_spec->str)
+            format_spec_object = PyUnicode_Substring(format_spec->str,
+                                                     format_spec->start,
+                                                     format_spec->end);
+        else
+            format_spec_object = PyUnicode_New(0, 0);
         if (format_spec_object == NULL)
             goto done;
 
         result = PyObject_Format(fieldobj, format_spec_object);
     }
-    if (result == NULL)
+    if (result == NULL || PyUnicode_READY(result) == -1)
         goto done;
 
-#if PY_VERSION_HEX >= 0x03000000
     assert(PyUnicode_Check(result));
-#else
-    assert(PyBytes_Check(result) || PyUnicode_Check(result));
-
-    /* Convert result to our type.  We could be str, and result could
-       be unicode */
-    {
-        PyObject *tmp = STRINGLIB_TOSTR(result);
-        if (tmp == NULL)
-            goto done;
-        Py_DECREF(result);
-        result = tmp;
-    }
-#endif
-
-    ok = output_data(output,
-                     STRINGLIB_STR(result), STRINGLIB_LEN(result));
+    ok = output_data(output, result, 0, PyUnicode_GET_LENGTH(result));
 done:
     Py_XDECREF(format_spec_object);
     Py_XDECREF(result);
@@ -638,23 +664,24 @@
 
 static int
 parse_field(SubString *str, SubString *field_name, SubString *format_spec,
-            STRINGLIB_CHAR *conversion)
+            Py_UCS4 *conversion)
 {
     /* Note this function works if the field name is zero length,
        which is good.  Zero length field names are handled later, in
        field_name_split. */
 
-    STRINGLIB_CHAR c = 0;
+    Py_UCS4 c = 0;
 
     /* initialize these, as they may be empty */
     *conversion = '\0';
-    SubString_init(format_spec, NULL, 0);
+    SubString_init(format_spec, NULL, 0, 0);
 
     /* Search for the field name.  it's terminated by the end of
        the string, or a ':' or '!' */
-    field_name->ptr = str->ptr;
-    while (str->ptr < str->end) {
-        switch (c = *(str->ptr++)) {
+    field_name->str = str->str;
+    field_name->start = str->start;
+    while (str->start < str->end) {
+        switch ((c = PyUnicode_READ_CHAR(str->str, str->start++))) {
         case ':':
         case '!':
             break;
@@ -667,26 +694,27 @@
     if (c == '!' || c == ':') {
         /* we have a format specifier and/or a conversion */
         /* don't include the last character */
-        field_name->end = str->ptr-1;
+        field_name->end = str->start-1;
 
         /* the format specifier is the rest of the string */
-        format_spec->ptr = str->ptr;
+        format_spec->str = str->str;
+        format_spec->start = str->start;
         format_spec->end = str->end;
 
         /* see if there's a conversion specifier */
         if (c == '!') {
             /* there must be another character present */
-            if (format_spec->ptr >= format_spec->end) {
+            if (format_spec->start >= format_spec->end) {
                 PyErr_SetString(PyExc_ValueError,
                                 "end of format while looking for conversion "
                                 "specifier");
                 return 0;
             }
-            *conversion = *(format_spec->ptr++);
+            *conversion = PyUnicode_READ_CHAR(format_spec->str, format_spec->start++);
 
             /* if there is another character, it must be a colon */
-            if (format_spec->ptr < format_spec->end) {
-                c = *(format_spec->ptr++);
+            if (format_spec->start < format_spec->end) {
+                c = PyUnicode_READ_CHAR(format_spec->str, format_spec->start++);
                 if (c != ':') {
                     PyErr_SetString(PyExc_ValueError,
                                     "expected ':' after format specifier");
@@ -697,7 +725,7 @@
     }
     else
         /* end of string, there's no format_spec or conversion */
-        field_name->end = str->ptr;
+        field_name->end = str->start;
 
     return 1;
 }
@@ -716,9 +744,10 @@
 } MarkupIterator;
 
 static int
-MarkupIterator_init(MarkupIterator *self, STRINGLIB_CHAR *ptr, Py_ssize_t len)
+MarkupIterator_init(MarkupIterator *self, PyObject *str, 
+                    Py_ssize_t start, Py_ssize_t end)
 {
-    SubString_init(&self->str, ptr, len);
+    SubString_init(&self->str, str, start, end);
     return 1;
 }
 
@@ -727,30 +756,30 @@
 static int
 MarkupIterator_next(MarkupIterator *self, SubString *literal,
                     int *field_present, SubString *field_name,
-                    SubString *format_spec, STRINGLIB_CHAR *conversion,
+                    SubString *format_spec, Py_UCS4 *conversion,
                     int *format_spec_needs_expanding)
 {
     int at_end;
-    STRINGLIB_CHAR c = 0;
-    STRINGLIB_CHAR *start;
+    Py_UCS4 c = 0;
+    Py_ssize_t start;
     int count;
     Py_ssize_t len;
     int markup_follows = 0;
 
     /* initialize all of the output variables */
-    SubString_init(literal, NULL, 0);
-    SubString_init(field_name, NULL, 0);
-    SubString_init(format_spec, NULL, 0);
+    SubString_init(literal, NULL, 0, 0);
+    SubString_init(field_name, NULL, 0, 0);
+    SubString_init(format_spec, NULL, 0, 0);
     *conversion = '\0';
     *format_spec_needs_expanding = 0;
     *field_present = 0;
 
     /* No more input, end of iterator.  This is the normal exit
        path. */
-    if (self->str.ptr >= self->str.end)
+    if (self->str.start >= self->str.end)
         return 1;
 
-    start = self->str.ptr;
+    start = self->str.start;
 
     /* First read any literal text. Read until the end of string, an
        escaped '{' or '}', or an unescaped '{'.  In order to never
@@ -759,8 +788,8 @@
        including the brace, but no format object.  The next time
        through, we'll return the rest of the literal, skipping past
        the second consecutive brace. */
-    while (self->str.ptr < self->str.end) {
-        switch (c = *(self->str.ptr++)) {
+    while (self->str.start < self->str.end) {
+        switch (c = PyUnicode_READ_CHAR(self->str.str, self->str.start++)) {
         case '{':
         case '}':
             markup_follows = 1;
@@ -771,10 +800,12 @@
         break;
     }
 
-    at_end = self->str.ptr >= self->str.end;
-    len = self->str.ptr - start;
+    at_end = self->str.start >= self->str.end;
+    len = self->str.start - start;
 
-    if ((c == '}') && (at_end || (c != *self->str.ptr))) {
+    if ((c == '}') && (at_end || 
+                       (c != PyUnicode_READ_CHAR(self->str.str, 
+                                                 self->str.start)))) {
         PyErr_SetString(PyExc_ValueError, "Single '}' encountered "
                         "in format string");
         return 0;
@@ -785,10 +816,10 @@
         return 0;
     }
     if (!at_end) {
-        if (c == *self->str.ptr) {
+        if (c == PyUnicode_READ_CHAR(self->str.str, self->str.start)) {
             /* escaped } or {, skip it in the input.  there is no
                markup object following us, just this literal text */
-            self->str.ptr++;
+            self->str.start++;
             markup_follows = 0;
         }
         else
@@ -796,7 +827,8 @@
     }
 
     /* record the literal text */
-    literal->ptr = start;
+    literal->str = self->str.str;
+    literal->start = start;
     literal->end = start + len;
 
     if (!markup_follows)
@@ -808,12 +840,12 @@
     *field_present = 1;
     count = 1;
 
-    start = self->str.ptr;
+    start = self->str.start;
 
     /* we know we can't have a zero length string, so don't worry
        about that case */
-    while (self->str.ptr < self->str.end) {
-        switch (c = *(self->str.ptr++)) {
+    while (self->str.start < self->str.end) {
+        switch (c = PyUnicode_READ_CHAR(self->str.str, self->str.start++)) {
         case '{':
             /* the format spec needs to be recursively expanded.
                this is an optimization, and not strictly needed */
@@ -826,7 +858,7 @@
                 /* we're done.  parse and get out */
                 SubString s;
 
-                SubString_init(&s, start, self->str.ptr - 1 - start);
+                SubString_init(&s, self->str.str, start, self->str.start - 1);
                 if (parse_field(&s, field_name, format_spec, conversion) == 0)
                     return 0;
 
@@ -845,7 +877,7 @@
 
 /* do the !r or !s conversion on obj */
 static PyObject *
-do_conversion(PyObject *obj, STRINGLIB_CHAR conversion)
+do_conversion(PyObject *obj, Py_UCS4 conversion)
 {
     /* XXX in pre-3.0, do we need to convert this to unicode, since it
        might have returned a string? */
@@ -853,11 +885,9 @@
     case 'r':
         return PyObject_Repr(obj);
     case 's':
-        return STRINGLIB_TOSTR(obj);
-#if PY_VERSION_HEX >= 0x03000000
+        return PyObject_Str(obj);
     case 'a':
-        return STRINGLIB_TOASCII(obj);
-#endif
+        return PyObject_ASCII(obj);
     default:
         if (conversion > 32 && conversion < 127) {
                 /* It's the ASCII subrange; casting to char is safe
@@ -889,7 +919,7 @@
 
 static int
 output_markup(SubString *field_name, SubString *format_spec,
-              int format_spec_needs_expanding, STRINGLIB_CHAR conversion,
+              int format_spec_needs_expanding, Py_UCS4 conversion,
               OutputString *output, PyObject *args, PyObject *kwargs,
               int recursion_depth, AutoNumber *auto_number)
 {
@@ -906,7 +936,7 @@
 
     if (conversion != '\0') {
         tmp = do_conversion(fieldobj, conversion);
-        if (tmp == NULL)
+        if (tmp == NULL || PyUnicode_READY(tmp) == -1)
             goto done;
 
         /* do the assignment, transferring ownership: fieldobj = tmp */
@@ -919,14 +949,13 @@
     if (format_spec_needs_expanding) {
         tmp = build_string(format_spec, args, kwargs, recursion_depth-1,
                            auto_number);
-        if (tmp == NULL)
+        if (tmp == NULL || PyUnicode_READY(tmp) == -1)
             goto done;
 
         /* note that in the case we're expanding the format string,
            tmp must be kept around until after the call to
            render_field. */
-        SubString_init(&expanded_format_spec,
-                       STRINGLIB_STR(tmp), STRINGLIB_LEN(tmp));
+        SubString_init(&expanded_format_spec, tmp, 0, PyUnicode_GET_LENGTH(tmp));
         actual_format_spec = &expanded_format_spec;
     }
     else
@@ -961,14 +990,14 @@
     SubString literal;
     SubString field_name;
     SubString format_spec;
-    STRINGLIB_CHAR conversion;
+    Py_UCS4 conversion;
 
-    MarkupIterator_init(&iter, input->ptr, input->end - input->ptr);
+    MarkupIterator_init(&iter, input->str, input->start, input->end);
     while ((result = MarkupIterator_next(&iter, &literal, &field_present,
                                          &field_name, &format_spec,
                                          &conversion,
                                          &format_spec_needs_expanding)) == 2) {
-        if (!output_data(output, literal.ptr, literal.end - literal.ptr))
+        if (!output_data(output, literal.str, literal.start, literal.end))
             return 0;
         if (field_present)
             if (!output_markup(&field_name, &format_spec,
@@ -990,9 +1019,8 @@
 {
     OutputString output;
     PyObject *result = NULL;
-    Py_ssize_t count;
 
-    output.obj = NULL; /* needed so cleanup code always works */
+    output.data = NULL; /* needed so cleanup code always works */
 
     /* check the recursion level */
     if (recursion_depth <= 0) {
@@ -1004,7 +1032,7 @@
     /* initial size is the length of the format string, plus the size
        increment.  seems like a reasonable default */
     if (!output_initialize(&output,
-                           input->end - input->ptr +
+                           input->end - input->start +
                            INITIAL_SIZE_INCREMENT))
         goto done;
 
@@ -1013,17 +1041,14 @@
         goto done;
     }
 
-    count = output.ptr - STRINGLIB_STR(output.obj);
-    if (STRINGLIB_RESIZE(&output.obj, count) < 0) {
+    result = PyUnicode_New(output.pos, output.maxchar);
+    if (!result)
         goto done;
-    }
-
-    /* transfer ownership to result */
-    result = output.obj;
-    output.obj = NULL;
+    memcpy(PyUnicode_DATA(result), output.data, output.pos << (output.kind-1));
 
 done:
-    Py_XDECREF(output.obj);
+    if (output.data)
+        PyMem_Free(output.data);
     return result;
 }
 
@@ -1045,8 +1070,11 @@
 
     AutoNumber auto_number;
 
+    if (PyUnicode_READY(self) == -1)
+        return NULL;
+
     AutoNumber_Init(&auto_number);
-    SubString_init(&input, STRINGLIB_STR(self), STRINGLIB_LEN(self));
+    SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
     return build_string(&input, args, kwargs, recursion_depth, &auto_number);
 }
 
@@ -1069,7 +1097,7 @@
 typedef struct {
     PyObject_HEAD
 
-    STRINGLIB_OBJECT *str;
+    PyUnicodeObject *str;
 
     MarkupIterator it_markup;
 } formatteriterobject;
@@ -1095,7 +1123,7 @@
     SubString literal;
     SubString field_name;
     SubString format_spec;
-    STRINGLIB_CHAR conversion;
+    Py_UCS4 conversion;
     int format_spec_needs_expanding;
     int field_present;
     int result = MarkupIterator_next(&it->it_markup, &literal, &field_present,
@@ -1139,7 +1167,8 @@
             Py_INCREF(conversion_str);
         }
         else
-            conversion_str = STRINGLIB_NEW(&conversion, 1);
+            conversion_str = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
+                                                       &conversion, 1);
         if (conversion_str == NULL)
             goto done;
 
@@ -1196,7 +1225,7 @@
    describing the parsed elements.  It's a wrapper around
    stringlib/string_format.h's MarkupIterator */
 static PyObject *
-formatter_parser(PyObject *ignored, STRINGLIB_OBJECT *self)
+formatter_parser(PyObject *ignored, PyUnicodeObject *self)
 {
     formatteriterobject *it;
 
@@ -1205,6 +1234,9 @@
         return NULL;
     }
 
+    if (PyUnicode_READY(self) == -1)
+        return NULL;
+
     it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
     if (it == NULL)
         return NULL;
@@ -1214,10 +1246,7 @@
     it->str = self;
 
     /* initialize the contained MarkupIterator */
-    MarkupIterator_init(&it->it_markup,
-                        STRINGLIB_STR(self),
-                        STRINGLIB_LEN(self));
-
+    MarkupIterator_init(&it->it_markup, (PyObject*)self, 0, PyUnicode_GET_LENGTH(self));
     return (PyObject *)it;
 }
 
@@ -1234,7 +1263,7 @@
 typedef struct {
     PyObject_HEAD
 
-    STRINGLIB_OBJECT *str;
+    PyUnicodeObject *str;
 
     FieldNameIterator it_field;
 } fieldnameiterobject;
@@ -1336,7 +1365,7 @@
    field_name_split.  The iterator it returns is a
    FieldNameIterator */
 static PyObject *
-formatter_field_name_split(PyObject *ignored, STRINGLIB_OBJECT *self)
+formatter_field_name_split(PyObject *ignored, PyUnicodeObject *self)
 {
     SubString first;
     Py_ssize_t first_idx;
@@ -1350,6 +1379,9 @@
         return NULL;
     }
 
+    if (PyUnicode_READY(self) == -1)
+        return NULL;
+
     it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
     if (it == NULL)
         return NULL;
@@ -1361,8 +1393,7 @@
 
     /* Pass in auto_number = NULL. We'll return an empty string for
        first_obj in that case. */
-    if (!field_name_split(STRINGLIB_STR(self),
-                          STRINGLIB_LEN(self),
+    if (!field_name_split((PyObject*)self, 0, PyUnicode_GET_LENGTH(self),
                           &first, &first_idx, &it->it_field, NULL))
         goto done;
 
diff --git a/Objects/stringlib/unicodedefs.h b/Objects/stringlib/unicodedefs.h
index 09dae6d..0c40b80 100644
--- a/Objects/stringlib/unicodedefs.h
+++ b/Objects/stringlib/unicodedefs.h
@@ -6,6 +6,8 @@
    compiled as unicode. */
 #define STRINGLIB_IS_UNICODE     1
 
+#define FASTSEARCH               fastsearch
+#define STRINGLIB(F)             stringlib_##F
 #define STRINGLIB_OBJECT         PyUnicodeObject
 #define STRINGLIB_CHAR           Py_UNICODE
 #define STRINGLIB_TYPE_NAME      "unicode"