1771 lines · 41.9 KB · C
RawDownload
 /* New getargs implementation */ #include "Python.h" #include <ctype.h>  #ifdef __cplusplusextern "C" { #endifint PyArg_Parse(PyObject *, const char *, ...);int PyArg_ParseTuple(PyObject *, const char *, ...);int PyArg_VaParse(PyObject *, const char *, va_list); int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,				const char *, char **, ...);int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,				const char *, char **, va_list); #ifdef HAVE_DECLSPEC_DLL/* Export functions */PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, char *, ...);PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, char *, ...);PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,                                                  const char *, char **, ...);PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, char *, va_list);PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,                                              const char *, char **, va_list);#endif #define FLAG_COMPAT 1#define FLAG_SIZE_T 2  /* Forward */static int vgetargs1(PyObject *, const char *, va_list *, int);static void seterror(int, const char *, int *, const char *, const char *);static char *convertitem(PyObject *, const char **, va_list *, int, int *,                          char *, size_t, PyObject **);static char *converttuple(PyObject *, const char **, va_list *, int,			  int *, char *, size_t, int, PyObject **);static char *convertsimple(PyObject *, const char **, va_list *, int, char *,			   size_t, PyObject **);static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int vgetargskeywords(PyObject *, PyObject *,			    const char *, char **, va_list *, int);static char *skipitem(const char **, va_list *, int); intPyArg_Parse(PyObject *args, const char *format, ...){	int retval;	va_list va;		va_start(va, format);	retval = vgetargs1(args, format, &va, FLAG_COMPAT);	va_end(va);	return retval;} int_PyArg_Parse_SizeT(PyObject *args, char *format, ...){	int retval;	va_list va;		va_start(va, format);	retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T);	va_end(va);	return retval;}  intPyArg_ParseTuple(PyObject *args, const char *format, ...){	int retval;	va_list va;		va_start(va, format);	retval = vgetargs1(args, format, &va, 0);	va_end(va);	return retval;} int_PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...){	int retval;	va_list va;		va_start(va, format);	retval = vgetargs1(args, format, &va, FLAG_SIZE_T);	va_end(va);	return retval;}  intPyArg_VaParse(PyObject *args, const char *format, va_list va){	va_list lva; #ifdef VA_LIST_IS_ARRAY	memcpy(lva, va, sizeof(va_list));#else#ifdef __va_copy	__va_copy(lva, va);#else	lva = va;#endif#endif 	return vgetargs1(args, format, &lva, 0);} int_PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va){	va_list lva; #ifdef VA_LIST_IS_ARRAY	memcpy(lva, va, sizeof(va_list));#else#ifdef __va_copy	__va_copy(lva, va);#else	lva = va;#endif#endif 	return vgetargs1(args, format, &lva, FLAG_SIZE_T);}  /* Handle cleanup of allocated memory in case of exception */ static intaddcleanup(void *ptr, PyObject **freelist){	PyObject *cobj;	if (!*freelist) {		*freelist = PyList_New(0);		if (!*freelist) {			PyMem_FREE(ptr);			return -1;		}	}	cobj = PyCObject_FromVoidPtr(ptr, NULL);	if (!cobj) {		PyMem_FREE(ptr);		return -1;	}	if(PyList_Append(*freelist, cobj)) {                PyMem_FREE(ptr);		Py_DECREF(cobj);		return -1;	}        Py_DECREF(cobj);	return 0;} static intcleanreturn(int retval, PyObject *freelist){	if(freelist) {		if((retval) == 0) {			Py_ssize_t len = PyList_GET_SIZE(freelist), i;			for (i = 0; i < len; i++)                                PyMem_FREE(PyCObject_AsVoidPtr(                                		PyList_GET_ITEM(freelist, i)));		}		Py_DECREF(freelist);	}	return retval;}  static intvgetargs1(PyObject *args, const char *format, va_list *p_va, int flags){	char msgbuf[256];	int levels[32];	const char *fname = NULL;	const char *message = NULL;	int min = -1;	int max = 0;	int level = 0;	int endfmt = 0;	const char *formatsave = format;	Py_ssize_t i, len;	char *msg;	PyObject *freelist = NULL;	int compat = flags & FLAG_COMPAT; 	assert(compat || (args != (PyObject*)NULL));	flags = flags & ~FLAG_COMPAT; 	while (endfmt == 0) {		int c = *format++;		switch (c) {		case '(':			if (level == 0)				max++;			level++;			if (level >= 30)				Py_FatalError("too many tuple nesting levels "					      "in argument format string");			break;		case ')':			if (level == 0)				Py_FatalError("excess ')' in getargs format");			else				level--;			break;		case '\0':			endfmt = 1;			break;		case ':':			fname = format;			endfmt = 1;			break;		case ';':			message = format;			endfmt = 1;			break;		default:			if (level == 0) {				if (c == 'O')					max++;				else if (isalpha(Py_CHARMASK(c))) {					if (c != 'e') /* skip encoded */						max++;				} else if (c == '|')					min = max;			}			break;		}	}		if (level != 0)		Py_FatalError(/* '(' */ "missing ')' in getargs format");		if (min < 0)		min = max;		format = formatsave;		if (compat) {		if (max == 0) {			if (args == NULL)				return 1;			PyOS_snprintf(msgbuf, sizeof(msgbuf),				      "%.200s%s takes no arguments",				      fname==NULL ? "function" : fname,				      fname==NULL ? "" : "()");			PyErr_SetString(PyExc_TypeError, msgbuf);			return 0;		}		else if (min == 1 && max == 1) {			if (args == NULL) {				PyOS_snprintf(msgbuf, sizeof(msgbuf),				      "%.200s%s takes at least one argument",					      fname==NULL ? "function" : fname,					      fname==NULL ? "" : "()");				PyErr_SetString(PyExc_TypeError, msgbuf);				return 0;			}			msg = convertitem(args, &format, p_va, flags, levels, 					  msgbuf, sizeof(msgbuf), &freelist);			if (msg == NULL)				return cleanreturn(1, freelist);			seterror(levels[0], msg, levels+1, fname, message);			return cleanreturn(0, freelist);		}		else {			PyErr_SetString(PyExc_SystemError,			    "old style getargs format uses new features");			return 0;		}	}		if (!PyTuple_Check(args)) {		PyErr_SetString(PyExc_SystemError,		    "new style getargs format but argument is not a tuple");		return 0;	}		len = PyTuple_GET_SIZE(args);		if (len < min || max < len) {		if (message == NULL) {			PyOS_snprintf(msgbuf, sizeof(msgbuf),				      "%.150s%s takes %s %d argument%s "				      "(%ld given)",				      fname==NULL ? "function" : fname,				      fname==NULL ? "" : "()",				      min==max ? "exactly"				      : len < min ? "at least" : "at most",				      len < min ? min : max,				      (len < min ? min : max) == 1 ? "" : "s",				      Py_SAFE_DOWNCAST(len, Py_ssize_t, long));			message = msgbuf;		}		PyErr_SetString(PyExc_TypeError, message);		return 0;	}		for (i = 0; i < len; i++) {		if (*format == '|')			format++;		msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,				  flags, levels, msgbuf, 				  sizeof(msgbuf), &freelist);		if (msg) {			seterror(i+1, msg, levels, fname, message);			return cleanreturn(0, freelist);		}	} 	if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) &&	    *format != '(' &&	    *format != '|' && *format != ':' && *format != ';') {		PyErr_Format(PyExc_SystemError,			     "bad format string: %.200s", formatsave);		return cleanreturn(0, freelist);	}		return cleanreturn(1, freelist);}   static voidseterror(int iarg, const char *msg, int *levels, const char *fname,         const char *message){	char buf[512];	int i;	char *p = buf; 	if (PyErr_Occurred())		return;	else if (message == NULL) {		if (fname != NULL) {			PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname);			p += strlen(p);		}		if (iarg != 0) {			PyOS_snprintf(p, sizeof(buf) - (p - buf),				      "argument %d", iarg);			i = 0;			p += strlen(p);			while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) {				PyOS_snprintf(p, sizeof(buf) - (p - buf),					      ", item %d", levels[i]-1);				p += strlen(p);				i++;			}		}		else {			PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument");			p += strlen(p);		}		PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg);		message = buf;	}	PyErr_SetString(PyExc_TypeError, message);}  /* Convert a tuple argument.   On entry, *p_format points to the character _after_ the opening '('.   On successful exit, *p_format points to the closing ')'.   If successful:      *p_format and *p_va are updated,      *levels and *msgbuf are untouched,      and NULL is returned.   If the argument is invalid:      *p_format is unchanged,      *p_va is undefined,      *levels is a 0-terminated list of item numbers,      *msgbuf contains an error message, whose format is:         "must be <typename1>, not <typename2>", where:            <typename1> is the name of the expected type, and            <typename2> is the name of the actual type,      and msgbuf is returned.*/ static char *converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,             int *levels, char *msgbuf, size_t bufsize, int toplevel,              PyObject **freelist){	int level = 0;	int n = 0;	const char *format = *p_format;	int i;		for (;;) {		int c = *format++;		if (c == '(') {			if (level == 0)				n++;			level++;		}		else if (c == ')') {			if (level == 0)				break;			level--;		}		else if (c == ':' || c == ';' || c == '\0')			break;		else if (level == 0 && isalpha(Py_CHARMASK(c)))			n++;	}		if (!PySequence_Check(arg) || PyString_Check(arg)) {		levels[0] = 0;		PyOS_snprintf(msgbuf, bufsize,			      toplevel ? "expected %d arguments, not %.50s" :			              "must be %d-item sequence, not %.50s",			      n, 			      arg == Py_None ? "None" : arg->ob_type->tp_name);		return msgbuf;	}		if ((i = PySequence_Size(arg)) != n) {		levels[0] = 0;		PyOS_snprintf(msgbuf, bufsize,			      toplevel ? "expected %d arguments, not %d" :			             "must be sequence of length %d, not %d",			      n, i);		return msgbuf;	} 	format = *p_format;	for (i = 0; i < n; i++) {		char *msg;		PyObject *item;		item = PySequence_GetItem(arg, i);		if (item == NULL) {			PyErr_Clear();			levels[0] = i+1;			levels[1] = 0;			strncpy(msgbuf, "is not retrievable", bufsize);			return msgbuf;		}		msg = convertitem(item, &format, p_va, flags, levels+1, 				  msgbuf, bufsize, freelist);		/* PySequence_GetItem calls tp->sq_item, which INCREFs */		Py_XDECREF(item);		if (msg != NULL) {			levels[0] = i+1;			return msg;		}	} 	*p_format = format;	return NULL;}  /* Convert a single item. */ static char *convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags,            int *levels, char *msgbuf, size_t bufsize, PyObject **freelist){	char *msg;	const char *format = *p_format;		if (*format == '(' /* ')' */) {		format++;		msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, 				   bufsize, 0, freelist);		if (msg == NULL)			format++;	}	else {		msg = convertsimple(arg, &format, p_va, flags, 				    msgbuf, bufsize, freelist);		if (msg != NULL)			levels[0] = 0;	}	if (msg == NULL)		*p_format = format;	return msg;}   #define UNICODE_DEFAULT_ENCODING(arg) \        _PyUnicode_AsDefaultEncodedString(arg, NULL) /* Format an error message generated by convertsimple(). */ 

Lines 1–500 of 1771.