mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
* 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:
parent
f48b419a07
commit
e537240c25
21 changed files with 503 additions and 273 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue