# HG changeset patch # User vimboss # Date 1104963377 0 # Node ID 388f285bda1b095e325f06bdcc62319d07c9352d # Parent 1154524da1cd64726f3c67a529a51daa487e8718 updated for version 7.0031 diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.0aa. Last change: 2005 Jan 04 +*eval.txt* For Vim version 7.0aa. Last change: 2005 Jan 05 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2774,6 +2774,7 @@ string({expr}) Return {expr} converted t String identical Number decimal representation Funcref name of the function + List "[item, item]" form *strlen()* strlen({expr}) The result is a Number, which is the length of the String @@ -3619,29 +3620,69 @@ 7. Commands *expression-commands* as long as {expr1} evaluates to non-zero. When an error is detected from a command inside the loop, execution continues after the "endwhile". - + Example: > + :let lnum = 1 + :while lnum <= line("$") + :call FixLine(lnum) + :let lnum = lnum + 1 + :endwhile +< NOTE: The ":append" and ":insert" commands don't work - properly inside a ":while" loop. - + properly inside a :while" and ":for" loop. + +:for {var} in {list} *:for* +:endfo[r] *:endfo* *:endfor* + Repeat the commands between ":for" and ":endfor" for + each item in {list}. {var} is set to the value of the + item. + When an error is detected from a command inside the + loop, execution continues after the "endfor". + A copy of {list} is made, so that it cannot change + while executing the commands. Example (an inefficient + way to make a list empty): > + :for a in mylist + :call remove(mylist, 0) + :endfor +< Note that the type of each list item should be + identical to avoid errors for the type of {var} + changing. Unlet the variable at the end of the loop + to allow multiple item types. + +:for {var} in {string} +:endfo[r] Like ":for" above, but use each character in {string} + as a list item. + Composing characters are used as separate characters. + A Number is first converted to a String. + +:for [{var1}, {var2}, ...] in {listlist} +:endfo[r] + Like ":for" above, but each item in {listlist} must be + a list, of which each item is assigned to {var1}, + {var2}, etc. Example: > + :for [lnum, col] in [[1, 3], [2, 5], [3, 8]] + :echo getline(lnum)[col] + :endfor +< *:continue* *:con* *E586* -:con[tinue] When used inside a ":while", jumps back to the - ":while". If it is used after a |:try| inside the - ":while" but before the matching |:finally| (if - present), the commands following the ":finally" up to - the matching |:endtry| are executed first. This - process applies to all nested ":try"s inside the - ":while". The outermost ":endtry" then jumps back to - the ":while". +:con[tinue] When used inside a ":while" or ":for" loop, jumps back + to the start of the loop. + If it is used after a |:try| inside the loop but + before the matching |:finally| (if present), the + commands following the ":finally" up to the matching + |:endtry| are executed first. This process applies to + all nested ":try"s inside the loop. The outermost + ":endtry" then jumps back to the start of the loop. *:break* *:brea* *E587* -:brea[k] When used inside a ":while", skips to the command - after the matching ":endwhile". If it is used after - a |:try| inside the ":while" but before the matching - |:finally| (if present), the commands following the - ":finally" up to the matching |:endtry| are executed - first. This process applies to all nested ":try"s - inside the ":while". The outermost ":endtry" then - jumps to the command after the ":endwhile". +:brea[k] When used inside a ":while" or ":for" loop, skips to + the command after the matching ":endwhile" or + ":endfor". + If it is used after a |:try| inside the loop but + before the matching |:finally| (if present), the + commands following the ":finally" up to the matching + |:endtry| are executed first. This process applies to + all nested ":try"s inside the loop. The outermost + ":endtry" then jumps to the command after the loop. :try *:try* *:endt* *:endtry* *E600* *E601* *E602* :endt[ry] Change the error handling for the commands between diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.0aa. Last change: 2004 Dec 24 +*options.txt* For Vim version 7.0aa. Last change: 2005 Jan 05 VIM REFERENCE MANUAL by Bram Moolenaar @@ -5019,7 +5019,8 @@ A jump table for the options with a shor folds manually created folds, opened/closed folds and local fold options globals global variables that start with an uppercase letter - and contain at least one lowercase letter. + and contain at least one lowercase letter. Only + String and Number types are stored. help the help window localoptions options and mappings local to a window or buffer (not global values for local options) @@ -6410,7 +6411,8 @@ A jump table for the options with a shor ! When included, save and restore global variables that start with an uppercase letter, and don't contain a lowercase letter. Thus "KEEPTHIS and "K_L_M" are stored, but "KeepThis" - and "_K_L_M" are not. + and "_K_L_M" are not. Only String and Number types are + stored. " Maximum number of lines saved for each register. Old name of the '<' item, with the disadvantage that you need to put a backslash before the ", otherwise it will be recognized as the diff --git a/runtime/doc/tags b/runtime/doc/tags --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1883,6 +1883,8 @@ 90.5 usr_90.txt /*90.5* :emenu gui.txt /*:emenu* :en eval.txt /*:en* :endf eval.txt /*:endf* +:endfo eval.txt /*:endfo* +:endfor eval.txt /*:endfor* :endfunction eval.txt /*:endfunction* :endif eval.txt /*:endif* :endt eval.txt /*:endt* @@ -1934,6 +1936,7 @@ 90.5 usr_90.txt /*90.5* :folddoopen fold.txt /*:folddoopen* :foldo fold.txt /*:foldo* :foldopen fold.txt /*:foldopen* +:for eval.txt /*:for* :fu eval.txt /*:fu* :function eval.txt /*:function* :g repeat.txt /*:g* @@ -2039,6 +2042,7 @@ 90.5 usr_90.txt /*90.5* :let-option eval.txt /*:let-option* :let-register eval.txt /*:let-register* :let-star eval.txt /*:let-star* +:let-unpack eval.txt /*:let-unpack* :list various.txt /*:list* :lm map.txt /*:lm* :lmap map.txt /*:lmap* @@ -5298,6 +5302,7 @@ linewise motion.txt /*linewise* linewise-register change.txt /*linewise-register* linewise-visual visual.txt /*linewise-visual* lispindent() eval.txt /*lispindent()* +list-index eval.txt /*list-index* list-repeat windows.txt /*list-repeat* lite-syntax syntax.txt /*lite-syntax* lite.vim syntax.txt /*lite.vim* @@ -5871,6 +5876,7 @@ remote_foreground() eval.txt /*remote_fo remote_peek() eval.txt /*remote_peek()* remote_read() eval.txt /*remote_read()* remote_send() eval.txt /*remote_send()* +remove() eval.txt /*remove()* remove-filetype filetype.txt /*remove-filetype* remove-option-flags options.txt /*remove-option-flags* rename() eval.txt /*rename()* diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -6236,9 +6236,11 @@ ins_esc(count, cmdchar) { /* * Don't append the ESC for "r" and "grx". + * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for + * when "count" is non-zero. */ if (cmdchar != 'r' && cmdchar != 'v') - AppendToRedobuff(ESC_STR); + AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); /* * Repeating insert may take a long time. Check for diff --git a/src/ex_eval.c b/src/ex_eval.c --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -17,6 +17,7 @@ static void free_msglist __ARGS((struct msglist *l)); static int throw_exception __ARGS((void *, int, char_u *)); +static char_u *get_end_emsg __ARGS((struct condstack *cstack)); static void rewind_conditionals __ARGS((struct condstack *, int, int, int *)); @@ -863,7 +864,7 @@ ex_endif(eap) did_endif = TRUE; if (eap->cstack->cs_idx < 0 || (eap->cstack->cs_flags[eap->cstack->cs_idx] & - (CSF_WHILE | CSF_TRY))) + (CSF_WHILE | CSF_FOR | CSF_TRY))) eap->errmsg = (char_u *)N_("E580: :endif without :if"); else { @@ -904,7 +905,8 @@ ex_else(eap) && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); if (cstack->cs_idx < 0 - || (cstack->cs_flags[cstack->cs_idx] & (CSF_WHILE | CSF_TRY))) + || (cstack->cs_flags[cstack->cs_idx] + & (CSF_WHILE | CSF_FOR | CSF_TRY))) { if (eap->cmdidx == CMD_else) { @@ -976,7 +978,7 @@ ex_else(eap) } /* - * Handle ":while". + * Handle ":while" and ":for". */ void ex_while(eap) @@ -988,45 +990,87 @@ ex_while(eap) struct condstack *cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) - eap->errmsg = (char_u *)N_("E585: :while nesting too deep"); + eap->errmsg = (char_u *)N_("E585: :while/:for nesting too deep"); else { /* - * cs_had_while is set when we have jumped back from the matching - * ":endwhile". When not set, need to initialise this cstack entry. + * The loop flag is set when we have jumped back from the matching + * ":endwhile" or ":endfor". When not set, need to initialise this + * cstack entry. */ - if (!cstack->cs_had_while) + if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0) { ++cstack->cs_idx; - ++cstack->cs_whilelevel; + ++cstack->cs_looplevel; cstack->cs_line[cstack->cs_idx] = -1; } - cstack->cs_flags[cstack->cs_idx] = CSF_WHILE; + cstack->cs_flags[cstack->cs_idx] = + eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; /* - * Don't do something after an error, interrupt, or throw, or when there - * is a surrounding conditional and it was not active. + * Don't do something after an error, interrupt, or throw, or when + * there is a surrounding conditional and it was not active. */ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0 && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); - result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + if (eap->cmdidx == CMD_while) + { + /* + * ":while bool-expr" + */ + result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + } + else + { + void *fi; + + /* + * ":for var in list-expr" + */ + if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) + { + /* Jumping here from a ":continue" or ":endfor": use the + * previously evaluated list. */ + fi = cstack->cs_fors[cstack->cs_idx]; + error = FALSE; + } + else + { + /* Evaluate the argument and get the info in a structure. */ + fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip); + cstack->cs_fors[cstack->cs_idx] = fi; + } + + /* use the element at the start of the list and advance */ + if (!error && fi != NULL && !skip) + result = next_for_item(fi, eap->arg); + else + result = FALSE; + + if (!result) + { + free_for_info(fi); + cstack->cs_fors[cstack->cs_idx] = NULL; + } + } /* - * If this cstack entry was just initialised and is active, set - * cs_had_while flag, so do_cmdline() will set the line number - * in cs_line[]. + * If this cstack entry was just initialised and is active, set the + * loop flag, so do_cmdline() will set the line number in cs_line[]. + * If executing the command a second time, clear the loop flag. */ if (!skip && !error && result) { - cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE; - cstack->cs_had_while = !cstack->cs_had_while; + cstack->cs_flags[cstack->cs_idx] |= (CSF_ACTIVE | CSF_TRUE); + cstack->cs_lflags ^= CSL_HAD_LOOP; } else { - cstack->cs_had_while = FALSE; - /* If the ":while" evaluates to FALSE, show the debug prompt at the - * ":endwhile" as if there was a ":break" in a ":while" evaluating - * to TRUE. */ + cstack->cs_lflags &= ~CSL_HAD_LOOP; + /* If the ":while" evaluates to FALSE or ":for" is past the end of + * the list, show the debug prompt at the ":endwhile"/":endfor" as + * if there was a ":break" in a ":while"/":for" evaluating to + * TRUE. */ if (!skip && !error) cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE; } @@ -1043,25 +1087,25 @@ ex_continue(eap) int idx; struct condstack *cstack = eap->cstack; - if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) - eap->errmsg = (char_u *)N_("E586: :continue without :while"); + if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) + eap->errmsg = (char_u *)N_("E586: :continue without :while or :for"); else { /* Try to find the matching ":while". This might stop at a try * conditional not in its finally clause (which is then to be executed * next). Therefor, inactivate all conditionals except the ":while" * itself (if reached). */ - idx = cleanup_conditionals(cstack, CSF_WHILE, FALSE); - if ((cstack->cs_flags[idx] & CSF_WHILE)) + idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); + if ((cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR))) { if (cstack->cs_idx > idx) rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); /* - * Set cs_had_continue, so do_cmdline() will jump back to the + * Set CSL_HAD_CONT, so do_cmdline() will jump back to the * matching ":while". */ - cstack->cs_had_continue = TRUE; /* let do_cmdline() handle it */ + cstack->cs_lflags |= CSL_HAD_CONT; /* let do_cmdline() handle it */ } else { @@ -1083,16 +1127,16 @@ ex_break(eap) int idx; struct condstack *cstack = eap->cstack; - if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) - eap->errmsg = (char_u *)N_("E587: :break without :while"); + if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) + eap->errmsg = (char_u *)N_("E587: :break without :while or :for"); else { /* Inactivate conditionals until the matching ":while" or a try * conditional not in its finally clause (which is then to be * executed next) is found. In the latter case, make the ":break" * pending for execution at the ":endtry". */ - idx = cleanup_conditionals(cstack, CSF_WHILE, TRUE); - if (!(cstack->cs_flags[idx] & CSF_WHILE)) + idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, TRUE); + if (!(cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR))) { cstack->cs_pending[idx] = CSTP_BREAK; report_make_pending(CSTP_BREAK, NULL); @@ -1101,53 +1145,72 @@ ex_break(eap) } /* - * ":endwhile" + * ":endwhile" and ":endfor" */ void ex_endwhile(eap) exarg_T *eap; { struct condstack *cstack = eap->cstack; - int idx; + int idx; + char_u *err; + int csf; + int fl; - if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) - eap->errmsg = e_while; + if (eap->cmdidx == CMD_endwhile) + { + err = e_while; + csf = CSF_WHILE; + } + else + { + err = e_for; + csf = CSF_FOR; + } + + if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) + eap->errmsg = err; else { - if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)) + fl = cstack->cs_flags[cstack->cs_idx]; + if (!(fl & csf)) { + if (fl & CSF_WHILE) + eap->errmsg = (char_u *)_("E999: Using :endfor with :while"); + else if (fl & CSF_FOR) + eap->errmsg = (char_u *)_("E999: Using :endwhile with :for"); + else if (!(fl & CSF_TRY)) + eap->errmsg = e_endif; + else if (fl & CSF_FINALLY) + eap->errmsg = e_endtry; /* Try to find the matching ":while" and report what's missing. */ - if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) - eap->errmsg = e_endif; - else if (cstack->cs_flags[cstack->cs_idx] & CSF_FINALLY) - eap->errmsg = e_endtry; for (idx = cstack->cs_idx; idx > 0; --idx) { - if ((cstack->cs_flags[idx] & CSF_TRY) - && !(cstack->cs_flags[idx] & CSF_FINALLY)) + fl = cstack->cs_flags[idx]; + if ((fl & CSF_TRY) && !(fl & CSF_FINALLY)) { /* Give up at a try conditional not in its finally clause. - * Ignore the ":endwhile". */ - eap->errmsg = e_while; + * Ignore the ":endwhile"/":endfor". */ + eap->errmsg = err; return; } - if (cstack->cs_flags[idx] & CSF_WHILE) + if (fl & csf) break; } /* Cleanup and rewind all contained (and unclosed) conditionals. */ - (void)cleanup_conditionals(cstack, CSF_WHILE, FALSE); + (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE); rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); } /* * When debugging or a breakpoint was encountered, display the debug * prompt (if not already done). This shows the user that an - * ":enwhile" is executed when the ":while" was not TRUE or after - * a ":break". Handle a ">quit" debug command as if an interrupt - * had occurred before the ":endwhile". That is, throw an interrupt - * exception if appropriate. Doing this here prevents that an - * exception for a parsing error is discarded when throwing the - * interrupt exception later on. + * ":endwhile"/":endfor" is executed when the ":while" was not TRUE or + * after a ":break". Handle a ">quit" debug command as if an + * interrupt had occurred before the ":endwhile"/":endfor". That is, + * throw an interrupt exception if appropriate. Doing this here + * prevents that an exception for a parsing error is discarded when + * throwing the interrupt exception later on. */ else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE) @@ -1155,10 +1218,10 @@ ex_endwhile(eap) (void)do_intthrow(cstack); /* - * Set cs_had_endwhile, so do_cmdline() will jump back to the matching - * ":while". + * Set loop flag, so do_cmdline() will jump back to the matching + * ":while" or ":for". */ - cstack->cs_had_endwhile = TRUE; + cstack->cs_lflags |= CSL_HAD_ENDLOOP; } } @@ -1372,10 +1435,7 @@ ex_catch(eap) { /* Report what's missing if the matching ":try" is not in its * finally clause. */ - if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) - eap->errmsg = e_endwhile; - else - eap->errmsg = e_endif; + eap->errmsg = get_end_emsg(cstack); skip = TRUE; } for (idx = cstack->cs_idx; idx > 0; --idx) @@ -1389,7 +1449,8 @@ ex_catch(eap) give_up = TRUE; } else if (cstack->cs_idx > idx) - rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); + rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, + &cstack->cs_looplevel); } if (ends_excmd(*eap->arg)) /* no argument, catch all errors */ @@ -1523,11 +1584,7 @@ ex_finally(eap) { if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { - /* Find the matching ":try" and report what's missing. */ - if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) - eap->errmsg = e_endwhile; - else - eap->errmsg = e_endif; + eap->errmsg = get_end_emsg(cstack); for (idx = cstack->cs_idx - 1; idx > 0; --idx) if (cstack->cs_flags[idx] & CSF_TRY) break; @@ -1546,7 +1603,8 @@ ex_finally(eap) return; } if (cstack->cs_idx > idx) - rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); + rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, + &cstack->cs_looplevel); /* * Don't do something when the corresponding try block never got active @@ -1590,11 +1648,12 @@ ex_finally(eap) * got_int is set). The pending values are restored by the * ":endtry", except if there is a new error, interrupt, exception, * ":continue", ":break", ":return", or ":finish" in the following - * finally clause. A missing ":endwhile" or ":endif" detected here - * is treated as if did_emsg and did_throw had already been set, - * respectively in case that the error is not converted to an - * exception, did_throw had already been unset. We must not set - * did_emsg here since that would suppress the error message. + * finally clause. A missing ":endwhile", ":endfor" or ":endif" + * detected here is treated as if did_emsg and did_throw had + * already been set, respectively in case that the error is not + * converted to an exception, did_throw had already been unset. + * We must not set did_emsg here since that would suppress the + * error message. */ if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) { @@ -1617,21 +1676,21 @@ ex_finally(eap) * discarded if the finally clause is left by a ":continue", * ":break", ":return", ":finish", error, interrupt, or another * exception. When emsg() is called for a missing ":endif" or - * a missing ":endwhile" detected here, the exception will be - * discarded. */ + * a missing ":endwhile"/":endfor" detected here, the + * exception will be discarded. */ if (did_throw && cstack->cs_exception[cstack->cs_idx] != current_exception) EMSG(_(e_internal)); } /* - * Set cs_had_finally, so do_cmdline() will reset did_emsg, + * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, * got_int, and did_throw and make the finally clause active. * This will happen after emsg() has been called for a missing - * ":endif" or a missing ":endwhile" detected here, so that the - * following finally clause will be executed even then. + * ":endif" or a missing ":endwhile"/":endfor" detected here, so + * that the following finally clause will be executed even then. */ - cstack->cs_had_finally = TRUE; + cstack->cs_lflags |= CSL_HAD_FINA; } } } @@ -1670,16 +1729,14 @@ ex_endtry(eap) if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) { + eap->errmsg = get_end_emsg(cstack); /* Find the matching ":try" and report what's missing. */ - if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) - eap->errmsg = e_endwhile; - else - eap->errmsg = e_endif; idx = cstack->cs_idx; do --idx; while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); - rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); + rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, + &cstack->cs_looplevel); skip = TRUE; /* @@ -1977,15 +2034,16 @@ leave_cleanup(csp) * Make conditionals inactive and discard what's pending in finally clauses * until the conditional type searched for or a try conditional not in its * finally clause is reached. If this is in an active catch clause, finish the - * caught exception. Return the cstack index where the search stopped. Values - * used for "searched_cond" are CSF_WHILE or CSF_TRY or 0, the latter meaning - * the innermost try conditional not in its finally clause. "inclusive" tells - * whether the conditional searched for should be made inactive itself (a try - * conditional not in its finally claused possibly find before is always made - * inactive). If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT, - * the saved former value of "emsg_silent", if reset when the try conditional - * finally reached was entered, is restored (unsed by ex_endtry()). This is - * normally done only when such a try conditional is left. + * caught exception. Return the cstack index where the search stopped. + * Values used for "searched_cond" are (CSF_WHILE | CSF_FOR) or CSF_TRY or 0, + * the latter meaning the innermost try conditional not in its finally clause. + * "inclusive" tells whether the conditional searched for should be made + * inactive itself (a try conditional not in its finally claused possibly find + * before is always made inactive). If "inclusive" is TRUE and + * "searched_cond" is CSF_TRY|CSF_SILENT, the saved former value of + * "emsg_silent", if reset when the try conditional finally reached was + * entered, is restored (unsed by ex_endtry()). This is normally done only + * when such a try conditional is left. */ int cleanup_conditionals(cstack, searched_cond, inclusive) @@ -2109,6 +2167,21 @@ cleanup_conditionals(cstack, searched_co } /* + * Return an appropriate error message for a missing endwhile/endfor/endif. + */ + static char_u * +get_end_emsg(cstack) + struct condstack *cstack; +{ + if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) + return e_endwhile; + if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) + return e_endfor; + return e_endif; +} + + +/* * Rewind conditionals until index "idx" is reached. "cond_type" and * "cond_level" specify a conditional type and the address of a level variable * which is to be decremented with each skipped conditional of the specified @@ -2141,16 +2214,17 @@ ex_endfunction(eap) } /* - * Return TRUE if the string "p" looks like a ":while" command. + * Return TRUE if the string "p" looks like a ":while" or ":for" command. */ int -has_while_cmd(p) +has_loop_cmd(p) char_u *p; { p = skipwhite(p); while (*p == ':') p = skipwhite(p + 1); - if (p[0] == 'w' && p[1] == 'h') + if ((p[0] == 'w' && p[1] == 'h') + || (p[0] == 'f' && p[1] == 'o' && p[2] == 'r')) return TRUE; return FALSE; } diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5459,7 +5459,7 @@ script_get(eap, cmd) { theline = eap->getline( #ifdef FEAT_EVAL - eap->cstack->cs_whilelevel > 0 ? -1 : + eap->cstack->cs_looplevel > 0 ? -1 : #endif NUL, eap->cookie, 0); diff --git a/src/gui_kde.cc b/src/gui_kde.cc --- a/src/gui_kde.cc +++ b/src/gui_kde.cc @@ -241,12 +241,12 @@ gui_mch_add_menu(vimmenu_T *menu, int id { idx++; // for tearoffs to be first in menus me = new QPopupMenu(parent->widget, QSTR(menu->name)); - parent->widget->insertItem(QSTR(menu->name), me, (int)me, idx); + parent->widget->insertItem(QSTR(menu->name), me, (long)me, idx); } else { me = new QPopupMenu(vmw->menuBar(), QSTR(menu->name)); - vmw->menuBar()->insertItem(QSTR(menu->name), me, (int)me, idx); + vmw->menuBar()->insertItem(QSTR(menu->name), me, (long)me, idx); } me->setCaption((const char *)(menu->dname)); @@ -296,7 +296,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, i return; // failed vmw->toolBar()->insertButton( pix, - (int)menu, // id + (long)menu, // id true, QSTR(menu->strings[MENU_INDEX_TIP]), // tooltip or text idx); @@ -311,7 +311,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, i parent->widget->insertSeparator(); return; } - parent->widget->insertItem(QSTR(menu->name), (int)menu, idx); + parent->widget->insertItem(QSTR(menu->name), (long)menu, idx); #endif }//}}} @@ -390,12 +390,12 @@ gui_mch_destroy_menu(vimmenu_T *menu)//{ #ifdef FEAT_TOOLBAR if (menu->parent && menu_is_toolbar(menu->parent->name)) { - vmw->toolBar()->removeItem((int)menu); + vmw->toolBar()->removeItem((long)menu); return; } #endif if (menu->parent) - menu->parent->widget->removeItem((int)menu); + menu->parent->widget->removeItem((long)menu); if (menu->widget) delete menu->widget; menu->widget = 0; diff --git a/src/gui_kde_x11.cc b/src/gui_kde_x11.cc --- a/src/gui_kde_x11.cc +++ b/src/gui_kde_x11.cc @@ -1210,7 +1210,7 @@ gui_mch_menu_grey(vimmenu_T * menu, int { if (!menu || !menu->parent || !menu->parent->widget) return; - menu->parent->widget->setItemEnabled((int)menu, !grey); + menu->parent->widget->setItemEnabled((long)menu, !grey); gui_mch_update(); }//}}} diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -20,6 +20,9 @@ void *save_funccal __ARGS((void)); void restore_funccal __ARGS((void *fc)); int eval_foldexpr __ARGS((char_u *arg, int *cp)); void ex_let __ARGS((exarg_T *eap)); +void *eval_for_line __ARGS((char_u *arg, int *errp, char_u **nextcmdp, int skip)); +int next_for_item __ARGS((void *fi_void, char_u *arg)); +void free_for_info __ARGS((void *fi_void)); void set_context_for_expression __ARGS((expand_T *xp, char_u *arg, cmdidx_T cmdidx)); void ex_call __ARGS((exarg_T *eap)); void ex_unlet __ARGS((exarg_T *eap)); @@ -47,9 +50,9 @@ void ex_function __ARGS((exarg_T *eap)); char_u *get_user_func_name __ARGS((expand_T *xp, int idx)); void ex_delfunction __ARGS((exarg_T *eap)); void ex_return __ARGS((exarg_T *eap)); -int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *value)); -void discard_pending_return __ARGS((void *retvar)); -char_u *get_return_cmd __ARGS((void *retvar)); +int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *rettv)); +void discard_pending_return __ARGS((void *rettv)); +char_u *get_return_cmd __ARGS((void *rettv)); char_u *get_func_line __ARGS((int c, void *cookie, int indent)); int func_has_ended __ARGS((void *cookie)); int func_has_abort __ARGS((void *cookie)); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -595,34 +595,34 @@ struct eslist_elem struct condstack { - char cs_flags[CSTACK_LEN]; /* CSF_ flags */ + short cs_flags[CSTACK_LEN]; /* CSF_ flags */ char cs_pending[CSTACK_LEN]; /* CSTP_: what's pending in ":finally"*/ union { - void *cs_pend_rv[CSTACK_LEN]; /* return typeval for pending return */ - void *cs_pend_ex[CSTACK_LEN]; /* exception for pending throw */ + void *csp_rv[CSTACK_LEN]; /* return typeval for pending return */ + void *csp_ex[CSTACK_LEN]; /* exception for pending throw */ } cs_pend; - int cs_line[CSTACK_LEN]; /* line number of ":while" line */ + void *cs_fors[CSTACK_LEN]; /* info used by ":for" */ + int cs_line[CSTACK_LEN]; /* line nr of ":while"/":for" line */ int cs_idx; /* current entry, or -1 if none */ - int cs_whilelevel; /* number of nested ":while"s */ - int cs_trylevel; /* number of nested ":try"s */ + int cs_looplevel; /* nr of nested ":while"s and ":for"s */ + int cs_trylevel; /* nr of nested ":try"s */ eslist_T *cs_emsg_silent_list; /* saved values of "emsg_silent" */ - char cs_had_while; /* just found ":while" */ - char cs_had_continue; /* just found ":continue" */ - char cs_had_endwhile; /* just found ":endwhile" */ - char cs_had_finally; /* just found ":finally" */ + char cs_lflags; /* loop flags: CSL_ flags */ }; -# define cs_rettv cs_pend.cs_pend_rv -# define cs_exception cs_pend.cs_pend_ex +# define cs_rettv cs_pend.csp_rv +# define cs_exception cs_pend.csp_ex -# define CSF_TRUE 1 /* condition was TRUE */ -# define CSF_ACTIVE 2 /* current state is active */ -# define CSF_ELSE 4 /* ":else" has been passed */ -# define CSF_WHILE 8 /* is a ":while" */ -# define CSF_TRY 16 /* is a ":try" */ -# define CSF_FINALLY 32 /* ":finally" has been passed */ -# define CSF_THROWN 64 /* exception thrown to this try conditional */ -# define CSF_CAUGHT 128 /* exception caught by this try conditional */ -# define CSF_SILENT 4 /* "emsg_silent" reset by ":try" */ +# define CSF_TRUE 0x0001 /* condition was TRUE */ +# define CSF_ACTIVE 0x0002 /* current state is active */ +# define CSF_ELSE 0x0004 /* ":else" has been passed */ +# define CSF_WHILE 0x0008 /* is a ":while" */ +# define CSF_FOR 0x0010 /* is a ":for" */ + +# define CSF_TRY 0x0100 /* is a ":try" */ +# define CSF_FINALLY 0x0200 /* ":finally" has been passed */ +# define CSF_THROWN 0x0400 /* exception thrown to this try conditional */ +# define CSF_CAUGHT 0x0800 /* exception caught by this try conditional */ +# define CSF_SILENT 0x1000 /* "emsg_silent" reset by ":try" */ /* Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset * (an ":if"), and CSF_SILENT is only used when CSF_TRY is set. */ @@ -640,6 +640,14 @@ struct condstack # define CSTP_FINISH 32 /* ":finish" is pending */ /* + * Flags for the cs_lflags item in struct condstack. + */ +# define CSL_HAD_LOOP 1 /* just found ":while" or ":for" */ +# define CSL_HAD_ENDLOOP 2 /* just found ":endwhile" or ":endfor" */ +# define CSL_HAD_CONT 4 /* just found ":continue" */ +# define CSL_HAD_FINA 8 /* just found ":finally" */ + +/* * A list of error messages that can be converted to an exception. "throw_msg" * is only set in the first element of the list. Usually, it points to the * original message stored in that element, but sometimes it points to a later diff --git a/src/version.h b/src/version.h --- a/src/version.h +++ b/src/version.h @@ -36,5 +36,5 @@ #define VIM_VERSION_NODOT "vim70aa" #define VIM_VERSION_SHORT "7.0aa" #define VIM_VERSION_MEDIUM "7.0aa ALPHA" -#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 4)" -#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 4, compiled " +#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 5)" +#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 5, compiled "