LCOV - code coverage report
Current view: top level - src/terminal - terminaldispatcher.cc (source / functions) Hit Total Coverage
Test: mosh-1.3.2 Code Coverage Lines: 104 128 81.2 %
Date: 2022-02-06 20:19:53 Functions: 11 15 73.3 %
Legend: Lines: hit not hit

          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 <stdio.h>
      34             : #include <assert.h>
      35             : #include <string.h>
      36             : #include <errno.h>
      37             : #include <stdlib.h>
      38             : 
      39             : #include "terminaldispatcher.h"
      40             : #include "parseraction.h"
      41             : #include "terminalframebuffer.h"
      42             : 
      43             : using namespace Terminal;
      44             : 
      45             : static const size_t MAXIMUM_CLIPBOARD_SIZE = 16*1024;
      46             : 
      47       11654 : Dispatcher::Dispatcher()
      48       11654 :   : params(), parsed_params(), parsed( false ), dispatch_chars(),
      49       11654 :     OSC_string(), terminal_to_host()
      50       11654 : {}
      51             : 
      52      187351 : void Dispatcher::newparamchar( const Parser::Param *act )
      53             : {
      54      187351 :   assert( act->char_present );
      55      187351 :   assert( (act->ch == ';') || ( (act->ch >= '0') && (act->ch <= '9') ) );
      56      187351 :   if ( params.length() < 100 ) {
      57             :     /* enough for 16 five-char params plus 15 semicolons */
      58      187351 :     params.push_back( act->ch );
      59             :   }
      60      187351 :   parsed = false;
      61      187351 : }
      62             : 
      63       39253 : void Dispatcher::collect( const Parser::Collect *act )
      64             : {
      65       39253 :   assert( act->char_present );
      66       39253 :   if ( ( dispatch_chars.length() < 8 ) /* never should need more than 2 */
      67       39253 :        && ( act->ch <= 255 ) ) {  /* ignore non-8-bit */    
      68       39253 :     dispatch_chars.push_back( act->ch );
      69             :   }
      70       39253 : }
      71             : 
      72       60038 : void Dispatcher::clear( const Parser::Clear *act __attribute((unused)) )
      73             : {
      74       60038 :   params.clear();
      75       60038 :   dispatch_chars.clear();
      76       60038 :   parsed = false;
      77       60038 : }
      78             : 
      79       30013 : void Dispatcher::parse_params( void )
      80             : {
      81       30013 :   if ( parsed ) {
      82           0 :     return;
      83             :   }
      84             : 
      85       30013 :   parsed_params.clear();
      86       30013 :   const char *str = params.c_str();
      87       30013 :   const char *segment_begin = str;
      88             : 
      89      130707 :   while ( 1 ) {
      90       80360 :     const char *segment_end = strchr( segment_begin, ';' );
      91       80360 :     if ( segment_end == NULL ) {
      92             :       break;
      93             :     }
      94             : 
      95       50347 :     errno = 0;
      96       50347 :     char *endptr;
      97       50347 :     long val = strtol( segment_begin, &endptr, 10 );
      98       50347 :     if ( endptr == segment_begin ) {
      99             :       val = -1;
     100             :     }
     101             : 
     102       50347 :     if ( val > PARAM_MAX || errno == ERANGE ) {
     103           0 :       val = -1;
     104           0 :       errno = 0;
     105             :     }
     106             : 
     107       50347 :     if ( errno == 0 || segment_begin == endptr ) {
     108       50347 :       parsed_params.push_back( val );
     109             :     }
     110             : 
     111       50347 :     segment_begin = segment_end + 1;
     112       50347 :   }
     113             : 
     114             :   /* get last param */
     115       30013 :   errno = 0;
     116       30013 :   char *endptr;
     117       30013 :   long val = strtol( segment_begin, &endptr, 10 );
     118       30013 :   if ( endptr == segment_begin ) {
     119             :     val = -1;
     120             :   }
     121             : 
     122       30013 :   if ( val > PARAM_MAX || errno == ERANGE ) {
     123           0 :     val = -1;
     124           0 :     errno = 0;
     125             :   }
     126             : 
     127       30013 :   if ( errno == 0 || segment_begin == endptr ) {
     128       30013 :     parsed_params.push_back( val );
     129             :   }
     130             : 
     131       30013 :   parsed = true;
     132             : }
     133             : 
     134       91935 : int Dispatcher::getparam( size_t N, int defaultval )
     135             : {
     136       91935 :   int ret = defaultval;
     137       91935 :   if ( !parsed ) {
     138        6689 :     parse_params();
     139             :   }
     140             : 
     141       91935 :   if ( parsed_params.size() > N ) {
     142       91519 :     ret = parsed_params[ N ];
     143             :   }
     144             : 
     145       91935 :   if ( ret < 1 ) ret = defaultval;
     146             : 
     147       91935 :   return ret;
     148             : }
     149             : 
     150       75696 : int Dispatcher::param_count( void )
     151             : {
     152       75696 :   if ( !parsed ) {
     153       23324 :     parse_params();
     154             :   }
     155             : 
     156       75696 :   return parsed_params.size();
     157             : }
     158             : 
     159           0 : std::string Dispatcher::str( void )
     160             : {
     161           0 :   char assum[ 64 ];
     162           0 :   snprintf( assum, 64, "[dispatch=\"%s\" params=\"%s\"]",
     163             :             dispatch_chars.c_str(), params.c_str() );
     164           0 :   return std::string( assum );
     165             : }
     166             : 
     167             : /* construct on first use to avoid static initialization order crash */
     168    47965661 : DispatchRegistry & Terminal::get_global_dispatch_registry( void )
     169             : {
     170    47965661 :   static DispatchRegistry global_dispatch_registry;
     171    47965661 :   return global_dispatch_registry;
     172             : }
     173             : 
     174       62192 : static void register_function( Function_Type type,
     175             :                                const std::string & dispatch_chars,
     176             :                                Function f )
     177             : {
     178       62192 :   switch ( type ) {
     179        5408 :   case ESCAPE:
     180        5408 :     get_global_dispatch_registry().escape.insert( dispatch_map_t::value_type( dispatch_chars, f ) );
     181        5408 :     break;
     182       41912 :   case CSI:
     183       41912 :     get_global_dispatch_registry().CSI.insert( dispatch_map_t::value_type( dispatch_chars, f ) );
     184       41912 :     break;
     185       14872 :   case CONTROL:
     186       14872 :     get_global_dispatch_registry().control.insert( dispatch_map_t::value_type( dispatch_chars, f ) );
     187       14872 :     break;
     188             :   }
     189       62192 : }
     190             : 
     191       62192 : Function::Function( Function_Type type, const std::string & dispatch_chars,
     192             :                     void (*s_function)( Framebuffer *, Dispatcher * ),
     193       62192 :                     bool s_clears_wrap_state )
     194       62192 :   : function( s_function ), clears_wrap_state( s_clears_wrap_state )
     195             : {
     196       62192 :   register_function( type, dispatch_chars, *this );
     197       62192 : }
     198             : 
     199    47903469 : void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, Framebuffer *fb )
     200             : {
     201             :   /* add final char to dispatch key */
     202    47903469 :   if ( (type == ESCAPE) || (type == CSI) ) {
     203       30021 :     assert( act->char_present );
     204       30021 :     Parser::Collect act2;
     205       30021 :     act2.char_present = true;
     206       30021 :     act2.ch = act->ch;
     207       30021 :     collect( &act2 ); 
     208       30021 :   }
     209             : 
     210    47903469 :   dispatch_map_t *map = NULL;
     211    47903469 :   switch ( type ) {
     212           4 :   case ESCAPE:  map = &get_global_dispatch_registry().escape;  break;
     213       30017 :   case CSI:     map = &get_global_dispatch_registry().CSI;     break;
     214    47873448 :   case CONTROL: map = &get_global_dispatch_registry().control; break;
     215             :   }
     216             : 
     217    95806930 :   std::string key = dispatch_chars;
     218    47903469 :   if ( type == CONTROL ) {
     219    47873448 :     assert( act->ch <= 255 );
     220    47873448 :     char ctrlstr[ 2 ] = { (char)act->ch, 0 };
     221    95746896 :     key = std::string( ctrlstr, 1 );
     222             :   }
     223             : 
     224    47903469 :   dispatch_map_t::const_iterator i = map->find( key );
     225    47903469 :   if ( i == map->end() ) {
     226             :     /* unknown function */
     227           8 :     fb->ds.next_print_will_wrap = false;
     228           8 :     return;
     229             :   }
     230    47903461 :   if ( i->second.clears_wrap_state ) {
     231    47880127 :     fb->ds.next_print_will_wrap = false;
     232             :   }
     233    47903461 :   i->second.function( fb, this );
     234             : }
     235             : 
     236           0 : void Dispatcher::OSC_put( const Parser::OSC_Put *act )
     237             : {
     238           0 :   assert( act->char_present );
     239           0 :   if ( OSC_string.size() < MAXIMUM_CLIPBOARD_SIZE) {
     240           0 :     OSC_string.push_back( act->ch );
     241             :   }
     242           0 : }
     243             : 
     244           0 : void Dispatcher::OSC_start( const Parser::OSC_Start *act __attribute((unused)) )
     245             : {
     246           0 :   OSC_string.clear();
     247           0 : }
     248             : 
     249           0 : bool Dispatcher::operator==( const Dispatcher &x ) const
     250             : {
     251           0 :   return ( params == x.params )
     252           0 :     && ( parsed_params == x.parsed_params )
     253           0 :     && ( parsed == x.parsed )
     254           0 :     && ( dispatch_chars == x.dispatch_chars )
     255           0 :     && ( OSC_string == x.OSC_string )
     256           0 :     && ( terminal_to_host == x.terminal_to_host );
     257             : }

Generated by: LCOV version 1.14