blob: 1232fd0924f6021270e2cf42105f7bcd35b93d3c [file] [log] [blame]
Guido van Rossumfe3f1a21994-09-29 09:42:55 +00001/***********************************************************
2Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
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
262 if (iarg == 0 && message == NULL)
263 message = msg;
264 else if (message == NULL) {
265 if (fname != NULL) {
266 sprintf(p, "%s, ", fname);
267 p += strlen(p);
268 }
269 sprintf(p, "argument %d", iarg);
270 i = 0;
271 p += strlen(p);
272 while (levels[i] > 0) {
273 sprintf(p, ", item %d", levels[i]-1);
274 p += strlen(p);
275 i++;
276 }
277 sprintf(p, ": expected %s found", msg);
278 message = buf;
279 }
280 err_setstr(TypeError, message);
281}
282
283
284/* Convert a tuple argument.
285 On entry, *p_format points to the character _after_ the opening '('.
286 On successful exit, *p_format points to the closing ')'.
287 If successful:
288 *p_format and *p_va are updated,
289 *levels and *msgbuf are untouched,
290 and NULL is returned.
291 If the argument is invalid:
292 *p_format is unchanged,
293 *p_va is undefined,
294 *levels is a 0-terminated list of item numbers,
295 *msgbuf contains an error message, whose format is:
296 "<typename1>, <typename2>", where:
297 <typename1> is the name of the expected type, and
298 <typename2> is the name of the actual type,
299 (so you can surround it by "expected ... found"),
300 and msgbuf is returned.
301*/
302
303static char *
304converttuple(arg, p_format, p_va, levels, msgbuf, toplevel)
305 object *arg;
306 char **p_format;
307 va_list *p_va;
308 int *levels;
309 char *msgbuf;
310 int toplevel;
311{
312 int level = 0;
313 int n = 0;
314 char *format = *p_format;
315 int i;
316
317 for (;;) {
318 int c = *format++;
319 if (c == '(') {
320 if (level == 0)
321 n++;
322 level++;
323 }
324 else if (c == ')') {
325 if (level == 0)
326 break;
327 level--;
328 }
329 else if (c == ':' || c == ';' || c == '\0')
330 break;
331 else if (level == 0 && isalpha(c))
332 n++;
333 }
334
335 if (!is_tupleobject(arg)) {
336 levels[0] = 0;
337 sprintf(msgbuf,
338 toplevel ? "%d arguments, %s" : "%d-tuple, %s",
339 n, arg == None ? "None" : arg->ob_type->tp_name);
340 return msgbuf;
341 }
342
343 if ((i = gettuplesize(arg)) != n) {
344 levels[0] = 0;
345 sprintf(msgbuf,
346 toplevel ? "%d arguments, %d" : "%d-tuple, %d-tuple",
347 n, i);
348 return msgbuf;
349 }
350
351 format = *p_format;
352 for (i = 0; i < n; i++) {
353 char *msg;
354 msg = convertitem(gettupleitem(arg, i), &format, p_va,
355 levels+1, msgbuf);
356 if (msg != NULL) {
357 levels[0] = i+1;
358 return msg;
359 }
360 }
361
362 *p_format = format;
363 return NULL;
364}
365
366
367/* Convert a single item. */
368
369static char *
370convertitem(arg, p_format, p_va, levels, msgbuf)
371 object *arg;
372 char **p_format;
373 va_list *p_va;
374 int *levels;
375 char *msgbuf;
376{
377 char *msg;
378 char *format = *p_format;
379
380 if (*format == '(' /* ')' */) {
381 format++;
382 msg = converttuple(arg, &format, p_va, levels, msgbuf, 0);
383 if (msg == NULL)
384 format++;
385 }
386 else {
387 msg = convertsimple(arg, &format, p_va, msgbuf);
388 if (msg != NULL)
389 levels[0] = 0;
390 }
391 if (msg == NULL)
392 *p_format = format;
393 return msg;
394}
395
396
397/* Convert a non-tuple argument. Adds to convertsimple1 functionality
398 by appending ", <actual argument type>" to error message. */
399
400static char *
401convertsimple(arg, p_format, p_va, msgbuf)
402 object *arg;
403 char **p_format;
404 va_list *p_va;
405 char *msgbuf;
406{
407 char *msg = convertsimple1(arg, p_format, p_va);
408 if (msg != NULL) {
409 sprintf(msgbuf, "%.50s, %.50s", msg,
410 arg == None ? "None" : arg->ob_type->tp_name);
411 msg = msgbuf;
412 }
413 return msg;
414}
415
416
417/* Convert a non-tuple argument. Return NULL if conversion went OK,
418 or a string representing the expected type if the conversion failed.
419 When failing, an exception may or may not have been raised.
420 Don't call if a tuple is expected. */
421
422static char *
423convertsimple1(arg, p_format, p_va)
424 object *arg;
425 char **p_format;
426 va_list *p_va;
427{
428 char *format = *p_format;
429 char c = *format++;
430
431 switch (c) {
432
433 case 'b': /* byte -- very short int */
434 {
435 char *p = va_arg(*p_va, char *);
436 long ival = getintvalue(arg);
437 if (ival == -1 && err_occurred())
438 return "integer<b>";
439 else
440 *p = ival;
441 break;
442 }
443
444 case 'h': /* short int */
445 {
446 short *p = va_arg(*p_va, short *);
447 long ival = getintvalue(arg);
448 if (ival == -1 && err_occurred())
449 return "integer<h>";
450 else
451 *p = ival;
452 break;
453 }
454
455 case 'i': /* int */
456 {
457 int *p = va_arg(*p_va, int *);
458 long ival = getintvalue(arg);
459 if (ival == -1 && err_occurred())
460 return "integer<i>";
461 else
462 *p = ival;
463 break;
464 }
465
466 case 'l': /* long int */
467 {
468 long *p = va_arg(*p_va, long *);
469 long ival = getintvalue(arg);
470 if (ival == -1 && err_occurred())
471 return "integer<l>";
472 else
473 *p = ival;
474 break;
475 }
476
477 case 'f': /* float */
478 {
479 float *p = va_arg(*p_va, float *);
480 double dval = getfloatvalue(arg);
481 if (err_occurred())
482 return "float<f>";
483 else
484 *p = dval;
485 break;
486 }
487
488 case 'd': /* double */
489 {
490 double *p = va_arg(*p_va, double *);
491 double dval = getfloatvalue(arg);
492 if (err_occurred())
493 return "float<d>";
494 else
495 *p = dval;
496 break;
497 }
498
499 case 'c': /* char */
500 {
501 char *p = va_arg(*p_va, char *);
502 if (is_stringobject(arg) && getstringsize(arg) == 1)
503 *p = getstringvalue(arg)[0];
504 else
505 return "char";
506 break;
507 }
508
509 case 's': /* string */
510 {
511 char **p = va_arg(*p_va, char **);
512 if (is_stringobject(arg))
513 *p = getstringvalue(arg);
514 else
515 return "string";
516 if (*format == '#') {
517 int *q = va_arg(*p_va, int *);
518 *q = getstringsize(arg);
519 format++;
520 }
521 else if (strlen(*p) != getstringsize(arg))
522 return "string without null bytes";
523 break;
524 }
525
526 case 'z': /* string, may be NULL (None) */
527 {
528 char **p = va_arg(*p_va, char **);
529 if (arg == None)
530 *p = 0;
531 else if (is_stringobject(arg))
532 *p = getstringvalue(arg);
533 else
534 return "None or string";
535 if (*format == '#') {
536 int *q = va_arg(*p_va, int *);
537 if (arg == None)
538 *q = 0;
539 else
540 *q = getstringsize(arg);
541 format++;
542 }
543 else if (*p != NULL && strlen(*p) != getstringsize(arg))
544 return "None or string without null bytes";
545 break;
546 }
547
548 case 'S': /* string object */
549 {
550 object **p = va_arg(*p_va, object **);
551 if (is_stringobject(arg))
552 *p = arg;
553 else
554 return "string";
555 break;
556 }
557
558 case 'O': /* object */
559 {
560 typeobject *type;
561 object **p;
562 if (*format == '!') {
563 format++;
564 type = va_arg(*p_va, typeobject*);
565 if (arg->ob_type != type)
566 return type->tp_name;
567 else {
568 p = va_arg(*p_va, object **);
569 *p = arg;
570 }
571 }
572 else if (*format == '?') {
573 inquiry pred = va_arg(*p_va, inquiry);
574 format++;
575 if ((*pred)(arg)) {
576 p = va_arg(*p_va, object **);
577 *p = arg;
578 }
579 }
580 else if (*format == '&') {
581 typedef int (*converter) PROTO((object *, void *));
582 converter convert = va_arg(*p_va, converter);
583 void *addr = va_arg(*p_va, void *);
584 format++;
585 if (! (*convert)(arg, addr))
586 return "";
587 }
588 else {
589 p = va_arg(*p_va, object **);
590 *p = arg;
591 }
592 break;
593 }
594
595 default:
596 return "impossible<bad format char>";
597
598 }
599
600 *p_format = format;
601 return NULL;
602}