From a0182400776d7772d7d4ed3bbda916f4f9463f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 15 Apr 2009 20:53:44 +0200 Subject: [PATCH] Added support for specifying (some) modifiers via a mapping. Rev: src/modules/sprintf/sprintf.c:1.161 --- src/modules/sprintf/sprintf.c | 90 ++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/src/modules/sprintf/sprintf.c b/src/modules/sprintf/sprintf.c index ff499615e5..7dff00698c 100644 --- a/src/modules/sprintf/sprintf.c +++ b/src/modules/sprintf/sprintf.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: sprintf.c,v 1.160 2009/04/01 20:46:57 mast Exp $ +|| $Id: sprintf.c,v 1.161 2009/04/15 18:53:44 grubba Exp $ */ /* TODO: use ONERROR to cleanup fsp */ @@ -90,15 +90,26 @@ *! @value '$' *! Inverse table mode (left-to-right order). *! @value 'n' - *! (Where n is a number or *) field size specifier. + *! @value ':n' + *! (Where n is a number or *) field width specifier. *! @value '.n' *! Precision specifier. - *! @value ':n' - *! Field size precision specifier. *! @value ';n' *! Column width specifier. *! @value '*' - *! If n is a * then next argument is used for precision/field size. + *! If n is a @tt{*@} then next argument is used for precision/field + *! size. The argument may either be an integer, or a modifier mapping + *! as received by @[lfun::_sprintf()]: + *! @mapping + *! @member int|void "precision" + *! Precision. + *! @member int(0..)|void "width" + *! Field width. + *! @member int(0..1)|void "flag_left" + *! Indicates that the output should be left-aligned. + *! @member int(0..)|void "indent" + *! Indentation level in @tt{%O@}-mode. + *! @endmapping *! @value "'" *! Set a pad string. @tt{'@} cannot be a part of the pad string (yet). *! @value '~' @@ -197,6 +208,9 @@ *! @note *! The 'q' operator was added in Pike 7.7. *! + *! @note + *! Support for specifying modifiers via a mapping was added in Pike 7.8. + *! *! @example *! Pike v7.4 release 13 running Hilfe v3.5 (Incremental Pike Frontend) *! > sprintf("The unicode character %c has character code %04X.", 'A', 'A'); @@ -1009,7 +1023,7 @@ static void low_pike_sprintf(struct format_stack *fs, int compat_mode) { int argument=0; - int tmp,setwhat,d,e; + int tmp,setwhat,d,e,indent; char buffer[140]; struct format_info *f,*start; double tf; @@ -1056,6 +1070,7 @@ static void low_pike_sprintf(struct format_stack *fs, arg=NULL; setwhat=0; begin=a; + indent = 0; for(INC_PCHARP(a,1);;INC_PCHARP(a,1)) { @@ -1091,7 +1106,42 @@ static void low_pike_sprintf(struct format_stack *fs, goto got_arg; case '*': - GET_INT(tmp); + { + struct svalue *sval; + struct mapping *m; + GET_SVALUE(sval); + if (sval->type == T_INT) { + tmp = sval->u.integer; + goto got_arg; + } else if (sval->type != T_MAPPING) { + sprintf_error(fs, "Wrong type for argument %d: " + "expected %s, got %s.\n", + argument+1, "int|mapping(string:int)", + get_name_of_type(sval->type)); + } + m = sval->u.mapping; + if ((sval = simple_mapping_string_lookup(m, "precision")) && + (sval->type == T_INT)) { + fs->fsp->precision = sval->u.integer; + } + if ((sval = simple_mapping_string_lookup(m, "width")) && + (sval->type == T_INT) && (sval->u.integer >= 0)) { + fs->fsp->width = sval->u.integer; + } + if ((sval = simple_mapping_string_lookup(m, "flag_left")) && + (sval->type == T_INT)) { + if (sval->u.integer) { + fs->fsp->flags |= FIELD_LEFT; + } else { + fs->fsp->flags &= ~FIELD_LEFT; + } + } + if ((sval = simple_mapping_string_lookup(m, "indent")) && + (sval->type == T_INT) && (sval->u.integer >= 0)) { + indent = sval->u.integer; + } + continue; + } got_arg: switch(setwhat) @@ -1633,7 +1683,7 @@ static void low_pike_sprintf(struct format_stack *fs, dynbuf_string s; init_buf(&save_buf); - describe_svalue(t,0,0); + describe_svalue(t,indent,0); s=complex_free_buf(&save_buf); fs->fsp->b=MKPCHARP(s.str,0); fs->fsp->len=s.len; @@ -1930,15 +1980,6 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len, break; /* First the modifiers */ - case '0': - if (setwhat<2) continue; - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - tmp=STRTOL_PCHARP(a,&a,10); - INC_PCHARP(a,-1); - goto got_arg; - case '*': tmp = 0; if (setwhat < 2) { @@ -1946,8 +1987,21 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len, } else { push_int_type(MIN_INT32, MAX_INT32); } + /* Allow a mapping in all cases. */ + push_int_type(MIN_INT32, MAX_INT32); + push_type(T_STRING); + push_int_type(MIN_INT32, MAX_INT32); + push_reverse_type(T_MAPPING); + push_type(T_OR); + continue; - got_arg: + case '0': + if (setwhat<2) continue; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + tmp=STRTOL_PCHARP(a,&a,10); + INC_PCHARP(a,-1); switch(setwhat) { case 0: case 1: -- GitLab