Ignore:
Timestamp:
Aug 23, 2017, 9:27:43 AM (7 years ago)
Author:
coas-nagasima
Message:

文字コードを設定

File:
1 edited

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/plugin/lib/GenHRP2Marshaler.rb

    • Property svn:mime-type changed from text/x-ruby to text/x-ruby;charset=UTF-8
    r270 r321  
    66#   Copyright (C) 2008-2014 by TOPPERS Project
    77#--
    8 #   ä¸Šè¨˜è‘—作権è€
    9 ã¯ï¼Œä»¥ä¸‹ã®(1)~(4)の条件を満たす場合に限り,本ソフトウェ
    10 #   ã‚¢ï¼ˆæœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’改変したものを含む.以下同じ)を使用・複製・改
    11 #   å¤‰ãƒ»å†é
    12 å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
    13 #   (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
    14 #       æ¨©è¡¨ç¤ºï¼Œã“の利用条件および下記の無保証規定が,そのままの形でソー
    15 #       ã‚¹ã‚³ãƒ¼ãƒ‰ä¸­ã«å«ã¾ã‚Œã¦ã„ること.
    16 #   (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
    17 #       ç”¨ã§ãã‚‹å½¢ã§å†é
    18 å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é
    19 å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
    20 #       è€
    21 ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãªã©ï¼‰ã«ï¼Œä¸Šè¨˜ã®è‘—作権表示,この利用条件および下記
    22 #       ã®ç„¡ä¿è¨¼è¦å®šã‚’掲載すること.
    23 #   (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
    24 #       ç”¨ã§ããªã„形で再é
    25 å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
    26 #       ã¨ï¼Ž
    27 #     (a) 再é
    28 å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€
    29 ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãªã©ï¼‰ã«ï¼Œä¸Šè¨˜ã®è‘—
    30 #         ä½œæ¨©è¡¨ç¤ºï¼Œã“の利用条件および下記の無保証規定を掲載すること.
    31 #     (b) 再é
    32 å¸ƒã®å½¢æ
    33 ‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
    34 #         å ±å‘Šã™ã‚‹ã“と.
    35 #   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
    36 #       å®³ã‹ã‚‰ã‚‚,上記著作権è€
    37 ãŠã‚ˆã³TOPPERSプロジェクトをå
    38 è²¬ã™ã‚‹ã“と.
    39 #       ã¾ãŸï¼Œæœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ãƒ¦ãƒ¼ã‚¶ã¾ãŸã¯ã‚¨ãƒ³ãƒ‰ãƒ¦ãƒ¼ã‚¶ã‹ã‚‰ã®ã„かなる理
    40 #       ç”±ã«åŸºã¥ãè«‹æ±‚からも,上記著作権è€
    41 ãŠã‚ˆã³TOPPERSプロジェクトを
    42 #       å
    43 è²¬ã™ã‚‹ã“と.
     8#   上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
     9#   ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
     10#   変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
     11#   (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
     12#       権表示,この利用条件および下記の無保証規定が,そのままの形でソー
     13#       スコード中に含まれていること.
     14#   (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
     15#       用できる形で再配布する場合には,再配布に伴うドキュメント(利用
     16#       者マニュアルなど)に,上記の著作権表示,この利用条件および下記
     17#       の無保証規定を掲載すること.
     18#   (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
     19#       用できない形で再配布する場合には,次のいずれかの条件を満たすこ
     20#       と.
     21#     (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
     22#         作権表示,この利用条件および下記の無保証規定を掲載すること.
     23#     (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
     24#         報告すること.
     25#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
     26#       害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
     27#       また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
     28#       由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
     29#       免責すること.
    4430
    45 #   æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯ï¼Œç„¡ä¿è¨¼ã§æä¾›ã•ã‚Œã¦ã„るものである.上記著作権è€
    46 ãŠ
    47 #   ã‚ˆã³TOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
    48 #   ã«å¯¾ã™ã‚‹é©åˆæ€§ã‚‚含めて,いかなる保証も行わない.また,本ソフトウェ
    49 #   ã‚¢ã®åˆ©ç”¨ã«ã‚ˆã‚Šç›´æŽ¥çš„または間接的に生じたいかなる損害に関しても,そ
    50 #   ã®è²¬ä»»ã‚’負わない.
     31#   本ソフトウェアは,無保証で提供されているものである.上記著作権者お
     32#   よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
     33#   に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
     34#   アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
     35#   の責任を負わない.
    5136
    5237#++
    5338
    54 #プラグインオプション用変数
     39#プラグインオプション用変数
    5540#@task_priority:: Integer
    5641#@channelCelltype:: String
     
    5944module GenTransparentMarshaler
    6045
    61   # プラグイン引数名と Proc
     46  # プラグイン引数名と Proc
    6247  RPCPluginArgProc = {
    6348    "taskPriority"    => Proc.new { |obj,rhs| obj.set_taskPriority rhs },
     
    6853  }
    6954
    70   #=== プラグイン引数 taskPriority のチェック
     55  #=== プラグイン引数 taskPriority のチェック
    7156  def set_taskPriority( rhs )
    7257    @task_priority = rhs
    7358  end
    7459
    75   #=== プラグイン引数 channelCelltype のチェック
     60  #=== プラグイン引数 channelCelltype のチェック
    7661  def set_channelCelltype( rhs )
    7762    @channelCelltype = rhs.to_sym
     
    8570  end
    8671
    87   #=== プラグイン引数 TDRCelltype のチェック
     72  #=== プラグイン引数 TDRCelltype のチェック
    8873  def set_TDRCelltype( rhs )
    8974    @TDRCelltype = rhs.to_sym
     
    9782  end
    9883
    99   #=== プラグイン引数 channelCellName のチェック
     84  #=== プラグイン引数 channelCellName のチェック
    10085  def set_channelCellName( rhs )
    10186    @channelCellName = rhs
     
    10792  end
    10893
    109   #=== プラグイン引数 PPAllocatorSize のチェック
     94  #=== プラグイン引数 PPAllocatorSize のチェック
    11095  def set_PPAllocatorSize( rhs )
    11196    @PPAllocatorSize = rhs
    11297  end
    11398
    114   #=== marshaler のセルタイプ名を設定する
     99  #=== marshaler のセルタイプ名を設定する
    115100  def initialize_transparent_marshaler cell_name
    116101    @task_priority = 8
     
    134119
    135120    f = CFile.open( @marshaler_celltype_file_name, "w" )
    136     # 同じå†
    137 å®¹ã‚’二度書く可能性あり (AppFile は不可)
     121    # 同じ内容を二度書く可能性あり (AppFile は不可)
    138122
    139123    # modified by ishikawa
     
    163147  end
    164148
    165   #===  受け口関数の本体コードを生成(頭部と末尾は別途出力)
    166   #ct_name:: Symbol    (through プラグインで生成された) セルタイプ名 .Symbol として送られてくる(らしい)
     149  #===  受け口関数の本体コードを生成(頭部と末尾は別途出力)
     150  #ct_name:: Symbol    (through プラグインで生成された) セルタイプ名 .Symbol として送られてくる(らしい)
    167151  def gen_ep_func_body( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
    168152
    169     # unmarshaler クラスか?
     153    # unmarshaler クラスか?
    170154    if ct_name == @unmarshaler_celltype_name.to_sym then
    171155      gen_ep_func_body_unmarshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
     
    175159  end
    176160
    177   #===  marshal コードの生成
     161  #===  marshal コードの生成
    178162  def gen_ep_func_body_marshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
    179163
     
    181165    b_ret_er = false
    182166
    183     # 関数の戻り値のå
    184 ƒã®åž‹ã‚’å¾—ã‚‹(typedef されている場合)
     167    # 関数の戻り値の元の型を得る(typedef されている場合)
    185168    type = func_type.get_type.get_original_type
    186169
    187     # 戻り値記憶用の変数を出力(void 型の関数では出力しない)
     170    # 戻り値記憶用の変数を出力(void 型の関数では出力しない)
    188171    if ! type.kind_of?( VoidType ) then
    189172      if func_type.get_type.kind_of?( DefinedType ) && ( func_type.get_type.get_type_str == "ER" || func_type.get_type.get_type_str == "ER_INT" ) then
     
    200183    file.print( "    FLGPTN  flgptn;\n" )
    201184
    202     # 呼びå
    203 ˆã® signature を取り出す
     185    # 呼び先の signature を取り出す
    204186    signature = @signature
    205187
    206     # 関数 ID (整数値)
     188    # 関数 ID (整数値)
    207189    func_id = signature.get_id_from_func_name( func_name )
    208190    file.print( "    int16_t  func_id_ = #{func_id};    /* id of #{func_name}: #{func_id} */\n" )
     
    210192    file.print( "    uint8_t  msg[256];\n" )
    211193
    212     # シングルトンでないか?
     194    # シングルトンでないか?
    213195    if ! b_singleton then
    214196
    215       # singleton でなければ p_cellcb 取得コードを出力
     197      # singleton でなければ p_cellcb 取得コードを出力
    216198      file.print <<EOT
    217199    #{ct_name}_CB *p_cellcb;
     
    221203EOT
    222204
    223       # エラーを返すか?
     205      # エラーを返すか?
    224206      if b_ret_er then
    225207        file.print <<EOT
     
    231213        file.print <<EOT
    232214    }else{
    233         /* エラー処理コードをここに記述 */
    234     }
    235 EOT
    236       end
    237     end
    238 
    239     # channel lock コード
     215        /* エラー処理コードをここに記述 */
     216    }
     217EOT
     218      end
     219    end
     220
     221    # channel lock コード
    240222    file.print <<EOT
    241223    ///* Channel Lock */
     
    246228
    247229=begin
    248     # SOP を送信
    249     file.print "    /* SOPの送出 */\n"
     230    # SOP を送信
     231    file.print "    /* SOPの送出 */\n"
    250232    file.print "    if( ( ercd_ = cTDR_sendSOP( true ) ) != E_OK )\n"
    251233    file.print "      goto error_reset;\n"
    252234=end
    253235
    254     # func_id を送信
    255     file.print "    /* 関数 id の送出 */\n"
     236    # func_id を送信
     237    file.print "    /* 関数 id の送出 */\n"
    256238=begin
    257239    file.print "    if( ( ercd_ = cTDR_putInt16( func_id_ ) ) != E_OK )\n"
     
    263245    # p "#{ct_name}, #{sig_name}, #{func_name}, #{func_global_name}"
    264246
    265     b_get = false    # marshal なら put
     247    b_get = false    # marshal なら put
    266248    b_marshal = true  # marshal
    267249
    268     # in 方向のå
    269 ¥å‡ºåŠ›ã‚’出力
     250    # in 方向の入出力を出力
    270251    @index = 2
    271     file.print "    /* å
    272 ¥åŠ›å¼•æ•°é€å‡º */\n"
     252    file.print "    /* 入力引数送出 */\n"
    273253    print_params( params, file, 1, b_marshal, b_get, true, func_type.is_oneway? )
    274254    print_params( params, file, 1, b_marshal, b_get, false, func_type.is_oneway? )
     
    280260=end
    281261
    282     file.print "    /* EOPの送出(パケットの掃きだし) */\n"
     262    file.print "    /* EOPの送出(パケットの掃きだし) */\n"
    283263    if ! func_type.is_oneway? then
    284264      b_continue = "true"
     
    315295
    316296    if( b_void == false )then
    317       # 呼びå
    318 ƒã«æˆ»ã‚Šå€¤ã‚’リターン
     297      # 呼び元に戻り値をリターン
    319298      file.print( "    cMessageBuffer_receive(&retval_);\n" )
    320299      file.print( "    return retval_;\n" )
     
    332311EOT
    333312
    334     # channel lock コード
     313    # channel lock コード
    335314    file.print <<EOT
    336315    ///* Channel Lock */
     
    341320
    342321    if( b_ret_er != false )then
    343       # 呼びå
    344 ƒã«æˆ»ã‚Šå€¤ã‚’リターン
     322      # 呼び元に戻り値をリターン
    345323      file.print( "    return ercd_;\n" )
    346324    else
     
    350328  end
    351329
    352   #===  unmarshal コードの生成
     330  #===  unmarshal コードの生成
    353331  def gen_ep_func_body_unmarshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
    354332
     
    356334    b_ret_er = false
    357335
    358     # func_id を得るコードを生成
     336    # func_id を得るコードを生成
    359337    file.print <<EOT
    360338
     
    377355        file.print <<EOT
    378356    }else{
    379         /* エラー処理コードをここに記述 */
     357        /* エラー処理コードをここに記述 */
    380358    }
    381359EOT
     
    387365
    388366#if 0
    389     /* SOPのチェック */
     367    /* SOPのチェック */
    390368    if( (ercd_=cTDR_receiveSOP( false )) != E_OK )
    391369        goto error_reset;
    392     /* func_id の取得 */
     370    /* func_id の取得 */
    393371    if( (ercd_=cTDR_getInt16( &func_id_ )) != E_OK )
    394372        goto error_reset;
     
    405383EOT
    406384
    407     # 呼びå
    408 ˆã® signature を取り出す
     385    # 呼び先の signature を取り出す
    409386    # port = @celltype.find( @next_cell_port_name )
    410387    # signature = port.get_signature
    411388    signature = @signature
    412389
    413     # through の signature に含まれる すべての関数について
     390    # through の signature に含まれる すべての関数について
    414391    signature.get_function_head_array.each { |f|
    415392      f_name = f.get_name
     
    417394      id = signature.get_id_from_func_name( f_name )
    418395
    419       # 関数は返り値を持つか?
     396      # 関数は返り値を持つか?
    420397      if f_type.get_type.kind_of?( VoidType ) then
    421398        b_void = true
     
    424401      end
    425402
    426       # パケットの終わりをチェック(未受け取りのデータが残っていないかチェック)
     403      # パケットの終わりをチェック(未受け取りのデータが残っていないかチェック)
    427404      file.print "    case #{id}:       /*** #{f_name} ***/ \n"
    428405      file.print "        if( tTransparentUnmarshaler_#{@signature.get_name}_#{f_name}() != E_OK )\n"
     
    433410
    434411    if @PPAllocatorSize then
    435       ppallocator_dealloc_str = "    /* PPAllocator のすべてを解放 */\n    cPPAllocator_dealloc_all();"
     412      ppallocator_dealloc_str = "    /* PPAllocator のすべてを解放 */\n    cPPAllocator_dealloc_all();"
    436413    else
    437414      ppallocator_dealloc_str = ""
     
    441418    file.print <<EOT
    442419    default:
    443 #if 0 // deleted by ishikawa: tSysLogが未実è£
    444 
     420#if 0 // deleted by ishikawa: tSysLogが未実装
    445421        syslog(LOG_INFO, "unmarshaler task: ERROR: unknown func_id: %d", func_id_ );
    446422#endif /* 0 */
     
    463439
    464440  # IN b_marshal, b_get
    465   #  b_marshal = true  && b_get == false   :  マーシャラでå
    466 ¥åŠ›å¼•æ•°é€å‡º
    467   #  b_marshal = true  && b_get == true    :  マーシャラで出力引数受取
    468   #  b_marshal = false && b_get == true    :  アンマーシャラでå
    469 ¥åŠ›å¼•æ•°å—取
    470   #  b_marshal = false && b_get == get     :  アンマーシャラで出力引数送出
     441  #  b_marshal = true  && b_get == false   :  マーシャラで入力引数送出
     442  #  b_marshal = true  && b_get == true    :  マーシャラで出力引数受取
     443  #  b_marshal = false && b_get == true    :  アンマーシャラで入力引数受取
     444  #  b_marshal = false && b_get == get     :  アンマーシャラで出力引数送出
    471445  def print_params( params, file, nest, b_marshal, b_get, b_referenced, b_oneway = false )
    472446    params.each{ |param|
     
    479453      type = param.get_type
    480454      if b_oneway && dir == :IN && type.get_original_type.kind_of?( PtrType ) || type.get_original_type.kind_of?( ArrayType ) then
    481         # oneway, in, PtrType の場合コピー
     455        # oneway, in, PtrType の場合コピー
    482456        alloc_cp = "cPPAllocator_alloc"
    483457        alloc_cp_extra = nil
     
    501475  end
    502476
    503   #=== コピーしない引数渡しコードの出力
     477  #=== コピーしない引数渡しコードの出力
    504478  def print_param_nc( name, type, file, nest, b_marshal, outer, outer2, b_get )
    505479    indent = "    " * ( nest + 1 )
     
    521495        when :SIGNED
    522496          if bit_size == -1 || bit_size == -11 then
    523             # signed char の場合、signed を指定する
     497            # signed char の場合、signed を指定する
    524498            signC = "S"
    525499            sign  = "s"
     
    640614
    641615
    642   #=== PREAMBLE 部のコード生成
    643   # アンマーシャラセルタイプの場合、アンマーシャラ関数のプロトタイプ宣言を生成
     616  #=== PREAMBLE 部のコード生成
     617  # アンマーシャラセルタイプの場合、アンマーシャラ関数のプロトタイプ宣言を生成
    644618  def gen_preamble file, b_singleton, ct_name, global_name
    645619    if ct_name != @unmarshaler_celltype_name.to_sym then
     
    647621    end
    648622
    649     file.print "/* アンマーシャラ関数のプロトタイプ宣言 */\n"
    650     # signature に含まれる すべての関数について
     623    file.print "/* アンマーシャラ関数のプロトタイプ宣言 */\n"
     624    # signature に含まれる すべての関数について
    651625    @signature.get_function_head_array.each { |f|
    652626      f_name = f.get_name
     
    660634  end
    661635
    662   #=== POSTAMBLE 部のコード生成
    663   # アンマーシャラセルタイプの場合、アンマーシャラ関数の生成
     636  #=== POSTAMBLE 部のコード生成
     637  # アンマーシャラセルタイプの場合、アンマーシャラ関数の生成
    664638  def gen_postamble file, b_singleton, ct_name, global_name
    665639    if ct_name != @unmarshaler_celltype_name.to_sym then
     
    667641    end
    668642
    669     file.print "\n/*** アンマーシャラ関数 ***/\n\n"
     643    file.print "\n/*** アンマーシャラ関数 ***/\n\n"
    670644    @signature.get_function_head_array.each { |f|
    671645      f_name = f.get_name
     
    673647      id = @signature.get_id_from_func_name( f_name )
    674648
    675       # 関数は返り値を持つか?
     649      # 関数は返り値を持つか?
    676650      if f_type.get_type.kind_of?( VoidType ) then
    677651        b_void = true
     
    691665      file.print "      ER  ercd_;\n"
    692666
    693       # 引数を受取る変数の定義
     667      # 引数を受取る変数の定義
    694668      param_list = f.get_declarator.get_type.get_paramlist.get_items
    695669           # FuncHead->  Decl->    FuncType->ParamList
     
    706680        end
    707681
    708         type_str = type.get_type_str.gsub( /\bconst\b */, "" ) # "const" を外す
     682        type_str = type.get_type_str.gsub( /\bconst\b */, "" ) # "const" を外す
    709683
    710684        file.printf( "    %-12s %s%s%s%s;\n", type_str, aster, name, aster2, type.get_type_str_post )
    711685      }
    712686
    713       # 戻り値を受け取る変数の定義
     687      # 戻り値を受け取る変数の定義
    714688      if ! b_void then
    715689        if f.is_oneway? then
    716           retval_ptr = ""   # oneway の場合、受け取るが捨てられる
     690          retval_ptr = ""   # oneway の場合、受け取るが捨てられる
    717691        else
    718692          # =begin ishikawa modified
     
    724698      end
    725699
    726       # in 方向のå
    727 ¥å‡ºåŠ›ã‚’å
    728 ¥åŠ›
    729       file.print "\n        /* å
    730 ¥åŠ›å¼•æ•°å—取 */\n"
    731       b_get = true    # unmarshal では get
     700      # in 方向の入出力を入力
     701      file.print "\n        /* 入力引数受取 */\n"
     702      b_get = true    # unmarshal では get
    732703      b_marshal  = false
    733704      @index = 2
     
    740711      end
    741712=end
    742       # パケットの受信完了
    743       # mikan 本当は、対象関数を呼出す後に実施したい.呼出しパケットの使用終わりを宣言する目的として
    744       file.print "        /* パケット終わりをチェック */\n"
     713      # パケットの受信完了
     714      # mikan 本当は、対象関数を呼出す後に実施したい.呼出しパケットの使用終わりを宣言する目的として
     715      file.print "        /* パケット終わりをチェック */\n"
    745716      if ! f.is_oneway? then
    746717        b_continue = "true"
     
    752723      file.print "        goto error_reset;\n\n"
    753724=end
    754       # 対象関数を呼出す
    755       file.print "    /* 対象関数の呼出し */\n"
     725      # 対象関数を呼出す
     726      file.print "    /* 対象関数の呼出し */\n"
    756727      if b_void then
    757728        file.print( "    cServerCall_#{f_name}(" )
     
    768739      file.print( " );\n" )
    769740
    770       # 戻り値、出力引数の受取コードの生成
     741      # 戻り値、出力引数の受取コードの生成
    771742
    772743      if ! b_void && ! f.is_oneway? then
     
    775746
    776747      end
    777       # oneway の場合出力、戻り値が無く、受取をå¾
    778 ãŸãªã„(非同期な呼出し)
     748      # oneway の場合出力、戻り値が無く、受取を待たない(非同期な呼出し)
    779749      if ! f.is_oneway? then
    780750        file.print <<EOT
    781     /* 関数処理の終了を通知 */
     751    /* 関数処理の終了を通知 */
    782752    if( ( ercd_ = cEventflag_set( 0x01 ) ) != E_OK ){
    783753      goto error_reset;
Note: See TracChangeset for help on using the changeset viewer.