summaryrefslogtreecommitdiffstats
path: root/Objects/stringobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1994-08-30 08:19:36 (GMT)
committerGuido van Rossum <guido@python.org>1994-08-30 08:19:36 (GMT)
commit013142a95fd63a05d09cec7b36b7c86cc98e30c1 (patch)
treeeb39efa2a38a6d6c9b5caf6853738556e67618ca /Objects/stringobject.c
parente59214ed91cc2fdc5f1fd2367da8d8753c61aaea (diff)
downloadcpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.zip
cpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.tar.gz
cpython-013142a95fd63a05d09cec7b36b7c86cc98e30c1.tar.bz2
fix nasty bug in resizing (formatstring)
Diffstat (limited to 'Objects/stringobject.c')
-rw-r--r--Objects/stringobject.c116
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) {