diff options
author | Guido van Rossum <guido@python.org> | 1994-08-30 08:19:36 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1994-08-30 08:19:36 (GMT) |
commit | 013142a95fd63a05d09cec7b36b7c86cc98e30c1 (patch) | |
tree | eb39efa2a38a6d6c9b5caf6853738556e67618ca | |
parent | e59214ed91cc2fdc5f1fd2367da8d8753c61aaea (diff) | |
download | cpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.zip cpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.tar.gz cpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.tar.bz2 |
fix nasty bug in resizing (formatstring)
-rw-r--r-- | Objects/stringobject.c | 116 |
1 files changed, 98 insertions, 18 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c index ed5af57..4221d68 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -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) { |