• 作成:

edコマンド世界ではwqは1文字?

ちょっとedを実装してたら謎を見つけました

GNU 'ed' Manual より引用.

All ed commands are single characters

全てのedのコマンドは1文字です

(1,$)wq file Writes the addressed lines to file, and then executes a 'q' command.

(1,$)wq file ファイルに指定した行を書き出し, 'q' コマンドを実行する

wqは1文字だった…? そんなことはないと思うんだがなあ.

指摘

実装

gnu edでの実装は以下のようになっていた.

やはりコマンドは1文字という原則から外れ, 2文字を処理しているように見える.

qwparametersという扱いなら, 矛盾はなかったのだが.

klcコマンドは, lcparameters扱いになっているため, 矛盾はない.

/* execute the next command in command buffer; return error status */
static int exec_command( const char ** const ibufpp, const int prev_status,
                         const bool isglobal )
  {
  const char * fnp;
  int gflags = 0;
  int addr, c, n;
  const int addr_cnt = extract_addr_range( ibufpp );

  if( addr_cnt < 0 ) return ERR;
  *ibufpp = skip_blanks( *ibufpp );
  c = *(*ibufpp)++;
  switch( c )
    {
    // 省略
    case 'w':
    case 'W': n = **ibufpp;
              if( n == 'q' || n == 'Q' ) ++*ibufpp;
              if( unexpected_command_suffix( **ibufpp ) ) return ERR;
              fnp = get_filename( ibufpp );
              if( !fnp ) return ERR;
              if( addr_cnt == 0 && last_addr() == 0 )
                first_addr = second_addr = 0;
              else if( !check_addr_range( 1, last_addr(), addr_cnt ) )
                return ERR;
              if( !def_filename[0] && fnp[0] != '!' ) set_def_filename( fnp );
              if( traditional() && !fnp[0] && !def_filename[0] )
                { set_error_msg( "No current filename" ); return ERR; }
              addr = write_file( fnp[0] ? fnp : def_filename,
                     ( c == 'W' ) ? "a" : "w", first_addr, second_addr );
              if( addr < 0 ) return ERR;
              if( addr == last_addr() ) set_modified( false );
              else if( modified() && !scripted() && n == 'q' &&
                       prev_status != EMOD ) return EMOD;
              if( n == 'q' || n == 'Q' ) return QUIT;
              break;
    default : set_error_msg( "Unknown command" ); return ERR;
    }
  if( gflags && !display_lines( current_addr(), current_addr(), gflags ) )
    return ERR;
  return 0;
  }