Changeset 34 for SimpleSample/trunk
- Timestamp:
- Jun 24, 2012, 7:42:09 PM (11 years ago)
- Location:
- SimpleSample/trunk
- Files:
-
- 4 added
- 2 deleted
- 9 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
SimpleSample/trunk/README.txt
r32 r34 1 Simple な Sample1 TECS の Simple な Sample 2 2 3 3 2012年 6月17日 … … 9 9 10 10 【概要】 11 11 12 TECS のもっとも単純なサンプルです。 exerb 版の TECS ジェネレータと 12 cygwin 版の gcc だけで動作します。 13 14 cygwin 上で pthread を用いた tTask 等のセルタイプを用意していますが、 15 あくまでテスト用であり、完成度はもう一歩です。いろいろ変更して試そうと 16 すると、期待した動作にならない可能性が高いのでご注意ください。 13 cygwin 版の gcc だけで動作します。Linux などの POSIX 環境でも動作しま 14 す。 15 exerb 版で動作しますので、Ruby や racc のインストールする必要がありま 16 せん。 17 17 18 18 【動作環境】 19 19 20 cygwin 上でビルドし動作します。Linux などで動作させるときは Makefile 21 の TECSGEN を tecsgen.exe から tecsgen に変更してください。 20 cygwin 上でビルドし動作します。2012.6.2 に発行された tecs_package 21 (TECS ジェネレータ V1.1.0.4 を同梱) を用いてください。exerb 版を用いる 22 ようになっているため、Ruby インタープリターは不要です。 22 23 23 【使用方法】 24 exerb 版とは ruby インタプリタと TECS ジェネレータが一体の exe 化さ 25 れたもので、ruby インタプリタのインストールを必要としません。 26 27 Linux などの POSIX 環境でも動作させることができます。その場合 Makefile 28 の TECSGEN_EXE を tecsgen.exe から tecsgen に変更してください。Ruby 29 1.8 がインストールされている必要があります。Ruby 1.9 には対応しません。 30 31 【準備】 24 32 25 33 1) ファイルの展開 26 34 27 35 tecs_package ディレクトリの直下 asp+tecs, tecsgen の並びに 28 SimpleSample を置いてください。exerb 版 36 SimpleSample を置いてください。exerb 版を用いる都合上、tecsgen コマン 37 ド引数に与えるパスは、すべて相対パスで指定しています。 29 38 30 39 tecs_package-+- asp+tecs … … 33 42 | 34 43 +- SimpleSample -+- SimpleSample 35 (※) | 36 +- SimpleSampleOpaqueRPC 37 | 38 +- SimpleSampleTransparentRPC 44 (※) | 45 +- SimpleSampleTrace 46 | 47 +- SimpleSampleOpaqueRPC 48 | 49 +- SimpleSampleTransparentRPC 39 50 40 51 ※ svn の trunk のディレクトリの位置に対応します。名前は変更しても構いません。 41 52 42 2) 準備53 2) パスの設定 43 54 44 cygwin コンソールを開き、以下のような方法で set_env.sh ないの PATH 等45 を取り込みます。55 cygwin コンソールを開き、以下のような方法で set_env.sh 内の PATH 等を 56 取り込みます。 46 57 47 58 % cd tecs_package/tecsgen … … 49 60 50 61 exerb 版を使用するため、TECS ジェネレータのビルドは不要です。 62 63 【ビルドと実行】 51 64 52 65 3) 直接結合版のビルドと実行 … … 62 75 % ./SimpleSample.exe 63 76 64 ・trace ありのビルド 77 4) 直接結合の TracePlugin あり版のビルドと実行 65 78 66 % cd tecs_package/SimpleSample/SimpleSample 67 % make tecs -f Makefile-trace68 % make all -f Makefile-trace79 % cd tecs_package/SimpleSample/SimpleSampleTrace 80 % make tecs 81 % make all 69 82 70 83 ・実行 71 84 72 % ./SimpleSample -trace.exe85 % ./SimpleSample.exe 73 86 74 4) transparent RPC 版のビルドと実行87 5) transparent RPC 版のビルドと実行 75 88 76 89 ・ビルド … … 88 101 わかりにくいですが、Simple と Sample は異なるタスクで実行されています。 89 102 90 4) transparentRPC 版のビルドと実行103 6) opaque RPC 版のビルドと実行 91 104 92 105 ・ビルド … … 103 116 % ./rSample/SimpleSample-rSample.exe 104 117 105 2 つ目のコンソールでクライアント側を起動します。118 次に 2 つ目のコンソールでクライアント側を起動します。 106 119 107 120 % cd tecs_package/SimpleSample/SimpleSampleOpaqueRPC … … 113 126 が、これは out 引数で返されたものを表示しているためです。 114 127 115 重要なことは、tSimple.c, tSample.c は、まったく無変更で 4 つのパターンに 116 対応しています。簡単に再利用が図られることがわかります。 128 【ポイント】 129 130 ポイントは、各 CDL 内の tSimple, tSample の定義、セルタイプコード 131 tSimple.c, tSample.c は、まったく無変更で 4 つのパターンに対応している 132 ことです。再利用が図られることがわかります。 117 133 118 134 【次のステップ】 … … 123 139 まずは、これの手順を理解しましょう。 124 140 141 ・もう一組インスタンスを設ける 125 142 143 【cygwin_kernel について】 144 145 cygwin 上で pthread を用いた tTask 等のセルタイプを用意していますが、 146 テストドライバーまたはスタブであり、ほとんど機能は備わっていません。 147 -
SimpleSample/trunk/SimpleSample/Makefile
r33 r34 1 # このファイルは tecsgen により自動生成されました2 # Makefile.temp は gen の一つ上のディレクトリに移して使用します3 # % mv Makefile.temp Makefile4 #5 # clean のデフォルト動作は $(GEN_DIR)/Makefile.* を削除します6 #7 # このファイルは GNU make で gcc を用い POSIX 環境で動作するモジュールをビルドするのに適切なように生成されています8 # vpath, CFLAGS, OTHER_OBJS などを調整する必要があるかもしれません9 # 他の環境やターゲットの場合、このファイルを元に変更する必要があります10 11 1 # 変数 #_MVAR_# 12 TARGET = SimpleSample -trace.exe2 TARGET = SimpleSample.exe 13 3 TIMESTAMP = tecsgen.timestamp 14 4 TECSGEN_EXE = tecsgen.exe … … 49 39 50 40 $(TIMESTAMP) : $(TECS_IMPORTS) 51 $(TECSGEN_EXE) -k euc -I src -I gen -I ../../tecsgen/tecs/../test/cygwin -I ../../tecsgen/tecs SimpleSample -trace.cdl41 $(TECSGEN_EXE) -k euc -I src -I gen -I ../../tecsgen/tecs/../test/cygwin -I ../../tecsgen/tecs SimpleSample.cdl 52 42 touch $(TIMESTAMP) 53 43 … … 71 61 $(CC) -c $(CFLAGS) -o $@ $< 72 62 73 $(_TECS_OBJ_DIR)tTracePlugin_sSample.o : tTracePlugin_sSample.c74 $(CC) -c $(CFLAGS) -o $@ $<75 -
SimpleSample/trunk/SimpleSample/SimpleSample.cdl
r30 r34 9 9 * | |Body | | | | 10 10 * +-------------+ +-------------+ +-------------+ 11 * 12 *・シグニチャ記述 13 * 14 * sSample … 関数インタフェースの定義 15 * 慣習として接頭文字 s を付加する 16 * 17 * シグニチャ sSampleには 2 つの関数 sayHello と howAreYou がある。 18 * セルタイプ tSample の提供する機能となるので、sSample という名前にした。 19 * 20 *・セルタイプ記述 21 * 22 * tSimple … 呼び元のセルタイプ 23 * tSample … 呼び先のセルタイプ 24 * 慣習として接頭文字 t を付加する 25 * tTask … cygwin 用の tTask は cygwin_kernel.cdl を import することで使用できる 26 * 27 *・組上げ記述 28 * 29 * Simple … 呼び元のセル 30 * Sample … 呼び先のセル 31 * Task … タスクセル 32 * 33 * セルタイプコード: 34 * src/tSimple.c … 呼び元のセルタイプコード 35 * src/tSample.c … 呼び先のセルタイプコード 36 * 11 37 */ 12 13 38 14 39 // cygwin 用の簡易な型定義 15 40 import( <cygwin_kernel.cdl> ); 16 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); でよい41 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); に相当する 17 42 43 // シグニチャ sSample 18 44 signature sSample { 19 45 ER sayHello( [in]int32_t times ); … … 21 47 }; 22 48 49 // セルタイプ tSample 23 50 celltype tSample { 24 51 entry sSample eEnt; 25 52 }; 26 53 27 [singleton,active] 54 // セルタイプ tSimple 28 55 celltype tSimple { 29 56 call sSample cCall; … … 31 58 }; 32 59 60 // セル Sample 33 61 cell tSample Sample { 34 62 }; 35 63 64 // セル Simple 36 65 cell tSimple Simple { 37 66 cCall = Sample.eEnt; 38 67 }; 39 68 69 // セル Task 40 70 cell tTask Task { 41 71 cBody = Simple.eBody; -
SimpleSample/trunk/SimpleSample/src/tSimple.c
r30 r34 30 30 * #[</ENTRY_FUNC>]# */ 31 31 void 32 eBody_main( )32 eBody_main(CELLIDX idx) 33 33 { 34 CELLCB *p_cellcb; 34 35 char buf[256]; 36 if (VALID_IDX(idx)) { 37 p_cellcb = GET_CELLCB(idx); 38 } 39 else { 40 /* エラー処理コードをここに記述します */ 41 } /* end if VALID_IDX(idx) */ 35 42 36 43 #define N_HELLO 3 -
SimpleSample/trunk/SimpleSampleOpaqueRPC/SimpleSample.cdl
r30 r34 11 11 * | |Body | | | | | | 12 12 * +-------------+ +-------------+ +-------------+ +-------------+ 13 * 14 * * SimpleSample/SimpleSample.cdl を参照 15 * * rSimple, rSample リージョンに分割し、それぞれを linkunit (リンク単位) とした 16 * * リージョン間には、OpaqueRPCPlugin で OpaqueRPC Channel を挿入する 17 * * TaskMain はチャンネルオープン後、 tSimple を呼び出す 13 18 */ 14 19 … … 22 27 import( <tSocketChannel.cdl> ); 23 28 29 // シグニチャ sSample 24 30 signature sSample { 25 31 ER sayHello( [in]int32_t times ); … … 27 33 }; 28 34 35 // セルタイプ tSample 29 36 celltype tSample { 30 37 entry sSample eEnt; 31 38 }; 32 39 33 [singleton,active] 40 // セルタイプ tSimple 34 41 celltype tSimple { 35 42 call sSample cCall; … … 37 44 }; 38 45 46 // セルタイプ tTaskMain (クライアント側チャンネルをオープンするために用いる) 39 47 celltype tTaskMain { 40 48 entry sTaskBody eBody; … … 45 53 [linkunit] 46 54 region rSample { 55 // セル SysLog 47 56 cell tSysLog SysLog { 48 57 }; 58 // セル Kernel 49 59 cell tKernel Kernel { 50 60 }; 61 // セル Sample 51 62 cell tSample Sample { 52 63 }; … … 57 68 "PPAllocatorSize=1024," 58 69 "clientChannelCell= 'ClientChannel', " // クライアント側チャンネルセル名 70 // このオプションでは、複数結合に対応できない 71 // 複数結合に対応するには、複数結合可能なオプション指定とするか、SharedOpaqueRPCPlugin を用いる 72 // 複数結合可能なオプション指定例は test/opaqueRPC 下にサンプルコードがある 59 73 )] 60 74 region rSimple { 75 // セル SysLog 61 76 cell tSysLog SysLog { 62 77 }; 78 // セル Simple 63 79 cell tSimple Simple { 64 80 cCall = rSample::Sample.eEnt; 65 81 }; 82 // セル TaskMain 66 83 cell tTaskMain TaskMain { 67 84 cBody = Simple.eBody; 68 85 cOpener = ClientChannel.eOpener; 69 86 }; 70 87 // セル Task 71 88 cell tTask Task { 72 cBody = TaskMain.eBody; 89 cBody = TaskMain.eBody; // TaskMain に変更 73 90 priority = 11; 74 91 stackSize = 1024; -
SimpleSample/trunk/SimpleSampleOpaqueRPC/src/tSimple.c
r30 r34 30 30 * #[</ENTRY_FUNC>]# */ 31 31 void 32 eBody_main( )32 eBody_main(CELLIDX idx) 33 33 { 34 CELLCB *p_cellcb; 34 35 char buf[256]; 36 if (VALID_IDX(idx)) { 37 p_cellcb = GET_CELLCB(idx); 38 } 39 else { 40 /* エラー処理コードをここに記述します */ 41 } /* end if VALID_IDX(idx) */ 35 42 36 43 #define N_HELLO 3 -
SimpleSample/trunk/SimpleSampleTrace/Makefile
r30 r34 1 # このファイルは tecsgen により自動生成されました2 # Makefile.temp は gen の一つ上のディレクトリに移して使用します3 # % mv Makefile.temp Makefile4 #5 # clean のデフォルト動作は $(GEN_DIR)/Makefile.* を削除します6 #7 # このファイルは GNU make で gcc を用い POSIX 環境で動作するモジュールをビルドするのに適切なように生成されています8 # vpath, CFLAGS, OTHER_OBJS などを調整する必要があるかもしれません9 # 他の環境やターゲットの場合、このファイルを元に変更する必要があります10 11 1 # 変数 #_MVAR_# 12 TARGET = SimpleSample -trace.exe13 TIMESTAMP = tecsgen.timestamp -trace14 TECSGEN_EXE = tecsgen 2 TARGET = SimpleSample.exe 3 TIMESTAMP = tecsgen.timestamp 4 TECSGEN_EXE = tecsgen.exe 15 5 BASE_DIR = . 16 6 CC = gcc … … 18 8 LD = gcc 19 9 LDFLAGS = 20 GEN_DIR = $(BASE_DIR)/gen -trace10 GEN_DIR = $(BASE_DIR)/gen 21 11 SRC_DIR = $(BASE_DIR)/src 22 12 _TECS_OBJ_DIR = $(GEN_DIR)/ … … 49 39 50 40 $(TIMESTAMP) : $(TECS_IMPORTS) 51 $(TECSGEN_EXE) -g gen -trace -k euc -I src -I gen -I ../../tecsgen/tecs/../test/cygwin -I ../../tecsgen/tecs SimpleSample-trace.cdl41 $(TECSGEN_EXE) -g gen -k euc -I src -I gen -I ../../tecsgen/tecs/../test/cygwin -I ../../tecsgen/tecs SimpleSample.cdl 52 42 touch $(TIMESTAMP) 53 43 -
SimpleSample/trunk/SimpleSampleTrace/SimpleSample.cdl
r30 r34 5 5 * | | | | | | 6 6 * | tTask | sTaskBody | tSimple | sSample | tSample | 7 * | Task |-----------|> Simple | ----------|> Sample |7 * | Task |-----------|> Simple |==========|> Sample | 8 8 * | |cTask eBody| |cCall eEnt| | 9 9 * | |Body | | | | 10 10 * +-------------+ +-------------+ +-------------+ 11 * 12 * * SimpleSample/SimpleSample.cdl を参照 13 * * この例では Trace プラグインが指定される。以下の※を参照 14 * * Trace プラグインのため tSysLog, tKernel を用いる 11 15 */ 12 13 16 14 17 // cygwin 用の簡易な型定義 15 18 import( <cygwin_kernel.cdl> ); 16 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); でよい19 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); に相当する 17 20 21 // tSysLog の定義 (Trace の出力先) 18 22 import( <tSysLog.cdl> ); 19 23 24 // セル SysLog (Trace の出力先) 20 25 cell tSysLog SysLog { 21 26 }; 27 // セル Kernel (Trace の時刻を得る) 22 28 cell tKernel Kernel { 23 29 }; 24 30 31 // シグニチャ sSample 25 32 signature sSample { 26 33 ER sayHello( [in]int32_t times ); … … 28 35 }; 29 36 37 // セルタイプ tSample 30 38 celltype tSample { 31 39 entry sSample eEnt; 32 40 }; 33 41 34 [singleton,active] 42 // セルタイプ tSimple 35 43 celltype tSimple { 36 44 call sSample cCall; … … 38 46 }; 39 47 48 // セル Sample 40 49 cell tSample Sample { 41 50 }; 42 51 52 // セル Simple 43 53 cell tSimple Simple { 44 [through(TracePlugin,"")] 54 [through(TracePlugin,"")] // <<< ※ この行を挿入 45 55 cCall = Sample.eEnt; 46 56 }; 47 57 58 // セル Task 48 59 cell tTask Task { 49 60 cBody = Simple.eBody; … … 52 63 taskAttribute = C_EXP( "TA_ACT" ); 53 64 }; 65 -
SimpleSample/trunk/SimpleSampleTransparentRPC/SimpleSample.cdl
r30 r34 9 9 * | |Body | | | | 10 10 * +-------------+ +-------------+ +-------------+ 11 * 12 * * SimpleSample/SimpleSample.cdl を参照 13 * * この例では Transparent プラグインが指定される。以下の※を参照 14 * * Tranceparent プラグインのため tSysLog, rpc, tDataqueOWChannel を import 11 15 */ 12 13 16 14 17 // cygwin 用の簡易な型定義 15 18 import( <cygwin_kernel.cdl> ); 16 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); でよい19 // TECS 対応 TOPPERS/ASP ならば import( <kernel.cdl> ); に相当する 17 20 21 // tSysLog の定義 18 22 import( <tSysLog.cdl> ); 23 24 // SysLog の定義 (RPC のエラーメッセージ出力) 25 cell tSysLog SysLog { 26 }; 27 28 // RPC 関連のセルタイプの定義 19 29 import( <rpc.cdl> ); 30 // Transparent RPC に用いる Dataqueue OneWay チャンネルセルタイプの定義 20 31 import( <tDataqueueOWChannel.cdl> ); 21 32 33 // シグニチャ sSample 22 34 signature sSample { 23 35 ER sayHello( [in]int32_t times ); … … 25 37 }; 26 38 39 // セルタイプ tSample 27 40 celltype tSample { 28 41 entry sSample eEnt; 29 42 }; 30 43 31 [singleton,active] 44 // セルタイプ tSimple 32 45 celltype tSimple { 33 46 call sSample cCall; … … 35 48 }; 36 49 37 cell tSysLog SysLog { 38 }; 39 50 // セル Sample 40 51 cell tSample Sample { 41 52 }; 42 53 54 // セル Simple 43 55 cell tSimple Simple { 44 [through(RPCPlugin,"")] 56 [through(RPCPlugin,"")] // <<< ※ この行を挿入 45 57 cCall = Sample.eEnt; 46 58 }; 47 59 60 // セル Task 48 61 cell tTask Task { 49 62 cBody = Simple.eBody; -
SimpleSample/trunk/SimpleSampleTransparentRPC/src/tSample.c
r30 r34 1 /*2 * このファイルは tecsgen によりテンプレートとして自動生成されました3 * このファイルを編集して使用することが意図されていますが4 * tecsgen の再実行により上書きされてしまうため、通常5 * gen/tSample_template.c => src/tSample.c6 * のように名前, フォルダを変更してから修正します7 */8 1 /* #[<PREAMBLE>]# 9 2 * #[<...>]# から #[</...>]# で囲まれたコメントは編集しないでください 10 3 * tecsmerge によるマージに使用されます 11 4 * 5 * このファイルは tecsgen によりテンプレートとして自動生成されました 6 * このファイルを編集して使用することが意図されていますが 7 * tecsgen の再実行により上書きされてしまうため、通常 8 * gen/tSimpleServer_template.c => src/tSimpleServer.c 9 * のように名前, フォルダを変更してから修正します 10 * 12 11 * #[</PREAMBLE>]# */ 13 12 14 /* プロトタイプ宣言や変数の定義をここに書きます #_PAC_# */ 13 #include <stdio.h> 14 #include <string.h> 15 15 #include "tSample_tecsgen.h" 16 #include <stdio.h>17 16 18 17 #ifndef E_OK 19 #define E_OK 0 /* success*/20 #define E_ID (-18) /* illegal ID*/18 #define E_OK 0 /* 正常終了 */ 19 #define E_ID (-18) /* 不正ID番号 */ 21 20 #endif 21 22 22 23 23 /* 受け口関数 #_TEPF_# */ … … 26 26 * signature: sSample 27 27 * context: task 28 * params: 28 29 * #[</ENTRY_PORT>]# */ 29 30 … … 31 32 * name: eEnt_sayHello 32 33 * global_name: tSample_eEnt_sayHello 33 * oneway: false34 * #[ </ENTRY_FUNC>]# */34 * oneway: 35 * #[/ENTRY_FUNC>]# */ 35 36 ER 36 37 eEnt_sayHello(CELLIDX idx, int32_t times) … … 43 44 else { 44 45 return(E_ID); 45 } /* end if VALID_IDX(idx) */46 } 46 47 47 /* ここに処理本体を記述します #_TEFB_# */ 48 /* ここに処理本体を記述します */ 49 printf( "Sample: " ); 48 50 while( times-- > 0 ) 49 printf( " Hello!" );50 p uts( "" );51 printf( "hello " ); 52 printf( "\n" ); 51 53 52 54 return(ercd); … … 56 58 * name: eEnt_howAreYou 57 59 * global_name: tSample_eEnt_howAreYou 58 * oneway: false59 * #[ </ENTRY_FUNC>]# */60 * oneway: 61 * #[/ENTRY_FUNC>]# */ 60 62 ER 61 63 eEnt_howAreYou(CELLIDX idx, char_t* buf, int32_t len) … … 68 70 else { 69 71 return(E_ID); 70 } /* end if VALID_IDX(idx) */72 } 71 73 72 /* ここに処理本体を記述します #_TEFB_#*/73 strncpy( buf, " I'm fine thank you.", len );74 /* ここに処理本体を記述します */ 75 strncpy( buf, "Sample: I'm fine!", len ); 74 76 75 77 return(ercd); 76 78 } 77 79 78 /* #[<POSTAMBLE>]# 79 * これより下に非受け口関数を書きます 80 * #[</POSTAMBLE>]#*/ 80 -
SimpleSample/trunk/SimpleSampleTransparentRPC/src/tSimple.c
r30 r34 1 /*2 * このファイルは tecsgen によりテンプレートとして自動生成されました3 * このファイルを編集して使用することが意図されていますが4 * tecsgen の再実行により上書きされてしまうため、通常5 * gen/tSimple_template.c => src/tSimple.c6 * のように名前, フォルダを変更してから修正します7 */8 1 /* #[<PREAMBLE>]# 9 2 * #[<...>]# から #[</...>]# で囲まれたコメントは編集しないでください … … 17 10 * #[</PREAMBLE>]# */ 18 11 19 /* プロトタイプ宣言や変数の定義をここに書きます #_PAC_# */ 12 #include <stdio.h> 20 13 #include "tSimple_tecsgen.h" 21 #include <stdio.h>22 14 23 15 #ifndef E_OK 24 #define E_OK 0 /* success*/25 #define E_ID (-18) /* illegal ID*/16 #define E_OK 0 /* 正常終了 */ 17 #define E_ID (-18) /* 不正ID番号 */ 26 18 #endif 27 19 … … 38 30 * #[</ENTRY_FUNC>]# */ 39 31 void 40 eBody_main( )32 eBody_main(CELLIDX idx) 41 33 { 42 #define BUF_LEN 64 43 char_t buf[64]; 44 #define HELLO_TIMES (3) 45 puts( "calling sayHello" ); 46 cCall_sayHello( HELLO_TIMES ); 47 cCall_howAreYou( buf, BUF_LEN ); 34 CELLCB *p_cellcb; 35 char buf[256]; 36 if (VALID_IDX(idx)) { 37 p_cellcb = GET_CELLCB(idx); 38 } 39 else { 40 /* エラー処理コードをここに記述します */ 41 } /* end if VALID_IDX(idx) */ 42 43 #define N_HELLO 3 44 printf( "Simple: Say hello %d times.\n", N_HELLO ); 45 cCall_sayHello( N_HELLO ); /* 呼び口 cCall の sayHello を呼び出す */ 46 47 printf( "Simple: How are you?\n" ); 48 cCall_howAreYou( buf, sizeof buf ); /* 呼び口 cCall の howAreYou を呼び出す */ 48 49 puts( buf ); 49 50 }
Note:
See TracChangeset
for help on using the changeset viewer.