1 /** @file 2 3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 13 **/ 14 15 #include "Edb.h" 16 17 /** 18 19 Convert hex string to uint. 20 21 @param Str - The string 22 23 **/ 24 UINTN 25 EFIAPI 26 Xtoi ( 27 CHAR16 *Str 28 ) 29 { 30 UINTN RetVal; 31 CHAR16 TempChar; 32 UINTN MaxVal; 33 34 ASSERT (Str != NULL); 35 36 MaxVal = (UINTN) -1 >> 4; 37 // 38 // skip preceeding white space 39 // 40 while (*Str != '\0' && *Str == ' ') { 41 Str += 1; 42 } 43 // 44 // skip preceeding zeros 45 // 46 while (*Str != '\0' && *Str == '0') { 47 Str += 1; 48 } 49 // 50 // skip preceeding white space 51 // 52 if (*Str != '\0' && (*Str == 'x' || *Str == 'X')) { 53 Str += 1; 54 } 55 // 56 // convert hex digits 57 // 58 RetVal = 0; 59 TempChar = *(Str++); 60 while (TempChar != '\0') { 61 if (TempChar >= 'a' && TempChar <= 'f') { 62 TempChar -= 'a' - 'A'; 63 } 64 65 if ((TempChar >= '0' && TempChar <= '9') || (TempChar >= 'A' && TempChar <= 'F')) { 66 if (RetVal > MaxVal) { 67 return (UINTN) -1; 68 } 69 70 RetVal = (RetVal << 4) | (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0')); 71 } else { 72 break; 73 } 74 75 TempChar = *(Str++); 76 } 77 78 return RetVal; 79 } 80 81 /** 82 83 Convert hex string to uint. 84 85 @param Str - The string 86 87 **/ 88 UINT64 89 EFIAPI 90 LXtoi ( 91 CHAR16 *Str 92 ) 93 { 94 UINT64 RetVal; 95 CHAR16 TempChar; 96 UINT64 MaxVal; 97 98 ASSERT (Str != NULL); 99 100 MaxVal = RShiftU64 ((UINT64) -1, 4); 101 // 102 // skip preceeding white space 103 // 104 while (*Str != '\0' && *Str == ' ') { 105 Str += 1; 106 } 107 // 108 // skip preceeding zeros 109 // 110 while (*Str != '\0' && *Str == '0') { 111 Str += 1; 112 } 113 // 114 // skip preceeding white space 115 // 116 if (*Str != '\0' && (*Str == 'x' || *Str == 'X')) { 117 Str += 1; 118 } 119 // 120 // convert hex digits 121 // 122 RetVal = 0; 123 TempChar = *(Str++); 124 while (TempChar != '\0') { 125 if (TempChar >= 'a' && TempChar <= 'f') { 126 TempChar -= 'a' - 'A'; 127 } 128 129 if ((TempChar >= '0' && TempChar <= '9') || (TempChar >= 'A' && TempChar <= 'F')) { 130 if (RetVal > MaxVal) { 131 return (UINT64) -1; 132 } 133 134 RetVal = LShiftU64 (RetVal, 4); 135 RetVal = RetVal + (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0')); 136 } else { 137 break; 138 } 139 140 TempChar = *(Str++); 141 } 142 143 return RetVal; 144 } 145 146 /** 147 148 Convert hex string to uint. 149 150 @param Str - The string 151 152 **/ 153 UINTN 154 EFIAPI 155 Atoi ( 156 CHAR16 *Str 157 ) 158 { 159 UINTN RetVal; 160 CHAR16 TempChar; 161 UINTN MaxVal; 162 UINTN ResteVal; 163 164 ASSERT (Str != NULL); 165 166 MaxVal = (UINTN) -1 / 10; 167 ResteVal = (UINTN) -1 % 10; 168 // 169 // skip preceeding white space 170 // 171 while (*Str != '\0' && *Str == ' ') { 172 Str += 1; 173 } 174 // 175 // convert digits 176 // 177 RetVal = 0; 178 TempChar = *(Str++); 179 while (TempChar != '\0') { 180 if (TempChar >= '0' && TempChar <= '9') { 181 if (RetVal > MaxVal || (RetVal == MaxVal && TempChar - '0' > (INTN) ResteVal)) { 182 return (UINTN) -1; 183 } 184 185 RetVal = (RetVal * 10) + TempChar - '0'; 186 } else { 187 break; 188 } 189 190 TempChar = *(Str++); 191 } 192 193 return RetVal; 194 } 195 196 /** 197 198 Convert hex string to uint. 199 200 @param Str - The string 201 202 **/ 203 UINTN 204 EFIAPI 205 AsciiXtoi ( 206 CHAR8 *Str 207 ) 208 { 209 UINTN RetVal; 210 CHAR8 TempChar; 211 UINTN MaxVal; 212 213 ASSERT (Str != NULL); 214 215 MaxVal = (UINTN) -1 >> 4; 216 // 217 // skip preceeding white space 218 // 219 while (*Str != '\0' && *Str == ' ') { 220 Str += 1; 221 } 222 // 223 // skip preceeding zeros 224 // 225 while (*Str != '\0' && *Str == '0') { 226 Str += 1; 227 } 228 // 229 // skip preceeding white space 230 // 231 if (*Str != '\0' && (*Str == 'x' || *Str == 'X')) { 232 Str += 1; 233 } 234 // 235 // convert hex digits 236 // 237 RetVal = 0; 238 TempChar = *(Str++); 239 while (TempChar != '\0') { 240 if (TempChar >= 'a' && TempChar <= 'f') { 241 TempChar -= 'a' - 'A'; 242 } 243 244 if ((TempChar >= '0' && TempChar <= '9') || (TempChar >= 'A' && TempChar <= 'F')) { 245 if (RetVal > MaxVal) { 246 return (UINTN) -1; 247 } 248 249 RetVal = (RetVal << 4) | (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0')); 250 } else { 251 break; 252 } 253 254 TempChar = *(Str++); 255 } 256 257 return RetVal; 258 } 259 260 /** 261 262 Convert hex string to uint. 263 264 @param Str - The string 265 266 **/ 267 UINTN 268 EFIAPI 269 AsciiAtoi ( 270 CHAR8 *Str 271 ) 272 { 273 UINTN RetVal; 274 CHAR8 TempChar; 275 UINTN MaxVal; 276 UINTN ResteVal; 277 278 ASSERT (Str != NULL); 279 280 MaxVal = (UINTN) -1 / 10; 281 ResteVal = (UINTN) -1 % 10; 282 // 283 // skip preceeding white space 284 // 285 while (*Str != '\0' && *Str == ' ') { 286 Str += 1; 287 } 288 // 289 // convert digits 290 // 291 RetVal = 0; 292 TempChar = *(Str++); 293 while (TempChar != '\0') { 294 if (TempChar >= '0' && TempChar <= '9') { 295 if (RetVal > MaxVal || (RetVal == MaxVal && TempChar - '0' > (INTN) ResteVal)) { 296 return (UINTN) -1; 297 } 298 299 RetVal = (RetVal * 10) + TempChar - '0'; 300 } else { 301 break; 302 } 303 304 TempChar = *(Str++); 305 } 306 307 return RetVal; 308 } 309 310 /** 311 312 Convert the character to upper case. 313 314 @param Chr the character to be converted. 315 316 **/ 317 STATIC 318 CHAR16 319 UnicodeToUpper ( 320 IN CHAR16 Chr 321 ) 322 { 323 return (Chr >= L'a' && Chr <= L'z') ? Chr - (L'a' - L'A') : Chr; 324 } 325 326 /** 327 328 Convert the character to upper case. 329 330 @param Chr the character to be converted. 331 332 **/ 333 STATIC 334 CHAR8 335 AsciiToUpper ( 336 IN CHAR8 Chr 337 ) 338 { 339 return (Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr; 340 } 341 342 /** 343 Compare the Unicode and Ascii string pointed by String to the string pointed by String2. 344 345 @param String - Unicode String to process 346 347 @param String2 - Ascii string to process 348 349 @return Return a positive integer if String is lexicall greater than String2; Zero if 350 the two strings are identical; and a negative interger if String is lexically 351 less than String2. 352 353 **/ 354 INTN 355 EFIAPI 356 StrCmpUnicodeAndAscii ( 357 IN CHAR16 *String, 358 IN CHAR8 *String2 359 ) 360 { 361 while (*String != '\0') { 362 if (*String != (CHAR16)*String2) { 363 break; 364 } 365 366 String += 1; 367 String2 += 1; 368 } 369 370 return (*String - (CHAR16)*String2); 371 } 372 373 /** 374 375 Compare the Unicode string pointed by String to the string pointed by String2. 376 377 @param String - Unicode String to process 378 @param String2 - Unicode string to process 379 380 @return Return a positive integer if String is lexically greater than String2; Zero if 381 the two strings are identical; and a negative integer if String is lexically 382 less than String2. 383 384 **/ 385 INTN 386 EFIAPI 387 StriCmp ( 388 IN CHAR16 *String, 389 IN CHAR16 *String2 390 ) 391 { 392 while ((*String != L'\0') && 393 (UnicodeToUpper (*String) == UnicodeToUpper (*String2))) { 394 String++; 395 String2++; 396 } 397 398 return UnicodeToUpper (*String) - UnicodeToUpper (*String2); 399 } 400 401 /** 402 403 Compare the Unicode and Ascii string pointed by String to the string pointed by String2. 404 405 @param String - Unicode String to process 406 @param String2 - Ascii string to process 407 408 @return Return a positive integer if String is lexically greater than String2; Zero if 409 the two strings are identical; and a negative integer if String is lexically 410 less than String2. 411 412 **/ 413 INTN 414 EFIAPI 415 StriCmpUnicodeAndAscii ( 416 IN CHAR16 *String, 417 IN CHAR8 *String2 418 ) 419 { 420 while ((*String != L'\0') && 421 (UnicodeToUpper (*String) == (CHAR16)AsciiToUpper (*String2))) { 422 String++; 423 String2++; 424 } 425 426 return UnicodeToUpper (*String) - (CHAR16)AsciiToUpper (*String2); 427 } 428 429 /** 430 431 Verify if the string is end with the sub string. 432 433 @param Str - The string where to search the sub string 434 @param SubStr - The substring. 435 436 **/ 437 BOOLEAN 438 EFIAPI 439 StrEndWith ( 440 IN CHAR16 *Str, 441 IN CHAR16 *SubStr 442 ) 443 { 444 CHAR16 *Temp; 445 446 if ((Str == NULL) || (SubStr == NULL) || (StrLen(Str) < StrLen(SubStr))) { 447 return FALSE; 448 } 449 450 Temp = Str + StrLen(Str) - StrLen(SubStr); 451 452 // 453 // Compare 454 // 455 if (StriCmp (Temp, SubStr) == 0) { 456 return TRUE; 457 } else { 458 return FALSE; 459 } 460 } 461 462 /** 463 Duplicate a string. 464 465 @param Src The string to be duplicated. 466 467 **/ 468 CHAR16 * 469 EFIAPI 470 StrDuplicate ( 471 IN CHAR16 *Src 472 ) 473 { 474 CHAR16 *Dest; 475 UINTN Size; 476 477 Size = (StrLen(Src) + 1) * sizeof(CHAR16); 478 Dest = AllocateZeroPool (Size); 479 if (Dest != NULL) { 480 CopyMem (Dest, Src, Size); 481 } 482 return Dest; 483 } 484 485 486 CHAR16 *mLineBuffer = NULL; 487 CHAR16 *mFieldBuffer = NULL; 488 489 /** 490 491 Find the first substring. 492 493 @param String Point to the string where to find the substring. 494 @param CharSet Point to the string to be found. 495 496 **/ 497 UINTN 498 EFIAPI 499 StrSpn ( 500 IN CHAR16 *String, 501 IN CHAR16 *CharSet 502 ) 503 { 504 UINTN Count; 505 CHAR16 *Str1; 506 CHAR16 *Str2; 507 508 Count = 0; 509 510 for (Str1 = String; *Str1 != L'\0'; Str1 ++) { 511 for (Str2 = CharSet; *Str2 != L'\0'; Str2 ++) { 512 if (*Str1 == *Str2) { 513 break; 514 } 515 } 516 517 if (*Str2 == L'\0') { 518 return Count; 519 } 520 521 Count ++; 522 } 523 524 return Count; 525 } 526 527 /** 528 529 Searches a string for the first occurrence of a character contained in a 530 specified buffer. 531 532 @param String Point to the string where to find the substring. 533 @param CharSet Point to the string to be found. 534 535 **/ 536 CHAR16 * 537 EFIAPI 538 StrBrk ( 539 IN CHAR16 *String, 540 IN CHAR16 *CharSet 541 ) 542 { 543 CHAR16 *Str1; 544 CHAR16 *Str2; 545 546 for (Str1 = String; *Str1 != L'\0'; Str1 ++) { 547 for (Str2 = CharSet; *Str2 != L'\0'; Str2 ++) { 548 if (*Str1 == *Str2) { 549 return (CHAR16 *) Str1; 550 } 551 } 552 } 553 554 return NULL; 555 } 556 557 /** 558 559 Find the next token after one or more specified characters. 560 561 @param String Point to the string where to find the substring. 562 @param CharSet Point to the string to be found. 563 564 **/ 565 CHAR16 * 566 EFIAPI 567 StrTokenLine ( 568 IN CHAR16 *String OPTIONAL, 569 IN CHAR16 *CharSet 570 ) 571 { 572 CHAR16 *Begin; 573 CHAR16 *End; 574 575 Begin = (String == NULL) ? mLineBuffer : String; 576 if (Begin == NULL) { 577 return NULL; 578 } 579 580 Begin += StrSpn (Begin, CharSet); 581 if (*Begin == L'\0') { 582 mLineBuffer = NULL; 583 return NULL; 584 } 585 586 End = StrBrk (Begin, CharSet); 587 if ((End != NULL) && (*End != L'\0')) { 588 *End = L'\0'; 589 End ++; 590 } 591 592 mLineBuffer = End; 593 return Begin; 594 } 595 596 /** 597 598 Find the next token after one specificed characters. 599 600 @param String Point to the string where to find the substring. 601 @param CharSet Point to the string to be found. 602 603 **/ 604 CHAR16 * 605 EFIAPI 606 StrTokenField ( 607 IN CHAR16 *String OPTIONAL, 608 IN CHAR16 *CharSet 609 ) 610 { 611 CHAR16 *Begin; 612 CHAR16 *End; 613 614 615 Begin = (String == NULL) ? mFieldBuffer : String; 616 if (Begin == NULL) { 617 return NULL; 618 } 619 620 if (*Begin == L'\0') { 621 mFieldBuffer = NULL; 622 return NULL; 623 } 624 625 End = StrBrk (Begin, CharSet); 626 if ((End != NULL) && (*End != L'\0')) { 627 *End = L'\0'; 628 End ++; 629 } 630 631 mFieldBuffer = End; 632 return Begin; 633 } 634 635 /** 636 637 Find the next token after one or more specified characters. 638 639 @param String Point to the string where to find the substring. 640 @param CharSet Point to the string to be found. 641 642 **/ 643 CHAR16 * 644 EFIAPI 645 StrGetNewTokenLine ( 646 IN CHAR16 *String, 647 IN CHAR16 *CharSet 648 ) 649 { 650 return StrTokenLine (String, CharSet); 651 } 652 653 /** 654 655 Find the next token after one or more specified characters. 656 657 @param CharSet Point to the string to be found. 658 659 **/ 660 CHAR16 * 661 EFIAPI 662 StrGetNextTokenLine ( 663 IN CHAR16 *CharSet 664 ) 665 { 666 return StrTokenLine (NULL, CharSet); 667 } 668 669 /** 670 671 Find the next token after one specificed characters. 672 673 @param String Point to the string where to find the substring. 674 @param CharSet Point to the string to be found. 675 676 **/ 677 CHAR16 * 678 EFIAPI 679 StrGetNewTokenField ( 680 IN CHAR16 *String, 681 IN CHAR16 *CharSet 682 ) 683 { 684 return StrTokenField (String, CharSet); 685 } 686 687 /** 688 689 Find the next token after one specificed characters. 690 691 @param CharSet Point to the string to be found. 692 693 **/ 694 CHAR16 * 695 EFIAPI 696 StrGetNextTokenField ( 697 IN CHAR16 *CharSet 698 ) 699 { 700 return StrTokenField (NULL, CharSet); 701 } 702 703 /** 704 705 Patch a character to the end of a string. 706 707 @param Buffer The string to be patched. 708 @param Patch The patch character. 709 710 **/ 711 VOID 712 EFIAPI 713 PatchForStrTokenAfter ( 714 IN CHAR16 *Buffer, 715 IN CHAR16 Patch 716 ) 717 { 718 CHAR16 *Str; 719 720 if (Buffer == NULL) { 721 return ; 722 } 723 724 Str = Buffer; 725 while (*Str != 0) { 726 Str ++; 727 } 728 *Str = Patch; 729 730 while (*(Str ++) != '\0') { 731 if (*Str == 0) { 732 *Str = Patch; 733 } else { 734 break; 735 } 736 } 737 738 return ; 739 } 740 741 /** 742 Patch a character at the beginning of a string. 743 744 @param Buffer The string to be patched. 745 @param Patch The patch character. 746 747 **/ 748 VOID 749 EFIAPI 750 PatchForStrTokenBefore ( 751 IN CHAR16 *Buffer, 752 IN CHAR16 Patch 753 ) 754 { 755 CHAR16 *Str; 756 757 if (Buffer == NULL) { 758 return ; 759 } 760 761 Str = Buffer; 762 while (*(Str --) != '\0') { 763 if ((*Str == 0) || (*Str == Patch)) { 764 *Str = Patch; 765 } else { 766 break; 767 } 768 } 769 770 return ; 771 } 772 773 CHAR8 *mAsciiLineBuffer = NULL; 774 CHAR8 *mAsciiFieldBuffer = NULL; 775 776 /** 777 778 Find the first substring. 779 780 @param String Point to the string where to find the substring. 781 @param CharSet Point to the string to be found. 782 783 **/ 784 UINTN 785 EFIAPI 786 AsciiStrSpn ( 787 IN CHAR8 *String, 788 IN CHAR8 *CharSet 789 ) 790 { 791 UINTN Count; 792 CHAR8 *Str1; 793 CHAR8 *Str2; 794 795 Count = 0; 796 797 for (Str1 = String; *Str1 != '\0'; Str1 ++) { 798 for (Str2 = CharSet; *Str2 != '\0'; Str2 ++) { 799 if (*Str1 == *Str2) { 800 break; 801 } 802 } 803 804 if (*Str2 == '\0') { 805 return Count; 806 } 807 808 Count ++; 809 } 810 811 return Count; 812 } 813 814 /** 815 Searches a string for the first occurrence of a character contained in a 816 specified buffer. 817 818 @param String Point to the string where to find the substring. 819 @param CharSet Point to the string to be found. 820 821 **/ 822 CHAR8 * 823 EFIAPI 824 AsciiStrBrk ( 825 IN CHAR8 *String, 826 IN CHAR8 *CharSet 827 ) 828 { 829 CHAR8 *Str1; 830 CHAR8 *Str2; 831 832 for (Str1 = String; *Str1 != '\0'; Str1 ++) { 833 for (Str2 = CharSet; *Str2 != '\0'; Str2 ++) { 834 if (*Str1 == *Str2) { 835 return (CHAR8 *) Str1; 836 } 837 } 838 } 839 840 return NULL; 841 } 842 843 /** 844 845 Find the next token after one or more specified characters. 846 847 @param String Point to the string where to find the substring. 848 @param CharSet Point to the string to be found. 849 850 **/ 851 CHAR8 * 852 EFIAPI 853 AsciiStrTokenLine ( 854 IN CHAR8 *String OPTIONAL, 855 IN CHAR8 *CharSet 856 ) 857 { 858 CHAR8 *Begin; 859 CHAR8 *End; 860 861 Begin = (String == NULL) ? mAsciiLineBuffer : String; 862 if (Begin == NULL) { 863 return NULL; 864 } 865 866 Begin += AsciiStrSpn (Begin, CharSet); 867 if (*Begin == '\0') { 868 mAsciiLineBuffer = NULL; 869 return NULL; 870 } 871 872 End = AsciiStrBrk (Begin, CharSet); 873 if ((End != NULL) && (*End != '\0')) { 874 *End = '\0'; 875 End ++; 876 } 877 878 mAsciiLineBuffer = End; 879 return Begin; 880 } 881 882 /** 883 884 Find the next token after one specificed characters. 885 886 @param String Point to the string where to find the substring. 887 @param CharSet Point to the string to be found. 888 889 **/ 890 CHAR8 * 891 EFIAPI 892 AsciiStrTokenField ( 893 IN CHAR8 *String OPTIONAL, 894 IN CHAR8 *CharSet 895 ) 896 { 897 CHAR8 *Begin; 898 CHAR8 *End; 899 900 901 Begin = (String == NULL) ? mAsciiFieldBuffer : String; 902 if (Begin == NULL) { 903 return NULL; 904 } 905 906 if (*Begin == '\0') { 907 mAsciiFieldBuffer = NULL; 908 return NULL; 909 } 910 911 End = AsciiStrBrk (Begin, CharSet); 912 if ((End != NULL) && (*End != '\0')) { 913 *End = '\0'; 914 End ++; 915 } 916 917 mAsciiFieldBuffer = End; 918 return Begin; 919 } 920 921 /** 922 923 Find the next token after one or more specified characters. 924 925 @param String Point to the string where to find the substring. 926 @param CharSet Point to the string to be found. 927 928 **/ 929 CHAR8 * 930 EFIAPI 931 AsciiStrGetNewTokenLine ( 932 IN CHAR8 *String, 933 IN CHAR8 *CharSet 934 ) 935 { 936 return AsciiStrTokenLine (String, CharSet); 937 } 938 939 /** 940 941 Find the next token after one or more specified characters. 942 943 @param CharSet Point to the string to be found. 944 945 **/ 946 CHAR8 * 947 EFIAPI 948 AsciiStrGetNextTokenLine ( 949 IN CHAR8 *CharSet 950 ) 951 { 952 return AsciiStrTokenLine (NULL, CharSet); 953 } 954 955 /** 956 957 Find the next token after one specificed characters. 958 959 @param String Point to the string where to find the substring. 960 @param CharSet Point to the string to be found. 961 962 **/ 963 CHAR8 * 964 EFIAPI 965 AsciiStrGetNewTokenField ( 966 IN CHAR8 *String, 967 IN CHAR8 *CharSet 968 ) 969 { 970 return AsciiStrTokenField (String, CharSet); 971 } 972 973 /** 974 975 Find the next token after one specificed characters. 976 977 @param CharSet Point to the string to be found. 978 979 **/ 980 CHAR8 * 981 EFIAPI 982 AsciiStrGetNextTokenField ( 983 IN CHAR8 *CharSet 984 ) 985 { 986 return AsciiStrTokenField (NULL, CharSet); 987 } 988 989 /** 990 991 Patch a character to the end of a string. 992 993 @param Buffer The string to be patched. 994 @param Patch The patch character. 995 996 **/ 997 VOID 998 EFIAPI 999 PatchForAsciiStrTokenAfter ( 1000 IN CHAR8 *Buffer, 1001 IN CHAR8 Patch 1002 ) 1003 { 1004 CHAR8 *Str; 1005 1006 if (Buffer == NULL) { 1007 return ; 1008 } 1009 1010 Str = Buffer; 1011 while (*Str != 0) { 1012 Str ++; 1013 } 1014 *Str = Patch; 1015 1016 while (*(Str ++) != '\0') { 1017 if (*Str == 0) { 1018 *Str = Patch; 1019 } else { 1020 break; 1021 } 1022 } 1023 1024 return ; 1025 } 1026 1027 /** 1028 Patch a character at the beginning of a string. 1029 1030 @param Buffer The string to be patched. 1031 @param Patch The patch character. 1032 1033 **/ 1034 VOID 1035 EFIAPI 1036 PatchForAsciiStrTokenBefore ( 1037 IN CHAR8 *Buffer, 1038 IN CHAR8 Patch 1039 ) 1040 { 1041 CHAR8 *Str; 1042 1043 if (Buffer == NULL) { 1044 return ; 1045 } 1046 1047 Str = Buffer; 1048 while (*(Str --) != '\0') { 1049 if ((*Str == 0) || (*Str == Patch)) { 1050 *Str = Patch; 1051 } else { 1052 break; 1053 } 1054 } 1055 1056 return ; 1057 } 1058