bpo-20180: complete AC conversion of Objects/stringlib/transmogrify.h (GH-8039)

* converted bytes methods: expandtabs, ljust, rjust, center, zfill
* updated char_convertor to properly set the C default value
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 753ee8e..9d32965 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2138,7 +2138,7 @@
     BYTEARRAY_APPEND_METHODDEF
     {"capitalize", stringlib_capitalize, METH_NOARGS,
      _Py_capitalize__doc__},
-    {"center", (PyCFunction)stringlib_center, METH_VARARGS, _Py_center__doc__},
+    STRINGLIB_CENTER_METHODDEF
     BYTEARRAY_CLEAR_METHODDEF
     BYTEARRAY_COPY_METHODDEF
     {"count", (PyCFunction)bytearray_count, METH_VARARGS,
@@ -2146,8 +2146,7 @@
     BYTEARRAY_DECODE_METHODDEF
     {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS,
      _Py_endswith__doc__},
-    {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
-     _Py_expandtabs__doc__},
+    STRINGLIB_EXPANDTABS_METHODDEF
     BYTEARRAY_EXTEND_METHODDEF
     {"find", (PyCFunction)bytearray_find, METH_VARARGS,
      _Py_find__doc__},
@@ -2172,7 +2171,7 @@
     {"isupper", stringlib_isupper, METH_NOARGS,
      _Py_isupper__doc__},
     BYTEARRAY_JOIN_METHODDEF
-    {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
+    STRINGLIB_LJUST_METHODDEF
     {"lower", stringlib_lower, METH_NOARGS, _Py_lower__doc__},
     BYTEARRAY_LSTRIP_METHODDEF
     BYTEARRAY_MAKETRANS_METHODDEF
@@ -2183,7 +2182,7 @@
     BYTEARRAY_REVERSE_METHODDEF
     {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
     {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
-    {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
+    STRINGLIB_RJUST_METHODDEF
     BYTEARRAY_RPARTITION_METHODDEF
     BYTEARRAY_RSPLIT_METHODDEF
     BYTEARRAY_RSTRIP_METHODDEF
@@ -2197,7 +2196,7 @@
     {"title", stringlib_title, METH_NOARGS, _Py_title__doc__},
     BYTEARRAY_TRANSLATE_METHODDEF
     {"upper", stringlib_upper, METH_NOARGS, _Py_upper__doc__},
-    {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
+    STRINGLIB_ZFILL_METHODDEF
     {NULL}
 };
 
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index 07842f7..05679e3 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -845,33 +845,3 @@
 {
     return _Py_bytes_tailmatch(str, len, "endswith", args, +1);
 }
-
-PyDoc_STRVAR_shared(_Py_expandtabs__doc__,
-"B.expandtabs(tabsize=8) -> copy of B\n\
-\n\
-Return a copy of B where all tab characters are expanded using spaces.\n\
-If tabsize is not given, a tab size of 8 characters is assumed.");
-
-PyDoc_STRVAR_shared(_Py_ljust__doc__,
-"B.ljust(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B left justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space).");
-
-PyDoc_STRVAR_shared(_Py_rjust__doc__,
-"B.rjust(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B right justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space)");
-
-PyDoc_STRVAR_shared(_Py_center__doc__,
-"B.center(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B centered in a string of length width.  Padding is\n"
-"done using the specified fill character (default is a space).");
-
-PyDoc_STRVAR_shared(_Py_zfill__doc__,
-"B.zfill(width) -> copy of B\n"
-"\n"
-"Pad a numeric string B with zeros on the left, to fill a field\n"
-"of the specified width.  B is never truncated.");
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index f5bd5fb..943c329 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2441,15 +2441,13 @@
     {"__getnewargs__",          (PyCFunction)bytes_getnewargs,  METH_NOARGS},
     {"capitalize", stringlib_capitalize, METH_NOARGS,
      _Py_capitalize__doc__},
-    {"center", (PyCFunction)stringlib_center, METH_VARARGS,
-     _Py_center__doc__},
+    STRINGLIB_CENTER_METHODDEF
     {"count", (PyCFunction)bytes_count, METH_VARARGS,
      _Py_count__doc__},
     BYTES_DECODE_METHODDEF
     {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
      _Py_endswith__doc__},
-    {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
-     _Py_expandtabs__doc__},
+    STRINGLIB_EXPANDTABS_METHODDEF
     {"find", (PyCFunction)bytes_find, METH_VARARGS,
      _Py_find__doc__},
     BYTES_FROMHEX_METHODDEF
@@ -2472,7 +2470,7 @@
     {"isupper", stringlib_isupper, METH_NOARGS,
      _Py_isupper__doc__},
     BYTES_JOIN_METHODDEF
-    {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
+    STRINGLIB_LJUST_METHODDEF
     {"lower", stringlib_lower, METH_NOARGS, _Py_lower__doc__},
     BYTES_LSTRIP_METHODDEF
     BYTES_MAKETRANS_METHODDEF
@@ -2480,7 +2478,7 @@
     BYTES_REPLACE_METHODDEF
     {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
     {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
-    {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
+    STRINGLIB_RJUST_METHODDEF
     BYTES_RPARTITION_METHODDEF
     BYTES_RSPLIT_METHODDEF
     BYTES_RSTRIP_METHODDEF
@@ -2494,7 +2492,7 @@
     {"title", stringlib_title, METH_NOARGS, _Py_title__doc__},
     BYTES_TRANSLATE_METHODDEF
     {"upper", stringlib_upper, METH_NOARGS, _Py_upper__doc__},
-    {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
+    STRINGLIB_ZFILL_METHODDEF
     {NULL,     NULL}                         /* sentinel */
 };
 
diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h
new file mode 100644
index 0000000..6d26622
--- /dev/null
+++ b/Objects/stringlib/clinic/transmogrify.h.h
@@ -0,0 +1,158 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(stringlib_expandtabs__doc__,
+"expandtabs($self, /, tabsize=8)\n"
+"--\n"
+"\n"
+"Return a copy where all tab characters are expanded using spaces.\n"
+"\n"
+"If tabsize is not given, a tab size of 8 characters is assumed.");
+
+#define STRINGLIB_EXPANDTABS_METHODDEF    \
+    {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_FASTCALL|METH_KEYWORDS, stringlib_expandtabs__doc__},
+
+static PyObject *
+stringlib_expandtabs_impl(PyObject *self, int tabsize);
+
+static PyObject *
+stringlib_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"tabsize", NULL};
+    static _PyArg_Parser _parser = {"|i:expandtabs", _keywords, 0};
+    int tabsize = 8;
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+        &tabsize)) {
+        goto exit;
+    }
+    return_value = stringlib_expandtabs_impl(self, tabsize);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(stringlib_ljust__doc__,
+"ljust($self, width, fillchar=b\' \', /)\n"
+"--\n"
+"\n"
+"Return a left-justified string of length width.\n"
+"\n"
+"Padding is done using the specified fill character.");
+
+#define STRINGLIB_LJUST_METHODDEF    \
+    {"ljust", (PyCFunction)stringlib_ljust, METH_FASTCALL, stringlib_ljust__doc__},
+
+static PyObject *
+stringlib_ljust_impl(PyObject *self, Py_ssize_t width, char fillchar);
+
+static PyObject *
+stringlib_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t width;
+    char fillchar = ' ';
+
+    if (!_PyArg_ParseStack(args, nargs, "n|c:ljust",
+        &width, &fillchar)) {
+        goto exit;
+    }
+    return_value = stringlib_ljust_impl(self, width, fillchar);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(stringlib_rjust__doc__,
+"rjust($self, width, fillchar=b\' \', /)\n"
+"--\n"
+"\n"
+"Return a right-justified string of length width.\n"
+"\n"
+"Padding is done using the specified fill character.");
+
+#define STRINGLIB_RJUST_METHODDEF    \
+    {"rjust", (PyCFunction)stringlib_rjust, METH_FASTCALL, stringlib_rjust__doc__},
+
+static PyObject *
+stringlib_rjust_impl(PyObject *self, Py_ssize_t width, char fillchar);
+
+static PyObject *
+stringlib_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t width;
+    char fillchar = ' ';
+
+    if (!_PyArg_ParseStack(args, nargs, "n|c:rjust",
+        &width, &fillchar)) {
+        goto exit;
+    }
+    return_value = stringlib_rjust_impl(self, width, fillchar);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(stringlib_center__doc__,
+"center($self, width, fillchar=b\' \', /)\n"
+"--\n"
+"\n"
+"Return a centered string of length width.\n"
+"\n"
+"Padding is done using the specified fill character.");
+
+#define STRINGLIB_CENTER_METHODDEF    \
+    {"center", (PyCFunction)stringlib_center, METH_FASTCALL, stringlib_center__doc__},
+
+static PyObject *
+stringlib_center_impl(PyObject *self, Py_ssize_t width, char fillchar);
+
+static PyObject *
+stringlib_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t width;
+    char fillchar = ' ';
+
+    if (!_PyArg_ParseStack(args, nargs, "n|c:center",
+        &width, &fillchar)) {
+        goto exit;
+    }
+    return_value = stringlib_center_impl(self, width, fillchar);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(stringlib_zfill__doc__,
+"zfill($self, width, /)\n"
+"--\n"
+"\n"
+"Pad a numeric string with zeros on the left, to fill a field of the given width.\n"
+"\n"
+"The original string is never truncated.");
+
+#define STRINGLIB_ZFILL_METHODDEF    \
+    {"zfill", (PyCFunction)stringlib_zfill, METH_O, stringlib_zfill__doc__},
+
+static PyObject *
+stringlib_zfill_impl(PyObject *self, Py_ssize_t width);
+
+static PyObject *
+stringlib_zfill(PyObject *self, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t width;
+
+    if (!PyArg_Parse(arg, "n:zfill", &width)) {
+        goto exit;
+    }
+    return_value = stringlib_zfill_impl(self, width);
+
+exit:
+    return return_value;
+}
+/*[clinic end generated code: output=336620159a1fc70d input=a9049054013a1b77]*/
diff --git a/Objects/stringlib/transmogrify.h b/Objects/stringlib/transmogrify.h
index 326ce14..9506019 100644
--- a/Objects/stringlib/transmogrify.h
+++ b/Objects/stringlib/transmogrify.h
@@ -5,6 +5,13 @@
 /* the more complicated methods.  parts of these should be pulled out into the
    shared code in bytes_methods.c to cut down on duplicate code bloat.  */
 
+/*[clinic input]
+class B "PyObject *" "&PyType_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2935558188d97c76]*/
+
+#include "clinic/transmogrify.h.h"
+
 static inline PyObject *
 return_self(PyObject *self)
 {
@@ -17,19 +24,24 @@
     return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
 }
 
-static PyObject*
-stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
+/*[clinic input]
+B.expandtabs as stringlib_expandtabs
+
+    tabsize: int = 8
+
+Return a copy where all tab characters are expanded using spaces.
+
+If tabsize is not given, a tab size of 8 characters is assumed.
+[clinic start generated code]*/
+
+static PyObject *
+stringlib_expandtabs_impl(PyObject *self, int tabsize)
+/*[clinic end generated code: output=069cb7fae72e4c2b input=3c6d3b12aa3ccbea]*/
 {
     const char *e, *p;
     char *q;
     Py_ssize_t i, j;
     PyObject *u;
-    static char *kwlist[] = {"tabsize", 0};
-    int tabsize = 8;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:expandtabs",
-                                     kwlist, &tabsize))
-        return NULL;
 
     /* First pass: determine size of output string */
     i = j = 0;
@@ -119,15 +131,22 @@
     return u;
 }
 
+/*[clinic input]
+B.ljust as stringlib_ljust
+
+    width: Py_ssize_t
+    fillchar: char = b' '
+    /
+
+Return a left-justified string of length width.
+
+Padding is done using the specified fill character.
+[clinic start generated code]*/
+
 static PyObject *
-stringlib_ljust(PyObject *self, PyObject *args)
+stringlib_ljust_impl(PyObject *self, Py_ssize_t width, char fillchar)
+/*[clinic end generated code: output=c79ca173c5ff8337 input=eff2d014bc7d80df]*/
 {
-    Py_ssize_t width;
-    char fillchar = ' ';
-
-    if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
-        return NULL;
-
     if (STRINGLIB_LEN(self) >= width) {
         return return_self(self);
     }
@@ -136,15 +155,22 @@
 }
 
 
+/*[clinic input]
+B.rjust as stringlib_rjust
+
+    width: Py_ssize_t
+    fillchar: char = b' '
+    /
+
+Return a right-justified string of length width.
+
+Padding is done using the specified fill character.
+[clinic start generated code]*/
+
 static PyObject *
-stringlib_rjust(PyObject *self, PyObject *args)
+stringlib_rjust_impl(PyObject *self, Py_ssize_t width, char fillchar)
+/*[clinic end generated code: output=7df5d728a5439570 input=218b0bd31308955d]*/
 {
-    Py_ssize_t width;
-    char fillchar = ' ';
-
-    if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
-        return NULL;
-
     if (STRINGLIB_LEN(self) >= width) {
         return return_self(self);
     }
@@ -153,15 +179,23 @@
 }
 
 
+/*[clinic input]
+B.center as stringlib_center
+
+    width: Py_ssize_t
+    fillchar: char = b' '
+    /
+
+Return a centered string of length width.
+
+Padding is done using the specified fill character.
+[clinic start generated code]*/
+
 static PyObject *
-stringlib_center(PyObject *self, PyObject *args)
+stringlib_center_impl(PyObject *self, Py_ssize_t width, char fillchar)
+/*[clinic end generated code: output=d8da2e055288b4c2 input=3776fd278765d89b]*/
 {
     Py_ssize_t marg, left;
-    Py_ssize_t width;
-    char fillchar = ' ';
-
-    if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
-        return NULL;
 
     if (STRINGLIB_LEN(self) >= width) {
         return return_self(self);
@@ -173,16 +207,24 @@
     return pad(self, left, marg - left, fillchar);
 }
 
+/*[clinic input]
+B.zfill as stringlib_zfill
+
+    width: Py_ssize_t
+    /
+
+Pad a numeric string with zeros on the left, to fill a field of the given width.
+
+The original string is never truncated.
+[clinic start generated code]*/
+
 static PyObject *
-stringlib_zfill(PyObject *self, PyObject *args)
+stringlib_zfill_impl(PyObject *self, Py_ssize_t width)
+/*[clinic end generated code: output=0b3c684a7f1b2319 input=2da6d7b8e9bcb19a]*/
 {
     Py_ssize_t fill;
     PyObject *s;
     char *p;
-    Py_ssize_t width;
-
-    if (!PyArg_ParseTuple(args, "n:zfill", &width))
-        return NULL;
 
     if (STRINGLIB_LEN(self) >= width) {
         return return_self(self);