summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-04-13 15:53:41 (GMT)
committerGuido van Rossum <guido@python.org>1992-04-13 15:53:41 (GMT)
commitfc61adb5f1b562935557a79c9e024fa1eb6e8db1 (patch)
tree9394ded5d364046e475c584656cee086bda84d8a
parent3cfe6faffeaddd64355d16c358894a31b72e5450 (diff)
downloadcpython-fc61adb5f1b562935557a79c9e024fa1eb6e8db1.zip
cpython-fc61adb5f1b562935557a79c9e024fa1eb6e8db1.tar.gz
cpython-fc61adb5f1b562935557a79c9e024fa1eb6e8db1.tar.bz2
Merged with Steve Miale's version
-rw-r--r--Python/modsupport.c224
1 files changed, 145 insertions, 79 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 6dcac00..8b47296 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -67,6 +67,36 @@ initmodule(name, methods)
}
+/* Helper for getargs() and mkvalue() to scan the length of a format */
+
+static int countformat PROTO((char *format, int endchar));
+static int countformat(format, endchar)
+ char *format;
+ int endchar;
+{
+ int count = 0;
+ int level = 0;
+ while (level > 0 || *format != endchar) {
+ if (*format == '\0') {
+ /* Premature end */
+ err_setstr(SystemError, "unmatched paren in format");
+ return -1;
+ }
+ else if (*format == '(') {
+ if (level == 0)
+ count++;
+ level++;
+ }
+ else if (*format == ')')
+ level--;
+ else if (level == 0 && *format != '#')
+ count++;
+ format++;
+ }
+ return count;
+}
+
+
/* Generic argument list parser */
static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
@@ -97,7 +127,16 @@ do_arg(arg, p_format, p_va)
return 0;
break;
}
-
+
+ case 'b': /* byte -- very short int */ {
+ char *p = va_arg(va, char *);
+ if (is_intobject(arg))
+ *p = getintvalue(arg);
+ else
+ return 0;
+ break;
+ }
+
case 'h': /* short int */ {
short *p = va_arg(va, short *);
if (is_intobject(arg))
@@ -339,78 +378,76 @@ getshortlistarg(args, a, n)
return 1;
}
+
+/* Generic function to create a value -- the inverse of getargs() */
+/* After an original idea and first implementation by Steven Miale */
+
+static object *do_mktuple PROTO((char**, va_list *, int, int));
+static object *do_mkvalue PROTO((char**, va_list *));
+
static object *
-do_mkval(char **p_format, va_list *p_va) {
+do_mktuple(p_format, p_va, endchar, n)
+ char **p_format;
+ va_list *p_va;
+ int endchar;
+ int n;
+{
object *v;
+ int i;
+ if (n < 0)
+ return NULL;
+ if ((v = newtupleobject(n)) == NULL)
+ return NULL;
+ for (i = 0; i < n; i++) {
+ object *w = do_mkvalue(p_format, p_va);
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ settupleitem(v, i, w);
+ }
+ if (v != NULL && **p_format != endchar) {
+ DECREF(v);
+ v = NULL;
+ err_setstr(SystemError, "Unmatched paren in format");
+ }
+ else if (endchar)
+ ++*p_format;
+ return v;
+}
+
+static object *
+do_mkvalue(p_format, p_va) {
switch (*(*p_format)++) {
case '(':
- {
- int n = 0;
- char *p = *p_format;
- int level = 0;
- int i;
- while (level > 0 || *p != ')') {
- if (*p == '\0') {
- err_setstr(SystemError, "missing ')' in mkvalue format");
- return NULL;
- }
- else if (*p == '(') {
- if (level == 0)
- n++;
- level++;
- }
- else if (*p == ')')
- level--;
- else if (level == 0 && *p != '#')
- n++;
- p++;
- }
- v = newtupleobject(n);
- if (v == NULL)
- break;
- for (i = 0; i < n; i++) {
- object *w = do_mkval(p_format, p_va);
- if (w == NULL) {
- DECREF(v);
- v = NULL;
- break;
- }
- settupleitem(v, i, w);
- }
- if (v != NULL && *(*p_format)++ != ')') {
- /* "Cannot happen" */
- err_setstr(SystemError, "inconsistent format in mkvalue???");
- DECREF(v);
- v = NULL;
- }
- }
- break;
-
+ return do_mktuple(p_format, p_va, ')',
+ countformat(*p_format, ')'));
+
+ case 'b':
case 'h':
- v = newintobject((long)va_arg(*p_va, short));
- break;
-
case 'i':
- v = newintobject((long)va_arg(*p_va, int));
- break;
+ return newintobject((long)va_arg(*p_va, int));
case 'l':
- v = newintobject((long)va_arg(*p_va, long));
- break;
+ return newintobject((long)va_arg(*p_va, long));
case 'f':
- v = newfloatobject((double)va_arg(*p_va, float));
- break;
-
case 'd':
- v = newfloatobject((double)va_arg(*p_va, double));
- break;
+ return newfloatobject((double)va_arg(*p_va, double));
+
+ case 'c':
+ {
+ char p[1];
+ p[0] = va_arg(*p_va, int);
+ return newsizedstringobject(p, 1);
+ }
case 's':
case 'z':
{
+ object *v;
char *str = va_arg(*p_va, char *);
int n;
if (**p_format == '#') {
@@ -428,40 +465,69 @@ do_mkval(char **p_format, va_list *p_va) {
n = strlen(str);
v = newsizedstringobject(str, n);
}
+ return v;
}
- break;
case 'S':
case 'O':
- v = va_arg(*p_va, object *);
- if (v == NULL) {
- if (!err_occurred())
- err_setstr(SystemError, "NULL object passed to mkvalue");
+ {
+ object *v;
+ v = va_arg(*p_va, object *);
+ if (v != NULL)
+ INCREF(v);
+ else if (!err_occurred())
+ /* If a NULL was passed because a call
+ that should have constructed a value
+ failed, that's OK, and we pass the error
+ on; but if no error occurred it's not
+ clear that the caller knew what she
+ was doing. */
+ err_setstr(SystemError,
+ "NULL object passed to mkvalue");
+ return v;
}
- else
- INCREF(v);
- break;
default:
err_setstr(SystemError, "bad format char passed to mkvalue");
- v = NULL;
- break;
+ return NULL;
}
-
- return v;
}
-object *
-mkvalue(char *format, ...)
+#ifdef USE_STDARG
+/* VARARGS 2 */
+object *mkvalue(char *format, ...)
+#else
+/* VARARGS */
+object *mkvalue(va_alist) va_dcl
+#endif
{
- char *fmt = format;
- object *v;
- va_list p;
- va_start(p, format);
- v = do_mkval(&fmt, &p);
- va_end(p);
- if (v == NULL)
- fprintf(stderr, "mkvalue: format = \"%s\" \"%s\"\n", format, fmt);
- return v;
+ int n;
+ char *f;
+ va_list va;
+ object* retval;
+#ifdef USE_STDARG
+ va_start(va, format);
+#else
+ char *format;
+
+ va_start(va);
+ format = va_arg(va, char *);
+#endif
+ f = format;
+ n = countformat(f, '\0');
+ if (n < 0)
+ retval = NULL; /* Error in the format */
+ else if (n == 0) {
+ retval = None;
+ INCREF(retval);
+ }
+ else if (n == 1)
+ retval = do_mkvalue(&f, &va);
+ else
+ retval = do_mktuple(&f, &va, '\0', n);
+ va_end(va);
+ if (retval == NULL)
+ fprintf(stderr, "format \"%s\", f \"%s\"\n", format, f);
+ return retval;
}