home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Objects / stringobject.c < prev    next >
C/C++ Source or Header  |  1994-04-22  |  20KB  |  932 lines

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* String object implementation */
  26.  
  27. #include "allobjects.h"
  28.  
  29. #include <ctype.h>
  30.  
  31. #ifdef COUNT_ALLOCS
  32. int null_strings, one_strings;
  33. #endif
  34.  
  35. #ifdef __STDC__
  36. #include <limits.h>
  37. #else
  38. #ifndef UCHAR_MAX
  39. #define UCHAR_MAX 255
  40. #endif
  41. #endif
  42.  
  43. static stringobject *characters[UCHAR_MAX + 1];
  44. #ifndef DONT_SHARE_SHORT_STRINGS
  45. static stringobject *nullstring;
  46. #endif
  47.  
  48. /*
  49.    Newsizedstringobject() and newstringobject() try in certain cases
  50.    to share string objects.  When the size of the string is zero,
  51.    these routines always return a pointer to the same string object;
  52.    when the size is one, they return a pointer to an already existing
  53.    object if the contents of the string is known.  For
  54.    newstringobject() this is always the case, for
  55.    newsizedstringobject() this is the case when the first argument in
  56.    not NULL.
  57.    A common practice to allocate a string and then fill it in or
  58.    change it must be done carefully.  It is only allowed to change the
  59.    contents of the string if the obect was gotten from
  60.    newsizedstringobject() with a NULL first argument, because in the
  61.    future these routines may try to do even more sharing of objects.
  62. */
  63. object *
  64. newsizedstringobject(str, size)
  65.     char *str;
  66.     int size;
  67. {
  68.     register stringobject *op;
  69. #ifndef DONT_SHARE_SHORT_STRINGS
  70.     if (size == 0 && (op = nullstring) != NULL) {
  71. #ifdef COUNT_ALLOCS
  72.         null_strings++;
  73. #endif
  74.         INCREF(op);
  75.         return (object *)op;
  76.     }
  77.     if (size == 1 && str != NULL && (op = characters[*str & UCHAR_MAX]) != NULL) {
  78. #ifdef COUNT_ALLOCS
  79.         one_strings++;
  80. #endif
  81.         INCREF(op);
  82.         return (object *)op;
  83.     }
  84. #endif /* DONT_SHARE_SHORT_STRINGS */
  85.     op = (stringobject *)
  86.         malloc(sizeof(stringobject) + size * sizeof(char));
  87.     if (op == NULL)
  88.         return err_nomem();
  89.     op->ob_type = &Stringtype;
  90.     op->ob_size = size;
  91. #ifdef CACHE_HASH
  92.     op->ob_shash = -1;
  93. #endif
  94.     NEWREF(op);
  95.     if (str != NULL)
  96.         memcpy(op->ob_sval, str, size);
  97.     op->ob_sval[size] = '\0';
  98. #ifndef DONT_SHARE_SHORT_STRINGS
  99.     if (size == 0) {
  100.         nullstring = op;
  101.         INCREF(op);
  102.     } else if (size == 1 && str != NULL) {
  103.         characters[*str & UCHAR_MAX] = op;
  104.         INCREF(op);
  105.     }
  106. #endif
  107.     return (object *) op;
  108. }
  109.  
  110. object *
  111. newstringobject(str)
  112.     char *str;
  113. {
  114.     register unsigned int size = strlen(str);
  115.     register stringobject *op;
  116. #ifndef DONT_SHARE_SHORT_STRINGS
  117.     if (size == 0 && (op = nullstring) != NULL) {
  118. #ifdef COUNT_ALLOCS
  119.         null_strings++;
  120. #endif
  121.         INCREF(op);
  122.         return (object *)op;
  123.     }
  124.     if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
  125. #ifdef COUNT_ALLOCS
  126.         one_strings++;
  127. #endif
  128.         INCREF(op);
  129.         return (object *)op;
  130.     }
  131. #endif /* DONT_SHARE_SHORT_STRINGS */
  132.     op = (stringobject *)
  133.         malloc(sizeof(stringobject) + size * sizeof(char));
  134.     if (op == NULL)
  135.         return err_nomem();
  136.     op->ob_type = &Stringtype;
  137.     op->ob_size = size;
  138. #ifdef CACHE_HASH
  139.     op->ob_shash = -1;
  140. #endif
  141.     NEWREF(op);
  142.     strcpy(op->ob_sval, str);
  143. #ifndef DONT_SHARE_SHORT_STRINGS
  144.     if (size == 0) {
  145.         nullstring = op;
  146.         INCREF(op);
  147.     } else if (size == 1) {
  148.         characters[*str & UCHAR_MAX] = op;
  149.         INCREF(op);
  150.     }
  151. #endif
  152.     return (object *) op;
  153. }
  154.  
  155. static void
  156. string_dealloc(op)
  157.     object *op;
  158. {
  159.     DEL(op);
  160. }
  161.  
  162. unsigned int
  163. getstringsize(op)
  164.     register object *op;
  165. {
  166.     if (!is_stringobject(op)) {
  167.         err_badcall();
  168.         return -1;
  169.     }
  170.     return ((stringobject *)op) -> ob_size;
  171. }
  172.  
  173. /*const*/ char *
  174. getstringvalue(op)
  175.     register object *op;
  176. {
  177.     if (!is_stringobject(op)) {
  178.         err_badcall();
  179.         return NULL;
  180.     }
  181.     return ((stringobject *)op) -> ob_sval;
  182. }
  183.  
  184. /* Methods */
  185.  
  186. static int
  187. string_print(op, fp, flags)
  188.     stringobject *op;
  189.     FILE *fp;
  190.     int flags;
  191. {
  192.     int i;
  193.     char c;
  194.     int quote;
  195.     /* XXX Ought to check for interrupts when writing long strings */
  196.     if (flags & PRINT_RAW) {
  197.         fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
  198.         return 0;
  199.     }
  200.  
  201.     /* figure out which quote to use; single is prefered */
  202.     quote = '\'';
  203.     if (strchr(op->ob_sval, '\'') && !strchr(op->ob_sval, '"'))
  204.         quote = '"';
  205.  
  206.     fputc(quote, fp);
  207.     for (i = 0; i < op->ob_size; i++) {
  208.         c = op->ob_sval[i];
  209.         if (c == quote || c == '\\')
  210.             fprintf(fp, "\\%c", c);
  211.         else if (c < ' ' || c >= 0177)
  212.             fprintf(fp, "\\%03o", c & 0377);
  213.         else
  214.             fputc(c, fp);
  215.     }
  216.     fputc(quote, fp);
  217.     return 0;
  218. }
  219.  
  220. static object *
  221. string_repr(op)
  222.     register stringobject *op;
  223. {
  224.     /* XXX overflow? */
  225.     int newsize = 2 + 4 * op->ob_size * sizeof(char);
  226.     object *v = newsizedstringobject((char *)NULL, newsize);
  227.     if (v == NULL) {
  228.         return NULL;
  229.     }
  230.     else {
  231.         register int i;
  232.         register char c;
  233.         register char *p;
  234.         int quote;
  235.  
  236.         /* figure out which quote to use; single is prefered */
  237.         quote = '\'';
  238.         if (strchr(op->ob_sval, '\'') && !strchr(op->ob_sval, '"'))
  239.             quote = '"';
  240.  
  241.         p = ((stringobject *)v)->ob_sval;
  242.         *p++ = quote;
  243.         for (i = 0; i < op->ob_size; i++) {
  244.             c = op->ob_sval[i];
  245.             if (c == quote || c == '\\')
  246.                 *p++ = '\\', *p++ = c;
  247.             else if (c < ' ' || c >= 0177) {
  248.                 sprintf(p, "\\%03o", c & 0377);
  249.                 while (*p != '\0')
  250.                     p++;
  251.             }
  252.             else
  253.                 *p++ = c;
  254.         }
  255.         *p++ = quote;
  256.         *p = '\0';
  257.         resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
  258.         return v;
  259.     }
  260. }
  261.  
  262. static int
  263. string_length(a)
  264.     stringobject *a;
  265. {
  266.     return a->ob_size;
  267. }
  268.  
  269. static object *
  270. string_concat(a, bb)
  271.     register stringobject *a;
  272.     register object *bb;
  273. {
  274.     register unsigned int size;
  275.     register stringobject *op;
  276.     if (!is_stringobject(bb)) {
  277.         err_badarg();
  278.         return NULL;
  279.     }
  280. #define b ((stringobject *)bb)
  281.     /* Optimize cases with empty left or right operand */
  282.     if (a->ob_size == 0) {
  283.         INCREF(bb);
  284.         return bb;
  285.     }
  286.     if (b->ob_size == 0) {
  287.         INCREF(a);
  288.         return (object *)a;
  289.     }
  290.     size = a->ob_size + b->ob_size;
  291.     op = (stringobject *)
  292.         malloc(sizeof(stringobject) + size * sizeof(char));
  293.     if (op == NULL)
  294.         return err_nomem();
  295.     op->ob_type = &Stringtype;
  296.     op->ob_size = size;
  297. #ifdef CACHE_HASH
  298.     op->ob_shash = -1;
  299. #endif
  300.     NEWREF(op);
  301.     memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
  302.     memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
  303.     op->ob_sval[size] = '\0';
  304.     return (object *) op;
  305. #undef b
  306. }
  307.  
  308. static object *
  309. string_repeat(a, n)
  310.     register stringobject *a;
  311.     register int n;
  312. {
  313.     register int i;
  314.     register unsigned int size;
  315.     register stringobject *op;
  316.     if (n < 0)
  317.         n = 0;
  318.     size = a->ob_size * n;
  319.     if (size == a->ob_size) {
  320.         INCREF(a);
  321.         return (object *)a;
  322.     }
  323.     op = (stringobject *)
  324.         malloc(sizeof(stringobject) + size * sizeof(char));
  325.     if (op == NULL)
  326.         return err_nomem();
  327.     op->ob_type = &Stringtype;
  328.     op->ob_size = size;
  329. #ifdef CACHE_HASH
  330.     op->ob_shash = -1;
  331. #endif
  332.     NEWREF(op);
  333.     for (i = 0; i < size; i += a->ob_size)
  334.         memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
  335.     op->ob_sval[size] = '\0';
  336.     return (object *) op;
  337. }
  338.  
  339. /* String slice a[i:j] consists of characters a[i] ... a[j-1] */
  340.  
  341. static object *
  342. string_slice(a, i, j)
  343.     register stringobject *a;
  344.     register int i, j; /* May be negative! */
  345. {
  346.     if (i < 0)
  347.         i = 0;
  348.     if (j < 0)
  349.         j = 0; /* Avoid signed/unsigned bug in next line */
  350.     if (j > a->ob_size)
  351.         j = a->ob_size;
  352.     if (i == 0 && j == a->ob_size) { /* It's the same as a */
  353.         INCREF(a);
  354.         return (object *)a;
  355.     }
  356.     if (j < i)
  357.         j = i;
  358.     return newsizedstringobject(a->ob_sval + i, (int) (j-i));
  359. }
  360.  
  361. static object *
  362. string_item(a, i)
  363.     stringobject *a;
  364.     register int i;
  365. {
  366.     int c;
  367.     object *v;
  368.     if (i < 0 || i >= a->ob_size) {
  369.         err_setstr(IndexError, "string index out of range");
  370.         return NULL;
  371.     }
  372.     c = a->ob_sval[i] & UCHAR_MAX;
  373.     v = (object *) characters[c];
  374. #ifdef COUNT_ALLOCS
  375.     if (v != NULL)
  376.         one_strings++;
  377. #endif
  378.     if (v == NULL) {
  379.         v = newsizedstringobject((char *)NULL, 1);
  380.         if (v == NULL)
  381.             return NULL;
  382.         characters[c] = (stringobject *) v;
  383.         ((stringobject *)v)->ob_sval[0] = c;
  384.     }
  385.     INCREF(v);
  386.     return v;
  387. }
  388.  
  389. static int
  390. string_compare(a, b)
  391.     stringobject *a, *b;
  392. {
  393.     int len_a = a->ob_size, len_b = b->ob_size;
  394.     int min_len = (len_a < len_b) ? len_a : len_b;
  395.     int cmp;
  396.     if (min_len > 0) {
  397.         cmp = *a->ob_sval - *b->ob_sval;
  398.         if (cmp == 0)
  399.             cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
  400.         if (cmp != 0)
  401.             return cmp;
  402.     }
  403.     return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
  404. }
  405.  
  406. static long
  407. string_hash(a)
  408.     stringobject *a;
  409. {
  410.     register int len;
  411.     register unsigned char *p;
  412.     register long x;
  413.  
  414. #ifdef CACHE_HASH
  415.     if (a->ob_shash != -1)
  416.         return a->ob_shash;
  417. #endif
  418.     len = a->ob_size;
  419.     p = (unsigned char *) a->ob_sval;
  420.     x = *p << 7;
  421.     while (--len >= 0)
  422.         x = (x + x + x) ^ *p++;
  423.     x ^= a->ob_size;
  424.     if (x == -1)
  425.         x = -2;
  426. #ifdef CACHE_HASH
  427.     a->ob_shash = x;
  428. #endif
  429.     return x;
  430. }
  431.  
  432. static sequence_methods string_as_sequence = {
  433.     (inquiry)string_length, /*sq_length*/
  434.     (binaryfunc)string_concat, /*sq_concat*/
  435.     (intargfunc)string_repeat, /*sq_repeat*/
  436.     (intargfunc)string_item, /*sq_item*/
  437.     (intintargfunc)string_slice, /*sq_slice*/
  438.     0,        /*sq_ass_item*/
  439.     0,        /*sq_ass_slice*/
  440. };
  441.  
  442. typeobject Stringtype = {
  443.     OB_HEAD_INIT(&Typetype)
  444.     0,
  445.     "string",
  446.     sizeof(stringobject),
  447.     sizeof(char),
  448.     (destructor)string_dealloc, /*tp_dealloc*/
  449.     (printfunc)string_print, /*tp_print*/
  450.     0,        /*tp_getattr*/
  451.     0,        /*tp_setattr*/
  452.     (cmpfunc)string_compare, /*tp_compare*/
  453.     (reprfunc)string_repr, /*tp_repr*/
  454.     0,        /*tp_as_number*/
  455.     &string_as_sequence,    /*tp_as_sequence*/
  456.     0,        /*tp_as_mapping*/
  457.     (hashfunc)string_hash, /*tp_hash*/
  458. };
  459.  
  460. void
  461. joinstring(pv, w)
  462.     register object **pv;
  463.     register object *w;
  464. {
  465.     register object *v;
  466.     if (*pv == NULL)
  467.         return;
  468.     if (w == NULL || !is_stringobject(*pv)) {
  469.         DECREF(*pv);
  470.         *pv = NULL;
  471.         return;
  472.     }
  473.     v = string_concat((stringobject *) *pv, w);
  474.     DECREF(*pv);
  475.     *pv = v;
  476. }
  477.  
  478. void
  479. joinstring_decref(pv, w)
  480.     register object **pv;
  481.     register object *w;
  482. {
  483.     joinstring(pv, w);
  484.     XDECREF(w);
  485. }
  486.  
  487.  
  488. /* The following function breaks the notion that strings are immutable:
  489.    it changes the size of a string.  We get away with this only if there
  490.    is only one module referencing the object.  You can also think of it
  491.    as creating a new string object and destroying the old one, only
  492.    more efficiently.  In any case, don't use this if the string may
  493.    already be known to some other part of the code... */
  494.  
  495. int
  496. resizestring(pv, newsize)
  497.     object **pv;
  498.     int newsize;
  499. {
  500.     register object *v;
  501.     register stringobject *sv;
  502.     v = *pv;
  503.     if (!is_stringobject(v) || v->ob_refcnt != 1) {
  504.         *pv = 0;
  505.         DECREF(v);
  506.         err_badcall();
  507.         return -1;
  508.     }
  509.     /* XXX UNREF/NEWREF interface should be more symmetrical */
  510. #ifdef REF_DEBUG
  511.     --ref_total;
  512. #endif
  513.     UNREF(v);
  514.     *pv = (object *)
  515.         realloc((char *)v,
  516.             sizeof(stringobject) + newsize * sizeof(char));
  517.     if (*pv == NULL) {
  518.         DEL(v);
  519.         err_nomem();
  520.         return -1;
  521.     }
  522.     NEWREF(*pv);
  523.     sv = (stringobject *) *pv;
  524.     sv->ob_size = newsize;
  525.     sv->ob_sval[newsize] = '\0';
  526.     return 0;
  527. }
  528.  
  529. /* Helpers for formatstring */
  530.  
  531. static object *
  532. getnextarg(args, arglen, p_argidx)
  533.     object *args;
  534.     int arglen;
  535.     int *p_argidx;
  536. {
  537.     int argidx = *p_argidx;
  538.     if (argidx < arglen) {
  539.         (*p_argidx)++;
  540.         if (arglen < 0)
  541.             return args;
  542.         else
  543.             return gettupleitem(args, argidx);
  544.     }
  545.     err_setstr(TypeError, "not enough arguments for format string");
  546.     return NULL;
  547. }
  548.  
  549. #define F_LJUST (1<<0)
  550. #define F_SIGN    (1<<1)
  551. #define F_BLANK (1<<2)
  552. #define F_ALT    (1<<3)
  553. #define F_ZERO    (1<<4)
  554.  
  555. extern double fabs PROTO((double));
  556.  
  557. static char *
  558. formatfloat(flags, prec, type, v)
  559.     int flags;
  560.     int prec;
  561.     int type;
  562.     object *v;
  563. {
  564.     char fmt[20];
  565.     static char buf[120];
  566.     double x;
  567.     if (!getargs(v, "d;float argument required", &x))
  568.         return NULL;
  569.     if (prec < 0)
  570.         prec = 6;
  571.     if (prec > 50)
  572.         prec = 50; /* Arbitrary limitation */
  573.     if (type == 'f' && fabs(x)/1e25 >= 1e25)
  574.         type = 'g';
  575.     sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
  576.     sprintf(buf, fmt, x);
  577.     return buf;
  578. }
  579.  
  580. static char *
  581. formatint(flags, prec, type, v)
  582.     int flags;
  583.     int prec;
  584.     int type;
  585.     object *v;
  586. {
  587.     char fmt[20];
  588.     static char buf[50];
  589.     long x;
  590.     if (!getargs(v, "l;int argument required", &x))
  591.         return NULL;
  592.     if (prec < 0)
  593.         prec = 1;
  594.     sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
  595.     sprintf(buf, fmt, x);
  596.     return buf;
  597. }
  598.  
  599. static char *
  600. formatchar(v)
  601.     object *v;
  602. {
  603.     static char buf[2];
  604.     if (is_stringobject(v)) {
  605.         if (!getargs(v, "c;%c requires int or char", &buf[0]))
  606.             return NULL;
  607.     }
  608.     else {
  609.         if (!getargs(v, "b;%c requires int or char", &buf[0]))
  610.             return NULL;
  611.     }
  612.     buf[1] = '\0';
  613.     return buf;
  614. }
  615.  
  616. /* XXX this could be moved to object.c */
  617. static object *
  618. get_mapping_item(mo, ko)
  619.     object *mo;
  620.     object *ko;
  621. {
  622.     mapping_methods *mm = mo->ob_type->tp_as_mapping;
  623.     object *val;
  624.  
  625.     if (!mm || !mm->mp_subscript) {
  626.         err_setstr(TypeError, "subscript not implemented");
  627.         return NULL;
  628.     }
  629.  
  630.     val = (*mm->mp_subscript)(mo, ko);
  631.     XDECREF(val);        /* still in mapping */
  632.  
  633.     return val;
  634. }
  635.  
  636.  
  637. /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
  638.  
  639. object *
  640. formatstring(format, args)
  641.     object *format;
  642.     object *args;
  643. {
  644.     char *fmt, *res;
  645.     int fmtcnt, rescnt, reslen, arglen, argidx;
  646.     object *result;
  647.     object *dict = NULL;
  648.     if (format == NULL || !is_stringobject(format) || args == NULL) {
  649.         err_badcall();
  650.         return NULL;
  651.     }
  652.     fmt = getstringvalue(format);
  653.     fmtcnt = getstringsize(format);
  654.     reslen = rescnt = fmtcnt + 100;
  655.     result = newsizedstringobject((char *)NULL, reslen);
  656.     if (result == NULL)
  657.         return NULL;
  658.     res = getstringvalue(result);
  659.     if (is_tupleobject(args)) {
  660.         arglen = gettuplesize(args);
  661.         argidx = 0;
  662.     }
  663.     else {
  664.         arglen = -1;
  665.         argidx = -2;
  666.     }
  667.     if (args->ob_type->tp_as_mapping)
  668.         dict = args;
  669.     while (--fmtcnt >= 0) {
  670.         if (*fmt != '%') {
  671.             if (--rescnt < 0) {
  672.                 rescnt = fmtcnt + 100;
  673.                 reslen += rescnt;
  674.                 if (resizestring(&result, reslen) < 0)
  675.                     return NULL;
  676.                 res = getstringvalue(result) + reslen - rescnt;
  677.             }
  678.             *res++ = *fmt++;
  679.         }
  680.         else {
  681.             /* Got a format specifier */
  682.             int flags = 0;
  683.             char *fmtstart = fmt++;
  684.             int width = -1;
  685.             int prec = -1;
  686.             int size = 0;
  687.             int c = '\0';
  688.             int fill;
  689.             object *v;
  690.             char *buf;
  691.             int sign;
  692.             int len;
  693.             if (*fmt == '(') {
  694.                 char *keystart;
  695.                 int keylen;
  696.                 object *key;
  697.  
  698.                 if (dict == NULL) {
  699.                     err_setstr(TypeError,
  700.                          "format requires a mapping"); 
  701.                     goto error;
  702.                 }
  703.                 ++fmt;
  704.                 --fmtcnt;
  705.                 keystart = fmt;
  706.                 while (--fmtcnt >= 0 && *fmt != ')')
  707.                     fmt++;
  708.                 keylen = fmt - keystart;
  709.                 ++fmt;
  710.                 if (fmtcnt < 0) {
  711.                     err_setstr(ValueError,
  712.                            "incomplete format key");
  713.                     goto error;
  714.                 }
  715.                 key = newsizedstringobject(keystart, keylen);
  716.                 if (key == NULL)
  717.                     goto error;
  718.                 args = get_mapping_item(dict, key);
  719.                 DECREF(key);
  720.                 if (args == NULL) {
  721.                     goto error;
  722.                 }
  723.                 arglen = -1;
  724.                 argidx = -2;
  725.             }
  726.             while (--fmtcnt >= 0) {
  727.                 switch (c = *fmt++) {
  728.                 case '-': flags |= F_LJUST; continue;
  729.                 case '+': flags |= F_SIGN; continue;
  730.                 case ' ': flags |= F_BLANK; continue;
  731.                 case '#': flags |= F_ALT; continue;
  732.                 case '0': flags |= F_ZERO; continue;
  733.                 }
  734.                 break;
  735.             }
  736.             if (c == '*') {
  737.                 v = getnextarg(args, arglen, &argidx);
  738.                 if (v == NULL)
  739.                     goto error;
  740.                 if (!is_intobject(v)) {
  741.                     err_setstr(TypeError, "* wants int");
  742.                     goto error;
  743.                 }
  744.                 width = getintvalue(v);
  745.                 if (width < 0)
  746.                     width = 0;
  747.                 if (--fmtcnt >= 0)
  748.                     c = *fmt++;
  749.             }
  750.             else if (isdigit(c)) {
  751.                 width = c - '0';
  752.                 while (--fmtcnt >= 0) {
  753.                     c = *fmt++;
  754.                     if (!isdigit(c))
  755.                         break;
  756.                     if ((width*10) / 10 != width) {
  757.                         err_setstr(ValueError,
  758.                                "width too big");
  759.                         goto error;
  760.                     }
  761.                     width = width*10 + (c - '0');
  762.                 }
  763.             }
  764.             if (c == '.') {
  765.                 prec = 0;
  766.                 if (--fmtcnt >= 0)
  767.                     c = *fmt++;
  768.                 if (c == '*') {
  769.                     v = getnextarg(args, arglen, &argidx);
  770.                     if (v == NULL)
  771.                         goto error;
  772.                     if (!is_intobject(v)) {
  773.                         err_setstr(TypeError,
  774.                                "* wants int");
  775.                         goto error;
  776.                     }
  777.                     prec = getintvalue(v);
  778.                     if (prec < 0)
  779.                         prec = 0;
  780.                     if (--fmtcnt >= 0)
  781.                         c = *fmt++;
  782.                 }
  783.                 else if (isdigit(c)) {
  784.                     prec = c - '0';
  785.                     while (--fmtcnt >= 0) {
  786.                         c = *fmt++;
  787.                         if (!isdigit(c))
  788.                             break;
  789.                         if ((prec*10) / 10 != prec) {
  790.                             err_setstr(ValueError,
  791.                                 "prec too big");
  792.                             goto error;
  793.                         }
  794.                         prec = prec*10 + (c - '0');
  795.                     }
  796.                 }
  797.             } /* prec */
  798.             if (fmtcnt >= 0) {
  799.                 if (c == 'h' || c == 'l' || c == 'L') {
  800.                     size = c;
  801.                     if (--fmtcnt >= 0)
  802.                         c = *fmt++;
  803.                 }
  804.             }
  805.             if (fmtcnt < 0) {
  806.                 err_setstr(ValueError, "incomplete format");
  807.                 goto error;
  808.             }
  809.             if (c != '%') {
  810.                 v = getnextarg(args, arglen, &argidx);
  811.                 if (v == NULL)
  812.                     goto error;
  813.             }
  814.             sign = 0;
  815.             fill = ' ';
  816.             switch (c) {
  817.             case '%':
  818.                 buf = "%";
  819.                 len = 1;
  820.                 break;
  821.             case 's':
  822.                 v = strobject(v);
  823.                 if (v == NULL)
  824.                     goto error;
  825.                 buf = getstringvalue(v);
  826.                 len = getstringsize(v);
  827.                 DECREF(v);
  828.                 if (prec >= 0 && len > prec)
  829.                     len = prec;
  830.                 break;
  831.             case 'i':
  832.             case 'd':
  833.             case 'u':
  834.             case 'o':
  835.             case 'x':
  836.             case 'X':
  837.                 if (c == 'i')
  838.                     c = 'd';
  839.                 buf = formatint(flags, prec, c, v);
  840.                 if (buf == NULL)
  841.                     goto error;
  842.                 len = strlen(buf);
  843.                 sign = (c == 'd');
  844.                 if (flags&F_ZERO)
  845.                     fill = '0';
  846.                 break;
  847.             case 'e':
  848.             case 'E':
  849.             case 'f':
  850.             case 'g':
  851.             case 'G':
  852.                 buf = formatfloat(flags, prec, c, v);
  853.                 if (buf == NULL)
  854.                     goto error;
  855.                 len = strlen(buf);
  856.                 sign = 1;
  857.                 if (flags&F_ZERO)
  858.                     fill = '0';
  859.                 break;
  860.             case 'c':
  861.                 buf = formatchar(v);
  862.                 if (buf == NULL)
  863.                     goto error;
  864.                 len = 1;
  865.                 break;
  866.             default:
  867.                 err_setstr(ValueError,
  868.                        "unsupported format character");
  869.                 goto error;
  870.             }
  871.             if (sign) {
  872.                 if (*buf == '-' || *buf == '+') {
  873.                     sign = *buf++;
  874.                     len--;
  875.                 }
  876.                 else if (flags & F_SIGN)
  877.                     sign = '+';
  878.                 else if (flags & F_BLANK)
  879.                     sign = ' ';
  880.                 else
  881.                     sign = '\0';
  882.             }
  883.             if (width < len)
  884.                 width = len;
  885.             if (rescnt < width + (sign != '\0')) {
  886.                 reslen -= rescnt;
  887.                 rescnt = width + fmtcnt + 100;
  888.                 reslen += rescnt;
  889.                 if (resizestring(&result, reslen) < 0)
  890.                     return NULL;
  891.                 res = getstringvalue(result) + reslen - rescnt;
  892.             }
  893.             if (sign) {
  894.                 if (fill != ' ')
  895.                     *res++ = sign;
  896.                 rescnt--;
  897.                 if (width > len)
  898.                     width--;
  899.             }
  900.             if (width > len && !(flags&F_LJUST)) {
  901.                 do {
  902.                     --rescnt;
  903.                     *res++ = fill;
  904.                 } while (--width > len);
  905.             }
  906.             if (sign && fill == ' ')
  907.                 *res++ = sign;
  908.             memcpy(res, buf, len);
  909.             res += len;
  910.             rescnt -= len;
  911.             while (--width >= len) {
  912.                 --rescnt;
  913.                 *res++ = ' ';
  914.             }
  915.                         if (dict && (argidx < arglen)) {
  916.                                 err_setstr(TypeError,
  917.                                            "not all arguments converted");
  918.                                 goto error;
  919.                         }
  920.         } /* '%' */
  921.     } /* until end */
  922.     if (argidx < arglen) {
  923.         err_setstr(TypeError, "not all arguments converted");
  924.         goto error;
  925.     }
  926.     resizestring(&result, reslen - rescnt);
  927.     return result;
  928.  error:
  929.     DECREF(result);
  930.     return NULL;
  931. }
  932.