1425bb815Sopenharmony_ci#!/usr/bin/tclsh
2425bb815Sopenharmony_ci
3425bb815Sopenharmony_ci# Copyright JS Foundation and other contributors, http://js.foundation
4425bb815Sopenharmony_ci#
5425bb815Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
6425bb815Sopenharmony_ci# you may not use this file except in compliance with the License.
7425bb815Sopenharmony_ci# You may obtain a copy of the License at
8425bb815Sopenharmony_ci#
9425bb815Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
10425bb815Sopenharmony_ci#
11425bb815Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
12425bb815Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS
13425bb815Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14425bb815Sopenharmony_ci# See the License for the specific language governing permissions and
15425bb815Sopenharmony_ci# limitations under the License.
16425bb815Sopenharmony_ci
17425bb815Sopenharmony_ci# switch-case
18425bb815Sopenharmony_ci
19425bb815Sopenharmony_ciforeach fileName [getSourceFileNames] {
20425bb815Sopenharmony_ci    set is_in_comment "no"
21425bb815Sopenharmony_ci    set is_in_pp_define "no"
22425bb815Sopenharmony_ci
23425bb815Sopenharmony_ci    foreach token [getTokens $fileName 1 0 -1 -1 {}] {
24425bb815Sopenharmony_ci        set type [lindex $token 3]
25425bb815Sopenharmony_ci        set lineNumber [lindex $token 1]
26425bb815Sopenharmony_ci
27425bb815Sopenharmony_ci        if {$is_in_comment == "yes"} {
28425bb815Sopenharmony_ci            set is_in_comment "no"
29425bb815Sopenharmony_ci        }
30425bb815Sopenharmony_ci
31425bb815Sopenharmony_ci        if {$type == "newline"} {
32425bb815Sopenharmony_ci            set is_in_pp_define "no"
33425bb815Sopenharmony_ci        } elseif {$type == "ccomment"} {
34425bb815Sopenharmony_ci            set is_in_comment "yes"
35425bb815Sopenharmony_ci        } elseif {[string first "pp_" $type] == 0} {
36425bb815Sopenharmony_ci            if {$type == "pp_define"} {
37425bb815Sopenharmony_ci                set is_in_pp_define "yes"
38425bb815Sopenharmony_ci            }
39425bb815Sopenharmony_ci        } elseif {$type == "space"} {
40425bb815Sopenharmony_ci        } elseif {$type != "eof"} {
41425bb815Sopenharmony_ci            if {$is_in_pp_define == "no" && $type == "switch"} {
42425bb815Sopenharmony_ci                set next_token_start [lindex $token 2]
43425bb815Sopenharmony_ci                incr next_token_start 1
44425bb815Sopenharmony_ci                set line_num 0
45425bb815Sopenharmony_ci                set state "switch"
46425bb815Sopenharmony_ci                set case_block "no"
47425bb815Sopenharmony_ci                set seen_braces 0
48425bb815Sopenharmony_ci                foreach next_token [getTokens $fileName $lineNumber $next_token_start -1 -1 {}] {
49425bb815Sopenharmony_ci                    set next_token_type [lindex $next_token 3]
50425bb815Sopenharmony_ci                    set next_token_value [lindex $next_token 0]
51425bb815Sopenharmony_ci                    if {$state == "switch"} {
52425bb815Sopenharmony_ci                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
53425bb815Sopenharmony_ci                            continue
54425bb815Sopenharmony_ci                        } elseif {$next_token_type == "leftbrace"} {
55425bb815Sopenharmony_ci                            set state "first-case"
56425bb815Sopenharmony_ci                            continue
57425bb815Sopenharmony_ci                        } else {
58425bb815Sopenharmony_ci                            # TODO: check switch
59425bb815Sopenharmony_ci                            continue
60425bb815Sopenharmony_ci                        }
61425bb815Sopenharmony_ci                    } elseif {$state == "first-case"} {
62425bb815Sopenharmony_ci                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
63425bb815Sopenharmony_ci                            continue
64425bb815Sopenharmony_ci                        } elseif {$next_token_type == "case"} {
65425bb815Sopenharmony_ci                            set state "case"
66425bb815Sopenharmony_ci                            continue
67425bb815Sopenharmony_ci                        } elseif {$next_token_type == "default"} {
68425bb815Sopenharmony_ci                            set state "default"
69425bb815Sopenharmony_ci                            continue
70425bb815Sopenharmony_ci                        } else {
71425bb815Sopenharmony_ci                            # Macros magic: give up
72425bb815Sopenharmony_ci                            break
73425bb815Sopenharmony_ci                        }
74425bb815Sopenharmony_ci                    } elseif {$state == "case"} {
75425bb815Sopenharmony_ci                        if {$next_token_type == "space"} {
76425bb815Sopenharmony_ci                            set state "space-after-case"
77425bb815Sopenharmony_ci                            continue
78425bb815Sopenharmony_ci                        } else {
79425bb815Sopenharmony_ci                            report $fileName [lindex $next_token 1] "There should be single space character after 'case' keyword (state $state)"
80425bb815Sopenharmony_ci                        }
81425bb815Sopenharmony_ci                    } elseif {$state == "space-after-case"} {
82425bb815Sopenharmony_ci                        if {$next_token_type != "identifier" && $next_token_type != "intlit" && $next_token_type != "charlit" && $next_token_type != "sizeof"} {
83425bb815Sopenharmony_ci                            report $fileName [lindex $next_token 1] "There should be single space character after 'case' keyword (state $state, next_token_type $next_token_type)"
84425bb815Sopenharmony_ci                        } else {
85425bb815Sopenharmony_ci                            set state "case-label"
86425bb815Sopenharmony_ci                            continue
87425bb815Sopenharmony_ci                        }
88425bb815Sopenharmony_ci                    } elseif {$state == "case-label" || $state == "default"} {
89425bb815Sopenharmony_ci                        set case_block "no"
90425bb815Sopenharmony_ci                        if {$next_token_type != "colon"} {
91425bb815Sopenharmony_ci                            continue
92425bb815Sopenharmony_ci                        } else {
93425bb815Sopenharmony_ci                            set state "colon"
94425bb815Sopenharmony_ci                            continue
95425bb815Sopenharmony_ci                        }
96425bb815Sopenharmony_ci                    } elseif {$state == "after-colon-preprocessor"} {
97425bb815Sopenharmony_ci                      if {$next_token_type == "newline"} {
98425bb815Sopenharmony_ci                          set state "colon"
99425bb815Sopenharmony_ci                      }
100425bb815Sopenharmony_ci                    } elseif {$state == "colon"} {
101425bb815Sopenharmony_ci                        if {$next_token_type == "space" || $next_token_type == "newline"} {
102425bb815Sopenharmony_ci                            continue
103425bb815Sopenharmony_ci                        } elseif {$next_token_type == "ccomment"} {
104425bb815Sopenharmony_ci                            if {[string match "*FALL*" $next_token_value]} {
105425bb815Sopenharmony_ci                                set state "fallthru"
106425bb815Sopenharmony_ci                                set line_num [lindex $next_token 1]
107425bb815Sopenharmony_ci                                continue
108425bb815Sopenharmony_ci                            } else {
109425bb815Sopenharmony_ci                                continue
110425bb815Sopenharmony_ci                            }
111425bb815Sopenharmony_ci                        } elseif {$next_token_type == "case"} {
112425bb815Sopenharmony_ci                            set state "case"
113425bb815Sopenharmony_ci                            continue
114425bb815Sopenharmony_ci                        } elseif {$next_token_type == "default"} {
115425bb815Sopenharmony_ci                            set state "default"
116425bb815Sopenharmony_ci                            continue
117425bb815Sopenharmony_ci                        } elseif {$next_token_type == "leftbrace"} {
118425bb815Sopenharmony_ci                            set case_block "yes"
119425bb815Sopenharmony_ci                            set state "wait-for-break"
120425bb815Sopenharmony_ci                            continue
121425bb815Sopenharmony_ci                        } elseif {$next_token_type == "identifier"} {
122425bb815Sopenharmony_ci                            if {[string compare "JERRY_UNREACHABLE" $next_token_value] == 0
123425bb815Sopenharmony_ci                                || [string first "JERRY_UNIMPLEMENTED" $next_token_value] == 0} {
124425bb815Sopenharmony_ci                                set state "wait-for-semicolon"
125425bb815Sopenharmony_ci                                continue
126425bb815Sopenharmony_ci                            } else {
127425bb815Sopenharmony_ci                                set state "wait-for-break"
128425bb815Sopenharmony_ci                                continue
129425bb815Sopenharmony_ci                            }
130425bb815Sopenharmony_ci                        } elseif {$next_token_type == "break"
131425bb815Sopenharmony_ci                                  || $next_token_type == "continue"
132425bb815Sopenharmony_ci                                  || $next_token_type == "return"} {
133425bb815Sopenharmony_ci                            set state "wait-for-semicolon"
134425bb815Sopenharmony_ci                            continue
135425bb815Sopenharmony_ci                        } elseif {[string first "pp_" $next_token_type] == 0} {
136425bb815Sopenharmony_ci                            set state "after-colon-preprocessor"
137425bb815Sopenharmony_ci                        } else {
138425bb815Sopenharmony_ci                            set state "wait-for-break"
139425bb815Sopenharmony_ci                            continue
140425bb815Sopenharmony_ci                        }
141425bb815Sopenharmony_ci                    } elseif {$state == "wait-for-semicolon"} {
142425bb815Sopenharmony_ci                        if {$next_token_type == "semicolon"} {
143425bb815Sopenharmony_ci                            set state "break"
144425bb815Sopenharmony_ci                        }
145425bb815Sopenharmony_ci                        continue
146425bb815Sopenharmony_ci                    } elseif {$state == "wait-for-break"} {
147425bb815Sopenharmony_ci                        if {$next_token_type == "case" || $next_token_type == "default"} {
148425bb815Sopenharmony_ci                            report $fileName [lindex $next_token 1] "Missing break, continue or FALLTHRU comment before case (state $state)"
149425bb815Sopenharmony_ci                        } elseif {$next_token_type == "leftbrace"} {
150425bb815Sopenharmony_ci                            set state "inside-braces"
151425bb815Sopenharmony_ci                            incr seen_braces 1
152425bb815Sopenharmony_ci                            continue
153425bb815Sopenharmony_ci                        } elseif {$next_token_type == "rightbrace"} {
154425bb815Sopenharmony_ci                            if {$case_block == "yes"} {
155425bb815Sopenharmony_ci                                set state "case-blocks-end"
156425bb815Sopenharmony_ci                                continue
157425bb815Sopenharmony_ci                            } else {
158425bb815Sopenharmony_ci                                break
159425bb815Sopenharmony_ci                            }
160425bb815Sopenharmony_ci                        } elseif {[string compare "JERRY_UNREACHABLE" $next_token_value] == 0
161425bb815Sopenharmony_ci                                   || [string first "JERRY_UNIMPLEMENTED" $next_token_value] == 0} {
162425bb815Sopenharmony_ci                            set state "wait-for-semicolon"
163425bb815Sopenharmony_ci                            continue
164425bb815Sopenharmony_ci                        } elseif {$next_token_type == "ccomment" && [string match "*FALL*" $next_token_value]} {
165425bb815Sopenharmony_ci                            set state "fallthru"
166425bb815Sopenharmony_ci                            set line_num [lindex $next_token 1]
167425bb815Sopenharmony_ci                            continue
168425bb815Sopenharmony_ci                        } elseif {$next_token_type == "break"
169425bb815Sopenharmony_ci                                  || $next_token_type == "continue"
170425bb815Sopenharmony_ci                                  || $next_token_type == "return"
171425bb815Sopenharmony_ci                                  || $next_token_type == "goto"} {
172425bb815Sopenharmony_ci                            set state "wait-for-semicolon"
173425bb815Sopenharmony_ci                            continue
174425bb815Sopenharmony_ci                        }
175425bb815Sopenharmony_ci                        continue
176425bb815Sopenharmony_ci                    } elseif {$state == "break" || $state == "fallthru"} {
177425bb815Sopenharmony_ci                        if {$case_block == "no"} {
178425bb815Sopenharmony_ci                            if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
179425bb815Sopenharmony_ci                                continue
180425bb815Sopenharmony_ci                            } elseif {$next_token_type == "case"} {
181425bb815Sopenharmony_ci                                set state "case"
182425bb815Sopenharmony_ci                                continue
183425bb815Sopenharmony_ci                            } elseif {$next_token_type == "default"} {
184425bb815Sopenharmony_ci                                set state "default"
185425bb815Sopenharmony_ci                                continue
186425bb815Sopenharmony_ci                            } elseif {$next_token_type == "leftbrace"} {
187425bb815Sopenharmony_ci                                set state "inside-braces"
188425bb815Sopenharmony_ci                                incr seen_braces 1
189425bb815Sopenharmony_ci                                continue
190425bb815Sopenharmony_ci                            } elseif {$next_token_type == "rightbrace"} {
191425bb815Sopenharmony_ci                                lappend switch_ends [lindex $next_token 1]
192425bb815Sopenharmony_ci                                break
193425bb815Sopenharmony_ci                            } elseif {$next_token_type == "break"
194425bb815Sopenharmony_ci                                      || $next_token_type == "continue"
195425bb815Sopenharmony_ci                                      || $next_token_type == "return"} {
196425bb815Sopenharmony_ci                                set state "wait-for-semicolon"
197425bb815Sopenharmony_ci                                continue
198425bb815Sopenharmony_ci                            } else {
199425bb815Sopenharmony_ci                                set state "wait-for-break"
200425bb815Sopenharmony_ci                                continue
201425bb815Sopenharmony_ci                            }
202425bb815Sopenharmony_ci                        } else {
203425bb815Sopenharmony_ci                            if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
204425bb815Sopenharmony_ci                                continue
205425bb815Sopenharmony_ci                            } elseif {$next_token_type == "case"} {
206425bb815Sopenharmony_ci                                set state "case"
207425bb815Sopenharmony_ci                                continue
208425bb815Sopenharmony_ci                            } elseif {$next_token_type == "default"} {
209425bb815Sopenharmony_ci                                set state "default"
210425bb815Sopenharmony_ci                                continue
211425bb815Sopenharmony_ci                            } elseif {$next_token_type == "leftbrace"} {
212425bb815Sopenharmony_ci                                set state "inside-braces"
213425bb815Sopenharmony_ci                                incr seen_braces 1
214425bb815Sopenharmony_ci                                continue
215425bb815Sopenharmony_ci                            } elseif {$next_token_type == "rightbrace"} {
216425bb815Sopenharmony_ci                                set state "after-rightbrace"
217425bb815Sopenharmony_ci                                continue
218425bb815Sopenharmony_ci                            } elseif {$next_token_type == "break"
219425bb815Sopenharmony_ci                                      || $next_token_type == "continue"
220425bb815Sopenharmony_ci                                      || $next_token_type == "return"} {
221425bb815Sopenharmony_ci                                set state "wait-for-semicolon"
222425bb815Sopenharmony_ci                                continue
223425bb815Sopenharmony_ci                            } else {
224425bb815Sopenharmony_ci                                set state "wait-for-break"
225425bb815Sopenharmony_ci                                continue
226425bb815Sopenharmony_ci                            }
227425bb815Sopenharmony_ci                        }
228425bb815Sopenharmony_ci                    } elseif {$state == "inside-braces"} {
229425bb815Sopenharmony_ci                        if {$next_token_type == "rightbrace"} {
230425bb815Sopenharmony_ci                            incr seen_braces -1
231425bb815Sopenharmony_ci                            if {$seen_braces == 0} {
232425bb815Sopenharmony_ci                                set state "wait-for-break"
233425bb815Sopenharmony_ci                                continue
234425bb815Sopenharmony_ci                            }
235425bb815Sopenharmony_ci                        } elseif {$next_token_type == "leftbrace"} {
236425bb815Sopenharmony_ci                            incr seen_braces 1
237425bb815Sopenharmony_ci                        }
238425bb815Sopenharmony_ci                        continue
239425bb815Sopenharmony_ci                    } elseif {$state == "after-rightbrace-preprocessor"} {
240425bb815Sopenharmony_ci                        if {$next_token_type == "newline"} {
241425bb815Sopenharmony_ci                            set state "after-rightbrace"
242425bb815Sopenharmony_ci                        }
243425bb815Sopenharmony_ci                   } elseif {$state == "after-rightbrace"} {
244425bb815Sopenharmony_ci                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
245425bb815Sopenharmony_ci                            continue
246425bb815Sopenharmony_ci                        } elseif {$next_token_type == "case"} {
247425bb815Sopenharmony_ci                            set state "case"
248425bb815Sopenharmony_ci                            continue
249425bb815Sopenharmony_ci                        } elseif {$next_token_type == "default"} {
250425bb815Sopenharmony_ci                            set state "default"
251425bb815Sopenharmony_ci                            continue
252425bb815Sopenharmony_ci                        }  elseif {$next_token_type == "rightbrace"} {
253425bb815Sopenharmony_ci                            lappend switch_ends [lindex $next_token 1]
254425bb815Sopenharmony_ci                            break
255425bb815Sopenharmony_ci                        } elseif {[string first "pp_" $next_token_type] == 0} {
256425bb815Sopenharmony_ci                            set state "after-rightbrace-preprocessor"
257425bb815Sopenharmony_ci                        } else {
258425bb815Sopenharmony_ci                            report $fileName [lindex $next_token 1] "There should be 'case' or 'default' (state $state)"
259425bb815Sopenharmony_ci                        }
260425bb815Sopenharmony_ci                    } elseif {$state == "case-blocks-end-preprocessor"} {
261425bb815Sopenharmony_ci                      if {$next_token_type == "newline"} {
262425bb815Sopenharmony_ci                          set state "case-blocks-end"
263425bb815Sopenharmony_ci                      }
264425bb815Sopenharmony_ci                    } elseif {$state == "case-blocks-end"} {
265425bb815Sopenharmony_ci                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
266425bb815Sopenharmony_ci                            continue
267425bb815Sopenharmony_ci                        } elseif {$next_token_type == "rightbrace"} {
268425bb815Sopenharmony_ci                            lappend switch_ends [lindex $next_token 1]
269425bb815Sopenharmony_ci                            break
270425bb815Sopenharmony_ci                        } elseif {[string first "pp_" $next_token_type] == 0} {
271425bb815Sopenharmony_ci                            set state "case-blocks-end-preprocessor"
272425bb815Sopenharmony_ci                        } else {
273425bb815Sopenharmony_ci                            report $fileName [lindex $next_token 1] "Missing break, continue or FALLTHRU comment before rightbrace (state $state)"
274425bb815Sopenharmony_ci                        }
275425bb815Sopenharmony_ci                    } else {
276425bb815Sopenharmony_ci                        report $fileName [lindex $next_token 1] "Unknown state: $state"
277425bb815Sopenharmony_ci                    }
278425bb815Sopenharmony_ci                }
279425bb815Sopenharmony_ci            }
280425bb815Sopenharmony_ci        }
281425bb815Sopenharmony_ci    }
282425bb815Sopenharmony_ci}
283