fix nasty bug in resizing (formatstring)
This commit is contained in:
parent
e59214ed91
commit
013142a95f
|
@ -1,5 +1,5 @@
|
|||
/***********************************************************
|
||||
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
|
||||
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
|
||||
Amsterdam, The Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include "allobjects.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef COUNT_ALLOCS
|
||||
int null_strings, one_strings;
|
||||
#endif
|
||||
|
@ -428,11 +430,11 @@ string_hash(a)
|
|||
}
|
||||
|
||||
static sequence_methods string_as_sequence = {
|
||||
string_length, /*sq_length*/
|
||||
string_concat, /*sq_concat*/
|
||||
string_repeat, /*sq_repeat*/
|
||||
string_item, /*sq_item*/
|
||||
string_slice, /*sq_slice*/
|
||||
(inquiry)string_length, /*sq_length*/
|
||||
(binaryfunc)string_concat, /*sq_concat*/
|
||||
(intargfunc)string_repeat, /*sq_repeat*/
|
||||
(intargfunc)string_item, /*sq_item*/
|
||||
(intintargfunc)string_slice, /*sq_slice*/
|
||||
0, /*sq_ass_item*/
|
||||
0, /*sq_ass_slice*/
|
||||
};
|
||||
|
@ -443,16 +445,16 @@ typeobject Stringtype = {
|
|||
"string",
|
||||
sizeof(stringobject),
|
||||
sizeof(char),
|
||||
string_dealloc, /*tp_dealloc*/
|
||||
string_print, /*tp_print*/
|
||||
(destructor)string_dealloc, /*tp_dealloc*/
|
||||
(printfunc)string_print, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
string_compare, /*tp_compare*/
|
||||
string_repr, /*tp_repr*/
|
||||
(cmpfunc)string_compare, /*tp_compare*/
|
||||
(reprfunc)string_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
&string_as_sequence, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
string_hash, /*tp_hash*/
|
||||
(hashfunc)string_hash, /*tp_hash*/
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -461,13 +463,28 @@ joinstring(pv, w)
|
|||
register object *w;
|
||||
{
|
||||
register object *v;
|
||||
if (*pv == NULL || w == NULL || !is_stringobject(*pv))
|
||||
if (*pv == NULL)
|
||||
return;
|
||||
if (w == NULL || !is_stringobject(*pv)) {
|
||||
DECREF(*pv);
|
||||
*pv = NULL;
|
||||
return;
|
||||
}
|
||||
v = string_concat((stringobject *) *pv, w);
|
||||
DECREF(*pv);
|
||||
*pv = v;
|
||||
}
|
||||
|
||||
void
|
||||
joinstring_decref(pv, w)
|
||||
register object **pv;
|
||||
register object *w;
|
||||
{
|
||||
joinstring(pv, w);
|
||||
XDECREF(w);
|
||||
}
|
||||
|
||||
|
||||
/* The following function breaks the notion that strings are immutable:
|
||||
it changes the size of a string. We get away with this only if there
|
||||
is only one module referencing the object. You can also think of it
|
||||
|
@ -596,6 +613,27 @@ formatchar(v)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/* XXX this could be moved to object.c */
|
||||
static object *
|
||||
get_mapping_item(mo, ko)
|
||||
object *mo;
|
||||
object *ko;
|
||||
{
|
||||
mapping_methods *mm = mo->ob_type->tp_as_mapping;
|
||||
object *val;
|
||||
|
||||
if (!mm || !mm->mp_subscript) {
|
||||
err_setstr(TypeError, "subscript not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
val = (*mm->mp_subscript)(mo, ko);
|
||||
XDECREF(val); /* still in mapping */
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
|
||||
|
||||
object *
|
||||
|
@ -606,6 +644,7 @@ formatstring(format, args)
|
|||
char *fmt, *res;
|
||||
int fmtcnt, rescnt, reslen, arglen, argidx;
|
||||
object *result;
|
||||
object *dict = NULL;
|
||||
if (format == NULL || !is_stringobject(format) || args == NULL) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
|
@ -625,6 +664,8 @@ formatstring(format, args)
|
|||
arglen = -1;
|
||||
argidx = -2;
|
||||
}
|
||||
if (args->ob_type->tp_as_mapping)
|
||||
dict = args;
|
||||
while (--fmtcnt >= 0) {
|
||||
if (*fmt != '%') {
|
||||
if (--rescnt < 0) {
|
||||
|
@ -633,6 +674,7 @@ formatstring(format, args)
|
|||
if (resizestring(&result, reslen) < 0)
|
||||
return NULL;
|
||||
res = getstringvalue(result) + reslen - rescnt;
|
||||
--rescnt;
|
||||
}
|
||||
*res++ = *fmt++;
|
||||
}
|
||||
|
@ -646,9 +688,43 @@ formatstring(format, args)
|
|||
int c = '\0';
|
||||
int fill;
|
||||
object *v;
|
||||
object *temp = NULL;
|
||||
char *buf;
|
||||
int sign;
|
||||
int len;
|
||||
if (*fmt == '(') {
|
||||
char *keystart;
|
||||
int keylen;
|
||||
object *key;
|
||||
|
||||
if (dict == NULL) {
|
||||
err_setstr(TypeError,
|
||||
"format requires a mapping");
|
||||
goto error;
|
||||
}
|
||||
++fmt;
|
||||
--fmtcnt;
|
||||
keystart = fmt;
|
||||
while (--fmtcnt >= 0 && *fmt != ')')
|
||||
fmt++;
|
||||
keylen = fmt - keystart;
|
||||
++fmt;
|
||||
if (fmtcnt < 0) {
|
||||
err_setstr(ValueError,
|
||||
"incomplete format key");
|
||||
goto error;
|
||||
}
|
||||
key = newsizedstringobject(keystart, keylen);
|
||||
if (key == NULL)
|
||||
goto error;
|
||||
args = get_mapping_item(dict, key);
|
||||
DECREF(key);
|
||||
if (args == NULL) {
|
||||
goto error;
|
||||
}
|
||||
arglen = -1;
|
||||
argidx = -2;
|
||||
}
|
||||
while (--fmtcnt >= 0) {
|
||||
switch (c = *fmt++) {
|
||||
case '-': flags |= F_LJUST; continue;
|
||||
|
@ -745,13 +821,11 @@ formatstring(format, args)
|
|||
len = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (!is_stringobject(v)) {
|
||||
err_setstr(TypeError,
|
||||
"%s wants string");
|
||||
temp = strobject(v);
|
||||
if (temp == NULL)
|
||||
goto error;
|
||||
}
|
||||
buf = getstringvalue(v);
|
||||
len = getstringsize(v);
|
||||
buf = getstringvalue(temp);
|
||||
len = getstringsize(temp);
|
||||
if (prec >= 0 && len > prec)
|
||||
len = prec;
|
||||
break;
|
||||
|
@ -839,6 +913,12 @@ formatstring(format, args)
|
|||
--rescnt;
|
||||
*res++ = ' ';
|
||||
}
|
||||
if (dict && (argidx < arglen)) {
|
||||
err_setstr(TypeError,
|
||||
"not all arguments converted");
|
||||
goto error;
|
||||
}
|
||||
XDECREF(temp);
|
||||
} /* '%' */
|
||||
} /* until end */
|
||||
if (argidx < arglen) {
|
||||
|
|
Loading…
Reference in New Issue