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