summaryrefslogtreecommitdiffstats
path: root/Objects/stringobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1993-03-16 12:15:04 (GMT)
committerGuido van Rossum <guido@python.org>1993-03-16 12:15:04 (GMT)
commite537240c252ff678d49451ee6f80fa934653a724 (patch)
treeb3dcbdb870e90f5843ac66f26a102ea4da444ff5 /Objects/stringobject.c
parentf48b419a075dc237eb145e1b71cec12afdb7aff4 (diff)
downloadcpython-e537240c252ff678d49451ee6f80fa934653a724.zip
cpython-e537240c252ff678d49451ee6f80fa934653a724.tar.gz
cpython-e537240c252ff678d49451ee6f80fa934653a724.tar.bz2
* 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.
Diffstat (limited to 'Objects/stringobject.c')
-rw-r--r--Objects/stringobject.c383
1 files changed, 362 insertions, 21 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 9f8de92..25f12fc 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -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;
+}