comparison src/ex_docmd.c @ 24254:0868ac82ef18 v8.2.2668

patch 8.2.2668: Vim9: omitting "call" for "confirm()" does not give an error Commit: https://github.com/vim/vim/commit/f49a1fcdb952ca270f108fcc27bb8ad6922e0807 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 27 22:20:21 2021 +0100 patch 8.2.2668: Vim9: omitting "call" for "confirm()" does not give an error Problem: Vim9: omitting "call" for "confirm()" does not give an error. Solution: Do not recognize a modifier followed by "(".
author Bram Moolenaar <Bram@vim.org>
date Sat, 27 Mar 2021 22:30:02 +0100
parents a2e6029d354e
children b471a413d36a
comparison
equal deleted inserted replaced
24253:5fdc41e253e7 24254:0868ac82ef18
2683 vim_snprintf(ex_error_buf, MSG_BUF_LEN, _(msg), arg); 2683 vim_snprintf(ex_error_buf, MSG_BUF_LEN, _(msg), arg);
2684 return ex_error_buf; 2684 return ex_error_buf;
2685 } 2685 }
2686 2686
2687 /* 2687 /*
2688 * Check for an Ex command with optional tail.
2689 * If there is a match advance "pp" to the argument and return TRUE.
2690 * If "noparen" is TRUE do not recognize the command followed by "(".
2691 */
2692 static int
2693 checkforcmd_opt(
2694 char_u **pp, // start of command
2695 char *cmd, // name of command
2696 int len, // required length
2697 int noparen)
2698 {
2699 int i;
2700
2701 for (i = 0; cmd[i] != NUL; ++i)
2702 if (((char_u *)cmd)[i] != (*pp)[i])
2703 break;
2704 if (i >= len && !isalpha((*pp)[i])
2705 && (*pp)[i] != '_' && (!noparen || (*pp)[i] != '('))
2706 {
2707 *pp = skipwhite(*pp + i);
2708 return TRUE;
2709 }
2710 return FALSE;
2711 }
2712
2713 /*
2714 * Check for an Ex command with optional tail.
2715 * If there is a match advance "pp" to the argument and return TRUE.
2716 */
2717 int
2718 checkforcmd(
2719 char_u **pp, // start of command
2720 char *cmd, // name of command
2721 int len) // required length
2722 {
2723 return checkforcmd_opt(pp, cmd, len, FALSE);
2724 }
2725
2726 /*
2727 * Check for an Ex command with optional tail, not followed by "(".
2728 * If there is a match advance "pp" to the argument and return TRUE.
2729 */
2730 static int
2731 checkforcmd_noparen(
2732 char_u **pp, // start of command
2733 char *cmd, // name of command
2734 int len) // required length
2735 {
2736 return checkforcmd_opt(pp, cmd, len, TRUE);
2737 }
2738
2739 /*
2688 * Parse and skip over command modifiers: 2740 * Parse and skip over command modifiers:
2689 * - update eap->cmd 2741 * - update eap->cmd
2690 * - store flags in "cmod". 2742 * - store flags in "cmod".
2691 * - Set ex_pressedreturn for an empty command line. 2743 * - Set ex_pressedreturn for an empty command line.
2692 * When "skip_only" is TRUE the global variables are not changed, except for 2744 * When "skip_only" is TRUE the global variables are not changed, except for
2768 } 2820 }
2769 2821
2770 switch (*p) 2822 switch (*p)
2771 { 2823 {
2772 // When adding an entry, also modify cmd_exists(). 2824 // When adding an entry, also modify cmd_exists().
2773 case 'a': if (!checkforcmd(&eap->cmd, "aboveleft", 3)) 2825 case 'a': if (!checkforcmd_noparen(&eap->cmd, "aboveleft", 3))
2774 break; 2826 break;
2775 cmod->cmod_split |= WSP_ABOVE; 2827 cmod->cmod_split |= WSP_ABOVE;
2776 continue; 2828 continue;
2777 2829
2778 case 'b': if (checkforcmd(&eap->cmd, "belowright", 3)) 2830 case 'b': if (checkforcmd_noparen(&eap->cmd, "belowright", 3))
2779 { 2831 {
2780 cmod->cmod_split |= WSP_BELOW; 2832 cmod->cmod_split |= WSP_BELOW;
2781 continue; 2833 continue;
2782 } 2834 }
2783 if (checkforcmd(&eap->cmd, "browse", 3)) 2835 if (checkforcmd_opt(&eap->cmd, "browse", 3, TRUE))
2784 { 2836 {
2785 #ifdef FEAT_BROWSE_CMD 2837 #ifdef FEAT_BROWSE_CMD
2786 cmod->cmod_flags |= CMOD_BROWSE; 2838 cmod->cmod_flags |= CMOD_BROWSE;
2787 #endif 2839 #endif
2788 continue; 2840 continue;
2789 } 2841 }
2790 if (!checkforcmd(&eap->cmd, "botright", 2)) 2842 if (!checkforcmd_noparen(&eap->cmd, "botright", 2))
2791 break; 2843 break;
2792 cmod->cmod_split |= WSP_BOT; 2844 cmod->cmod_split |= WSP_BOT;
2793 continue; 2845 continue;
2794 2846
2795 case 'c': if (!checkforcmd(&eap->cmd, "confirm", 4)) 2847 case 'c': if (!checkforcmd_opt(&eap->cmd, "confirm", 4, TRUE))
2796 break; 2848 break;
2797 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2849 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2798 cmod->cmod_flags |= CMOD_CONFIRM; 2850 cmod->cmod_flags |= CMOD_CONFIRM;
2799 #endif 2851 #endif
2800 continue; 2852 continue;
2801 2853
2802 case 'k': if (checkforcmd(&eap->cmd, "keepmarks", 3)) 2854 case 'k': if (checkforcmd_noparen(&eap->cmd, "keepmarks", 3))
2803 { 2855 {
2804 cmod->cmod_flags |= CMOD_KEEPMARKS; 2856 cmod->cmod_flags |= CMOD_KEEPMARKS;
2805 continue; 2857 continue;
2806 } 2858 }
2807 if (checkforcmd(&eap->cmd, "keepalt", 5)) 2859 if (checkforcmd_noparen(&eap->cmd, "keepalt", 5))
2808 { 2860 {
2809 cmod->cmod_flags |= CMOD_KEEPALT; 2861 cmod->cmod_flags |= CMOD_KEEPALT;
2810 continue; 2862 continue;
2811 } 2863 }
2812 if (checkforcmd(&eap->cmd, "keeppatterns", 5)) 2864 if (checkforcmd_noparen(&eap->cmd, "keeppatterns", 5))
2813 { 2865 {
2814 cmod->cmod_flags |= CMOD_KEEPPATTERNS; 2866 cmod->cmod_flags |= CMOD_KEEPPATTERNS;
2815 continue; 2867 continue;
2816 } 2868 }
2817 if (!checkforcmd(&eap->cmd, "keepjumps", 5)) 2869 if (!checkforcmd_noparen(&eap->cmd, "keepjumps", 5))
2818 break; 2870 break;
2819 cmod->cmod_flags |= CMOD_KEEPJUMPS; 2871 cmod->cmod_flags |= CMOD_KEEPJUMPS;
2820 continue; 2872 continue;
2821 2873
2822 case 'f': // only accept ":filter {pat} cmd" 2874 case 'f': // only accept ":filter {pat} cmd"
2823 { 2875 {
2824 char_u *reg_pat; 2876 char_u *reg_pat;
2825 2877
2826 if (!checkforcmd(&p, "filter", 4) 2878 if (!checkforcmd_noparen(&p, "filter", 4)
2827 || *p == NUL || ends_excmd(*p)) 2879 || *p == NUL || ends_excmd(*p))
2828 break; 2880 break;
2829 if (*p == '!') 2881 if (*p == '!')
2830 { 2882 {
2831 cmod->cmod_filter_force = TRUE; 2883 cmod->cmod_filter_force = TRUE;
2855 eap->cmd = p; 2907 eap->cmd = p;
2856 continue; 2908 continue;
2857 } 2909 }
2858 2910
2859 // ":hide" and ":hide | cmd" are not modifiers 2911 // ":hide" and ":hide | cmd" are not modifiers
2860 case 'h': if (p != eap->cmd || !checkforcmd(&p, "hide", 3) 2912 case 'h': if (p != eap->cmd || !checkforcmd_noparen(&p, "hide", 3)
2861 || *p == NUL || ends_excmd(*p)) 2913 || *p == NUL || ends_excmd(*p))
2862 break; 2914 break;
2863 eap->cmd = p; 2915 eap->cmd = p;
2864 cmod->cmod_flags |= CMOD_HIDE; 2916 cmod->cmod_flags |= CMOD_HIDE;
2865 continue; 2917 continue;
2866 2918
2867 case 'l': if (checkforcmd(&eap->cmd, "lockmarks", 3)) 2919 case 'l': if (checkforcmd_noparen(&eap->cmd, "lockmarks", 3))
2868 { 2920 {
2869 cmod->cmod_flags |= CMOD_LOCKMARKS; 2921 cmod->cmod_flags |= CMOD_LOCKMARKS;
2870 continue; 2922 continue;
2871 } 2923 }
2872 2924
2873 if (!checkforcmd(&eap->cmd, "leftabove", 5)) 2925 if (!checkforcmd_noparen(&eap->cmd, "leftabove", 5))
2874 break; 2926 break;
2875 cmod->cmod_split |= WSP_ABOVE; 2927 cmod->cmod_split |= WSP_ABOVE;
2876 continue; 2928 continue;
2877 2929
2878 case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3)) 2930 case 'n': if (checkforcmd_noparen(&eap->cmd, "noautocmd", 3))
2879 { 2931 {
2880 cmod->cmod_flags |= CMOD_NOAUTOCMD; 2932 cmod->cmod_flags |= CMOD_NOAUTOCMD;
2881 continue; 2933 continue;
2882 } 2934 }
2883 if (!checkforcmd(&eap->cmd, "noswapfile", 3)) 2935 if (!checkforcmd_noparen(&eap->cmd, "noswapfile", 3))
2884 break; 2936 break;
2885 cmod->cmod_flags |= CMOD_NOSWAPFILE; 2937 cmod->cmod_flags |= CMOD_NOSWAPFILE;
2886 continue; 2938 continue;
2887 2939
2888 case 'r': if (!checkforcmd(&eap->cmd, "rightbelow", 6)) 2940 case 'r': if (!checkforcmd_noparen(&eap->cmd, "rightbelow", 6))
2889 break; 2941 break;
2890 cmod->cmod_split |= WSP_BELOW; 2942 cmod->cmod_split |= WSP_BELOW;
2891 continue; 2943 continue;
2892 2944
2893 case 's': if (checkforcmd(&eap->cmd, "sandbox", 3)) 2945 case 's': if (checkforcmd_noparen(&eap->cmd, "sandbox", 3))
2894 { 2946 {
2895 cmod->cmod_flags |= CMOD_SANDBOX; 2947 cmod->cmod_flags |= CMOD_SANDBOX;
2896 continue; 2948 continue;
2897 } 2949 }
2898 if (!checkforcmd(&eap->cmd, "silent", 3)) 2950 if (!checkforcmd_noparen(&eap->cmd, "silent", 3))
2899 break; 2951 break;
2900 cmod->cmod_flags |= CMOD_SILENT; 2952 cmod->cmod_flags |= CMOD_SILENT;
2901 if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1])) 2953 if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
2902 { 2954 {
2903 // ":silent!", but not "silent !cmd" 2955 // ":silent!", but not "silent !cmd"
2904 eap->cmd = skipwhite(eap->cmd + 1); 2956 eap->cmd = skipwhite(eap->cmd + 1);
2905 cmod->cmod_flags |= CMOD_ERRSILENT; 2957 cmod->cmod_flags |= CMOD_ERRSILENT;
2906 } 2958 }
2907 continue; 2959 continue;
2908 2960
2909 case 't': if (checkforcmd(&p, "tab", 3)) 2961 case 't': if (checkforcmd_noparen(&p, "tab", 3))
2910 { 2962 {
2911 if (!skip_only) 2963 if (!skip_only)
2912 { 2964 {
2913 long tabnr = get_address(eap, &eap->cmd, 2965 long tabnr = get_address(eap, &eap->cmd,
2914 ADDR_TABS, eap->skip, 2966 ADDR_TABS, eap->skip,
2926 } 2978 }
2927 } 2979 }
2928 eap->cmd = p; 2980 eap->cmd = p;
2929 continue; 2981 continue;
2930 } 2982 }
2931 if (!checkforcmd(&eap->cmd, "topleft", 2)) 2983 if (!checkforcmd_noparen(&eap->cmd, "topleft", 2))
2932 break; 2984 break;
2933 cmod->cmod_split |= WSP_TOP; 2985 cmod->cmod_split |= WSP_TOP;
2934 continue; 2986 continue;
2935 2987
2936 case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3)) 2988 case 'u': if (!checkforcmd_noparen(&eap->cmd, "unsilent", 3))
2937 break; 2989 break;
2938 cmod->cmod_flags |= CMOD_UNSILENT; 2990 cmod->cmod_flags |= CMOD_UNSILENT;
2939 continue; 2991 continue;
2940 2992
2941 case 'v': if (checkforcmd(&eap->cmd, "vertical", 4)) 2993 case 'v': if (checkforcmd_noparen(&eap->cmd, "vertical", 4))
2942 { 2994 {
2943 cmod->cmod_split |= WSP_VERT; 2995 cmod->cmod_split |= WSP_VERT;
2944 continue; 2996 continue;
2945 } 2997 }
2946 if (checkforcmd(&eap->cmd, "vim9cmd", 4)) 2998 if (checkforcmd_noparen(&eap->cmd, "vim9cmd", 4))
2947 { 2999 {
2948 if (ends_excmd2(p, eap->cmd)) 3000 if (ends_excmd2(p, eap->cmd))
2949 { 3001 {
2950 *errormsg = 3002 *errormsg =
2951 _(e_vim9cmd_must_be_followed_by_command); 3003 _(e_vim9cmd_must_be_followed_by_command);
2952 return FAIL; 3004 return FAIL;
2953 } 3005 }
2954 cmod->cmod_flags |= CMOD_VIM9CMD; 3006 cmod->cmod_flags |= CMOD_VIM9CMD;
2955 continue; 3007 continue;
2956 } 3008 }
2957 if (!checkforcmd(&p, "verbose", 4)) 3009 if (!checkforcmd_noparen(&p, "verbose", 4))
2958 break; 3010 break;
2959 if (vim_isdigit(*eap->cmd)) 3011 if (vim_isdigit(*eap->cmd))
2960 cmod->cmod_verbose = atoi((char *)eap->cmd); 3012 cmod->cmod_verbose = atoi((char *)eap->cmd);
2961 else 3013 else
2962 cmod->cmod_verbose = 1; 3014 cmod->cmod_verbose = 1;
3250 } 3302 }
3251 return OK; 3303 return OK;
3252 } 3304 }
3253 3305
3254 /* 3306 /*
3255 * Check for an Ex command with optional tail.
3256 * If there is a match advance "pp" to the argument and return TRUE.
3257 */
3258 int
3259 checkforcmd(
3260 char_u **pp, // start of command
3261 char *cmd, // name of command
3262 int len) // required length
3263 {
3264 int i;
3265
3266 for (i = 0; cmd[i] != NUL; ++i)
3267 if (((char_u *)cmd)[i] != (*pp)[i])
3268 break;
3269 if (i >= len && !isalpha((*pp)[i]) && (*pp)[i] != '_')
3270 {
3271 *pp = skipwhite(*pp + i);
3272 return TRUE;
3273 }
3274 return FALSE;
3275 }
3276
3277 /*
3278 * Append "cmd" to the error message in IObuff. 3307 * Append "cmd" to the error message in IObuff.
3279 * Takes care of limiting the length and handling 0xa0, which would be 3308 * Takes care of limiting the length and handling 0xa0, which would be
3280 * invisible otherwise. 3309 * invisible otherwise.
3281 */ 3310 */
3282 static void 3311 static void