Don't reference removed files in Makefile
[python/dscho.git] / Python / getargs.c
blobcd3ff6d4d8c1f2cd037f20b7c38213fd1c95f2b9
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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));
40 /* Forward */
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 *,
45 int *, char *, int));
46 static char *convertsimple PROTO((object *, char **, va_list *, char *));
47 static char *convertsimple1 PROTO((object *, char **, va_list *));
50 #ifdef HAVE_STDARG_PROTOTYPES
51 /* VARARGS2 */
52 int getargs(object *args, char *format, ...)
53 #else
54 /* VARARGS */
55 int getargs(va_alist) va_dcl
56 #endif
58 int retval;
59 va_list va;
60 #ifdef HAVE_STDARG_PROTOTYPES
62 va_start(va, format);
63 #else
64 object *args;
65 char *format;
67 va_start(va);
68 args = va_arg(va, object *);
69 format = va_arg(va, char *);
70 #endif
71 retval = vgetargs1(args, format, &va, 1);
72 va_end(va);
73 return retval;
77 #ifdef HAVE_STDARG_PROTOTYPES
78 /* VARARGS2 */
79 int newgetargs(object *args, char *format, ...)
80 #else
81 /* VARARGS */
82 int newgetargs(va_alist) va_dcl
83 #endif
85 int retval;
86 va_list va;
87 #ifdef HAVE_STDARG_PROTOTYPES
89 va_start(va, format);
90 #else
91 object *args;
92 char *format;
94 va_start(va);
95 args = va_arg(va, object *);
96 format = va_arg(va, char *);
97 #endif
98 retval = vgetargs1(args, format, &va, 0);
99 va_end(va);
100 return retval;
105 vgetargs(args, format, va)
106 object *args;
107 char *format;
108 va_list va;
110 va_list lva;
112 #ifdef VA_LIST_IS_ARRAY
113 memcpy(lva, va, sizeof(va_list));
114 #else
115 lva = va;
116 #endif
118 return vgetargs1(args, format, &lva, 0);
122 static int
123 vgetargs1(args, format, p_va, compat)
124 object *args;
125 char *format;
126 va_list *p_va;
127 int compat;
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;
140 for (;;) {
141 int c = *format++;
142 if (c == '(' /* ')' */) {
143 if (level == 0)
144 max++;
145 level++;
147 else if (/* '(' */ c == ')') {
148 if (level == 0)
149 fatal(/* '(' */
150 "excess ')' in getargs format");
151 else
152 level--;
154 else if (c == '\0')
155 break;
156 else if (c == ':') {
157 fname = format;
158 break;
160 else if (c == ';') {
161 message = format;
162 break;
164 else if (level != 0)
165 ; /* Pass */
166 else if (isalpha(c))
167 max++;
168 else if (c == '|')
169 min = max;
172 if (level != 0)
173 fatal(/* '(' */ "missing ')' in getargs format");
175 if (min < 0)
176 min = max;
178 format = formatsave;
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;
189 else if (min == 1 && max == 1) {
190 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;
197 msg = convertitem(args, &format, p_va, levels, msgbuf);
198 if (msg == NULL)
199 return 1;
200 seterror(levels[0], msg, levels+1, fname, message);
201 return 0;
203 else {
204 err_setstr(SystemError,
205 "old style getargs format uses new features");
206 return 0;
210 if (!is_tupleobject(args)) {
211 err_setstr(SystemError,
212 "new style getargs format but argument is not a tuple");
213 return 0;
216 len = gettuplesize(args);
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;
230 err_setstr(TypeError, message);
231 return 0;
234 for (i = 0; i < len; i++) {
235 if (*format == '|')
236 format++;
237 msg = convertitem(gettupleitem(args, i), &format, p_va,
238 levels, msgbuf);
239 if (msg) {
240 seterror(i+1, msg, levels, fname, message);
241 return 0;
245 return 1;
250 static void
251 seterror(iarg, msg, levels, fname, message)
252 int iarg;
253 char *msg;
254 int *levels;
255 char *fname;
256 char *message;
258 char buf[256];
259 int i;
260 char *p = buf;
262 if (err_occurred())
263 return;
264 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);
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++;
279 sprintf(p, ": expected %s found", msg);
280 message = buf;
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 ')'.
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.
305 static char *
306 converttuple(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;
314 int level = 0;
315 int n = 0;
316 char *format = *p_format;
317 int i;
319 for (;;) {
320 int c = *format++;
321 if (c == '(') {
322 if (level == 0)
323 n++;
324 level++;
326 else if (c == ')') {
327 if (level == 0)
328 break;
329 level--;
331 else if (c == ':' || c == ';' || c == '\0')
332 break;
333 else if (level == 0 && isalpha(c))
334 n++;
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;
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;
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;
364 *p_format = format;
365 return NULL;
369 /* Convert a single item. */
371 static char *
372 convertitem(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;
379 char *msg;
380 char *format = *p_format;
382 if (*format == '(' /* ')' */) {
383 format++;
384 msg = converttuple(arg, &format, p_va, levels, msgbuf, 0);
385 if (msg == NULL)
386 format++;
388 else {
389 msg = convertsimple(arg, &format, p_va, msgbuf);
390 if (msg != NULL)
391 levels[0] = 0;
393 if (msg == NULL)
394 *p_format = format;
395 return msg;
399 /* Convert a non-tuple argument. Adds to convertsimple1 functionality
400 by appending ", <actual argument type>" to error message. */
402 static char *
403 convertsimple(arg, p_format, p_va, msgbuf)
404 object *arg;
405 char **p_format;
406 va_list *p_va;
407 char *msgbuf;
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;
415 return msg;
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. */
424 static char *
425 convertsimple1(arg, p_format, p_va)
426 object *arg;
427 char **p_format;
428 va_list *p_va;
430 char *format = *p_format;
431 char c = *format++;
433 switch (c) {
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())
440 return "integer<b>";
441 else
442 *p = ival;
443 break;
446 case 'h': /* short int */
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;
457 case 'i': /* int */
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;
468 case 'l': /* long int */
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;
479 case 'f': /* float */
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;
490 case 'd': /* double */
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;
501 case 'c': /* char */
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;
511 case 's': /* string */
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++;
523 else if (strlen(*p) != getstringsize(arg))
524 return "string without null bytes";
525 break;
528 case 'z': /* string, may be NULL (None) */
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++;
545 else if (*p != NULL && strlen(*p) != getstringsize(arg))
546 return "None or string without null bytes";
547 break;
550 case 'S': /* string object */
552 object **p = va_arg(*p_va, object **);
553 if (is_stringobject(arg))
554 *p = arg;
555 else
556 return "string";
557 break;
560 case 'O': /* object */
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;
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;
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))
588 return "(unspecified)";
590 else {
591 p = va_arg(*p_va, object **);
592 *p = arg;
594 break;
597 default:
598 return "impossible<bad format char>";
602 *p_format = format;
603 return NULL;