blob: f66a82ccb8927cddb180bcebc0c1b54ae56d26df [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossume5372401993-03-16 12:15:04 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* String object implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +000029#ifdef COUNT_ALLOCS
30int null_strings, one_strings;
31#endif
32
33#ifdef __STDC__
34#include <limits.h>
35#else
36#ifndef UCHAR_MAX
37#define UCHAR_MAX 255
38#endif
39#endif
40
41static stringobject *characters[UCHAR_MAX + 1];
42static stringobject *nullstring;
43
44/*
45 Newsizedstringobject() and newstringobject() try in certain cases
46 to share string objects. When the size of the string is zero,
47 these routines always return a pointer to the same string object;
48 when the size is one, they return a pointer to an already existing
49 object if the contents of the string is known. For
50 newstringobject() this is always the case, for
51 newsizedstringobject() this is the case when the first argument in
52 not NULL.
53 A common practice to allocate a string and then fill it in or
54 change it must be done carefully. It is only allowed to change the
55 contents of the string if the obect was gotten from
56 newsizedstringobject() with a NULL first argument, because in the
57 future these routines may try to do even more sharing of objects.
58*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000059object *
60newsizedstringobject(str, size)
61 char *str;
62 int size;
63{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +000064 register stringobject *op;
65 if (size == 0 && (op = nullstring) != NULL) {
66#ifdef COUNT_ALLOCS
67 null_strings++;
68#endif
69 INCREF(op);
70 return op;
71 }
72 if (size == 1 && str != NULL && (op = characters[*str & UCHAR_MAX]) != NULL) {
73#ifdef COUNT_ALLOCS
74 one_strings++;
75#endif
76 INCREF(op);
77 return op;
78 }
79 op = (stringobject *)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000080 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000081 if (op == NULL)
82 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +000083 op->ob_type = &Stringtype;
84 op->ob_size = size;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +000085#ifdef CACHE_HASH
86 op->ob_shash = -1;
87#endif
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000088 NEWREF(op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000089 if (str != NULL)
90 memcpy(op->ob_sval, str, size);
91 op->ob_sval[size] = '\0';
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +000092 if (size == 0) {
93 nullstring = op;
94 INCREF(op);
95 } else if (size == 1 && str != NULL) {
96 characters[*str & UCHAR_MAX] = op;
97 INCREF(op);
98 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000099 return (object *) op;
100}
101
102object *
103newstringobject(str)
104 char *str;
105{
106 register unsigned int size = strlen(str);
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000107 register stringobject *op;
108 if (size == 0 && (op = nullstring) != NULL) {
109#ifdef COUNT_ALLOCS
110 null_strings++;
111#endif
112 INCREF(op);
113 return op;
114 }
115 if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
116#ifdef COUNT_ALLOCS
117 one_strings++;
118#endif
119 INCREF(op);
120 return op;
121 }
122 op = (stringobject *)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000124 if (op == NULL)
125 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000126 op->ob_type = &Stringtype;
127 op->ob_size = size;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000128#ifdef CACHE_HASH
129 op->ob_shash = -1;
130#endif
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000131 NEWREF(op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000132 strcpy(op->ob_sval, str);
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000133 if (size == 0) {
134 nullstring = op;
135 INCREF(op);
136 } else if (size == 1) {
137 characters[*str & UCHAR_MAX] = op;
138 INCREF(op);
139 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000140 return (object *) op;
141}
142
Guido van Rossum234f9421993-06-17 12:35:49 +0000143static void
Guido van Rossume5372401993-03-16 12:15:04 +0000144string_dealloc(op)
Guido van Rossum719f5fa1992-03-27 17:31:02 +0000145 object *op;
146{
147 DEL(op);
148}
149
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000150unsigned int
151getstringsize(op)
152 register object *op;
153{
154 if (!is_stringobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000155 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 return -1;
157 }
158 return ((stringobject *)op) -> ob_size;
159}
160
161/*const*/ char *
162getstringvalue(op)
163 register object *op;
164{
165 if (!is_stringobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000166 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 return NULL;
168 }
169 return ((stringobject *)op) -> ob_sval;
170}
171
172/* Methods */
173
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000174static int
Guido van Rossume5372401993-03-16 12:15:04 +0000175string_print(op, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000176 stringobject *op;
177 FILE *fp;
178 int flags;
179{
180 int i;
181 char c;
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000182 /* XXX Ought to check for interrupts when writing long strings */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000183 if (flags & PRINT_RAW) {
184 fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000185 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186 }
187 fprintf(fp, "'");
188 for (i = 0; i < op->ob_size; i++) {
189 c = op->ob_sval[i];
190 if (c == '\'' || c == '\\')
191 fprintf(fp, "\\%c", c);
192 else if (c < ' ' || c >= 0177)
193 fprintf(fp, "\\%03o", c&0377);
194 else
195 putc(c, fp);
196 }
197 fprintf(fp, "'");
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000198 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000199}
200
201static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000202string_repr(op)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000203 register stringobject *op;
204{
205 /* XXX overflow? */
206 int newsize = 2 + 4 * op->ob_size * sizeof(char);
207 object *v = newsizedstringobject((char *)NULL, newsize);
208 if (v == NULL) {
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000209 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000210 }
211 else {
212 register int i;
213 register char c;
214 register char *p;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000215 p = ((stringobject *)v)->ob_sval;
216 *p++ = '\'';
217 for (i = 0; i < op->ob_size; i++) {
218 c = op->ob_sval[i];
219 if (c == '\'' || c == '\\')
220 *p++ = '\\', *p++ = c;
221 else if (c < ' ' || c >= 0177) {
222 sprintf(p, "\\%03o", c&0377);
223 while (*p != '\0')
224 p++;
225
226 }
227 else
228 *p++ = c;
229 }
230 *p++ = '\'';
231 *p = '\0';
232 resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000233 return v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000234 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000235}
236
237static int
Guido van Rossume5372401993-03-16 12:15:04 +0000238string_length(a)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000239 stringobject *a;
240{
241 return a->ob_size;
242}
243
244static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000245string_concat(a, bb)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000246 register stringobject *a;
247 register object *bb;
248{
249 register unsigned int size;
250 register stringobject *op;
251 if (!is_stringobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000252 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000253 return NULL;
254 }
255#define b ((stringobject *)bb)
256 /* Optimize cases with empty left or right operand */
257 if (a->ob_size == 0) {
258 INCREF(bb);
259 return bb;
260 }
261 if (b->ob_size == 0) {
262 INCREF(a);
263 return (object *)a;
264 }
265 size = a->ob_size + b->ob_size;
266 op = (stringobject *)
267 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000268 if (op == NULL)
269 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000270 op->ob_type = &Stringtype;
271 op->ob_size = size;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000272#ifdef CACHE_HASH
273 op->ob_shash = -1;
274#endif
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000275 NEWREF(op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000276 memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
277 memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
278 op->ob_sval[size] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000279 return (object *) op;
280#undef b
281}
282
283static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000284string_repeat(a, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000285 register stringobject *a;
286 register int n;
287{
288 register int i;
289 register unsigned int size;
290 register stringobject *op;
291 if (n < 0)
292 n = 0;
293 size = a->ob_size * n;
294 if (size == a->ob_size) {
295 INCREF(a);
296 return (object *)a;
297 }
298 op = (stringobject *)
299 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000300 if (op == NULL)
301 return err_nomem();
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000302 op->ob_type = &Stringtype;
303 op->ob_size = size;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000304#ifdef CACHE_HASH
305 op->ob_shash = -1;
306#endif
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000307 NEWREF(op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000308 for (i = 0; i < size; i += a->ob_size)
309 memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
310 op->ob_sval[size] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000311 return (object *) op;
312}
313
314/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
315
316static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000317string_slice(a, i, j)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000318 register stringobject *a;
319 register int i, j; /* May be negative! */
320{
321 if (i < 0)
322 i = 0;
323 if (j < 0)
324 j = 0; /* Avoid signed/unsigned bug in next line */
325 if (j > a->ob_size)
326 j = a->ob_size;
327 if (i == 0 && j == a->ob_size) { /* It's the same as a */
328 INCREF(a);
329 return (object *)a;
330 }
331 if (j < i)
332 j = i;
333 return newsizedstringobject(a->ob_sval + i, (int) (j-i));
334}
335
336static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000337string_item(a, i)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000338 stringobject *a;
339 register int i;
340{
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000341 int c;
342 object *v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000343 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000344 err_setstr(IndexError, "string index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000345 return NULL;
346 }
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000347 c = a->ob_sval[i] & UCHAR_MAX;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000348 v = (object *) characters[c];
349#ifdef COUNT_ALLOCS
350 if (v != NULL)
351 one_strings++;
352#endif
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000353 if (v == NULL) {
354 v = newsizedstringobject((char *)NULL, 1);
355 if (v == NULL)
356 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000357 characters[c] = (stringobject *) v;
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000358 ((stringobject *)v)->ob_sval[0] = c;
359 }
360 INCREF(v);
361 return v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000362}
363
364static int
Guido van Rossume5372401993-03-16 12:15:04 +0000365string_compare(a, b)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000366 stringobject *a, *b;
367{
Guido van Rossum253919f1991-02-13 23:18:39 +0000368 int len_a = a->ob_size, len_b = b->ob_size;
369 int min_len = (len_a < len_b) ? len_a : len_b;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000370 int cmp;
371 if (min_len > 0) {
372 cmp = *a->ob_sval - *b->ob_sval;
373 if (cmp == 0)
374 cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
375 if (cmp != 0)
376 return cmp;
377 }
Guido van Rossum253919f1991-02-13 23:18:39 +0000378 return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000379}
380
Guido van Rossum9bfef441993-03-29 10:43:31 +0000381static long
382string_hash(a)
383 stringobject *a;
384{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000385 register int len;
386 register unsigned char *p;
387 register long x;
388
389#ifdef CACHE_HASH
390 if (a->ob_shash != -1)
391 return a->ob_shash;
392#endif
393 len = a->ob_size;
394 p = (unsigned char *) a->ob_sval;
395 x = *p << 7;
Guido van Rossum9bfef441993-03-29 10:43:31 +0000396 while (--len >= 0)
397 x = (x + x + x) ^ *p++;
398 x ^= a->ob_size;
399 if (x == -1)
400 x = -2;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000401#ifdef CACHE_HASH
402 a->ob_shash = x;
403#endif
Guido van Rossum9bfef441993-03-29 10:43:31 +0000404 return x;
405}
406
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000407static sequence_methods string_as_sequence = {
Guido van Rossume5372401993-03-16 12:15:04 +0000408 string_length, /*sq_length*/
409 string_concat, /*sq_concat*/
410 string_repeat, /*sq_repeat*/
411 string_item, /*sq_item*/
412 string_slice, /*sq_slice*/
Guido van Rossumf380e661991-06-04 19:36:32 +0000413 0, /*sq_ass_item*/
414 0, /*sq_ass_slice*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000415};
416
417typeobject Stringtype = {
418 OB_HEAD_INIT(&Typetype)
419 0,
420 "string",
421 sizeof(stringobject),
422 sizeof(char),
Guido van Rossume5372401993-03-16 12:15:04 +0000423 string_dealloc, /*tp_dealloc*/
424 string_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000425 0, /*tp_getattr*/
426 0, /*tp_setattr*/
Guido van Rossume5372401993-03-16 12:15:04 +0000427 string_compare, /*tp_compare*/
428 string_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000429 0, /*tp_as_number*/
430 &string_as_sequence, /*tp_as_sequence*/
431 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000432 string_hash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000433};
434
435void
436joinstring(pv, w)
437 register object **pv;
438 register object *w;
439{
440 register object *v;
441 if (*pv == NULL || w == NULL || !is_stringobject(*pv))
442 return;
Guido van Rossume5372401993-03-16 12:15:04 +0000443 v = string_concat((stringobject *) *pv, w);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000444 DECREF(*pv);
445 *pv = v;
446}
447
448/* The following function breaks the notion that strings are immutable:
449 it changes the size of a string. We get away with this only if there
450 is only one module referencing the object. You can also think of it
451 as creating a new string object and destroying the old one, only
452 more efficiently. In any case, don't use this if the string may
453 already be known to some other part of the code... */
454
455int
456resizestring(pv, newsize)
457 object **pv;
458 int newsize;
459{
Guido van Rossum921842f1990-11-18 17:30:23 +0000460 register object *v;
461 register stringobject *sv;
462 v = *pv;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000463 if (!is_stringobject(v) || v->ob_refcnt != 1) {
464 *pv = 0;
465 DECREF(v);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000466 err_badcall();
467 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000468 }
Guido van Rossum921842f1990-11-18 17:30:23 +0000469 /* XXX UNREF/NEWREF interface should be more symmetrical */
Guido van Rossum392ab321990-11-18 17:41:19 +0000470#ifdef REF_DEBUG
Guido van Rossum921842f1990-11-18 17:30:23 +0000471 --ref_total;
472#endif
473 UNREF(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000474 *pv = (object *)
475 realloc((char *)v,
476 sizeof(stringobject) + newsize * sizeof(char));
477 if (*pv == NULL) {
Guido van Rossum921842f1990-11-18 17:30:23 +0000478 DEL(v);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000479 err_nomem();
480 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000481 }
Guido van Rossum921842f1990-11-18 17:30:23 +0000482 NEWREF(*pv);
483 sv = (stringobject *) *pv;
484 sv->ob_size = newsize;
485 sv->ob_sval[newsize] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000486 return 0;
487}
Guido van Rossume5372401993-03-16 12:15:04 +0000488
489/* Helpers for formatstring */
490
491static object *
492getnextarg(args, arglen, p_argidx)
493 object *args;
494 int arglen;
495 int *p_argidx;
496{
497 int argidx = *p_argidx;
498 if (argidx < arglen) {
499 (*p_argidx)++;
500 if (arglen < 0)
501 return args;
502 else
503 return gettupleitem(args, argidx);
504 }
505 err_setstr(TypeError, "not enough arguments for format string");
506 return NULL;
507}
508
509#define F_LJUST (1<<0)
510#define F_SIGN (1<<1)
511#define F_BLANK (1<<2)
512#define F_ALT (1<<3)
513#define F_ZERO (1<<4)
514
515extern double fabs PROTO((double));
516
517static char *
518formatfloat(flags, prec, type, v)
519 int flags;
520 int prec;
521 int type;
522 object *v;
523{
524 char fmt[20];
525 static char buf[120];
526 double x;
527 if (!getargs(v, "d;float argument required", &x))
528 return NULL;
529 if (prec < 0)
530 prec = 6;
531 if (prec > 50)
532 prec = 50; /* Arbitrary limitation */
533 if (type == 'f' && fabs(x)/1e25 >= 1e25)
534 type = 'g';
535 sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
536 sprintf(buf, fmt, x);
537 return buf;
538}
539
540static char *
541formatint(flags, prec, type, v)
542 int flags;
543 int prec;
544 int type;
545 object *v;
546{
547 char fmt[20];
548 static char buf[50];
549 long x;
550 if (!getargs(v, "l;int argument required", &x))
551 return NULL;
552 if (prec < 0)
553 prec = 1;
554 sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
555 sprintf(buf, fmt, x);
556 return buf;
557}
558
559static char *
560formatchar(v)
561 object *v;
562{
563 static char buf[2];
564 if (is_stringobject(v)) {
565 if (!getargs(v, "c;%c requires int or char", &buf[0]))
566 return NULL;
567 }
568 else {
569 if (!getargs(v, "b;%c requires int or char", &buf[0]))
570 return NULL;
571 }
572 buf[1] = '\0';
573 return buf;
574}
575
576/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
577
578object *
579formatstring(format, args)
580 object *format;
581 object *args;
582{
583 char *fmt, *res;
584 int fmtcnt, rescnt, reslen, arglen, argidx;
585 object *result;
586 if (format == NULL || !is_stringobject(format) || args == NULL) {
587 err_badcall();
588 return NULL;
589 }
Guido van Rossum6ac258d1993-05-12 08:24:20 +0000590 fmt = getstringvalue(format);
591 fmtcnt = getstringsize(format);
592 reslen = rescnt = fmtcnt + 100;
Guido van Rossume5372401993-03-16 12:15:04 +0000593 result = newsizedstringobject((char *)NULL, reslen);
594 if (result == NULL)
595 return NULL;
596 res = getstringvalue(result);
Guido van Rossume5372401993-03-16 12:15:04 +0000597 if (is_tupleobject(args)) {
598 arglen = gettuplesize(args);
599 argidx = 0;
600 }
601 else {
602 arglen = -1;
603 argidx = -2;
604 }
605 while (--fmtcnt >= 0) {
606 if (*fmt != '%') {
607 if (--rescnt < 0) {
Guido van Rossum6ac258d1993-05-12 08:24:20 +0000608 rescnt = fmtcnt + 100;
609 reslen += rescnt;
Guido van Rossume5372401993-03-16 12:15:04 +0000610 if (resizestring(&result, reslen) < 0)
611 return NULL;
Guido van Rossum6ac258d1993-05-12 08:24:20 +0000612 res = getstringvalue(result) + reslen - rescnt;
Guido van Rossume5372401993-03-16 12:15:04 +0000613 }
614 *res++ = *fmt++;
615 }
616 else {
617 /* Got a format specifier */
618 int flags = 0;
619 char *fmtstart = fmt++;
620 int width = -1;
621 int prec = -1;
622 int size = 0;
623 int c;
624 int fill;
625 object *v;
626 char *buf;
627 int sign;
628 int len;
629 while (--fmtcnt >= 0) {
630 switch (c = *fmt++) {
631 case '-': flags |= F_LJUST; continue;
632 case '+': flags |= F_SIGN; continue;
633 case ' ': flags |= F_BLANK; continue;
634 case '#': flags |= F_ALT; continue;
635 case '0': flags |= F_ZERO; continue;
636 }
637 break;
638 }
639 if (c == '*') {
640 v = getnextarg(args, arglen, &argidx);
641 if (v == NULL)
642 goto error;
643 if (!is_intobject(v)) {
644 err_setstr(TypeError, "* wants int");
645 goto error;
646 }
647 width = getintvalue(v);
648 if (width < 0)
649 width = 0;
650 if (--fmtcnt >= 0)
651 c = *fmt++;
652 }
653 else if (isdigit(c)) {
654 width = c - '0';
655 while (--fmtcnt >= 0) {
656 c = *fmt++;
657 if (!isdigit(c))
658 break;
659 if ((width*10) / 10 != width) {
660 err_setstr(ValueError,
661 "width too big");
662 goto error;
663 }
664 width = width*10 + (c - '0');
665 }
666 }
667 if (c == '.') {
668 prec = 0;
669 if (--fmtcnt >= 0)
670 c = *fmt++;
671 if (c == '*') {
672 v = getnextarg(args, arglen, &argidx);
673 if (v == NULL)
674 goto error;
675 if (!is_intobject(v)) {
676 err_setstr(TypeError,
677 "* wants int");
678 goto error;
679 }
680 prec = getintvalue(v);
681 if (prec < 0)
682 prec = 0;
683 if (--fmtcnt >= 0)
684 c = *fmt++;
685 }
686 else if (isdigit(c)) {
687 prec = c - '0';
688 while (--fmtcnt >= 0) {
689 c = *fmt++;
690 if (!isdigit(c))
691 break;
692 if ((prec*10) / 10 != prec) {
693 err_setstr(ValueError,
694 "prec too big");
695 goto error;
696 }
697 prec = prec*10 + (c - '0');
698 }
699 }
700 } /* prec */
701 if (fmtcnt >= 0) {
702 if (c == 'h' || c == 'l' || c == 'L') {
703 size = c;
704 if (--fmtcnt >= 0)
705 c = *fmt++;
706 }
707 }
708 if (fmtcnt < 0) {
709 err_setstr(ValueError, "incomplete format");
710 goto error;
711 }
712 if (c != '%') {
713 v = getnextarg(args, arglen, &argidx);
714 if (v == NULL)
715 goto error;
716 }
717 sign = 0;
718 fill = ' ';
719 switch (c) {
720 case '%':
721 buf = "%";
722 len = 1;
723 break;
724 case 's':
725 if (!is_stringobject(v)) {
726 err_setstr(TypeError,
727 "%s wants string");
728 goto error;
729 }
730 buf = getstringvalue(v);
731 len = getstringsize(v);
732 if (prec >= 0 && len > prec)
733 len = prec;
734 break;
735 case 'i':
736 case 'd':
737 case 'u':
738 case 'o':
739 case 'x':
740 case 'X':
741 if (c == 'i')
742 c = 'd';
743 buf = formatint(flags, prec, c, v);
744 if (buf == NULL)
745 goto error;
746 len = strlen(buf);
747 sign = (c == 'd');
748 if (flags&F_ZERO)
749 fill = '0';
750 break;
751 case 'e':
752 case 'E':
753 case 'f':
754 case 'g':
755 case 'G':
756 buf = formatfloat(flags, prec, c, v);
757 if (buf == NULL)
758 goto error;
759 len = strlen(buf);
760 sign = 1;
761 if (flags&F_ZERO)
762 fill = '0';
763 break;
764 case 'c':
765 buf = formatchar(v);
766 if (buf == NULL)
767 goto error;
768 len = strlen(buf);
769 break;
770 default:
771 err_setstr(ValueError,
772 "unsupported format character");
773 goto error;
774 }
Guido van Rossum234f9421993-06-17 12:35:49 +0000775 /* XXX There's a bug somewhere here so that
776 XXX '%4d'%-1 yields '- 1' ... */
Guido van Rossume5372401993-03-16 12:15:04 +0000777 if (sign) {
778 if (*buf == '-' || *buf == '+') {
779 sign = *buf++;
780 len--;
781 }
782 else if (flags & F_SIGN)
783 sign = '+';
784 else if (flags & F_BLANK)
785 sign = ' ';
786 else
787 sign = '\0';
788 }
789 if (width < len)
790 width = len;
791 if (rescnt < width + (sign != '\0')) {
Guido van Rossum6ac258d1993-05-12 08:24:20 +0000792 reslen -= rescnt;
793 rescnt = width + fmtcnt + 100;
794 reslen += rescnt;
Guido van Rossume5372401993-03-16 12:15:04 +0000795 if (resizestring(&result, reslen) < 0)
796 return NULL;
Guido van Rossum6ac258d1993-05-12 08:24:20 +0000797 res = getstringvalue(result) + reslen - rescnt;
Guido van Rossume5372401993-03-16 12:15:04 +0000798 }
799 if (sign) {
800 *res++ = sign;
801 rescnt--;
802 if (width > len)
803 width--;
804 }
805 if (width > len && !(flags&F_LJUST)) {
806 do {
807 --rescnt;
808 *res++ = fill;
809 } while (--width > len);
810 }
811 memcpy(res, buf, len);
812 res += len;
813 rescnt -= len;
814 while (--width >= len) {
815 --rescnt;
816 *res++ = ' ';
817 }
818 } /* '%' */
819 } /* until end */
820 if (argidx < arglen) {
821 err_setstr(TypeError, "not all arguments converted");
822 goto error;
823 }
824 resizestring(&result, reslen - rescnt);
825 return result;
826 error:
827 DECREF(result);
828 return NULL;
829}