LCOV - code coverage report
Current view: | top level - Python - getargs.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 427 | 1357 | 31.5 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 26 | 55 | 47.3 %
|  |  | Branches: | 268 | 1098 | 24.4 %

               Branch data     Line data    Source code
           1                 :            :
           2                 :            : /* New getargs implementation */
           3                 :            :
           4                 :            : #include "Python.h"
           5                 :            : #include "pycore_tuple.h"         // _PyTuple_ITEMS()
           6                 :            : #include "pycore_pylifecycle.h"   // _PyArg_Fini
           7                 :            :
           8                 :            : #include <ctype.h>
           9                 :            : #include <float.h>
          10                 :            :
          11                 :            :
          12                 :            : #ifdef __cplusplus
          13                 :            : extern "C" {
          14                 :            : #endif
          15                 :            : int PyArg_Parse(PyObject *, const char *, ...);
          16                 :            : int PyArg_ParseTuple(PyObject *, const char *, ...);
          17                 :            : int PyArg_VaParse(PyObject *, const char *, va_list);
          18                 :            :
          19                 :            : int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
          20                 :            :                                 const char *, char **, ...);
          21                 :            : int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
          22                 :            :                                 const char *, char **, va_list);
          23                 :            :
          24                 :            : int _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
          25                 :            :                                             struct _PyArg_Parser *, ...);
          26                 :            : int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
          27                 :            :                                             struct _PyArg_Parser *, va_list);
          28                 :            :
          29                 :            : #ifdef HAVE_DECLSPEC_DLL
          30                 :            : /* Export functions */
          31                 :            : PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
          32                 :            : PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs,
          33                 :            :                                         const char *format, ...);
          34                 :            : PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs,
          35                 :            :                                         PyObject *kwnames,
          36                 :            :                                         struct _PyArg_Parser *parser, ...);
          37                 :            : PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
          38                 :            : PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
          39                 :            :                                                   const char *, char **, ...);
          40                 :            : PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);
          41                 :            : PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list);
          42                 :            : PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
          43                 :            :                                               const char *, char **, va_list);
          44                 :            :
          45                 :            : PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *,
          46                 :            :                                             struct _PyArg_Parser *, ...);
          47                 :            : PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *,
          48                 :            :                                             struct _PyArg_Parser *, va_list);
          49                 :            : #endif
          50                 :            :
          51                 :            : #define FLAG_COMPAT 1
          52                 :            : #define FLAG_SIZE_T 2
          53                 :            :
          54                 :            : typedef int (*destr_t)(PyObject *, void *);
          55                 :            :
          56                 :            :
          57                 :            : /* Keep track of "objects" that have been allocated or initialized and
          58                 :            :    which will need to be deallocated or cleaned up somehow if overall
          59                 :            :    parsing fails.
          60                 :            : */
          61                 :            : typedef struct {
          62                 :            :   void *item;
          63                 :            :   destr_t destructor;
          64                 :            : } freelistentry_t;
          65                 :            :
          66                 :            : typedef struct {
          67                 :            :   freelistentry_t *entries;
          68                 :            :   int first_available;
          69                 :            :   int entries_malloced;
          70                 :            : } freelist_t;
          71                 :            :
          72                 :            : #define STATIC_FREELIST_ENTRIES 8
          73                 :            :
          74                 :            : /* Forward */
          75                 :            : static int vgetargs1_impl(PyObject *args, PyObject *const *stack, Py_ssize_t nargs,
          76                 :            :                           const char *format, va_list *p_va, int flags);
          77                 :            : static int vgetargs1(PyObject *, const char *, va_list *, int);
          78                 :            : static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
          79                 :            : static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
          80                 :            :                                char *, size_t, freelist_t *);
          81                 :            : static const char *converttuple(PyObject *, const char **, va_list *, int,
          82                 :            :                                 int *, char *, size_t, int, freelist_t *);
          83                 :            : static const char *convertsimple(PyObject *, const char **, va_list *, int,
          84                 :            :                                  char *, size_t, freelist_t *);
          85                 :            : static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);
          86                 :            : static int getbuffer(PyObject *, Py_buffer *, const char**);
          87                 :            :
          88                 :            : static int vgetargskeywords(PyObject *, PyObject *,
          89                 :            :                             const char *, char **, va_list *, int);
          90                 :            : static int vgetargskeywordsfast(PyObject *, PyObject *,
          91                 :            :                             struct _PyArg_Parser *, va_list *, int);
          92                 :            : static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
          93                 :            :                           PyObject *keywords, PyObject *kwnames,
          94                 :            :                           struct _PyArg_Parser *parser,
          95                 :            :                           va_list *p_va, int flags);
          96                 :            : static const char *skipitem(const char **, va_list *, int);
          97                 :            :
          98                 :            : int
          99                 :          0 : PyArg_Parse(PyObject *args, const char *format, ...)
         100                 :            : {
         101                 :            :     int retval;
         102                 :            :     va_list va;
         103                 :            :
         104                 :          0 :     va_start(va, format);
         105                 :          0 :     retval = vgetargs1(args, format, &va, FLAG_COMPAT);
         106                 :          0 :     va_end(va);
         107                 :          0 :     return retval;
         108                 :            : }
         109                 :            :
         110                 :            : PyAPI_FUNC(int)
         111                 :          0 : _PyArg_Parse_SizeT(PyObject *args, const char *format, ...)
         112                 :            : {
         113                 :            :     int retval;
         114                 :            :     va_list va;
         115                 :            :
         116                 :          0 :     va_start(va, format);
         117                 :          0 :     retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T);
         118                 :          0 :     va_end(va);
         119                 :          0 :     return retval;
         120                 :            : }
         121                 :            :
         122                 :            :
         123                 :            : int
         124                 :     106645 : PyArg_ParseTuple(PyObject *args, const char *format, ...)
         125                 :            : {
         126                 :            :     int retval;
         127                 :            :     va_list va;
         128                 :            :
         129                 :     106645 :     va_start(va, format);
         130                 :     106645 :     retval = vgetargs1(args, format, &va, 0);
         131                 :     106645 :     va_end(va);
         132                 :     106645 :     return retval;
         133                 :            : }
         134                 :            :
         135                 :            : PyAPI_FUNC(int)
         136                 :      23529 : _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)
         137                 :            : {
         138                 :            :     int retval;
         139                 :            :     va_list va;
         140                 :            :
         141                 :      23529 :     va_start(va, format);
         142                 :      23529 :     retval = vgetargs1(args, format, &va, FLAG_SIZE_T);
         143                 :      23529 :     va_end(va);
         144                 :      23529 :     return retval;
         145                 :            : }
         146                 :            :
         147                 :            :
         148                 :            : int
         149                 :          0 : _PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, ...)
         150                 :            : {
         151                 :            :     int retval;
         152                 :            :     va_list va;
         153                 :            :
         154                 :          0 :     va_start(va, format);
         155                 :          0 :     retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);
         156                 :          0 :     va_end(va);
         157                 :          0 :     return retval;
         158                 :            : }
         159                 :            :
         160                 :            : PyAPI_FUNC(int)
         161                 :          1 : _PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs, const char *format, ...)
         162                 :            : {
         163                 :            :     int retval;
         164                 :            :     va_list va;
         165                 :            :
         166                 :          1 :     va_start(va, format);
         167                 :          1 :     retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T);
         168                 :          1 :     va_end(va);
         169                 :          1 :     return retval;
         170                 :            : }
         171                 :            :
         172                 :            :
         173                 :            : int
         174                 :          0 : PyArg_VaParse(PyObject *args, const char *format, va_list va)
         175                 :            : {
         176                 :            :     va_list lva;
         177                 :            :     int retval;
         178                 :            :
         179                 :          0 :     va_copy(lva, va);
         180                 :            :
         181                 :          0 :     retval = vgetargs1(args, format, &lva, 0);
         182                 :          0 :     va_end(lva);
         183                 :          0 :     return retval;
         184                 :            : }
         185                 :            :
         186                 :            : PyAPI_FUNC(int)
         187                 :          0 : _PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va)
         188                 :            : {
         189                 :            :     va_list lva;
         190                 :            :     int retval;
         191                 :            :
         192                 :          0 :     va_copy(lva, va);
         193                 :            :
         194                 :          0 :     retval = vgetargs1(args, format, &lva, FLAG_SIZE_T);
         195                 :          0 :     va_end(lva);
         196                 :          0 :     return retval;
         197                 :            : }
         198                 :            :
         199                 :            :
         200                 :            : /* Handle cleanup of allocated memory in case of exception */
         201                 :            :
         202                 :            : static int
         203                 :          0 : cleanup_ptr(PyObject *self, void *ptr)
         204                 :            : {
         205                 :          0 :     void **pptr = (void **)ptr;
         206                 :          0 :     PyMem_Free(*pptr);
         207                 :          0 :     *pptr = NULL;
         208                 :          0 :     return 0;
         209                 :            : }
         210                 :            :
         211                 :            : static int
         212                 :          0 : cleanup_buffer(PyObject *self, void *ptr)
         213                 :            : {
         214                 :          0 :     Py_buffer *buf = (Py_buffer *)ptr;
         215         [ #  # ]:          0 :     if (buf) {
         216                 :          0 :         PyBuffer_Release(buf);
         217                 :            :     }
         218                 :          0 :     return 0;
         219                 :            : }
         220                 :            :
         221                 :            : static int
         222                 :          0 : addcleanup(void *ptr, freelist_t *freelist, destr_t destructor)
         223                 :            : {
         224                 :            :     int index;
         225                 :            :
         226                 :          0 :     index = freelist->first_available;
         227                 :          0 :     freelist->first_available += 1;
         228                 :            :
         229                 :          0 :     freelist->entries[index].item = ptr;
         230                 :          0 :     freelist->entries[index].destructor = destructor;
         231                 :            :
         232                 :          0 :     return 0;
         233                 :            : }
         234                 :            :
         235                 :            : static int
         236                 :     260408 : cleanreturn(int retval, freelist_t *freelist)
         237                 :            : {
         238                 :            :     int index;
         239                 :            :
         240         [ -  + ]:     260408 :     if (retval == 0) {
         241                 :            :       /* A failure occurred, therefore execute all of the cleanup
         242                 :            :          functions.
         243                 :            :       */
         244         [ #  # ]:          0 :       for (index = 0; index < freelist->first_available; ++index) {
         245                 :          0 :           freelist->entries[index].destructor(NULL,
         246                 :          0 :                                               freelist->entries[index].item);
         247                 :            :       }
         248                 :            :     }
         249         [ +  + ]:     260408 :     if (freelist->entries_malloced)
         250                 :         30 :         PyMem_Free(freelist->entries);
         251                 :     260408 :     return retval;
         252                 :            : }
         253                 :            :
         254                 :            :
         255                 :            : static int
         256                 :     130175 : vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format,
         257                 :            :                va_list *p_va, int flags)
         258                 :            : {
         259                 :            :     char msgbuf[256];
         260                 :            :     int levels[32];
         261                 :     130175 :     const char *fname = NULL;
         262                 :     130175 :     const char *message = NULL;
         263                 :     130175 :     int min = -1;
         264                 :     130175 :     int max = 0;
         265                 :     130175 :     int level = 0;
         266                 :     130175 :     int endfmt = 0;
         267                 :     130175 :     const char *formatsave = format;
         268                 :            :     Py_ssize_t i;
         269                 :            :     const char *msg;
         270                 :     130175 :     int compat = flags & FLAG_COMPAT;
         271                 :            :     freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
         272                 :            :     freelist_t freelist;
         273                 :            :
         274                 :            :     assert(nargs == 0 || stack != NULL);
         275                 :            :
         276                 :     130175 :     freelist.entries = static_entries;
         277                 :     130175 :     freelist.first_available = 0;
         278                 :     130175 :     freelist.entries_malloced = 0;
         279                 :            :
         280                 :     130175 :     flags = flags & ~FLAG_COMPAT;
         281                 :            :
         282         [ +  + ]:     486266 :     while (endfmt == 0) {
         283                 :     356091 :         int c = *format++;
         284   [ -  -  +  +  :     356091 :         switch (c) {
                    +  +  + ]
         285                 :          0 :         case '(':
         286         [ #  # ]:          0 :             if (level == 0)
         287                 :          0 :                 max++;
         288                 :          0 :             level++;
         289         [ #  # ]:          0 :             if (level >= 30)
         290                 :          0 :                 Py_FatalError("too many tuple nesting levels "
         291                 :            :                               "in argument format string");
         292                 :          0 :             break;
         293                 :          0 :         case ')':
         294         [ #  # ]:          0 :             if (level == 0)
         295                 :          0 :                 Py_FatalError("excess ')' in getargs format");
         296                 :            :             else
         297                 :          0 :                 level--;
         298                 :          0 :             break;
         299                 :        298 :         case '\0':
         300                 :        298 :             endfmt = 1;
         301                 :        298 :             break;
         302                 :     129861 :         case ':':
         303                 :     129861 :             fname = format;
         304                 :     129861 :             endfmt = 1;
         305                 :     129861 :             break;
         306                 :         16 :         case ';':
         307                 :         16 :             message = format;
         308                 :         16 :             endfmt = 1;
         309                 :         16 :             break;
         310                 :      23513 :         case '|':
         311         [ +  - ]:      23513 :             if (level == 0)
         312                 :      23513 :                 min = max;
         313                 :      23513 :             break;
         314                 :     202403 :         default:
         315         [ +  - ]:     202403 :             if (level == 0) {
         316         [ +  + ]:     202403 :                 if (Py_ISALPHA(c))
         317         [ +  - ]:     189815 :                     if (c != 'e') /* skip encoded */
         318                 :     189815 :                         max++;
         319                 :            :             }
         320                 :     202403 :             break;
         321                 :            :         }
         322                 :            :     }
         323                 :            :
         324         [ -  + ]:     130175 :     if (level != 0)
         325                 :          0 :         Py_FatalError(/* '(' */ "missing ')' in getargs format");
         326                 :            :
         327         [ +  + ]:     130175 :     if (min < 0)
         328                 :     106662 :         min = max;
         329                 :            :
         330                 :     130175 :     format = formatsave;
         331                 :            :
         332         [ -  + ]:     130175 :     if (max > STATIC_FREELIST_ENTRIES) {
         333         [ #  # ]:          0 :         freelist.entries = PyMem_NEW(freelistentry_t, max);
         334         [ #  # ]:          0 :         if (freelist.entries == NULL) {
         335                 :          0 :             PyErr_NoMemory();
         336                 :          0 :             return 0;
         337                 :            :         }
         338                 :          0 :         freelist.entries_malloced = 1;
         339                 :            :     }
         340                 :            :
         341         [ -  + ]:     130175 :     if (compat) {
         342         [ #  # ]:          0 :         if (max == 0) {
         343         [ #  # ]:          0 :             if (compat_args == NULL)
         344                 :          0 :                 return 1;
         345   [ #  #  #  # ]:          0 :             PyErr_Format(PyExc_TypeError,
         346                 :            :                          "%.200s%s takes no arguments",
         347                 :            :                          fname==NULL ? "function" : fname,
         348                 :            :                          fname==NULL ? "" : "()");
         349                 :          0 :             return cleanreturn(0, &freelist);
         350                 :            :         }
         351   [ #  #  #  # ]:          0 :         else if (min == 1 && max == 1) {
         352         [ #  # ]:          0 :             if (compat_args == NULL) {
         353   [ #  #  #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
         354                 :            :                              "%.200s%s takes at least one argument",
         355                 :            :                              fname==NULL ? "function" : fname,
         356                 :            :                              fname==NULL ? "" : "()");
         357                 :          0 :                 return cleanreturn(0, &freelist);
         358                 :            :             }
         359                 :          0 :             msg = convertitem(compat_args, &format, p_va, flags, levels,
         360                 :            :                               msgbuf, sizeof(msgbuf), &freelist);
         361         [ #  # ]:          0 :             if (msg == NULL)
         362                 :          0 :                 return cleanreturn(1, &freelist);
         363                 :          0 :             seterror(levels[0], msg, levels+1, fname, message);
         364                 :          0 :             return cleanreturn(0, &freelist);
         365                 :            :         }
         366                 :            :         else {
         367                 :          0 :             PyErr_SetString(PyExc_SystemError,
         368                 :            :                 "old style getargs format uses new features");
         369                 :          0 :             return cleanreturn(0, &freelist);
         370                 :            :         }
         371                 :            :     }
         372                 :            :
         373   [ +  -  -  + ]:     130175 :     if (nargs < min || max < nargs) {
         374         [ #  # ]:          0 :         if (message == NULL)
         375   [ #  #  #  #  :          0 :             PyErr_Format(PyExc_TypeError,
                 #  #  #  # ]
         376                 :            :                          "%.150s%s takes %s %d argument%s (%zd given)",
         377                 :            :                          fname==NULL ? "function" : fname,
         378                 :            :                          fname==NULL ? "" : "()",
         379                 :            :                          min==max ? "exactly"
         380         [ #  # ]:          0 :                          : nargs < min ? "at least" : "at most",
         381         [ #  # ]:          0 :                          nargs < min ? min : max,
         382         [ #  # ]:          0 :                          (nargs < min ? min : max) == 1 ? "" : "s",
         383                 :            :                          nargs);
         384                 :            :         else
         385                 :          0 :             PyErr_SetString(PyExc_TypeError, message);
         386                 :          0 :         return cleanreturn(0, &freelist);
         387                 :            :     }
         388                 :            :
         389         [ +  + ]:     273914 :     for (i = 0; i < nargs; i++) {
         390         [ +  + ]:     143739 :         if (*format == '|')
         391                 :        835 :             format++;
         392                 :     143739 :         msg = convertitem(stack[i], &format, p_va,
         393                 :            :                           flags, levels, msgbuf,
         394                 :            :                           sizeof(msgbuf), &freelist);
         395         [ -  + ]:     143739 :         if (msg) {
         396                 :          0 :             seterror(i+1, msg, levels, fname, message);
         397                 :          0 :             return cleanreturn(0, &freelist);
         398                 :            :         }
         399                 :            :     }
         400                 :            :
         401   [ +  +  +  + ]:     130175 :     if (*format != '\0' && !Py_ISALPHA(*format) &&
         402         [ +  - ]:     129156 :         *format != '(' &&
         403   [ +  +  +  +  :     129156 :         *format != '|' && *format != ':' && *format != ';') {
                       -  + ]
         404                 :          0 :         PyErr_Format(PyExc_SystemError,
         405                 :            :                      "bad format string: %.200s", formatsave);
         406                 :          0 :         return cleanreturn(0, &freelist);
         407                 :            :     }
         408                 :            :
         409                 :     130175 :     return cleanreturn(1, &freelist);
         410                 :            : }
         411                 :            :
         412                 :            : static int
         413                 :     130174 : vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
         414                 :            : {
         415                 :            :     PyObject **stack;
         416                 :            :     Py_ssize_t nargs;
         417                 :            :
         418         [ +  - ]:     130174 :     if (!(flags & FLAG_COMPAT)) {
         419                 :            :         assert(args != NULL);
         420                 :            :
         421         [ -  + ]:     130174 :         if (!PyTuple_Check(args)) {
         422                 :          0 :             PyErr_SetString(PyExc_SystemError,
         423                 :            :                 "new style getargs format but argument is not a tuple");
         424                 :          0 :             return 0;
         425                 :            :         }
         426                 :            :
         427                 :     130174 :         stack = _PyTuple_ITEMS(args);
         428                 :     130174 :         nargs = PyTuple_GET_SIZE(args);
         429                 :            :     }
         430                 :            :     else {
         431                 :          0 :         stack = NULL;
         432                 :          0 :         nargs = 0;
         433                 :            :     }
         434                 :            :
         435                 :     130174 :     return vgetargs1_impl(args, stack, nargs, format, p_va, flags);
         436                 :            : }
         437                 :            :
         438                 :            :
         439                 :            : static void
         440                 :          0 : seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname,
         441                 :            :          const char *message)
         442                 :            : {
         443                 :            :     char buf[512];
         444                 :            :     int i;
         445                 :          0 :     char *p = buf;
         446                 :            :
         447         [ #  # ]:          0 :     if (PyErr_Occurred())
         448                 :          0 :         return;
         449         [ #  # ]:          0 :     else if (message == NULL) {
         450         [ #  # ]:          0 :         if (fname != NULL) {
         451                 :          0 :             PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname);
         452                 :          0 :             p += strlen(p);
         453                 :            :         }
         454         [ #  # ]:          0 :         if (iarg != 0) {
         455                 :          0 :             PyOS_snprintf(p, sizeof(buf) - (p - buf),
         456                 :            :                           "argument %zd", iarg);
         457                 :          0 :             i = 0;
         458                 :          0 :             p += strlen(p);
         459   [ #  #  #  #  :          0 :             while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) {
                       #  # ]
         460                 :          0 :                 PyOS_snprintf(p, sizeof(buf) - (p - buf),
         461                 :          0 :                               ", item %d", levels[i]-1);
         462                 :          0 :                 p += strlen(p);
         463                 :          0 :                 i++;
         464                 :            :             }
         465                 :            :         }
         466                 :            :         else {
         467                 :          0 :             PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument");
         468                 :          0 :             p += strlen(p);
         469                 :            :         }
         470                 :          0 :         PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg);
         471                 :          0 :         message = buf;
         472                 :            :     }
         473         [ #  # ]:          0 :     if (msg[0] == '(') {
         474                 :          0 :         PyErr_SetString(PyExc_SystemError, message);
         475                 :            :     }
         476                 :            :     else {
         477                 :          0 :         PyErr_SetString(PyExc_TypeError, message);
         478                 :            :     }
         479                 :            : }
         480                 :            :
         481                 :            :
         482                 :            : /* Convert a tuple argument.
         483                 :            :    On entry, *p_format points to the character _after_ the opening '('.
         484                 :            :    On successful exit, *p_format points to the closing ')'.
         485                 :            :    If successful:
         486                 :            :       *p_format and *p_va are updated,
         487                 :            :       *levels and *msgbuf are untouched,
         488                 :            :       and NULL is returned.
         489                 :            :    If the argument is invalid:
         490                 :            :       *p_format is unchanged,
         491                 :            :       *p_va is undefined,
         492                 :            :       *levels is a 0-terminated list of item numbers,
         493                 :            :       *msgbuf contains an error message, whose format is:
         494                 :            :      "must be <typename1>, not <typename2>", where:
         495                 :            :         <typename1> is the name of the expected type, and
         496                 :            :         <typename2> is the name of the actual type,
         497                 :            :       and msgbuf is returned.
         498                 :            : */
         499                 :            :
         500                 :            : static const char *
         501                 :          0 : converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
         502                 :            :              int *levels, char *msgbuf, size_t bufsize, int toplevel,
         503                 :            :              freelist_t *freelist)
         504                 :            : {
         505                 :          0 :     int level = 0;
         506                 :          0 :     int n = 0;
         507                 :          0 :     const char *format = *p_format;
         508                 :            :     int i;
         509                 :            :     Py_ssize_t len;
         510                 :            :
         511                 :          0 :     for (;;) {
         512                 :          0 :         int c = *format++;
         513         [ #  # ]:          0 :         if (c == '(') {
         514         [ #  # ]:          0 :             if (level == 0)
         515                 :          0 :                 n++;
         516                 :          0 :             level++;
         517                 :            :         }
         518         [ #  # ]:          0 :         else if (c == ')') {
         519         [ #  # ]:          0 :             if (level == 0)
         520                 :          0 :                 break;
         521                 :          0 :             level--;
         522                 :            :         }
         523   [ #  #  #  #  :          0 :         else if (c == ':' || c == ';' || c == '\0')
                       #  # ]
         524                 :            :             break;
         525   [ #  #  #  # ]:          0 :         else if (level == 0 && Py_ISALPHA(c))
         526                 :          0 :             n++;
         527                 :            :     }
         528                 :            :
         529   [ #  #  #  # ]:          0 :     if (!PySequence_Check(arg) || PyBytes_Check(arg)) {
         530                 :          0 :         levels[0] = 0;
         531   [ #  #  #  # ]:          0 :         PyOS_snprintf(msgbuf, bufsize,
         532                 :            :                       toplevel ? "expected %d arguments, not %.50s" :
         533                 :            :                       "must be %d-item sequence, not %.50s",
         534                 :            :                   n,
         535                 :          0 :                   arg == Py_None ? "None" : Py_TYPE(arg)->tp_name);
         536                 :          0 :         return msgbuf;
         537                 :            :     }
         538                 :            :
         539                 :          0 :     len = PySequence_Size(arg);
         540         [ #  # ]:          0 :     if (len != n) {
         541                 :          0 :         levels[0] = 0;
         542         [ #  # ]:          0 :         if (toplevel) {
         543         [ #  # ]:          0 :             PyOS_snprintf(msgbuf, bufsize,
         544                 :            :                           "expected %d argument%s, not %zd",
         545                 :            :                           n,
         546                 :            :                           n == 1 ? "" : "s",
         547                 :            :                           len);
         548                 :            :         }
         549                 :            :         else {
         550                 :          0 :             PyOS_snprintf(msgbuf, bufsize,
         551                 :            :                           "must be sequence of length %d, not %zd",
         552                 :            :                           n, len);
         553                 :            :         }
         554                 :          0 :         return msgbuf;
         555                 :            :     }
         556                 :            :
         557                 :          0 :     format = *p_format;
         558         [ #  # ]:          0 :     for (i = 0; i < n; i++) {
         559                 :            :         const char *msg;
         560                 :            :         PyObject *item;
         561                 :          0 :         item = PySequence_GetItem(arg, i);
         562         [ #  # ]:          0 :         if (item == NULL) {
         563                 :          0 :             PyErr_Clear();
         564                 :          0 :             levels[0] = i+1;
         565                 :          0 :             levels[1] = 0;
         566                 :          0 :             strncpy(msgbuf, "is not retrievable", bufsize);
         567                 :          0 :             return msgbuf;
         568                 :            :         }
         569                 :          0 :         msg = convertitem(item, &format, p_va, flags, levels+1,
         570                 :            :                           msgbuf, bufsize, freelist);
         571                 :            :         /* PySequence_GetItem calls tp->sq_item, which INCREFs */
         572                 :          0 :         Py_XDECREF(item);
         573         [ #  # ]:          0 :         if (msg != NULL) {
         574                 :          0 :             levels[0] = i+1;
         575                 :          0 :             return msg;
         576                 :            :         }
         577                 :            :     }
         578                 :            :
         579                 :          0 :     *p_format = format;
         580                 :          0 :     return NULL;
         581                 :            : }
         582                 :            :
         583                 :            :
         584                 :            : /* Convert a single item. */
         585                 :            :
         586                 :            : static const char *
         587                 :     144805 : convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags,
         588                 :            :             int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist)
         589                 :            : {
         590                 :            :     const char *msg;
         591                 :     144805 :     const char *format = *p_format;
         592                 :            :
         593         [ -  + ]:     144805 :     if (*format == '(' /* ')' */) {
         594                 :          0 :         format++;
         595                 :          0 :         msg = converttuple(arg, &format, p_va, flags, levels, msgbuf,
         596                 :            :                            bufsize, 0, freelist);
         597         [ #  # ]:          0 :         if (msg == NULL)
         598                 :          0 :             format++;
         599                 :            :     }
         600                 :            :     else {
         601                 :     144805 :         msg = convertsimple(arg, &format, p_va, flags,
         602                 :            :                             msgbuf, bufsize, freelist);
         603         [ -  + ]:     144805 :         if (msg != NULL)
         604                 :          0 :             levels[0] = 0;
         605                 :            :     }
         606         [ +  - ]:     144805 :     if (msg == NULL)
         607                 :     144805 :         *p_format = format;
         608                 :     144805 :     return msg;
         609                 :            : }
         610                 :            :
         611                 :            :
         612                 :            :
         613                 :            : /* Format an error message generated by convertsimple().
         614                 :            :    displayname must be UTF-8 encoded.
         615                 :            : */
         616                 :            :
         617                 :            : void
         618                 :          0 : _PyArg_BadArgument(const char *fname, const char *displayname,
         619                 :            :                    const char *expected, PyObject *arg)
         620                 :            : {
         621         [ #  # ]:          0 :     PyErr_Format(PyExc_TypeError,
         622                 :            :                  "%.200s() %.200s must be %.50s, not %.50s",
         623                 :            :                  fname, displayname, expected,
         624                 :          0 :                  arg == Py_None ? "None" : Py_TYPE(arg)->tp_name);
         625                 :          0 : }
         626                 :            :
         627                 :            : static const char *
         628                 :          0 : converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)
         629                 :            : {
         630                 :            :     assert(expected != NULL);
         631                 :            :     assert(arg != NULL);
         632         [ #  # ]:          0 :     if (expected[0] == '(') {
         633                 :          0 :         PyOS_snprintf(msgbuf, bufsize,
         634                 :            :                       "%.100s", expected);
         635                 :            :     }
         636                 :            :     else {
         637         [ #  # ]:          0 :         PyOS_snprintf(msgbuf, bufsize,
         638                 :            :                       "must be %.50s, not %.50s", expected,
         639                 :          0 :                       arg == Py_None ? "None" : Py_TYPE(arg)->tp_name);
         640                 :            :     }
         641                 :          0 :     return msgbuf;
         642                 :            : }
         643                 :            :
         644                 :            : #define CONV_UNICODE "(unicode conversion error)"
         645                 :            :
         646                 :            : /* Convert a non-tuple argument.  Return NULL if conversion went OK,
         647                 :            :    or a string with a message describing the failure.  The message is
         648                 :            :    formatted as "must be <desired type>, not <actual type>".
         649                 :            :    When failing, an exception may or may not have been raised.
         650                 :            :    Don't call if a tuple is expected.
         651                 :            :
         652                 :            :    When you add new format codes, please don't forget poor skipitem() below.
         653                 :            : */
         654                 :            :
         655                 :            : static const char *
         656                 :     144805 : convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
         657                 :            :               char *msgbuf, size_t bufsize, freelist_t *freelist)
         658                 :            : {
         659                 :            : #define RETURN_ERR_OCCURRED return msgbuf
         660                 :            :     /* For # codes */
         661                 :            : #define REQUIRE_PY_SSIZE_T_CLEAN \
         662                 :            :     if (!(flags & FLAG_SIZE_T)) { \
         663                 :            :         PyErr_SetString(PyExc_SystemError, \
         664                 :            :                         "PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); \
         665                 :            :         RETURN_ERR_OCCURRED; \
         666                 :            :     }
         667                 :            :
         668                 :     144805 :     const char *format = *p_format;
         669                 :     144805 :     char c = *format++;
         670                 :            :     const char *sarg;
         671                 :            :
         672   [ -  -  -  -  :     144805 :     switch (c) {
              +  -  +  -  -
              -  +  -  -  -
              -  -  +  -  -
              -  -  -  +  +
                       -  - ]
         673                 :            :
         674                 :          0 :     case 'b': { /* unsigned byte -- very short int */
         675                 :          0 :         char *p = va_arg(*p_va, char *);
         676                 :          0 :         long ival = PyLong_AsLong(arg);
         677   [ #  #  #  # ]:          0 :         if (ival == -1 && PyErr_Occurred())
         678                 :          0 :             RETURN_ERR_OCCURRED;
         679         [ #  # ]:          0 :         else if (ival < 0) {
         680                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         681                 :            :                             "unsigned byte integer is less than minimum");
         682                 :          0 :             RETURN_ERR_OCCURRED;
         683                 :            :         }
         684         [ #  # ]:          0 :         else if (ival > UCHAR_MAX) {
         685                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         686                 :            :                             "unsigned byte integer is greater than maximum");
         687                 :          0 :             RETURN_ERR_OCCURRED;
         688                 :            :         }
         689                 :            :         else
         690                 :          0 :             *p = (unsigned char) ival;
         691                 :          0 :         break;
         692                 :            :     }
         693                 :            :
         694                 :          0 :     case 'B': {/* byte sized bitfield - both signed and unsigned
         695                 :            :                   values allowed */
         696                 :          0 :         char *p = va_arg(*p_va, char *);
         697                 :          0 :         unsigned long ival = PyLong_AsUnsignedLongMask(arg);
         698   [ #  #  #  # ]:          0 :         if (ival == (unsigned long)-1 && PyErr_Occurred())
         699                 :          0 :             RETURN_ERR_OCCURRED;
         700                 :            :         else
         701                 :          0 :             *p = (unsigned char) ival;
         702                 :          0 :         break;
         703                 :            :     }
         704                 :            :
         705                 :          0 :     case 'h': {/* signed short int */
         706                 :          0 :         short *p = va_arg(*p_va, short *);
         707                 :          0 :         long ival = PyLong_AsLong(arg);
         708   [ #  #  #  # ]:          0 :         if (ival == -1 && PyErr_Occurred())
         709                 :          0 :             RETURN_ERR_OCCURRED;
         710         [ #  # ]:          0 :         else if (ival < SHRT_MIN) {
         711                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         712                 :            :                             "signed short integer is less than minimum");
         713                 :          0 :             RETURN_ERR_OCCURRED;
         714                 :            :         }
         715         [ #  # ]:          0 :         else if (ival > SHRT_MAX) {
         716                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         717                 :            :                             "signed short integer is greater than maximum");
         718                 :          0 :             RETURN_ERR_OCCURRED;
         719                 :            :         }
         720                 :            :         else
         721                 :          0 :             *p = (short) ival;
         722                 :          0 :         break;
         723                 :            :     }
         724                 :            :
         725                 :          0 :     case 'H': { /* short int sized bitfield, both signed and
         726                 :            :                    unsigned allowed */
         727                 :          0 :         unsigned short *p = va_arg(*p_va, unsigned short *);
         728                 :          0 :         unsigned long ival = PyLong_AsUnsignedLongMask(arg);
         729   [ #  #  #  # ]:          0 :         if (ival == (unsigned long)-1 && PyErr_Occurred())
         730                 :          0 :             RETURN_ERR_OCCURRED;
         731                 :            :         else
         732                 :          0 :             *p = (unsigned short) ival;
         733                 :          0 :         break;
         734                 :            :     }
         735                 :            :
         736                 :          6 :     case 'i': {/* signed int */
         737                 :          6 :         int *p = va_arg(*p_va, int *);
         738                 :          6 :         long ival = PyLong_AsLong(arg);
         739   [ +  +  -  + ]:          6 :         if (ival == -1 && PyErr_Occurred())
         740                 :          0 :             RETURN_ERR_OCCURRED;
         741         [ -  + ]:          6 :         else if (ival > INT_MAX) {
         742                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         743                 :            :                             "signed integer is greater than maximum");
         744                 :          0 :             RETURN_ERR_OCCURRED;
         745                 :            :         }
         746         [ -  + ]:          6 :         else if (ival < INT_MIN) {
         747                 :          0 :             PyErr_SetString(PyExc_OverflowError,
         748                 :            :                             "signed integer is less than minimum");
         749                 :          0 :             RETURN_ERR_OCCURRED;
         750                 :            :         }
         751                 :            :         else
         752                 :          6 :             *p = ival;
         753                 :          6 :         break;
         754                 :            :     }
         755                 :            :
         756                 :          0 :     case 'I': { /* int sized bitfield, both signed and
         757                 :            :                    unsigned allowed */
         758                 :          0 :         unsigned int *p = va_arg(*p_va, unsigned int *);
         759                 :          0 :         unsigned long ival = PyLong_AsUnsignedLongMask(arg);
         760   [ #  #  #  # ]:          0 :         if (ival == (unsigned long)-1 && PyErr_Occurred())
         761                 :          0 :             RETURN_ERR_OCCURRED;
         762                 :            :         else
         763                 :          0 :             *p = (unsigned int) ival;
         764                 :          0 :         break;
         765                 :            :     }
         766                 :            :
         767                 :        348 :     case 'n': /* Py_ssize_t */
         768                 :            :     {
         769                 :            :         PyObject *iobj;
         770                 :        348 :         Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);
         771                 :        348 :         Py_ssize_t ival = -1;
         772                 :        348 :         iobj = _PyNumber_Index(arg);
         773         [ +  - ]:        348 :         if (iobj != NULL) {
         774                 :        348 :             ival = PyLong_AsSsize_t(iobj);
         775                 :        348 :             Py_DECREF(iobj);
         776                 :            :         }
         777   [ -  +  -  - ]:        348 :         if (ival == -1 && PyErr_Occurred())
         778                 :          0 :             RETURN_ERR_OCCURRED;
         779                 :        348 :         *p = ival;
         780                 :        348 :         break;
         781                 :            :     }
         782                 :          0 :     case 'l': {/* long int */
         783                 :          0 :         long *p = va_arg(*p_va, long *);
         784                 :          0 :         long ival = PyLong_AsLong(arg);
         785   [ #  #  #  # ]:          0 :         if (ival == -1 && PyErr_Occurred())
         786                 :          0 :             RETURN_ERR_OCCURRED;
         787                 :            :         else
         788                 :          0 :             *p = ival;
         789                 :          0 :         break;
         790                 :            :     }
         791                 :            :
         792                 :          0 :     case 'k': { /* long sized bitfield */
         793                 :          0 :         unsigned long *p = va_arg(*p_va, unsigned long *);
         794                 :            :         unsigned long ival;
         795         [ #  # ]:          0 :         if (PyLong_Check(arg))
         796                 :          0 :             ival = PyLong_AsUnsignedLongMask(arg);
         797                 :            :         else
         798                 :          0 :             return converterr("int", arg, msgbuf, bufsize);
         799                 :          0 :         *p = ival;
         800                 :          0 :         break;
         801                 :            :     }
         802                 :            :
         803                 :          0 :     case 'L': {/* long long */
         804                 :          0 :         long long *p = va_arg( *p_va, long long * );
         805                 :          0 :         long long ival = PyLong_AsLongLong(arg);
         806   [ #  #  #  # ]:          0 :         if (ival == (long long)-1 && PyErr_Occurred())
         807                 :          0 :             RETURN_ERR_OCCURRED;
         808                 :            :         else
         809                 :          0 :             *p = ival;
         810                 :          0 :         break;
         811                 :            :     }
         812                 :            :
         813                 :          8 :     case 'K': { /* long long sized bitfield */
         814                 :          8 :         unsigned long long *p = va_arg(*p_va, unsigned long long *);
         815                 :            :         unsigned long long ival;
         816         [ +  - ]:          8 :         if (PyLong_Check(arg))
         817                 :          8 :             ival = PyLong_AsUnsignedLongLongMask(arg);
         818                 :            :         else
         819                 :          0 :             return converterr("int", arg, msgbuf, bufsize);
         820                 :          8 :         *p = ival;
         821                 :          8 :         break;
         822                 :            :     }
         823                 :            :
         824                 :          0 :     case 'f': {/* float */
         825                 :          0 :         float *p = va_arg(*p_va, float *);
         826                 :          0 :         double dval = PyFloat_AsDouble(arg);
         827   [ #  #  #  # ]:          0 :         if (dval == -1.0 && PyErr_Occurred())
         828                 :          0 :             RETURN_ERR_OCCURRED;
         829                 :            :         else
         830                 :          0 :             *p = (float) dval;
         831                 :          0 :         break;
         832                 :            :     }
         833                 :            :
         834                 :          0 :     case 'd': {/* double */
         835                 :          0 :         double *p = va_arg(*p_va, double *);
         836                 :          0 :         double dval = PyFloat_AsDouble(arg);
         837   [ #  #  #  # ]:          0 :         if (dval == -1.0 && PyErr_Occurred())
         838                 :          0 :             RETURN_ERR_OCCURRED;
         839                 :            :         else
         840                 :          0 :             *p = dval;
         841                 :          0 :         break;
         842                 :            :     }
         843                 :            :
         844                 :          0 :     case 'D': {/* complex double */
         845                 :          0 :         Py_complex *p = va_arg(*p_va, Py_complex *);
         846                 :            :         Py_complex cval;
         847                 :          0 :         cval = PyComplex_AsCComplex(arg);
         848         [ #  # ]:          0 :         if (PyErr_Occurred())
         849                 :          0 :             RETURN_ERR_OCCURRED;
         850                 :            :         else
         851                 :          0 :             *p = cval;
         852                 :          0 :         break;
         853                 :            :     }
         854                 :            :
         855                 :          0 :     case 'c': {/* char */
         856                 :          0 :         char *p = va_arg(*p_va, char *);
         857   [ #  #  #  # ]:          0 :         if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1)
         858                 :          0 :             *p = PyBytes_AS_STRING(arg)[0];
         859   [ #  #  #  # ]:          0 :         else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1)
         860                 :          0 :             *p = PyByteArray_AS_STRING(arg)[0];
         861                 :            :         else
         862                 :          0 :             return converterr("a byte string of length 1", arg, msgbuf, bufsize);
         863                 :          0 :         break;
         864                 :            :     }
         865                 :            :
         866                 :          0 :     case 'C': {/* unicode char */
         867                 :          0 :         int *p = va_arg(*p_va, int *);
         868                 :            :         int kind;
         869                 :            :         const void *data;
         870                 :            :
         871         [ #  # ]:          0 :         if (!PyUnicode_Check(arg))
         872                 :          0 :             return converterr("a unicode character", arg, msgbuf, bufsize);
         873                 :            :
         874         [ #  # ]:          0 :         if (PyUnicode_READY(arg))
         875                 :          0 :             RETURN_ERR_OCCURRED;
         876                 :            :
         877         [ #  # ]:          0 :         if (PyUnicode_GET_LENGTH(arg) != 1)
         878                 :          0 :             return converterr("a unicode character", arg, msgbuf, bufsize);
         879                 :            :
         880                 :          0 :         kind = PyUnicode_KIND(arg);
         881                 :          0 :         data = PyUnicode_DATA(arg);
         882                 :          0 :         *p = PyUnicode_READ(kind, data, 0);
         883                 :          0 :         break;
         884                 :            :     }
         885                 :            :
         886                 :         61 :     case 'p': {/* boolean *p*redicate */
         887                 :         61 :         int *p = va_arg(*p_va, int *);
         888                 :         61 :         int val = PyObject_IsTrue(arg);
         889         [ +  + ]:         61 :         if (val > 0)
         890                 :         26 :             *p = 1;
         891         [ +  - ]:         35 :         else if (val == 0)
         892                 :         35 :             *p = 0;
         893                 :            :         else
         894                 :          0 :             RETURN_ERR_OCCURRED;
         895                 :         61 :         break;
         896                 :            :     }
         897                 :            :
         898                 :            :     /* XXX WAAAAH!  's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all
         899                 :            :        need to be cleaned up! */
         900                 :            :
         901                 :          0 :     case 'y': {/* any bytes-like object */
         902                 :          0 :         void **p = (void **)va_arg(*p_va, char **);
         903                 :            :         const char *buf;
         904                 :            :         Py_ssize_t count;
         905         [ #  # ]:          0 :         if (*format == '*') {
         906         [ #  # ]:          0 :             if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)
         907                 :          0 :                 return converterr(buf, arg, msgbuf, bufsize);
         908                 :          0 :             format++;
         909         [ #  # ]:          0 :             if (addcleanup(p, freelist, cleanup_buffer)) {
         910                 :          0 :                 return converterr(
         911                 :            :                     "(cleanup problem)",
         912                 :            :                     arg, msgbuf, bufsize);
         913                 :            :             }
         914                 :          0 :             break;
         915                 :            :         }
         916                 :          0 :         count = convertbuffer(arg, (const void **)p, &buf);
         917         [ #  # ]:          0 :         if (count < 0)
         918                 :          0 :             return converterr(buf, arg, msgbuf, bufsize);
         919         [ #  # ]:          0 :         if (*format == '#') {
         920         [ #  # ]:          0 :             REQUIRE_PY_SSIZE_T_CLEAN;
         921                 :          0 :             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
         922                 :          0 :             *psize = count;
         923                 :          0 :             format++;
         924                 :            :         } else {
         925         [ #  # ]:          0 :             if (strlen(*p) != (size_t)count) {
         926                 :          0 :                 PyErr_SetString(PyExc_ValueError, "embedded null byte");
         927                 :          0 :                 RETURN_ERR_OCCURRED;
         928                 :            :             }
         929                 :            :         }
         930                 :          0 :         break;
         931                 :            :     }
         932                 :            :
         933                 :          0 :     case 's': /* text string or bytes-like object */
         934                 :            :     case 'z': /* text string, bytes-like object or None */
         935                 :            :     {
         936         [ #  # ]:          0 :         if (*format == '*') {
         937                 :            :             /* "s*" or "z*" */
         938                 :          0 :             Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
         939                 :            :
         940   [ #  #  #  # ]:          0 :             if (c == 'z' && arg == Py_None)
         941                 :          0 :                 PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
         942         [ #  # ]:          0 :             else if (PyUnicode_Check(arg)) {
         943                 :            :                 Py_ssize_t len;
         944                 :          0 :                 sarg = PyUnicode_AsUTF8AndSize(arg, &len);
         945         [ #  # ]:          0 :                 if (sarg == NULL)
         946                 :          0 :                     return converterr(CONV_UNICODE,
         947                 :            :                                       arg, msgbuf, bufsize);
         948                 :          0 :                 PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0);
         949                 :            :             }
         950                 :            :             else { /* any bytes-like object */
         951                 :            :                 const char *buf;
         952         [ #  # ]:          0 :                 if (getbuffer(arg, p, &buf) < 0)
         953                 :          0 :                     return converterr(buf, arg, msgbuf, bufsize);
         954                 :            :             }
         955         [ #  # ]:          0 :             if (addcleanup(p, freelist, cleanup_buffer)) {
         956                 :          0 :                 return converterr(
         957                 :            :                     "(cleanup problem)",
         958                 :            :                     arg, msgbuf, bufsize);
         959                 :            :             }
         960                 :          0 :             format++;
         961         [ #  # ]:          0 :         } else if (*format == '#') { /* a string or read-only bytes-like object */
         962                 :            :             /* "s#" or "z#" */
         963                 :          0 :             const void **p = (const void **)va_arg(*p_va, const char **);
         964         [ #  # ]:          0 :             REQUIRE_PY_SSIZE_T_CLEAN;
         965                 :          0 :             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
         966                 :            :
         967   [ #  #  #  # ]:          0 :             if (c == 'z' && arg == Py_None) {
         968                 :          0 :                 *p = NULL;
         969                 :          0 :                 *psize = 0;
         970                 :            :             }
         971         [ #  # ]:          0 :             else if (PyUnicode_Check(arg)) {
         972                 :            :                 Py_ssize_t len;
         973                 :          0 :                 sarg = PyUnicode_AsUTF8AndSize(arg, &len);
         974         [ #  # ]:          0 :                 if (sarg == NULL)
         975                 :          0 :                     return converterr(CONV_UNICODE,
         976                 :            :                                       arg, msgbuf, bufsize);
         977                 :          0 :                 *p = sarg;
         978                 :          0 :                 *psize = len;
         979                 :            :             }
         980                 :            :             else { /* read-only bytes-like object */
         981                 :            :                 /* XXX Really? */
         982                 :            :                 const char *buf;
         983                 :          0 :                 Py_ssize_t count = convertbuffer(arg, p, &buf);
         984         [ #  # ]:          0 :                 if (count < 0)
         985                 :          0 :                     return converterr(buf, arg, msgbuf, bufsize);
         986                 :          0 :                 *psize = count;
         987                 :            :             }
         988                 :          0 :             format++;
         989                 :            :         } else {
         990                 :            :             /* "s" or "z" */
         991                 :          0 :             const char **p = va_arg(*p_va, const char **);
         992                 :            :             Py_ssize_t len;
         993                 :          0 :             sarg = NULL;
         994                 :            :
         995   [ #  #  #  # ]:          0 :             if (c == 'z' && arg == Py_None)
         996                 :          0 :                 *p = NULL;
         997         [ #  # ]:          0 :             else if (PyUnicode_Check(arg)) {
         998                 :          0 :                 sarg = PyUnicode_AsUTF8AndSize(arg, &len);
         999         [ #  # ]:          0 :                 if (sarg == NULL)
        1000                 :          0 :                     return converterr(CONV_UNICODE,
        1001                 :            :                                       arg, msgbuf, bufsize);
        1002         [ #  # ]:          0 :                 if (strlen(sarg) != (size_t)len) {
        1003                 :          0 :                     PyErr_SetString(PyExc_ValueError, "embedded null character");
        1004                 :          0 :                     RETURN_ERR_OCCURRED;
        1005                 :            :                 }
        1006                 :          0 :                 *p = sarg;
        1007                 :            :             }
        1008                 :            :             else
        1009         [ #  # ]:          0 :                 return converterr(c == 'z' ? "str or None" : "str",
        1010                 :            :                                   arg, msgbuf, bufsize);
        1011                 :            :         }
        1012                 :          0 :         break;
        1013                 :            :     }
        1014                 :            :
        1015                 :          0 :     case 'e': {/* encoded string */
        1016                 :            :         char **buffer;
        1017                 :            :         const char *encoding;
        1018                 :            :         PyObject *s;
        1019                 :            :         int recode_strings;
        1020                 :            :         Py_ssize_t size;
        1021                 :            :         const char *ptr;
        1022                 :            :
        1023                 :            :         /* Get 'e' parameter: the encoding name */
        1024                 :          0 :         encoding = (const char *)va_arg(*p_va, const char *);
        1025         [ #  # ]:          0 :         if (encoding == NULL)
        1026                 :          0 :             encoding = PyUnicode_GetDefaultEncoding();
        1027                 :            :
        1028                 :            :         /* Get output buffer parameter:
        1029                 :            :            's' (recode all objects via Unicode) or
        1030                 :            :            't' (only recode non-string objects)
        1031                 :            :         */
        1032         [ #  # ]:          0 :         if (*format == 's')
        1033                 :          0 :             recode_strings = 1;
        1034         [ #  # ]:          0 :         else if (*format == 't')
        1035                 :          0 :             recode_strings = 0;
        1036                 :            :         else
        1037                 :          0 :             return converterr(
        1038                 :            :                 "(unknown parser marker combination)",
        1039                 :            :                 arg, msgbuf, bufsize);
        1040                 :          0 :         buffer = (char **)va_arg(*p_va, char **);
        1041                 :          0 :         format++;
        1042         [ #  # ]:          0 :         if (buffer == NULL)
        1043                 :          0 :             return converterr("(buffer is NULL)",
        1044                 :            :                               arg, msgbuf, bufsize);
        1045                 :            :
        1046                 :            :         /* Encode object */
        1047   [ #  #  #  # ]:          0 :         if (!recode_strings &&
        1048         [ #  # ]:          0 :             (PyBytes_Check(arg) || PyByteArray_Check(arg))) {
        1049                 :          0 :             s = Py_NewRef(arg);
        1050         [ #  # ]:          0 :             if (PyBytes_Check(arg)) {
        1051                 :          0 :                 size = PyBytes_GET_SIZE(s);
        1052                 :          0 :                 ptr = PyBytes_AS_STRING(s);
        1053                 :            :             }
        1054                 :            :             else {
        1055                 :          0 :                 size = PyByteArray_GET_SIZE(s);
        1056                 :          0 :                 ptr = PyByteArray_AS_STRING(s);
        1057                 :            :             }
        1058                 :            :         }
        1059         [ #  # ]:          0 :         else if (PyUnicode_Check(arg)) {
        1060                 :            :             /* Encode object; use default error handling */
        1061                 :          0 :             s = PyUnicode_AsEncodedString(arg,
        1062                 :            :                                           encoding,
        1063                 :            :                                           NULL);
        1064         [ #  # ]:          0 :             if (s == NULL)
        1065                 :          0 :                 return converterr("(encoding failed)",
        1066                 :            :                                   arg, msgbuf, bufsize);
        1067                 :            :             assert(PyBytes_Check(s));
        1068                 :          0 :             size = PyBytes_GET_SIZE(s);
        1069                 :          0 :             ptr = PyBytes_AS_STRING(s);
        1070         [ #  # ]:          0 :             if (ptr == NULL)
        1071                 :          0 :                 ptr = "";
        1072                 :            :         }
        1073                 :            :         else {
        1074         [ #  # ]:          0 :             return converterr(
        1075                 :            :                 recode_strings ? "str" : "str, bytes or bytearray",
        1076                 :            :                 arg, msgbuf, bufsize);
        1077                 :            :         }
        1078                 :            :
        1079                 :            :         /* Write output; output is guaranteed to be 0-terminated */
        1080         [ #  # ]:          0 :         if (*format == '#') {
        1081                 :            :             /* Using buffer length parameter '#':
        1082                 :            :
        1083                 :            :                - if *buffer is NULL, a new buffer of the
        1084                 :            :                needed size is allocated and the data
        1085                 :            :                copied into it; *buffer is updated to point
        1086                 :            :                to the new buffer; the caller is
        1087                 :            :                responsible for PyMem_Free()ing it after
        1088                 :            :                usage
        1089                 :            :
        1090                 :            :                - if *buffer is not NULL, the data is
        1091                 :            :                copied to *buffer; *buffer_len has to be
        1092                 :            :                set to the size of the buffer on input;
        1093                 :            :                buffer overflow is signalled with an error;
        1094                 :            :                buffer has to provide enough room for the
        1095                 :            :                encoded string plus the trailing 0-byte
        1096                 :            :
        1097                 :            :                - in both cases, *buffer_len is updated to
        1098                 :            :                the size of the buffer /excluding/ the
        1099                 :            :                trailing 0-byte
        1100                 :            :
        1101                 :            :             */
        1102         [ #  # ]:          0 :             REQUIRE_PY_SSIZE_T_CLEAN;
        1103                 :          0 :             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);
        1104                 :            :
        1105                 :          0 :             format++;
        1106         [ #  # ]:          0 :             if (psize == NULL) {
        1107                 :          0 :                 Py_DECREF(s);
        1108                 :          0 :                 return converterr(
        1109                 :            :                     "(buffer_len is NULL)",
        1110                 :            :                     arg, msgbuf, bufsize);
        1111                 :            :             }
        1112         [ #  # ]:          0 :             if (*buffer == NULL) {
        1113         [ #  # ]:          0 :                 *buffer = PyMem_NEW(char, size + 1);
        1114         [ #  # ]:          0 :                 if (*buffer == NULL) {
        1115                 :          0 :                     Py_DECREF(s);
        1116                 :          0 :                     PyErr_NoMemory();
        1117                 :          0 :                     RETURN_ERR_OCCURRED;
        1118                 :            :                 }
        1119         [ #  # ]:          0 :                 if (addcleanup(buffer, freelist, cleanup_ptr)) {
        1120                 :          0 :                     Py_DECREF(s);
        1121                 :          0 :                     return converterr(
        1122                 :            :                         "(cleanup problem)",
        1123                 :            :                         arg, msgbuf, bufsize);
        1124                 :            :                 }
        1125                 :            :             } else {
        1126         [ #  # ]:          0 :                 if (size + 1 > *psize) {
        1127                 :          0 :                     Py_DECREF(s);
        1128                 :          0 :                     PyErr_Format(PyExc_ValueError,
        1129                 :            :                                  "encoded string too long "
        1130                 :            :                                  "(%zd, maximum length %zd)",
        1131                 :          0 :                                  (Py_ssize_t)size, (Py_ssize_t)(*psize - 1));
        1132                 :          0 :                     RETURN_ERR_OCCURRED;
        1133                 :            :                 }
        1134                 :            :             }
        1135                 :          0 :             memcpy(*buffer, ptr, size+1);
        1136                 :            :
        1137                 :          0 :             *psize = size;
        1138                 :            :         }
        1139                 :            :         else {
        1140                 :            :             /* Using a 0-terminated buffer:
        1141                 :            :
        1142                 :            :                - the encoded string has to be 0-terminated
        1143                 :            :                for this variant to work; if it is not, an
        1144                 :            :                error raised
        1145                 :            :
        1146                 :            :                - a new buffer of the needed size is
        1147                 :            :                allocated and the data copied into it;
        1148                 :            :                *buffer is updated to point to the new
        1149                 :            :                buffer; the caller is responsible for
        1150                 :            :                PyMem_Free()ing it after usage
        1151                 :            :
        1152                 :            :             */
        1153         [ #  # ]:          0 :             if ((Py_ssize_t)strlen(ptr) != size) {
        1154                 :          0 :                 Py_DECREF(s);
        1155                 :          0 :                 return converterr(
        1156                 :            :                     "encoded string without null bytes",
        1157                 :            :                     arg, msgbuf, bufsize);
        1158                 :            :             }
        1159         [ #  # ]:          0 :             *buffer = PyMem_NEW(char, size + 1);
        1160         [ #  # ]:          0 :             if (*buffer == NULL) {
        1161                 :          0 :                 Py_DECREF(s);
        1162                 :          0 :                 PyErr_NoMemory();
        1163                 :          0 :                 RETURN_ERR_OCCURRED;
        1164                 :            :             }
        1165         [ #  # ]:          0 :             if (addcleanup(buffer, freelist, cleanup_ptr)) {
        1166                 :          0 :                 Py_DECREF(s);
        1167                 :          0 :                 return converterr("(cleanup problem)",
        1168                 :            :                                 arg, msgbuf, bufsize);
        1169                 :            :             }
        1170                 :          0 :             memcpy(*buffer, ptr, size+1);
        1171                 :            :         }
        1172                 :          0 :         Py_DECREF(s);
        1173                 :          0 :         break;
        1174                 :            :     }
        1175                 :            :
        1176                 :          0 :     case 'S': { /* PyBytes object */
        1177                 :          0 :         PyObject **p = va_arg(*p_va, PyObject **);
        1178         [ #  # ]:          0 :         if (PyBytes_Check(arg))
        1179                 :          0 :             *p = arg;
        1180                 :            :         else
        1181                 :          0 :             return converterr("bytes", arg, msgbuf, bufsize);
        1182                 :          0 :         break;
        1183                 :            :     }
        1184                 :            :
        1185                 :          0 :     case 'Y': { /* PyByteArray object */
        1186                 :          0 :         PyObject **p = va_arg(*p_va, PyObject **);
        1187         [ #  # ]:          0 :         if (PyByteArray_Check(arg))
        1188                 :          0 :             *p = arg;
        1189                 :            :         else
        1190                 :          0 :             return converterr("bytearray", arg, msgbuf, bufsize);
        1191                 :          0 :         break;
        1192                 :            :     }
        1193                 :            :
        1194                 :       6595 :     case 'U': { /* PyUnicode object */
        1195                 :       6595 :         PyObject **p = va_arg(*p_va, PyObject **);
        1196         [ +  - ]:       6595 :         if (PyUnicode_Check(arg)) {
        1197         [ -  + ]:       6595 :             if (PyUnicode_READY(arg) == -1)
        1198                 :          0 :                 RETURN_ERR_OCCURRED;
        1199                 :       6595 :             *p = arg;
        1200                 :            :         }
        1201                 :            :         else
        1202                 :          0 :             return converterr("str", arg, msgbuf, bufsize);
        1203                 :       6595 :         break;
        1204                 :            :     }
        1205                 :            :
        1206                 :     137787 :     case 'O': { /* object */
        1207                 :            :         PyTypeObject *type;
        1208                 :            :         PyObject **p;
        1209         [ +  + ]:     137787 :         if (*format == '!') {
        1210                 :      12588 :             type = va_arg(*p_va, PyTypeObject*);
        1211                 :      12588 :             p = va_arg(*p_va, PyObject **);
        1212                 :      12588 :             format++;
        1213         [ +  - ]:      12588 :             if (PyType_IsSubtype(Py_TYPE(arg), type))
        1214                 :      12588 :                 *p = arg;
        1215                 :            :             else
        1216                 :          0 :                 return converterr(type->tp_name, arg, msgbuf, bufsize);
        1217                 :            :
        1218                 :            :         }
        1219         [ -  + ]:     125199 :         else if (*format == '&') {
        1220                 :            :             typedef int (*converter)(PyObject *, void *);
        1221                 :          0 :             converter convert = va_arg(*p_va, converter);
        1222                 :          0 :             void *addr = va_arg(*p_va, void *);
        1223                 :            :             int res;
        1224                 :          0 :             format++;
        1225         [ #  # ]:          0 :             if (! (res = (*convert)(arg, addr)))
        1226                 :          0 :                 return converterr("(unspecified)",
        1227                 :            :                                   arg, msgbuf, bufsize);
        1228   [ #  #  #  # ]:          0 :             if (res == Py_CLEANUP_SUPPORTED &&
        1229                 :          0 :                 addcleanup(addr, freelist, convert) == -1)
        1230                 :          0 :                 return converterr("(cleanup problem)",
        1231                 :            :                                 arg, msgbuf, bufsize);
        1232                 :            :         }
        1233                 :            :         else {
        1234                 :     125199 :             p = va_arg(*p_va, PyObject **);
        1235                 :     125199 :             *p = arg;
        1236                 :            :         }
        1237                 :     137787 :         break;
        1238                 :            :     }
        1239                 :            :
        1240                 :            :
        1241                 :          0 :     case 'w': { /* "w*": memory buffer, read-write access */
        1242                 :          0 :         void **p = va_arg(*p_va, void **);
        1243                 :            :
        1244         [ #  # ]:          0 :         if (*format != '*')
        1245                 :          0 :             return converterr(
        1246                 :            :                 "(invalid use of 'w' format character)",
        1247                 :            :                 arg, msgbuf, bufsize);
        1248                 :          0 :         format++;
        1249                 :            :
        1250                 :            :         /* Caller is interested in Py_buffer, and the object
        1251                 :            :            supports it directly. */
        1252         [ #  # ]:          0 :         if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
        1253                 :          0 :             PyErr_Clear();
        1254                 :          0 :             return converterr("read-write bytes-like object",
        1255                 :            :                               arg, msgbuf, bufsize);
        1256                 :            :         }
        1257         [ #  # ]:          0 :         if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) {
        1258                 :          0 :             PyBuffer_Release((Py_buffer*)p);
        1259                 :          0 :             return converterr("contiguous buffer", arg, msgbuf, bufsize);
        1260                 :            :         }
        1261         [ #  # ]:          0 :         if (addcleanup(p, freelist, cleanup_buffer)) {
        1262                 :          0 :             return converterr(
        1263                 :            :                 "(cleanup problem)",
        1264                 :            :                 arg, msgbuf, bufsize);
        1265                 :            :         }
        1266                 :          0 :         break;
        1267                 :            :     }
        1268                 :            :
        1269                 :          0 :     default:
        1270                 :          0 :         return converterr("(impossible<bad format char>)", arg, msgbuf, bufsize);
        1271                 :            :
        1272                 :            :     }
        1273                 :            :
        1274                 :     144805 :     *p_format = format;
        1275                 :     144805 :     return NULL;
        1276                 :            :
        1277                 :            : #undef REQUIRE_PY_SSIZE_T_CLEAN
        1278                 :            : #undef RETURN_ERR_OCCURRED
        1279                 :            : }
        1280                 :            :
        1281                 :            : static Py_ssize_t
        1282                 :          0 : convertbuffer(PyObject *arg, const void **p, const char **errmsg)
        1283                 :            : {
        1284                 :          0 :     PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;
        1285                 :            :     Py_ssize_t count;
        1286                 :            :     Py_buffer view;
        1287                 :            :
        1288                 :          0 :     *errmsg = NULL;
        1289                 :          0 :     *p = NULL;
        1290   [ #  #  #  # ]:          0 :     if (pb != NULL && pb->bf_releasebuffer != NULL) {
        1291                 :          0 :         *errmsg = "read-only bytes-like object";
        1292                 :          0 :         return -1;
        1293                 :            :     }
        1294                 :            :
        1295         [ #  # ]:          0 :     if (getbuffer(arg, &view, errmsg) < 0)
        1296                 :          0 :         return -1;
        1297                 :          0 :     count = view.len;
        1298                 :          0 :     *p = view.buf;
        1299                 :          0 :     PyBuffer_Release(&view);
        1300                 :          0 :     return count;
        1301                 :            : }
        1302                 :            :
        1303                 :            : static int
        1304                 :          0 : getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg)
        1305                 :            : {
        1306         [ #  # ]:          0 :     if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) {
        1307                 :          0 :         *errmsg = "bytes-like object";
        1308                 :          0 :         return -1;
        1309                 :            :     }
        1310         [ #  # ]:          0 :     if (!PyBuffer_IsContiguous(view, 'C')) {
        1311                 :          0 :         PyBuffer_Release(view);
        1312                 :          0 :         *errmsg = "contiguous buffer";
        1313                 :          0 :         return -1;
        1314                 :            :     }
        1315                 :          0 :     return 0;
        1316                 :            : }
        1317                 :            :
        1318                 :            : /* Support for keyword arguments donated by
        1319                 :            :    Geoff Philbrick <philbric@delphi.hks.com> */
        1320                 :            :
        1321                 :            : /* Return false (0) for error, else true. */
        1322                 :            : int
        1323                 :     115790 : PyArg_ParseTupleAndKeywords(PyObject *args,
        1324                 :            :                             PyObject *keywords,
        1325                 :            :                             const char *format,
        1326                 :            :                             char **kwlist, ...)
        1327                 :            : {
        1328                 :            :     int retval;
        1329                 :            :     va_list va;
        1330                 :            :
        1331   [ +  -  +  -  :     115790 :     if ((args == NULL || !PyTuple_Check(args)) ||
                       +  + ]
        1332   [ +  -  +  - ]:     115790 :         (keywords != NULL && !PyDict_Check(keywords)) ||
        1333         [ -  + ]:     115790 :         format == NULL ||
        1334                 :            :         kwlist == NULL)
        1335                 :            :     {
        1336                 :          0 :         PyErr_BadInternalCall();
        1337                 :          0 :         return 0;
        1338                 :            :     }
        1339                 :            :
        1340                 :     115790 :     va_start(va, kwlist);
        1341                 :     115790 :     retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);
        1342                 :     115790 :     va_end(va);
        1343                 :     115790 :     return retval;
        1344                 :            : }
        1345                 :            :
        1346                 :            : PyAPI_FUNC(int)
        1347                 :      14443 : _PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,
        1348                 :            :                                   PyObject *keywords,
        1349                 :            :                                   const char *format,
        1350                 :            :                                   char **kwlist, ...)
        1351                 :            : {
        1352                 :            :     int retval;
        1353                 :            :     va_list va;
        1354                 :            :
        1355   [ +  -  +  -  :      14443 :     if ((args == NULL || !PyTuple_Check(args)) ||
                       +  + ]
        1356   [ +  -  +  - ]:      14443 :         (keywords != NULL && !PyDict_Check(keywords)) ||
        1357         [ -  + ]:      14443 :         format == NULL ||
        1358                 :            :         kwlist == NULL)
        1359                 :            :     {
        1360                 :          0 :         PyErr_BadInternalCall();
        1361                 :          0 :         return 0;
        1362                 :            :     }
        1363                 :            :
        1364                 :      14443 :     va_start(va, kwlist);
        1365                 :      14443 :     retval = vgetargskeywords(args, keywords, format,
        1366                 :            :                               kwlist, &va, FLAG_SIZE_T);
        1367                 :      14443 :     va_end(va);
        1368                 :      14443 :     return retval;
        1369                 :            : }
        1370                 :            :
        1371                 :            :
        1372                 :            : int
        1373                 :          0 : PyArg_VaParseTupleAndKeywords(PyObject *args,
        1374                 :            :                               PyObject *keywords,
        1375                 :            :                               const char *format,
        1376                 :            :                               char **kwlist, va_list va)
        1377                 :            : {
        1378                 :            :     int retval;
        1379                 :            :     va_list lva;
        1380                 :            :
        1381   [ #  #  #  #  :          0 :     if ((args == NULL || !PyTuple_Check(args)) ||
                       #  # ]
        1382   [ #  #  #  # ]:          0 :         (keywords != NULL && !PyDict_Check(keywords)) ||
        1383         [ #  # ]:          0 :         format == NULL ||
        1384                 :            :         kwlist == NULL)
        1385                 :            :     {
        1386                 :          0 :         PyErr_BadInternalCall();
        1387                 :          0 :         return 0;
        1388                 :            :     }
        1389                 :            :
        1390                 :          0 :     va_copy(lva, va);
        1391                 :            :
        1392                 :          0 :     retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);
        1393                 :          0 :     va_end(lva);
        1394                 :          0 :     return retval;
        1395                 :            : }
        1396                 :            :
        1397                 :            : PyAPI_FUNC(int)
        1398                 :          0 : _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,
        1399                 :            :                                     PyObject *keywords,
        1400                 :            :                                     const char *format,
        1401                 :            :                                     char **kwlist, va_list va)
        1402                 :            : {
        1403                 :            :     int retval;
        1404                 :            :     va_list lva;
        1405                 :            :
        1406   [ #  #  #  #  :          0 :     if ((args == NULL || !PyTuple_Check(args)) ||
                       #  # ]
        1407   [ #  #  #  # ]:          0 :         (keywords != NULL && !PyDict_Check(keywords)) ||
        1408         [ #  # ]:          0 :         format == NULL ||
        1409                 :            :         kwlist == NULL)
        1410                 :            :     {
        1411                 :          0 :         PyErr_BadInternalCall();
        1412                 :          0 :         return 0;
        1413                 :            :     }
        1414                 :            :
        1415                 :          0 :     va_copy(lva, va);
        1416                 :            :
        1417                 :          0 :     retval = vgetargskeywords(args, keywords, format,
        1418                 :            :                               kwlist, &lva, FLAG_SIZE_T);
        1419                 :          0 :     va_end(lva);
        1420                 :          0 :     return retval;
        1421                 :            : }
        1422                 :            :
        1423                 :            : PyAPI_FUNC(int)
        1424                 :          0 : _PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
        1425                 :            :                             struct _PyArg_Parser *parser, ...)
        1426                 :            : {
        1427                 :            :     int retval;
        1428                 :            :     va_list va;
        1429                 :            :
        1430                 :          0 :     va_start(va, parser);
        1431                 :          0 :     retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);
        1432                 :          0 :     va_end(va);
        1433                 :          0 :     return retval;
        1434                 :            : }
        1435                 :            :
        1436                 :            : PyAPI_FUNC(int)
        1437                 :          0 : _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
        1438                 :            :                             struct _PyArg_Parser *parser, ...)
        1439                 :            : {
        1440                 :            :     int retval;
        1441                 :            :     va_list va;
        1442                 :            :
        1443                 :          0 :     va_start(va, parser);
        1444                 :          0 :     retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T);
        1445                 :          0 :     va_end(va);
        1446                 :          0 :     return retval;
        1447                 :            : }
        1448                 :            :
        1449                 :            : PyAPI_FUNC(int)
        1450                 :          0 : _PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
        1451                 :            :                   struct _PyArg_Parser *parser, ...)
        1452                 :            : {
        1453                 :            :     int retval;
        1454                 :            :     va_list va;
        1455                 :            :
        1456                 :          0 :     va_start(va, parser);
        1457                 :          0 :     retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);
        1458                 :          0 :     va_end(va);
        1459                 :          0 :     return retval;
        1460                 :            : }
        1461                 :            :
        1462                 :            : PyAPI_FUNC(int)
        1463                 :          0 : _PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
        1464                 :            :                         struct _PyArg_Parser *parser, ...)
        1465                 :            : {
        1466                 :            :     int retval;
        1467                 :            :     va_list va;
        1468                 :            :
        1469                 :          0 :     va_start(va, parser);
        1470                 :          0 :     retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, FLAG_SIZE_T);
        1471                 :          0 :     va_end(va);
        1472                 :          0 :     return retval;
        1473                 :            : }
        1474                 :            :
        1475                 :            :
        1476                 :            : PyAPI_FUNC(int)
        1477                 :          0 : _PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
        1478                 :            :                             struct _PyArg_Parser *parser, va_list va)
        1479                 :            : {
        1480                 :            :     int retval;
        1481                 :            :     va_list lva;
        1482                 :            :
        1483                 :          0 :     va_copy(lva, va);
        1484                 :            :
        1485                 :          0 :     retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0);
        1486                 :          0 :     va_end(lva);
        1487                 :          0 :     return retval;
        1488                 :            : }
        1489                 :            :
        1490                 :            : PyAPI_FUNC(int)
        1491                 :          0 : _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
        1492                 :            :                             struct _PyArg_Parser *parser, va_list va)
        1493                 :            : {
        1494                 :            :     int retval;
        1495                 :            :     va_list lva;
        1496                 :            :
        1497                 :          0 :     va_copy(lva, va);
        1498                 :            :
        1499                 :          0 :     retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T);
        1500                 :          0 :     va_end(lva);
        1501                 :          0 :     return retval;
        1502                 :            : }
        1503                 :            :
        1504                 :            : static void
        1505                 :          0 : error_unexpected_keyword_arg(PyObject *kwargs, PyObject *kwnames, PyObject *kwtuple, const char *fname)
        1506                 :            : {
        1507                 :            :     /* make sure there are no extraneous keyword arguments */
        1508                 :          0 :     Py_ssize_t j = 0;
        1509                 :          0 :     while (1) {
        1510                 :            :         PyObject *keyword;
        1511         [ #  # ]:          0 :         if (kwargs != NULL) {
        1512         [ #  # ]:          0 :             if (!PyDict_Next(kwargs, &j, &keyword, NULL))
        1513                 :          0 :                 break;
        1514                 :            :         }
        1515                 :            :         else {
        1516         [ #  # ]:          0 :             if (j >= PyTuple_GET_SIZE(kwnames))
        1517                 :          0 :                 break;
        1518                 :          0 :             keyword = PyTuple_GET_ITEM(kwnames, j);
        1519                 :          0 :             j++;
        1520                 :            :         }
        1521         [ #  # ]:          0 :         if (!PyUnicode_Check(keyword)) {
        1522                 :          0 :             PyErr_SetString(PyExc_TypeError,
        1523                 :            :                             "keywords must be strings");
        1524                 :          0 :             return;
        1525                 :            :         }
        1526                 :            :
        1527                 :          0 :         int match = PySequence_Contains(kwtuple, keyword);
        1528         [ #  # ]:          0 :         if (match <= 0) {
        1529         [ #  # ]:          0 :             if (!match) {
        1530   [ #  #  #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
        1531                 :            :                              "'%S' is an invalid keyword "
        1532                 :            :                              "argument for %.200s%s",
        1533                 :            :                              keyword,
        1534                 :            :                              (fname == NULL) ? "this function" : fname,
        1535                 :            :                              (fname == NULL) ? "" : "()");
        1536                 :            :             }
        1537                 :          0 :             return;
        1538                 :            :         }
        1539                 :            :     }
        1540                 :            :     /* Something wrong happened. There are extraneous keyword arguments,
        1541                 :            :      * but we don't know what. And we don't bother. */
        1542   [ #  #  #  # ]:          0 :     PyErr_Format(PyExc_TypeError,
        1543                 :            :                  "invalid keyword argument for %.200s%s",
        1544                 :            :                  (fname == NULL) ? "this function" : fname,
        1545                 :            :                  (fname == NULL) ? "" : "()");
        1546                 :            : }
        1547                 :            :
        1548                 :            : int
        1549                 :        124 : PyArg_ValidateKeywordArguments(PyObject *kwargs)
        1550                 :            : {
        1551         [ -  + ]:        124 :     if (!PyDict_Check(kwargs)) {
        1552                 :          0 :         PyErr_BadInternalCall();
        1553                 :          0 :         return 0;
        1554                 :            :     }
        1555         [ -  + ]:        124 :     if (!_PyDict_HasOnlyStringKeys(kwargs)) {
        1556                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1557                 :            :                         "keywords must be strings");
        1558                 :          0 :         return 0;
        1559                 :            :     }
        1560                 :        124 :     return 1;
        1561                 :            : }
        1562                 :            :
        1563                 :            : #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':')
        1564                 :            :
        1565                 :            : static int
        1566                 :     130233 : vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
        1567                 :            :                  char **kwlist, va_list *p_va, int flags)
        1568                 :            : {
        1569                 :            :     char msgbuf[512];
        1570                 :            :     int levels[32];
        1571                 :            :     const char *fname, *msg, *custom_msg;
        1572                 :     130233 :     int min = INT_MAX;
        1573                 :     130233 :     int max = INT_MAX;
        1574                 :            :     int i, pos, len;
        1575                 :     130233 :     int skip = 0;
        1576                 :            :     Py_ssize_t nargs, nkwargs;
        1577                 :            :     PyObject *current_arg;
        1578                 :            :     freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
        1579                 :            :     freelist_t freelist;
        1580                 :            :
        1581                 :     130233 :     freelist.entries = static_entries;
        1582                 :     130233 :     freelist.first_available = 0;
        1583                 :     130233 :     freelist.entries_malloced = 0;
        1584                 :            :
        1585                 :            :     assert(args != NULL && PyTuple_Check(args));
        1586                 :            :     assert(kwargs == NULL || PyDict_Check(kwargs));
        1587                 :            :     assert(format != NULL);
        1588                 :            :     assert(kwlist != NULL);
        1589                 :            :     assert(p_va != NULL);
        1590                 :            :
        1591                 :            :     /* grab the function name or custom error msg first (mutually exclusive) */
        1592                 :     130233 :     fname = strchr(format, ':');
        1593         [ +  + ]:     130233 :     if (fname) {
        1594                 :     130049 :         fname++;
        1595                 :     130049 :         custom_msg = NULL;
        1596                 :            :     }
        1597                 :            :     else {
        1598                 :        184 :         custom_msg = strchr(format,';');
        1599         [ -  + ]:        184 :         if (custom_msg)
        1600                 :          0 :             custom_msg++;
        1601                 :            :     }
        1602                 :            :
        1603                 :            :     /* scan kwlist and count the number of positional-only parameters */
        1604   [ +  -  -  + ]:     130233 :     for (pos = 0; kwlist[pos] && !*kwlist[pos]; pos++) {
        1605                 :            :     }
        1606                 :            :     /* scan kwlist and get greatest possible nbr of args */
        1607         [ +  + ]:     391040 :     for (len = pos; kwlist[len]; len++) {
        1608         [ -  + ]:     260807 :         if (!*kwlist[len]) {
        1609                 :          0 :             PyErr_SetString(PyExc_SystemError,
        1610                 :            :                             "Empty keyword parameter name");
        1611                 :          0 :             return cleanreturn(0, &freelist);
        1612                 :            :         }
        1613                 :            :     }
        1614                 :            :
        1615         [ +  + ]:     130233 :     if (len > STATIC_FREELIST_ENTRIES) {
        1616         [ +  - ]:         30 :         freelist.entries = PyMem_NEW(freelistentry_t, len);
        1617         [ -  + ]:         30 :         if (freelist.entries == NULL) {
        1618                 :          0 :             PyErr_NoMemory();
        1619                 :          0 :             return 0;
        1620                 :            :         }
        1621                 :         30 :         freelist.entries_malloced = 1;
        1622                 :            :     }
        1623                 :            :
        1624                 :     130233 :     nargs = PyTuple_GET_SIZE(args);
        1625         [ +  + ]:     130233 :     nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);
        1626         [ -  + ]:     130233 :     if (nargs + nkwargs > len) {
        1627                 :            :         /* Adding "keyword" (when nargs == 0) prevents producing wrong error
        1628                 :            :            messages in some special cases (see bpo-31229). */
        1629   [ #  #  #  #  :          0 :         PyErr_Format(PyExc_TypeError,
                 #  #  #  # ]
        1630                 :            :                      "%.200s%s takes at most %d %sargument%s (%zd given)",
        1631                 :            :                      (fname == NULL) ? "function" : fname,
        1632                 :            :                      (fname == NULL) ? "" : "()",
        1633                 :            :                      len,
        1634                 :            :                      (nargs == 0) ? "keyword " : "",
        1635                 :            :                      (len == 1) ? "" : "s",
        1636                 :            :                      nargs + nkwargs);
        1637                 :          0 :         return cleanreturn(0, &freelist);
        1638                 :            :     }
        1639                 :            :
        1640                 :            :     /* convert tuple args and keyword args in same loop, using kwlist to drive process */
        1641         [ +  + ]:     131523 :     for (i = 0; i < len; i++) {
        1642         [ +  + ]:     131015 :         if (*format == '|') {
        1643         [ -  + ]:     130118 :             if (min != INT_MAX) {
        1644                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1645                 :            :                                 "Invalid format string (| specified twice)");
        1646                 :          0 :                 return cleanreturn(0, &freelist);
        1647                 :            :             }
        1648                 :            :
        1649                 :     130118 :             min = i;
        1650                 :     130118 :             format++;
        1651                 :            :
        1652         [ -  + ]:     130118 :             if (max != INT_MAX) {
        1653                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1654                 :            :                                 "Invalid format string ($ before |)");
        1655                 :          0 :                 return cleanreturn(0, &freelist);
        1656                 :            :             }
        1657                 :            :         }
        1658         [ +  + ]:     131015 :         if (*format == '$') {
        1659         [ -  + ]:     126975 :             if (max != INT_MAX) {
        1660                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1661                 :            :                                 "Invalid format string ($ specified twice)");
        1662                 :          0 :                 return cleanreturn(0, &freelist);
        1663                 :            :             }
        1664                 :            :
        1665                 :     126975 :             max = i;
        1666                 :     126975 :             format++;
        1667                 :            :
        1668         [ -  + ]:     126975 :             if (max < pos) {
        1669                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1670                 :            :                                 "Empty parameter name after $");
        1671                 :          0 :                 return cleanreturn(0, &freelist);
        1672                 :            :             }
        1673         [ -  + ]:     126975 :             if (skip) {
        1674                 :            :                 /* Now we know the minimal and the maximal numbers of
        1675                 :            :                  * positional arguments and can raise an exception with
        1676                 :            :                  * informative message (see below). */
        1677                 :          0 :                 break;
        1678                 :            :             }
        1679         [ -  + ]:     126975 :             if (max < nargs) {
        1680         [ #  # ]:          0 :                 if (max == 0) {
        1681   [ #  #  #  # ]:          0 :                     PyErr_Format(PyExc_TypeError,
        1682                 :            :                                  "%.200s%s takes no positional arguments",
        1683                 :            :                                  (fname == NULL) ? "function" : fname,
        1684                 :            :                                  (fname == NULL) ? "" : "()");
        1685                 :            :                 }
        1686                 :            :                 else {
        1687   [ #  #  #  #  :          0 :                     PyErr_Format(PyExc_TypeError,
                 #  #  #  # ]
        1688                 :            :                                  "%.200s%s takes %s %d positional argument%s"
        1689                 :            :                                  " (%zd given)",
        1690                 :            :                                  (fname == NULL) ? "function" : fname,
        1691                 :            :                                  (fname == NULL) ? "" : "()",
        1692                 :            :                                  (min != INT_MAX) ? "at most" : "exactly",
        1693                 :            :                                  max,
        1694                 :            :                                  max == 1 ? "" : "s",
        1695                 :            :                                  nargs);
        1696                 :            :                 }
        1697                 :          0 :                 return cleanreturn(0, &freelist);
        1698                 :            :             }
        1699                 :            :         }
        1700   [ +  -  +  -  :     131015 :         if (IS_END_OF_FORMAT(*format)) {
                       -  + ]
        1701                 :          0 :             PyErr_Format(PyExc_SystemError,
        1702                 :            :                          "More keyword list entries (%d) than "
        1703                 :            :                          "format specifiers (%d)", len, i);
        1704                 :          0 :             return cleanreturn(0, &freelist);
        1705                 :            :         }
        1706         [ +  - ]:     131015 :         if (!skip) {
        1707         [ +  + ]:     131015 :             if (i < nargs) {
        1708                 :        352 :                 current_arg = PyTuple_GET_ITEM(args, i);
        1709                 :            :             }
        1710   [ +  +  +  - ]:     130663 :             else if (nkwargs && i >= pos) {
        1711                 :        938 :                 current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);
        1712         [ +  + ]:        938 :                 if (current_arg) {
        1713                 :        714 :                     --nkwargs;
        1714                 :            :                 }
        1715         [ -  + ]:        224 :                 else if (PyErr_Occurred()) {
        1716                 :          0 :                     return cleanreturn(0, &freelist);
        1717                 :            :                 }
        1718                 :            :             }
        1719                 :            :             else {
        1720                 :     129725 :                 current_arg = NULL;
        1721                 :            :             }
        1722                 :            :
        1723         [ +  + ]:     131015 :             if (current_arg) {
        1724                 :       1066 :                 msg = convertitem(current_arg, &format, p_va, flags,
        1725                 :            :                     levels, msgbuf, sizeof(msgbuf), &freelist);
        1726         [ -  + ]:       1066 :                 if (msg) {
        1727                 :          0 :                     seterror(i+1, msg, levels, fname, custom_msg);
        1728                 :          0 :                     return cleanreturn(0, &freelist);
        1729                 :            :                 }
        1730                 :       1066 :                 continue;
        1731                 :            :             }
        1732                 :            :
        1733         [ -  + ]:     129949 :             if (i < min) {
        1734         [ #  # ]:          0 :                 if (i < pos) {
        1735                 :            :                     assert (min == INT_MAX);
        1736                 :            :                     assert (max == INT_MAX);
        1737                 :          0 :                     skip = 1;
        1738                 :            :                     /* At that moment we still don't know the minimal and
        1739                 :            :                      * the maximal numbers of positional arguments.  Raising
        1740                 :            :                      * an exception is deferred until we encounter | and $
        1741                 :            :                      * or the end of the format. */
        1742                 :            :                 }
        1743                 :            :                 else {
        1744         [ #  # ]:          0 :                     PyErr_Format(PyExc_TypeError,  "%.200s%s missing required "
        1745                 :            :                                  "argument '%s' (pos %d)",
        1746                 :            :                                  (fname == NULL) ? "function" : fname,
        1747                 :            :                                  (fname == NULL) ? "" : "()",
        1748         [ #  # ]:          0 :                                  kwlist[i], i+1);
        1749                 :          0 :                     return cleanreturn(0, &freelist);
        1750                 :            :                 }
        1751                 :            :             }
        1752                 :            :             /* current code reports success when all required args
        1753                 :            :              * fulfilled and no keyword args left, with no further
        1754                 :            :              * validation. XXX Maybe skip this in debug build ?
        1755                 :            :              */
        1756   [ +  +  +  - ]:     129949 :             if (!nkwargs && !skip) {
        1757                 :     129725 :                 return cleanreturn(1, &freelist);
        1758                 :            :             }
        1759                 :            :         }
        1760                 :            :
        1761                 :            :         /* We are into optional args, skip through to any remaining
        1762                 :            :          * keyword args */
        1763                 :        224 :         msg = skipitem(&format, p_va, flags);
        1764         [ -  + ]:        224 :         if (msg) {
        1765                 :          0 :             PyErr_Format(PyExc_SystemError, "%s: '%s'", msg,
        1766                 :            :                          format);
        1767                 :          0 :             return cleanreturn(0, &freelist);
        1768                 :            :         }
        1769                 :            :     }
        1770                 :            :
        1771         [ -  + ]:        508 :     if (skip) {
        1772   [ #  #  #  # ]:          0 :         PyErr_Format(PyExc_TypeError,
        1773                 :            :                      "%.200s%s takes %s %d positional argument%s"
        1774                 :            :                      " (%zd given)",
        1775                 :            :                      (fname == NULL) ? "function" : fname,
        1776                 :            :                      (fname == NULL) ? "" : "()",
        1777         [ #  # ]:          0 :                      (Py_MIN(pos, min) < i) ? "at least" : "exactly",
        1778                 :            :                      Py_MIN(pos, min),
        1779         [ #  # ]:          0 :                      Py_MIN(pos, min) == 1 ? "" : "s",
        1780                 :            :                      nargs);
        1781                 :          0 :         return cleanreturn(0, &freelist);
        1782                 :            :     }
        1783                 :            :
        1784   [ +  -  +  -  :        508 :     if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
              -  +  -  -  -
                          - ]
        1785                 :          0 :         PyErr_Format(PyExc_SystemError,
        1786                 :            :             "more argument specifiers than keyword list entries "
        1787                 :            :             "(remaining format:'%s')", format);
        1788                 :          0 :         return cleanreturn(0, &freelist);
        1789                 :            :     }
        1790                 :            :
        1791         [ -  + ]:        508 :     if (nkwargs > 0) {
        1792                 :            :         PyObject *key;
        1793                 :            :         Py_ssize_t j;
        1794                 :            :         /* make sure there are no arguments given by name and position */
        1795         [ #  # ]:          0 :         for (i = pos; i < nargs; i++) {
        1796                 :          0 :             current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);
        1797         [ #  # ]:          0 :             if (current_arg) {
        1798                 :            :                 /* arg present in tuple and in dict */
        1799         [ #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
        1800                 :            :                              "argument for %.200s%s given by name ('%s') "
        1801                 :            :                              "and position (%d)",
        1802                 :            :                              (fname == NULL) ? "function" : fname,
        1803                 :            :                              (fname == NULL) ? "" : "()",
        1804         [ #  # ]:          0 :                              kwlist[i], i+1);
        1805                 :          0 :                 return cleanreturn(0, &freelist);
        1806                 :            :             }
        1807         [ #  # ]:          0 :             else if (PyErr_Occurred()) {
        1808                 :          0 :                 return cleanreturn(0, &freelist);
        1809                 :            :             }
        1810                 :            :         }
        1811                 :            :         /* make sure there are no extraneous keyword arguments */
        1812                 :          0 :         j = 0;
        1813         [ #  # ]:          0 :         while (PyDict_Next(kwargs, &j, &key, NULL)) {
        1814                 :          0 :             int match = 0;
        1815         [ #  # ]:          0 :             if (!PyUnicode_Check(key)) {
        1816                 :          0 :                 PyErr_SetString(PyExc_TypeError,
        1817                 :            :                                 "keywords must be strings");
        1818                 :          0 :                 return cleanreturn(0, &freelist);
        1819                 :            :             }
        1820         [ #  # ]:          0 :             for (i = pos; i < len; i++) {
        1821         [ #  # ]:          0 :                 if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) {
        1822                 :          0 :                     match = 1;
        1823                 :          0 :                     break;
        1824                 :            :                 }
        1825                 :            :             }
        1826         [ #  # ]:          0 :             if (!match) {
        1827   [ #  #  #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
        1828                 :            :                              "'%U' is an invalid keyword "
        1829                 :            :                              "argument for %.200s%s",
        1830                 :            :                              key,
        1831                 :            :                              (fname == NULL) ? "this function" : fname,
        1832                 :            :                              (fname == NULL) ? "" : "()");
        1833                 :          0 :                 return cleanreturn(0, &freelist);
        1834                 :            :             }
        1835                 :            :         }
        1836                 :            :         /* Something wrong happened. There are extraneous keyword arguments,
        1837                 :            :          * but we don't know what. And we don't bother. */
        1838   [ #  #  #  # ]:          0 :         PyErr_Format(PyExc_TypeError,
        1839                 :            :                      "invalid keyword argument for %.200s%s",
        1840                 :            :                      (fname == NULL) ? "this function" : fname,
        1841                 :            :                      (fname == NULL) ? "" : "()");
        1842                 :          0 :         return cleanreturn(0, &freelist);
        1843                 :            :     }
        1844                 :            :
        1845                 :        508 :     return cleanreturn(1, &freelist);
        1846                 :            : }
        1847                 :            :
        1848                 :            :
        1849                 :            : static int
        1850                 :         88 : scan_keywords(const char * const *keywords, int *ptotal, int *pposonly)
        1851                 :            : {
        1852                 :            :     /* scan keywords and count the number of positional-only parameters */
        1853                 :            :     int i;
        1854   [ +  -  +  + ]:         89 :     for (i = 0; keywords[i] && !*keywords[i]; i++) {
        1855                 :            :     }
        1856                 :         88 :     *pposonly = i;
        1857                 :            :
        1858                 :            :     /* scan keywords and get greatest possible nbr of args */
        1859         [ +  + ]:        517 :     for (; keywords[i]; i++) {
        1860         [ -  + ]:        429 :         if (!*keywords[i]) {
        1861                 :          0 :             PyErr_SetString(PyExc_SystemError,
        1862                 :            :                             "Empty keyword parameter name");
        1863                 :          0 :             return -1;
        1864                 :            :         }
        1865                 :            :     }
        1866                 :         88 :     *ptotal = i;
        1867                 :         88 :     return 0;
        1868                 :            : }
        1869                 :            :
        1870                 :            : static int
        1871                 :          0 : parse_format(const char *format, int total, int npos,
        1872                 :            :              const char **pfname, const char **pcustommsg,
        1873                 :            :              int *pmin, int *pmax)
        1874                 :            : {
        1875                 :            :     /* grab the function name or custom error msg first (mutually exclusive) */
        1876                 :            :     const char *custommsg;
        1877                 :          0 :     const char *fname = strchr(format, ':');
        1878         [ #  # ]:          0 :     if (fname) {
        1879                 :          0 :         fname++;
        1880                 :          0 :         custommsg = NULL;
        1881                 :            :     }
        1882                 :            :     else {
        1883                 :          0 :         custommsg = strchr(format,';');
        1884         [ #  # ]:          0 :         if (custommsg) {
        1885                 :          0 :             custommsg++;
        1886                 :            :         }
        1887                 :            :     }
        1888                 :            :
        1889                 :          0 :     int min = INT_MAX;
        1890                 :          0 :     int max = INT_MAX;
        1891         [ #  # ]:          0 :     for (int i = 0; i < total; i++) {
        1892         [ #  # ]:          0 :         if (*format == '|') {
        1893         [ #  # ]:          0 :             if (min != INT_MAX) {
        1894                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1895                 :            :                                 "Invalid format string (| specified twice)");
        1896                 :          0 :                 return -1;
        1897                 :            :             }
        1898         [ #  # ]:          0 :             if (max != INT_MAX) {
        1899                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1900                 :            :                                 "Invalid format string ($ before |)");
        1901                 :          0 :                 return -1;
        1902                 :            :             }
        1903                 :          0 :             min = i;
        1904                 :          0 :             format++;
        1905                 :            :         }
        1906         [ #  # ]:          0 :         if (*format == '$') {
        1907         [ #  # ]:          0 :             if (max != INT_MAX) {
        1908                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1909                 :            :                                 "Invalid format string ($ specified twice)");
        1910                 :          0 :                 return -1;
        1911                 :            :             }
        1912         [ #  # ]:          0 :             if (i < npos) {
        1913                 :          0 :                 PyErr_SetString(PyExc_SystemError,
        1914                 :            :                                 "Empty parameter name after $");
        1915                 :          0 :                 return -1;
        1916                 :            :             }
        1917                 :          0 :             max = i;
        1918                 :          0 :             format++;
        1919                 :            :         }
        1920   [ #  #  #  #  :          0 :         if (IS_END_OF_FORMAT(*format)) {
                       #  # ]
        1921                 :          0 :             PyErr_Format(PyExc_SystemError,
        1922                 :            :                         "More keyword list entries (%d) than "
        1923                 :            :                         "format specifiers (%d)", total, i);
        1924                 :          0 :             return -1;
        1925                 :            :         }
        1926                 :            :
        1927                 :          0 :         const char *msg = skipitem(&format, NULL, 0);
        1928         [ #  # ]:          0 :         if (msg) {
        1929                 :          0 :             PyErr_Format(PyExc_SystemError, "%s: '%s'", msg,
        1930                 :            :                         format);
        1931                 :          0 :             return -1;
        1932                 :            :         }
        1933                 :            :     }
        1934                 :          0 :     min = Py_MIN(min, total);
        1935                 :          0 :     max = Py_MIN(max, total);
        1936                 :            :
        1937   [ #  #  #  #  :          0 :     if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
              #  #  #  #  #
                          # ]
        1938                 :          0 :         PyErr_Format(PyExc_SystemError,
        1939                 :            :             "more argument specifiers than keyword list entries "
        1940                 :            :             "(remaining format:'%s')", format);
        1941                 :          0 :         return -1;
        1942                 :            :     }
        1943                 :            :
        1944                 :          0 :     *pfname = fname;
        1945                 :          0 :     *pcustommsg = custommsg;
        1946                 :          0 :     *pmin = min;
        1947                 :          0 :     *pmax = max;
        1948                 :          0 :     return 0;
        1949                 :            : }
        1950                 :            :
        1951                 :            : static PyObject *
        1952                 :         15 : new_kwtuple(const char * const *keywords, int total, int pos)
        1953                 :            : {
        1954                 :         15 :     int nkw = total - pos;
        1955                 :         15 :     PyObject *kwtuple = PyTuple_New(nkw);
        1956         [ -  + ]:         15 :     if (kwtuple == NULL) {
        1957                 :          0 :         return NULL;
        1958                 :            :     }
        1959                 :         15 :     keywords += pos;
        1960         [ +  + ]:         46 :     for (int i = 0; i < nkw; i++) {
        1961                 :         31 :         PyObject *str = PyUnicode_FromString(keywords[i]);
        1962         [ -  + ]:         31 :         if (str == NULL) {
        1963                 :          0 :             Py_DECREF(kwtuple);
        1964                 :          0 :             return NULL;
        1965                 :            :         }
        1966                 :         31 :         PyUnicode_InternInPlace(&str);
        1967                 :         31 :         PyTuple_SET_ITEM(kwtuple, i, str);
        1968                 :            :     }
        1969                 :         15 :     return kwtuple;
        1970                 :            : }
        1971                 :            :
        1972                 :            : static int
        1973                 :         88 : _parser_init(struct _PyArg_Parser *parser)
        1974                 :            : {
        1975                 :         88 :     const char * const *keywords = parser->keywords;
        1976                 :            :     assert(keywords != NULL);
        1977                 :            :     assert(parser->pos == 0 &&
        1978                 :            :            (parser->format == NULL || parser->fname == NULL) &&
        1979                 :            :            parser->custom_msg == NULL &&
        1980                 :            :            parser->min == 0 &&
        1981                 :            :            parser->max == 0);
        1982                 :            :
        1983                 :            :     int len, pos;
        1984         [ -  + ]:         88 :     if (scan_keywords(keywords, &len, &pos) < 0) {
        1985                 :          0 :         return 0;
        1986                 :            :     }
        1987                 :            :
        1988                 :         88 :     const char *fname, *custommsg = NULL;
        1989                 :         88 :     int min = 0, max = 0;
        1990         [ -  + ]:         88 :     if (parser->format) {
        1991                 :            :         assert(parser->fname == NULL);
        1992         [ #  # ]:          0 :         if (parse_format(parser->format, len, pos,
        1993                 :            :                          &fname, &custommsg, &min, &max) < 0) {
        1994                 :          0 :             return 0;
        1995                 :            :         }
        1996                 :            :     }
        1997                 :            :     else {
        1998                 :            :         assert(parser->fname != NULL);
        1999                 :         88 :         fname = parser->fname;
        2000                 :            :     }
        2001                 :            :
        2002                 :            :     int owned;
        2003                 :         88 :     PyObject *kwtuple = parser->kwtuple;
        2004         [ +  + ]:         88 :     if (kwtuple == NULL) {
        2005                 :         15 :         kwtuple = new_kwtuple(keywords, len, pos);
        2006         [ -  + ]:         15 :         if (kwtuple == NULL) {
        2007                 :          0 :             return 0;
        2008                 :            :         }
        2009                 :         15 :         owned = 1;
        2010                 :            :     }
        2011                 :            :     else {
        2012                 :         73 :         owned = 0;
        2013                 :            :     }
        2014                 :            :
        2015                 :         88 :     parser->pos = pos;
        2016                 :         88 :     parser->fname = fname;
        2017                 :         88 :     parser->custom_msg = custommsg;
        2018                 :         88 :     parser->min = min;
        2019                 :         88 :     parser->max = max;
        2020                 :         88 :     parser->kwtuple = kwtuple;
        2021         [ +  + ]:         88 :     parser->initialized = owned ? 1 : -1;
        2022                 :            :
        2023                 :            :     assert(parser->next == NULL);
        2024                 :         88 :     parser->next = _PyRuntime.getargs.static_parsers;
        2025                 :         88 :     _PyRuntime.getargs.static_parsers = parser;
        2026                 :         88 :     return 1;
        2027                 :            : }
        2028                 :            :
        2029                 :            : static int
        2030                 :       1148 : parser_init(struct _PyArg_Parser *parser)
        2031                 :            : {
        2032                 :            :     // volatile as it can be modified by other threads
        2033                 :            :     // and should not be optimized or reordered by compiler
        2034         [ +  + ]:       1148 :     if (*((volatile int *)&parser->initialized)) {
        2035                 :            :         assert(parser->kwtuple != NULL);
        2036                 :       1060 :         return 1;
        2037                 :            :     }
        2038                 :         88 :     PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK);
        2039                 :            :     // Check again if another thread initialized the parser
        2040                 :            :     // while we were waiting for the lock.
        2041         [ -  + ]:         88 :     if (*((volatile int *)&parser->initialized)) {
        2042                 :            :         assert(parser->kwtuple != NULL);
        2043                 :          0 :         PyThread_release_lock(_PyRuntime.getargs.mutex);
        2044                 :          0 :         return 1;
        2045                 :            :     }
        2046                 :         88 :     int ret = _parser_init(parser);
        2047                 :         88 :     PyThread_release_lock(_PyRuntime.getargs.mutex);
        2048                 :         88 :     return ret;
        2049                 :            : }
        2050                 :            :
        2051                 :            : static void
        2052                 :         88 : parser_clear(struct _PyArg_Parser *parser)
        2053                 :            : {
        2054         [ +  + ]:         88 :     if (parser->initialized == 1) {
        2055         [ +  - ]:         15 :         Py_CLEAR(parser->kwtuple);
        2056                 :            :     }
        2057                 :         88 : }
        2058                 :            :
        2059                 :            : static PyObject*
        2060                 :       3127 : find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key)
        2061                 :            : {
        2062                 :            :     Py_ssize_t i, nkwargs;
        2063                 :            :
        2064                 :       3127 :     nkwargs = PyTuple_GET_SIZE(kwnames);
        2065         [ +  + ]:       5443 :     for (i = 0; i < nkwargs; i++) {
        2066                 :       3726 :         PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);
        2067                 :            :
        2068                 :            :         /* kwname == key will normally find a match in since keyword keys
        2069                 :            :            should be interned strings; if not retry below in a new loop. */
        2070         [ +  + ]:       3726 :         if (kwname == key) {
        2071                 :       1410 :             return kwstack[i];
        2072                 :            :         }
        2073                 :            :     }
        2074                 :            :
        2075         [ +  + ]:       3752 :     for (i = 0; i < nkwargs; i++) {
        2076                 :       2035 :         PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);
        2077                 :            :         assert(PyUnicode_Check(kwname));
        2078         [ -  + ]:       2035 :         if (_PyUnicode_EQ(kwname, key)) {
        2079                 :          0 :             return kwstack[i];
        2080                 :            :         }
        2081                 :            :     }
        2082                 :       1717 :     return NULL;
        2083                 :            : }
        2084                 :            :
        2085                 :            : static int
        2086                 :          0 : vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
        2087                 :            :                           PyObject *kwargs, PyObject *kwnames,
        2088                 :            :                           struct _PyArg_Parser *parser,
        2089                 :            :                           va_list *p_va, int flags)
        2090                 :            : {
        2091                 :            :     PyObject *kwtuple;
        2092                 :            :     char msgbuf[512];
        2093                 :            :     int levels[32];
        2094                 :            :     const char *format;
        2095                 :            :     const char *msg;
        2096                 :            :     PyObject *keyword;
        2097                 :            :     int i, pos, len;
        2098                 :            :     Py_ssize_t nkwargs;
        2099                 :            :     PyObject *current_arg;
        2100                 :            :     freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
        2101                 :            :     freelist_t freelist;
        2102                 :          0 :     PyObject *const *kwstack = NULL;
        2103                 :            :
        2104                 :          0 :     freelist.entries = static_entries;
        2105                 :          0 :     freelist.first_available = 0;
        2106                 :          0 :     freelist.entries_malloced = 0;
        2107                 :            :
        2108                 :            :     assert(kwargs == NULL || PyDict_Check(kwargs));
        2109                 :            :     assert(kwargs == NULL || kwnames == NULL);
        2110                 :            :     assert(p_va != NULL);
        2111                 :            :
        2112         [ #  # ]:          0 :     if (parser == NULL) {
        2113                 :          0 :         PyErr_BadInternalCall();
        2114                 :          0 :         return 0;
        2115                 :            :     }
        2116                 :            :
        2117   [ #  #  #  # ]:          0 :     if (kwnames != NULL && !PyTuple_Check(kwnames)) {
        2118                 :          0 :         PyErr_BadInternalCall();
        2119                 :          0 :         return 0;
        2120                 :            :     }
        2121                 :            :
        2122         [ #  # ]:          0 :     if (!parser_init(parser)) {
        2123                 :          0 :         return 0;
        2124                 :            :     }
        2125                 :            :
        2126                 :          0 :     kwtuple = parser->kwtuple;
        2127                 :          0 :     pos = parser->pos;
        2128                 :          0 :     len = pos + (int)PyTuple_GET_SIZE(kwtuple);
        2129                 :            :
        2130         [ #  # ]:          0 :     if (len > STATIC_FREELIST_ENTRIES) {
        2131         [ #  # ]:          0 :         freelist.entries = PyMem_NEW(freelistentry_t, len);
        2132         [ #  # ]:          0 :         if (freelist.entries == NULL) {
        2133                 :          0 :             PyErr_NoMemory();
        2134                 :          0 :             return 0;
        2135                 :            :         }
        2136                 :          0 :         freelist.entries_malloced = 1;
        2137                 :            :     }
        2138                 :            :
        2139         [ #  # ]:          0 :     if (kwargs != NULL) {
        2140                 :          0 :         nkwargs = PyDict_GET_SIZE(kwargs);
        2141                 :            :     }
        2142         [ #  # ]:          0 :     else if (kwnames != NULL) {
        2143                 :          0 :         nkwargs = PyTuple_GET_SIZE(kwnames);
        2144                 :          0 :         kwstack = args + nargs;
        2145                 :            :     }
        2146                 :            :     else {
        2147                 :          0 :         nkwargs = 0;
        2148                 :            :     }
        2149         [ #  # ]:          0 :     if (nargs + nkwargs > len) {
        2150                 :            :         /* Adding "keyword" (when nargs == 0) prevents producing wrong error
        2151                 :            :            messages in some special cases (see bpo-31229). */
        2152   [ #  #  #  # ]:          0 :         PyErr_Format(PyExc_TypeError,
        2153                 :            :                      "%.200s%s takes at most %d %sargument%s (%zd given)",
        2154         [ #  # ]:          0 :                      (parser->fname == NULL) ? "function" : parser->fname,
        2155         [ #  # ]:          0 :                      (parser->fname == NULL) ? "" : "()",
        2156                 :            :                      len,
        2157                 :            :                      (nargs == 0) ? "keyword " : "",
        2158                 :            :                      (len == 1) ? "" : "s",
        2159                 :            :                      nargs + nkwargs);
        2160                 :          0 :         return cleanreturn(0, &freelist);
        2161                 :            :     }
        2162         [ #  # ]:          0 :     if (parser->max < nargs) {
        2163         [ #  # ]:          0 :         if (parser->max == 0) {
        2164                 :          0 :             PyErr_Format(PyExc_TypeError,
        2165                 :            :                          "%.200s%s takes no positional arguments",
        2166         [ #  # ]:          0 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2167         [ #  # ]:          0 :                          (parser->fname == NULL) ? "" : "()");
        2168                 :            :         }
        2169                 :            :         else {
        2170                 :          0 :             PyErr_Format(PyExc_TypeError,
        2171                 :            :                          "%.200s%s takes %s %d positional argument%s (%zd given)",
        2172         [ #  # ]:          0 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2173         [ #  # ]:          0 :                          (parser->fname == NULL) ? "" : "()",
        2174         [ #  # ]:          0 :                          (parser->min < parser->max) ? "at most" : "exactly",
        2175                 :            :                          parser->max,
        2176         [ #  # ]:          0 :                          parser->max == 1 ? "" : "s",
        2177                 :            :                          nargs);
        2178                 :            :         }
        2179                 :          0 :         return cleanreturn(0, &freelist);
        2180                 :            :     }
        2181                 :            :
        2182                 :          0 :     format = parser->format;
        2183                 :            :     assert(format != NULL || len == 0);
        2184                 :            :     /* convert tuple args and keyword args in same loop, using kwtuple to drive process */
        2185         [ #  # ]:          0 :     for (i = 0; i < len; i++) {
        2186         [ #  # ]:          0 :         if (*format == '|') {
        2187                 :          0 :             format++;
        2188                 :            :         }
        2189         [ #  # ]:          0 :         if (*format == '$') {
        2190                 :          0 :             format++;
        2191                 :            :         }
        2192                 :            :         assert(!IS_END_OF_FORMAT(*format));
        2193                 :            :
        2194         [ #  # ]:          0 :         if (i < nargs) {
        2195                 :          0 :             current_arg = args[i];
        2196                 :            :         }
        2197   [ #  #  #  # ]:          0 :         else if (nkwargs && i >= pos) {
        2198                 :          0 :             keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
        2199         [ #  # ]:          0 :             if (kwargs != NULL) {
        2200                 :          0 :                 current_arg = PyDict_GetItemWithError(kwargs, keyword);
        2201   [ #  #  #  # ]:          0 :                 if (!current_arg && PyErr_Occurred()) {
        2202                 :          0 :                     return cleanreturn(0, &freelist);
        2203                 :            :                 }
        2204                 :            :             }
        2205                 :            :             else {
        2206                 :          0 :                 current_arg = find_keyword(kwnames, kwstack, keyword);
        2207                 :            :             }
        2208         [ #  # ]:          0 :             if (current_arg) {
        2209                 :          0 :                 --nkwargs;
        2210                 :            :             }
        2211                 :            :         }
        2212                 :            :         else {
        2213                 :          0 :             current_arg = NULL;
        2214                 :            :         }
        2215                 :            :
        2216         [ #  # ]:          0 :         if (current_arg) {
        2217                 :          0 :             msg = convertitem(current_arg, &format, p_va, flags,
        2218                 :            :                 levels, msgbuf, sizeof(msgbuf), &freelist);
        2219         [ #  # ]:          0 :             if (msg) {
        2220                 :          0 :                 seterror(i+1, msg, levels, parser->fname, parser->custom_msg);
        2221                 :          0 :                 return cleanreturn(0, &freelist);
        2222                 :            :             }
        2223                 :          0 :             continue;
        2224                 :            :         }
        2225                 :            :
        2226         [ #  # ]:          0 :         if (i < parser->min) {
        2227                 :            :             /* Less arguments than required */
        2228         [ #  # ]:          0 :             if (i < pos) {
        2229                 :          0 :                 Py_ssize_t min = Py_MIN(pos, parser->min);
        2230         [ #  # ]:          0 :                 PyErr_Format(PyExc_TypeError,
        2231                 :            :                              "%.200s%s takes %s %d positional argument%s"
        2232                 :            :                              " (%zd given)",
        2233         [ #  # ]:          0 :                              (parser->fname == NULL) ? "function" : parser->fname,
        2234         [ #  # ]:          0 :                              (parser->fname == NULL) ? "" : "()",
        2235         [ #  # ]:          0 :                              min < parser->max ? "at least" : "exactly",
        2236                 :            :                              min,
        2237                 :            :                              min == 1 ? "" : "s",
        2238                 :            :                              nargs);
        2239                 :            :             }
        2240                 :            :             else {
        2241                 :          0 :                 keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
        2242                 :          0 :                 PyErr_Format(PyExc_TypeError,  "%.200s%s missing required "
        2243                 :            :                              "argument '%U' (pos %d)",
        2244         [ #  # ]:          0 :                              (parser->fname == NULL) ? "function" : parser->fname,
        2245         [ #  # ]:          0 :                              (parser->fname == NULL) ? "" : "()",
        2246                 :            :                              keyword, i+1);
        2247                 :            :             }
        2248                 :          0 :             return cleanreturn(0, &freelist);
        2249                 :            :         }
        2250                 :            :         /* current code reports success when all required args
        2251                 :            :          * fulfilled and no keyword args left, with no further
        2252                 :            :          * validation. XXX Maybe skip this in debug build ?
        2253                 :            :          */
        2254         [ #  # ]:          0 :         if (!nkwargs) {
        2255                 :          0 :             return cleanreturn(1, &freelist);
        2256                 :            :         }
        2257                 :            :
        2258                 :            :         /* We are into optional args, skip through to any remaining
        2259                 :            :          * keyword args */
        2260                 :          0 :         msg = skipitem(&format, p_va, flags);
        2261                 :            :         assert(msg == NULL);
        2262                 :            :     }
        2263                 :            :
        2264                 :            :     assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));
        2265                 :            :
        2266         [ #  # ]:          0 :     if (nkwargs > 0) {
        2267                 :            :         /* make sure there are no arguments given by name and position */
        2268         [ #  # ]:          0 :         for (i = pos; i < nargs; i++) {
        2269                 :          0 :             keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
        2270         [ #  # ]:          0 :             if (kwargs != NULL) {
        2271                 :          0 :                 current_arg = PyDict_GetItemWithError(kwargs, keyword);
        2272   [ #  #  #  # ]:          0 :                 if (!current_arg && PyErr_Occurred()) {
        2273                 :          0 :                     return cleanreturn(0, &freelist);
        2274                 :            :                 }
        2275                 :            :             }
        2276                 :            :             else {
        2277                 :          0 :                 current_arg = find_keyword(kwnames, kwstack, keyword);
        2278                 :            :             }
        2279         [ #  # ]:          0 :             if (current_arg) {
        2280                 :            :                 /* arg present in tuple and in dict */
        2281                 :          0 :                 PyErr_Format(PyExc_TypeError,
        2282                 :            :                              "argument for %.200s%s given by name ('%U') "
        2283                 :            :                              "and position (%d)",
        2284         [ #  # ]:          0 :                              (parser->fname == NULL) ? "function" : parser->fname,
        2285         [ #  # ]:          0 :                              (parser->fname == NULL) ? "" : "()",
        2286                 :            :                              keyword, i+1);
        2287                 :          0 :                 return cleanreturn(0, &freelist);
        2288                 :            :             }
        2289                 :            :         }
        2290                 :            :
        2291                 :          0 :         error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);
        2292                 :          0 :         return cleanreturn(0, &freelist);
        2293                 :            :     }
        2294                 :            :
        2295                 :          0 :     return cleanreturn(1, &freelist);
        2296                 :            : }
        2297                 :            :
        2298                 :            : static int
        2299                 :          0 : vgetargskeywordsfast(PyObject *args, PyObject *keywords,
        2300                 :            :                      struct _PyArg_Parser *parser, va_list *p_va, int flags)
        2301                 :            : {
        2302                 :            :     PyObject **stack;
        2303                 :            :     Py_ssize_t nargs;
        2304                 :            :
        2305         [ #  # ]:          0 :     if (args == NULL
        2306         [ #  # ]:          0 :         || !PyTuple_Check(args)
        2307   [ #  #  #  # ]:          0 :         || (keywords != NULL && !PyDict_Check(keywords)))
        2308                 :            :     {
        2309                 :          0 :         PyErr_BadInternalCall();
        2310                 :          0 :         return 0;
        2311                 :            :     }
        2312                 :            :
        2313                 :          0 :     stack = _PyTuple_ITEMS(args);
        2314                 :          0 :     nargs = PyTuple_GET_SIZE(args);
        2315                 :          0 :     return vgetargskeywordsfast_impl(stack, nargs, keywords, NULL,
        2316                 :            :                                      parser, p_va, flags);
        2317                 :            : }
        2318                 :            :
        2319                 :            :
        2320                 :            : #undef _PyArg_UnpackKeywords
        2321                 :            :
        2322                 :            : PyObject * const *
        2323                 :       1100 : _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
        2324                 :            :                       PyObject *kwargs, PyObject *kwnames,
        2325                 :            :                       struct _PyArg_Parser *parser,
        2326                 :            :                       int minpos, int maxpos, int minkw,
        2327                 :            :                       PyObject **buf)
        2328                 :            : {
        2329                 :            :     PyObject *kwtuple;
        2330                 :            :     PyObject *keyword;
        2331                 :            :     int i, posonly, minposonly, maxargs;
        2332         [ -  + ]:       1100 :     int reqlimit = minkw ? maxpos + minkw : minpos;
        2333                 :            :     Py_ssize_t nkwargs;
        2334                 :            :     PyObject *current_arg;
        2335                 :       1100 :     PyObject * const *kwstack = NULL;
        2336                 :            :
        2337                 :            :     assert(kwargs == NULL || PyDict_Check(kwargs));
        2338                 :            :     assert(kwargs == NULL || kwnames == NULL);
        2339                 :            :
        2340         [ -  + ]:       1100 :     if (parser == NULL) {
        2341                 :          0 :         PyErr_BadInternalCall();
        2342                 :          0 :         return NULL;
        2343                 :            :     }
        2344                 :            :
        2345   [ +  +  -  + ]:       1100 :     if (kwnames != NULL && !PyTuple_Check(kwnames)) {
        2346                 :          0 :         PyErr_BadInternalCall();
        2347                 :          0 :         return NULL;
        2348                 :            :     }
        2349                 :            :
        2350   [ -  +  -  - ]:       1100 :     if (args == NULL && nargs == 0) {
        2351                 :          0 :         args = buf;
        2352                 :            :     }
        2353                 :            :
        2354         [ -  + ]:       1100 :     if (!parser_init(parser)) {
        2355                 :          0 :         return NULL;
        2356                 :            :     }
        2357                 :            :
        2358                 :       1100 :     kwtuple = parser->kwtuple;
        2359                 :       1100 :     posonly = parser->pos;
        2360                 :       1100 :     minposonly = Py_MIN(posonly, minpos);
        2361                 :       1100 :     maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);
        2362                 :            :
        2363         [ +  + ]:       1100 :     if (kwargs != NULL) {
        2364                 :          3 :         nkwargs = PyDict_GET_SIZE(kwargs);
        2365                 :            :     }
        2366         [ +  + ]:       1097 :     else if (kwnames != NULL) {
        2367                 :       1095 :         nkwargs = PyTuple_GET_SIZE(kwnames);
        2368                 :       1095 :         kwstack = args + nargs;
        2369                 :            :     }
        2370                 :            :     else {
        2371                 :          2 :         nkwargs = 0;
        2372                 :            :     }
        2373   [ +  +  +  -  :       1100 :     if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) {
                 +  +  -  + ]
        2374                 :            :         /* Fast path. */
        2375                 :          0 :         return args;
        2376                 :            :     }
        2377         [ -  + ]:       1100 :     if (nargs + nkwargs > maxargs) {
        2378                 :            :         /* Adding "keyword" (when nargs == 0) prevents producing wrong error
        2379                 :            :            messages in some special cases (see bpo-31229). */
        2380   [ #  #  #  # ]:          0 :         PyErr_Format(PyExc_TypeError,
        2381                 :            :                      "%.200s%s takes at most %d %sargument%s (%zd given)",
        2382         [ #  # ]:          0 :                      (parser->fname == NULL) ? "function" : parser->fname,
        2383         [ #  # ]:          0 :                      (parser->fname == NULL) ? "" : "()",
        2384                 :            :                      maxargs,
        2385                 :            :                      (nargs == 0) ? "keyword " : "",
        2386                 :            :                      (maxargs == 1) ? "" : "s",
        2387                 :            :                      nargs + nkwargs);
        2388                 :          0 :         return NULL;
        2389                 :            :     }
        2390         [ +  + ]:       1100 :     if (nargs > maxpos) {
        2391         [ -  + ]:          1 :         if (maxpos == 0) {
        2392                 :          0 :             PyErr_Format(PyExc_TypeError,
        2393                 :            :                          "%.200s%s takes no positional arguments",
        2394         [ #  # ]:          0 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2395         [ #  # ]:          0 :                          (parser->fname == NULL) ? "" : "()");
        2396                 :            :         }
        2397                 :            :         else {
        2398   [ +  -  -  + ]:          3 :             PyErr_Format(PyExc_TypeError,
        2399                 :            :                          "%.200s%s takes %s %d positional argument%s (%zd given)",
        2400         [ +  - ]:          1 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2401         [ -  + ]:          1 :                          (parser->fname == NULL) ? "" : "()",
        2402                 :            :                          (minpos < maxpos) ? "at most" : "exactly",
        2403                 :            :                          maxpos,
        2404                 :            :                          (maxpos == 1) ? "" : "s",
        2405                 :            :                          nargs);
        2406                 :            :         }
        2407                 :          1 :         return NULL;
        2408                 :            :     }
        2409         [ +  + ]:       1099 :     if (nargs < minposonly) {
        2410   [ +  -  -  + ]:          3 :         PyErr_Format(PyExc_TypeError,
        2411                 :            :                      "%.200s%s takes %s %d positional argument%s"
        2412                 :            :                      " (%zd given)",
        2413         [ +  - ]:          1 :                      (parser->fname == NULL) ? "function" : parser->fname,
        2414         [ -  + ]:          1 :                      (parser->fname == NULL) ? "" : "()",
        2415                 :            :                      minposonly < maxpos ? "at least" : "exactly",
        2416                 :            :                      minposonly,
        2417                 :            :                      minposonly == 1 ? "" : "s",
        2418                 :            :                      nargs);
        2419                 :          1 :         return NULL;
        2420                 :            :     }
        2421                 :            :
        2422                 :            :     /* copy tuple args */
        2423         [ +  + ]:       2677 :     for (i = 0; i < nargs; i++) {
        2424                 :       1579 :         buf[i] = args[i];
        2425                 :            :     }
        2426                 :            :
        2427                 :            :     /* copy keyword args using kwtuple to drive process */
        2428         [ +  + ]:       4118 :     for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) {
        2429         [ +  + ]:       3929 :         if (nkwargs) {
        2430                 :       3020 :             keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
        2431         [ +  + ]:       3020 :             if (kwargs != NULL) {
        2432                 :          9 :                 current_arg = PyDict_GetItemWithError(kwargs, keyword);
        2433   [ +  +  -  + ]:          9 :                 if (!current_arg && PyErr_Occurred()) {
        2434                 :          0 :                     return NULL;
        2435                 :            :                 }
        2436                 :            :             }
        2437                 :            :             else {
        2438                 :       3011 :                 current_arg = find_keyword(kwnames, kwstack, keyword);
        2439                 :            :             }
        2440                 :            :         }
        2441         [ +  - ]:        909 :         else if (i >= reqlimit) {
        2442                 :        909 :             break;
        2443                 :            :         }
        2444                 :            :         else {
        2445                 :          0 :             current_arg = NULL;
        2446                 :            :         }
        2447                 :            :
        2448                 :       3020 :         buf[i] = current_arg;
        2449                 :            :
        2450         [ +  + ]:       3020 :         if (current_arg) {
        2451                 :       1339 :             --nkwargs;
        2452                 :            :         }
        2453   [ +  -  +  +  :       1681 :         else if (i < minpos || (maxpos <= i && i < reqlimit)) {
                       -  + ]
        2454                 :            :             /* Less arguments than required */
        2455                 :          0 :             keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
        2456                 :          0 :             PyErr_Format(PyExc_TypeError,  "%.200s%s missing required "
        2457                 :            :                          "argument '%U' (pos %d)",
        2458         [ #  # ]:          0 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2459         [ #  # ]:          0 :                          (parser->fname == NULL) ? "" : "()",
        2460                 :            :                          keyword, i+1);
        2461                 :          0 :             return NULL;
        2462                 :            :         }
        2463                 :            :     }
        2464                 :            :
        2465         [ -  + ]:       1098 :     if (nkwargs > 0) {
        2466                 :            :         /* make sure there are no arguments given by name and position */
        2467         [ #  # ]:          0 :         for (i = posonly; i < nargs; i++) {
        2468                 :          0 :             keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
        2469         [ #  # ]:          0 :             if (kwargs != NULL) {
        2470                 :          0 :                 current_arg = PyDict_GetItemWithError(kwargs, keyword);
        2471   [ #  #  #  # ]:          0 :                 if (!current_arg && PyErr_Occurred()) {
        2472                 :          0 :                     return NULL;
        2473                 :            :                 }
        2474                 :            :             }
        2475                 :            :             else {
        2476                 :          0 :                 current_arg = find_keyword(kwnames, kwstack, keyword);
        2477                 :            :             }
        2478         [ #  # ]:          0 :             if (current_arg) {
        2479                 :            :                 /* arg present in tuple and in dict */
        2480                 :          0 :                 PyErr_Format(PyExc_TypeError,
        2481                 :            :                              "argument for %.200s%s given by name ('%U') "
        2482                 :            :                              "and position (%d)",
        2483         [ #  # ]:          0 :                              (parser->fname == NULL) ? "function" : parser->fname,
        2484         [ #  # ]:          0 :                              (parser->fname == NULL) ? "" : "()",
        2485                 :            :                              keyword, i+1);
        2486                 :          0 :                 return NULL;
        2487                 :            :             }
        2488                 :            :         }
        2489                 :            :
        2490                 :          0 :         error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);
        2491                 :          0 :         return NULL;
        2492                 :            :     }
        2493                 :            :
        2494                 :       1098 :     return buf;
        2495                 :            : }
        2496                 :            :
        2497                 :            : PyObject * const *
        2498                 :         48 : _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
        2499                 :            :                                 PyObject *kwargs, PyObject *kwnames,
        2500                 :            :                                 struct _PyArg_Parser *parser,
        2501                 :            :                                 int minpos, int maxpos, int minkw,
        2502                 :            :                                 int vararg, PyObject **buf)
        2503                 :            : {
        2504                 :            :     PyObject *kwtuple;
        2505                 :            :     PyObject *keyword;
        2506                 :         48 :     Py_ssize_t varargssize = 0;
        2507                 :            :     int i, posonly, minposonly, maxargs;
        2508         [ -  + ]:         48 :     int reqlimit = minkw ? maxpos + minkw : minpos;
        2509                 :            :     Py_ssize_t nkwargs;
        2510                 :            :     PyObject *current_arg;
        2511                 :         48 :     PyObject * const *kwstack = NULL;
        2512                 :            :
        2513                 :            :     assert(kwargs == NULL || PyDict_Check(kwargs));
        2514                 :            :     assert(kwargs == NULL || kwnames == NULL);
        2515                 :            :
        2516         [ -  + ]:         48 :     if (parser == NULL) {
        2517                 :          0 :         PyErr_BadInternalCall();
        2518                 :          0 :         return NULL;
        2519                 :            :     }
        2520                 :            :
        2521   [ +  +  -  + ]:         48 :     if (kwnames != NULL && !PyTuple_Check(kwnames)) {
        2522                 :          0 :         PyErr_BadInternalCall();
        2523                 :          0 :         return NULL;
        2524                 :            :     }
        2525                 :            :
        2526   [ -  +  -  - ]:         48 :     if (args == NULL && nargs == 0) {
        2527                 :          0 :         args = buf;
        2528                 :            :     }
        2529                 :            :
        2530         [ -  + ]:         48 :     if (!parser_init(parser)) {
        2531                 :          0 :         return NULL;
        2532                 :            :     }
        2533                 :            :
        2534                 :         48 :     kwtuple = parser->kwtuple;
        2535                 :         48 :     posonly = parser->pos;
        2536                 :         48 :     minposonly = Py_MIN(posonly, minpos);
        2537                 :         48 :     maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);
        2538         [ -  + ]:         48 :     if (kwargs != NULL) {
        2539                 :          0 :         nkwargs = PyDict_GET_SIZE(kwargs);
        2540                 :            :     }
        2541         [ +  + ]:         48 :     else if (kwnames != NULL) {
        2542                 :         38 :         nkwargs = PyTuple_GET_SIZE(kwnames);
        2543                 :         38 :         kwstack = args + nargs;
        2544                 :            :     }
        2545                 :            :     else {
        2546                 :         10 :         nkwargs = 0;
        2547                 :            :     }
        2548         [ -  + ]:         48 :     if (nargs < minposonly) {
        2549   [ #  #  #  # ]:          0 :         PyErr_Format(PyExc_TypeError,
        2550                 :            :                      "%.200s%s takes %s %d positional argument%s"
        2551                 :            :                      " (%zd given)",
        2552         [ #  # ]:          0 :                      (parser->fname == NULL) ? "function" : parser->fname,
        2553         [ #  # ]:          0 :                      (parser->fname == NULL) ? "" : "()",
        2554                 :            :                      minposonly < maxpos ? "at least" : "exactly",
        2555                 :            :                      minposonly,
        2556                 :            :                      minposonly == 1 ? "" : "s",
        2557                 :            :                      nargs);
        2558                 :          0 :         return NULL;
        2559                 :            :     }
        2560                 :            :
        2561                 :            :     /* create varargs tuple */
        2562                 :         48 :     varargssize = nargs - maxpos;
        2563         [ -  + ]:         48 :     if (varargssize < 0) {
        2564                 :          0 :         varargssize = 0;
        2565                 :            :     }
        2566                 :         48 :     buf[vararg] = PyTuple_New(varargssize);
        2567         [ -  + ]:         48 :     if (!buf[vararg]) {
        2568                 :          0 :         return NULL;
        2569                 :            :     }
        2570                 :            :
        2571                 :            :     /* copy tuple args */
        2572         [ +  + ]:         94 :     for (i = 0; i < nargs; i++) {
        2573         [ +  - ]:         46 :         if (i >= vararg) {
        2574                 :         46 :             PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));
        2575                 :         46 :             continue;
        2576                 :            :         }
        2577                 :            :         else {
        2578                 :          0 :             buf[i] = args[i];
        2579                 :            :         }
        2580                 :            :     }
        2581                 :            :
        2582                 :            :     /* copy keyword args using kwtuple to drive process */
        2583         [ +  + ]:        240 :     for (i = Py_MAX((int)nargs, posonly) -
        2584                 :        240 :          Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {
        2585         [ +  + ]:        192 :         if (nkwargs) {
        2586                 :        116 :             keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
        2587         [ -  + ]:        116 :             if (kwargs != NULL) {
        2588                 :          0 :                 current_arg = PyDict_GetItemWithError(kwargs, keyword);
        2589   [ #  #  #  # ]:          0 :                 if (!current_arg && PyErr_Occurred()) {
        2590                 :          0 :                     goto exit;
        2591                 :            :                 }
        2592                 :            :             }
        2593                 :            :             else {
        2594                 :        116 :                 current_arg = find_keyword(kwnames, kwstack, keyword);
        2595                 :            :             }
        2596                 :            :         }
        2597                 :            :         else {
        2598                 :         76 :             current_arg = NULL;
        2599                 :            :         }
        2600                 :            :
        2601                 :            :         /* If an arguments is passed in as a keyword argument,
        2602                 :            :          * it should be placed before `buf[vararg]`.
        2603                 :            :          *
        2604                 :            :          * For example:
        2605                 :            :          * def f(a, /, b, *args):
        2606                 :            :          *     pass
        2607                 :            :          * f(1, b=2)
        2608                 :            :          *
        2609                 :            :          * This `buf` array should be: [1, 2, NULL].
        2610                 :            :          * In this case, nargs < vararg.
        2611                 :            :          *
        2612                 :            :          * Otherwise, we leave a place at `buf[vararg]` for vararg tuple
        2613                 :            :          * so the index is `i + 1`. */
        2614         [ -  + ]:        192 :         if (nargs < vararg) {
        2615                 :          0 :             buf[i] = current_arg;
        2616                 :            :         }
        2617                 :            :         else {
        2618                 :        192 :             buf[i + 1] = current_arg;
        2619                 :            :         }
        2620                 :            :
        2621         [ +  + ]:        192 :         if (current_arg) {
        2622                 :         74 :             --nkwargs;
        2623                 :            :         }
        2624   [ +  -  +  -  :        118 :         else if (i < minpos || (maxpos <= i && i < reqlimit)) {
                       -  + ]
        2625                 :            :             /* Less arguments than required */
        2626                 :          0 :             keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
        2627                 :          0 :             PyErr_Format(PyExc_TypeError,  "%.200s%s missing required "
        2628                 :            :                          "argument '%U' (pos %d)",
        2629         [ #  # ]:          0 :                          (parser->fname == NULL) ? "function" : parser->fname,
        2630         [ #  # ]:          0 :                          (parser->fname == NULL) ? "" : "()",
        2631                 :            :                          keyword, i+1);
        2632                 :          0 :             goto exit;
        2633                 :            :         }
        2634                 :            :     }
        2635                 :            :
        2636         [ -  + ]:         48 :     if (nkwargs > 0) {
        2637                 :          0 :         error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);
        2638                 :          0 :         goto exit;
        2639                 :            :     }
        2640                 :            :
        2641                 :         48 :     return buf;
        2642                 :            :
        2643                 :          0 : exit:
        2644                 :          0 :     Py_XDECREF(buf[vararg]);
        2645                 :          0 :     return NULL;
        2646                 :            : }
        2647                 :            :
        2648                 :            :
        2649                 :            : static const char *
        2650                 :        224 : skipitem(const char **p_format, va_list *p_va, int flags)
        2651                 :            : {
        2652                 :        224 :     const char *format = *p_format;
        2653                 :        224 :     char c = *format++;
        2654                 :            :
        2655   [ +  -  -  +  :        224 :     switch (c) {
                    -  -  - ]
        2656                 :            :
        2657                 :            :     /*
        2658                 :            :      * codes that take a single data pointer as an argument
        2659                 :            :      * (the type of the pointer is irrelevant)
        2660                 :            :      */
        2661                 :            :
        2662                 :          3 :     case 'b': /* byte -- very short int */
        2663                 :            :     case 'B': /* byte as bitfield */
        2664                 :            :     case 'h': /* short int */
        2665                 :            :     case 'H': /* short int as bitfield */
        2666                 :            :     case 'i': /* int */
        2667                 :            :     case 'I': /* int sized bitfield */
        2668                 :            :     case 'l': /* long int */
        2669                 :            :     case 'k': /* long int sized bitfield */
        2670                 :            :     case 'L': /* long long */
        2671                 :            :     case 'K': /* long long sized bitfield */
        2672                 :            :     case 'n': /* Py_ssize_t */
        2673                 :            :     case 'f': /* float */
        2674                 :            :     case 'd': /* double */
        2675                 :            :     case 'D': /* complex double */
        2676                 :            :     case 'c': /* char */
        2677                 :            :     case 'C': /* unicode char */
        2678                 :            :     case 'p': /* boolean predicate */
        2679                 :            :     case 'S': /* string object */
        2680                 :            :     case 'Y': /* string object */
        2681                 :            :     case 'U': /* unicode string object */
        2682                 :            :         {
        2683         [ +  - ]:          3 :             if (p_va != NULL) {
        2684                 :          3 :                 (void) va_arg(*p_va, void *);
        2685                 :            :             }
        2686                 :          3 :             break;
        2687                 :            :         }
        2688                 :            :
        2689                 :            :     /* string codes */
        2690                 :            :
        2691                 :          0 :     case 'e': /* string with encoding */
        2692                 :            :         {
        2693         [ #  # ]:          0 :             if (p_va != NULL) {
        2694                 :          0 :                 (void) va_arg(*p_va, const char *);
        2695                 :            :             }
        2696   [ #  #  #  # ]:          0 :             if (!(*format == 's' || *format == 't'))
        2697                 :            :                 /* after 'e', only 's' and 't' is allowed */
        2698                 :          0 :                 goto err;
        2699                 :          0 :             format++;
        2700                 :            :         }
        2701                 :            :         /* fall through */
        2702                 :            :
        2703                 :          0 :     case 's': /* string */
        2704                 :            :     case 'z': /* string or None */
        2705                 :            :     case 'y': /* bytes */
        2706                 :            :     case 'w': /* buffer, read-write */
        2707                 :            :         {
        2708         [ #  # ]:          0 :             if (p_va != NULL) {
        2709                 :          0 :                 (void) va_arg(*p_va, char **);
        2710                 :            :             }
        2711         [ #  # ]:          0 :             if (*format == '#') {
        2712         [ #  # ]:          0 :                 if (p_va != NULL) {
        2713         [ #  # ]:          0 :                     if (!(flags & FLAG_SIZE_T)) {
        2714                 :          0 :                         return "PY_SSIZE_T_CLEAN macro must be defined for '#' formats";
        2715                 :            :                     }
        2716                 :          0 :                     (void) va_arg(*p_va, Py_ssize_t *);
        2717                 :            :                 }
        2718                 :          0 :                 format++;
        2719   [ #  #  #  #  :          0 :             } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w')
                 #  #  #  # ]
        2720         [ #  # ]:          0 :                        && *format == '*')
        2721                 :            :             {
        2722                 :          0 :                 format++;
        2723                 :            :             }
        2724                 :          0 :             break;
        2725                 :            :         }
        2726                 :            :
        2727                 :        221 :     case 'O': /* object */
        2728                 :            :         {
        2729         [ -  + ]:        221 :             if (*format == '!') {
        2730                 :          0 :                 format++;
        2731         [ #  # ]:          0 :                 if (p_va != NULL) {
        2732                 :          0 :                     (void) va_arg(*p_va, PyTypeObject*);
        2733                 :          0 :                     (void) va_arg(*p_va, PyObject **);
        2734                 :            :                 }
        2735                 :            :             }
        2736         [ -  + ]:        221 :             else if (*format == '&') {
        2737                 :            :                 typedef int (*converter)(PyObject *, void *);
        2738         [ #  # ]:          0 :                 if (p_va != NULL) {
        2739                 :          0 :                     (void) va_arg(*p_va, converter);
        2740                 :          0 :                     (void) va_arg(*p_va, void *);
        2741                 :            :                 }
        2742                 :          0 :                 format++;
        2743                 :            :             }
        2744                 :            :             else {
        2745         [ +  - ]:        221 :                 if (p_va != NULL) {
        2746                 :        221 :                     (void) va_arg(*p_va, PyObject **);
        2747                 :            :                 }
        2748                 :            :             }
        2749                 :        221 :             break;
        2750                 :            :         }
        2751                 :            :
        2752                 :          0 :     case '(':           /* bypass tuple, not handled at all previously */
        2753                 :            :         {
        2754                 :            :             const char *msg;
        2755                 :            :             for (;;) {
        2756         [ #  # ]:          0 :                 if (*format==')')
        2757                 :          0 :                     break;
        2758   [ #  #  #  #  :          0 :                 if (IS_END_OF_FORMAT(*format))
                       #  # ]
        2759                 :          0 :                     return "Unmatched left paren in format "
        2760                 :            :                            "string";
        2761                 :          0 :                 msg = skipitem(&format, p_va, flags);
        2762         [ #  # ]:          0 :                 if (msg)
        2763                 :          0 :                     return msg;
        2764                 :            :             }
        2765                 :          0 :             format++;
        2766                 :          0 :             break;
        2767                 :            :         }
        2768                 :            :
        2769                 :          0 :     case ')':
        2770                 :          0 :         return "Unmatched right paren in format string";
        2771                 :            :
        2772                 :            :     default:
        2773                 :          0 : err:
        2774                 :          0 :         return "impossible<bad format char>";
        2775                 :            :
        2776                 :            :     }
        2777                 :            :
        2778                 :        224 :     *p_format = format;
        2779                 :        224 :     return NULL;
        2780                 :            : }
        2781                 :            :
        2782                 :            :
        2783                 :            : #undef _PyArg_CheckPositional
        2784                 :            :
        2785                 :            : int
        2786                 :      11414 : _PyArg_CheckPositional(const char *name, Py_ssize_t nargs,
        2787                 :            :                        Py_ssize_t min, Py_ssize_t max)
        2788                 :            : {
        2789                 :            :     assert(min >= 0);
        2790                 :            :     assert(min <= max);
        2791                 :            :
        2792         [ +  + ]:      11414 :     if (nargs < min) {
        2793         [ +  - ]:         12 :         if (name != NULL)
        2794   [ +  +  +  + ]:         12 :             PyErr_Format(
        2795                 :            :                 PyExc_TypeError,
        2796                 :            :                 "%.200s expected %s%zd argument%s, got %zd",
        2797                 :            :                 name, (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs);
        2798                 :            :         else
        2799   [ #  #  #  # ]:          0 :             PyErr_Format(
        2800                 :            :                 PyExc_TypeError,
        2801                 :            :                 "unpacked tuple should have %s%zd element%s,"
        2802                 :            :                 " but has %zd",
        2803                 :            :                 (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs);
        2804                 :         12 :         return 0;
        2805                 :            :     }
        2806                 :            :
        2807         [ +  + ]:      11402 :     if (nargs == 0) {
        2808                 :        854 :         return 1;
        2809                 :            :     }
        2810                 :            :
        2811         [ +  + ]:      10548 :     if (nargs > max) {
        2812         [ +  - ]:          4 :         if (name != NULL)
        2813   [ -  +  +  + ]:          4 :             PyErr_Format(
        2814                 :            :                 PyExc_TypeError,
        2815                 :            :                 "%.200s expected %s%zd argument%s, got %zd",
        2816                 :            :                 name, (min == max ? "" : "at most "), max, max == 1 ? "" : "s", nargs);
        2817                 :            :         else
        2818   [ #  #  #  # ]:          0 :             PyErr_Format(
        2819                 :            :                 PyExc_TypeError,
        2820                 :            :                 "unpacked tuple should have %s%zd element%s,"
        2821                 :            :                 " but has %zd",
        2822                 :            :                 (min == max ? "" : "at most "), max, max == 1 ? "" : "s", nargs);
        2823                 :          4 :         return 0;
        2824                 :            :     }
        2825                 :            :
        2826                 :      10544 :     return 1;
        2827                 :            : }
        2828                 :            :
        2829                 :            : static int
        2830                 :      11398 : unpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name,
        2831                 :            :              Py_ssize_t min, Py_ssize_t max, va_list vargs)
        2832                 :            : {
        2833                 :            :     Py_ssize_t i;
        2834                 :            :     PyObject **o;
        2835                 :            :
        2836         [ -  + ]:      11398 :     if (!_PyArg_CheckPositional(name, nargs, min, max)) {
        2837                 :          0 :         return 0;
        2838                 :            :     }
        2839                 :            :
        2840         [ +  + ]:      28417 :     for (i = 0; i < nargs; i++) {
        2841                 :      17019 :         o = va_arg(vargs, PyObject **);
        2842                 :      17019 :         *o = args[i];
        2843                 :            :     }
        2844                 :      11398 :     return 1;
        2845                 :            : }
        2846                 :            :
        2847                 :            : int
        2848                 :      10321 : PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
        2849                 :            : {
        2850                 :            :     PyObject **stack;
        2851                 :            :     Py_ssize_t nargs;
        2852                 :            :     int retval;
        2853                 :            :     va_list vargs;
        2854                 :            :
        2855         [ -  + ]:      10321 :     if (!PyTuple_Check(args)) {
        2856                 :          0 :         PyErr_SetString(PyExc_SystemError,
        2857                 :            :             "PyArg_UnpackTuple() argument list is not a tuple");
        2858                 :          0 :         return 0;
        2859                 :            :     }
        2860                 :      10321 :     stack = _PyTuple_ITEMS(args);
        2861                 :      10321 :     nargs = PyTuple_GET_SIZE(args);
        2862                 :            :
        2863                 :      10321 :     va_start(vargs, max);
        2864                 :      10321 :     retval = unpack_stack(stack, nargs, name, min, max, vargs);
        2865                 :      10321 :     va_end(vargs);
        2866                 :      10321 :     return retval;
        2867                 :            : }
        2868                 :            :
        2869                 :            : int
        2870                 :       1077 : _PyArg_UnpackStack(PyObject *const *args, Py_ssize_t nargs, const char *name,
        2871                 :            :                    Py_ssize_t min, Py_ssize_t max, ...)
        2872                 :            : {
        2873                 :            :     int retval;
        2874                 :            :     va_list vargs;
        2875                 :            :
        2876                 :       1077 :     va_start(vargs, max);
        2877                 :       1077 :     retval = unpack_stack(args, nargs, name, min, max, vargs);
        2878                 :       1077 :     va_end(vargs);
        2879                 :       1077 :     return retval;
        2880                 :            : }
        2881                 :            :
        2882                 :            :
        2883                 :            : #undef _PyArg_NoKeywords
        2884                 :            : #undef _PyArg_NoKwnames
        2885                 :            : #undef _PyArg_NoPositional
        2886                 :            :
        2887                 :            : /* For type constructors that don't take keyword args
        2888                 :            :  *
        2889                 :            :  * Sets a TypeError and returns 0 if the args/kwargs is
        2890                 :            :  * not empty, returns 1 otherwise
        2891                 :            :  */
        2892                 :            : int
        2893                 :          0 : _PyArg_NoKeywords(const char *funcname, PyObject *kwargs)
        2894                 :            : {
        2895         [ #  # ]:          0 :     if (kwargs == NULL) {
        2896                 :          0 :         return 1;
        2897                 :            :     }
        2898         [ #  # ]:          0 :     if (!PyDict_CheckExact(kwargs)) {
        2899                 :          0 :         PyErr_BadInternalCall();
        2900                 :          0 :         return 0;
        2901                 :            :     }
        2902         [ #  # ]:          0 :     if (PyDict_GET_SIZE(kwargs) == 0) {
        2903                 :          0 :         return 1;
        2904                 :            :     }
        2905                 :            :
        2906                 :          0 :     PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
        2907                 :            :                     funcname);
        2908                 :          0 :     return 0;
        2909                 :            : }
        2910                 :            :
        2911                 :            : int
        2912                 :          0 : _PyArg_NoPositional(const char *funcname, PyObject *args)
        2913                 :            : {
        2914         [ #  # ]:          0 :     if (args == NULL)
        2915                 :          0 :         return 1;
        2916         [ #  # ]:          0 :     if (!PyTuple_CheckExact(args)) {
        2917                 :          0 :         PyErr_BadInternalCall();
        2918                 :          0 :         return 0;
        2919                 :            :     }
        2920         [ #  # ]:          0 :     if (PyTuple_GET_SIZE(args) == 0)
        2921                 :          0 :         return 1;
        2922                 :            :
        2923                 :          0 :     PyErr_Format(PyExc_TypeError, "%.200s() takes no positional arguments",
        2924                 :            :                     funcname);
        2925                 :          0 :     return 0;
        2926                 :            : }
        2927                 :            :
        2928                 :            : int
        2929                 :          0 : _PyArg_NoKwnames(const char *funcname, PyObject *kwnames)
        2930                 :            : {
        2931         [ #  # ]:          0 :     if (kwnames == NULL) {
        2932                 :          0 :         return 1;
        2933                 :            :     }
        2934                 :            :
        2935                 :            :     assert(PyTuple_CheckExact(kwnames));
        2936                 :            :
        2937         [ #  # ]:          0 :     if (PyTuple_GET_SIZE(kwnames) == 0) {
        2938                 :          0 :         return 1;
        2939                 :            :     }
        2940                 :            :
        2941                 :          0 :     PyErr_Format(PyExc_TypeError, "%s() takes no keyword arguments", funcname);
        2942                 :          0 :     return 0;
        2943                 :            : }
        2944                 :            :
        2945                 :            : void
        2946                 :         25 : _PyArg_Fini(void)
        2947                 :            : {
        2948                 :         25 :     struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers;
        2949         [ +  + ]:        113 :     while (s) {
        2950                 :         88 :         tmp = s->next;
        2951                 :         88 :         s->next = NULL;
        2952                 :         88 :         parser_clear(s);
        2953                 :         88 :         s = tmp;
        2954                 :            :     }
        2955                 :         25 :     _PyRuntime.getargs.static_parsers = NULL;
        2956                 :         25 : }
        2957                 :            :
        2958                 :            : #ifdef __cplusplus
        2959                 :            : };
        2960                 :            : #endif

Generated by: LCOV version 1.14