mirror of
https://github.com/python/cpython.git
synced 2025-09-06 08:51:39 +00:00
* Python/{modsupport.c,getargs.c,Makefile.in},
Include/modsupport.h: moved getargs() to its own file and re-implemented it entirely to support optional arguments, multiple arguments without surrounding parentheses (when called as newgetargs()), and better error messages
This commit is contained in:
parent
6989e54ebf
commit
fe3f1a256b
3 changed files with 588 additions and 341 deletions
|
@ -25,7 +25,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* Module support implementation */
|
||||
|
||||
#include "allobjects.h"
|
||||
#include "modsupport.h"
|
||||
#include "import.h"
|
||||
|
||||
#ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
|
||||
|
@ -111,345 +110,6 @@ static int countformat(format, endchar)
|
|||
}
|
||||
|
||||
|
||||
/* Generic argument list parser */
|
||||
|
||||
static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
|
||||
static int
|
||||
do_arg(arg, p_format, p_va)
|
||||
object *arg;
|
||||
char** p_format;
|
||||
va_list *p_va;
|
||||
{
|
||||
char *format = *p_format;
|
||||
|
||||
if (arg == NULL)
|
||||
return 0; /* Incomplete tuple or list */
|
||||
|
||||
switch (*format++) {
|
||||
|
||||
case '(': /* tuple, distributed over C parameters */ {
|
||||
int i, n;
|
||||
if (!is_tupleobject(arg))
|
||||
return 0;
|
||||
n = gettuplesize(arg);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!do_arg(gettupleitem(arg, i), &format, p_va))
|
||||
return 0;
|
||||
}
|
||||
if (*format++ != ')')
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case ')': /* End of format -- too many arguments */
|
||||
return 0;
|
||||
|
||||
case 'b': /* byte -- very short int */ {
|
||||
char *p = va_arg(*p_va, char *);
|
||||
long ival = getintvalue(arg);
|
||||
if (ival == -1 && err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h': /* short int */ {
|
||||
short *p = va_arg(*p_va, short *);
|
||||
long ival = getintvalue(arg);
|
||||
if (ival == -1 && err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i': /* int */ {
|
||||
int *p = va_arg(*p_va, int *);
|
||||
long ival = getintvalue(arg);
|
||||
if (ival == -1 && err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l': /* long int */ {
|
||||
long *p = va_arg(*p_va, long *);
|
||||
long ival = getintvalue(arg);
|
||||
if (ival == -1 && err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f': /* float */ {
|
||||
float *p = va_arg(*p_va, float *);
|
||||
double dval = getfloatvalue(arg);
|
||||
if (err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = dval;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd': /* double */ {
|
||||
double *p = va_arg(*p_va, double *);
|
||||
double dval = getfloatvalue(arg);
|
||||
if (err_occurred())
|
||||
return 0;
|
||||
else
|
||||
*p = dval;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c': /* char */ {
|
||||
char *p = va_arg(*p_va, char *);
|
||||
if (is_stringobject(arg) && getstringsize(arg) == 1)
|
||||
*p = getstringvalue(arg)[0];
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': /* string */ {
|
||||
char **p = va_arg(*p_va, char **);
|
||||
if (is_stringobject(arg))
|
||||
*p = getstringvalue(arg);
|
||||
else
|
||||
return 0;
|
||||
if (*format == '#') {
|
||||
int *q = va_arg(*p_va, int *);
|
||||
*q = getstringsize(arg);
|
||||
format++;
|
||||
}
|
||||
else if (strlen(*p) != getstringsize(arg)) {
|
||||
err_setstr(ValueError, "embedded '\\0' in string arg");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z': /* string, may be NULL (None) */ {
|
||||
char **p = va_arg(*p_va, char **);
|
||||
if (arg == None)
|
||||
*p = 0;
|
||||
else if (is_stringobject(arg))
|
||||
*p = getstringvalue(arg);
|
||||
else
|
||||
return 0;
|
||||
if (*format == '#') {
|
||||
int *q = va_arg(*p_va, int *);
|
||||
if (arg == None)
|
||||
*q = 0;
|
||||
else
|
||||
*q = getstringsize(arg);
|
||||
format++;
|
||||
}
|
||||
else if (*p != NULL && strlen(*p) != getstringsize(arg)) {
|
||||
err_setstr(ValueError, "embedded '\\0' in string arg");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'S': /* string object */ {
|
||||
object **p = va_arg(*p_va, object **);
|
||||
if (is_stringobject(arg))
|
||||
*p = arg;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O': /* object */ {
|
||||
typeobject *type;
|
||||
object **p;
|
||||
if (*format == '!') {
|
||||
format++;
|
||||
type = va_arg(*p_va, typeobject*);
|
||||
if (arg->ob_type != type)
|
||||
return 0;
|
||||
else {
|
||||
p = va_arg(*p_va, object **);
|
||||
*p = arg;
|
||||
}
|
||||
}
|
||||
else if (*format == '?') {
|
||||
inquiry pred = va_arg(*p_va, inquiry);
|
||||
format++;
|
||||
if ((*pred)(arg)) {
|
||||
p = va_arg(*p_va, object **);
|
||||
*p = arg;
|
||||
}
|
||||
}
|
||||
else if (*format == '&') {
|
||||
binaryfunc convert = va_arg(*p_va, binaryfunc);
|
||||
void *addr = va_arg(*p_va, void *);
|
||||
format++;
|
||||
if (! (*convert)(arg, addr))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
p = va_arg(*p_va, object **);
|
||||
*p = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "bad do_arg format: x%x '%c'\n",
|
||||
format[-1], format[-1]);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
*p_format = format;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_STDARG_PROTOTYPES
|
||||
/* VARARGS2 */
|
||||
int getargs(object *arg, char *format, ...)
|
||||
#else
|
||||
/* VARARGS */
|
||||
int getargs(va_alist) va_dcl
|
||||
#endif
|
||||
{
|
||||
char *f;
|
||||
int ok;
|
||||
va_list va;
|
||||
#ifdef HAVE_STDARG_PROTOTYPES
|
||||
|
||||
va_start(va, format);
|
||||
#else
|
||||
object *arg;
|
||||
char *format;
|
||||
|
||||
va_start(va);
|
||||
arg = va_arg(va, object *);
|
||||
format = va_arg(va, char *);
|
||||
#endif
|
||||
if (*format == '\0' || *format == ';') {
|
||||
va_end(va);
|
||||
if (arg != NULL) {
|
||||
char *str = "no arguments needed";
|
||||
if (*format == ';')
|
||||
str = format+1;
|
||||
err_setstr(TypeError, str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = format;
|
||||
ok = do_arg(arg, &f, &va) && (*f == '\0' || *f == ';');
|
||||
va_end(va);
|
||||
if (!ok) {
|
||||
if (!err_occurred()) {
|
||||
char buf[256];
|
||||
char *str;
|
||||
f = strchr(format, ';');
|
||||
if (f != NULL)
|
||||
str = f+1;
|
||||
else {
|
||||
sprintf(buf, "bad argument list (format '%s')",
|
||||
format);
|
||||
str = buf;
|
||||
}
|
||||
err_setstr(TypeError, str);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
#ifdef UNUSED
|
||||
|
||||
int
|
||||
getlongtuplearg(args, a, n)
|
||||
object *args;
|
||||
long *a; /* [n] */
|
||||
int n;
|
||||
{
|
||||
int i;
|
||||
if (!is_tupleobject(args) || gettuplesize(args) != n) {
|
||||
return err_badarg();
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
object *v = gettupleitem(args, i);
|
||||
if (!is_intobject(v)) {
|
||||
return err_badarg();
|
||||
}
|
||||
a[i] = getintvalue(v);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
getshorttuplearg(args, a, n)
|
||||
object *args;
|
||||
short *a; /* [n] */
|
||||
int n;
|
||||
{
|
||||
int i;
|
||||
if (!is_tupleobject(args) || gettuplesize(args) != n) {
|
||||
return err_badarg();
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
object *v = gettupleitem(args, i);
|
||||
if (!is_intobject(v)) {
|
||||
return err_badarg();
|
||||
}
|
||||
a[i] = getintvalue(v);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
getlonglistarg(args, a, n)
|
||||
object *args;
|
||||
long *a; /* [n] */
|
||||
int n;
|
||||
{
|
||||
int i;
|
||||
if (!is_listobject(args) || getlistsize(args) != n) {
|
||||
return err_badarg();
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
object *v = getlistitem(args, i);
|
||||
if (!is_intobject(v)) {
|
||||
return err_badarg();
|
||||
}
|
||||
a[i] = getintvalue(v);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
getshortlistarg(args, a, n)
|
||||
object *args;
|
||||
short *a; /* [n] */
|
||||
int n;
|
||||
{
|
||||
int i;
|
||||
if (!is_listobject(args) || getlistsize(args) != n) {
|
||||
return err_badarg();
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
object *v = getlistitem(args, i);
|
||||
if (!is_intobject(v)) {
|
||||
return err_badarg();
|
||||
}
|
||||
a[i] = getintvalue(v);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* UNUSED */
|
||||
|
||||
|
||||
/* Generic function to create a value -- the inverse of getargs() */
|
||||
/* After an original idea and first implementation by Steven Miale */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue