blob: cd3ff6d4d8c1f2cd037f20b7c38213fd1c95f2b9 [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
501 case 'c': /* char */
502 {
503 char *p = va_arg(*p_va, char *);
504 if (is_stringobject(arg) && getstringsize(arg) == 1)
505 *p = getstringvalue(arg)[0];
506 else
507 return "char";
508 break;
509 }
510
511 case 's': /* string */
512 {
513 char **p = va_arg(*p_va, char **);
514 if (is_stringobject(arg))
515 *p = getstringvalue(arg);
516 else
517 return "string";
518 if (*format == '#') {
519 int *q = va_arg(*p_va, int *);
520 *q = getstringsize(arg);
521 format++;
522 }
523 else if (strlen(*p) != getstringsize(arg))
524 return "string without null bytes";
525 break;
526 }
527
528 case 'z': /* string, may be NULL (None) */
529 {
530 char **p = va_arg(*p_va, char **);
531 if (arg == None)
532 *p = 0;
533 else if (is_stringobject(arg))
534 *p = getstringvalue(arg);
535 else
536 return "None or string";
537 if (*format == '#') {
538 int *q = va_arg(*p_va, int *);
539 if (arg == None)
540 *q = 0;
541 else
542 *q = getstringsize(arg);
543 format++;
544 }
545 else if (*p != NULL && strlen(*p) != getstringsize(arg))
546 return "None or string without null bytes";
547 break;
548 }
549
550 case 'S': /* string object */
551 {
552 object **p = va_arg(*p_va, object **);
553 if (is_stringobject(arg))
554 *p = arg;
555 else
556 return "string";
557 break;
558 }
559
560 case 'O': /* object */
561 {
562 typeobject *type;
563 object **p;
564 if (*format == '!') {
565 format++;
566 type = va_arg(*p_va, typeobject*);
567 if (arg->ob_type != type)
568 return type->tp_name;
569 else {
570 p = va_arg(*p_va, object **);
571 *p = arg;
572 }
573 }
574 else if (*format == '?') {
575 inquiry pred = va_arg(*p_va, inquiry);
576 format++;
577 if ((*pred)(arg)) {
578 p = va_arg(*p_va, object **);
579 *p = arg;
580 }
581 }
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 *);
586 format++;
587 if (! (*convert)(arg, addr))
Guido van Rossum64fc6491995-01-21 14:09:37 +0000588 return "(unspecified)";
Guido van Rossumfe3f1a21994-09-29 09:42:55 +0000589 }
590 else {
591 p = va_arg(*p_va, object **);
592 *p = arg;
593 }
594 break;
595 }
596
597 default:
598 return "impossible<bad format char>";
599
600 }
601
602 *p_format = format;
603 return NULL;
604}