diff options
author | Guido van Rossum <guido@python.org> | 1993-03-16 12:15:04 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1993-03-16 12:15:04 (GMT) |
commit | e537240c252ff678d49451ee6f80fa934653a724 (patch) | |
tree | b3dcbdb870e90f5843ac66f26a102ea4da444ff5 /Objects/stringobject.c | |
parent | f48b419a075dc237eb145e1b71cec12afdb7aff4 (diff) | |
download | cpython-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.c | 383 |
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; +} |