| 前へ | 次へ | 目次 | 索引 |
ネットワーク (リモート・ホスト) から受信したデータ・ストリームを変換するフィルタ・ルーチンです。漢字変換フィルタは他機種漢字コードから DEC 漢字コードへの変換を行います。
VMS 用法: cond_value データ型: longword (unsigned) アクセス: write only 受け渡し方: by value
stream
VMS 用法: データ型: longword (unsigned) アクセス: read only 受け渡し方: by reference
フィルタ・ストリーム初期化ルーチンで得たフィルタ・ストリーム識別子。変換ストリームの識別のために使用されます。src
VMS 用法: データ型: character string アクセス: read only 受け渡し方: by reference
入力フィルタ・ルーチンにより変換されるソース文字列。文字列の先頭アドレスがパラメータとして渡されます。文字列のバイト数は srclen パラメータが示します。srclen
VMS 用法: データ型: word (unsigned) アクセス: read only 受け渡し方: by reference
src パラメータで渡されるソース文字列のバイト数を示します。dst
VMS 用法: データ型: address of character string アクセス: write only 受け渡し方: by reference
入力フィルタ・ルーチンが変換結果文字列の先頭アドレスを書き込みます。フィルタ初期化ルーチンでバッファ資源数 2 以上を指示した場合,このパラメータで返される値がバッファ資源解放ルーチンが呼び出されるときのパラメータになります。dstlen
VMS 用法: データ型: word (unsigned) アクセス: write only 受け渡し方: by reference
入力フィルタ・ルーチンが変換結果文字列のバイト数を書き込みます。
入力フィルタは,ネットワークあるいはリモート・ホストから受信したデータの変換を行います。変換結果は dst, dstlen パラメータで呼び出し者に返されます。入力フィルタ・ルーチンは,呼び出されるたびにストリームのバッファ資源を消費します。この資源は,不要になった時点でフィルタ資源解放ルーチンを呼び出して,フィルタ・ストリームに返されます。フィルタ資源解放ルーチンが呼び出されてバッファが解放されたら,その資源は再使用することができます。ただし,ストリーム初期化時にあらかじめ確保されたバッファ資源数が 1 の場合は,バッファ資源解放ルーチンが呼び出されなくても, 1 つのバッファ資源を繰り返し使用することになります。漢字コードの変換においては,入力文字列と出力文字列の長さが異なる場合が予想されます。入力フィルタ・ルーチンは変換結果の格納のために,あらかじめ確保されていたバッファ資源,あるいはバッファ資源解放ルーチンでストリームに返されたバッファ資源を使用します。しかし,変換中に変換結果文字列を格納するための領域が不足することが判明したら,その時点でさらに大きな領域を取得する必要があります。
戻り値がサクセスの場合,変換結果の文字列が変換前の文字列の代わりに使われます。 FTP の場合変換結果文字列がファイルに出力され, TELNET の場合変換結果文字列は端末に表示されます。戻り値がエラーの場合,フィルタ処理は解除されフィルタなしの状態に戻ります。
ネットワーク (リモート・ホスト) へ送信するデータを変換するフィルタ・ルーチンです。漢字変換フィルタは DEC 漢字コードから他機種漢字コードへの変換を行います。
VMS 用法: cond_value データ型: longword (unsigned) アクセス: write only 受け渡し方: by value
stream
VMS 用法: データ型: longword (unsigned) アクセス: read only 受け渡し方: by reference
フィルタ・ストリーム初期化ルーチンで得たフィルタ・ストリーム識別子。変換ストリームの識別のために使用されます。src
VMS 用法: データ型: character string アクセス: read only 受け渡し方: by reference
出力フィルタ・ルーチンにより変換されるソース文字列。文字列の先頭アドレスがパラメータとして渡されます。文字列のバイト数は srclen パラメータが示します。srclen
VMS 用法: データ型: word (unsigned) アクセス: read only 受け渡し方: by reference
src パラメータで渡されるソース文字列のバイト数を示します。dst
VMS 用法: データ型: address of character string アクセス: write only 受け渡し方: by reference
出力フィルタ・ルーチンが変換結果文字列の先頭アドレスを書き込みます。フィルタ初期化ルーチンでバッファ資源数 2 以上を指示した場合,このパラメータで返される値がバッファ資源解放ルーチンが呼び出される時のパラメータになります。dstlen
VMS 用法: データ型: word (unsigned) アクセス: write only 受け渡し方: by reference
出力フィルタ・ルーチンが変換結果文字列のバイト数を書き込みます。
出力フィルタは,ネットワークあるいはリモート・ホストへ送信するデータの変換を行います。変換結果は dst,dstlen パラメータで呼び出し者に返されます。出力フィルタ・ルーチンは呼び出されるたびにストリームのバッファ資源を消費します。この資源は,不要になった時点でフィルタ資源解放ルーチンを呼び出して,フィルタ・ストリームに返されます。フィルタ資源解放ルーチンが呼び出されてバッファが解放されたら,その資源は再使用することができます。ただし,ストリーム初期化時にあらかじめ確保されたバッファ資源数が 1 の場合は,バッファ資源解放ルーチンが呼び出されなくても, 1つのバッファ資源を繰返し使用することになります。漢字コードの変換においては,入力文字列と出力文字列の長さが異なる場合が予想されます。出力フィルタ・ルーチンは変換結果の格納のために,あらかじめ確保されていたバッファ資源,あるいはバッファ資源解放ルーチンでストリームに返されたバッファ資源を使用します。しかし,変換中に変換結果文字列を格納するための領域が不足することが判明したら,その時点でさらに大きな領域を取得する必要があります。
戻り値がサクセスの場合,変換結果の文字列が変換前の文字列の代わりに使われます。FTP の場合変換結果文字列がリモート・ホストに送信されます。戻り値がエラーの場合,フィルタ処理は解除され,フィルタなしの状態に戻ります。
入力/出力フィルタ・ルーチンの呼び出しにより消費されたバッファ資源をフィルタ・ストリームに解放するために呼び出されます。
VMS 用法: cond_value データ型: longword (unsigned) アクセス: write only 受け渡し方: by value
stream
VMS 用法: データ型: longword (unsigned) アクセス: read only 受け渡し方: by reference
フィルタ・ストリーム識別子。フィルタ・ストリーム初期化ルーチンにより与えられた識別子です。buffer
VMS 用法: データ型: character string アクセス: read only 受け渡し方: by reference
入力/出力フィルタ・ルーチンが dst パラメータで与えた変換結果文字列の先頭アドレスです。
入力/出力フィルタ・ルーチンの呼び出しにより消費されたバッファ資源をフィルタ・ストリームに解放し,再使用可能にします。ストリーム初期化ルーチンで指示した,あらかじめ確保する資源の数が 1だった場合,フィルタ資源解放ルーチンを呼び出すことなく入力/出力フィルタ・ルーチンが繰り返し呼び出されます。
あらかじめ確保するバッファ資源が 2 以上だった場合,入力/出力フィルタ・ルーチンの呼び出しで dst パラメータとして与えたバッファは,バッファ資源解放ルーチンが呼び出されてストリームに返されるまでは再び使用することはできません。
戻り値がエラーの場合,フィルタ処理は解除されフィルタなしの状態に戻ります。
不要となった変換ストリームを解放するために呼び出されます。
VMS 用法: cond_value データ型: longword (unsigned) アクセス: write only 受け渡し方: by value
stream
VMS 用法: データ型: longword (unsigned) アクセス: read only 受け渡し方: by reference
フィルタ・ストリーム識別子。フィルタ・ストリーム初期化ルーチンにより与えられた識別子です。
フィルタ・ストリーム初期化ルーチンの呼び出しで生成したフィルタ・ストリームを解放します。戻り値がエラーの場合,フィルタ処理は解除されフィルタなしの状態に戻ります。
3.4 フィルタ・ルーチンの例
この例は,STR$UPCASE ルーチンを使ってすべての小文字を大文字に変換するフィルタです。使用言語は VAXC V3.1 です。
次のようにコンパイル/リンクします。^Z は Ctrl/Z を表します。
$ CC UPCASE.C $ LINK/SHARE=TCPIP$UPCASE_FSHR.EXE UPCASE, TT/OPT UNIVERSAL = tcpip_filter ^Z $ |
このフィルタ共用イメージを使用するには, TCPIP$UPCASE_FSHR.EXE をSYS$SHARE: ディレクトリにコピーするか,あるいは TCPIP$UPCASE_FSHR.EXE のあるディレクトリで次のように論理名を定義してください。
$ DEFINE TCPIP$UPCASE_FSHR 'F$ENVIRON("DEFAULT")'TCPIP$UPCASE_FSHR.EXE
|
UPCASE.C のソース・プログラムの例を以降に示します。
| 例 3-1 UPCASE.C の場合 |
|---|
#module UPCASE "V2.2-021"
#include ssdef
#pragma builtins
#define KF_LENGTH sizeof(struct KnjFilter)
struct KnjFilter {
struct KnjFilter *kf_next; /* Forward link */
struct KnjFilter *kf_prev; /* Backward link */
unsigned short int kf_size; /* Length */
unsigned char kf_type; /* Type */
unsigned char kf_fill; /* Unused */
int (*kf_begin_filter)(); /* Allocate filter stream */
int (*kf_hton_filter)(); /* Host to net filter */
int (*kf_ntoh_filter)(); /* Net to host filter */
int (*kf_release_filter)(); /* Resource deallocation */
int (*kf_end_filter)(); /* Deallocate filter stream */
} ;
#define KB_LENGTH (sizeof(struct KnjBuf)-sizeof(char))
struct KnjBuf { /* */
struct KnjBuf *kb_next; /* Forward link */
struct KnjBuf *kb_prev; /* Backward link */
long int kb_size; /* Length */
char kb_data [1]; /* Data */
} ;
#define KC_LENGTH sizeof(struct KnjContext)
struct KnjContext { /* */
struct KnjContext *kc_next; /* Forward link */
struct KnjContext *kc_prev; /* Backward link */
unsigned short int kc_size; /* Length */
unsigned char kc_type; /* Type */
char kc_fill; /* Unused */
long int kc_application; /* Name of caller */
struct KnjBuf *kc_kb [2]; /* Queue header of free KnjBuf */
struct KnjBuf *kc_kbinuse [2]; /* Queue header of in-use KnjBuf */
long int kc_flags; /* Flags, see KC_ */
} ;
#define KC_M_RELREQ 1
#define KC_M_PRESERVE 2
#define HLA_FTP 1 /* File Transfer Protocol */
#define HLA_TELNET 2 /* TELNET, virturl terminal */
#define HLA_SMTP 3 /* Simple Mail Transfer Protocol */
#define HLA_LPR 4 /* LPR */
#define HLA_MAX 4
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
/*
* The macros used to check condition value
*/
#define issuccess(r) (1&(r))
#define iserror(r) (!issuccess(r))
#define check(f) {long $$r=(f);if(iserror($$r))lib$stop($$r);}
#define onerror(f,a) {long $$r=(f);if(iserror($$r)) a;}
/*
* When filter routines realize that KanjiBuf is too short to
* store resultant string, ReplaceKB macro is executed.
*/
#define ReplaceKB(kc,kb,d,dl){\
long l = (kb)->kb_size - (dl);\
if(((kb) = NewBuf((kc),(kb),l)) == 0) return(SS$_INSFMEM);\
(d) = (kb)->kb_data + l; (dl) = (kb)->kb_size - l;}
#define Display(m){\
static char d$[]=m; long d[]={sizeof(d$)-1,d$}; lib$put_output(d);}
static begin_filter();
static end_filter();
static hton_filter();
static ntoh_filter();
static release_filter();
static struct KnjBuf *GetBuf();
static struct KnjBuf *NewBuf();
static handler();
static long KnjContext[] = {KnjContext,KnjContext};
/*
* tcpip_filter
*
* This routine fills Kanji Filter block with entry
* points of all filter routines. To make the address
* of this routine known to external, TCPIP$UPCASE_FSHR
* is an universal symbol.
*/
tcpip_filter(kf)
register struct KnjFilter *kf;
{
/*
* Place known entry points of filter routine in KnjFilter block.
*/
kf->kf_begin_filter = begin_filter;
kf->kf_hton_filter = hton_filter;
kf->kf_ntoh_filter = ntoh_filter;
kf->kf_end_filter = end_filter;
kf->kf_release_filter = release_filter;
return(SS$_NORMAL);
}
/*
* BEGIN_FILTER
*
* Begin_filter routine is called by TCPIP applications
* to get filter stream. Filter stream preserves several
* stream specific information.
* When a value of resource arguent is 1, TCPIP application
* do not call release_filter routine after a call of
* ntoh_filter or hton_filter. When a value of the argument
* is greater than 1, release_filter routine must be called
* after a call of ntoh_filter or hton_filter.
*/
static begin_filter(stream,application,resource)
u_long *stream;
u_long *application;
long *resource;
{
register struct KnjContext *kc;
register struct KnjBuf *kb;
static char *t;
/*
* Establish a condition handler.
* R13 = FP.
*/
((long *)_READ_GPR(13))[0] = handler;
/*
* Allocate Kanji Filter Context block for the stream.
*/
onerror(lib$get_vm(&sizeof(struct KnjContext),&t), return($$r));
kc = (struct KnjContext *)t;
kc->kc_size = sizeof(struct KnjContext);
kc->kc_type = 0;
kc->kc_fill = 0;
kc->kc_application = *application;
kc->kc_kb[1] = kc->kc_kb[0] = kc->kc_kb;
kc->kc_kbinuse[1] = kc->kc_kbinuse[0] = kc->kc_kbinuse;
kc->kc_flags = 0;
/*
* Queue it
*/
_INSQUE((void *)kc,(void *)KnjContext);
/*
* Allocate 1 Kanji Buff. Length of buffer
* depends on high level application.
*/
kb = GetBuf(kc,512);
if(kb == 0) {
end_filter(kc);
*stream = 0;
return(SS$_INSFMEM);
}
/*
* Queue the Kanji Buff into Kanji Context.
*/
_INSQUE((void *)kb,(void *)kc->kc_kb);
if(*resource > 1)
kc->kc_flags |= KC_M_RELREQ;
*stream = (long)kc;
return(SS$_NORMAL);
}
/*
* END_FILTER
*
* This routine is called when TCPIP application no longer
* needs filter stream, that was previously allocated by
* begin_filter call. Note that this routine must be called
* after all resource has been released by release_filter
* calls.
*/
static end_filter(stream)
u_long *stream;
{
register struct KnjContext *kc;
register struct KnjBuf *kb;
static char *t;
/*
* Establish a condition handler.
* R13 = FP.
*/
((long *)_READ_GPR(13))[0] = handler;
/*
* Remove all Kanji Buffers from queue.
* Deallocate memory.
*/
kc = (struct KnjContext *)*stream;
while(_REMQUE((void *)kc->kc_kbinuse[0],(void **)&kb) != 2) {
kb->kb_size += KB_LENGTH;
lib$free_vm(&kb->kb_size,&kb);
}
while(_REMQUE((void *)kc->kc_kb[0],(void **)&kb) != 2) {
kb->kb_size += KB_LENGTH;
lib$free_vm(&kb->kb_size,&kb);
}
/*
* Release Kanji Context block.
*/
_REMQUE((void *)kc,(void **)&t);
lib$free_vm(&kc->kc_size,&t);
return(SS$_NORMAL);
}
/*
* HTON_FILTER
*
* Translates from Host representation to Network representation.
*/
static hton_filter(stream,src,slen,dst,dlen)
u_long *stream;
u_char *src,**dst;
u_short *slen,*dlen;
{
register struct KnjBuf *kb;
register struct KnjContext *kc;
register unsigned char *s,*d;
register long sl,dl;
long sdsc[2],ddsc[2];
/*
* Establish a condition handler.
* R13 = FP.
*/
((long *)_READ_GPR(13))[0] = handler;
kc = (struct KnjContext *)*stream;
kb = kc->kc_kb[0];
/*
* If multi-buffer was requested in begin_filter,
* we will remque Kanji buffer, then insque it
* to in-use queue later. The buffer can be
* replaced by larger one when we realize
* the size of buffer is insufficient.
*/
if(kc->kc_flags) {
if(_REMQUE((void *)kb,(void **)&kb) == 2)
if((kb = GetBuf(kc,*slen)) == 0) {
*dlen = 0;
*dst = (char *)0;
return(SS$_INSFMEM);
}
}
s = src;
d = kb->kb_data;
dl = kb->kb_size;
sl = *slen;
if(sl == 0)
goto end;
if(sl > dl) {
ReplaceKB(kc,kb,d,dl);
}
sdsc[0] = sl, sdsc[1] = s;
ddsc[0] = sl, ddsc[1] = d;
str$upcase(ddsc,sdsc);
end:
/*
* Insert Kanji Buf to in-use queue,
* if release_filter should be called later.
*/
if(kc->kc_flags)
_INSQUE((void *)kb,(void *)kc->kc_kbinuse);
/*
* Give resultant buffer to user.
*/
*dlen = sl;
*dst = d;
return(SS$_NORMAL);
}
/*
* NTOH_FILTER
*
* Translates Network representation to Host representation.
*/
static ntoh_filter(stream,src,slen,dst,dlen)
u_long *stream;
u_char *src,**dst;
u_short *slen,*dlen;
{
register struct KnjBuf *kb;
register struct KnjContext *kc;
register unsigned char *s,*d;
register long sl,dl;
long sdsc[2],ddsc[2];
/*
* Establish a condition handler.
* R13 = FP.
*/
((long *)_READ_GPR(13))[0] = handler;
kc = (struct KnjContext *)*stream;
kb = kc->kc_kb[0];
/*
* If multi-buffer was requested in begin_filter,
* we will remque Kanji buffer, then insque it
* to in-use queue later. The buffer can be
* replaced by larger one when we realize
* the size of buffer is insufficient.
*/
if(kc->kc_flags) {
if(_REMQUE((void *)kb,(void **)&kb) == 2) {
if((kb = GetBuf(kc,*slen)) == 0) {
/*
* Woops no buffer available...
*/
*dlen = 0;
*dst = (char *)0;
return(SS$_INSFMEM);
}
}
}
s = src;
d = kb->kb_data;
dl = kb->kb_size;
sl = *slen;
if(sl == 0)
goto end;
if(sl > dl) {
ReplaceKB(kc,kb,d,dl);
}
sdsc[0] = sl, sdsc[1] = s;
ddsc[0] = sl, ddsc[1] = d;
str$upcase(ddsc,sdsc);
end:
/*
* Insert Kanji Buf to in-use queue,
* if release_filter should be called later.
*/
if(kc->kc_flags)
_INSQUE((void *)kb,(void *)kc->kc_kbinuse);
/*
* Give resultant buffer to user.
*/
*dlen = sl;
*dst = d;
return(SS$_NORMAL);
}
/*
* RELEASE_FILTER
*
* This routine is called to release resource. The buffers
* allocated by hton_filter or ntoh_filter routine must be
* deallocated, unless value of resource argument of begin_filter
* call was 1. When the value one for resource argument of
* begin_filter routine had been specified, release_filter
* must not be called.
*/
static release_filter(stream,c)
u_long *stream;
u_char *c;
{
register struct KnjBuf *kb;
register struct KnjContext *kc;
/*
* Establish a condition handler.
* R13 = FP.
*/
((long *)_READ_GPR(13))[0] = handler;
kc = *stream;
kb = c - KB_LENGTH;
{long z;_REMQUE((void *)kb,(void **)&z);}
_INSQUE((void *)kb,(void *)kc->kc_kb);
return(SS$_NORMAL);
}
/*
* GETBUF
*
* Allocates filter routine internal buffers. Ntoh_filter and
* hton_filter fills the buffer with resultant string, and
* give it to TCPIP application.
*/
static long newlength = 0;
static struct KnjBuf *
GetBuf(kc,min)
register struct KnjContext *kc;
long min;
{
register struct KnjBuf *kb;
long len;
if(newlength == 0)
switch(kc->kc_application) {
case HLA_FTP: newlength = 4096*2; break;
case HLA_TELNET:
case HLA_SMTP:
case HLA_LPR:
default: newlength = 1024*2; break;
};
len = (min * 125 / 100 + 511) & ~511;
if(newlength < len)
newlength = len;
onerror(lib$get_vm(&newlength,&kb), return(0));
kb->kb_size = newlength - KB_LENGTH;
return(kb);
}
/*
* NEWBUF
*
* This routine replaces a short buffer by a large buffer,
* which is newly allocated. Contents of a short buffer is
* copied to a large buffer.
* See also ReplaceKB macro.
*/
static struct KnjBuf *
NewBuf(kc,kb,l)
register struct KnjContext *kc;
register struct KnjBuf *kb;
long l;
{
struct KnjBuf *kb0;
kb->kb_size += KB_LENGTH;
newlength = (kb->kb_size * 125 / 100 + 511) & ~511;
if(iserror(lib$get_vm(&newlength,&kb0))) {
if(!kc->kc_flags)
_REMQUE(kb,&kb);
lib$free_vm(&kb->kb_size,&kb);
return(0);
}
kb0->kb_size = newlength - KB_LENGTH;
_MOVC3(l,kb->kb_data,kb0->kb_data);
if(!kc->kc_flags) {
_REMQUE(kb,&kb);
_INSQUE(kb0,kc->kc_kb);
}
lib$free_vm(&kb->kb_size,&kb);
return(kb0);
}
/*
* HANDLER
*
* The condition handler routine, which prevents TCPIP applications
* from fatal errors of filter routine.
*/
static handler(sig,mec)
u_long *sig;
u_long *mec;
{
if(sig[1] == SS$_UNWIND)
return;
Display("Filter routine has detected fatal condition.");
sys$putmsg(sig,0,0);
mec[3] = sig[1];
sys$unwind(&1,0);
}
|
| 前へ | 次へ | 目次 | 索引 |