Merged with Steve Miale's version
This commit is contained in:
parent
3cfe6faffe
commit
fc61adb5f1
|
@ -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));
|
||||||
|
@ -97,7 +127,16 @@ do_arg(arg, p_format, p_va)
|
||||||
return 0;
|
return 0;
|
||||||
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)
|
||||||
return 1;
|
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 *
|
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;
|
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)++) {
|
switch (*(*p_format)++) {
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
{
|
return do_mktuple(p_format, p_va, ')',
|
||||||
int n = 0;
|
countformat(*p_format, ')'));
|
||||||
char *p = *p_format;
|
|
||||||
int level = 0;
|
case 'b':
|
||||||
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;
|
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
v = newintobject((long)va_arg(*p_va, short));
|
|
||||||
break;
|
|
||||||
|
|
||||||
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) {
|
||||||
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':
|
||||||
v = va_arg(*p_va, object *);
|
{
|
||||||
if (v == NULL) {
|
object *v;
|
||||||
if (!err_occurred())
|
v = va_arg(*p_va, object *);
|
||||||
err_setstr(SystemError, "NULL object passed to mkvalue");
|
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:
|
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue