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