blob: 7ec31c353569f1c41599e457718112a5d4fbe4f8 [file] [log] [blame]
Guido van Rossumfe3f1a21994-09-29 09:42:55 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumfe3f1a21994-09-29 09:42:55 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* New getargs implementation */
26
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. */
31
32#include "allobjects.h"
33
34
35int getargs PROTO((object *, char *, ...));
36int newgetargs PROTO((object *, char *, ...));
37int vgetargs PROTO((object *, char *, va_list));
38
39
40/* Forward */
Guido van Rossum1ae940a1995-01-02 19:04:15 +000041static int vgetargs1 PROTO((object *, char *, va_list *, int));
Guido van Rossumfe3f1a21994-09-29 09:42:55 +000042static void seterror PROTO((int, char *, int *, char *, char *));
43static char *convertitem PROTO((object *, char **, va_list *, int *, char *));
44static char *converttuple PROTO((object *, char **, va_list *,
45 int *, char *, int));
46static char *convertsimple PROTO((object *, char **, va_list *, char *));
47static char *convertsimple1 PROTO((object *, char **, va_list *));
48
49
50#ifdef HAVE_STDARG_PROTOTYPES
51/* VARARGS2 */
52int getargs(object *args, char *format, ...)
53#else
54/* VARARGS */
55int getargs(va_alist) va_dcl
56#endif
57{
58 int retval;
59 va_list va;
60#ifdef HAVE_STDARG_PROTOTYPES
61
62 va_start(va, format);
63#else
64 object *args;
65 char *format;
66
67 va_start(va);
68 args = va_arg(va, object *);
69 format = va_arg(va, char *);
70#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +000071 retval = vgetargs1(args, format, &va, 1);
Guido van Rossumfe3f1a21994-09-29 09:42:55 +000072 va_end(va);
73 return retval;
74}
75
76
77#ifdef HAVE_STDARG_PROTOTYPES
78/* VARARGS2 */
79int newgetargs(object *args, char *format, ...)
80#else
81/* VARARGS */
82int newgetargs(va_alist) va_dcl
83#endif
84{
85 int retval;
86 va_list va;
87#ifdef HAVE_STDARG_PROTOTYPES
88
89 va_start(va, format);
90#else
91 object *args;
92 char *format;
93
94 va_start(va);
95 args = va_arg(va, object *);
96 format = va_arg(va, char *);
97#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +000098 retval = vgetargs1(args, format, &va, 0);
Guido van Rossumfe3f1a21994-09-29 09:42:55 +000099 va_end(va);
100 return retval;
101}
102
103
104int
105vgetargs(args, format, va)
106 object *args;
107 char *format;
108 va_list va;
109{
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000110 va_list lva;
111
112#ifdef VA_LIST_IS_ARRAY
113 memcpy(lva, va, sizeof(va_list));
114#else
115 lva = va;
116#endif
117
118 return vgetargs1(args, format, &lva, 0);
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000119}
120
121
122static int
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000123vgetargs1(args, format, p_va, compat)
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000124 object *args;
125 char *format;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000126 va_list *p_va;
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000127 int compat;
128{
129 char msgbuf[256];
130 int levels[32];
131 char *fname = NULL;
132 char *message = NULL;
133 int min = -1;
134 int max = 0;
135 int level = 0;
136 char *formatsave = format;
137 int i, len;
138 char *msg;
139
140 for (;;) {
141 int c = *format++;
142 if (c == '(' /* ')' */) {
143 if (level == 0)
144 max++;
145 level++;
146 }
147 else if (/* '(' */ c == ')') {
148 if (level == 0)
149 fatal(/* '(' */
150 "excess ')' in getargs format");
151 else
152 level--;
153 }
154 else if (c == '\0')
155 break;
156 else if (c == ':') {
157 fname = format;
158 break;
159 }
160 else if (c == ';') {
161 message = format;
162 break;
163 }
164 else if (level != 0)
165 ; /* Pass */
166 else if (isalpha(c))
167 max++;
168 else if (c == '|')
169 min = max;
170 }
171
172 if (level != 0)
173 fatal(/* '(' */ "missing ')' in getargs format");
174
175 if (min < 0)
176 min = max;
177
178 format = formatsave;
179
180 if (compat) {
181 if (max == 0) {
182 if (args == NULL)
183 return 1;
184 sprintf(msgbuf, "%s requires no arguments",
185 fname==NULL ? "function" : fname);
186 err_setstr(TypeError, msgbuf);
187 return 0;
188 }
189 else if (min == 1 && max == 1) {
Guido van Rossum13d0ed11994-11-10 22:35:48 +0000190 if (args == NULL) {
191 sprintf(msgbuf,
192 "%s requires at least one argument",
193 fname==NULL ? "function" : fname);
194 err_setstr(TypeError, msgbuf);
195 return 0;
196 }
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000197 msg = convertitem(args, &format, p_va, levels, msgbuf);
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000198 if (msg == NULL)
199 return 1;
200 seterror(levels[0], msg, levels+1, fname, message);
201 return 0;
202 }
203 else {
204 err_setstr(SystemError,
205 "old style getargs format uses new features");
206 return 0;
207 }
208 }
209
210 if (!is_tupleobject(args)) {
211 err_setstr(SystemError,
212 "new style getargs format but argument is not a tuple");
213 return 0;
214 }
215
216 len = gettuplesize(args);
217
218 if (len < min || max < len) {
219 if (message == NULL) {
220 sprintf(msgbuf,
221 "%s requires %s %d argument%s; %d given",
222 fname==NULL ? "function" : fname,
223 min==max ? "exactly"
224 : len < min ? "at least" : "at most",
225 len < min ? min : max,
226 (len < min ? min : max) == 1 ? "" : "s",
227 len);
228 message = msgbuf;
229 }
230 err_setstr(TypeError, message);
231 return 0;
232 }
233
234 for (i = 0; i < len; i++) {
235 if (*format == '|')
236 format++;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000237 msg = convertitem(gettupleitem(args, i), &format, p_va,
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000238 levels, msgbuf);
239 if (msg) {
240 seterror(i+1, msg, levels, fname, message);
241 return 0;
242 }
243 }
244
245 return 1;
246}
247
248
249
250static void
251seterror(iarg, msg, levels, fname, message)
252 int iarg;
253 char *msg;
254 int *levels;
255 char *fname;
256 char *message;
257{
258 char buf[256];
259 int i;
260 char *p = buf;
261
Guido van Rossum64fc6491995-01-21 14:09:37 +0000262 if (err_occurred())
263 return;
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000264 if (iarg == 0 && message == NULL)
265 message = msg;
266 else if (message == NULL) {
267 if (fname != NULL) {
268 sprintf(p, "%s, ", fname);
269 p += strlen(p);
270 }
271 sprintf(p, "argument %d", iarg);
272 i = 0;
273 p += strlen(p);
274 while (levels[i] > 0) {
275 sprintf(p, ", item %d", levels[i]-1);
276 p += strlen(p);
277 i++;
278 }
279 sprintf(p, ": expected %s found", msg);
280 message = buf;
281 }
282 err_setstr(TypeError, message);
283}
284
285
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 ')'.
289 If successful:
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,
295 *p_va is undefined,
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.
303*/
304
305static char *
306converttuple(arg, p_format, p_va, levels, msgbuf, toplevel)
307 object *arg;
308 char **p_format;
309 va_list *p_va;
310 int *levels;
311 char *msgbuf;
312 int toplevel;
313{
314 int level = 0;
315 int n = 0;
316 char *format = *p_format;
317 int i;
318
319 for (;;) {
320 int c = *format++;
321 if (c == '(') {
322 if (level == 0)
323 n++;
324 level++;
325 }
326 else if (c == ')') {
327 if (level == 0)
328 break;
329 level--;
330 }
331 else if (c == ':' || c == ';' || c == '\0')
332 break;
333 else if (level == 0 && isalpha(c))
334 n++;
335 }
336
337 if (!is_tupleobject(arg)) {
338 levels[0] = 0;
339 sprintf(msgbuf,
340 toplevel ? "%d arguments, %s" : "%d-tuple, %s",
341 n, arg == None ? "None" : arg->ob_type->tp_name);
342 return msgbuf;
343 }
344
345 if ((i = gettuplesize(arg)) != n) {
346 levels[0] = 0;
347 sprintf(msgbuf,
348 toplevel ? "%d arguments, %d" : "%d-tuple, %d-tuple",
349 n, i);
350 return msgbuf;
351 }
352
353 format = *p_format;
354 for (i = 0; i < n; i++) {
355 char *msg;
356 msg = convertitem(gettupleitem(arg, i), &format, p_va,
357 levels+1, msgbuf);
358 if (msg != NULL) {
359 levels[0] = i+1;
360 return msg;
361 }
362 }
363
364 *p_format = format;
365 return NULL;
366}
367
368
369/* Convert a single item. */
370
371static char *
372convertitem(arg, p_format, p_va, levels, msgbuf)
373 object *arg;
374 char **p_format;
375 va_list *p_va;
376 int *levels;
377 char *msgbuf;
378{
379 char *msg;
380 char *format = *p_format;
381
382 if (*format == '(' /* ')' */) {
383 format++;
384 msg = converttuple(arg, &format, p_va, levels, msgbuf, 0);
385 if (msg == NULL)
386 format++;
387 }
388 else {
389 msg = convertsimple(arg, &format, p_va, msgbuf);
390 if (msg != NULL)
391 levels[0] = 0;
392 }
393 if (msg == NULL)
394 *p_format = format;
395 return msg;
396}
397
398
399/* Convert a non-tuple argument. Adds to convertsimple1 functionality
400 by appending ", <actual argument type>" to error message. */
401
402static char *
403convertsimple(arg, p_format, p_va, msgbuf)
404 object *arg;
405 char **p_format;
406 va_list *p_va;
407 char *msgbuf;
408{
409 char *msg = convertsimple1(arg, p_format, p_va);
410 if (msg != NULL) {
411 sprintf(msgbuf, "%.50s, %.50s", msg,
412 arg == None ? "None" : arg->ob_type->tp_name);
413 msg = msgbuf;
414 }
415 return msg;
416}
417
418
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. */
423
424static char *
425convertsimple1(arg, p_format, p_va)
426 object *arg;
427 char **p_format;
428 va_list *p_va;
429{
430 char *format = *p_format;
431 char c = *format++;
432
433 switch (c) {
434
435 case 'b': /* byte -- very short int */
436 {
437 char *p = va_arg(*p_va, char *);
438 long ival = getintvalue(arg);
439 if (ival == -1 && err_occurred())
440 return "integer<b>";
441 else
442 *p = ival;
443 break;
444 }
445
446 case 'h': /* short int */
447 {
448 short *p = va_arg(*p_va, short *);
449 long ival = getintvalue(arg);
450 if (ival == -1 && err_occurred())
451 return "integer<h>";
452 else
453 *p = ival;
454 break;
455 }
456
457 case 'i': /* int */
458 {
459 int *p = va_arg(*p_va, int *);
460 long ival = getintvalue(arg);
461 if (ival == -1 && err_occurred())
462 return "integer<i>";
463 else
464 *p = ival;
465 break;
466 }
467
468 case 'l': /* long int */
469 {
470 long *p = va_arg(*p_va, long *);
471 long ival = getintvalue(arg);
472 if (ival == -1 && err_occurred())
473 return "integer<l>";
474 else
475 *p = ival;
476 break;
477 }
478
479 case 'f': /* float */
480 {
481 float *p = va_arg(*p_va, float *);
482 double dval = getfloatvalue(arg);
483 if (err_occurred())
484 return "float<f>";
485 else
486 *p = dval;
487 break;
488 }
489
490 case 'd': /* double */
491 {
492 double *p = va_arg(*p_va, double *);
493 double dval = getfloatvalue(arg);
494 if (err_occurred())
495 return "float<d>";
496 else
497 *p = dval;
498 break;
499 }
500
Guido van Rossum8a5c5d21996-01-12 01:09:56 +0000501 case 'D': /* complex double */
502 {
503 complex *p = va_arg(*p_va, complex *);
504 complex cval = PyComplex_AsCComplex(arg);
505 if (err_occurred())
506 return "complex<D>";
507 else
508 *p = cval;
509 break;
510 }
511
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000512 case 'c': /* char */
513 {
514 char *p = va_arg(*p_va, char *);
515 if (is_stringobject(arg) && getstringsize(arg) == 1)
516 *p = getstringvalue(arg)[0];
517 else
518 return "char";
519 break;
520 }
521
522 case 's': /* string */
523 {
524 char **p = va_arg(*p_va, char **);
525 if (is_stringobject(arg))
526 *p = getstringvalue(arg);
527 else
528 return "string";
529 if (*format == '#') {
530 int *q = va_arg(*p_va, int *);
531 *q = getstringsize(arg);
532 format++;
533 }
534 else if (strlen(*p) != getstringsize(arg))
535 return "string without null bytes";
536 break;
537 }
538
539 case 'z': /* string, may be NULL (None) */
540 {
541 char **p = va_arg(*p_va, char **);
542 if (arg == None)
543 *p = 0;
544 else if (is_stringobject(arg))
545 *p = getstringvalue(arg);
546 else
547 return "None or string";
548 if (*format == '#') {
549 int *q = va_arg(*p_va, int *);
550 if (arg == None)
551 *q = 0;
552 else
553 *q = getstringsize(arg);
554 format++;
555 }
556 else if (*p != NULL && strlen(*p) != getstringsize(arg))
557 return "None or string without null bytes";
558 break;
559 }
560
561 case 'S': /* string object */
562 {
563 object **p = va_arg(*p_va, object **);
564 if (is_stringobject(arg))
565 *p = arg;
566 else
567 return "string";
568 break;
569 }
570
571 case 'O': /* object */
572 {
573 typeobject *type;
574 object **p;
575 if (*format == '!') {
576 format++;
577 type = va_arg(*p_va, typeobject*);
578 if (arg->ob_type != type)
579 return type->tp_name;
580 else {
581 p = va_arg(*p_va, object **);
582 *p = arg;
583 }
584 }
585 else if (*format == '?') {
586 inquiry pred = va_arg(*p_va, inquiry);
587 format++;
588 if ((*pred)(arg)) {
589 p = va_arg(*p_va, object **);
590 *p = arg;
591 }
592 }
593 else if (*format == '&') {
594 typedef int (*converter) PROTO((object *, void *));
595 converter convert = va_arg(*p_va, converter);
596 void *addr = va_arg(*p_va, void *);
597 format++;
598 if (! (*convert)(arg, addr))
Guido van Rossum64fc6491995-01-21 14:09:37 +0000599 return "(unspecified)";
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000600 }
601 else {
602 p = va_arg(*p_va, object **);
603 *p = arg;
604 }
605 break;
606 }
607
608 default:
609 return "impossible<bad format char>";
610
611 }
612
613 *p_format = format;
614 return NULL;
615}