1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * strings.c: string manipulation functions 12 */ 13 14 #define USING_FLOAT_STUFF 15 #include "vim.h" 16 17 /* 18 * Copy "string" into newly allocated memory. 19 */ 20 char_u * 21 vim_strsave(char_u *string) 22 { 23 char_u *p; 24 size_t len; 25 26 len = STRLEN(string) + 1; 27 p = alloc(len); 28 if (p != NULL) 29 mch_memmove(p, string, len); 30 return p; 31 } 32 33 /* 34 * Copy up to "len" bytes of "string" into newly allocated memory and 35 * terminate with a NUL. 36 * The allocated memory always has size "len + 1", also when "string" is 37 * shorter. 38 */ 39 char_u * 40 vim_strnsave(char_u *string, size_t len) 41 { 42 char_u *p; 43 44 p = alloc(len + 1); 45 if (p != NULL) 46 { 47 STRNCPY(p, string, len); 48 p[len] = NUL; 49 } 50 return p; 51 } 52 53 /* 54 * Same as vim_strsave(), but any characters found in esc_chars are preceded 55 * by a backslash. 56 */ 57 char_u * 58 vim_strsave_escaped(char_u *string, char_u *esc_chars) 59 { 60 return vim_strsave_escaped_ext(string, esc_chars, '\\', FALSE); 61 } 62 63 /* 64 * Same as vim_strsave_escaped(), but when "bsl" is TRUE also escape 65 * characters where rem_backslash() would remove the backslash. 66 * Escape the characters with "cc". 67 */ 68 char_u * 69 vim_strsave_escaped_ext( 70 char_u *string, 71 char_u *esc_chars, 72 int cc, 73 int bsl) 74 { 75 char_u *p; 76 char_u *p2; 77 char_u *escaped_string; 78 unsigned length; 79 int l; 80 81 // First count the number of backslashes required. 82 // Then allocate the memory and insert them. 83 length = 1; // count the trailing NUL 84 for (p = string; *p; p++) 85 { 86 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 87 { 88 length += l; // count a multibyte char 89 p += l - 1; 90 continue; 91 } 92 if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) 93 ++length; // count a backslash 94 ++length; // count an ordinary char 95 } 96 escaped_string = alloc(length); 97 if (escaped_string != NULL) 98 { 99 p2 = escaped_string; 100 for (p = string; *p; p++) 101 { 102 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 103 { 104 mch_memmove(p2, p, (size_t)l); 105 p2 += l; 106 p += l - 1; // skip multibyte char 107 continue; 108 } 109 if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) 110 *p2++ = cc; 111 *p2++ = *p; 112 } 113 *p2 = NUL; 114 } 115 return escaped_string; 116 } 117 118 /* 119 * Return TRUE when 'shell' has "csh" in the tail. 120 */ 121 int 122 csh_like_shell(void) 123 { 124 return (strstr((char *)gettail(p_sh), "csh") != NULL); 125 } 126 127 /* 128 * Escape "string" for use as a shell argument with system(). 129 * This uses single quotes, except when we know we need to use double quotes 130 * (MS-DOS and MS-Windows not using PowerShell and without 'shellslash' set). 131 * PowerShell also uses a novel escaping for enclosed single quotes - double 132 * them up. 133 * Escape a newline, depending on the 'shell' option. 134 * When "do_special" is TRUE also replace "!", "%", "#" and things starting 135 * with "<" like "<cfile>". 136 * When "do_newline" is FALSE do not escape newline unless it is csh shell. 137 * Returns the result in allocated memory, NULL if we have run out. 138 */ 139 char_u * 140 vim_strsave_shellescape(char_u *string, int do_special, int do_newline) 141 { 142 unsigned length; 143 char_u *p; 144 char_u *d; 145 char_u *escaped_string; 146 int l; 147 int csh_like; 148 char_u *shname; 149 int powershell; 150 # ifdef MSWIN 151 int double_quotes; 152 # endif 153 154 // Only csh and similar shells expand '!' within single quotes. For sh and 155 // the like we must not put a backslash before it, it will be taken 156 // literally. If do_special is set the '!' will be escaped twice. 157 // Csh also needs to have "\n" escaped twice when do_special is set. 158 csh_like = csh_like_shell(); 159 160 // PowerShell uses it's own version for quoting single quotes 161 shname = gettail(p_sh); 162 powershell = strstr((char *)shname, "pwsh") != NULL; 163 # ifdef MSWIN 164 powershell = powershell || strstr((char *)shname, "powershell") != NULL; 165 // PowerShell only accepts single quotes so override shellslash. 166 double_quotes = !powershell && !p_ssl; 167 # endif 168 169 // First count the number of extra bytes required. 170 length = (unsigned)STRLEN(string) + 3; // two quotes and a trailing NUL 171 for (p = string; *p != NUL; MB_PTR_ADV(p)) 172 { 173 # ifdef MSWIN 174 if (double_quotes) 175 { 176 if (*p == '"') 177 ++length; // " -> "" 178 } 179 else 180 # endif 181 if (*p == '\'') 182 { 183 if (powershell) 184 length +=2; // ' => '' 185 else 186 length += 3; // ' => '\'' 187 } 188 if ((*p == '\n' && (csh_like || do_newline)) 189 || (*p == '!' && (csh_like || do_special))) 190 { 191 ++length; // insert backslash 192 if (csh_like && do_special) 193 ++length; // insert backslash 194 } 195 if (do_special && find_cmdline_var(p, &l) >= 0) 196 { 197 ++length; // insert backslash 198 p += l - 1; 199 } 200 } 201 202 // Allocate memory for the result and fill it. 203 escaped_string = alloc(length); 204 if (escaped_string != NULL) 205 { 206 d = escaped_string; 207 208 // add opening quote 209 # ifdef MSWIN 210 if (double_quotes) 211 *d++ = '"'; 212 else 213 # endif 214 *d++ = '\''; 215 216 for (p = string; *p != NUL; ) 217 { 218 # ifdef MSWIN 219 if (double_quotes) 220 { 221 if (*p == '"') 222 { 223 *d++ = '"'; 224 *d++ = '"'; 225 ++p; 226 continue; 227 } 228 } 229 else 230 # endif 231 if (*p == '\'') 232 { 233 if (powershell) 234 { 235 *d++ = '\''; 236 *d++ = '\''; 237 } 238 else 239 { 240 *d++ = '\''; 241 *d++ = '\\'; 242 *d++ = '\''; 243 *d++ = '\''; 244 } 245 ++p; 246 continue; 247 } 248 if ((*p == '\n' && (csh_like || do_newline)) 249 || (*p == '!' && (csh_like || do_special))) 250 { 251 *d++ = '\\'; 252 if (csh_like && do_special) 253 *d++ = '\\'; 254 *d++ = *p++; 255 continue; 256 } 257 if (do_special && find_cmdline_var(p, &l) >= 0) 258 { 259 *d++ = '\\'; // insert backslash 260 while (--l >= 0) // copy the var 261 *d++ = *p++; 262 continue; 263 } 264 265 MB_COPY_CHAR(p, d); 266 } 267 268 // add terminating quote and finish with a NUL 269 # ifdef MSWIN 270 if (double_quotes) 271 *d++ = '"'; 272 else 273 # endif 274 *d++ = '\''; 275 *d = NUL; 276 } 277 278 return escaped_string; 279 } 280 281 /* 282 * Like vim_strsave(), but make all characters uppercase. 283 * This uses ASCII lower-to-upper case translation, language independent. 284 */ 285 char_u * 286 vim_strsave_up(char_u *string) 287 { 288 char_u *p1; 289 290 p1 = vim_strsave(string); 291 vim_strup(p1); 292 return p1; 293 } 294 295 /* 296 * Like vim_strnsave(), but make all characters uppercase. 297 * This uses ASCII lower-to-upper case translation, language independent. 298 */ 299 char_u * 300 vim_strnsave_up(char_u *string, size_t len) 301 { 302 char_u *p1; 303 304 p1 = vim_strnsave(string, len); 305 vim_strup(p1); 306 return p1; 307 } 308 309 /* 310 * ASCII lower-to-upper case translation, language independent. 311 */ 312 void 313 vim_strup( 314 char_u *p) 315 { 316 char_u *p2; 317 int c; 318 319 if (p != NULL) 320 { 321 p2 = p; 322 while ((c = *p2) != NUL) 323 #ifdef EBCDIC 324 *p2++ = isalpha(c) ? toupper(c) : c; 325 #else 326 *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20); 327 #endif 328 } 329 } 330 331 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO) 332 /* 333 * Make string "s" all upper-case and return it in allocated memory. 334 * Handles multi-byte characters as well as possible. 335 * Returns NULL when out of memory. 336 */ 337 static char_u * 338 strup_save(char_u *orig) 339 { 340 char_u *p; 341 char_u *res; 342 343 res = p = vim_strsave(orig); 344 345 if (res != NULL) 346 while (*p != NUL) 347 { 348 int l; 349 350 if (enc_utf8) 351 { 352 int c, uc; 353 int newl; 354 char_u *s; 355 356 c = utf_ptr2char(p); 357 l = utf_ptr2len(p); 358 if (c == 0) 359 { 360 // overlong sequence, use only the first byte 361 c = *p; 362 l = 1; 363 } 364 uc = utf_toupper(c); 365 366 // Reallocate string when byte count changes. This is rare, 367 // thus it's OK to do another malloc()/free(). 368 newl = utf_char2len(uc); 369 if (newl != l) 370 { 371 s = alloc(STRLEN(res) + 1 + newl - l); 372 if (s == NULL) 373 { 374 vim_free(res); 375 return NULL; 376 } 377 mch_memmove(s, res, p - res); 378 STRCPY(s + (p - res) + newl, p + l); 379 p = s + (p - res); 380 vim_free(res); 381 res = s; 382 } 383 384 utf_char2bytes(uc, p); 385 p += newl; 386 } 387 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 388 p += l; // skip multi-byte character 389 else 390 { 391 *p = TOUPPER_LOC(*p); // note that toupper() can be a macro 392 p++; 393 } 394 } 395 396 return res; 397 } 398 399 /* 400 * Make string "s" all lower-case and return it in allocated memory. 401 * Handles multi-byte characters as well as possible. 402 * Returns NULL when out of memory. 403 */ 404 char_u * 405 strlow_save(char_u *orig) 406 { 407 char_u *p; 408 char_u *res; 409 410 res = p = vim_strsave(orig); 411 412 if (res != NULL) 413 while (*p != NUL) 414 { 415 int l; 416 417 if (enc_utf8) 418 { 419 int c, lc; 420 int newl; 421 char_u *s; 422 423 c = utf_ptr2char(p); 424 l = utf_ptr2len(p); 425 if (c == 0) 426 { 427 // overlong sequence, use only the first byte 428 c = *p; 429 l = 1; 430 } 431 lc = utf_tolower(c); 432 433 // Reallocate string when byte count changes. This is rare, 434 // thus it's OK to do another malloc()/free(). 435 newl = utf_char2len(lc); 436 if (newl != l) 437 { 438 s = alloc(STRLEN(res) + 1 + newl - l); 439 if (s == NULL) 440 { 441 vim_free(res); 442 return NULL; 443 } 444 mch_memmove(s, res, p - res); 445 STRCPY(s + (p - res) + newl, p + l); 446 p = s + (p - res); 447 vim_free(res); 448 res = s; 449 } 450 451 utf_char2bytes(lc, p); 452 p += newl; 453 } 454 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 455 p += l; // skip multi-byte character 456 else 457 { 458 *p = TOLOWER_LOC(*p); // note that tolower() can be a macro 459 p++; 460 } 461 } 462 463 return res; 464 } 465 #endif 466 467 /* 468 * delete spaces at the end of a string 469 */ 470 void 471 del_trailing_spaces(char_u *ptr) 472 { 473 char_u *q; 474 475 q = ptr + STRLEN(ptr); 476 while (--q > ptr && VIM_ISWHITE(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) 477 *q = NUL; 478 } 479 480 /* 481 * Like strncpy(), but always terminate the result with one NUL. 482 * "to" must be "len + 1" long! 483 */ 484 void 485 vim_strncpy(char_u *to, char_u *from, size_t len) 486 { 487 STRNCPY(to, from, len); 488 to[len] = NUL; 489 } 490 491 /* 492 * Like strcat(), but make sure the result fits in "tosize" bytes and is 493 * always NUL terminated. "from" and "to" may overlap. 494 */ 495 void 496 vim_strcat(char_u *to, char_u *from, size_t tosize) 497 { 498 size_t tolen = STRLEN(to); 499 size_t fromlen = STRLEN(from); 500 501 if (tolen + fromlen + 1 > tosize) 502 { 503 mch_memmove(to + tolen, from, tosize - tolen - 1); 504 to[tosize - 1] = NUL; 505 } 506 else 507 mch_memmove(to + tolen, from, fromlen + 1); 508 } 509 510 #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO) 511 /* 512 * Compare two strings, ignoring case, using current locale. 513 * Doesn't work for multi-byte characters. 514 * return 0 for match, < 0 for smaller, > 0 for bigger 515 */ 516 int 517 vim_stricmp(char *s1, char *s2) 518 { 519 int i; 520 521 for (;;) 522 { 523 i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); 524 if (i != 0) 525 return i; // this character different 526 if (*s1 == NUL) 527 break; // strings match until NUL 528 ++s1; 529 ++s2; 530 } 531 return 0; // strings match 532 } 533 #endif 534 535 #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO) 536 /* 537 * Compare two strings, for length "len", ignoring case, using current locale. 538 * Doesn't work for multi-byte characters. 539 * return 0 for match, < 0 for smaller, > 0 for bigger 540 */ 541 int 542 vim_strnicmp(char *s1, char *s2, size_t len) 543 { 544 int i; 545 546 while (len > 0) 547 { 548 i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); 549 if (i != 0) 550 return i; // this character different 551 if (*s1 == NUL) 552 break; // strings match until NUL 553 ++s1; 554 ++s2; 555 --len; 556 } 557 return 0; // strings match 558 } 559 #endif 560 561 /* 562 * Search for first occurrence of "c" in "string". 563 * Version of strchr() that handles unsigned char strings with characters from 564 * 128 to 255 correctly. It also doesn't return a pointer to the NUL at the 565 * end of the string. 566 */ 567 char_u * 568 vim_strchr(char_u *string, int c) 569 { 570 char_u *p; 571 int b; 572 573 p = string; 574 if (enc_utf8 && c >= 0x80) 575 { 576 while (*p != NUL) 577 { 578 int l = utfc_ptr2len(p); 579 580 // Avoid matching an illegal byte here. 581 if (utf_ptr2char(p) == c && l > 1) 582 return p; 583 p += l; 584 } 585 return NULL; 586 } 587 if (enc_dbcs != 0 && c > 255) 588 { 589 int n2 = c & 0xff; 590 591 c = ((unsigned)c >> 8) & 0xff; 592 while ((b = *p) != NUL) 593 { 594 if (b == c && p[1] == n2) 595 return p; 596 p += (*mb_ptr2len)(p); 597 } 598 return NULL; 599 } 600 if (has_mbyte) 601 { 602 while ((b = *p) != NUL) 603 { 604 if (b == c) 605 return p; 606 p += (*mb_ptr2len)(p); 607 } 608 return NULL; 609 } 610 while ((b = *p) != NUL) 611 { 612 if (b == c) 613 return p; 614 ++p; 615 } 616 return NULL; 617 } 618 619 /* 620 * Version of strchr() that only works for bytes and handles unsigned char 621 * strings with characters above 128 correctly. It also doesn't return a 622 * pointer to the NUL at the end of the string. 623 */ 624 char_u * 625 vim_strbyte(char_u *string, int c) 626 { 627 char_u *p = string; 628 629 while (*p != NUL) 630 { 631 if (*p == c) 632 return p; 633 ++p; 634 } 635 return NULL; 636 } 637 638 /* 639 * Search for last occurrence of "c" in "string". 640 * Version of strrchr() that handles unsigned char strings with characters from 641 * 128 to 255 correctly. It also doesn't return a pointer to the NUL at the 642 * end of the string. 643 * Return NULL if not found. 644 * Does not handle multi-byte char for "c"! 645 */ 646 char_u * 647 vim_strrchr(char_u *string, int c) 648 { 649 char_u *retval = NULL; 650 char_u *p = string; 651 652 while (*p) 653 { 654 if (*p == c) 655 retval = p; 656 MB_PTR_ADV(p); 657 } 658 return retval; 659 } 660 661 /* 662 * Vim's version of strpbrk(), in case it's missing. 663 * Don't generate a prototype for this, causes problems when it's not used. 664 */ 665 #ifndef PROTO 666 # ifndef HAVE_STRPBRK 667 # ifdef vim_strpbrk 668 # undef vim_strpbrk 669 # endif 670 char_u * 671 vim_strpbrk(char_u *s, char_u *charset) 672 { 673 while (*s) 674 { 675 if (vim_strchr(charset, *s) != NULL) 676 return s; 677 MB_PTR_ADV(s); 678 } 679 return NULL; 680 } 681 # endif 682 #endif 683 684 /* 685 * Sort an array of strings. 686 */ 687 static int sort_compare(const void *s1, const void *s2); 688 689 static int 690 sort_compare(const void *s1, const void *s2) 691 { 692 return STRCMP(*(char **)s1, *(char **)s2); 693 } 694 695 void 696 sort_strings( 697 char_u **files, 698 int count) 699 { 700 qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare); 701 } 702 703 #if defined(FEAT_QUICKFIX) || defined(FEAT_SPELL) || defined(PROTO) 704 /* 705 * Return TRUE if string "s" contains a non-ASCII character (128 or higher). 706 * When "s" is NULL FALSE is returned. 707 */ 708 int 709 has_non_ascii(char_u *s) 710 { 711 char_u *p; 712 713 if (s != NULL) 714 for (p = s; *p != NUL; ++p) 715 if (*p >= 128) 716 return TRUE; 717 return FALSE; 718 } 719 #endif 720 721 /* 722 * Concatenate two strings and return the result in allocated memory. 723 * Returns NULL when out of memory. 724 */ 725 char_u * 726 concat_str(char_u *str1, char_u *str2) 727 { 728 char_u *dest; 729 size_t l = str1 == NULL ? 0 : STRLEN(str1); 730 731 dest = alloc(l + (str2 == NULL ? 0 : STRLEN(str2)) + 1L); 732 if (dest != NULL) 733 { 734 if (str1 == NULL) 735 *dest = NUL; 736 else 737 STRCPY(dest, str1); 738 if (str2 != NULL) 739 STRCPY(dest + l, str2); 740 } 741 return dest; 742 } 743 744 #if defined(FEAT_EVAL) || defined(PROTO) 745 746 /* 747 * Return string "str" in ' quotes, doubling ' characters. 748 * If "str" is NULL an empty string is assumed. 749 * If "function" is TRUE make it function('string'). 750 */ 751 char_u * 752 string_quote(char_u *str, int function) 753 { 754 unsigned len; 755 char_u *p, *r, *s; 756 757 len = (function ? 13 : 3); 758 if (str != NULL) 759 { 760 len += (unsigned)STRLEN(str); 761 for (p = str; *p != NUL; MB_PTR_ADV(p)) 762 if (*p == '\'') 763 ++len; 764 } 765 s = r = alloc(len); 766 if (r != NULL) 767 { 768 if (function) 769 { 770 STRCPY(r, "function('"); 771 r += 10; 772 } 773 else 774 *r++ = '\''; 775 if (str != NULL) 776 for (p = str; *p != NUL; ) 777 { 778 if (*p == '\'') 779 *r++ = '\''; 780 MB_COPY_CHAR(p, r); 781 } 782 *r++ = '\''; 783 if (function) 784 *r++ = ')'; 785 *r++ = NUL; 786 } 787 return s; 788 } 789 790 static void 791 byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED) 792 { 793 char_u *t; 794 char_u *str; 795 varnumber_T idx; 796 797 rettv->vval.v_number = -1; 798 799 if (in_vim9script() 800 && (check_for_string_arg(argvars, 0) == FAIL 801 || check_for_number_arg(argvars, 1) == FAIL)) 802 return; 803 804 str = tv_get_string_chk(&argvars[0]); 805 idx = tv_get_number_chk(&argvars[1], NULL); 806 if (str == NULL || idx < 0) 807 return; 808 809 t = str; 810 for ( ; idx > 0; idx--) 811 { 812 if (*t == NUL) // EOL reached 813 return; 814 if (enc_utf8 && comp) 815 t += utf_ptr2len(t); 816 else 817 t += (*mb_ptr2len)(t); 818 } 819 rettv->vval.v_number = (varnumber_T)(t - str); 820 } 821 822 /* 823 * "byteidx()" function 824 */ 825 void 826 f_byteidx(typval_T *argvars, typval_T *rettv) 827 { 828 byteidx(argvars, rettv, FALSE); 829 } 830 831 /* 832 * "byteidxcomp()" function 833 */ 834 void 835 f_byteidxcomp(typval_T *argvars, typval_T *rettv) 836 { 837 byteidx(argvars, rettv, TRUE); 838 } 839 840 /* 841 * "charidx()" function 842 */ 843 void 844 f_charidx(typval_T *argvars, typval_T *rettv) 845 { 846 char_u *str; 847 varnumber_T idx; 848 varnumber_T countcc = FALSE; 849 char_u *p; 850 int len; 851 int (*ptr2len)(char_u *); 852 853 rettv->vval.v_number = -1; 854 855 if (in_vim9script() 856 && (check_for_string_arg(argvars, 0) == FAIL 857 || check_for_number_arg(argvars, 1) == FAIL 858 || check_for_opt_bool_arg(argvars, 2) == FAIL)) 859 return; 860 861 if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER 862 || (argvars[2].v_type != VAR_UNKNOWN 863 && argvars[2].v_type != VAR_NUMBER 864 && argvars[2].v_type != VAR_BOOL)) 865 { 866 emsg(_(e_invarg)); 867 return; 868 } 869 870 str = tv_get_string_chk(&argvars[0]); 871 idx = tv_get_number_chk(&argvars[1], NULL); 872 if (str == NULL || idx < 0) 873 return; 874 875 if (argvars[2].v_type != VAR_UNKNOWN) 876 countcc = tv_get_bool(&argvars[2]); 877 if (countcc < 0 || countcc > 1) 878 { 879 semsg(_(e_using_number_as_bool_nr), countcc); 880 return; 881 } 882 883 if (enc_utf8 && countcc) 884 ptr2len = utf_ptr2len; 885 else 886 ptr2len = mb_ptr2len; 887 888 for (p = str, len = 0; p <= str + idx; len++) 889 { 890 if (*p == NUL) 891 return; 892 p += ptr2len(p); 893 } 894 895 rettv->vval.v_number = len > 0 ? len - 1 : 0; 896 } 897 898 /* 899 * "str2list()" function 900 */ 901 void 902 f_str2list(typval_T *argvars, typval_T *rettv) 903 { 904 char_u *p; 905 int utf8 = FALSE; 906 907 if (rettv_list_alloc(rettv) == FAIL) 908 return; 909 910 if (in_vim9script() 911 && (check_for_string_arg(argvars, 0) == FAIL 912 || check_for_opt_bool_arg(argvars, 1) == FAIL)) 913 return; 914 915 if (argvars[1].v_type != VAR_UNKNOWN) 916 utf8 = (int)tv_get_bool_chk(&argvars[1], NULL); 917 918 p = tv_get_string(&argvars[0]); 919 920 if (has_mbyte || utf8) 921 { 922 int (*ptr2len)(char_u *); 923 int (*ptr2char)(char_u *); 924 925 if (utf8 || enc_utf8) 926 { 927 ptr2len = utf_ptr2len; 928 ptr2char = utf_ptr2char; 929 } 930 else 931 { 932 ptr2len = mb_ptr2len; 933 ptr2char = mb_ptr2char; 934 } 935 936 for ( ; *p != NUL; p += (*ptr2len)(p)) 937 list_append_number(rettv->vval.v_list, (*ptr2char)(p)); 938 } 939 else 940 for ( ; *p != NUL; ++p) 941 list_append_number(rettv->vval.v_list, *p); 942 } 943 944 /* 945 * "str2nr()" function 946 */ 947 void 948 f_str2nr(typval_T *argvars, typval_T *rettv) 949 { 950 int base = 10; 951 char_u *p; 952 varnumber_T n; 953 int what = 0; 954 int isneg; 955 956 if (in_vim9script() 957 && (check_for_string_arg(argvars, 0) == FAIL 958 || check_for_opt_number_arg(argvars, 1) == FAIL 959 || (argvars[1].v_type != VAR_UNKNOWN 960 && check_for_opt_bool_arg(argvars, 2) == FAIL))) 961 return; 962 963 if (argvars[1].v_type != VAR_UNKNOWN) 964 { 965 base = (int)tv_get_number(&argvars[1]); 966 if (base != 2 && base != 8 && base != 10 && base != 16) 967 { 968 emsg(_(e_invarg)); 969 return; 970 } 971 if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2])) 972 what |= STR2NR_QUOTE; 973 } 974 975 p = skipwhite(tv_get_string_strict(&argvars[0])); 976 isneg = (*p == '-'); 977 if (*p == '+' || *p == '-') 978 p = skipwhite(p + 1); 979 switch (base) 980 { 981 case 2: what |= STR2NR_BIN + STR2NR_FORCE; break; 982 case 8: what |= STR2NR_OCT + STR2NR_OOCT + STR2NR_FORCE; break; 983 case 16: what |= STR2NR_HEX + STR2NR_FORCE; break; 984 } 985 vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE); 986 // Text after the number is silently ignored. 987 if (isneg) 988 rettv->vval.v_number = -n; 989 else 990 rettv->vval.v_number = n; 991 992 } 993 994 /* 995 * "strgetchar()" function 996 */ 997 void 998 f_strgetchar(typval_T *argvars, typval_T *rettv) 999 { 1000 char_u *str; 1001 int len; 1002 int error = FALSE; 1003 int charidx; 1004 int byteidx = 0; 1005 1006 rettv->vval.v_number = -1; 1007 1008 if (in_vim9script() 1009 && (check_for_string_arg(argvars, 0) == FAIL 1010 || check_for_number_arg(argvars, 1) == FAIL)) 1011 return; 1012 1013 str = tv_get_string_chk(&argvars[0]); 1014 if (str == NULL) 1015 return; 1016 len = (int)STRLEN(str); 1017 charidx = (int)tv_get_number_chk(&argvars[1], &error); 1018 if (error) 1019 return; 1020 1021 while (charidx >= 0 && byteidx < len) 1022 { 1023 if (charidx == 0) 1024 { 1025 rettv->vval.v_number = mb_ptr2char(str + byteidx); 1026 break; 1027 } 1028 --charidx; 1029 byteidx += MB_CPTR2LEN(str + byteidx); 1030 } 1031 } 1032 1033 /* 1034 * "stridx()" function 1035 */ 1036 void 1037 f_stridx(typval_T *argvars, typval_T *rettv) 1038 { 1039 char_u buf[NUMBUFLEN]; 1040 char_u *needle; 1041 char_u *haystack; 1042 char_u *save_haystack; 1043 char_u *pos; 1044 int start_idx; 1045 1046 if (in_vim9script() 1047 && (check_for_string_arg(argvars, 0) == FAIL 1048 || check_for_string_arg(argvars, 1) == FAIL 1049 || check_for_opt_number_arg(argvars, 2) == FAIL)) 1050 return; 1051 1052 needle = tv_get_string_chk(&argvars[1]); 1053 save_haystack = haystack = tv_get_string_buf_chk(&argvars[0], buf); 1054 rettv->vval.v_number = -1; 1055 if (needle == NULL || haystack == NULL) 1056 return; // type error; errmsg already given 1057 1058 if (argvars[2].v_type != VAR_UNKNOWN) 1059 { 1060 int error = FALSE; 1061 1062 start_idx = (int)tv_get_number_chk(&argvars[2], &error); 1063 if (error || start_idx >= (int)STRLEN(haystack)) 1064 return; 1065 if (start_idx >= 0) 1066 haystack += start_idx; 1067 } 1068 1069 pos = (char_u *)strstr((char *)haystack, (char *)needle); 1070 if (pos != NULL) 1071 rettv->vval.v_number = (varnumber_T)(pos - save_haystack); 1072 } 1073 1074 /* 1075 * "string()" function 1076 */ 1077 void 1078 f_string(typval_T *argvars, typval_T *rettv) 1079 { 1080 char_u *tofree; 1081 char_u numbuf[NUMBUFLEN]; 1082 1083 rettv->v_type = VAR_STRING; 1084 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 1085 get_copyID()); 1086 // Make a copy if we have a value but it's not in allocated memory. 1087 if (rettv->vval.v_string != NULL && tofree == NULL) 1088 rettv->vval.v_string = vim_strsave(rettv->vval.v_string); 1089 } 1090 1091 /* 1092 * "strlen()" function 1093 */ 1094 void 1095 f_strlen(typval_T *argvars, typval_T *rettv) 1096 { 1097 if (in_vim9script() 1098 && check_for_string_or_number_arg(argvars, 0) == FAIL) 1099 return; 1100 1101 rettv->vval.v_number = (varnumber_T)(STRLEN( 1102 tv_get_string(&argvars[0]))); 1103 } 1104 1105 static void 1106 strchar_common(typval_T *argvars, typval_T *rettv, int skipcc) 1107 { 1108 char_u *s = tv_get_string(&argvars[0]); 1109 varnumber_T len = 0; 1110 int (*func_mb_ptr2char_adv)(char_u **pp); 1111 1112 func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; 1113 while (*s != NUL) 1114 { 1115 func_mb_ptr2char_adv(&s); 1116 ++len; 1117 } 1118 rettv->vval.v_number = len; 1119 } 1120 1121 /* 1122 * "strcharlen()" function 1123 */ 1124 void 1125 f_strcharlen(typval_T *argvars, typval_T *rettv) 1126 { 1127 if (in_vim9script() 1128 && check_for_string_or_number_arg(argvars, 0) == FAIL) 1129 return; 1130 1131 strchar_common(argvars, rettv, TRUE); 1132 } 1133 1134 /* 1135 * "strchars()" function 1136 */ 1137 void 1138 f_strchars(typval_T *argvars, typval_T *rettv) 1139 { 1140 varnumber_T skipcc = FALSE; 1141 1142 if (in_vim9script() 1143 && (check_for_string_arg(argvars, 0) == FAIL 1144 || check_for_opt_bool_arg(argvars, 1) == FAIL)) 1145 return; 1146 1147 if (argvars[1].v_type != VAR_UNKNOWN) 1148 skipcc = tv_get_bool(&argvars[1]); 1149 if (skipcc < 0 || skipcc > 1) 1150 semsg(_(e_using_number_as_bool_nr), skipcc); 1151 else 1152 strchar_common(argvars, rettv, skipcc); 1153 } 1154 1155 /* 1156 * "strdisplaywidth()" function 1157 */ 1158 void 1159 f_strdisplaywidth(typval_T *argvars, typval_T *rettv) 1160 { 1161 char_u *s; 1162 int col = 0; 1163 1164 rettv->vval.v_number = -1; 1165 1166 if (in_vim9script() 1167 && (check_for_string_arg(argvars, 0) == FAIL 1168 || check_for_opt_number_arg(argvars, 1) == FAIL)) 1169 return; 1170 1171 s = tv_get_string(&argvars[0]); 1172 if (argvars[1].v_type != VAR_UNKNOWN) 1173 col = (int)tv_get_number(&argvars[1]); 1174 1175 rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col); 1176 } 1177 1178 /* 1179 * "strwidth()" function 1180 */ 1181 void 1182 f_strwidth(typval_T *argvars, typval_T *rettv) 1183 { 1184 char_u *s; 1185 1186 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) 1187 return; 1188 1189 s = tv_get_string_strict(&argvars[0]); 1190 rettv->vval.v_number = (varnumber_T)(mb_string2cells(s, -1)); 1191 } 1192 1193 /* 1194 * "strcharpart()" function 1195 */ 1196 void 1197 f_strcharpart(typval_T *argvars, typval_T *rettv) 1198 { 1199 char_u *p; 1200 int nchar; 1201 int nbyte = 0; 1202 int charlen; 1203 int skipcc = FALSE; 1204 int len = 0; 1205 int slen; 1206 int error = FALSE; 1207 1208 if (in_vim9script() 1209 && (check_for_string_arg(argvars, 0) == FAIL 1210 || check_for_number_arg(argvars, 1) == FAIL 1211 || check_for_opt_number_arg(argvars, 2) == FAIL 1212 || (argvars[2].v_type != VAR_UNKNOWN 1213 && check_for_opt_bool_arg(argvars, 3) == FAIL))) 1214 return; 1215 1216 p = tv_get_string(&argvars[0]); 1217 slen = (int)STRLEN(p); 1218 1219 nchar = (int)tv_get_number_chk(&argvars[1], &error); 1220 if (!error) 1221 { 1222 if (argvars[2].v_type != VAR_UNKNOWN 1223 && argvars[3].v_type != VAR_UNKNOWN) 1224 { 1225 skipcc = tv_get_bool(&argvars[3]); 1226 if (skipcc < 0 || skipcc > 1) 1227 { 1228 semsg(_(e_using_number_as_bool_nr), skipcc); 1229 return; 1230 } 1231 } 1232 1233 if (nchar > 0) 1234 while (nchar > 0 && nbyte < slen) 1235 { 1236 if (skipcc) 1237 nbyte += mb_ptr2len(p + nbyte); 1238 else 1239 nbyte += MB_CPTR2LEN(p + nbyte); 1240 --nchar; 1241 } 1242 else 1243 nbyte = nchar; 1244 if (argvars[2].v_type != VAR_UNKNOWN) 1245 { 1246 charlen = (int)tv_get_number(&argvars[2]); 1247 while (charlen > 0 && nbyte + len < slen) 1248 { 1249 int off = nbyte + len; 1250 1251 if (off < 0) 1252 len += 1; 1253 else 1254 { 1255 if (skipcc) 1256 len += mb_ptr2len(p + off); 1257 else 1258 len += MB_CPTR2LEN(p + off); 1259 } 1260 --charlen; 1261 } 1262 } 1263 else 1264 len = slen - nbyte; // default: all bytes that are available. 1265 } 1266 1267 // Only return the overlap between the specified part and the actual 1268 // string. 1269 if (nbyte < 0) 1270 { 1271 len += nbyte; 1272 nbyte = 0; 1273 } 1274 else if (nbyte > slen) 1275 nbyte = slen; 1276 if (len < 0) 1277 len = 0; 1278 else if (nbyte + len > slen) 1279 len = slen - nbyte; 1280 1281 rettv->v_type = VAR_STRING; 1282 rettv->vval.v_string = vim_strnsave(p + nbyte, len); 1283 } 1284 1285 /* 1286 * "strpart()" function 1287 */ 1288 void 1289 f_strpart(typval_T *argvars, typval_T *rettv) 1290 { 1291 char_u *p; 1292 int n; 1293 int len; 1294 int slen; 1295 int error = FALSE; 1296 1297 if (in_vim9script() 1298 && (check_for_string_arg(argvars, 0) == FAIL 1299 || check_for_number_arg(argvars, 1) == FAIL 1300 || check_for_opt_number_arg(argvars, 2) == FAIL 1301 || (argvars[2].v_type != VAR_UNKNOWN 1302 && check_for_opt_bool_arg(argvars, 3) == FAIL))) 1303 return; 1304 1305 p = tv_get_string(&argvars[0]); 1306 slen = (int)STRLEN(p); 1307 1308 n = (int)tv_get_number_chk(&argvars[1], &error); 1309 if (error) 1310 len = 0; 1311 else if (argvars[2].v_type != VAR_UNKNOWN) 1312 len = (int)tv_get_number(&argvars[2]); 1313 else 1314 len = slen - n; // default len: all bytes that are available. 1315 1316 // Only return the overlap between the specified part and the actual 1317 // string. 1318 if (n < 0) 1319 { 1320 len += n; 1321 n = 0; 1322 } 1323 else if (n > slen) 1324 n = slen; 1325 if (len < 0) 1326 len = 0; 1327 else if (n + len > slen) 1328 len = slen - n; 1329 1330 if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN) 1331 { 1332 int off; 1333 1334 // length in characters 1335 for (off = n; off < slen && len > 0; --len) 1336 off += mb_ptr2len(p + off); 1337 len = off - n; 1338 } 1339 1340 rettv->v_type = VAR_STRING; 1341 rettv->vval.v_string = vim_strnsave(p + n, len); 1342 } 1343 1344 /* 1345 * "strridx()" function 1346 */ 1347 void 1348 f_strridx(typval_T *argvars, typval_T *rettv) 1349 { 1350 char_u buf[NUMBUFLEN]; 1351 char_u *needle; 1352 char_u *haystack; 1353 char_u *rest; 1354 char_u *lastmatch = NULL; 1355 int haystack_len, end_idx; 1356 1357 if (in_vim9script() 1358 && (check_for_string_arg(argvars, 0) == FAIL 1359 || check_for_string_arg(argvars, 1) == FAIL 1360 || check_for_opt_number_arg(argvars, 2) == FAIL)) 1361 return; 1362 1363 needle = tv_get_string_chk(&argvars[1]); 1364 haystack = tv_get_string_buf_chk(&argvars[0], buf); 1365 1366 rettv->vval.v_number = -1; 1367 if (needle == NULL || haystack == NULL) 1368 return; // type error; errmsg already given 1369 1370 haystack_len = (int)STRLEN(haystack); 1371 if (argvars[2].v_type != VAR_UNKNOWN) 1372 { 1373 // Third argument: upper limit for index 1374 end_idx = (int)tv_get_number_chk(&argvars[2], NULL); 1375 if (end_idx < 0) 1376 return; // can never find a match 1377 } 1378 else 1379 end_idx = haystack_len; 1380 1381 if (*needle == NUL) 1382 { 1383 // Empty string matches past the end. 1384 lastmatch = haystack + end_idx; 1385 } 1386 else 1387 { 1388 for (rest = haystack; *rest != '\0'; ++rest) 1389 { 1390 rest = (char_u *)strstr((char *)rest, (char *)needle); 1391 if (rest == NULL || rest > haystack + end_idx) 1392 break; 1393 lastmatch = rest; 1394 } 1395 } 1396 1397 if (lastmatch == NULL) 1398 rettv->vval.v_number = -1; 1399 else 1400 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); 1401 } 1402 1403 /* 1404 * "strtrans()" function 1405 */ 1406 void 1407 f_strtrans(typval_T *argvars, typval_T *rettv) 1408 { 1409 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) 1410 return; 1411 1412 rettv->v_type = VAR_STRING; 1413 rettv->vval.v_string = transstr(tv_get_string(&argvars[0])); 1414 } 1415 1416 /* 1417 * "tolower(string)" function 1418 */ 1419 void 1420 f_tolower(typval_T *argvars, typval_T *rettv) 1421 { 1422 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) 1423 return; 1424 1425 rettv->v_type = VAR_STRING; 1426 rettv->vval.v_string = strlow_save(tv_get_string(&argvars[0])); 1427 } 1428 1429 /* 1430 * "toupper(string)" function 1431 */ 1432 void 1433 f_toupper(typval_T *argvars, typval_T *rettv) 1434 { 1435 if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) 1436 return; 1437 1438 rettv->v_type = VAR_STRING; 1439 rettv->vval.v_string = strup_save(tv_get_string(&argvars[0])); 1440 } 1441 1442 /* 1443 * "tr(string, fromstr, tostr)" function 1444 */ 1445 void 1446 f_tr(typval_T *argvars, typval_T *rettv) 1447 { 1448 char_u *in_str; 1449 char_u *fromstr; 1450 char_u *tostr; 1451 char_u *p; 1452 int inlen; 1453 int fromlen; 1454 int tolen; 1455 int idx; 1456 char_u *cpstr; 1457 int cplen; 1458 int first = TRUE; 1459 char_u buf[NUMBUFLEN]; 1460 char_u buf2[NUMBUFLEN]; 1461 garray_T ga; 1462 1463 if (in_vim9script() 1464 && (check_for_string_arg(argvars, 0) == FAIL 1465 || check_for_string_arg(argvars, 1) == FAIL 1466 || check_for_string_arg(argvars, 2) == FAIL)) 1467 return; 1468 1469 in_str = tv_get_string(&argvars[0]); 1470 fromstr = tv_get_string_buf_chk(&argvars[1], buf); 1471 tostr = tv_get_string_buf_chk(&argvars[2], buf2); 1472 1473 // Default return value: empty string. 1474 rettv->v_type = VAR_STRING; 1475 rettv->vval.v_string = NULL; 1476 if (fromstr == NULL || tostr == NULL) 1477 return; // type error; errmsg already given 1478 ga_init2(&ga, (int)sizeof(char), 80); 1479 1480 if (!has_mbyte) 1481 // not multi-byte: fromstr and tostr must be the same length 1482 if (STRLEN(fromstr) != STRLEN(tostr)) 1483 { 1484 error: 1485 semsg(_(e_invarg2), fromstr); 1486 ga_clear(&ga); 1487 return; 1488 } 1489 1490 // fromstr and tostr have to contain the same number of chars 1491 while (*in_str != NUL) 1492 { 1493 if (has_mbyte) 1494 { 1495 inlen = (*mb_ptr2len)(in_str); 1496 cpstr = in_str; 1497 cplen = inlen; 1498 idx = 0; 1499 for (p = fromstr; *p != NUL; p += fromlen) 1500 { 1501 fromlen = (*mb_ptr2len)(p); 1502 if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) 1503 { 1504 for (p = tostr; *p != NUL; p += tolen) 1505 { 1506 tolen = (*mb_ptr2len)(p); 1507 if (idx-- == 0) 1508 { 1509 cplen = tolen; 1510 cpstr = p; 1511 break; 1512 } 1513 } 1514 if (*p == NUL) // tostr is shorter than fromstr 1515 goto error; 1516 break; 1517 } 1518 ++idx; 1519 } 1520 1521 if (first && cpstr == in_str) 1522 { 1523 // Check that fromstr and tostr have the same number of 1524 // (multi-byte) characters. Done only once when a character 1525 // of in_str doesn't appear in fromstr. 1526 first = FALSE; 1527 for (p = tostr; *p != NUL; p += tolen) 1528 { 1529 tolen = (*mb_ptr2len)(p); 1530 --idx; 1531 } 1532 if (idx != 0) 1533 goto error; 1534 } 1535 1536 (void)ga_grow(&ga, cplen); 1537 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); 1538 ga.ga_len += cplen; 1539 1540 in_str += inlen; 1541 } 1542 else 1543 { 1544 // When not using multi-byte chars we can do it faster. 1545 p = vim_strchr(fromstr, *in_str); 1546 if (p != NULL) 1547 ga_append(&ga, tostr[p - fromstr]); 1548 else 1549 ga_append(&ga, *in_str); 1550 ++in_str; 1551 } 1552 } 1553 1554 // add a terminating NUL 1555 (void)ga_grow(&ga, 1); 1556 ga_append(&ga, NUL); 1557 1558 rettv->vval.v_string = ga.ga_data; 1559 } 1560 1561 /* 1562 * "trim({expr})" function 1563 */ 1564 void 1565 f_trim(typval_T *argvars, typval_T *rettv) 1566 { 1567 char_u buf1[NUMBUFLEN]; 1568 char_u buf2[NUMBUFLEN]; 1569 char_u *head; 1570 char_u *mask = NULL; 1571 char_u *tail; 1572 char_u *prev; 1573 char_u *p; 1574 int c1; 1575 int dir = 0; 1576 1577 rettv->v_type = VAR_STRING; 1578 rettv->vval.v_string = NULL; 1579 1580 if (in_vim9script() 1581 && (check_for_string_arg(argvars, 0) == FAIL 1582 || check_for_opt_string_arg(argvars, 1) == FAIL 1583 || (argvars[1].v_type != VAR_UNKNOWN 1584 && check_for_opt_number_arg(argvars, 2) == FAIL))) 1585 return; 1586 1587 head = tv_get_string_buf_chk(&argvars[0], buf1); 1588 if (head == NULL) 1589 return; 1590 1591 if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING) 1592 { 1593 semsg(_(e_invarg2), tv_get_string(&argvars[1])); 1594 return; 1595 } 1596 1597 if (argvars[1].v_type == VAR_STRING) 1598 { 1599 mask = tv_get_string_buf_chk(&argvars[1], buf2); 1600 1601 if (argvars[2].v_type != VAR_UNKNOWN) 1602 { 1603 int error = 0; 1604 1605 // leading or trailing characters to trim 1606 dir = (int)tv_get_number_chk(&argvars[2], &error); 1607 if (error) 1608 return; 1609 if (dir < 0 || dir > 2) 1610 { 1611 semsg(_(e_invarg2), tv_get_string(&argvars[2])); 1612 return; 1613 } 1614 } 1615 } 1616 1617 if (dir == 0 || dir == 1) 1618 { 1619 // Trim leading characters 1620 while (*head != NUL) 1621 { 1622 c1 = PTR2CHAR(head); 1623 if (mask == NULL) 1624 { 1625 if (c1 > ' ' && c1 != 0xa0) 1626 break; 1627 } 1628 else 1629 { 1630 for (p = mask; *p != NUL; MB_PTR_ADV(p)) 1631 if (c1 == PTR2CHAR(p)) 1632 break; 1633 if (*p == NUL) 1634 break; 1635 } 1636 MB_PTR_ADV(head); 1637 } 1638 } 1639 1640 tail = head + STRLEN(head); 1641 if (dir == 0 || dir == 2) 1642 { 1643 // Trim trailing characters 1644 for (; tail > head; tail = prev) 1645 { 1646 prev = tail; 1647 MB_PTR_BACK(head, prev); 1648 c1 = PTR2CHAR(prev); 1649 if (mask == NULL) 1650 { 1651 if (c1 > ' ' && c1 != 0xa0) 1652 break; 1653 } 1654 else 1655 { 1656 for (p = mask; *p != NUL; MB_PTR_ADV(p)) 1657 if (c1 == PTR2CHAR(p)) 1658 break; 1659 if (*p == NUL) 1660 break; 1661 } 1662 } 1663 } 1664 rettv->vval.v_string = vim_strnsave(head, tail - head); 1665 } 1666 1667 #endif 1668 1669 #if defined(FEAT_EVAL) 1670 static char *e_printf = N_("E766: Insufficient arguments for printf()"); 1671 1672 /* 1673 * Get number argument from "idxp" entry in "tvs". First entry is 1. 1674 */ 1675 static varnumber_T 1676 tv_nr(typval_T *tvs, int *idxp) 1677 { 1678 int idx = *idxp - 1; 1679 varnumber_T n = 0; 1680 int err = FALSE; 1681 1682 if (tvs[idx].v_type == VAR_UNKNOWN) 1683 emsg(_(e_printf)); 1684 else 1685 { 1686 ++*idxp; 1687 n = tv_get_number_chk(&tvs[idx], &err); 1688 if (err) 1689 n = 0; 1690 } 1691 return n; 1692 } 1693 1694 /* 1695 * Get string argument from "idxp" entry in "tvs". First entry is 1. 1696 * If "tofree" is NULL tv_get_string_chk() is used. Some types (e.g. List) 1697 * are not converted to a string. 1698 * If "tofree" is not NULL echo_string() is used. All types are converted to 1699 * a string with the same format as ":echo". The caller must free "*tofree". 1700 * Returns NULL for an error. 1701 */ 1702 static char * 1703 tv_str(typval_T *tvs, int *idxp, char_u **tofree) 1704 { 1705 int idx = *idxp - 1; 1706 char *s = NULL; 1707 static char_u numbuf[NUMBUFLEN]; 1708 1709 if (tvs[idx].v_type == VAR_UNKNOWN) 1710 emsg(_(e_printf)); 1711 else 1712 { 1713 ++*idxp; 1714 if (tofree != NULL) 1715 s = (char *)echo_string(&tvs[idx], tofree, numbuf, get_copyID()); 1716 else 1717 s = (char *)tv_get_string_chk(&tvs[idx]); 1718 } 1719 return s; 1720 } 1721 1722 # ifdef FEAT_FLOAT 1723 /* 1724 * Get float argument from "idxp" entry in "tvs". First entry is 1. 1725 */ 1726 static double 1727 tv_float(typval_T *tvs, int *idxp) 1728 { 1729 int idx = *idxp - 1; 1730 double f = 0; 1731 1732 if (tvs[idx].v_type == VAR_UNKNOWN) 1733 emsg(_(e_printf)); 1734 else 1735 { 1736 ++*idxp; 1737 if (tvs[idx].v_type == VAR_FLOAT) 1738 f = tvs[idx].vval.v_float; 1739 else if (tvs[idx].v_type == VAR_NUMBER) 1740 f = (double)tvs[idx].vval.v_number; 1741 else 1742 emsg(_("E807: Expected Float argument for printf()")); 1743 } 1744 return f; 1745 } 1746 # endif 1747 #endif 1748 1749 #ifdef FEAT_FLOAT 1750 /* 1751 * Return the representation of infinity for printf() function: 1752 * "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". 1753 */ 1754 static const char * 1755 infinity_str(int positive, 1756 char fmt_spec, 1757 int force_sign, 1758 int space_for_positive) 1759 { 1760 static const char *table[] = 1761 { 1762 "-inf", "inf", "+inf", " inf", 1763 "-INF", "INF", "+INF", " INF" 1764 }; 1765 int idx = positive * (1 + force_sign + force_sign * space_for_positive); 1766 1767 if (ASCII_ISUPPER(fmt_spec)) 1768 idx += 4; 1769 return table[idx]; 1770 } 1771 #endif 1772 1773 /* 1774 * This code was included to provide a portable vsnprintf() and snprintf(). 1775 * Some systems may provide their own, but we always use this one for 1776 * consistency. 1777 * 1778 * This code is based on snprintf.c - a portable implementation of snprintf 1779 * by Mark Martinec <[email protected]>, Version 2.2, 2000-10-06. 1780 * Included with permission. It was heavily modified to fit in Vim. 1781 * The original code, including useful comments, can be found here: 1782 * http://www.ijs.si/software/snprintf/ 1783 * 1784 * This snprintf() only supports the following conversion specifiers: 1785 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) 1786 * with flags: '-', '+', ' ', '0' and '#'. 1787 * An asterisk is supported for field width as well as precision. 1788 * 1789 * Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'. 1790 * 1791 * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int) 1792 * are supported. NOTE: for 'll' the argument is varnumber_T or uvarnumber_T. 1793 * 1794 * The locale is not used, the string is used as a byte string. This is only 1795 * relevant for double-byte encodings where the second byte may be '%'. 1796 * 1797 * It is permitted for "str_m" to be zero, and it is permitted to specify NULL 1798 * pointer for resulting string argument if "str_m" is zero (as per ISO C99). 1799 * 1800 * The return value is the number of characters which would be generated 1801 * for the given input, excluding the trailing NUL. If this value 1802 * is greater or equal to "str_m", not all characters from the result 1803 * have been stored in str, output bytes beyond the ("str_m"-1) -th character 1804 * are discarded. If "str_m" is greater than zero it is guaranteed 1805 * the resulting string will be NUL-terminated. 1806 */ 1807 1808 /* 1809 * When va_list is not supported we only define vim_snprintf(). 1810 * 1811 * vim_vsnprintf_typval() can be invoked with either "va_list" or a list of 1812 * "typval_T". When the latter is not used it must be NULL. 1813 */ 1814 1815 // When generating prototypes all of this is skipped, cproto doesn't 1816 // understand this. 1817 #ifndef PROTO 1818 1819 // Like vim_vsnprintf() but append to the string. 1820 int 1821 vim_snprintf_add(char *str, size_t str_m, const char *fmt, ...) 1822 { 1823 va_list ap; 1824 int str_l; 1825 size_t len = STRLEN(str); 1826 size_t space; 1827 1828 if (str_m <= len) 1829 space = 0; 1830 else 1831 space = str_m - len; 1832 va_start(ap, fmt); 1833 str_l = vim_vsnprintf(str + len, space, fmt, ap); 1834 va_end(ap); 1835 return str_l; 1836 } 1837 1838 int 1839 vim_snprintf(char *str, size_t str_m, const char *fmt, ...) 1840 { 1841 va_list ap; 1842 int str_l; 1843 1844 va_start(ap, fmt); 1845 str_l = vim_vsnprintf(str, str_m, fmt, ap); 1846 va_end(ap); 1847 return str_l; 1848 } 1849 1850 int 1851 vim_vsnprintf( 1852 char *str, 1853 size_t str_m, 1854 const char *fmt, 1855 va_list ap) 1856 { 1857 return vim_vsnprintf_typval(str, str_m, fmt, ap, NULL); 1858 } 1859 1860 int 1861 vim_vsnprintf_typval( 1862 char *str, 1863 size_t str_m, 1864 const char *fmt, 1865 va_list ap, 1866 typval_T *tvs) 1867 { 1868 size_t str_l = 0; 1869 const char *p = fmt; 1870 int arg_idx = 1; 1871 1872 if (p == NULL) 1873 p = ""; 1874 while (*p != NUL) 1875 { 1876 if (*p != '%') 1877 { 1878 char *q = strchr(p + 1, '%'); 1879 size_t n = (q == NULL) ? STRLEN(p) : (size_t)(q - p); 1880 1881 // Copy up to the next '%' or NUL without any changes. 1882 if (str_l < str_m) 1883 { 1884 size_t avail = str_m - str_l; 1885 1886 mch_memmove(str + str_l, p, n > avail ? avail : n); 1887 } 1888 p += n; 1889 str_l += n; 1890 } 1891 else 1892 { 1893 size_t min_field_width = 0, precision = 0; 1894 int zero_padding = 0, precision_specified = 0, justify_left = 0; 1895 int alternate_form = 0, force_sign = 0; 1896 1897 // If both the ' ' and '+' flags appear, the ' ' flag should be 1898 // ignored. 1899 int space_for_positive = 1; 1900 1901 // allowed values: \0, h, l, L 1902 char length_modifier = '\0'; 1903 1904 // temporary buffer for simple numeric->string conversion 1905 # if defined(FEAT_FLOAT) 1906 # define TMP_LEN 350 // On my system 1e308 is the biggest number possible. 1907 // That sounds reasonable to use as the maximum 1908 // printable. 1909 # else 1910 # define TMP_LEN 66 1911 # endif 1912 char tmp[TMP_LEN]; 1913 1914 // string address in case of string argument 1915 const char *str_arg = NULL; 1916 1917 // natural field width of arg without padding and sign 1918 size_t str_arg_l; 1919 1920 // unsigned char argument value - only defined for c conversion. 1921 // N.B. standard explicitly states the char argument for the c 1922 // conversion is unsigned 1923 unsigned char uchar_arg; 1924 1925 // number of zeros to be inserted for numeric conversions as 1926 // required by the precision or minimal field width 1927 size_t number_of_zeros_to_pad = 0; 1928 1929 // index into tmp where zero padding is to be inserted 1930 size_t zero_padding_insertion_ind = 0; 1931 1932 // current conversion specifier character 1933 char fmt_spec = '\0'; 1934 1935 // buffer for 's' and 'S' specs 1936 char_u *tofree = NULL; 1937 1938 1939 p++; // skip '%' 1940 1941 // parse flags 1942 while (*p == '0' || *p == '-' || *p == '+' || *p == ' ' 1943 || *p == '#' || *p == '\'') 1944 { 1945 switch (*p) 1946 { 1947 case '0': zero_padding = 1; break; 1948 case '-': justify_left = 1; break; 1949 case '+': force_sign = 1; space_for_positive = 0; break; 1950 case ' ': force_sign = 1; 1951 // If both the ' ' and '+' flags appear, the ' ' 1952 // flag should be ignored 1953 break; 1954 case '#': alternate_form = 1; break; 1955 case '\'': break; 1956 } 1957 p++; 1958 } 1959 // If the '0' and '-' flags both appear, the '0' flag should be 1960 // ignored. 1961 1962 // parse field width 1963 if (*p == '*') 1964 { 1965 int j; 1966 1967 p++; 1968 j = 1969 # if defined(FEAT_EVAL) 1970 tvs != NULL ? tv_nr(tvs, &arg_idx) : 1971 # endif 1972 va_arg(ap, int); 1973 if (j >= 0) 1974 min_field_width = j; 1975 else 1976 { 1977 min_field_width = -j; 1978 justify_left = 1; 1979 } 1980 } 1981 else if (VIM_ISDIGIT((int)(*p))) 1982 { 1983 // size_t could be wider than unsigned int; make sure we treat 1984 // argument like common implementations do 1985 unsigned int uj = *p++ - '0'; 1986 1987 while (VIM_ISDIGIT((int)(*p))) 1988 uj = 10 * uj + (unsigned int)(*p++ - '0'); 1989 min_field_width = uj; 1990 } 1991 1992 // parse precision 1993 if (*p == '.') 1994 { 1995 p++; 1996 precision_specified = 1; 1997 if (*p == '*') 1998 { 1999 int j; 2000 2001 j = 2002 # if defined(FEAT_EVAL) 2003 tvs != NULL ? tv_nr(tvs, &arg_idx) : 2004 # endif 2005 va_arg(ap, int); 2006 p++; 2007 if (j >= 0) 2008 precision = j; 2009 else 2010 { 2011 precision_specified = 0; 2012 precision = 0; 2013 } 2014 } 2015 else if (VIM_ISDIGIT((int)(*p))) 2016 { 2017 // size_t could be wider than unsigned int; make sure we 2018 // treat argument like common implementations do 2019 unsigned int uj = *p++ - '0'; 2020 2021 while (VIM_ISDIGIT((int)(*p))) 2022 uj = 10 * uj + (unsigned int)(*p++ - '0'); 2023 precision = uj; 2024 } 2025 } 2026 2027 // parse 'h', 'l' and 'll' length modifiers 2028 if (*p == 'h' || *p == 'l') 2029 { 2030 length_modifier = *p; 2031 p++; 2032 if (length_modifier == 'l' && *p == 'l') 2033 { 2034 // double l = __int64 / varnumber_T 2035 length_modifier = 'L'; 2036 p++; 2037 } 2038 } 2039 fmt_spec = *p; 2040 2041 // common synonyms: 2042 switch (fmt_spec) 2043 { 2044 case 'i': fmt_spec = 'd'; break; 2045 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; 2046 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; 2047 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; 2048 default: break; 2049 } 2050 2051 # if defined(FEAT_EVAL) 2052 switch (fmt_spec) 2053 { 2054 case 'd': case 'u': case 'o': case 'x': case 'X': 2055 if (tvs != NULL && length_modifier == '\0') 2056 length_modifier = 'L'; 2057 } 2058 # endif 2059 2060 // get parameter value, do initial processing 2061 switch (fmt_spec) 2062 { 2063 // '%' and 'c' behave similar to 's' regarding flags and field 2064 // widths 2065 case '%': 2066 case 'c': 2067 case 's': 2068 case 'S': 2069 str_arg_l = 1; 2070 switch (fmt_spec) 2071 { 2072 case '%': 2073 str_arg = p; 2074 break; 2075 2076 case 'c': 2077 { 2078 int j; 2079 2080 j = 2081 # if defined(FEAT_EVAL) 2082 tvs != NULL ? tv_nr(tvs, &arg_idx) : 2083 # endif 2084 va_arg(ap, int); 2085 // standard demands unsigned char 2086 uchar_arg = (unsigned char)j; 2087 str_arg = (char *)&uchar_arg; 2088 break; 2089 } 2090 2091 case 's': 2092 case 'S': 2093 str_arg = 2094 # if defined(FEAT_EVAL) 2095 tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) : 2096 # endif 2097 va_arg(ap, char *); 2098 if (str_arg == NULL) 2099 { 2100 str_arg = "[NULL]"; 2101 str_arg_l = 6; 2102 } 2103 // make sure not to address string beyond the specified 2104 // precision !!! 2105 else if (!precision_specified) 2106 str_arg_l = strlen(str_arg); 2107 // truncate string if necessary as requested by precision 2108 else if (precision == 0) 2109 str_arg_l = 0; 2110 else 2111 { 2112 // Don't put the #if inside memchr(), it can be a 2113 // macro. 2114 // memchr on HP does not like n > 2^31 !!! 2115 char *q = memchr(str_arg, '\0', 2116 precision <= (size_t)0x7fffffffL ? precision 2117 : (size_t)0x7fffffffL); 2118 str_arg_l = (q == NULL) ? precision 2119 : (size_t)(q - str_arg); 2120 } 2121 if (fmt_spec == 'S') 2122 { 2123 if (min_field_width != 0) 2124 min_field_width += STRLEN(str_arg) 2125 - mb_string2cells((char_u *)str_arg, -1); 2126 if (precision) 2127 { 2128 char_u *p1; 2129 size_t i = 0; 2130 2131 for (p1 = (char_u *)str_arg; *p1; 2132 p1 += mb_ptr2len(p1)) 2133 { 2134 i += (size_t)mb_ptr2cells(p1); 2135 if (i > precision) 2136 break; 2137 } 2138 str_arg_l = precision = p1 - (char_u *)str_arg; 2139 } 2140 } 2141 break; 2142 2143 default: 2144 break; 2145 } 2146 break; 2147 2148 case 'd': case 'u': 2149 case 'b': case 'B': 2150 case 'o': 2151 case 'x': case 'X': 2152 case 'p': 2153 { 2154 // NOTE: the u, b, o, x, X and p conversion specifiers 2155 // imply the value is unsigned; d implies a signed 2156 // value 2157 2158 // 0 if numeric argument is zero (or if pointer is 2159 // NULL for 'p'), +1 if greater than zero (or nonzero 2160 // for unsigned arguments), -1 if negative (unsigned 2161 // argument is never negative) 2162 int arg_sign = 0; 2163 2164 // only set for length modifier h, or for no length 2165 // modifiers 2166 int int_arg = 0; 2167 unsigned int uint_arg = 0; 2168 2169 // only set for length modifier l 2170 long int long_arg = 0; 2171 unsigned long int ulong_arg = 0; 2172 2173 // only set for length modifier ll 2174 varnumber_T llong_arg = 0; 2175 uvarnumber_T ullong_arg = 0; 2176 2177 // only set for b conversion 2178 uvarnumber_T bin_arg = 0; 2179 2180 // pointer argument value -only defined for p 2181 // conversion 2182 void *ptr_arg = NULL; 2183 2184 if (fmt_spec == 'p') 2185 { 2186 length_modifier = '\0'; 2187 ptr_arg = 2188 # if defined(FEAT_EVAL) 2189 tvs != NULL ? (void *)tv_str(tvs, &arg_idx, 2190 NULL) : 2191 # endif 2192 va_arg(ap, void *); 2193 if (ptr_arg != NULL) 2194 arg_sign = 1; 2195 } 2196 else if (fmt_spec == 'b' || fmt_spec == 'B') 2197 { 2198 bin_arg = 2199 # if defined(FEAT_EVAL) 2200 tvs != NULL ? 2201 (uvarnumber_T)tv_nr(tvs, &arg_idx) : 2202 # endif 2203 va_arg(ap, uvarnumber_T); 2204 if (bin_arg != 0) 2205 arg_sign = 1; 2206 } 2207 else if (fmt_spec == 'd') 2208 { 2209 // signed 2210 switch (length_modifier) 2211 { 2212 case '\0': 2213 case 'h': 2214 // char and short arguments are passed as int. 2215 int_arg = 2216 # if defined(FEAT_EVAL) 2217 tvs != NULL ? tv_nr(tvs, &arg_idx) : 2218 # endif 2219 va_arg(ap, int); 2220 if (int_arg > 0) 2221 arg_sign = 1; 2222 else if (int_arg < 0) 2223 arg_sign = -1; 2224 break; 2225 case 'l': 2226 long_arg = 2227 # if defined(FEAT_EVAL) 2228 tvs != NULL ? tv_nr(tvs, &arg_idx) : 2229 # endif 2230 va_arg(ap, long int); 2231 if (long_arg > 0) 2232 arg_sign = 1; 2233 else if (long_arg < 0) 2234 arg_sign = -1; 2235 break; 2236 case 'L': 2237 llong_arg = 2238 # if defined(FEAT_EVAL) 2239 tvs != NULL ? tv_nr(tvs, &arg_idx) : 2240 # endif 2241 va_arg(ap, varnumber_T); 2242 if (llong_arg > 0) 2243 arg_sign = 1; 2244 else if (llong_arg < 0) 2245 arg_sign = -1; 2246 break; 2247 } 2248 } 2249 else 2250 { 2251 // unsigned 2252 switch (length_modifier) 2253 { 2254 case '\0': 2255 case 'h': 2256 uint_arg = 2257 # if defined(FEAT_EVAL) 2258 tvs != NULL ? (unsigned) 2259 tv_nr(tvs, &arg_idx) : 2260 # endif 2261 va_arg(ap, unsigned int); 2262 if (uint_arg != 0) 2263 arg_sign = 1; 2264 break; 2265 case 'l': 2266 ulong_arg = 2267 # if defined(FEAT_EVAL) 2268 tvs != NULL ? (unsigned long) 2269 tv_nr(tvs, &arg_idx) : 2270 # endif 2271 va_arg(ap, unsigned long int); 2272 if (ulong_arg != 0) 2273 arg_sign = 1; 2274 break; 2275 case 'L': 2276 ullong_arg = 2277 # if defined(FEAT_EVAL) 2278 tvs != NULL ? (uvarnumber_T) 2279 tv_nr(tvs, &arg_idx) : 2280 # endif 2281 va_arg(ap, uvarnumber_T); 2282 if (ullong_arg != 0) 2283 arg_sign = 1; 2284 break; 2285 } 2286 } 2287 2288 str_arg = tmp; 2289 str_arg_l = 0; 2290 2291 // NOTE: 2292 // For d, i, u, o, x, and X conversions, if precision is 2293 // specified, the '0' flag should be ignored. This is so 2294 // with Solaris 2.6, Digital UNIX 4.0, HPUX 10, Linux, 2295 // FreeBSD, NetBSD; but not with Perl. 2296 if (precision_specified) 2297 zero_padding = 0; 2298 if (fmt_spec == 'd') 2299 { 2300 if (force_sign && arg_sign >= 0) 2301 tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; 2302 // leave negative numbers for sprintf to handle, to 2303 // avoid handling tricky cases like (short int)-32768 2304 } 2305 else if (alternate_form) 2306 { 2307 if (arg_sign != 0 2308 && (fmt_spec == 'b' || fmt_spec == 'B' 2309 || fmt_spec == 'x' || fmt_spec == 'X') ) 2310 { 2311 tmp[str_arg_l++] = '0'; 2312 tmp[str_arg_l++] = fmt_spec; 2313 } 2314 // alternate form should have no effect for p 2315 // conversion, but ... 2316 } 2317 2318 zero_padding_insertion_ind = str_arg_l; 2319 if (!precision_specified) 2320 precision = 1; // default precision is 1 2321 if (precision == 0 && arg_sign == 0) 2322 { 2323 // When zero value is formatted with an explicit 2324 // precision 0, the resulting formatted string is 2325 // empty (d, i, u, b, B, o, x, X, p). 2326 } 2327 else 2328 { 2329 char f[6]; 2330 int f_l = 0; 2331 2332 // construct a simple format string for sprintf 2333 f[f_l++] = '%'; 2334 if (!length_modifier) 2335 ; 2336 else if (length_modifier == 'L') 2337 { 2338 # ifdef MSWIN 2339 f[f_l++] = 'I'; 2340 f[f_l++] = '6'; 2341 f[f_l++] = '4'; 2342 # else 2343 f[f_l++] = 'l'; 2344 f[f_l++] = 'l'; 2345 # endif 2346 } 2347 else 2348 f[f_l++] = length_modifier; 2349 f[f_l++] = fmt_spec; 2350 f[f_l++] = '\0'; 2351 2352 if (fmt_spec == 'p') 2353 str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); 2354 else if (fmt_spec == 'b' || fmt_spec == 'B') 2355 { 2356 char b[8 * sizeof(uvarnumber_T)]; 2357 size_t b_l = 0; 2358 uvarnumber_T bn = bin_arg; 2359 2360 do 2361 { 2362 b[sizeof(b) - ++b_l] = '0' + (bn & 0x1); 2363 bn >>= 1; 2364 } 2365 while (bn != 0); 2366 2367 memcpy(tmp + str_arg_l, b + sizeof(b) - b_l, b_l); 2368 str_arg_l += b_l; 2369 } 2370 else if (fmt_spec == 'd') 2371 { 2372 // signed 2373 switch (length_modifier) 2374 { 2375 case '\0': str_arg_l += sprintf( 2376 tmp + str_arg_l, f, 2377 int_arg); 2378 break; 2379 case 'h': str_arg_l += sprintf( 2380 tmp + str_arg_l, f, 2381 (short)int_arg); 2382 break; 2383 case 'l': str_arg_l += sprintf( 2384 tmp + str_arg_l, f, long_arg); 2385 break; 2386 case 'L': str_arg_l += sprintf( 2387 tmp + str_arg_l, f, llong_arg); 2388 break; 2389 } 2390 } 2391 else 2392 { 2393 // unsigned 2394 switch (length_modifier) 2395 { 2396 case '\0': str_arg_l += sprintf( 2397 tmp + str_arg_l, f, 2398 uint_arg); 2399 break; 2400 case 'h': str_arg_l += sprintf( 2401 tmp + str_arg_l, f, 2402 (unsigned short)uint_arg); 2403 break; 2404 case 'l': str_arg_l += sprintf( 2405 tmp + str_arg_l, f, ulong_arg); 2406 break; 2407 case 'L': str_arg_l += sprintf( 2408 tmp + str_arg_l, f, ullong_arg); 2409 break; 2410 } 2411 } 2412 2413 // include the optional minus sign and possible 2414 // "0x" in the region before the zero padding 2415 // insertion point 2416 if (zero_padding_insertion_ind < str_arg_l 2417 && tmp[zero_padding_insertion_ind] == '-') 2418 zero_padding_insertion_ind++; 2419 if (zero_padding_insertion_ind + 1 < str_arg_l 2420 && tmp[zero_padding_insertion_ind] == '0' 2421 && (tmp[zero_padding_insertion_ind + 1] == 'x' 2422 || tmp[zero_padding_insertion_ind + 1] == 'X')) 2423 zero_padding_insertion_ind += 2; 2424 } 2425 2426 { 2427 size_t num_of_digits = str_arg_l 2428 - zero_padding_insertion_ind; 2429 2430 if (alternate_form && fmt_spec == 'o' 2431 // unless zero is already the first 2432 // character 2433 && !(zero_padding_insertion_ind < str_arg_l 2434 && tmp[zero_padding_insertion_ind] == '0')) 2435 { 2436 // assure leading zero for alternate-form 2437 // octal numbers 2438 if (!precision_specified 2439 || precision < num_of_digits + 1) 2440 { 2441 // precision is increased to force the 2442 // first character to be zero, except if a 2443 // zero value is formatted with an 2444 // explicit precision of zero 2445 precision = num_of_digits + 1; 2446 } 2447 } 2448 // zero padding to specified precision? 2449 if (num_of_digits < precision) 2450 number_of_zeros_to_pad = precision - num_of_digits; 2451 } 2452 // zero padding to specified minimal field width? 2453 if (!justify_left && zero_padding) 2454 { 2455 int n = (int)(min_field_width - (str_arg_l 2456 + number_of_zeros_to_pad)); 2457 if (n > 0) 2458 number_of_zeros_to_pad += n; 2459 } 2460 break; 2461 } 2462 2463 # ifdef FEAT_FLOAT 2464 case 'f': 2465 case 'F': 2466 case 'e': 2467 case 'E': 2468 case 'g': 2469 case 'G': 2470 { 2471 // Floating point. 2472 double f; 2473 double abs_f; 2474 char format[40]; 2475 int l; 2476 int remove_trailing_zeroes = FALSE; 2477 2478 f = 2479 # if defined(FEAT_EVAL) 2480 tvs != NULL ? tv_float(tvs, &arg_idx) : 2481 # endif 2482 va_arg(ap, double); 2483 abs_f = f < 0 ? -f : f; 2484 2485 if (fmt_spec == 'g' || fmt_spec == 'G') 2486 { 2487 // Would be nice to use %g directly, but it prints 2488 // "1.0" as "1", we don't want that. 2489 if ((abs_f >= 0.001 && abs_f < 10000000.0) 2490 || abs_f == 0.0) 2491 fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; 2492 else 2493 fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; 2494 remove_trailing_zeroes = TRUE; 2495 } 2496 2497 if ((fmt_spec == 'f' || fmt_spec == 'F') && 2498 # ifdef VAX 2499 abs_f > 1.0e38 2500 # else 2501 abs_f > 1.0e307 2502 # endif 2503 ) 2504 { 2505 // Avoid a buffer overflow 2506 STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, 2507 force_sign, space_for_positive)); 2508 str_arg_l = STRLEN(tmp); 2509 zero_padding = 0; 2510 } 2511 else 2512 { 2513 if (isnan(f)) 2514 { 2515 // Not a number: nan or NAN 2516 STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" 2517 : "nan"); 2518 str_arg_l = 3; 2519 zero_padding = 0; 2520 } 2521 else if (isinf(f)) 2522 { 2523 STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, 2524 force_sign, space_for_positive)); 2525 str_arg_l = STRLEN(tmp); 2526 zero_padding = 0; 2527 } 2528 else 2529 { 2530 // Regular float number 2531 format[0] = '%'; 2532 l = 1; 2533 if (force_sign) 2534 format[l++] = space_for_positive ? ' ' : '+'; 2535 if (precision_specified) 2536 { 2537 size_t max_prec = TMP_LEN - 10; 2538 2539 // Make sure we don't get more digits than we 2540 // have room for. 2541 if ((fmt_spec == 'f' || fmt_spec == 'F') 2542 && abs_f > 1.0) 2543 max_prec -= (size_t)log10(abs_f); 2544 if (precision > max_prec) 2545 precision = max_prec; 2546 l += sprintf(format + l, ".%d", (int)precision); 2547 } 2548 format[l] = fmt_spec == 'F' ? 'f' : fmt_spec; 2549 format[l + 1] = NUL; 2550 2551 str_arg_l = sprintf(tmp, format, f); 2552 } 2553 2554 if (remove_trailing_zeroes) 2555 { 2556 int i; 2557 char *tp; 2558 2559 // Using %g or %G: remove superfluous zeroes. 2560 if (fmt_spec == 'f' || fmt_spec == 'F') 2561 tp = tmp + str_arg_l - 1; 2562 else 2563 { 2564 tp = (char *)vim_strchr((char_u *)tmp, 2565 fmt_spec == 'e' ? 'e' : 'E'); 2566 if (tp != NULL) 2567 { 2568 // Remove superfluous '+' and leading 2569 // zeroes from the exponent. 2570 if (tp[1] == '+') 2571 { 2572 // Change "1.0e+07" to "1.0e07" 2573 STRMOVE(tp + 1, tp + 2); 2574 --str_arg_l; 2575 } 2576 i = (tp[1] == '-') ? 2 : 1; 2577 while (tp[i] == '0') 2578 { 2579 // Change "1.0e07" to "1.0e7" 2580 STRMOVE(tp + i, tp + i + 1); 2581 --str_arg_l; 2582 } 2583 --tp; 2584 } 2585 } 2586 2587 if (tp != NULL && !precision_specified) 2588 // Remove trailing zeroes, but keep the one 2589 // just after a dot. 2590 while (tp > tmp + 2 && *tp == '0' 2591 && tp[-1] != '.') 2592 { 2593 STRMOVE(tp, tp + 1); 2594 --tp; 2595 --str_arg_l; 2596 } 2597 } 2598 else 2599 { 2600 char *tp; 2601 2602 // Be consistent: some printf("%e") use 1.0e+12 2603 // and some 1.0e+012. Remove one zero in the last 2604 // case. 2605 tp = (char *)vim_strchr((char_u *)tmp, 2606 fmt_spec == 'e' ? 'e' : 'E'); 2607 if (tp != NULL && (tp[1] == '+' || tp[1] == '-') 2608 && tp[2] == '0' 2609 && vim_isdigit(tp[3]) 2610 && vim_isdigit(tp[4])) 2611 { 2612 STRMOVE(tp + 2, tp + 3); 2613 --str_arg_l; 2614 } 2615 } 2616 } 2617 if (zero_padding && min_field_width > str_arg_l 2618 && (tmp[0] == '-' || force_sign)) 2619 { 2620 // padding 0's should be inserted after the sign 2621 number_of_zeros_to_pad = min_field_width - str_arg_l; 2622 zero_padding_insertion_ind = 1; 2623 } 2624 str_arg = tmp; 2625 break; 2626 } 2627 # endif 2628 2629 default: 2630 // unrecognized conversion specifier, keep format string 2631 // as-is 2632 zero_padding = 0; // turn zero padding off for non-numeric 2633 // conversion 2634 justify_left = 1; 2635 min_field_width = 0; // reset flags 2636 2637 // discard the unrecognized conversion, just keep * 2638 // the unrecognized conversion character 2639 str_arg = p; 2640 str_arg_l = 0; 2641 if (*p != NUL) 2642 str_arg_l++; // include invalid conversion specifier 2643 // unchanged if not at end-of-string 2644 break; 2645 } 2646 2647 if (*p != NUL) 2648 p++; // step over the just processed conversion specifier 2649 2650 // insert padding to the left as requested by min_field_width; 2651 // this does not include the zero padding in case of numerical 2652 // conversions 2653 if (!justify_left) 2654 { 2655 // left padding with blank or zero 2656 int pn = (int)(min_field_width - (str_arg_l + number_of_zeros_to_pad)); 2657 2658 if (pn > 0) 2659 { 2660 if (str_l < str_m) 2661 { 2662 size_t avail = str_m - str_l; 2663 2664 vim_memset(str + str_l, zero_padding ? '0' : ' ', 2665 (size_t)pn > avail ? avail 2666 : (size_t)pn); 2667 } 2668 str_l += pn; 2669 } 2670 } 2671 2672 // zero padding as requested by the precision or by the minimal 2673 // field width for numeric conversions required? 2674 if (number_of_zeros_to_pad == 0) 2675 { 2676 // will not copy first part of numeric right now, * 2677 // force it to be copied later in its entirety 2678 zero_padding_insertion_ind = 0; 2679 } 2680 else 2681 { 2682 // insert first part of numerics (sign or '0x') before zero 2683 // padding 2684 int zn = (int)zero_padding_insertion_ind; 2685 2686 if (zn > 0) 2687 { 2688 if (str_l < str_m) 2689 { 2690 size_t avail = str_m - str_l; 2691 2692 mch_memmove(str + str_l, str_arg, 2693 (size_t)zn > avail ? avail 2694 : (size_t)zn); 2695 } 2696 str_l += zn; 2697 } 2698 2699 // insert zero padding as requested by the precision or min 2700 // field width 2701 zn = (int)number_of_zeros_to_pad; 2702 if (zn > 0) 2703 { 2704 if (str_l < str_m) 2705 { 2706 size_t avail = str_m - str_l; 2707 2708 vim_memset(str + str_l, '0', 2709 (size_t)zn > avail ? avail 2710 : (size_t)zn); 2711 } 2712 str_l += zn; 2713 } 2714 } 2715 2716 // insert formatted string 2717 // (or as-is conversion specifier for unknown conversions) 2718 { 2719 int sn = (int)(str_arg_l - zero_padding_insertion_ind); 2720 2721 if (sn > 0) 2722 { 2723 if (str_l < str_m) 2724 { 2725 size_t avail = str_m - str_l; 2726 2727 mch_memmove(str + str_l, 2728 str_arg + zero_padding_insertion_ind, 2729 (size_t)sn > avail ? avail : (size_t)sn); 2730 } 2731 str_l += sn; 2732 } 2733 } 2734 2735 // insert right padding 2736 if (justify_left) 2737 { 2738 // right blank padding to the field width 2739 int pn = (int)(min_field_width 2740 - (str_arg_l + number_of_zeros_to_pad)); 2741 2742 if (pn > 0) 2743 { 2744 if (str_l < str_m) 2745 { 2746 size_t avail = str_m - str_l; 2747 2748 vim_memset(str + str_l, ' ', 2749 (size_t)pn > avail ? avail 2750 : (size_t)pn); 2751 } 2752 str_l += pn; 2753 } 2754 } 2755 vim_free(tofree); 2756 } 2757 } 2758 2759 if (str_m > 0) 2760 { 2761 // make sure the string is nul-terminated even at the expense of 2762 // overwriting the last character (shouldn't happen, but just in case) 2763 // 2764 str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; 2765 } 2766 2767 if (tvs != NULL && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) 2768 emsg(_("E767: Too many arguments to printf()")); 2769 2770 // Return the number of characters formatted (excluding trailing nul 2771 // character), that is, the number of characters that would have been 2772 // written to the buffer if it were large enough. 2773 return (int)str_l; 2774 } 2775 2776 #endif // PROTO 2777