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