summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Python/Makefile.in2
-rw-r--r--Python/getargs.c587
-rw-r--r--Python/modsupport.c340
3 files changed, 588 insertions, 341 deletions
diff --git a/Python/Makefile.in b/Python/Makefile.in
index ba69a60..ef5b2ef 100644
--- a/Python/Makefile.in
+++ b/Python/Makefile.in
@@ -34,7 +34,7 @@ OBJS= \
ceval.o cgensupport.o compile.o \
errors.o \
frozenmain.o \
- getmtime.o graminit.o \
+ getargs.o getmtime.o graminit.o \
import.o \
marshal.o modsupport.o mystrtoul.o \
pythonmain.o pythonrun.o \
diff --git a/Python/getargs.c b/Python/getargs.c
new file mode 100644
index 0000000..605cb01
--- /dev/null
+++ b/Python/getargs.c
@@ -0,0 +1,587 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* New getargs implementation */
+
+/* XXX There are several unchecked sprintf or strcat calls in this file.
+ XXX The only way these can become a danger is if some C code in the
+ XXX Python source (or in an extension) uses ridiculously long names
+ XXX or riduculously deep nesting in format strings. */
+
+#include "allobjects.h"
+
+
+int getargs PROTO((object *, char *, ...));
+int newgetargs PROTO((object *, char *, ...));
+int vgetargs PROTO((object *, char *, va_list));
+
+
+/* Forward */
+static int vgetargs1 PROTO((object *, char *, va_list, int));
+static void seterror PROTO((int, char *, int *, char *, char *));
+static char *convertitem PROTO((object *, char **, va_list *, int *, char *));
+static char *converttuple PROTO((object *, char **, va_list *,
+ int *, char *, int));
+static char *convertsimple PROTO((object *, char **, va_list *, char *));
+static char *convertsimple1 PROTO((object *, char **, va_list *));
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+/* VARARGS2 */
+int getargs(object *args, char *format, ...)
+#else
+/* VARARGS */
+int getargs(va_alist) va_dcl
+#endif
+{
+ int retval;
+ va_list va;
+#ifdef HAVE_STDARG_PROTOTYPES
+
+ va_start(va, format);
+#else
+ object *args;
+ char *format;
+
+ va_start(va);
+ args = va_arg(va, object *);
+ format = va_arg(va, char *);
+#endif
+ retval = vgetargs1(args, format, va, 1);
+ va_end(va);
+ return retval;
+}
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+/* VARARGS2 */
+int newgetargs(object *args, char *format, ...)
+#else
+/* VARARGS */
+int newgetargs(va_alist) va_dcl
+#endif
+{
+ int retval;
+ va_list va;
+#ifdef HAVE_STDARG_PROTOTYPES
+
+ va_start(va, format);
+#else
+ object *args;
+ char *format;
+
+ va_start(va);
+ args = va_arg(va, object *);
+ format = va_arg(va, char *);
+#endif
+ retval = vgetargs1(args, format, va, 0);
+ va_end(va);
+ return retval;
+}
+
+
+int
+vgetargs(args, format, va)
+ object *args;
+ char *format;
+ va_list va;
+{
+ return vgetargs1(args, format, va, 0);
+}
+
+
+static int
+vgetargs1(args, format, va, compat)
+ object *args;
+ char *format;
+ va_list va;
+ int compat;
+{
+ char msgbuf[256];
+ int levels[32];
+ char *fname = NULL;
+ char *message = NULL;
+ int min = -1;
+ int max = 0;
+ int level = 0;
+ char *formatsave = format;
+ int i, len;
+ char *msg;
+
+ for (;;) {
+ int c = *format++;
+ if (c == '(' /* ')' */) {
+ if (level == 0)
+ max++;
+ level++;
+ }
+ else if (/* '(' */ c == ')') {
+ if (level == 0)
+ fatal(/* '(' */
+ "excess ')' in getargs format");
+ else
+ level--;
+ }
+ else if (c == '\0')
+ break;
+ else if (c == ':') {
+ fname = format;
+ break;
+ }
+ else if (c == ';') {
+ message = format;
+ break;
+ }
+ else if (level != 0)
+ ; /* Pass */
+ else if (isalpha(c))
+ max++;
+ else if (c == '|')
+ min = max;
+ }
+
+ if (level != 0)
+ fatal(/* '(' */ "missing ')' in getargs format");
+
+ if (min < 0)
+ min = max;
+
+ format = formatsave;
+
+ if (compat) {
+ if (max == 0) {
+ if (args == NULL)
+ return 1;
+ sprintf(msgbuf, "%s requires no arguments",
+ fname==NULL ? "function" : fname);
+ err_setstr(TypeError, msgbuf);
+ return 0;
+ }
+ else if (min == 1 && max == 1) {
+ msg = convertitem(args, &format, &va, levels, msgbuf);
+ if (msg == NULL)
+ return 1;
+ seterror(levels[0], msg, levels+1, fname, message);
+ return 0;
+ }
+ else {
+ err_setstr(SystemError,
+ "old style getargs format uses new features");
+ return 0;
+ }
+ }
+
+ if (!is_tupleobject(args)) {
+ err_setstr(SystemError,
+ "new style getargs format but argument is not a tuple");
+ return 0;
+ }
+
+ len = gettuplesize(args);
+
+ if (len < min || max < len) {
+ if (message == NULL) {
+ sprintf(msgbuf,
+ "%s requires %s %d argument%s; %d given",
+ fname==NULL ? "function" : fname,
+ min==max ? "exactly"
+ : len < min ? "at least" : "at most",
+ len < min ? min : max,
+ (len < min ? min : max) == 1 ? "" : "s",
+ len);
+ message = msgbuf;
+ }
+ err_setstr(TypeError, message);
+ return 0;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (*format == '|')
+ format++;
+ msg = convertitem(gettupleitem(args, i), &format, &va,
+ levels, msgbuf);
+ if (msg) {
+ seterror(i+1, msg, levels, fname, message);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+
+static void
+seterror(iarg, msg, levels, fname, message)
+ int iarg;
+ char *msg;
+ int *levels;
+ char *fname;
+ char *message;
+{
+ char buf[256];
+ int i;
+ char *p = buf;
+
+ if (iarg == 0 && message == NULL)
+ message = msg;
+ else if (message == NULL) {
+ if (fname != NULL) {
+ sprintf(p, "%s, ", fname);
+ p += strlen(p);
+ }
+ sprintf(p, "argument %d", iarg);
+ i = 0;
+ p += strlen(p);
+ while (levels[i] > 0) {
+ sprintf(p, ", item %d", levels[i]-1);
+ p += strlen(p);
+ i++;
+ }
+ sprintf(p, ": expected %s found", msg);
+ message = buf;
+ }
+ err_setstr(TypeError, message);
+}
+
+
+/* Convert a tuple argument.
+ On entry, *p_format points to the character _after_ the opening '('.
+ On successful exit, *p_format points to the closing ')'.
+ If successful:
+ *p_format and *p_va are updated,
+ *levels and *msgbuf are untouched,
+ and NULL is returned.
+ If the argument is invalid:
+ *p_format is unchanged,
+ *p_va is undefined,
+ *levels is a 0-terminated list of item numbers,
+ *msgbuf contains an error message, whose format is:
+ "<typename1>, <typename2>", where:
+ <typename1> is the name of the expected type, and
+ <typename2> is the name of the actual type,
+ (so you can surround it by "expected ... found"),
+ and msgbuf is returned.
+*/
+
+static char *
+converttuple(arg, p_format, p_va, levels, msgbuf, toplevel)
+ object *arg;
+ char **p_format;
+ va_list *p_va;
+ int *levels;
+ char *msgbuf;
+ int toplevel;
+{
+ int level = 0;
+ int n = 0;
+ char *format = *p_format;
+ int i;
+
+ for (;;) {
+ int c = *format++;
+ if (c == '(') {
+ if (level == 0)
+ n++;
+ level++;
+ }
+ else if (c == ')') {
+ if (level == 0)
+ break;
+ level--;
+ }
+ else if (c == ':' || c == ';' || c == '\0')
+ break;
+ else if (level == 0 && isalpha(c))
+ n++;
+ }
+
+ if (!is_tupleobject(arg)) {
+ levels[0] = 0;
+ sprintf(msgbuf,
+ toplevel ? "%d arguments, %s" : "%d-tuple, %s",
+ n, arg == None ? "None" : arg->ob_type->tp_name);
+ return msgbuf;
+ }
+
+ if ((i = gettuplesize(arg)) != n) {
+ levels[0] = 0;
+ sprintf(msgbuf,
+ toplevel ? "%d arguments, %d" : "%d-tuple, %d-tuple",
+ n, i);
+ return msgbuf;
+ }
+
+ format = *p_format;
+ for (i = 0; i < n; i++) {
+ char *msg;
+ msg = convertitem(gettupleitem(arg, i), &format, p_va,
+ levels+1, msgbuf);
+ if (msg != NULL) {
+ levels[0] = i+1;
+ return msg;
+ }
+ }
+
+ *p_format = format;
+ return NULL;
+}
+
+
+/* Convert a single item. */
+
+static char *
+convertitem(arg, p_format, p_va, levels, msgbuf)
+ object *arg;
+ char **p_format;
+ va_list *p_va;
+ int *levels;
+ char *msgbuf;
+{
+ char *msg;
+ char *format = *p_format;
+
+ if (*format == '(' /* ')' */) {
+ format++;
+ msg = converttuple(arg, &format, p_va, levels, msgbuf, 0);
+ if (msg == NULL)
+ format++;
+ }
+ else {
+ msg = convertsimple(arg, &format, p_va, msgbuf);
+ if (msg != NULL)
+ levels[0] = 0;
+ }
+ if (msg == NULL)
+ *p_format = format;
+ return msg;
+}
+
+
+/* Convert a non-tuple argument. Adds to convertsimple1 functionality
+ by appending ", <actual argument type>" to error message. */
+
+static char *
+convertsimple(arg, p_format, p_va, msgbuf)
+ object *arg;
+ char **p_format;
+ va_list *p_va;
+ char *msgbuf;
+{
+ char *msg = convertsimple1(arg, p_format, p_va);
+ if (msg != NULL) {
+ sprintf(msgbuf, "%.50s, %.50s", msg,
+ arg == None ? "None" : arg->ob_type->tp_name);
+ msg = msgbuf;
+ }
+ return msg;
+}
+
+
+/* Convert a non-tuple argument. Return NULL if conversion went OK,
+ or a string representing the expected type if the conversion failed.
+ When failing, an exception may or may not have been raised.
+ Don't call if a tuple is expected. */
+
+static char *
+convertsimple1(arg, p_format, p_va)
+ object *arg;
+ char **p_format;
+ va_list *p_va;
+{
+ char *format = *p_format;
+ char c = *format++;
+
+ switch (c) {
+
+ case 'b': /* byte -- very short int */
+ {
+ char *p = va_arg(*p_va, char *);
+ long ival = getintvalue(arg);
+ if (ival == -1 && err_occurred())
+ return "integer<b>";
+ else
+ *p = ival;
+ break;
+ }
+
+ case 'h': /* short int */
+ {
+ short *p = va_arg(*p_va, short *);
+ long ival = getintvalue(arg);
+ if (ival == -1 && err_occurred())
+ return "integer<h>";
+ else
+ *p = ival;
+ break;
+ }
+
+ case 'i': /* int */
+ {
+ int *p = va_arg(*p_va, int *);
+ long ival = getintvalue(arg);
+ if (ival == -1 && err_occurred())
+ return "integer<i>";
+ else
+ *p = ival;
+ break;
+ }
+
+ case 'l': /* long int */
+ {
+ long *p = va_arg(*p_va, long *);
+ long ival = getintvalue(arg);
+ if (ival == -1 && err_occurred())
+ return "integer<l>";
+ else
+ *p = ival;
+ break;
+ }
+
+ case 'f': /* float */
+ {
+ float *p = va_arg(*p_va, float *);
+ double dval = getfloatvalue(arg);
+ if (err_occurred())
+ return "float<f>";
+ else
+ *p = dval;
+ break;
+ }
+
+ case 'd': /* double */
+ {
+ double *p = va_arg(*p_va, double *);
+ double dval = getfloatvalue(arg);
+ if (err_occurred())
+ return "float<d>";
+ else
+ *p = dval;
+ break;
+ }
+
+ case 'c': /* char */
+ {
+ char *p = va_arg(*p_va, char *);
+ if (is_stringobject(arg) && getstringsize(arg) == 1)
+ *p = getstringvalue(arg)[0];
+ else
+ return "char";
+ break;
+ }
+
+ case 's': /* string */
+ {
+ char **p = va_arg(*p_va, char **);
+ if (is_stringobject(arg))
+ *p = getstringvalue(arg);
+ else
+ return "string";
+ if (*format == '#') {
+ int *q = va_arg(*p_va, int *);
+ *q = getstringsize(arg);
+ format++;
+ }
+ else if (strlen(*p) != getstringsize(arg))
+ return "string without null bytes";
+ break;
+ }
+
+ case 'z': /* string, may be NULL (None) */
+ {
+ char **p = va_arg(*p_va, char **);
+ if (arg == None)
+ *p = 0;
+ else if (is_stringobject(arg))
+ *p = getstringvalue(arg);
+ else
+ return "None or string";
+ if (*format == '#') {
+ int *q = va_arg(*p_va, int *);
+ if (arg == None)
+ *q = 0;
+ else
+ *q = getstringsize(arg);
+ format++;
+ }
+ else if (*p != NULL && strlen(*p) != getstringsize(arg))
+ return "None or string without null bytes";
+ break;
+ }
+
+ case 'S': /* string object */
+ {
+ object **p = va_arg(*p_va, object **);
+ if (is_stringobject(arg))
+ *p = arg;
+ else
+ return "string";
+ break;
+ }
+
+ case 'O': /* object */
+ {
+ typeobject *type;
+ object **p;
+ if (*format == '!') {
+ format++;
+ type = va_arg(*p_va, typeobject*);
+ if (arg->ob_type != type)
+ return type->tp_name;
+ else {
+ p = va_arg(*p_va, object **);
+ *p = arg;
+ }
+ }
+ else if (*format == '?') {
+ inquiry pred = va_arg(*p_va, inquiry);
+ format++;
+ if ((*pred)(arg)) {
+ p = va_arg(*p_va, object **);
+ *p = arg;
+ }
+ }
+ else if (*format == '&') {
+ typedef int (*converter) PROTO((object *, void *));
+ converter convert = va_arg(*p_va, converter);
+ void *addr = va_arg(*p_va, void *);
+ format++;
+ if (! (*convert)(arg, addr))
+ return "";
+ }
+ else {
+ p = va_arg(*p_va, object **);
+ *p = arg;
+ }
+ break;
+ }
+
+ default:
+ return "impossible<bad format char>";
+
+ }
+
+ *p_format = format;
+ return NULL;
+}
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 826e285..ae9a838 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -25,7 +25,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Module support implementation */
#include "allobjects.h"
-#include "modsupport.h"
#include "import.h"
#ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
@@ -111,345 +110,6 @@ static int countformat(format, endchar)
}
-/* Generic argument list parser */
-
-static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
-static int
-do_arg(arg, p_format, p_va)
- object *arg;
- char** p_format;
- va_list *p_va;
-{
- char *format = *p_format;
-
- if (arg == NULL)
- return 0; /* Incomplete tuple or list */
-
- switch (*format++) {
-
- case '(': /* tuple, distributed over C parameters */ {
- int i, n;
- if (!is_tupleobject(arg))
- return 0;
- n = gettuplesize(arg);
- for (i = 0; i < n; i++) {
- if (!do_arg(gettupleitem(arg, i), &format, p_va))
- return 0;
- }
- if (*format++ != ')')
- return 0;
- break;
- }
-
- case ')': /* End of format -- too many arguments */
- return 0;
-
- case 'b': /* byte -- very short int */ {
- char *p = va_arg(*p_va, char *);
- long ival = getintvalue(arg);
- if (ival == -1 && err_occurred())
- return 0;
- else
- *p = ival;
- break;
- }
-
- case 'h': /* short int */ {
- short *p = va_arg(*p_va, short *);
- long ival = getintvalue(arg);
- if (ival == -1 && err_occurred())
- return 0;
- else
- *p = ival;
- break;
- }
-
- case 'i': /* int */ {
- int *p = va_arg(*p_va, int *);
- long ival = getintvalue(arg);
- if (ival == -1 && err_occurred())
- return 0;
- else
- *p = ival;
- break;
- }
-
- case 'l': /* long int */ {
- long *p = va_arg(*p_va, long *);
- long ival = getintvalue(arg);
- if (ival == -1 && err_occurred())
- return 0;
- else
- *p = ival;
- break;
- }
-
- case 'f': /* float */ {
- float *p = va_arg(*p_va, float *);
- double dval = getfloatvalue(arg);
- if (err_occurred())
- return 0;
- else
- *p = dval;
- break;
- }
-
- case 'd': /* double */ {
- double *p = va_arg(*p_va, double *);
- double dval = getfloatvalue(arg);
- if (err_occurred())
- return 0;
- else
- *p = dval;
- break;
- }
-
- case 'c': /* char */ {
- char *p = va_arg(*p_va, char *);
- if (is_stringobject(arg) && getstringsize(arg) == 1)
- *p = getstringvalue(arg)[0];
- else
- return 0;
- break;
- }
-
- case 's': /* string */ {
- char **p = va_arg(*p_va, char **);
- if (is_stringobject(arg))
- *p = getstringvalue(arg);
- else
- return 0;
- if (*format == '#') {
- int *q = va_arg(*p_va, int *);
- *q = getstringsize(arg);
- format++;
- }
- else if (strlen(*p) != getstringsize(arg)) {
- err_setstr(ValueError, "embedded '\\0' in string arg");
- return 0;
- }
- break;
- }
-
- case 'z': /* string, may be NULL (None) */ {
- char **p = va_arg(*p_va, char **);
- if (arg == None)
- *p = 0;
- else if (is_stringobject(arg))
- *p = getstringvalue(arg);
- else
- return 0;
- if (*format == '#') {
- int *q = va_arg(*p_va, int *);
- if (arg == None)
- *q = 0;
- else
- *q = getstringsize(arg);
- format++;
- }
- else if (*p != NULL && strlen(*p) != getstringsize(arg)) {
- err_setstr(ValueError, "embedded '\\0' in string arg");
- return 0;
- }
- break;
- }
-
- case 'S': /* string object */ {
- object **p = va_arg(*p_va, object **);
- if (is_stringobject(arg))
- *p = arg;
- else
- return 0;
- break;
- }
-
- case 'O': /* object */ {
- typeobject *type;
- object **p;
- if (*format == '!') {
- format++;
- type = va_arg(*p_va, typeobject*);
- if (arg->ob_type != type)
- return 0;
- else {
- p = va_arg(*p_va, object **);
- *p = arg;
- }
- }
- else if (*format == '?') {
- inquiry pred = va_arg(*p_va, inquiry);
- format++;
- if ((*pred)(arg)) {
- p = va_arg(*p_va, object **);
- *p = arg;
- }
- }
- else if (*format == '&') {
- binaryfunc convert = va_arg(*p_va, binaryfunc);
- void *addr = va_arg(*p_va, void *);
- format++;
- if (! (*convert)(arg, addr))
- return 0;
- }
- else {
- p = va_arg(*p_va, object **);
- *p = arg;
- }
- break;
- }
-
- default:
- fprintf(stderr, "bad do_arg format: x%x '%c'\n",
- format[-1], format[-1]);
- return 0;
-
- }
-
- *p_format = format;
-
- return 1;
-}
-
-#ifdef HAVE_STDARG_PROTOTYPES
-/* VARARGS2 */
-int getargs(object *arg, char *format, ...)
-#else
-/* VARARGS */
-int getargs(va_alist) va_dcl
-#endif
-{
- char *f;
- int ok;
- va_list va;
-#ifdef HAVE_STDARG_PROTOTYPES
-
- va_start(va, format);
-#else
- object *arg;
- char *format;
-
- va_start(va);
- arg = va_arg(va, object *);
- format = va_arg(va, char *);
-#endif
- if (*format == '\0' || *format == ';') {
- va_end(va);
- if (arg != NULL) {
- char *str = "no arguments needed";
- if (*format == ';')
- str = format+1;
- err_setstr(TypeError, str);
- return 0;
- }
- return 1;
- }
-
- f = format;
- ok = do_arg(arg, &f, &va) && (*f == '\0' || *f == ';');
- va_end(va);
- if (!ok) {
- if (!err_occurred()) {
- char buf[256];
- char *str;
- f = strchr(format, ';');
- if (f != NULL)
- str = f+1;
- else {
- sprintf(buf, "bad argument list (format '%s')",
- format);
- str = buf;
- }
- err_setstr(TypeError, str);
- }
- }
- return ok;
-}
-
-#ifdef UNUSED
-
-int
-getlongtuplearg(args, a, n)
- object *args;
- long *a; /* [n] */
- int n;
-{
- int i;
- if (!is_tupleobject(args) || gettuplesize(args) != n) {
- return err_badarg();
- }
- for (i = 0; i < n; i++) {
- object *v = gettupleitem(args, i);
- if (!is_intobject(v)) {
- return err_badarg();
- }
- a[i] = getintvalue(v);
- }
- return 1;
-}
-
-int
-getshorttuplearg(args, a, n)
- object *args;
- short *a; /* [n] */
- int n;
-{
- int i;
- if (!is_tupleobject(args) || gettuplesize(args) != n) {
- return err_badarg();
- }
- for (i = 0; i < n; i++) {
- object *v = gettupleitem(args, i);
- if (!is_intobject(v)) {
- return err_badarg();
- }
- a[i] = getintvalue(v);
- }
- return 1;
-}
-
-int
-getlonglistarg(args, a, n)
- object *args;
- long *a; /* [n] */
- int n;
-{
- int i;
- if (!is_listobject(args) || getlistsize(args) != n) {
- return err_badarg();
- }
- for (i = 0; i < n; i++) {
- object *v = getlistitem(args, i);
- if (!is_intobject(v)) {
- return err_badarg();
- }
- a[i] = getintvalue(v);
- }
- return 1;
-}
-
-int
-getshortlistarg(args, a, n)
- object *args;
- short *a; /* [n] */
- int n;
-{
- int i;
- if (!is_listobject(args) || getlistsize(args) != n) {
- return err_badarg();
- }
- for (i = 0; i < n; i++) {
- object *v = getlistitem(args, i);
- if (!is_intobject(v)) {
- return err_badarg();
- }
- a[i] = getintvalue(v);
- }
- return 1;
-}
-
-#endif /* UNUSED */
-
-
/* Generic function to create a value -- the inverse of getargs() */
/* After an original idea and first implementation by Steven Miale */