@@ -96,7 +96,90 @@ func (p *CTagsParser) prototypeAndCodeDontMatch(tag *types.CTag) bool {
9696 prototype := removeSpacesAndTabs (tag .Prototype )
9797 prototype = removeTralingSemicolon (prototype )
9898
99- return strings .Index (code , prototype ) == - 1
99+ // Prototype matches exactly with the code?
100+ ret := strings .Index (code , prototype )
101+
102+ if ret == - 1 {
103+ // If the definition is multiline ctags uses the function name as line number
104+ // Try to match functions in the form
105+ // void
106+ // foo() {}
107+
108+ // Add to code n non-whitespace non-comments tokens before the code line
109+
110+ code = removeEverythingAfterClosingRoundBracket (code )
111+ // Get how many characters are "missing"
112+ n := strings .Index (prototype , code )
113+ // Add these characters to "code" string
114+ code = getFunctionProtoWithNPreviousCharacters (tag , code , n )
115+ // Check again for perfect matching
116+ ret = strings .Index (code , prototype )
117+ }
118+
119+ return ret == - 1
120+ }
121+
122+ func removeEverythingAfterClosingRoundBracket (s string ) string {
123+ n := strings .Index (s , ")" )
124+ return s [0 : n + 1 ]
125+ }
126+
127+ func getFunctionProtoWithNPreviousCharacters (tag * types.CTag , code string , n int ) string {
128+
129+ /* FIXME I'm ugly */
130+ expectedPrototypeLen := len (code ) + n
131+
132+ file , err := os .Open (tag .Filename )
133+ if err == nil {
134+ defer file .Close ()
135+
136+ scanner := bufio .NewScanner (file )
137+ line := 0
138+ multilinecomment := false
139+ var textBuffer []string
140+
141+ // buffer lines until we get to the start of this tag
142+ for scanner .Scan () && line < (tag .Line - 1 ) {
143+ line ++
144+ text := scanner .Text ()
145+ textBuffer = append (textBuffer , text )
146+ }
147+
148+ for line > 0 && len (code ) < expectedPrototypeLen {
149+
150+ line = line - 1
151+ text := textBuffer [line ]
152+
153+ // Remove C++ style comments
154+ if strings .Index (text , "//" ) != - 1 {
155+ text = text [0 :strings .Index (text , "//" )]
156+ }
157+
158+ // Remove C style comments
159+ if strings .Index (text , "*/" ) != - 1 {
160+ if strings .Index (text , "/*" ) != - 1 {
161+ // C style comments on the same line
162+ text = text [0 :strings .Index (text , "/*" )] + text [strings .Index (text , "*/" )+ 1 :len (text )- 1 ]
163+ } else {
164+ text = text [strings .Index (text , "*/" )+ 1 : len (text )- 1 ]
165+ multilinecomment = true
166+ }
167+ }
168+
169+ if multilinecomment {
170+ if strings .Index (text , "/*" ) != - 1 {
171+ text = text [0 :strings .Index (text , "/*" )]
172+ multilinecomment = false
173+ } else {
174+ text = ""
175+ }
176+ }
177+
178+ code = text + code
179+ code = removeSpacesAndTabs (code )
180+ }
181+ }
182+ return code
100183}
101184
102185/* This function scans the source files searching for "extern C" context
0 commit comments