• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/tclsh
2
3# Copyright JS Foundation and other contributors, http://js.foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# switch-case
18
19foreach fileName [getSourceFileNames] {
20    set is_in_comment "no"
21    set is_in_pp_define "no"
22
23    foreach token [getTokens $fileName 1 0 -1 -1 {}] {
24        set type [lindex $token 3]
25        set lineNumber [lindex $token 1]
26
27        if {$is_in_comment == "yes"} {
28            set is_in_comment "no"
29        }
30
31        if {$type == "newline"} {
32            set is_in_pp_define "no"
33        } elseif {$type == "ccomment"} {
34            set is_in_comment "yes"
35        } elseif {[string first "pp_" $type] == 0} {
36            if {$type == "pp_define"} {
37                set is_in_pp_define "yes"
38            }
39        } elseif {$type == "space"} {
40        } elseif {$type != "eof"} {
41            if {$is_in_pp_define == "no" && $type == "switch"} {
42                set next_token_start [lindex $token 2]
43                incr next_token_start 1
44                set line_num 0
45                set state "switch"
46                set case_block "no"
47                set seen_braces 0
48                foreach next_token [getTokens $fileName $lineNumber $next_token_start -1 -1 {}] {
49                    set next_token_type [lindex $next_token 3]
50                    set next_token_value [lindex $next_token 0]
51                    if {$state == "switch"} {
52                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
53                            continue
54                        } elseif {$next_token_type == "leftbrace"} {
55                            set state "first-case"
56                            continue
57                        } else {
58                            # TODO: check switch
59                            continue
60                        }
61                    } elseif {$state == "first-case"} {
62                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
63                            continue
64                        } elseif {$next_token_type == "case"} {
65                            set state "case"
66                            continue
67                        } elseif {$next_token_type == "default"} {
68                            set state "default"
69                            continue
70                        } else {
71                            # Macros magic: give up
72                            break
73                        }
74                    } elseif {$state == "case"} {
75                        if {$next_token_type == "space"} {
76                            set state "space-after-case"
77                            continue
78                        } else {
79                            report $fileName [lindex $next_token 1] "There should be single space character after 'case' keyword (state $state)"
80                        }
81                    } elseif {$state == "space-after-case"} {
82                        if {$next_token_type != "identifier" && $next_token_type != "intlit" && $next_token_type != "charlit" && $next_token_type != "sizeof"} {
83                            report $fileName [lindex $next_token 1] "There should be single space character after 'case' keyword (state $state, next_token_type $next_token_type)"
84                        } else {
85                            set state "case-label"
86                            continue
87                        }
88                    } elseif {$state == "case-label" || $state == "default"} {
89                        set case_block "no"
90                        if {$next_token_type != "colon"} {
91                            continue
92                        } else {
93                            set state "colon"
94                            continue
95                        }
96                    } elseif {$state == "after-colon-preprocessor"} {
97                      if {$next_token_type == "newline"} {
98                          set state "colon"
99                      }
100                    } elseif {$state == "colon"} {
101                        if {$next_token_type == "space" || $next_token_type == "newline"} {
102                            continue
103                        } elseif {$next_token_type == "ccomment"} {
104                            if {[string match "*FALL*" $next_token_value]} {
105                                set state "fallthru"
106                                set line_num [lindex $next_token 1]
107                                continue
108                            } else {
109                                continue
110                            }
111                        } elseif {$next_token_type == "case"} {
112                            set state "case"
113                            continue
114                        } elseif {$next_token_type == "default"} {
115                            set state "default"
116                            continue
117                        } elseif {$next_token_type == "leftbrace"} {
118                            set case_block "yes"
119                            set state "wait-for-break"
120                            continue
121                        } elseif {$next_token_type == "identifier"} {
122                            if {[string compare "JERRY_UNREACHABLE" $next_token_value] == 0
123                                || [string first "JERRY_UNIMPLEMENTED" $next_token_value] == 0} {
124                                set state "wait-for-semicolon"
125                                continue
126                            } else {
127                                set state "wait-for-break"
128                                continue
129                            }
130                        } elseif {$next_token_type == "break"
131                                  || $next_token_type == "continue"
132                                  || $next_token_type == "return"} {
133                            set state "wait-for-semicolon"
134                            continue
135                        } elseif {[string first "pp_" $next_token_type] == 0} {
136                            set state "after-colon-preprocessor"
137                        } else {
138                            set state "wait-for-break"
139                            continue
140                        }
141                    } elseif {$state == "wait-for-semicolon"} {
142                        if {$next_token_type == "semicolon"} {
143                            set state "break"
144                        }
145                        continue
146                    } elseif {$state == "wait-for-break"} {
147                        if {$next_token_type == "case" || $next_token_type == "default"} {
148                            report $fileName [lindex $next_token 1] "Missing break, continue or FALLTHRU comment before case (state $state)"
149                        } elseif {$next_token_type == "leftbrace"} {
150                            set state "inside-braces"
151                            incr seen_braces 1
152                            continue
153                        } elseif {$next_token_type == "rightbrace"} {
154                            if {$case_block == "yes"} {
155                                set state "case-blocks-end"
156                                continue
157                            } else {
158                                break
159                            }
160                        } elseif {[string compare "JERRY_UNREACHABLE" $next_token_value] == 0
161                                   || [string first "JERRY_UNIMPLEMENTED" $next_token_value] == 0} {
162                            set state "wait-for-semicolon"
163                            continue
164                        } elseif {$next_token_type == "ccomment" && [string match "*FALL*" $next_token_value]} {
165                            set state "fallthru"
166                            set line_num [lindex $next_token 1]
167                            continue
168                        } elseif {$next_token_type == "break"
169                                  || $next_token_type == "continue"
170                                  || $next_token_type == "return"
171                                  || $next_token_type == "goto"} {
172                            set state "wait-for-semicolon"
173                            continue
174                        }
175                        continue
176                    } elseif {$state == "break" || $state == "fallthru"} {
177                        if {$case_block == "no"} {
178                            if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
179                                continue
180                            } elseif {$next_token_type == "case"} {
181                                set state "case"
182                                continue
183                            } elseif {$next_token_type == "default"} {
184                                set state "default"
185                                continue
186                            } elseif {$next_token_type == "leftbrace"} {
187                                set state "inside-braces"
188                                incr seen_braces 1
189                                continue
190                            } elseif {$next_token_type == "rightbrace"} {
191                                lappend switch_ends [lindex $next_token 1]
192                                break
193                            } elseif {$next_token_type == "break"
194                                      || $next_token_type == "continue"
195                                      || $next_token_type == "return"} {
196                                set state "wait-for-semicolon"
197                                continue
198                            } else {
199                                set state "wait-for-break"
200                                continue
201                            }
202                        } else {
203                            if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
204                                continue
205                            } elseif {$next_token_type == "case"} {
206                                set state "case"
207                                continue
208                            } elseif {$next_token_type == "default"} {
209                                set state "default"
210                                continue
211                            } elseif {$next_token_type == "leftbrace"} {
212                                set state "inside-braces"
213                                incr seen_braces 1
214                                continue
215                            } elseif {$next_token_type == "rightbrace"} {
216                                set state "after-rightbrace"
217                                continue
218                            } elseif {$next_token_type == "break"
219                                      || $next_token_type == "continue"
220                                      || $next_token_type == "return"} {
221                                set state "wait-for-semicolon"
222                                continue
223                            } else {
224                                set state "wait-for-break"
225                                continue
226                            }
227                        }
228                    } elseif {$state == "inside-braces"} {
229                        if {$next_token_type == "rightbrace"} {
230                            incr seen_braces -1
231                            if {$seen_braces == 0} {
232                                set state "wait-for-break"
233                                continue
234                            }
235                        } elseif {$next_token_type == "leftbrace"} {
236                            incr seen_braces 1
237                        }
238                        continue
239                    } elseif {$state == "after-rightbrace-preprocessor"} {
240                        if {$next_token_type == "newline"} {
241                            set state "after-rightbrace"
242                        }
243                   } elseif {$state == "after-rightbrace"} {
244                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
245                            continue
246                        } elseif {$next_token_type == "case"} {
247                            set state "case"
248                            continue
249                        } elseif {$next_token_type == "default"} {
250                            set state "default"
251                            continue
252                        }  elseif {$next_token_type == "rightbrace"} {
253                            lappend switch_ends [lindex $next_token 1]
254                            break
255                        } elseif {[string first "pp_" $next_token_type] == 0} {
256                            set state "after-rightbrace-preprocessor"
257                        } else {
258                            report $fileName [lindex $next_token 1] "There should be 'case' or 'default' (state $state)"
259                        }
260                    } elseif {$state == "case-blocks-end-preprocessor"} {
261                      if {$next_token_type == "newline"} {
262                          set state "case-blocks-end"
263                      }
264                    } elseif {$state == "case-blocks-end"} {
265                        if {$next_token_type == "ccomment" || $next_token_type == "space" || $next_token_type == "newline"} {
266                            continue
267                        } elseif {$next_token_type == "rightbrace"} {
268                            lappend switch_ends [lindex $next_token 1]
269                            break
270                        } elseif {[string first "pp_" $next_token_type] == 0} {
271                            set state "case-blocks-end-preprocessor"
272                        } else {
273                            report $fileName [lindex $next_token 1] "Missing break, continue or FALLTHRU comment before rightbrace (state $state)"
274                        }
275                    } else {
276                        report $fileName [lindex $next_token 1] "Unknown state: $state"
277                    }
278                }
279            }
280        }
281    }
282}
283