Mercurial > vim
comparison src/ex_docmd.c @ 72:2b454a43b2c6
updated for version 7.0031
author | vimboss |
---|---|
date | Wed, 05 Jan 2005 22:07:01 +0000 |
parents | c75153d791d0 |
children | 31e555c6c691 |
comparison
equal
deleted
inserted
replaced
71:7557b6ea0fb1 | 72:2b454a43b2c6 |
---|---|
322 # define ex_call ex_ni | 322 # define ex_call ex_ni |
323 # define ex_if ex_ni | 323 # define ex_if ex_ni |
324 # define ex_endif ex_ni | 324 # define ex_endif ex_ni |
325 # define ex_else ex_ni | 325 # define ex_else ex_ni |
326 # define ex_while ex_ni | 326 # define ex_while ex_ni |
327 # define ex_for ex_ni | |
327 # define ex_continue ex_ni | 328 # define ex_continue ex_ni |
328 # define ex_break ex_ni | 329 # define ex_break ex_ni |
329 # define ex_endwhile ex_ni | 330 # define ex_endwhile ex_ni |
331 # define ex_endfor ex_ni | |
330 # define ex_throw ex_ni | 332 # define ex_throw ex_ni |
331 # define ex_try ex_ni | 333 # define ex_try ex_ni |
332 # define ex_catch ex_ni | 334 # define ex_catch ex_ni |
333 # define ex_finally ex_ni | 335 # define ex_finally ex_ni |
334 # define ex_endtry ex_ni | 336 # define ex_endtry ex_ni |
470 | 472 |
471 static char_u dollar_command[2] = {'$', 0}; | 473 static char_u dollar_command[2] = {'$', 0}; |
472 | 474 |
473 | 475 |
474 #ifdef FEAT_EVAL | 476 #ifdef FEAT_EVAL |
475 /* Struct for storing a line inside a while loop */ | 477 /* Struct for storing a line inside a while/for loop */ |
476 typedef struct | 478 typedef struct |
477 { | 479 { |
478 char_u *line; /* command line */ | 480 char_u *line; /* command line */ |
479 linenr_T lnum; /* sourcing_lnum of the line */ | 481 linenr_T lnum; /* sourcing_lnum of the line */ |
480 } wcmd_T; | 482 } wcmd_T; |
481 | 483 |
482 /* | 484 /* |
483 * Structure used to store info for line position in a while loop. | 485 * Structure used to store info for line position in a while or for loop. |
484 * This is required, because do_one_cmd() may invoke ex_function(), which | 486 * This is required, because do_one_cmd() may invoke ex_function(), which |
485 * reads more lines that may come from the while loop. | 487 * reads more lines that may come from the while/for loop. |
486 */ | 488 */ |
487 struct while_cookie | 489 struct loop_cookie |
488 { | 490 { |
489 garray_T *lines_gap; /* growarray with line info */ | 491 garray_T *lines_gap; /* growarray with line info */ |
490 int current_line; /* last read line from growarray */ | 492 int current_line; /* last read line from growarray */ |
491 int repeating; /* TRUE when looping a second time */ | 493 int repeating; /* TRUE when looping a second time */ |
492 /* When "repeating" is FALSE use "getline" and "cookie" to get lines */ | 494 /* When "repeating" is FALSE use "getline" and "cookie" to get lines */ |
493 char_u *(*getline) __ARGS((int, void *, int)); | 495 char_u *(*getline) __ARGS((int, void *, int)); |
494 void *cookie; | 496 void *cookie; |
495 }; | 497 }; |
496 | 498 |
497 static char_u *get_while_line __ARGS((int c, void *cookie, int indent)); | 499 static char_u *get_loop_line __ARGS((int c, void *cookie, int indent)); |
498 static int store_while_line __ARGS((garray_T *gap, char_u *line)); | 500 static int store_loop_line __ARGS((garray_T *gap, char_u *line)); |
499 static void free_cmdlines __ARGS((garray_T *gap)); | 501 static void free_cmdlines __ARGS((garray_T *gap)); |
500 | 502 |
501 /* Struct to save a few things while debugging. Used in do_cmdline() only. */ | 503 /* Struct to save a few things while debugging. Used in do_cmdline() only. */ |
502 struct dbg_stuff | 504 struct dbg_stuff |
503 { | 505 { |
684 int count = 0; /* line number count */ | 686 int count = 0; /* line number count */ |
685 int did_inc = FALSE; /* incremented RedrawingDisabled */ | 687 int did_inc = FALSE; /* incremented RedrawingDisabled */ |
686 int retval = OK; | 688 int retval = OK; |
687 #ifdef FEAT_EVAL | 689 #ifdef FEAT_EVAL |
688 struct condstack cstack; /* conditional stack */ | 690 struct condstack cstack; /* conditional stack */ |
689 garray_T lines_ga; /* keep lines for ":while" */ | 691 garray_T lines_ga; /* keep lines for ":while"/":for" */ |
690 int current_line = 0; /* active line in lines_ga */ | 692 int current_line = 0; /* active line in lines_ga */ |
691 char_u *fname = NULL; /* function or script name */ | 693 char_u *fname = NULL; /* function or script name */ |
692 linenr_T *breakpoint = NULL; /* ptr to breakpoint field in cookie */ | 694 linenr_T *breakpoint = NULL; /* ptr to breakpoint field in cookie */ |
693 int *dbg_tick = NULL; /* ptr to dbg_tick field in cookie */ | 695 int *dbg_tick = NULL; /* ptr to dbg_tick field in cookie */ |
694 struct dbg_stuff debug_saved; /* saved things for debug mode */ | 696 struct dbg_stuff debug_saved; /* saved things for debug mode */ |
697 struct msglist *private_msg_list; | 699 struct msglist *private_msg_list; |
698 | 700 |
699 /* "getline" and "cookie" passed to do_one_cmd() */ | 701 /* "getline" and "cookie" passed to do_one_cmd() */ |
700 char_u *(*cmd_getline) __ARGS((int, void *, int)); | 702 char_u *(*cmd_getline) __ARGS((int, void *, int)); |
701 void *cmd_cookie; | 703 void *cmd_cookie; |
702 struct while_cookie cmd_while_cookie; | 704 struct loop_cookie cmd_loop_cookie; |
703 void *real_cookie; | 705 void *real_cookie; |
704 #else | 706 #else |
705 # define cmd_getline getline | 707 # define cmd_getline getline |
706 # define cmd_cookie cookie | 708 # define cmd_cookie cookie |
707 #endif | 709 #endif |
734 } | 736 } |
735 ++call_depth; | 737 ++call_depth; |
736 | 738 |
737 #ifdef FEAT_EVAL | 739 #ifdef FEAT_EVAL |
738 cstack.cs_idx = -1; | 740 cstack.cs_idx = -1; |
739 cstack.cs_whilelevel = 0; | 741 cstack.cs_looplevel = 0; |
740 cstack.cs_trylevel = 0; | 742 cstack.cs_trylevel = 0; |
741 cstack.cs_emsg_silent_list = NULL; | 743 cstack.cs_emsg_silent_list = NULL; |
742 cstack.cs_had_while = FALSE; | 744 cstack.cs_lflags = 0; |
743 cstack.cs_had_endwhile = FALSE; | |
744 cstack.cs_had_continue = FALSE; | |
745 cstack.cs_had_finally = FALSE; | |
746 ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10); | 745 ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10); |
747 | 746 |
748 real_cookie = getline_cookie(getline, cookie); | 747 real_cookie = getline_cookie(getline, cookie); |
749 | 748 |
750 /* Inside a function use a higher nesting level. */ | 749 /* Inside a function use a higher nesting level. */ |
790 */ | 789 */ |
791 did_throw = FALSE; | 790 did_throw = FALSE; |
792 #endif | 791 #endif |
793 /* | 792 /* |
794 * "did_emsg" will be set to TRUE when emsg() is used, in which case we | 793 * "did_emsg" will be set to TRUE when emsg() is used, in which case we |
795 * cancel the whole command line, and any if/endif while/endwhile loop. | 794 * cancel the whole command line, and any if/endif or loop. |
796 * If force_abort is set, we cancel everything. | 795 * If force_abort is set, we cancel everything. |
797 */ | 796 */ |
798 did_emsg = FALSE; | 797 did_emsg = FALSE; |
799 | 798 |
800 /* | 799 /* |
804 if (!(flags & DOCMD_KEYTYPED) && !getline_equal(getline, cookie, getexline)) | 803 if (!(flags & DOCMD_KEYTYPED) && !getline_equal(getline, cookie, getexline)) |
805 KeyTyped = FALSE; | 804 KeyTyped = FALSE; |
806 | 805 |
807 /* | 806 /* |
808 * Continue executing command lines: | 807 * Continue executing command lines: |
809 * - when inside an ":if" or ":while" | 808 * - when inside an ":if", ":while" or ":for" |
810 * - for multiple commands on one line, separated with '|' | 809 * - for multiple commands on one line, separated with '|' |
811 * - when repeating until there are no more lines (for ":source") | 810 * - when repeating until there are no more lines (for ":source") |
812 */ | 811 */ |
813 next_cmdline = cmdline; | 812 next_cmdline = cmdline; |
814 do | 813 do |
815 { | 814 { |
816 /* stop skipping cmds for an error msg after all endifs and endwhiles */ | 815 /* stop skipping cmds for an error msg after all endif/while/for */ |
817 if (next_cmdline == NULL | 816 if (next_cmdline == NULL |
818 #ifdef FEAT_EVAL | 817 #ifdef FEAT_EVAL |
819 && !force_abort | 818 && !force_abort |
820 && cstack.cs_idx < 0 | 819 && cstack.cs_idx < 0 |
821 && !(getline_equal(getline, cookie, get_func_line) | 820 && !(getline_equal(getline, cookie, get_func_line) |
823 #endif | 822 #endif |
824 ) | 823 ) |
825 did_emsg = FALSE; | 824 did_emsg = FALSE; |
826 | 825 |
827 /* | 826 /* |
828 * 1. If repeating a line with ":while", get a line from lines_ga. | 827 * 1. If repeating a line in a loop, get a line from lines_ga. |
829 * 2. If no line given: Get an allocated line with getline(). | 828 * 2. If no line given: Get an allocated line with getline(). |
830 * 3. If a line is given: Make a copy, so we can mess with it. | 829 * 3. If a line is given: Make a copy, so we can mess with it. |
831 */ | 830 */ |
832 | 831 |
833 #ifdef FEAT_EVAL | 832 #ifdef FEAT_EVAL |
834 /* 1. If repeating, get a previous line from lines_ga. */ | 833 /* 1. If repeating, get a previous line from lines_ga. */ |
835 if (cstack.cs_whilelevel && current_line < lines_ga.ga_len) | 834 if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len) |
836 { | 835 { |
837 /* Each '|' separated command is stored separately in lines_ga, to | 836 /* Each '|' separated command is stored separately in lines_ga, to |
838 * be able to jump to it. Don't use next_cmdline now. */ | 837 * be able to jump to it. Don't use next_cmdline now. */ |
839 vim_free(cmdline_copy); | 838 vim_free(cmdline_copy); |
840 cmdline_copy = NULL; | 839 cmdline_copy = NULL; |
879 fname, sourcing_lnum); | 878 fname, sourcing_lnum); |
880 *dbg_tick = debug_tick; | 879 *dbg_tick = debug_tick; |
881 } | 880 } |
882 } | 881 } |
883 | 882 |
884 if (cstack.cs_whilelevel) | 883 if (cstack.cs_looplevel > 0) |
885 { | 884 { |
886 /* Inside a while loop we need to store the lines and use them | 885 /* Inside a while/for loop we need to store the lines and use them |
887 * again. Pass a different "getline" function to do_one_cmd() | 886 * again. Pass a different "getline" function to do_one_cmd() |
888 * below, so that it stores lines in or reads them from | 887 * below, so that it stores lines in or reads them from |
889 * "lines_ga". Makes it possible to define a function inside a | 888 * "lines_ga". Makes it possible to define a function inside a |
890 * while loop. */ | 889 * while/for loop. */ |
891 cmd_getline = get_while_line; | 890 cmd_getline = get_loop_line; |
892 cmd_cookie = (void *)&cmd_while_cookie; | 891 cmd_cookie = (void *)&cmd_loop_cookie; |
893 cmd_while_cookie.lines_gap = &lines_ga; | 892 cmd_loop_cookie.lines_gap = &lines_ga; |
894 cmd_while_cookie.current_line = current_line; | 893 cmd_loop_cookie.current_line = current_line; |
895 cmd_while_cookie.getline = getline; | 894 cmd_loop_cookie.getline = getline; |
896 cmd_while_cookie.cookie = cookie; | 895 cmd_loop_cookie.cookie = cookie; |
897 cmd_while_cookie.repeating = (current_line < lines_ga.ga_len); | 896 cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len); |
898 } | 897 } |
899 else | 898 else |
900 { | 899 { |
901 cmd_getline = getline; | 900 cmd_getline = getline; |
902 cmd_cookie = cookie; | 901 cmd_cookie = cookie; |
956 } | 955 } |
957 cmdline_copy = next_cmdline; | 956 cmdline_copy = next_cmdline; |
958 | 957 |
959 #ifdef FEAT_EVAL | 958 #ifdef FEAT_EVAL |
960 /* | 959 /* |
961 * Save the current line when inside a ":while", and when the command | 960 * Save the current line when inside a ":while" or ":for", and when |
962 * looks like a ":while", because we may need it later. | 961 * the command looks like a ":while" or ":for", because we may need it |
963 * When there is a '|' and another command, it is stored separately, | 962 * later. When there is a '|' and another command, it is stored |
964 * because we need to be able to jump back to it from an :endwhile. | 963 * separately, because we need to be able to jump back to it from an |
964 * :endwhile/:endfor. | |
965 */ | 965 */ |
966 if ( current_line == lines_ga.ga_len | 966 if (current_line == lines_ga.ga_len |
967 && (cstack.cs_whilelevel || has_while_cmd(next_cmdline))) | 967 && (cstack.cs_looplevel || has_loop_cmd(next_cmdline))) |
968 { | 968 { |
969 if (store_while_line(&lines_ga, next_cmdline) == FAIL) | 969 if (store_loop_line(&lines_ga, next_cmdline) == FAIL) |
970 { | 970 { |
971 retval = FAIL; | 971 retval = FAIL; |
972 break; | 972 break; |
973 } | 973 } |
974 } | 974 } |
1028 #endif | 1028 #endif |
1029 cmd_getline, cmd_cookie); | 1029 cmd_getline, cmd_cookie); |
1030 --recursive; | 1030 --recursive; |
1031 | 1031 |
1032 #ifdef FEAT_EVAL | 1032 #ifdef FEAT_EVAL |
1033 if (cmd_cookie == (void *)&cmd_while_cookie) | 1033 if (cmd_cookie == (void *)&cmd_loop_cookie) |
1034 /* Use "current_line" from "cmd_while_cookie", it may have been | 1034 /* Use "current_line" from "cmd_loop_cookie", it may have been |
1035 * incremented when defining a function. */ | 1035 * incremented when defining a function. */ |
1036 current_line = cmd_while_cookie.current_line; | 1036 current_line = cmd_loop_cookie.current_line; |
1037 #endif | 1037 #endif |
1038 | 1038 |
1039 if (next_cmdline == NULL) | 1039 if (next_cmdline == NULL) |
1040 { | 1040 { |
1041 vim_free(cmdline_copy); | 1041 vim_free(cmdline_copy); |
1068 if (did_emsg && !force_abort | 1068 if (did_emsg && !force_abort |
1069 && getline_equal(getline, cookie, get_func_line) | 1069 && getline_equal(getline, cookie, get_func_line) |
1070 && !func_has_abort(real_cookie)) | 1070 && !func_has_abort(real_cookie)) |
1071 did_emsg = FALSE; | 1071 did_emsg = FALSE; |
1072 | 1072 |
1073 if (cstack.cs_whilelevel) | 1073 if (cstack.cs_looplevel > 0) |
1074 { | 1074 { |
1075 ++current_line; | 1075 ++current_line; |
1076 | 1076 |
1077 /* | 1077 /* |
1078 * An ":endwhile" and ":continue" is handled here. | 1078 * An ":endwhile", ":endfor" and ":continue" is handled here. |
1079 * If we were executing commands, jump back to the ":while". | 1079 * If we were executing commands, jump back to the ":while" or |
1080 * If we were not executing commands, decrement whilelevel. | 1080 * ":for". |
1081 * If we were not executing commands, decrement cs_looplevel. | |
1081 */ | 1082 */ |
1082 if (cstack.cs_had_endwhile || cstack.cs_had_continue) | 1083 if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP)) |
1083 { | 1084 { |
1084 if (cstack.cs_had_endwhile) | 1085 cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP); |
1085 cstack.cs_had_endwhile = FALSE; | 1086 |
1086 else | 1087 /* Jump back to the matching ":while" or ":for". Be careful |
1087 cstack.cs_had_continue = FALSE; | 1088 * not to use a cs_line[] from an entry that isn't a ":while" |
1088 | 1089 * or ":for": It would make "current_line" invalid and can |
1089 /* Jump back to the matching ":while". Be careful not to use | 1090 * cause a crash. */ |
1090 * a cs_line[] from an entry that isn't a ":while": It would | |
1091 * make "current_line" invalid and can cause a crash. */ | |
1092 if (!did_emsg && !got_int && !did_throw | 1091 if (!did_emsg && !got_int && !did_throw |
1093 && cstack.cs_idx >= 0 | 1092 && cstack.cs_idx >= 0 |
1094 && (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE) | 1093 && (cstack.cs_flags[cstack.cs_idx] |
1094 & (CSF_WHILE | CSF_FOR)) | |
1095 && cstack.cs_line[cstack.cs_idx] >= 0 | 1095 && cstack.cs_line[cstack.cs_idx] >= 0 |
1096 && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE)) | 1096 && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE)) |
1097 { | 1097 { |
1098 current_line = cstack.cs_line[cstack.cs_idx]; | 1098 current_line = cstack.cs_line[cstack.cs_idx]; |
1099 cstack.cs_had_while = TRUE; /* note we jumped there */ | 1099 /* remember we jumped there */ |
1100 cstack.cs_lflags |= CSL_HAD_LOOP; | |
1100 line_breakcheck(); /* check if CTRL-C typed */ | 1101 line_breakcheck(); /* check if CTRL-C typed */ |
1101 | 1102 |
1102 /* Check for the next breakpoint at or after the ":while".*/ | 1103 /* Check for the next breakpoint at or after the ":while" |
1104 * or ":for". */ | |
1103 if (breakpoint != NULL) | 1105 if (breakpoint != NULL) |
1104 { | 1106 { |
1105 *breakpoint = dbg_find_breakpoint( | 1107 *breakpoint = dbg_find_breakpoint( |
1106 getline_equal(getline, cookie, getsourceline), | 1108 getline_equal(getline, cookie, getsourceline), |
1107 fname, | 1109 fname, |
1108 ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1); | 1110 ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1); |
1109 *dbg_tick = debug_tick; | 1111 *dbg_tick = debug_tick; |
1110 } | 1112 } |
1111 } | 1113 } |
1112 else /* can only get here with ":endwhile" */ | 1114 else |
1113 { | 1115 { |
1114 --cstack.cs_whilelevel; | 1116 /* can only get here with ":endwhile" or ":endfor" */ |
1117 --cstack.cs_looplevel; | |
1115 if (cstack.cs_idx >= 0) | 1118 if (cstack.cs_idx >= 0) |
1116 --cstack.cs_idx; | 1119 --cstack.cs_idx; |
1117 } | 1120 } |
1118 } | 1121 } |
1119 | 1122 |
1120 /* | 1123 /* |
1121 * For a ":while" we need to remember the line number. | 1124 * For a ":while" or ":for" we need to remember the line number. |
1122 */ | 1125 */ |
1123 else if (cstack.cs_had_while) | 1126 else if (cstack.cs_lflags & CSL_HAD_LOOP) |
1124 { | 1127 { |
1125 cstack.cs_had_while = FALSE; | 1128 cstack.cs_lflags &= ~CSL_HAD_LOOP; |
1126 cstack.cs_line[cstack.cs_idx] = current_line - 1; | 1129 cstack.cs_line[cstack.cs_idx] = current_line - 1; |
1127 } | 1130 } |
1128 } | 1131 } |
1129 | 1132 |
1130 /* | 1133 /* |
1131 * When not inside any ":while" loop, clear remembered lines. | 1134 * When not inside any ":while" loop, clear remembered lines. |
1132 */ | 1135 */ |
1133 if (!cstack.cs_whilelevel) | 1136 if (cstack.cs_looplevel == 0) |
1134 { | 1137 { |
1135 if (lines_ga.ga_len > 0) | 1138 if (lines_ga.ga_len > 0) |
1136 { | 1139 { |
1137 sourcing_lnum = | 1140 sourcing_lnum = |
1138 ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; | 1141 ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; |
1140 } | 1143 } |
1141 current_line = 0; | 1144 current_line = 0; |
1142 } | 1145 } |
1143 | 1146 |
1144 /* | 1147 /* |
1145 * A ":finally" makes did_emsg, got_int, and did_throw pending for being | 1148 * A ":finally" makes did_emsg, got_int, and did_throw pending for |
1146 * restored at the ":endtry". Reset them here and set the ACTIVE and | 1149 * being restored at the ":endtry". Reset them here and set the |
1147 * FINALLY flags, so that the finally clause gets executed. This | 1150 * ACTIVE and FINALLY flags, so that the finally clause gets executed. |
1148 * includes the case where a missing ":endif" or ":endwhile" was | 1151 * This includes the case where a missing ":endif", ":endwhile" or |
1149 * detected by the ":finally" itself. | 1152 * ":endfor" was detected by the ":finally" itself. |
1150 */ | 1153 */ |
1151 if (cstack.cs_had_finally) | 1154 if (cstack.cs_lflags & CSL_HAD_FINA) |
1152 { | 1155 { |
1153 cstack.cs_had_finally = FALSE; | 1156 cstack.cs_lflags &= ~CSL_HAD_FINA; |
1154 report_make_pending(cstack.cs_pending[cstack.cs_idx] & | 1157 report_make_pending(cstack.cs_pending[cstack.cs_idx] |
1155 (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW), | 1158 & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW), |
1156 did_throw ? (void *)current_exception : NULL); | 1159 did_throw ? (void *)current_exception : NULL); |
1157 did_emsg = got_int = did_throw = FALSE; | 1160 did_emsg = got_int = did_throw = FALSE; |
1158 cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY; | 1161 cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY; |
1159 } | 1162 } |
1160 | 1163 |
1181 * Continue executing command lines when: | 1184 * Continue executing command lines when: |
1182 * - no CTRL-C typed, no aborting error, no exception thrown or try | 1185 * - no CTRL-C typed, no aborting error, no exception thrown or try |
1183 * conditionals need to be checked for executing finally clauses or | 1186 * conditionals need to be checked for executing finally clauses or |
1184 * catching an interrupt exception | 1187 * catching an interrupt exception |
1185 * - didn't get an error message or lines are not typed | 1188 * - didn't get an error message or lines are not typed |
1186 * - there is a command after '|', inside a :if, :while, or :try, or | 1189 * - there is a command after '|', inside a :if, :while, :for or :try, or |
1187 * looping for ":source" command or function call. | 1190 * looping for ":source" command or function call. |
1188 */ | 1191 */ |
1189 while (!((got_int | 1192 while (!((got_int |
1190 #ifdef FEAT_EVAL | 1193 #ifdef FEAT_EVAL |
1191 || (did_emsg && force_abort) || did_throw | 1194 || (did_emsg && force_abort) || did_throw |
1223 { | 1226 { |
1224 if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY) | 1227 if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY) |
1225 EMSG(_(e_endtry)); | 1228 EMSG(_(e_endtry)); |
1226 else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE) | 1229 else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE) |
1227 EMSG(_(e_endwhile)); | 1230 EMSG(_(e_endwhile)); |
1231 else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR) | |
1232 EMSG(_(e_endfor)); | |
1228 else | 1233 else |
1229 EMSG(_(e_endif)); | 1234 EMSG(_(e_endif)); |
1230 } | 1235 } |
1231 | 1236 |
1232 /* | 1237 /* |
1235 * conditional is in its finally clause, ignore anything pending. | 1240 * conditional is in its finally clause, ignore anything pending. |
1236 * If it is in a catch clause, finish the caught exception. | 1241 * If it is in a catch clause, finish the caught exception. |
1237 */ | 1242 */ |
1238 do | 1243 do |
1239 cstack.cs_idx = cleanup_conditionals(&cstack, 0, TRUE); | 1244 cstack.cs_idx = cleanup_conditionals(&cstack, 0, TRUE); |
1240 while (--cstack.cs_idx >= 0); | 1245 while (--cstack.cs_idx >= 0) |
1246 ; | |
1241 trylevel = initial_trylevel; | 1247 trylevel = initial_trylevel; |
1242 } | 1248 } |
1243 | 1249 |
1244 /* If a missing ":endtry", ":endwhile", or ":endif" or a memory lack | 1250 /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory |
1245 * was reported above and the error message is to be converted to an | 1251 * lack was reported above and the error message is to be converted to an |
1246 * exception, do this now after rewinding the cstack. */ | 1252 * exception, do this now after rewinding the cstack. */ |
1247 do_errthrow(&cstack, getline_equal(getline, cookie, get_func_line) | 1253 do_errthrow(&cstack, getline_equal(getline, cookie, get_func_line) |
1248 ? (char_u *)"endfunction" : (char_u *)NULL); | 1254 ? (char_u *)"endfunction" : (char_u *)NULL); |
1249 | 1255 |
1250 if (trylevel == 0) | 1256 if (trylevel == 0) |
1421 return retval; | 1427 return retval; |
1422 } | 1428 } |
1423 | 1429 |
1424 #ifdef FEAT_EVAL | 1430 #ifdef FEAT_EVAL |
1425 /* | 1431 /* |
1426 * Obtain a line when inside a ":while" loop. | 1432 * Obtain a line when inside a ":while" or ":for" loop. |
1427 */ | 1433 */ |
1428 static char_u * | 1434 static char_u * |
1429 get_while_line(c, cookie, indent) | 1435 get_loop_line(c, cookie, indent) |
1430 int c; | 1436 int c; |
1431 void *cookie; | 1437 void *cookie; |
1432 int indent; | 1438 int indent; |
1433 { | 1439 { |
1434 struct while_cookie *cp = (struct while_cookie *)cookie; | 1440 struct loop_cookie *cp = (struct loop_cookie *)cookie; |
1435 wcmd_T *wp; | 1441 wcmd_T *wp; |
1436 char_u *line; | 1442 char_u *line; |
1437 | 1443 |
1438 if (cp->current_line + 1 >= cp->lines_gap->ga_len) | 1444 if (cp->current_line + 1 >= cp->lines_gap->ga_len) |
1439 { | 1445 { |
1440 if (cp->repeating) | 1446 if (cp->repeating) |
1441 return NULL; /* trying to read past the ":endwhile" */ | 1447 return NULL; /* trying to read past ":endwhile"/":endfor" */ |
1442 | 1448 |
1443 /* First time inside the ":while": get line normally. */ | 1449 /* First time inside the ":while"/":for": get line normally. */ |
1444 if (cp->getline == NULL) | 1450 if (cp->getline == NULL) |
1445 line = getcmdline(c, 0L, indent); | 1451 line = getcmdline(c, 0L, indent); |
1446 else | 1452 else |
1447 line = cp->getline(c, cp->cookie, indent); | 1453 line = cp->getline(c, cp->cookie, indent); |
1448 if (store_while_line(cp->lines_gap, line) == OK) | 1454 if (store_loop_line(cp->lines_gap, line) == OK) |
1449 ++cp->current_line; | 1455 ++cp->current_line; |
1450 | 1456 |
1451 return line; | 1457 return line; |
1452 } | 1458 } |
1453 | 1459 |
1460 | 1466 |
1461 /* | 1467 /* |
1462 * Store a line in "gap" so that a ":while" loop can execute it again. | 1468 * Store a line in "gap" so that a ":while" loop can execute it again. |
1463 */ | 1469 */ |
1464 static int | 1470 static int |
1465 store_while_line(gap, line) | 1471 store_loop_line(gap, line) |
1466 garray_T *gap; | 1472 garray_T *gap; |
1467 char_u *line; | 1473 char_u *line; |
1468 { | 1474 { |
1469 if (ga_grow(gap, 1) == FAIL) | 1475 if (ga_grow(gap, 1) == FAIL) |
1470 return FAIL; | 1476 return FAIL; |
1473 ++gap->ga_len; | 1479 ++gap->ga_len; |
1474 return OK; | 1480 return OK; |
1475 } | 1481 } |
1476 | 1482 |
1477 /* | 1483 /* |
1478 * Free the lines stored for a ":while" loop. | 1484 * Free the lines stored for a ":while" or ":for" loop. |
1479 */ | 1485 */ |
1480 static void | 1486 static void |
1481 free_cmdlines(gap) | 1487 free_cmdlines(gap) |
1482 garray_T *gap; | 1488 garray_T *gap; |
1483 { | 1489 { |
1488 } | 1494 } |
1489 } | 1495 } |
1490 #endif | 1496 #endif |
1491 | 1497 |
1492 /* | 1498 /* |
1493 * If "getline" is get_while_line(), return TRUE if the getline it uses equals | 1499 * If "getline" is get_loop_line(), return TRUE if the getline it uses equals |
1494 * "func". * Otherwise return TRUE when "getline" equals "func". | 1500 * "func". * Otherwise return TRUE when "getline" equals "func". |
1495 */ | 1501 */ |
1496 /*ARGSUSED*/ | 1502 /*ARGSUSED*/ |
1497 int | 1503 int |
1498 getline_equal(getline, cookie, func) | 1504 getline_equal(getline, cookie, func) |
1500 void *cookie; /* argument for getline() */ | 1506 void *cookie; /* argument for getline() */ |
1501 char_u *(*func) __ARGS((int, void *, int)); | 1507 char_u *(*func) __ARGS((int, void *, int)); |
1502 { | 1508 { |
1503 #ifdef FEAT_EVAL | 1509 #ifdef FEAT_EVAL |
1504 char_u *(*gp) __ARGS((int, void *, int)); | 1510 char_u *(*gp) __ARGS((int, void *, int)); |
1505 struct while_cookie *cp; | 1511 struct loop_cookie *cp; |
1506 | 1512 |
1507 /* When "getline" is "get_while_line()" use the "cookie" to find the | 1513 /* When "getline" is "get_loop_line()" use the "cookie" to find the |
1508 * function that's orignally used to obtain the lines. This may be nested | 1514 * function that's orignally used to obtain the lines. This may be nested |
1509 * several levels. */ | 1515 * several levels. */ |
1510 gp = getline; | 1516 gp = getline; |
1511 cp = (struct while_cookie *)cookie; | 1517 cp = (struct loop_cookie *)cookie; |
1512 while (gp == get_while_line) | 1518 while (gp == get_loop_line) |
1513 { | 1519 { |
1514 gp = cp->getline; | 1520 gp = cp->getline; |
1515 cp = cp->cookie; | 1521 cp = cp->cookie; |
1516 } | 1522 } |
1517 return gp == func; | 1523 return gp == func; |
1520 #endif | 1526 #endif |
1521 } | 1527 } |
1522 | 1528 |
1523 #if defined(FEAT_EVAL) || defined(FEAT_MBYTE) || defined(PROTO) | 1529 #if defined(FEAT_EVAL) || defined(FEAT_MBYTE) || defined(PROTO) |
1524 /* | 1530 /* |
1525 * If "getline" is get_while_line(), return the cookie used by the original | 1531 * If "getline" is get_loop_line(), return the cookie used by the original |
1526 * getline function. Otherwise return "cookie". | 1532 * getline function. Otherwise return "cookie". |
1527 */ | 1533 */ |
1528 /*ARGSUSED*/ | 1534 /*ARGSUSED*/ |
1529 void * | 1535 void * |
1530 getline_cookie(getline, cookie) | 1536 getline_cookie(getline, cookie) |
1531 char_u *(*getline) __ARGS((int, void *, int)); | 1537 char_u *(*getline) __ARGS((int, void *, int)); |
1532 void *cookie; /* argument for getline() */ | 1538 void *cookie; /* argument for getline() */ |
1533 { | 1539 { |
1534 # ifdef FEAT_EVAL | 1540 # ifdef FEAT_EVAL |
1535 char_u *(*gp) __ARGS((int, void *, int)); | 1541 char_u *(*gp) __ARGS((int, void *, int)); |
1536 struct while_cookie *cp; | 1542 struct loop_cookie *cp; |
1537 | 1543 |
1538 /* When "getline" is "get_while_line()" use the "cookie" to find the | 1544 /* When "getline" is "get_loop_line()" use the "cookie" to find the |
1539 * cookie that's orignally used to obtain the lines. This may be nested | 1545 * cookie that's orignally used to obtain the lines. This may be nested |
1540 * several levels. */ | 1546 * several levels. */ |
1541 gp = getline; | 1547 gp = getline; |
1542 cp = (struct while_cookie *)cookie; | 1548 cp = (struct loop_cookie *)cookie; |
1543 while (gp == get_while_line) | 1549 while (gp == get_loop_line) |
1544 { | 1550 { |
1545 gp = cp->getline; | 1551 gp = cp->getline; |
1546 cp = cp->cookie; | 1552 cp = cp->cookie; |
1547 } | 1553 } |
1548 return cp; | 1554 return cp; |
2371 switch (ea.cmdidx) | 2377 switch (ea.cmdidx) |
2372 { | 2378 { |
2373 /* commands that need evaluation */ | 2379 /* commands that need evaluation */ |
2374 case CMD_while: | 2380 case CMD_while: |
2375 case CMD_endwhile: | 2381 case CMD_endwhile: |
2382 case CMD_for: | |
2383 case CMD_endfor: | |
2376 case CMD_if: | 2384 case CMD_if: |
2377 case CMD_elseif: | 2385 case CMD_elseif: |
2378 case CMD_else: | 2386 case CMD_else: |
2379 case CMD_endif: | 2387 case CMD_endif: |
2380 case CMD_try: | 2388 case CMD_try: |
3466 #ifdef FEAT_EVAL | 3474 #ifdef FEAT_EVAL |
3467 case CMD_let: | 3475 case CMD_let: |
3468 case CMD_if: | 3476 case CMD_if: |
3469 case CMD_elseif: | 3477 case CMD_elseif: |
3470 case CMD_while: | 3478 case CMD_while: |
3479 case CMD_for: | |
3471 case CMD_echo: | 3480 case CMD_echo: |
3472 case CMD_echon: | 3481 case CMD_echon: |
3473 case CMD_execute: | 3482 case CMD_execute: |
3474 case CMD_echomsg: | 3483 case CMD_echomsg: |
3475 case CMD_echoerr: | 3484 case CMD_echoerr: |