Line data Source code
1 : /* 2 : Mosh: the mobile shell 3 : Copyright 2012 Keith Winstein 4 : 5 : This program is free software: you can redistribute it and/or modify 6 : it under the terms of the GNU General Public License as published by 7 : the Free Software Foundation, either version 3 of the License, or 8 : (at your option) any later version. 9 : 10 : This program is distributed in the hope that it will be useful, 11 : but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : GNU General Public License for more details. 14 : 15 : You should have received a copy of the GNU General Public License 16 : along with this program. If not, see <http://www.gnu.org/licenses/>. 17 : 18 : In addition, as a special exception, the copyright holders give 19 : permission to link the code of portions of this program with the 20 : OpenSSL library under certain conditions as described in each 21 : individual source file, and distribute linked combinations including 22 : the two. 23 : 24 : You must obey the GNU General Public License in all respects for all 25 : of the code used other than OpenSSL. If you modify file(s) with this 26 : exception, you may extend this exception to your version of the 27 : file(s), but you are not obligated to do so. If you do not wish to do 28 : so, delete this exception statement from your version. If you delete 29 : this exception statement from all source files in the program, then 30 : also delete it here. 31 : */ 32 : 33 : #include "parserstate.h" 34 : #include "parserstatefamily.h" 35 : #include "shared.h" 36 : 37 : using namespace Parser; 38 : 39 72189527 : Transition State::anywhere_rule( wchar_t ch ) const 40 : { 41 72189527 : if ( (ch == 0x18) || (ch == 0x1A) 42 72189527 : || ((0x80 <= ch) && (ch <= 0x8F)) 43 72189527 : || ((0x91 <= ch) && (ch <= 0x97)) 44 : || (ch == 0x99) || (ch == 0x9A) ) { 45 0 : return Transition( shared::make_shared<Execute>(), &family->s_Ground ); 46 : } else if ( ch == 0x9C ) { 47 0 : return Transition( &family->s_Ground ); 48 : } else if ( ch == 0x1B ) { 49 90063 : return Transition( &family->s_Escape ); 50 : } else if ( (ch == 0x98) || (ch == 0x9E) || (ch == 0x9F) ) { 51 0 : return Transition( &family->s_SOS_PM_APC_String ); 52 : } else if ( ch == 0x90 ) { 53 0 : return Transition( &family->s_DCS_Entry ); 54 : } else if ( ch == 0x9D ) { 55 0 : return Transition( &family->s_OSC_String ); 56 : } else if ( ch == 0x9B ) { 57 0 : return Transition( &family->s_CSI_Entry ); 58 : } 59 : 60 72159506 : return Transition(( State * )NULL, ActionPointer() ); /* don't allocate an Ignore action */ 61 : } 62 : 63 72189527 : Transition State::input( wchar_t ch ) const 64 : { 65 : /* Check for immediate transitions. */ 66 72189527 : Transition anywhere = anywhere_rule( ch ); 67 72189527 : if ( anywhere.next_state ) { 68 30021 : anywhere.action->char_present = true; 69 30021 : anywhere.action->ch = ch; 70 30021 : return anywhere; 71 : } 72 : /* Normal X.364 state machine. */ 73 : /* Parse high Unicode codepoints like 'A'. */ 74 72160700 : Transition ret = this->input_state_rule( ch >= 0xA0 ? 0x41 : ch ); 75 72159506 : ret.action->char_present = true; 76 72159506 : ret.action->ch = ch; 77 72159506 : return ret; 78 72219548 : } 79 : 80 72159506 : static bool C0_prime( wchar_t ch ) 81 : { 82 72159506 : return (ch <= 0x17) 83 72159506 : || (ch == 0x19) 84 24285637 : || ( (0x1C <= ch) && (ch <= 0x1F) ); 85 : } 86 : 87 24029016 : static bool GLGR ( wchar_t ch ) 88 : { 89 24029016 : return ( (0x20 <= ch) && (ch <= 0x7F) ) /* GL area */ 90 24029016 : || ( (0xA0 <= ch) && (ch <= 0xFF) ); /* GR area */ 91 : } 92 : 93 71902885 : Transition Ground::input_state_rule( wchar_t ch ) const 94 : { 95 71902885 : if ( C0_prime( ch ) ) { 96 143621607 : return Transition( shared::make_shared< Execute >() ); 97 : } 98 : 99 24029016 : if ( GLGR( ch ) ) { 100 72087048 : return Transition( shared::make_shared< Print >() ); 101 : } 102 : 103 0 : return Transition(); 104 : } 105 : 106 30021 : ActionPointer Escape::enter( void ) const 107 : { 108 30021 : return shared::make_shared< Clear >(); 109 : } 110 : 111 30021 : Transition Escape::input_state_rule( wchar_t ch ) const 112 : { 113 30021 : if ( C0_prime( ch ) ) { 114 0 : return Transition( shared::make_shared< Execute >() ); 115 : } 116 : 117 30021 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 118 0 : return Transition( shared::make_shared< Collect >(), &family->s_Escape_Intermediate ); 119 : } 120 : 121 : if ( ( (0x30 <= ch) && (ch <= 0x4F) ) 122 : || ( (0x51 <= ch) && (ch <= 0x57) ) 123 : || ( ch == 0x59 ) 124 : || ( ch == 0x5A ) 125 : || ( ch == 0x5C ) 126 : || ( (0x60 <= ch) && (ch <= 0x7E) ) ) { 127 12 : return Transition( shared::make_shared< Esc_Dispatch >(), &family->s_Ground ); 128 : } 129 : 130 : if ( ch == 0x5B ) { 131 90051 : return Transition( &family->s_CSI_Entry ); 132 : } 133 : 134 : if ( ch == 0x5D ) { 135 0 : return Transition( &family->s_OSC_String ); 136 : } 137 : 138 : if ( ch == 0x50 ) { 139 0 : return Transition( &family->s_DCS_Entry ); 140 : } 141 : 142 : if ( (ch == 0x58) || (ch == 0x5E) || (ch == 0x5F) ) { 143 0 : return Transition( &family->s_SOS_PM_APC_String ); 144 : } 145 : 146 0 : return Transition(); 147 : } 148 : 149 0 : Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const 150 : { 151 0 : if ( C0_prime( ch ) ) { 152 0 : return Transition( shared::make_shared< Execute >() ); 153 : } 154 : 155 0 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 156 0 : return Transition( shared::make_shared< Collect >() ); 157 : } 158 : 159 0 : if ( (0x30 <= ch) && (ch <= 0x7E) ) { 160 0 : return Transition( shared::make_shared< Esc_Dispatch >(), &family->s_Ground ); 161 : } 162 : 163 0 : return Transition(); 164 : } 165 : 166 30017 : ActionPointer CSI_Entry::enter( void ) const 167 : { 168 30017 : return shared::make_shared< Clear >(); 169 : } 170 : 171 30017 : Transition CSI_Entry::input_state_rule( wchar_t ch ) const 172 : { 173 30017 : if ( C0_prime( ch ) ) { 174 0 : return Transition( shared::make_shared< Execute >() ); 175 : } 176 : 177 30017 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 178 15882 : return Transition( shared::make_shared< CSI_Dispatch >(), &family->s_Ground ); 179 : } 180 : 181 : if ( ( (0x30 <= ch) && (ch <= 0x39) ) 182 : || ( ch == 0x3B ) ) { 183 46473 : return Transition( shared::make_shared< Param >(), &family->s_CSI_Param ); 184 : } 185 : 186 : if ( (0x3C <= ch) && (ch <= 0x3F) ) { 187 27696 : return Transition( shared::make_shared< Collect >(), &family->s_CSI_Param ); 188 : } 189 : 190 : if ( ch == 0x3A ) { 191 0 : return Transition( &family->s_CSI_Ignore ); 192 : } 193 : 194 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 195 0 : return Transition( shared::make_shared< Collect >(), &family->s_CSI_Intermediate ); 196 : } 197 : 198 0 : return Transition(); 199 : } 200 : 201 196583 : Transition CSI_Param::input_state_rule( wchar_t ch ) const 202 : { 203 196583 : if ( C0_prime( ch ) ) { 204 0 : return Transition( shared::make_shared< Execute >() ); 205 : } 206 : 207 196583 : if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) { 208 515580 : return Transition( shared::make_shared< Param >() ); 209 : } 210 : 211 : if ( ( ch == 0x3A ) || ( (0x3C <= ch) && (ch <= 0x3F) ) ) { 212 0 : return Transition( &family->s_CSI_Ignore ); 213 : } 214 : 215 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 216 0 : return Transition( shared::make_shared< Collect >(), &family->s_CSI_Intermediate ); 217 : } 218 : 219 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 220 74169 : return Transition( shared::make_shared< CSI_Dispatch >(), &family->s_Ground ); 221 : } 222 : 223 0 : return Transition(); 224 : } 225 : 226 0 : Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const 227 : { 228 0 : if ( C0_prime( ch ) ) { 229 0 : return Transition( shared::make_shared< Execute >() ); 230 : } 231 : 232 0 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 233 0 : return Transition( shared::make_shared< Collect >() ); 234 : } 235 : 236 0 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 237 0 : return Transition( shared::make_shared< CSI_Dispatch >(), &family->s_Ground ); 238 : } 239 : 240 0 : if ( (0x30 <= ch) && (ch <= 0x3F) ) { 241 0 : return Transition( &family->s_CSI_Ignore ); 242 : } 243 : 244 0 : return Transition(); 245 : } 246 : 247 0 : Transition CSI_Ignore::input_state_rule( wchar_t ch ) const 248 : { 249 0 : if ( C0_prime( ch ) ) { 250 0 : return Transition( shared::make_shared< Execute >() ); 251 : } 252 : 253 0 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 254 0 : return Transition( &family->s_Ground ); 255 : } 256 : 257 0 : return Transition(); 258 : } 259 : 260 0 : ActionPointer DCS_Entry::enter( void ) const 261 : { 262 0 : return shared::make_shared< Clear >(); 263 : } 264 : 265 0 : Transition DCS_Entry::input_state_rule( wchar_t ch ) const 266 : { 267 0 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 268 0 : return Transition( shared::make_shared< Collect >(), &family->s_DCS_Intermediate ); 269 : } 270 : 271 0 : if ( ch == 0x3A ) { 272 0 : return Transition( &family->s_DCS_Ignore ); 273 : } 274 : 275 : if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) { 276 0 : return Transition( shared::make_shared< Param >(), &family->s_DCS_Param ); 277 : } 278 : 279 : if ( (0x3C <= ch) && (ch <= 0x3F) ) { 280 0 : return Transition( shared::make_shared< Collect >(), &family->s_DCS_Param ); 281 : } 282 : 283 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 284 0 : return Transition( &family->s_DCS_Passthrough ); 285 : } 286 : 287 0 : return Transition(); 288 : } 289 : 290 0 : Transition DCS_Param::input_state_rule( wchar_t ch ) const 291 : { 292 0 : if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) { 293 0 : return Transition( shared::make_shared< Param >() ); 294 : } 295 : 296 0 : if ( ( ch == 0x3A ) || ( (0x3C <= ch) && (ch <= 0x3F) ) ) { 297 0 : return Transition( &family->s_DCS_Ignore ); 298 : } 299 : 300 0 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 301 0 : return Transition( shared::make_shared< Collect >(), &family->s_DCS_Intermediate ); 302 : } 303 : 304 0 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 305 0 : return Transition( &family->s_DCS_Passthrough ); 306 : } 307 : 308 0 : return Transition(); 309 : } 310 : 311 0 : Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const 312 : { 313 0 : if ( (0x20 <= ch) && (ch <= 0x2F) ) { 314 0 : return Transition( shared::make_shared< Collect >() ); 315 : } 316 : 317 0 : if ( (0x40 <= ch) && (ch <= 0x7E) ) { 318 0 : return Transition( &family->s_DCS_Passthrough ); 319 : } 320 : 321 0 : if ( (0x30 <= ch) && (ch <= 0x3F) ) { 322 0 : return Transition( &family->s_DCS_Ignore ); 323 : } 324 : 325 0 : return Transition(); 326 : } 327 : 328 0 : ActionPointer DCS_Passthrough::enter( void ) const 329 : { 330 0 : return shared::make_shared< Hook >(); 331 : } 332 : 333 0 : ActionPointer DCS_Passthrough::exit( void ) const 334 : { 335 0 : return shared::make_shared< Unhook >(); 336 : } 337 : 338 0 : Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const 339 : { 340 0 : if ( C0_prime( ch ) || ( (0x20 <= ch) && (ch <= 0x7E) ) ) { 341 0 : return Transition( shared::make_shared< Put >() ); 342 : } 343 : 344 0 : if ( ch == 0x9C ) { 345 0 : return Transition( &family->s_Ground ); 346 : } 347 : 348 0 : return Transition(); 349 : } 350 : 351 0 : Transition DCS_Ignore::input_state_rule( wchar_t ch ) const 352 : { 353 0 : if ( ch == 0x9C ) { 354 0 : return Transition( &family->s_Ground ); 355 : } 356 : 357 0 : return Transition(); 358 : } 359 : 360 0 : ActionPointer OSC_String::enter( void ) const 361 : { 362 0 : return shared::make_shared< OSC_Start >(); 363 : } 364 : 365 0 : ActionPointer OSC_String::exit( void ) const 366 : { 367 0 : return shared::make_shared< OSC_End >(); 368 : } 369 : 370 0 : Transition OSC_String::input_state_rule( wchar_t ch ) const 371 : { 372 0 : if ( (0x20 <= ch) && (ch <= 0x7F) ) { 373 0 : return Transition( shared::make_shared< OSC_Put >() ); 374 : } 375 : 376 0 : if ( (ch == 0x9C) || (ch == 0x07) ) { /* 0x07 is xterm non-ANSI variant */ 377 0 : return Transition( &family->s_Ground ); 378 : } 379 : 380 0 : return Transition(); 381 : } 382 : 383 0 : Transition SOS_PM_APC_String::input_state_rule( wchar_t ch ) const 384 : { 385 0 : if ( ch == 0x9C ) { 386 0 : return Transition( &family->s_Ground ); 387 : } 388 : 389 0 : return Transition(); 390 : }