Dear Vim developers, I noticed certain cases which cause Vim's indentation for awk to go into an infinite loop. The problem appears when there is a negative brace balance, i.e. more closing braces than opening braces. This can easily happen if one uses a regexp to match a closing brace. Vim then moves upward through the file to find the corresponding opening brace, which does not exist. The loop is missing a break condition for the case that line 0 has been reached. I added it in my patch.
You see for yourself by opening the attached demo.awk and inserting a line below "match". Additionally, I think that strings and computed regexps should not be scanned for matching braces at all when it comes to determining the indentation. I changed the Get_brace_balance function to strip "..." and /.../ while taking into account escape characters. I am novice in writing Vim script and I'd be glad if somebody found a more elegant way of doing this but at least it seems to give proper indentation now. The attached patch should apply to the current version of indent/awk.vim. Cheers, Philipp
{
match($0, /[^)]/)
}
--- old/awk.vim 2011-04-02 00:42:52.251063401 +0200
+++ new/awk.vim 2011-04-02 01:49:50.172678039 +0200
@@ -120,6 +120,12 @@
if prev_data =~ ')' && brace_balance < 0
while brace_balance != 0
let prev_lineno = s:Get_prev_line( prev_lineno )
+ if prev_lineno <= 0
+ " If we reach the start of the file, some parentheses were
+ " misinterpreted probably. We should leave the otherwise infinite
+ " loop and do a failsafe indentation.
+ return 0
+ endif
let prev_data = getline( prev_lineno )
let brace_balance=brace_balance+s:Get_brace_balance(prev_data,'(',')' )
endwhile
@@ -150,8 +156,12 @@
" across multiple lines.
function! s:Get_brace_balance( line, b_open, b_close )
- let line2 = substitute( a:line, a:b_open, "", "g" )
- let openb = strlen( a:line ) - strlen( line2 )
+ " Remove escaped \, /, and "
+ let line = substitute( a:line, '\\\\\|\\/\|\\\"', '', 'g')
+ " Remove strings and computed regexps first to prevent incorrect matches.
+ let line = substitute( line, '/[^/]*/\|"[^/]*"', '', 'g')
+ let line2 = substitute( line, a:b_open, "", "g" )
+ let openb = strlen( line ) - strlen( line2 )
let line3 = substitute( line2, a:b_close, "", "g" )
let closeb = strlen( line2 ) - strlen( line3 )
return openb - closeb
signature.asc
Description: Digital signature
