aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbb/lineedit.c58
1 files changed, 34 insertions, 24 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index a99f9b5fd..cb675f230 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -685,29 +685,34 @@ static void exe_n_cwd_tab_completion(char *command, int type)
685#undef dirbuf 685#undef dirbuf
686} 686}
687 687
688//FIXME: HUH??? How about Unicode? 688/* QUOT is used on elements of int_buf[], which are bytes,
689 * not Unicode chars. Therefore it works correctly even in Unicode mode.
690 */
689#define QUOT (UCHAR_MAX+1) 691#define QUOT (UCHAR_MAX+1)
690 692
691#define collapse_pos(is, in) do { \ 693#define int_buf (S.find_match__int_buf)
692 memmove(int_buf+(is), int_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \ 694#define pos_buf (S.find_match__pos_buf)
693 memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \ 695
694} while (0) 696static void collapse_pos(int is, int in)
697{
698 memmove(int_buf+is, int_buf+in, (MAX_LINELEN+1 - is - in) * sizeof(int_buf[0]));
699 memmove(pos_buf+is, pos_buf+in, (MAX_LINELEN+1 - is - in) * sizeof(pos_buf[0]));
700}
695 701
696static NOINLINE int find_match(char *matchBuf, int *len_with_quotes) 702static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
697{ 703{
698 int i, j; 704 int i, j;
699 int command_mode; 705 int command_mode;
700 int c, c2; 706 int c, c2;
707/* Were local, but it uses too much stack */
701/* int16_t int_buf[MAX_LINELEN + 1]; */ 708/* int16_t int_buf[MAX_LINELEN + 1]; */
702/* int16_t pos_buf[MAX_LINELEN + 1]; */ 709/* int16_t pos_buf[MAX_LINELEN + 1]; */
703#define int_buf (S.find_match__int_buf)
704#define pos_buf (S.find_match__pos_buf)
705 710
706 /* set to integer dimension characters and own positions */ 711 /* set to integer dimension characters and own positions */
707 for (i = 0;; i++) { 712 for (i = 0;; i++) {
708 int_buf[i] = (unsigned char)matchBuf[i]; 713 int_buf[i] = (unsigned char)matchBuf[i];
709 if (int_buf[i] == 0) { 714 if (int_buf[i] == 0) {
710 pos_buf[i] = -1; /* indicator end line */ 715 pos_buf[i] = -1; /* end-fo-line indicator */
711 break; 716 break;
712 } 717 }
713 pos_buf[i] = i; 718 pos_buf[i] = i;
@@ -720,7 +725,7 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
720 int_buf[j] |= QUOT; 725 int_buf[j] |= QUOT;
721 i++; 726 i++;
722#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 727#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
723 if (matchBuf[i] == '\t') /* algorithm equivalent */ 728 if (matchBuf[i] == '\t') /* algorithm equivalent */
724 int_buf[j] = ' ' | QUOT; 729 int_buf[j] = ' ' | QUOT;
725#endif 730#endif
726 } 731 }
@@ -763,11 +768,11 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
763 } 768 }
764 if (command_mode) { 769 if (command_mode) {
765 collapse_pos(0, i + command_mode); 770 collapse_pos(0, i + command_mode);
766 i = -1; /* hack incremet */ 771 i = -1; /* hack incremet */
767 } 772 }
768 } 773 }
769 /* collapse `command...` */ 774 /* collapse `command...` */
770 for (i = 0; int_buf[i]; i++) 775 for (i = 0; int_buf[i]; i++) {
771 if (int_buf[i] == '`') { 776 if (int_buf[i] == '`') {
772 for (j = i + 1; int_buf[j]; j++) 777 for (j = i + 1; int_buf[j]; j++)
773 if (int_buf[j] == '`') { 778 if (int_buf[j] == '`') {
@@ -776,34 +781,37 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
776 break; 781 break;
777 } 782 }
778 if (j) { 783 if (j) {
779 /* not found close ` - command mode, collapse all previous */ 784 /* not found closing ` - command mode, collapse all previous */
780 collapse_pos(0, i + 1); 785 collapse_pos(0, i + 1);
781 break; 786 break;
782 } else 787 } else
783 i--; /* hack incremet */ 788 i--; /* hack incremet */
784 } 789 }
790 }
785 791
786 /* collapse (command...(command...)...) or {command...{command...}...} */ 792 /* collapse (command...(command...)...) or {command...{command...}...} */
787 c = 0; /* "recursive" level */ 793 c = 0; /* "recursive" level */
788 c2 = 0; 794 c2 = 0;
789 for (i = 0; int_buf[i]; i++) 795 for (i = 0; int_buf[i]; i++) {
790 if (int_buf[i] == '(' || int_buf[i] == '{') { 796 if (int_buf[i] == '(' || int_buf[i] == '{') {
791 if (int_buf[i] == '(') 797 if (int_buf[i] == '(')
792 c++; 798 c++;
793 else 799 else
794 c2++; 800 c2++;
795 collapse_pos(0, i + 1); 801 collapse_pos(0, i + 1);
796 i = -1; /* hack incremet */ 802 i = -1; /* hack incremet */
797 } 803 }
798 for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++) 804 }
805 for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++) {
799 if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) { 806 if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
800 if (int_buf[i] == ')') 807 if (int_buf[i] == ')')
801 c--; 808 c--;
802 else 809 else
803 c2--; 810 c2--;
804 collapse_pos(0, i + 1); 811 collapse_pos(0, i + 1);
805 i = -1; /* hack incremet */ 812 i = -1; /* hack incremet */
806 } 813 }
814 }
807 815
808 /* skip first not quote space */ 816 /* skip first not quote space */
809 for (i = 0; int_buf[i]; i++) 817 for (i = 0; int_buf[i]; i++)
@@ -814,7 +822,7 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
814 822
815 /* set find mode for completion */ 823 /* set find mode for completion */
816 command_mode = FIND_EXE_ONLY; 824 command_mode = FIND_EXE_ONLY;
817 for (i = 0; int_buf[i]; i++) 825 for (i = 0; int_buf[i]; i++) {
818 if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { 826 if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') {
819 if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY 827 if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY
820 && matchBuf[pos_buf[0]] == 'c' 828 && matchBuf[pos_buf[0]] == 'c'
@@ -826,6 +834,7 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
826 break; 834 break;
827 } 835 }
828 } 836 }
837 }
829 for (i = 0; int_buf[i]; i++) 838 for (i = 0; int_buf[i]; i++)
830 /* "strlen" */; 839 /* "strlen" */;
831 /* find last word */ 840 /* find last word */
@@ -873,9 +882,9 @@ static void showfiles(void)
873 int nrows = nfiles; 882 int nrows = nfiles;
874 int l; 883 int l;
875 884
876 /* find the longest file name- use that as the column width */ 885 /* find the longest file name - use that as the column width */
877 for (row = 0; row < nrows; row++) { 886 for (row = 0; row < nrows; row++) {
878 l = strlen(matches[row]); 887 l = bb_mbstrlen(matches[row]);
879 if (column_width < l) 888 if (column_width < l)
880 column_width = l; 889 column_width = l;
881 } 890 }
@@ -895,7 +904,8 @@ static void showfiles(void)
895 904
896 for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { 905 for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
897 printf("%s%-*s", matches[n], 906 printf("%s%-*s", matches[n],
898 (int)(column_width - strlen(matches[n])), ""); 907 (int)(column_width - bb_mbstrlen(matches[n])), ""
908 );
899 } 909 }
900 puts(matches[n]); 910 puts(matches[n]);
901 } 911 }
@@ -904,14 +914,14 @@ static void showfiles(void)
904static char *add_quote_for_spec_chars(char *found) 914static char *add_quote_for_spec_chars(char *found)
905{ 915{
906 int l = 0; 916 int l = 0;
907 char *s = xmalloc((strlen(found) + 1) * 2); 917 char *s = xzalloc((strlen(found) + 1) * 2);
908 918
909 while (*found) { 919 while (*found) {
910 if (strchr(" `\"#$%^&*()=+{}[]:;\'|\\<>", *found)) 920 if (strchr(" `\"#$%^&*()=+{}[]:;\'|\\<>", *found))
911 s[l++] = '\\'; 921 s[l++] = '\\';
912 s[l++] = *found++; 922 s[l++] = *found++;
913 } 923 }
914 s[l] = 0; 924 /* s[l] = '\0'; - already is */
915 return s; 925 return s;
916} 926}
917 927