Commit fc61adb5 authored by Guido van Rossum's avatar Guido van Rossum

Merged with Steve Miale's version

parent 3cfe6faf
...@@ -67,6 +67,36 @@ initmodule(name, methods) ...@@ -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 */ /* Generic argument list parser */
static int do_arg PROTO((object *arg, char** p_format, va_list *p_va)); static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
...@@ -98,6 +128,15 @@ do_arg(arg, p_format, p_va) ...@@ -98,6 +128,15 @@ do_arg(arg, p_format, p_va)
break; 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 */ { case 'h': /* short int */ {
short *p = va_arg(va, short *); short *p = va_arg(va, short *);
if (is_intobject(arg)) if (is_intobject(arg))
...@@ -339,78 +378,76 @@ getshortlistarg(args, a, n) ...@@ -339,78 +378,76 @@ getshortlistarg(args, a, n)
return 1; return 1;
} }
static object *
do_mkval(char **p_format, va_list *p_va) {
object *v;
switch (*(*p_format)++) { /* Generic function to create a value -- the inverse of getargs() */
/* After an original idea and first implementation by Steven Miale */
case '(': static object *do_mktuple PROTO((char**, va_list *, int, int));
{ static object *do_mkvalue PROTO((char**, va_list *));
int n = 0;
char *p = *p_format; static object *
int level = 0; do_mktuple(p_format, p_va, endchar, n)
char **p_format;
va_list *p_va;
int endchar;
int n;
{
object *v;
int i; int i;
while (level > 0 || *p != ')') { if (n < 0)
if (*p == '\0') { return NULL;
err_setstr(SystemError, "missing ')' in mkvalue format"); if ((v = newtupleobject(n)) == NULL)
return NULL; 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++) { for (i = 0; i < n; i++) {
object *w = do_mkval(p_format, p_va); object *w = do_mkvalue(p_format, p_va);
if (w == NULL) { if (w == NULL) {
DECREF(v); DECREF(v);
v = NULL; return NULL;
break;
} }
settupleitem(v, i, w); settupleitem(v, i, w);
} }
if (v != NULL && *(*p_format)++ != ')') { if (v != NULL && **p_format != endchar) {
/* "Cannot happen" */
err_setstr(SystemError, "inconsistent format in mkvalue???");
DECREF(v); DECREF(v);
v = NULL; v = NULL;
err_setstr(SystemError, "Unmatched paren in format");
} }
} else if (endchar)
break; ++*p_format;
return v;
}
case 'h': static object *
v = newintobject((long)va_arg(*p_va, short)); do_mkvalue(p_format, p_va) {
break;
switch (*(*p_format)++) {
case '(':
return do_mktuple(p_format, p_va, ')',
countformat(*p_format, ')'));
case 'b':
case 'h':
case 'i': case 'i':
v = newintobject((long)va_arg(*p_va, int)); return newintobject((long)va_arg(*p_va, int));
break;
case 'l': case 'l':
v = newintobject((long)va_arg(*p_va, long)); return newintobject((long)va_arg(*p_va, long));
break;
case 'f': case 'f':
v = newfloatobject((double)va_arg(*p_va, float));
break;
case 'd': case 'd':
v = newfloatobject((double)va_arg(*p_va, double)); return newfloatobject((double)va_arg(*p_va, double));
break;
case 'c':
{
char p[1];
p[0] = va_arg(*p_va, int);
return newsizedstringobject(p, 1);
}
case 's': case 's':
case 'z': case 'z':
{ {
object *v;
char *str = va_arg(*p_va, char *); char *str = va_arg(*p_va, char *);
int n; int n;
if (**p_format == '#') { if (**p_format == '#') {
...@@ -428,40 +465,69 @@ do_mkval(char **p_format, va_list *p_va) { ...@@ -428,40 +465,69 @@ do_mkval(char **p_format, va_list *p_va) {
n = strlen(str); n = strlen(str);
v = newsizedstringobject(str, n); v = newsizedstringobject(str, n);
} }
return v;
} }
break;
case 'S': case 'S':
case 'O': case 'O':
{
object *v;
v = va_arg(*p_va, object *); v = va_arg(*p_va, object *);
if (v == NULL) { if (v != NULL)
if (!err_occurred())
err_setstr(SystemError, "NULL object passed to mkvalue");
}
else
INCREF(v); INCREF(v);
break; 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;
}
default: default:
err_setstr(SystemError, "bad format char passed to mkvalue"); err_setstr(SystemError, "bad format char passed to mkvalue");
v = NULL; return NULL;
break;
} }
return v;
} }
object * #ifdef USE_STDARG
mkvalue(char *format, ...) /* VARARGS 2 */
object *mkvalue(char *format, ...)
#else
/* VARARGS */
object *mkvalue(va_alist) va_dcl
#endif
{ {
char *fmt = format; int n;
object *v; char *f;
va_list p; va_list va;
va_start(p, format); object* retval;
v = do_mkval(&fmt, &p); #ifdef USE_STDARG
va_end(p); va_start(va, format);
if (v == NULL) #else
fprintf(stderr, "mkvalue: format = \"%s\" \"%s\"\n", format, fmt); char *format;
return v;
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;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment