To: vim_dev@googlegroups.com Subject: Patch 7.4.2221 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.2221 Problem: printf() does not support binary format. Solution: Add %b and %B. (Ozaki Kiichi) Files: runtime/doc/eval.txt, src/message.c, src/testdir/test_expr.vim *** ../vim-7.4.2220/runtime/doc/eval.txt 2016-08-16 21:30:49.605848229 +0200 --- runtime/doc/eval.txt 2016-08-16 21:49:46.143645192 +0200 *************** *** 5855,5860 **** --- 5884,5890 ---- %04x hex number padded with zeros to at least 4 characters %X hex number using upper case letters %o octal number + %08b binary number padded with zeros to at least 8 chars %f floating point number in the form 123.456 %e floating point number in the form 1.234e3 %E floating point number in the form 1.234E3 *************** *** 5881,5886 **** --- 5911,5919 ---- character of the output string to a zero (except if a zero value is printed with an explicit precision of zero). + For b and B conversions, a non-zero result has + the string "0b" (or "0B" for B conversions) + prepended to it. For x and X conversions, a non-zero result has the string "0x" (or "0X" for X conversions) prepended to it. *************** *** 5888,5895 **** 0 (zero) Zero padding. For all conversions the converted value is padded on the left with zeros rather than blanks. If a precision is given with a ! numeric conversion (d, o, x, and X), the 0 flag ! is ignored. - A negative field width flag; the converted value is to be left adjusted on the field boundary. --- 5921,5928 ---- 0 (zero) Zero padding. For all conversions the converted value is padded on the left with zeros rather than blanks. If a precision is given with a ! numeric conversion (d, b, B, o, x, and X), the 0 ! flag is ignored. - A negative field width flag; the converted value is to be left adjusted on the field boundary. *************** *** 5901,5907 **** number produced by a signed conversion (d). + A sign must always be placed before a number ! produced by a signed conversion. A + overrides a space if both are used. field-width --- 5934,5940 ---- number produced by a signed conversion (d). + A sign must always be placed before a number ! produced by a signed conversion. A + overrides a space if both are used. field-width *************** *** 5927,5933 **** A field width or precision, or both, may be indicated by an asterisk '*' instead of a digit string. In this case, a ! Number argument supplies the field width or precision. A negative field width is treated as a left adjustment flag followed by a positive field width; a negative precision is treated as though it were missing. Example: > --- 5960,5966 ---- A field width or precision, or both, may be indicated by an asterisk '*' instead of a digit string. In this case, a ! Number argument supplies the field width or precision. A negative field width is treated as a left adjustment flag followed by a positive field width; a negative precision is treated as though it were missing. Example: > *************** *** 5937,5948 **** The conversion specifiers and their meanings are: ! *printf-d* *printf-o* *printf-x* *printf-X* ! doxX The Number argument is converted to signed decimal ! (d), unsigned octal (o), or unsigned hexadecimal (x ! and X) notation. The letters "abcdef" are used for ! x conversions; the letters "ABCDEF" are used for X ! conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with --- 5970,5982 ---- The conversion specifiers and their meanings are: ! *printf-d* *printf-b* *printf-B* *printf-o* ! *printf-x* *printf-X* ! dbBoxX The Number argument is converted to signed decimal ! (d), unsigned binary (b and B), unsigned octal (o), or ! unsigned hexadecimal (x and X) notation. The letters ! "abcdef" are used for x conversions; the letters ! "ABCDEF" are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with *** ../vim-7.4.2220/src/message.c 2016-08-16 21:30:49.605848229 +0200 --- src/message.c 2016-08-16 21:52:08.594366092 +0200 *************** *** 4091,4102 **** char length_modifier = '\0'; /* temporary buffer for simple numeric->string conversion */ ! # ifdef FEAT_FLOAT # define TMP_LEN 350 /* On my system 1e308 is the biggest number possible. * That sounds reasonable to use as the maximum * printable. */ # else ! # define TMP_LEN 32 # endif char tmp[TMP_LEN]; --- 4091,4104 ---- char length_modifier = '\0'; /* temporary buffer for simple numeric->string conversion */ ! # if defined(FEAT_FLOAT) # define TMP_LEN 350 /* On my system 1e308 is the biggest number possible. * That sounds reasonable to use as the maximum * printable. */ + # elif defined(FEAT_NUM64) + # define TMP_LEN 66 # else ! # define TMP_LEN 34 # endif char tmp[TMP_LEN]; *************** *** 4343,4351 **** } break; ! case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { ! /* NOTE: the u, o, x, X and p conversion specifiers * imply the value is unsigned; d implies a signed * value */ --- 4345,4357 ---- } break; ! case 'd': case 'u': ! case 'b': case 'B': ! case 'o': ! case 'x': case 'X': ! case 'p': { ! /* NOTE: the u, b, o, x, X and p conversion specifiers * imply the value is unsigned; d implies a signed * value */ *************** *** 4370,4375 **** --- 4376,4384 ---- uvarnumber_T ullong_arg = 0; # endif + /* only defined for b convertion */ + uvarnumber_T bin_arg = 0; + /* pointer argument value -only defined for p * conversion */ void *ptr_arg = NULL; *************** *** 4386,4391 **** --- 4395,4411 ---- if (ptr_arg != NULL) arg_sign = 1; } + else if (fmt_spec == 'b' || fmt_spec == 'B') + { + bin_arg = + # if defined(FEAT_EVAL) + tvs != NULL ? + (uvarnumber_T)tv_nr(tvs, &arg_idx) : + # endif + va_arg(ap, uvarnumber_T); + if (bin_arg != 0) + arg_sign = 1; + } else if (fmt_spec == 'd') { /* signed */ *************** *** 4492,4498 **** else if (alternate_form) { if (arg_sign != 0 ! && (fmt_spec == 'x' || fmt_spec == 'X') ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; --- 4512,4519 ---- else if (alternate_form) { if (arg_sign != 0 ! && (fmt_spec == 'b' || fmt_spec == 'B' ! || fmt_spec == 'x' || fmt_spec == 'X') ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; *************** *** 4508,4514 **** { /* When zero value is formatted with an explicit * precision 0, the resulting formatted string is ! * empty (d, i, u, o, x, X, p). */ } else { --- 4529,4535 ---- { /* When zero value is formatted with an explicit * precision 0, the resulting formatted string is ! * empty (d, i, u, b, B, o, x, X, p). */ } else { *************** *** 4541,4546 **** --- 4562,4583 ---- if (fmt_spec == 'p') str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); + else if (fmt_spec == 'b' || fmt_spec == 'B') + { + char b[8 * sizeof(uvarnumber_T)]; + size_t b_l = 0; + uvarnumber_T bn = bin_arg; + + do + { + b[sizeof(b) - ++b_l] = '0' + (bn & 0x1); + bn >>= 1; + } + while (bn != 0); + + memcpy(tmp + str_arg_l, b + sizeof(b) - b_l, b_l); + str_arg_l += b_l; + } else if (fmt_spec == 'd') { /* signed */ *** ../vim-7.4.2220/src/testdir/test_expr.vim 2016-08-16 21:30:49.605848229 +0200 --- src/testdir/test_expr.vim 2016-08-16 21:53:35.041589606 +0200 *************** *** 163,168 **** --- 163,185 ---- call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s']))) endfunc + function Test_printf_spec_b() + call assert_equal("0", printf('%b', 0)) + call assert_equal("00001100", printf('%08b', 12)) + call assert_equal("11111111", printf('%08b', 0xff)) + call assert_equal(" 1111011", printf('%10b', 123)) + call assert_equal("0001111011", printf('%010b', 123)) + call assert_equal(" 0b1111011", printf('%#10b', 123)) + call assert_equal("0B01111011", printf('%#010B', 123)) + call assert_equal("1001001100101100000001011010010", printf('%b', 1234567890)) + if has('num64') + call assert_equal("11100000100100010000110000011011101111101111001", printf('%b', 123456789012345)) + call assert_equal("1111111111111111111111111111111111111111111111111111111111111111", printf('%b', -1)) + else + call assert_equal("11111111111111111111111111111111", printf('%b', -1)) + endif + endfunc + func Test_substitute_expr() let g:val = 'XXX' call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', '')) *** ../vim-7.4.2220/src/version.c 2016-08-16 21:30:49.605848229 +0200 --- src/version.c 2016-08-16 21:47:18.536970024 +0200 *************** *** 765,766 **** --- 765,768 ---- { /* Add new patch number below this line */ + /**/ + 2221, /**/ -- How To Keep A Healthy Level Of Insanity: 14. Put mosquito netting around your work area. Play a tape of jungle sounds all day. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///