1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* New getargs implementation */
27 /* XXX There are several unchecked sprintf or strcat calls in this file.
28 XXX The only way these can become a danger is if some C code in the
29 XXX Python source (or in an extension) uses ridiculously long names
30 XXX or riduculously deep nesting in format strings. */
32 #include "allobjects.h"
35 int getargs
PROTO((object
*, char *, ...));
36 int newgetargs
PROTO((object
*, char *, ...));
37 int vgetargs
PROTO((object
*, char *, va_list));
41 static int vgetargs1
PROTO((object
*, char *, va_list *, int));
42 static void seterror
PROTO((int, char *, int *, char *, char *));
43 static char *convertitem
PROTO((object
*, char **, va_list *, int *, char *));
44 static char *converttuple
PROTO((object
*, char **, va_list *,
46 static char *convertsimple
PROTO((object
*, char **, va_list *, char *));
47 static char *convertsimple1
PROTO((object
*, char **, va_list *));
50 #ifdef HAVE_STDARG_PROTOTYPES
52 int getargs(object
*args
, char *format
, ...)
55 int getargs(va_alist
) va_dcl
60 #ifdef HAVE_STDARG_PROTOTYPES
68 args
= va_arg(va
, object
*);
69 format
= va_arg(va
, char *);
71 retval
= vgetargs1(args
, format
, &va
, 1);
77 #ifdef HAVE_STDARG_PROTOTYPES
79 int newgetargs(object
*args
, char *format
, ...)
82 int newgetargs(va_alist
) va_dcl
87 #ifdef HAVE_STDARG_PROTOTYPES
95 args
= va_arg(va
, object
*);
96 format
= va_arg(va
, char *);
98 retval
= vgetargs1(args
, format
, &va
, 0);
105 vgetargs(args
, format
, va
)
112 #ifdef VA_LIST_IS_ARRAY
113 memcpy(lva
, va
, sizeof(va_list));
118 return vgetargs1(args
, format
, &lva
, 0);
123 vgetargs1(args
, format
, p_va
, compat
)
132 char *message
= NULL
;
136 char *formatsave
= format
;
142 if (c
== '(' /* ')' */) {
147 else if (/* '(' */ c
== ')') {
150 "excess ')' in getargs format");
173 fatal(/* '(' */ "missing ')' in getargs format");
184 sprintf(msgbuf
, "%s requires no arguments",
185 fname
==NULL
? "function" : fname
);
186 err_setstr(TypeError
, msgbuf
);
189 else if (min
== 1 && max
== 1) {
192 "%s requires at least one argument",
193 fname
==NULL
? "function" : fname
);
194 err_setstr(TypeError
, msgbuf
);
197 msg
= convertitem(args
, &format
, p_va
, levels
, msgbuf
);
200 seterror(levels
[0], msg
, levels
+1, fname
, message
);
204 err_setstr(SystemError
,
205 "old style getargs format uses new features");
210 if (!is_tupleobject(args
)) {
211 err_setstr(SystemError
,
212 "new style getargs format but argument is not a tuple");
216 len
= gettuplesize(args
);
218 if (len
< min
|| max
< len
) {
219 if (message
== NULL
) {
221 "%s requires %s %d argument%s; %d given",
222 fname
==NULL
? "function" : fname
,
224 : len
< min
? "at least" : "at most",
225 len
< min
? min
: max
,
226 (len
< min
? min
: max
) == 1 ? "" : "s",
230 err_setstr(TypeError
, message
);
234 for (i
= 0; i
< len
; i
++) {
237 msg
= convertitem(gettupleitem(args
, i
), &format
, p_va
,
240 seterror(i
+1, msg
, levels
, fname
, message
);
251 seterror(iarg
, msg
, levels
, fname
, message
)
264 if (iarg
== 0 && message
== NULL
)
266 else if (message
== NULL
) {
268 sprintf(p
, "%s, ", fname
);
271 sprintf(p
, "argument %d", iarg
);
274 while (levels
[i
] > 0) {
275 sprintf(p
, ", item %d", levels
[i
]-1);
279 sprintf(p
, ": expected %s found", msg
);
282 err_setstr(TypeError
, message
);
286 /* Convert a tuple argument.
287 On entry, *p_format points to the character _after_ the opening '('.
288 On successful exit, *p_format points to the closing ')'.
290 *p_format and *p_va are updated,
291 *levels and *msgbuf are untouched,
292 and NULL is returned.
293 If the argument is invalid:
294 *p_format is unchanged,
296 *levels is a 0-terminated list of item numbers,
297 *msgbuf contains an error message, whose format is:
298 "<typename1>, <typename2>", where:
299 <typename1> is the name of the expected type, and
300 <typename2> is the name of the actual type,
301 (so you can surround it by "expected ... found"),
302 and msgbuf is returned.
306 converttuple(arg
, p_format
, p_va
, levels
, msgbuf
, toplevel
)
316 char *format
= *p_format
;
331 else if (c
== ':' || c
== ';' || c
== '\0')
333 else if (level
== 0 && isalpha(c
))
337 if (!is_tupleobject(arg
)) {
340 toplevel
? "%d arguments, %s" : "%d-tuple, %s",
341 n
, arg
== None
? "None" : arg
->ob_type
->tp_name
);
345 if ((i
= gettuplesize(arg
)) != n
) {
348 toplevel
? "%d arguments, %d" : "%d-tuple, %d-tuple",
354 for (i
= 0; i
< n
; i
++) {
356 msg
= convertitem(gettupleitem(arg
, i
), &format
, p_va
,
369 /* Convert a single item. */
372 convertitem(arg
, p_format
, p_va
, levels
, msgbuf
)
380 char *format
= *p_format
;
382 if (*format
== '(' /* ')' */) {
384 msg
= converttuple(arg
, &format
, p_va
, levels
, msgbuf
, 0);
389 msg
= convertsimple(arg
, &format
, p_va
, msgbuf
);
399 /* Convert a non-tuple argument. Adds to convertsimple1 functionality
400 by appending ", <actual argument type>" to error message. */
403 convertsimple(arg
, p_format
, p_va
, msgbuf
)
409 char *msg
= convertsimple1(arg
, p_format
, p_va
);
411 sprintf(msgbuf
, "%.50s, %.50s", msg
,
412 arg
== None
? "None" : arg
->ob_type
->tp_name
);
419 /* Convert a non-tuple argument. Return NULL if conversion went OK,
420 or a string representing the expected type if the conversion failed.
421 When failing, an exception may or may not have been raised.
422 Don't call if a tuple is expected. */
425 convertsimple1(arg
, p_format
, p_va
)
430 char *format
= *p_format
;
435 case 'b': /* byte -- very short int */
437 char *p
= va_arg(*p_va
, char *);
438 long ival
= getintvalue(arg
);
439 if (ival
== -1 && err_occurred())
446 case 'h': /* short int */
448 short *p
= va_arg(*p_va
, short *);
449 long ival
= getintvalue(arg
);
450 if (ival
== -1 && err_occurred())
459 int *p
= va_arg(*p_va
, int *);
460 long ival
= getintvalue(arg
);
461 if (ival
== -1 && err_occurred())
468 case 'l': /* long int */
470 long *p
= va_arg(*p_va
, long *);
471 long ival
= getintvalue(arg
);
472 if (ival
== -1 && err_occurred())
479 case 'f': /* float */
481 float *p
= va_arg(*p_va
, float *);
482 double dval
= getfloatvalue(arg
);
490 case 'd': /* double */
492 double *p
= va_arg(*p_va
, double *);
493 double dval
= getfloatvalue(arg
);
503 char *p
= va_arg(*p_va
, char *);
504 if (is_stringobject(arg
) && getstringsize(arg
) == 1)
505 *p
= getstringvalue(arg
)[0];
511 case 's': /* string */
513 char **p
= va_arg(*p_va
, char **);
514 if (is_stringobject(arg
))
515 *p
= getstringvalue(arg
);
518 if (*format
== '#') {
519 int *q
= va_arg(*p_va
, int *);
520 *q
= getstringsize(arg
);
523 else if (strlen(*p
) != getstringsize(arg
))
524 return "string without null bytes";
528 case 'z': /* string, may be NULL (None) */
530 char **p
= va_arg(*p_va
, char **);
533 else if (is_stringobject(arg
))
534 *p
= getstringvalue(arg
);
536 return "None or string";
537 if (*format
== '#') {
538 int *q
= va_arg(*p_va
, int *);
542 *q
= getstringsize(arg
);
545 else if (*p
!= NULL
&& strlen(*p
) != getstringsize(arg
))
546 return "None or string without null bytes";
550 case 'S': /* string object */
552 object
**p
= va_arg(*p_va
, object
**);
553 if (is_stringobject(arg
))
560 case 'O': /* object */
564 if (*format
== '!') {
566 type
= va_arg(*p_va
, typeobject
*);
567 if (arg
->ob_type
!= type
)
568 return type
->tp_name
;
570 p
= va_arg(*p_va
, object
**);
574 else if (*format
== '?') {
575 inquiry pred
= va_arg(*p_va
, inquiry
);
578 p
= va_arg(*p_va
, object
**);
582 else if (*format
== '&') {
583 typedef int (*converter
) PROTO((object
*, void *));
584 converter convert
= va_arg(*p_va
, converter
);
585 void *addr
= va_arg(*p_va
, void *);
587 if (! (*convert
)(arg
, addr
))
588 return "(unspecified)";
591 p
= va_arg(*p_va
, object
**);
598 return "impossible<bad format char>";