blob: 1f281266c9f36d8a703b2d5176407cf7ecfe1b99 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumf70e43a1991-02-19 12:39:46 +00003Netherlands.
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
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Module support implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028#include "modsupport.h"
29#include "import.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000030
Guido van Rossum922cfad1992-01-27 16:47:03 +000031#ifdef HAVE_PROTOTYPES
32#define USE_STDARG
33#endif
34
35#ifdef USE_STDARG
36#include <stdarg.h>
37#else
38#include <varargs.h>
39#endif
40
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000041
42object *
43initmodule(name, methods)
44 char *name;
45 struct methodlist *methods;
46{
47 object *m, *d, *v;
48 struct methodlist *ml;
Guido van Rossuma2b7f401993-01-04 09:09:59 +000049 char *namebuf;
Guido van Rossum3f5da241990-12-20 15:06:42 +000050 if ((m = add_module(name)) == NULL) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000051 fprintf(stderr, "initializing module: %s\n", name);
52 fatal("can't create a module");
53 }
54 d = getmoduledict(m);
55 for (ml = methods; ml->ml_name != NULL; ml++) {
Guido van Rossuma2b7f401993-01-04 09:09:59 +000056 namebuf = NEW(char, strlen(name) + strlen(ml->ml_name) + 2);
57 if (namebuf == NULL)
58 fatal("out of mem for method name");
Guido van Rossum3f5da241990-12-20 15:06:42 +000059 sprintf(namebuf, "%s.%s", name, ml->ml_name);
Guido van Rossuma2b7f401993-01-04 09:09:59 +000060 v = newmethodobject(namebuf, ml->ml_meth,
Guido van Rossumc0602291991-12-16 13:07:24 +000061 (object *)NULL, ml->ml_varargs);
Guido van Rossuma2b7f401993-01-04 09:09:59 +000062 /* XXX The malloc'ed memory in namebuf is never freed */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000063 if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
64 fprintf(stderr, "initializing module: %s\n", name);
65 fatal("can't initialize module");
66 }
67 DECREF(v);
68 }
Guido van Rossum3f5da241990-12-20 15:06:42 +000069 return m;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000070}
71
72
Guido van Rossumfc61adb1992-04-13 15:53:41 +000073/* Helper for getargs() and mkvalue() to scan the length of a format */
74
75static int countformat PROTO((char *format, int endchar));
76static int countformat(format, endchar)
77 char *format;
78 int endchar;
79{
80 int count = 0;
81 int level = 0;
82 while (level > 0 || *format != endchar) {
83 if (*format == '\0') {
84 /* Premature end */
85 err_setstr(SystemError, "unmatched paren in format");
86 return -1;
87 }
88 else if (*format == '(') {
89 if (level == 0)
90 count++;
91 level++;
92 }
93 else if (*format == ')')
94 level--;
95 else if (level == 0 && *format != '#')
96 count++;
97 format++;
98 }
99 return count;
100}
101
102
Guido van Rossum922cfad1992-01-27 16:47:03 +0000103/* Generic argument list parser */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000104
Guido van Rossum922cfad1992-01-27 16:47:03 +0000105static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
106static int
107do_arg(arg, p_format, p_va)
108 object *arg;
109 char** p_format;
110 va_list *p_va;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111{
Guido van Rossum922cfad1992-01-27 16:47:03 +0000112 char *format = *p_format;
113 va_list va = *p_va;
114
115 if (arg == NULL)
116 return 0; /* Incomplete tuple or list */
117
118 switch (*format++) {
119
Guido van Rossuma93265a1992-08-27 07:45:12 +0000120 case '(': /* tuple, distributed over C parameters */ {
Guido van Rossum922cfad1992-01-27 16:47:03 +0000121 int i, n;
122 if (!is_tupleobject(arg))
123 return 0;
124 n = gettuplesize(arg);
125 for (i = 0; i < n; i++) {
126 if (!do_arg(gettupleitem(arg, i), &format, &va))
127 return 0;
128 }
Guido van Rossuma93265a1992-08-27 07:45:12 +0000129 if (*format++ != ')')
Guido van Rossum922cfad1992-01-27 16:47:03 +0000130 return 0;
131 break;
132 }
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000133
Guido van Rossuma93265a1992-08-27 07:45:12 +0000134 case ')': /* End of format -- too many arguments */
135 return 0;
136
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000137 case 'b': /* byte -- very short int */ {
138 char *p = va_arg(va, char *);
139 if (is_intobject(arg))
140 *p = getintvalue(arg);
141 else
142 return 0;
143 break;
144 }
145
Guido van Rossum922cfad1992-01-27 16:47:03 +0000146 case 'h': /* short int */ {
147 short *p = va_arg(va, short *);
148 if (is_intobject(arg))
149 *p = getintvalue(arg);
150 else
151 return 0;
152 break;
153 }
154
155 case 'i': /* int */ {
156 int *p = va_arg(va, int *);
157 if (is_intobject(arg))
158 *p = getintvalue(arg);
159 else
160 return 0;
161 break;
162 }
163
164 case 'l': /* long int */ {
165 long *p = va_arg(va, long *);
166 if (is_intobject(arg))
167 *p = getintvalue(arg);
168 else
169 return 0;
170 break;
171 }
172
173 case 'f': /* float */ {
174 float *p = va_arg(va, float *);
175 if (is_floatobject(arg))
176 *p = getfloatvalue(arg);
177 else if (is_intobject(arg))
178 *p = (float)getintvalue(arg);
179 else
180 return 0;
181 break;
182 }
183
184 case 'd': /* double */ {
185 double *p = va_arg(va, double *);
186 if (is_floatobject(arg))
187 *p = getfloatvalue(arg);
188 else if (is_intobject(arg))
189 *p = (double)getintvalue(arg);
190 else
191 return 0;
192 break;
193 }
194
195 case 'c': /* char */ {
196 char *p = va_arg(va, char *);
197 if (is_stringobject(arg) && getstringsize(arg) == 1)
198 *p = getstringvalue(arg)[0];
199 else
200 return 0;
201 break;
202 }
203
204 case 's': /* string */ {
205 char **p = va_arg(va, char **);
206 if (is_stringobject(arg))
207 *p = getstringvalue(arg);
208 else
209 return 0;
210 if (*format == '#') {
211 int *q = va_arg(va, int *);
212 *q = getstringsize(arg);
213 format++;
214 }
Guido van Rossum96caaee1992-08-14 15:12:03 +0000215 else if (strlen(*p) != getstringsize(arg)) {
216 err_setstr(ValueError, "embedded '\\0' in string arg");
217 return 0;
218 }
Guido van Rossum922cfad1992-01-27 16:47:03 +0000219 break;
220 }
221
222 case 'z': /* string, may be NULL (None) */ {
223 char **p = va_arg(va, char **);
224 if (arg == None)
225 *p = 0;
226 else if (is_stringobject(arg))
227 *p = getstringvalue(arg);
228 else
229 return 0;
230 if (*format == '#') {
231 int *q = va_arg(va, int *);
232 if (arg == None)
233 *q = 0;
234 else
235 *q = getstringsize(arg);
236 format++;
237 }
Guido van Rossum96caaee1992-08-14 15:12:03 +0000238 else if (*p != NULL && strlen(*p) != getstringsize(arg)) {
239 err_setstr(ValueError, "embedded '\\0' in string arg");
240 return 0;
241 }
Guido van Rossum922cfad1992-01-27 16:47:03 +0000242 break;
243 }
244
245 case 'S': /* string object */ {
246 object **p = va_arg(va, object **);
247 if (is_stringobject(arg))
248 *p = arg;
249 else
250 return 0;
251 break;
252 }
253
254 case 'O': /* object */ {
255 object **p = va_arg(va, object **);
256 *p = arg;
257 break;
258 }
259
260 default:
261 fprintf(stderr, "bad do_arg format: x%x '%c'\n",
262 format[-1], format[-1]);
263 return 0;
264
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000265 }
Guido van Rossum922cfad1992-01-27 16:47:03 +0000266
267 *p_va = va;
268 *p_format = format;
269
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000270 return 1;
271}
272
Guido van Rossum922cfad1992-01-27 16:47:03 +0000273#ifdef USE_STDARG
Guido van Rossum292bb8e1992-03-27 17:23:29 +0000274/* VARARGS2 */
Guido van Rossum922cfad1992-01-27 16:47:03 +0000275int getargs(object *arg, char *format, ...)
276#else
Guido van Rossum292bb8e1992-03-27 17:23:29 +0000277/* VARARGS */
Guido van Rossum922cfad1992-01-27 16:47:03 +0000278int getargs(va_alist) va_dcl
279#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000280{
Guido van Rossum922cfad1992-01-27 16:47:03 +0000281 char *f;
282 int ok;
283 va_list va;
284#ifdef USE_STDARG
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285
Guido van Rossum922cfad1992-01-27 16:47:03 +0000286 va_start(va, format);
287#else
288 object *arg;
289 char *format;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000290
Guido van Rossum922cfad1992-01-27 16:47:03 +0000291 va_start(va);
292 arg = va_arg(va, object *);
293 format = va_arg(va, char *);
294#endif
295 if (*format == '\0') {
296 va_end(va);
297 if (arg != NULL) {
298 err_setstr(TypeError, "no arguments needed");
299 return 0;
300 }
Guido van Rossumc5da3501991-09-10 14:56:32 +0000301 return 1;
302 }
Guido van Rossum922cfad1992-01-27 16:47:03 +0000303
304 f = format;
305 ok = do_arg(arg, &f, &va) && *f == '\0';
306 va_end(va);
307 if (!ok) {
308 char buf[256];
Guido van Rossum96caaee1992-08-14 15:12:03 +0000309 if (!err_occurred()) {
310 sprintf(buf, "bad argument list (format '%s')",
311 format);
312 err_setstr(TypeError, buf);
313 }
Guido van Rossumc5da3501991-09-10 14:56:32 +0000314 }
Guido van Rossum922cfad1992-01-27 16:47:03 +0000315 return ok;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000316}
317
318int
319getlongtuplearg(args, a, n)
320 object *args;
321 long *a; /* [n] */
322 int n;
323{
324 int i;
325 if (!is_tupleobject(args) || gettuplesize(args) != n) {
326 return err_badarg();
327 }
328 for (i = 0; i < n; i++) {
329 object *v = gettupleitem(args, i);
330 if (!is_intobject(v)) {
331 return err_badarg();
332 }
333 a[i] = getintvalue(v);
334 }
335 return 1;
336}
337
338int
339getshorttuplearg(args, a, n)
340 object *args;
341 short *a; /* [n] */
342 int n;
343{
344 int i;
345 if (!is_tupleobject(args) || gettuplesize(args) != n) {
346 return err_badarg();
347 }
348 for (i = 0; i < n; i++) {
349 object *v = gettupleitem(args, i);
350 if (!is_intobject(v)) {
351 return err_badarg();
352 }
353 a[i] = getintvalue(v);
354 }
355 return 1;
356}
357
358int
359getlonglistarg(args, a, n)
360 object *args;
361 long *a; /* [n] */
362 int n;
363{
364 int i;
365 if (!is_listobject(args) || getlistsize(args) != n) {
366 return err_badarg();
367 }
368 for (i = 0; i < n; i++) {
369 object *v = getlistitem(args, i);
370 if (!is_intobject(v)) {
371 return err_badarg();
372 }
373 a[i] = getintvalue(v);
374 }
375 return 1;
376}
377
378int
379getshortlistarg(args, a, n)
380 object *args;
381 short *a; /* [n] */
382 int n;
383{
384 int i;
385 if (!is_listobject(args) || getlistsize(args) != n) {
386 return err_badarg();
387 }
388 for (i = 0; i < n; i++) {
389 object *v = getlistitem(args, i);
390 if (!is_intobject(v)) {
391 return err_badarg();
392 }
393 a[i] = getintvalue(v);
394 }
395 return 1;
396}
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000397
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000398
399/* Generic function to create a value -- the inverse of getargs() */
400/* After an original idea and first implementation by Steven Miale */
401
402static object *do_mktuple PROTO((char**, va_list *, int, int));
403static object *do_mkvalue PROTO((char**, va_list *));
404
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000405static object *
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000406do_mktuple(p_format, p_va, endchar, n)
407 char **p_format;
408 va_list *p_va;
409 int endchar;
410 int n;
411{
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000412 object *v;
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000413 int i;
414 if (n < 0)
415 return NULL;
416 if ((v = newtupleobject(n)) == NULL)
417 return NULL;
418 for (i = 0; i < n; i++) {
419 object *w = do_mkvalue(p_format, p_va);
420 if (w == NULL) {
421 DECREF(v);
422 return NULL;
423 }
424 settupleitem(v, i, w);
425 }
426 if (v != NULL && **p_format != endchar) {
427 DECREF(v);
428 v = NULL;
429 err_setstr(SystemError, "Unmatched paren in format");
430 }
431 else if (endchar)
432 ++*p_format;
433 return v;
434}
435
436static object *
Guido van Rossum899dcf31992-05-15 11:04:59 +0000437do_mkvalue(p_format, p_va)
438 char **p_format;
439 va_list *p_va;
440{
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000441
442 switch (*(*p_format)++) {
443
444 case '(':
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000445 return do_mktuple(p_format, p_va, ')',
446 countformat(*p_format, ')'));
447
448 case 'b':
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000449 case 'h':
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000450 case 'i':
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000451 return newintobject((long)va_arg(*p_va, int));
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000452
453 case 'l':
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000454 return newintobject((long)va_arg(*p_va, long));
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000455
456 case 'f':
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000457 case 'd':
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000458 return newfloatobject((double)va_arg(*p_va, double));
459
460 case 'c':
461 {
462 char p[1];
463 p[0] = va_arg(*p_va, int);
464 return newsizedstringobject(p, 1);
465 }
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000466
467 case 's':
468 case 'z':
469 {
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000470 object *v;
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000471 char *str = va_arg(*p_va, char *);
472 int n;
473 if (**p_format == '#') {
474 ++*p_format;
475 n = va_arg(*p_va, int);
476 }
477 else
478 n = -1;
479 if (str == NULL) {
480 v = None;
481 INCREF(v);
482 }
483 else {
484 if (n < 0)
485 n = strlen(str);
486 v = newsizedstringobject(str, n);
487 }
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000488 return v;
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000489 }
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000490
491 case 'S':
492 case 'O':
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000493 {
494 object *v;
495 v = va_arg(*p_va, object *);
496 if (v != NULL)
497 INCREF(v);
498 else if (!err_occurred())
499 /* If a NULL was passed because a call
500 that should have constructed a value
501 failed, that's OK, and we pass the error
502 on; but if no error occurred it's not
503 clear that the caller knew what she
504 was doing. */
505 err_setstr(SystemError,
506 "NULL object passed to mkvalue");
507 return v;
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000508 }
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000509
510 default:
511 err_setstr(SystemError, "bad format char passed to mkvalue");
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000512 return NULL;
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000513
514 }
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000515}
516
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000517#ifdef USE_STDARG
518/* VARARGS 2 */
519object *mkvalue(char *format, ...)
520#else
521/* VARARGS */
522object *mkvalue(va_alist) va_dcl
523#endif
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000524{
Guido van Rossumfc61adb1992-04-13 15:53:41 +0000525 int n;
526 char *f;
527 va_list va;
528 object* retval;
529#ifdef USE_STDARG
530 va_start(va, format);
531#else
532 char *format;
533
534 va_start(va);
535 format = va_arg(va, char *);
536#endif
537 f = format;
538 n = countformat(f, '\0');
539 if (n < 0)
540 retval = NULL; /* Error in the format */
541 else if (n == 0) {
542 retval = None;
543 INCREF(retval);
544 }
545 else if (n == 1)
546 retval = do_mkvalue(&f, &va);
547 else
548 retval = do_mktuple(&f, &va, '\0', n);
549 va_end(va);
550 if (retval == NULL)
551 fprintf(stderr, "format \"%s\", f \"%s\"\n", format, f);
552 return retval;
Guido van Rossum3cfe6fa1992-04-13 10:48:55 +0000553}