blob: 25f12fc36d0d3250fdf0b4be25c360bdad827bd3 [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
29object *
30newsizedstringobject(str, size)
31 char *str;
32 int size;
33{
34 register stringobject *op = (stringobject *)
35 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000036 if (op == NULL)
37 return err_nomem();
38 NEWREF(op);
39 op->ob_type = &Stringtype;
40 op->ob_size = size;
41 if (str != NULL)
42 memcpy(op->ob_sval, str, size);
43 op->ob_sval[size] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044 return (object *) op;
45}
46
47object *
48newstringobject(str)
49 char *str;
50{
51 register unsigned int size = strlen(str);
52 register stringobject *op = (stringobject *)
53 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000054 if (op == NULL)
55 return err_nomem();
56 NEWREF(op);
57 op->ob_type = &Stringtype;
58 op->ob_size = size;
59 strcpy(op->ob_sval, str);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000060 return (object *) op;
61}
62
Guido van Rossum719f5fa1992-03-27 17:31:02 +000063void
Guido van Rossume5372401993-03-16 12:15:04 +000064string_dealloc(op)
Guido van Rossum719f5fa1992-03-27 17:31:02 +000065 object *op;
66{
67 DEL(op);
68}
69
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000070unsigned int
71getstringsize(op)
72 register object *op;
73{
74 if (!is_stringobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000075 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 return -1;
77 }
78 return ((stringobject *)op) -> ob_size;
79}
80
81/*const*/ char *
82getstringvalue(op)
83 register object *op;
84{
85 if (!is_stringobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000086 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000087 return NULL;
88 }
89 return ((stringobject *)op) -> ob_sval;
90}
91
92/* Methods */
93
Guido van Rossumbcaa31c1991-06-07 22:58:57 +000094static int
Guido van Rossume5372401993-03-16 12:15:04 +000095string_print(op, fp, flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000096 stringobject *op;
97 FILE *fp;
98 int flags;
99{
100 int i;
101 char c;
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000102 /* XXX Ought to check for interrupts when writing long strings */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000103 if (flags & PRINT_RAW) {
104 fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000105 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000106 }
107 fprintf(fp, "'");
108 for (i = 0; i < op->ob_size; i++) {
109 c = op->ob_sval[i];
110 if (c == '\'' || c == '\\')
111 fprintf(fp, "\\%c", c);
112 else if (c < ' ' || c >= 0177)
113 fprintf(fp, "\\%03o", c&0377);
114 else
115 putc(c, fp);
116 }
117 fprintf(fp, "'");
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000118 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000119}
120
121static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000122string_repr(op)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000123 register stringobject *op;
124{
125 /* XXX overflow? */
126 int newsize = 2 + 4 * op->ob_size * sizeof(char);
127 object *v = newsizedstringobject((char *)NULL, newsize);
128 if (v == NULL) {
Guido van Rossumbcaa31c1991-06-07 22:58:57 +0000129 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 }
131 else {
132 register int i;
133 register char c;
134 register char *p;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000135 p = ((stringobject *)v)->ob_sval;
136 *p++ = '\'';
137 for (i = 0; i < op->ob_size; i++) {
138 c = op->ob_sval[i];
139 if (c == '\'' || c == '\\')
140 *p++ = '\\', *p++ = c;
141 else if (c < ' ' || c >= 0177) {
142 sprintf(p, "\\%03o", c&0377);
143 while (*p != '\0')
144 p++;
145
146 }
147 else
148 *p++ = c;
149 }
150 *p++ = '\'';
151 *p = '\0';
152 resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000153 return v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155}
156
157static int
Guido van Rossume5372401993-03-16 12:15:04 +0000158string_length(a)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000159 stringobject *a;
160{
161 return a->ob_size;
162}
163
164static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000165string_concat(a, bb)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166 register stringobject *a;
167 register object *bb;
168{
169 register unsigned int size;
170 register stringobject *op;
171 if (!is_stringobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000172 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 return NULL;
174 }
175#define b ((stringobject *)bb)
176 /* Optimize cases with empty left or right operand */
177 if (a->ob_size == 0) {
178 INCREF(bb);
179 return bb;
180 }
181 if (b->ob_size == 0) {
182 INCREF(a);
183 return (object *)a;
184 }
185 size = a->ob_size + b->ob_size;
186 op = (stringobject *)
187 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000188 if (op == NULL)
189 return err_nomem();
190 NEWREF(op);
191 op->ob_type = &Stringtype;
192 op->ob_size = size;
193 memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
194 memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
195 op->ob_sval[size] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 return (object *) op;
197#undef b
198}
199
200static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000201string_repeat(a, n)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000202 register stringobject *a;
203 register int n;
204{
205 register int i;
206 register unsigned int size;
207 register stringobject *op;
208 if (n < 0)
209 n = 0;
210 size = a->ob_size * n;
211 if (size == a->ob_size) {
212 INCREF(a);
213 return (object *)a;
214 }
215 op = (stringobject *)
216 malloc(sizeof(stringobject) + size * sizeof(char));
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000217 if (op == NULL)
218 return err_nomem();
219 NEWREF(op);
220 op->ob_type = &Stringtype;
221 op->ob_size = size;
222 for (i = 0; i < size; i += a->ob_size)
223 memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
224 op->ob_sval[size] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000225 return (object *) op;
226}
227
228/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
229
230static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000231string_slice(a, i, j)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000232 register stringobject *a;
233 register int i, j; /* May be negative! */
234{
235 if (i < 0)
236 i = 0;
237 if (j < 0)
238 j = 0; /* Avoid signed/unsigned bug in next line */
239 if (j > a->ob_size)
240 j = a->ob_size;
241 if (i == 0 && j == a->ob_size) { /* It's the same as a */
242 INCREF(a);
243 return (object *)a;
244 }
245 if (j < i)
246 j = i;
247 return newsizedstringobject(a->ob_sval + i, (int) (j-i));
248}
249
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000250#ifdef __STDC__
251#include <limits.h>
252#else
253#ifndef UCHAR_MAX
254#define UCHAR_MAX 255
255#endif
256#endif
257
258static object *characters[UCHAR_MAX + 1];
259
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260static object *
Guido van Rossume5372401993-03-16 12:15:04 +0000261string_item(a, i)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000262 stringobject *a;
263 register int i;
264{
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000265 int c;
266 object *v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000268 err_setstr(IndexError, "string index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000269 return NULL;
270 }
Guido van Rossumdaa8bb31991-04-04 10:48:33 +0000271 c = a->ob_sval[i] & UCHAR_MAX;
272 v = characters[c];
273 if (v == NULL) {
274 v = newsizedstringobject((char *)NULL, 1);
275 if (v == NULL)
276 return NULL;
277 characters[c] = v;
278 ((stringobject *)v)->ob_sval[0] = c;
279 }
280 INCREF(v);
281 return v;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000282}
283
284static int
Guido van Rossume5372401993-03-16 12:15:04 +0000285string_compare(a, b)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000286 stringobject *a, *b;
287{
Guido van Rossum253919f1991-02-13 23:18:39 +0000288 int len_a = a->ob_size, len_b = b->ob_size;
289 int min_len = (len_a < len_b) ? len_a : len_b;
290 int cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
291 if (cmp != 0)
292 return cmp;
293 return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000294}
295
296static sequence_methods string_as_sequence = {
Guido van Rossume5372401993-03-16 12:15:04 +0000297 string_length, /*sq_length*/
298 string_concat, /*sq_concat*/
299 string_repeat, /*sq_repeat*/
300 string_item, /*sq_item*/
301 string_slice, /*sq_slice*/
Guido van Rossumf380e661991-06-04 19:36:32 +0000302 0, /*sq_ass_item*/
303 0, /*sq_ass_slice*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000304};
305
306typeobject Stringtype = {
307 OB_HEAD_INIT(&Typetype)
308 0,
309 "string",
310 sizeof(stringobject),
311 sizeof(char),
Guido van Rossume5372401993-03-16 12:15:04 +0000312 string_dealloc, /*tp_dealloc*/
313 string_print, /*tp_print*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000314 0, /*tp_getattr*/
315 0, /*tp_setattr*/
Guido van Rossume5372401993-03-16 12:15:04 +0000316 string_compare, /*tp_compare*/
317 string_repr, /*tp_repr*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000318 0, /*tp_as_number*/
319 &string_as_sequence, /*tp_as_sequence*/
320 0, /*tp_as_mapping*/
321};
322
323void
324joinstring(pv, w)
325 register object **pv;
326 register object *w;
327{
328 register object *v;
329 if (*pv == NULL || w == NULL || !is_stringobject(*pv))
330 return;
Guido van Rossume5372401993-03-16 12:15:04 +0000331 v = string_concat((stringobject *) *pv, w);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000332 DECREF(*pv);
333 *pv = v;
334}
335
336/* The following function breaks the notion that strings are immutable:
337 it changes the size of a string. We get away with this only if there
338 is only one module referencing the object. You can also think of it
339 as creating a new string object and destroying the old one, only
340 more efficiently. In any case, don't use this if the string may
341 already be known to some other part of the code... */
342
343int
344resizestring(pv, newsize)
345 object **pv;
346 int newsize;
347{
Guido van Rossum921842f1990-11-18 17:30:23 +0000348 register object *v;
349 register stringobject *sv;
350 v = *pv;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000351 if (!is_stringobject(v) || v->ob_refcnt != 1) {
352 *pv = 0;
353 DECREF(v);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000354 err_badcall();
355 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000356 }
Guido van Rossum921842f1990-11-18 17:30:23 +0000357 /* XXX UNREF/NEWREF interface should be more symmetrical */
Guido van Rossum392ab321990-11-18 17:41:19 +0000358#ifdef REF_DEBUG
Guido van Rossum921842f1990-11-18 17:30:23 +0000359 --ref_total;
360#endif
361 UNREF(v);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000362 *pv = (object *)
363 realloc((char *)v,
364 sizeof(stringobject) + newsize * sizeof(char));
365 if (*pv == NULL) {
Guido van Rossum921842f1990-11-18 17:30:23 +0000366 DEL(v);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000367 err_nomem();
368 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000369 }
Guido van Rossum921842f1990-11-18 17:30:23 +0000370 NEWREF(*pv);
371 sv = (stringobject *) *pv;
372 sv->ob_size = newsize;
373 sv->ob_sval[newsize] = '\0';
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000374 return 0;
375}
Guido van Rossume5372401993-03-16 12:15:04 +0000376
377/* Helpers for formatstring */
378
379static object *
380getnextarg(args, arglen, p_argidx)
381 object *args;
382 int arglen;
383 int *p_argidx;
384{
385 int argidx = *p_argidx;
386 if (argidx < arglen) {
387 (*p_argidx)++;
388 if (arglen < 0)
389 return args;
390 else
391 return gettupleitem(args, argidx);
392 }
393 err_setstr(TypeError, "not enough arguments for format string");
394 return NULL;
395}
396
397#define F_LJUST (1<<0)
398#define F_SIGN (1<<1)
399#define F_BLANK (1<<2)
400#define F_ALT (1<<3)
401#define F_ZERO (1<<4)
402
403extern double fabs PROTO((double));
404
405static char *
406formatfloat(flags, prec, type, v)
407 int flags;
408 int prec;
409 int type;
410 object *v;
411{
412 char fmt[20];
413 static char buf[120];
414 double x;
415 if (!getargs(v, "d;float argument required", &x))
416 return NULL;
417 if (prec < 0)
418 prec = 6;
419 if (prec > 50)
420 prec = 50; /* Arbitrary limitation */
421 if (type == 'f' && fabs(x)/1e25 >= 1e25)
422 type = 'g';
423 sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
424 sprintf(buf, fmt, x);
425 return buf;
426}
427
428static char *
429formatint(flags, prec, type, v)
430 int flags;
431 int prec;
432 int type;
433 object *v;
434{
435 char fmt[20];
436 static char buf[50];
437 long x;
438 if (!getargs(v, "l;int argument required", &x))
439 return NULL;
440 if (prec < 0)
441 prec = 1;
442 sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
443 sprintf(buf, fmt, x);
444 return buf;
445}
446
447static char *
448formatchar(v)
449 object *v;
450{
451 static char buf[2];
452 if (is_stringobject(v)) {
453 if (!getargs(v, "c;%c requires int or char", &buf[0]))
454 return NULL;
455 }
456 else {
457 if (!getargs(v, "b;%c requires int or char", &buf[0]))
458 return NULL;
459 }
460 buf[1] = '\0';
461 return buf;
462}
463
464/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
465
466object *
467formatstring(format, args)
468 object *format;
469 object *args;
470{
471 char *fmt, *res;
472 int fmtcnt, rescnt, reslen, arglen, argidx;
473 object *result;
474 if (format == NULL || !is_stringobject(format) || args == NULL) {
475 err_badcall();
476 return NULL;
477 }
478 reslen = rescnt = 100;
479 result = newsizedstringobject((char *)NULL, reslen);
480 if (result == NULL)
481 return NULL;
482 res = getstringvalue(result);
483 fmt = getstringvalue(format);
484 fmtcnt = getstringsize(format);
485 if (is_tupleobject(args)) {
486 arglen = gettuplesize(args);
487 argidx = 0;
488 }
489 else {
490 arglen = -1;
491 argidx = -2;
492 }
493 while (--fmtcnt >= 0) {
494 if (*fmt != '%') {
495 if (--rescnt < 0) {
496 rescnt = reslen;
497 reslen = reslen * 2; /* Maybe less when big? */
498 if (resizestring(&result, reslen) < 0)
499 return NULL;
500 res = getstringvalue(result) + rescnt;
501 rescnt = reslen - rescnt;
502 }
503 *res++ = *fmt++;
504 }
505 else {
506 /* Got a format specifier */
507 int flags = 0;
508 char *fmtstart = fmt++;
509 int width = -1;
510 int prec = -1;
511 int size = 0;
512 int c;
513 int fill;
514 object *v;
515 char *buf;
516 int sign;
517 int len;
518 while (--fmtcnt >= 0) {
519 switch (c = *fmt++) {
520 case '-': flags |= F_LJUST; continue;
521 case '+': flags |= F_SIGN; continue;
522 case ' ': flags |= F_BLANK; continue;
523 case '#': flags |= F_ALT; continue;
524 case '0': flags |= F_ZERO; continue;
525 }
526 break;
527 }
528 if (c == '*') {
529 v = getnextarg(args, arglen, &argidx);
530 if (v == NULL)
531 goto error;
532 if (!is_intobject(v)) {
533 err_setstr(TypeError, "* wants int");
534 goto error;
535 }
536 width = getintvalue(v);
537 if (width < 0)
538 width = 0;
539 if (--fmtcnt >= 0)
540 c = *fmt++;
541 }
542 else if (isdigit(c)) {
543 width = c - '0';
544 while (--fmtcnt >= 0) {
545 c = *fmt++;
546 if (!isdigit(c))
547 break;
548 if ((width*10) / 10 != width) {
549 err_setstr(ValueError,
550 "width too big");
551 goto error;
552 }
553 width = width*10 + (c - '0');
554 }
555 }
556 if (c == '.') {
557 prec = 0;
558 if (--fmtcnt >= 0)
559 c = *fmt++;
560 if (c == '*') {
561 v = getnextarg(args, arglen, &argidx);
562 if (v == NULL)
563 goto error;
564 if (!is_intobject(v)) {
565 err_setstr(TypeError,
566 "* wants int");
567 goto error;
568 }
569 prec = getintvalue(v);
570 if (prec < 0)
571 prec = 0;
572 if (--fmtcnt >= 0)
573 c = *fmt++;
574 }
575 else if (isdigit(c)) {
576 prec = c - '0';
577 while (--fmtcnt >= 0) {
578 c = *fmt++;
579 if (!isdigit(c))
580 break;
581 if ((prec*10) / 10 != prec) {
582 err_setstr(ValueError,
583 "prec too big");
584 goto error;
585 }
586 prec = prec*10 + (c - '0');
587 }
588 }
589 } /* prec */
590 if (fmtcnt >= 0) {
591 if (c == 'h' || c == 'l' || c == 'L') {
592 size = c;
593 if (--fmtcnt >= 0)
594 c = *fmt++;
595 }
596 }
597 if (fmtcnt < 0) {
598 err_setstr(ValueError, "incomplete format");
599 goto error;
600 }
601 if (c != '%') {
602 v = getnextarg(args, arglen, &argidx);
603 if (v == NULL)
604 goto error;
605 }
606 sign = 0;
607 fill = ' ';
608 switch (c) {
609 case '%':
610 buf = "%";
611 len = 1;
612 break;
613 case 's':
614 if (!is_stringobject(v)) {
615 err_setstr(TypeError,
616 "%s wants string");
617 goto error;
618 }
619 buf = getstringvalue(v);
620 len = getstringsize(v);
621 if (prec >= 0 && len > prec)
622 len = prec;
623 break;
624 case 'i':
625 case 'd':
626 case 'u':
627 case 'o':
628 case 'x':
629 case 'X':
630 if (c == 'i')
631 c = 'd';
632 buf = formatint(flags, prec, c, v);
633 if (buf == NULL)
634 goto error;
635 len = strlen(buf);
636 sign = (c == 'd');
637 if (flags&F_ZERO)
638 fill = '0';
639 break;
640 case 'e':
641 case 'E':
642 case 'f':
643 case 'g':
644 case 'G':
645 buf = formatfloat(flags, prec, c, v);
646 if (buf == NULL)
647 goto error;
648 len = strlen(buf);
649 sign = 1;
650 if (flags&F_ZERO)
651 fill = '0';
652 break;
653 case 'c':
654 buf = formatchar(v);
655 if (buf == NULL)
656 goto error;
657 len = strlen(buf);
658 break;
659 default:
660 err_setstr(ValueError,
661 "unsupported format character");
662 goto error;
663 }
664 if (sign) {
665 if (*buf == '-' || *buf == '+') {
666 sign = *buf++;
667 len--;
668 }
669 else if (flags & F_SIGN)
670 sign = '+';
671 else if (flags & F_BLANK)
672 sign = ' ';
673 else
674 sign = '\0';
675 }
676 if (width < len)
677 width = len;
678 if (rescnt < width + (sign != '\0')) {
679 rescnt = reslen;
680 reslen = reslen + width + 100;
681 if (resizestring(&result, reslen) < 0)
682 return NULL;
683 res = getstringvalue(result) + rescnt;
684 rescnt = reslen - rescnt;
685 }
686 if (sign) {
687 *res++ = sign;
688 rescnt--;
689 if (width > len)
690 width--;
691 }
692 if (width > len && !(flags&F_LJUST)) {
693 do {
694 --rescnt;
695 *res++ = fill;
696 } while (--width > len);
697 }
698 memcpy(res, buf, len);
699 res += len;
700 rescnt -= len;
701 while (--width >= len) {
702 --rescnt;
703 *res++ = ' ';
704 }
705 } /* '%' */
706 } /* until end */
707 if (argidx < arglen) {
708 err_setstr(TypeError, "not all arguments converted");
709 goto error;
710 }
711 resizestring(&result, reslen - rescnt);
712 return result;
713 error:
714 DECREF(result);
715 return NULL;
716}