* Changed many files to use mkvalue() instead of newtupleobject().

* Fixcprt.py: added [-y file] option, do only files younger than file.
* modsupport.[ch]: added vmkvalue().
* intobject.c: use mkvalue().
* stringobject.c: added "formatstring"; renamed string* to string_*;
  ceval.c: call formatstring for string % value.
* longobject.c: close memory leak in divmod.
* parsetok.c: set result node to NULL when returning an error.
This commit is contained in:
Guido van Rossum 1993-03-16 12:15:04 +00:00
parent f48b419a07
commit e537240c25
21 changed files with 503 additions and 273 deletions

View file

@ -1,6 +1,6 @@
/***********************************************************
Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Netherlands.
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -61,7 +61,7 @@ newstringobject(str)
}
void
stringdealloc(op)
string_dealloc(op)
object *op;
{
DEL(op);
@ -92,7 +92,7 @@ getstringvalue(op)
/* Methods */
static int
stringprint(op, fp, flags)
string_print(op, fp, flags)
stringobject *op;
FILE *fp;
int flags;
@ -119,7 +119,7 @@ stringprint(op, fp, flags)
}
static object *
stringrepr(op)
string_repr(op)
register stringobject *op;
{
/* XXX overflow? */
@ -155,14 +155,14 @@ stringrepr(op)
}
static int
stringlength(a)
string_length(a)
stringobject *a;
{
return a->ob_size;
}
static object *
stringconcat(a, bb)
string_concat(a, bb)
register stringobject *a;
register object *bb;
{
@ -198,7 +198,7 @@ stringconcat(a, bb)
}
static object *
stringrepeat(a, n)
string_repeat(a, n)
register stringobject *a;
register int n;
{
@ -228,7 +228,7 @@ stringrepeat(a, n)
/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
static object *
stringslice(a, i, j)
string_slice(a, i, j)
register stringobject *a;
register int i, j; /* May be negative! */
{
@ -258,7 +258,7 @@ stringslice(a, i, j)
static object *characters[UCHAR_MAX + 1];
static object *
stringitem(a, i)
string_item(a, i)
stringobject *a;
register int i;
{
@ -282,7 +282,7 @@ stringitem(a, i)
}
static int
stringcompare(a, b)
string_compare(a, b)
stringobject *a, *b;
{
int len_a = a->ob_size, len_b = b->ob_size;
@ -294,11 +294,11 @@ stringcompare(a, b)
}
static sequence_methods string_as_sequence = {
stringlength, /*sq_length*/
stringconcat, /*sq_concat*/
stringrepeat, /*sq_repeat*/
stringitem, /*sq_item*/
stringslice, /*sq_slice*/
string_length, /*sq_length*/
string_concat, /*sq_concat*/
string_repeat, /*sq_repeat*/
string_item, /*sq_item*/
string_slice, /*sq_slice*/
0, /*sq_ass_item*/
0, /*sq_ass_slice*/
};
@ -309,12 +309,12 @@ typeobject Stringtype = {
"string",
sizeof(stringobject),
sizeof(char),
stringdealloc, /*tp_dealloc*/
stringprint, /*tp_print*/
string_dealloc, /*tp_dealloc*/
string_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
stringcompare, /*tp_compare*/
stringrepr, /*tp_repr*/
string_compare, /*tp_compare*/
string_repr, /*tp_repr*/
0, /*tp_as_number*/
&string_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
@ -328,7 +328,7 @@ joinstring(pv, w)
register object *v;
if (*pv == NULL || w == NULL || !is_stringobject(*pv))
return;
v = stringconcat((stringobject *) *pv, w);
v = string_concat((stringobject *) *pv, w);
DECREF(*pv);
*pv = v;
}
@ -373,3 +373,344 @@ resizestring(pv, newsize)
sv->ob_sval[newsize] = '\0';
return 0;
}
/* Helpers for formatstring */
static object *
getnextarg(args, arglen, p_argidx)
object *args;
int arglen;
int *p_argidx;
{
int argidx = *p_argidx;
if (argidx < arglen) {
(*p_argidx)++;
if (arglen < 0)
return args;
else
return gettupleitem(args, argidx);
}
err_setstr(TypeError, "not enough arguments for format string");
return NULL;
}
#define F_LJUST (1<<0)
#define F_SIGN (1<<1)
#define F_BLANK (1<<2)
#define F_ALT (1<<3)
#define F_ZERO (1<<4)
extern double fabs PROTO((double));
static char *
formatfloat(flags, prec, type, v)
int flags;
int prec;
int type;
object *v;
{
char fmt[20];
static char buf[120];
double x;
if (!getargs(v, "d;float argument required", &x))
return NULL;
if (prec < 0)
prec = 6;
if (prec > 50)
prec = 50; /* Arbitrary limitation */
if (type == 'f' && fabs(x)/1e25 >= 1e25)
type = 'g';
sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
sprintf(buf, fmt, x);
return buf;
}
static char *
formatint(flags, prec, type, v)
int flags;
int prec;
int type;
object *v;
{
char fmt[20];
static char buf[50];
long x;
if (!getargs(v, "l;int argument required", &x))
return NULL;
if (prec < 0)
prec = 1;
sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
sprintf(buf, fmt, x);
return buf;
}
static char *
formatchar(v)
object *v;
{
static char buf[2];
if (is_stringobject(v)) {
if (!getargs(v, "c;%c requires int or char", &buf[0]))
return NULL;
}
else {
if (!getargs(v, "b;%c requires int or char", &buf[0]))
return NULL;
}
buf[1] = '\0';
return buf;
}
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
object *
formatstring(format, args)
object *format;
object *args;
{
char *fmt, *res;
int fmtcnt, rescnt, reslen, arglen, argidx;
object *result;
if (format == NULL || !is_stringobject(format) || args == NULL) {
err_badcall();
return NULL;
}
reslen = rescnt = 100;
result = newsizedstringobject((char *)NULL, reslen);
if (result == NULL)
return NULL;
res = getstringvalue(result);
fmt = getstringvalue(format);
fmtcnt = getstringsize(format);
if (is_tupleobject(args)) {
arglen = gettuplesize(args);
argidx = 0;
}
else {
arglen = -1;
argidx = -2;
}
while (--fmtcnt >= 0) {
if (*fmt != '%') {
if (--rescnt < 0) {
rescnt = reslen;
reslen = reslen * 2; /* Maybe less when big? */
if (resizestring(&result, reslen) < 0)
return NULL;
res = getstringvalue(result) + rescnt;
rescnt = reslen - rescnt;
}
*res++ = *fmt++;
}
else {
/* Got a format specifier */
int flags = 0;
char *fmtstart = fmt++;
int width = -1;
int prec = -1;
int size = 0;
int c;
int fill;
object *v;
char *buf;
int sign;
int len;
while (--fmtcnt >= 0) {
switch (c = *fmt++) {
case '-': flags |= F_LJUST; continue;
case '+': flags |= F_SIGN; continue;
case ' ': flags |= F_BLANK; continue;
case '#': flags |= F_ALT; continue;
case '0': flags |= F_ZERO; continue;
}
break;
}
if (c == '*') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
goto error;
if (!is_intobject(v)) {
err_setstr(TypeError, "* wants int");
goto error;
}
width = getintvalue(v);
if (width < 0)
width = 0;
if (--fmtcnt >= 0)
c = *fmt++;
}
else if (isdigit(c)) {
width = c - '0';
while (--fmtcnt >= 0) {
c = *fmt++;
if (!isdigit(c))
break;
if ((width*10) / 10 != width) {
err_setstr(ValueError,
"width too big");
goto error;
}
width = width*10 + (c - '0');
}
}
if (c == '.') {
prec = 0;
if (--fmtcnt >= 0)
c = *fmt++;
if (c == '*') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
goto error;
if (!is_intobject(v)) {
err_setstr(TypeError,
"* wants int");
goto error;
}
prec = getintvalue(v);
if (prec < 0)
prec = 0;
if (--fmtcnt >= 0)
c = *fmt++;
}
else if (isdigit(c)) {
prec = c - '0';
while (--fmtcnt >= 0) {
c = *fmt++;
if (!isdigit(c))
break;
if ((prec*10) / 10 != prec) {
err_setstr(ValueError,
"prec too big");
goto error;
}
prec = prec*10 + (c - '0');
}
}
} /* prec */
if (fmtcnt >= 0) {
if (c == 'h' || c == 'l' || c == 'L') {
size = c;
if (--fmtcnt >= 0)
c = *fmt++;
}
}
if (fmtcnt < 0) {
err_setstr(ValueError, "incomplete format");
goto error;
}
if (c != '%') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
goto error;
}
sign = 0;
fill = ' ';
switch (c) {
case '%':
buf = "%";
len = 1;
break;
case 's':
if (!is_stringobject(v)) {
err_setstr(TypeError,
"%s wants string");
goto error;
}
buf = getstringvalue(v);
len = getstringsize(v);
if (prec >= 0 && len > prec)
len = prec;
break;
case 'i':
case 'd':
case 'u':
case 'o':
case 'x':
case 'X':
if (c == 'i')
c = 'd';
buf = formatint(flags, prec, c, v);
if (buf == NULL)
goto error;
len = strlen(buf);
sign = (c == 'd');
if (flags&F_ZERO)
fill = '0';
break;
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
buf = formatfloat(flags, prec, c, v);
if (buf == NULL)
goto error;
len = strlen(buf);
sign = 1;
if (flags&F_ZERO)
fill = '0';
break;
case 'c':
buf = formatchar(v);
if (buf == NULL)
goto error;
len = strlen(buf);
break;
default:
err_setstr(ValueError,
"unsupported format character");
goto error;
}
if (sign) {
if (*buf == '-' || *buf == '+') {
sign = *buf++;
len--;
}
else if (flags & F_SIGN)
sign = '+';
else if (flags & F_BLANK)
sign = ' ';
else
sign = '\0';
}
if (width < len)
width = len;
if (rescnt < width + (sign != '\0')) {
rescnt = reslen;
reslen = reslen + width + 100;
if (resizestring(&result, reslen) < 0)
return NULL;
res = getstringvalue(result) + rescnt;
rescnt = reslen - rescnt;
}
if (sign) {
*res++ = sign;
rescnt--;
if (width > len)
width--;
}
if (width > len && !(flags&F_LJUST)) {
do {
--rescnt;
*res++ = fill;
} while (--width > len);
}
memcpy(res, buf, len);
res += len;
rescnt -= len;
while (--width >= len) {
--rescnt;
*res++ = ' ';
}
} /* '%' */
} /* until end */
if (argidx < arglen) {
err_setstr(TypeError, "not all arguments converted");
goto error;
}
resizestring(&result, reslen - rescnt);
return result;
error:
DECREF(result);
return NULL;
}