IFS のストリーム・ファイルの内容は WRKLNK でも表示することができるのだが
WRKLNK では
・内容表示と HEX 表示が左右に表示されてしまうので HEX がわかりづらい。
・HEX で内容を修正することができない。
・UNI_CODE に対応していない。
の問題がある。
内容と HEX が左右の別々の位置では非常にわかりにくいし
DSPFL のように HEX で内容を修正することができない。
UNI コードに対応していないのも不満である。
UNI コードが普及している現在では CCSID : 1208 (UTF-8) , 1200 (UTF-16) ,
1202 (UTF16LE) への対応は必要である。
ClientAccess (i Access) の転送記述はすべて CCSID : 1202 として作成されているが
IBM i 自身はどういうわけか CCSID : 1202 と EBCDIC とのコード変換には対応してない。
さて 有名な DSPFL コマンドは確かに便利で
HEX でデータ・ベースの内容を直接、修正することができる。
そこで DSPFL のように
・内容と HEX を上下の同じ位置に表示する。
・HEX で内容を修正することができる。
・UNI_CODE も含めて、CCSID : 1200 , 1202 , 1208 , 819 , 943
および 5026 , 5035 , 1399 をサポートする。
の条件を満足するコマンド : DSPSTM を作成してみた。
操作もほぼ DSPFL と同じである。
コマンド: DSPSTM (Display Stream File) の実行の様子
STMF: /AS400-NET.USR/TEMP/CA.TXT CCSID: 943 1 1,344 バイト
制御 : 0
....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+....0....+....1....+....2....
NV-BS30S 目次ビデオ 1650000002
45245335229D8987868422222222222222223333333333
E6D23303006AEF32363900000000000000001650000002
NV-BS50S ビデオ画王 2000000002
45245335228786848E8A22222222222222223333333333
E6D2350300323639969400000000000000002000000002
NV-CF2 薄型テレビ 980000003
4524432222998586888722222222222222222333333333
E6D362000046CE353C3200000000000000000980000003
NV-CF81 更新テスト 580000004
4524433222859586858622222222222222222333333333
E6D3681000D80635383700000000000000000580000004
NV-CF9 漢字テスト 190000002
45244322228B8986858622222222222222222333333333
E6D3690000AFEA35383700000000000000000190000002
NV-F850 音声録画ビデオ 1400000002
45243332228B9B958E8786842222222222223333333333
E6D6850000990A8E963236390000000000001400000002
NV-HK1 歌えるビデオ 900000002
45244322228C8A8E878684222222222222222333333333
E6D8B100009C2629323639000000000000000900000002
続
F3= 終了 F10= 更新 F11= 表示切替 (CHR)
SFL 行の上 1 段が文字表示で下 2 段が HEX の表示である。
このストリーム・ファイルは右上に CCSID : 943 (日本語ASCII) であるので
HEX を見れば例えば数字 「1」 は HEX 「31」 と表示されている。
ご存知、EBCDIC であれば 「F1」 と表示されるところである。
つまり上 1段は ASCII CCSID : 943 を EBCDIC として表示しているのである。
となると 「目次ビデオ」 のような漢字で両端にシフト文字を含む場合は
上下で 2 バイトのずれが生じるはずであるが、DSPSTM はこのずれをちゃんと補正している。
(くわしくはソース。プログラムを参照)
上下の HEX コードを修正して 「F10=更新」 キーを押すと
ASCII コードとして修正することができる。
このように DSPSTM はストリーム・ファイルの CCSID を読み取って
適切に EBCDIC コード に変換して表示している。
したがってストリーム・ファイルの CCSID は正しく登録しておく必要がある。
IBM i の Ftp は無変換でアップロードするとすべて CCSID : 819 で IFS に保存してしまう。
CCSID : 819 は日本語 ASCII ではなく正しい日本語 ASCII の CCSID は 943 である。
WRKLNK のオプション 「13=属性の変更」で *CCSID 943 と変更することができる。
F11 キーを押すと表示を次のように切り替えることができる。
STMF: /AS400-NET.USR/TEMP/CA.TXT
制御 :
....+....1....+....2....+....3....+....4....+....5....+....6....+....
NV-BS30S 目次ビデオ 1650000002
NV-BS50S ビデオ画王 2000000002
NV-CF2 薄型テレビ 980000003
NV-CF81 更新テスト 580000004
NV-CF9 漢字テスト 190000002
NV-F850 音声録画ビデオ 1400000002
NV-HK1 歌えるビデオ 900000002
NV-H1T-S みんなのビデオ 698000002
NV-SX10 ビデオ画王 1150000002
NV-W1 世界放送方式ビデオ 3500000002
RX-DT75 CDラジオカセット 538000003
SC-CH150 超ミニ・コンポ 700000003
SC-CH505 パーソナル・ミニコンポ 1000000003
SC-CH655 ロングプレイ・コンポ 1290000003
SC-CH950 ドルビー・ミニコンポ 1620000003
SF-SDCD FFFFF 190000009
TH-19VS30 コンパクトTVBS19 1200000001
TH-21VS30 コンパクトTVBS21 1280000001
TH-25GF10 衛星放送内蔵TV25 1680000001
TH-25GV10 ビデオ内蔵型TV25 2550000001
TH-25VS30 コンパクトTVBS25 113000001
F3= 終了 F11= 表示切替 (HEX)
更新して終了すると
終了
更新されたバイト数
変更 . . . . . . . : 1,344 バイト
選択項目を打鍵して,実行キーを押してください。
データ入力の終了 . . . . . . Y Y=YES, N=NO
F3= 終了 F12= 前画面
のように終了画面が表示されて終了することができる。
それではソースを紹介しよう。
0001.00 CMD PROMPT(' ストリーム・ファィルの表示 ')
0002.00 PARM KWD(STMF) TYPE(*PNAME) LEN(256) MIN(1) +
0003.00 PROMPT(' ストリーム・ファイル ')

CRTCMD CMD(MYLIB/DSPSTM) PGM(MYLIB/DSPSTMCL) SRCFILE(MYSRCLIB/QCMDSRC) AUT(*ALL)
0001.00 PGM PARM(&STMF)
0002.00 /*-------------------------------------------------------------------*/
0003.00 /* DSPSTMCL : ストリーム・ファィルの表示 */
0004.00 /* */
0005.00 /* 2019/03/18 作成 */
0006.00 /*-------------------------------------------------------------------*/
0007.00 DCL VAR(&STMF) TYPE(*CHAR) LEN(256)
0008.00 DCL VAR(&CHR2) TYPE(*CHAR) LEN(2)
0009.00 DCL VAR(&ERR) TYPE(*CHAR) LEN(1)
0010.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132)
0011.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
0012.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
0013.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
0014.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132)
0015.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1)
0016.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10)
0017.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) +
0018.00 VALUE('*ESCAPE ')
0019.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) +
0020.00 VALUE(X'000074') /* 2 進数 */
0021.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) +
0022.00 VALUE(X'00000000')
0023.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0024.00
0025.00 /*( 環境の取得 )*/
0026.00 RTVJOBA TYPE(&TYPE)
0027.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */
0028.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ')
0029.00 ENDDO /* バッチ */
0030.00 ELSE CMD(DO) /* 対話式 */
0031.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ')
0032.00 ENDDO /* 対話式 */
0033.00
0034.00 /*( 入力パラメータの検査 )*/
0035.00
0036.00 /*( プログラムの実行 )*/
0037.00 CALL PGM(ASNET.COM/DSPSTM) PARM(&STMF &ERR &MSG)
0038.00 IF COND(&ERR *EQ ' ') THEN(DO)
0039.00 CHGVAR VAR(&MSGTYPE) VALUE('*DIAG ')
0040.00 ENDDO
0041.00 IF COND(&MSG *NE ' ') THEN(DO)
0042.00 GOTO SNDMSG
0043.00 ENDDO
0044.00 RETURN
0045.00
0046.00 APIERR:
0047.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7))
0048.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100))
0049.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ')
0050.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ')
0051.00 GOTO SNDMSG
0052.00
0053.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +
0054.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +
0055.00 MSGFLIB(&MSGFLIB)
0056.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO)
0057.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +
0058.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)
0059.00 MONMSG MSGID(CPF2400) EXEC(RETURN)
0060.00 ENDDO
0061.00 ELSE CMD(DO)
0062.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
0063.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +
0064.00 MSGTYPE(&MSGTYPE)
0065.00 MONMSG MSGID(CPF2400) EXEC(RETURN)
0066.00 ENDDO
0067.00 ENDPGM

CRTCLPGM PGM(MYLIB/DSPSTMCL) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
0001.00 A*%%TS SD 20190323 090527 QTR REL-V6R1M0 5761-WDS
0002.00 A*-----------------------------------------------*
0003.00 A* DSPSTMFM : サブ・ファイル入力
0004.00 A*
0005.00 A* ストリーム・ファイルの表示
0006.00 A*
0007.00 A* CRTEXDSPF QTROBJ/DSPSTMFM +
0008.00 A* SRCFILE(R610SRC/QDSPSRC) LVLCHK(*NO) AUT(*ALL)
0009.00 A*-----------------------------------------------*
0010.00 A*%%EC
0011.00 A DSPSIZ(27 132 *DS4)
0012.00 A MSGLOC(27)
0013.00 A PRINT
0014.00 A HELP
0015.00 A ALTHELP(CA01)
0016.00 A R SFREC01 SFL
0017.00 A TEXT(' SFLレコード ')
0018.00 A 20
0019.00 AO 99 SFLNXTCHG
0020.00 A DATA 120A O 4 2
0021.00 A N21 DSPATR(HI)
0022.00 A UPPDTA 120A B 5 2TEXT(' 上位 ')
0023.00 A 03 DSPATR(UL)
0024.00 A DWNDTA 120A B 6 2TEXT(' 下位 ')
0025.00 A 03 DSPATR(UL)
0026.00 A SFRLEN 4Y 0H TEXT(' 長さ ')
0027.00 A R SFCTL01 SFLCTL(SFREC01)
0028.00 A*%%TS SD 20190323 084809 QTR REL-V6R1M0 5761-WDS
0029.00 A SFLSIZ(0008)
0030.00 A SFLPAG(0007)
0031.00 A TEXT(' SFLコントロール ')
0032.00 A ROLLUP(14 ' 次頁 ')
0033.00 A ROLLDOWN(15 ' 前頁 ')
0034.00 A CF03(03 ' 終了 ')
0035.00 A CF04(04 'プロンプト')
0036.00 A CF10(10 ' 更新 ')
0037.00 A CF11(11 ' 切替 ')
0038.00 A SETOF(99)
0039.00 A BLINK
0040.00 A OVERLAY
0041.00 A 42 SFLDSP
0042.00 A 41 SFLDSPCTL
0043.00 A 43 SFLINZ
0044.00 A 46 SFLDLT
0045.00 A 44 SFLCLR
0046.00 A 45 SFLEND(*MORE)
0047.00 A MOUBTN(*ULP CF04)
0048.00 A 61 SFLMSGID(EDT0411 QPDA/QEDTMSG 61)
0049.00 A 62 SFLMSGID(EDT0410 QPDA/QEDTMSG 62)
0050.00 A 66 SFLMSGID(CPF9897 QSYS/QCPFMSG 66 &M-
0051.00 A SGDTA)
0052.00 A 67 SFLMSGID(CPD6A6D QSYS/QCPFMSG 67)
0053.00 A RTNCSRLOC(&RCD &FLD &CSRP)
0054.00 A DSPREC 4S 0H SFLRCDNBR(CURSOR)
0055.00 A RCD 10A H
0056.00 A FLD 10A H
0057.00 A CSRP 4S 0H TEXT('SFL 表示 レコード № ')
0058.00 A MSGDTA 60A P
0059.00 A 1 2'STMF:'
0060.00 A STMF80 80A O 1 8DSPATR(HI)
0061.00 A 1 89'CCSID:'
0062.00 A CCSID 4Y 0O 1 96DSPATR(HI)
0063.00 A EDTCDE(Z)
0064.00 A BYTE_RED 9Y 0O 1103EDTCDE(1)
0065.00 A DSPATR(HI)
0066.00 A +2' バイト '
0067.00 A 2 1' 制御 :'
0068.00 A CTRBUF 64O B 2 9
0069.00 A 1101'1'
0070.00 A DSPATR(HI)
0071.00 A 2101'0'
0072.00 A DSPATR(HI)
0073.00 A TOPHDR 128A O 3 2TEXT(' 目盛り ')
0074.00 A DSPATR(HI)
0075.00 A R SFREC02 SFL
0076.00 A TEXT(' SFLレコード ')
0077.00 A 20
0078.00 AO 99 SFLNXTCHG
0079.00 A DATA 120A O 4 2
0080.00 A*N21 DSPATR(HI)
0081.00 A R SFCTL02 SFLCTL(SFREC02)
0082.00 A*%%TS SD 20190321 214851 QTR REL-V6R1M0 5761-WDS
0083.00 A SFLSIZ(0022)
0084.00 A SFLPAG(0021)
0085.00 A TEXT(' SFLコントロール ')
0086.00 A ROLLUP(14 ' 次頁 ')
0087.00 A ROLLDOWN(15 ' 前頁 ')
0088.00 A CF03(03 ' 終了 ')
0089.00 A CF04(04 'プロンプト')
0090.00 A* CF10(10 ' 更新 ')
0091.00 A CF11(11 ' 切替 ')
0092.00 A SETOF(99)
0093.00 A BLINK
0094.00 A OVERLAY
0095.00 A 42 SFLDSP
0096.00 A 41 SFLDSPCTL
0097.00 A 43 SFLINZ
0098.00 A 46 SFLDLT
0099.00 A 44 SFLCLR
0100.00 A 45 SFLEND(*MORE)
0101.00 A MOUBTN(*ULP CF04)
0102.00 A 61 SFLMSGID(EDT0411 QPDA/QEDTMSG 61)
0103.00 A 62 SFLMSGID(EDT0410 QPDA/QEDTMSG 62)
0104.00 A 66 SFLMSGID(CPF9897 QSYS/QCPFMSG 66 &M-
0105.00 A SGDTA)
0106.00 A 67 SFLMSGID(CPD6A6D QSYS/QCPFMSG 67)
0107.00 A RTNCSRLOC(&RCD &FLD &CSRP)
0108.00 A DSPREC 4S 0H SFLRCDNBR(CURSOR)
0109.00 A RCD 10A H
0110.00 A FLD 10A H
0111.00 A CSRP 4S 0H TEXT('SFL 表示 レコード № ')
0112.00 A MSGDTA 60A P
0113.00 A 1 2'STMF:'
0114.00 A STMF80 80A O 1 8DSPATR(HI)
0115.00 A 1 89'CCSID:'
0116.00 A CCSID 4Y 0O 1 96DSPATR(HI)
0117.00 A EDTCDE(Z)
0118.00 A BYTE_RED 9Y 0O 1103EDTCDE(1)
0119.00 A +2' バイト '
0120.00 A 2 1' 制御 :'
0121.00 A CTRBUF 64O B 2 9
0122.00 A 1101'1' DSPATR(HI)
0123.00 A 2101'0' DSPATR(HI)
0124.00 A TOPHDR 128A O 3 2TEXT(' 目盛り ')
0125.00 A DSPATR(HI)
0126.00 *
0127.00 A R DSPEND01
0128.00 A*%%TS SD 20070731 210529 QTR REL-V5R4M0 5722-WDS
0129.00 A TEXT(' 機能キーの表示 ')
0130.00 A OVERLAY
0131.00 A 26 2'F3= 終了 '
0132.00 A COLOR(BLU)
0133.00 A 26 34'F10= 更新 '
0134.00 A COLOR(BLU)
0135.00 A 26 51'F11= 表示切替 (CHR)'
0136.00 A COLOR(BLU)
0137.00 A R DSPEND02
0138.00 A*%%TS SD 20070731 210529 QTR REL-V5R4M0 5722-WDS
0139.00 A TEXT(' 機能キーの表示 ')
0140.00 A OVERLAY
0141.00 A 26 2'F3= 終了 '
0142.00 A COLOR(BLU)
0143.00 A* 26 34'F10= 更新 '
0144.00 A* COLOR(BLU)
0145.00 A 26 51'F11= 表示切替 (HEX)'
0146.00 A COLOR(BLU)
0147.00 A R ENDOPT
0148.00 A*%%TS SD 20190323 090527 QTR REL-V6R1M0 5761-WDS
0149.00 A TEXT(' 終了画面 ')
0150.00 A CSRLOC(LIN POS)
0151.00 A CF03(03 ' 終了 ')
0152.00 A CF12(12 ' 前画面 ')
0153.00 A 1 34' 終了 '
0154.00 A COLOR(PNK)
0155.00 A DSPATR(HI)
0156.00 A 3 2' 更新されたバイト数 '
0157.00 A 5 10' 変更 . . . . . . . :'
0158.00 A UPDBYT 9Y 0O 5 35EDTCDE(1)
0159.00 A 11 2' 選択項目を打鍵して,実行キーを押 +
0160.00 A してください。 '
0161.00 A COLOR(BLU)
0162.00 A 13 5' データ入力の終了 . . . . . .'
0163.00 A ANS 1A B 13 39VALUES('Y' 'N')
0164.00 A 13 53'Y=YES, N=NO'
0165.00 A 23 2'F3= 終了 '
0166.00 A COLOR(BLU)
0167.00 A 23 15'F12= 前画面 '
0168.00 A COLOR(BLU)
0169.00 A LIN 3S 0H
0170.00 A POS 3S 0H
0171.00 A 5 47' バイト '

CRTDSPF FILE(MYLIB/DSPSTMFM) SRCFILE(MYSRCLIB/QDSPSRC) LVLCHK(*NO) AUT(*ALL)
読者諸兄にはなぜ SFLDROP を 使わないのかと思う方もいると思うが SFLDROP では
SFL レコードの高輝度表示を制御できないのである。
SFLDROP には標識を定義することが仕様上ではできるがこれは効力を発揮しない。
つまり SFLDROP を標識で制御することはできないのである。
SFLDOLD も同じである。
そこで2つの SFL ; SFREC01 と SFREC02 を用意して交互に表示を切り替えている。
0001.00 /********************************************************************/
0002.00 /* */
0003.00 /* STMSRV : ストリーム・ファイル・サービス・プログラム */
0004.00 /* */
0005.00 /* Office Quattro Co,.Ltd 2019/03/19 08:20:00 created */
0006.00 /* */
0007.00 /* */
0008.00 /********************************************************************/
0009.00 #pragma comment(COPYRIGHT, "as400-net.com EnterpriseServer (C) CopyRight \
0010.00 Office Quattro.Corp. 2019- All right reserved. Users Restricted \
0011.00 Rights - Use, duplication or disclosure restricted by Office Quattro \
0012.00 Corp. Licenced Materials-Property of Office Quattro.")
0013.00 #include <stdio.h>
0014.00 #include <stdlib.h>
0015.00 #include <string.h>
0016.00 #include <micomput.h> /* triml */
0017.00 #include <errno.h>
0018.00 #include <signal.h>
0019.00 #include <fcntl.h>
0020.00 #include <ctype.h>
0021.00
0022.00 #define TRUE 0
0023.00 #define FALSE -1
0024.00 #define READ 0
0025.00 #define UPDATE 1
0026.00 #define MAX_RECLEN 8192 /* 1 レコードの最大長 */
0027.00 int bLR = FALSE;
0028.00 char EBC_CRLF[] = {0x15, 0x00};
0029.00 char UTF_CRLF[] = {0x0d, 0x25, 0x00};
0030.00 char ASC_CRLF[] = {0x0d, 0x0a, 0x00}; /* ASCII 改行コード */
0031.00 char CRLF[3];
0032.00 #define JPN 1
0033.00 #define JPN5035 8
0034.00 #define UTF8 1208
0035.00 #define UTF16 1200
0036.00 #define UTF16LE 1202
0037.00 #define UTF16GE 1200
0038.00 typedef struct {
0039.00 int BYTESPRO;
0040.00 int BYTESAVL;
0041.00 char MSGID[7];
0042.00 char RESRVD;
0043.00 char EXCPDATA[100];
0044.00 } ERRSTRUCTURE; /* Define the error return structure */
0045.00 ERRSTRUCTURE errcode;/* Error Code Structure for RCVMSG */
0046.00 volatile _INTRPT_Hndlr_Parms_T ca;
0047.00 char EBCTBL[] = "EBCDIC5035";
0048.00 char EBCLIB[] = "ASNET.COM ";
0049.00 char ASCTBL[] = "ASCII5035 ";
0050.00 char ASCLIB[] = "ASNET.COM ";
0051.00 char CUMMA[] = {0x6b, 0x00};
0052.00
0053.00 /*************************************************************/
0054.00 /* EXPORT 関 数 */
0055.00 /*************************************************************/
0056.00 int Open(char* file);
0057.00 int Read(char* record, char* UPX, char* DWX);
0058.00 int Reset(void);
0059.00 int AddData(char* upddta, char* dwndta, int add_byte);
0060.00 int Update(char* file);
0061.00 int Close(void);
0062.00 /*************************************************************/
0063.00 /* EXPORT 変 数 */
0064.00 /*************************************************************/
0065.00 char m_MSG[132];
0066.00 int m_RRN = 0;
0067.00 int m_RECL;
0068.00 int m_CCSID;
0069.00 int m_BYTE_RED;
0070.00 int m_UPD_BYTE;
0071.00 /*************************************************************/
0072.00 /* 内 部 使 用 関 数 */
0073.00 /*************************************************************/
0074.00 void INZSR(void);
0075.00 int convert(char* ebcrcd, char* stmrcd, int ccsid, int stmlen);
0076.00
0077.00 /*************************************************************/
0078.00 /* IMPORT 関 数 */
0079.00 /*************************************************************/
0080.00 int toEBCDIC(char* ebcbuf, char* ascbuf, char table[10], char tbllib[10], int bSiSo);
0081.00 int fromUTF8(char* unibuf, char* ebcbuf, int CNTRY);
0082.00 int fromUTF(char* unibuf, char* ebcbuf, int CNTRY, int ccsid, int unilen);
0083.00 /*************************************************************/
0084.00 /* IMPORT 変 数 */
0085.00 /*************************************************************/
0086.00 /*************************************************************/
0087.00 /* 外 部 呼 出 し 関 数 */
0088.00 /*************************************************************/
0089.00 void MonitorMSG(_INTRPT_Hndlr_Parms_T ca, char* ref);
0090.00 #pragma linkage(MonitorMSG, OS)
0091.00 #pragma map(MonitorMSG, "ASNET.COM/MONMSG")
0092.00 /*************************************************************/
0093.00 /* グ ロ ー バ ル 変 数 */
0094.00 /*************************************************************/
0095.00 int fildes, m_bINZSR = FALSE;
0096.00 struct stat info;
0097.00 long tmplen, m_byte_red, m_cur_pos;
0098.00 int ccsid;
0099.00 char ref[133], *tmpbuf;
0100.00 /********************************************************************/
0101.00 /* m a i n --- main module of this pgm */
0102.00 /* */
0103.00 /*------------------------------------------------------------------*/
0104.00
0105.00 /****************/
0106.00 void INZSR(void)
0107.00 /****************/
0108.00 {
0109.00 int i;
0110.00
0111.00 m_bINZSR = TRUE;
0112.00 errcode.BYTESPRO = 160;
0113.00 errcode.BYTESAVL = 0;
0114.00 m_byte_red = 0;
0115.00 tmplen = 0;
0116.00 tmpbuf = NULL;
0117.00 }
0118.00 /*********************/
0119.00 int Open(char* file)
0120.00 /*********************/
0121.00 {
0122.00
0123.00 if(m_bINZSR == FALSE) INZSR();
0124.00 if((fildes = open(file, O_RDONLY)) == FALSE){/* エラー */
0125.00 sprintf(m_MSG, " オープン失敗 :%s:%s", file, strerror(errno));
0126.00 printf("STMSRV[%d] %s\n", __LINE__, m_MSG);
0127.00 getchar();
0128.00 return FALSE;
0129.00 }/* エラー */
0130.00 lstat(file, &info);
0131.00 ccsid = info.st_ccsid;
0132.00 m_CCSID = ccsid;
0133.00
0134.00 switch(ccsid){/*switch*/
0135.00 case 819: case 943: strcpy(CRLF, ASC_CRLF);
0136.00 break;
0137.00 case UTF16: case UTF16LE: case UTF8:
0138.00 strcpy(CRLF, UTF_CRLF);
0139.00 break;
0140.00 case 5026: case 5035: case 1399:
0141.00 strcpy(CRLF, EBC_CRLF);
0142.00 break;
0143.00 defalut: printf("CSV2DB[%d] 不明な CCSID: %d です。 \n", __LINE__, ccsid);
0144.00 break;
0145.00 }/*switch*/
0146.00 tmplen = (long)info.st_allocsize + 256;
0147.00 tmpbuf = (unsigned char *)malloc(tmplen + 1);
0148.00 m_byte_red = read(fildes, tmpbuf, tmplen);
0149.00 m_RRN = 0;
0150.00 m_cur_pos = 0;
0151.00 m_BYTE_RED = m_byte_red;
0152.00 return TRUE;
0153.00 }
0154.00 /****************/
0155.00 int Close(void)
0156.00 /****************/
0157.00 {
0158.00 close(fildes);
0159.00 fildes = FALSE;
0160.00 free(tmpbuf);
0161.00 m_byte_red = 0;
0162.00 tmplen = 0;
0163.00 return TRUE;
0164.00 }
0165.00 /*********************************************/
0166.00 int Read(char* record, char* UPX, char* DWX)
0167.00 /*********************************************/
0168.00 {
0169.00 int i, j;
0170.00 char recbuf[MAX_RECLEN], buff[12];
0171.00
0172.00 memset(recbuf, 0, sizeof(recbuf));
0173.00 if(m_cur_pos >= m_byte_red){/* エラー */
0174.00 if(m_cur_pos == 0){/* ファイルが空 */
0175.00 printf("STMRCV[%d] ファイルが空です (m_byte_red = %d)\n", __LINE__, m_byte_red);
0176.00 getchar();
0177.00 }/* ファイルが空 */
0178.00 return FALSE;
0179.00 }/* エラー */
0180.00 m_RECL = 0;
0181.00 for(i = m_cur_pos; i<m_byte_red; i++){/*for-loop*/
0182.00 if(strncmp(&tmpbuf[i], CRLF, strlen(CRLF)) == 0){/* 改行または終わり */
0183.00 m_RRN ++;
0184.00 m_cur_pos += m_RECL + strlen(CRLF);
0185.00 convert(record, recbuf, ccsid, m_RECL);
0186.00 for(j = 0; j<m_RECL; j++){/*for-loop-j*/
0187.00 sprintf(buff, "%02x", recbuf[j]);
0188.00 UPX[j] = toupper(buff[0]);
0189.00 DWX[j] = toupper(buff[1]);
0190.00 }/*for-loop-j*/
0191.00 return m_RECL;
0192.00 }/* 改行または終わり */
0193.00 recbuf[m_RECL] = tmpbuf[i];
0194.00 m_RECL ++;
0195.00 }/*for-loop*/
0196.00 if(m_RECL > 10){
0197.00 convert(record, recbuf, ccsid, m_RECL);
0198.00 return m_RECL;
0199.00 }
0200.00 else return FALSE;
0201.00 }
0202.00 /****************/
0203.00 int Reset(void)
0204.00 /****************/
0205.00 {
0206.00 m_byte_red = 0;
0207.00 return TRUE;
0208.00 }
0209.00 /******************************************************/
0210.00 int AddData(char* uppdta, char* dwndta, int add_byte)
0211.00 /******************************************************/
0212.00 {
0213.00 long pos;
0214.00 int i;
0215.00 char record[8192];
0216.00
0217.00 for(i = 0; i<add_byte; i++){/*for-loop*/
0218.00 switch(uppdta[i]){/*switch*/
0219.00 case '0': record[i] = 0x0F; break;
0220.00 case '1': record[i] = 0x1F; break;
0221.00 case '2': record[i] = 0x2F; break;
0222.00 case '3': record[i] = 0x3F; break;
0223.00 case '4': record[i] = 0x4F; break;
0224.00 case '5': record[i] = 0x5F; break;
0225.00 case '6': record[i] = 0x6F; break;
0226.00 case '7': record[i] = 0x7F; break;
0227.00 case '8': record[i] = 0x8F; break;
0228.00 case '9': record[i] = 0x9F; break;
0229.00 case 'A': record[i] = 0xAF; break;
0230.00 case 'B': record[i] = 0xBF; break;
0231.00 case 'C': record[i] = 0xCF; break;
0232.00 case 'D': record[i] = 0xDF; break;
0233.00 case 'E': record[i] = 0xEF; break;
0234.00 case 'F': record[i] = 0xFF; break;
0235.00 }/*switch*/
0236.00 switch(dwndta[i]){/*switch*/
0237.00 case '0': record[i] = record[i] & 0xF0; break;
0238.00 case '1': record[i] = record[i] & 0xF1; break;
0239.00 case '2': record[i] = record[i] & 0xF2; break;
0240.00 case '3': record[i] = record[i] & 0xF3; break;
0241.00 case '4': record[i] = record[i] & 0xF4; break;
0242.00 case '5': record[i] = record[i] & 0xF5; break;
0243.00 case '6': record[i] = record[i] & 0xF6; break;
0244.00 case '7': record[i] = record[i] & 0xF7; break;
0245.00 case '8': record[i] = record[i] & 0xF8; break;
0246.00 case '9': record[i] = record[i] & 0xF9; break;
0247.00 case 'A': record[i] = record[i] & 0xFA; break;
0248.00 case 'B': record[i] = record[i] & 0xFB; break;
0249.00 case 'C': record[i] = record[i] & 0xFC; break;
0250.00 case 'D': record[i] = record[i] & 0xFD; break;
0251.00 case 'E': record[i] = record[i] & 0xFE; break;
0252.00 case 'F': record[i] = record[i] & 0xFF; break;
0253.00 }/*switch*/
0254.00 }/*for-loop*/
0255.00 pos = m_byte_red;
0256.00 memcpy(&tmpbuf[pos], record, add_byte); /* データを追加 */
0257.00 pos += add_byte;
0258.00 tmpbuf[pos] = 0x00;
0259.00 memcpy(&tmpbuf[pos], CRLF, strlen(CRLF));
0260.00 pos += strlen(CRLF); /* 改行コード */
0261.00 tmpbuf[pos] = 0x00;
0262.00 m_byte_red = pos;
0263.00 return TRUE;
0264.00 }
0265.00 /***********************/
0266.00 int Update(char* file)
0267.00 /***********************/
0268.00 {
0269.00 int byte_red;
0270.00
0271.00 if(m_byte_red == 0){/* 更新対象なし */
0272.00 strcpy(m_MSG, " 更新対象のデータがありません。 ");
0273.00 printf("STMSRV[%d] %s\n", __LINE__, m_MSG);
0274.00 getchar();
0275.00 return FALSE;
0276.00 }/* 更新対象なし */
0277.00
0278.00 if((fildes = open(file, O_WRONLY | O_CREAT | O_TRUNC,
0279.00 S_IRWXO | S_IRWXU)) == FALSE){ /* *PUBLIC=RWX */
0280.00 sprintf(m_MSG, " オープン失敗 :%s:%s", file, strerror(errno));
0281.00 printf("STMSRV[%d] %s\n", __LINE__, m_MSG);
0282.00 getchar();
0283.00 return FALSE;
0284.00 }/* エラー */
0285.00 byte_red = write(fildes, tmpbuf, m_byte_red);
0286.00 if(byte_red == FALSE){/* エラー */
0287.00 sprintf(m_MSG, " 更新エラー :%s", strerror(errno));
0288.00 printf("STMSRV[%d] %s\n", __LINE__, m_MSG);
0289.00 return FALSE;
0290.00 }/* エラー */
0291.00 m_UPD_BYTE = byte_red;
0292.00 return byte_red;
0293.00 }
0294.00 /**************************************************************/
0295.00 int convert(char* ebcrcd, char* stmrcd, int ccsid, int stmlen)
0296.00 /**************************************************************/
0297.00 {
0298.00 int recl, rc = TRUE, i, j, bKJ = FALSE, bOF = FALSE;
0299.00 char ebcbuf[8192];
0300.00
0301.00 switch(ccsid){/*switch*/
0302.00 case 819: case 943:
0303.00 rc = toEBCDIC(ebcbuf, stmrcd, EBCTBL, EBCLIB, TRUE);
0304.00 break;
0305.00 case UTF16: rc = fromUTF(stmrcd, ebcbuf, JPN5035, UTF16, stmlen);
0306.00 break;
0307.00 case UTF16LE: rc = fromUTF(stmrcd, ebcbuf, JPN5035, UTF16LE, stmlen);
0308.00 break;
0309.00 case UTF8: rc =fromUTF8(stmrcd, ebcbuf, JPN);
0310.00 break;
0311.00 default: rc = FALSE;
0312.00 break;
0313.00 }/*switch*/
0314.00 if(rc != FALSE){/* レコード長を戻す */
0315.00 recl = strlen(ebcbuf);
0316.00 j = 0;
0317.00 for(i = 0; i<recl; i++){/*for-loop*/
0318.00 if(bKJ == FALSE){/* 非漢字 */
0319.00 if(ebcbuf[i] == 0x0e){/* 漢字の始まり */
0320.00 j --;
0321.00 bKJ = TRUE;
0322.00 }/* 漢字の始まり */
0323.00 }/* 非漢字 */
0324.00 else{/* 漢字中 */
0325.00 if(ebcbuf[i] == 0x0f){/* 漢字の終わり */
0326.00 bOF = TRUE;
0327.00 bKJ = FALSE;
0328.00 ebcrcd[j] = ebcbuf[i];
0329.00 j ++;
0330.00 continue;
0331.00 }/* 漢字の終わり */
0332.00 }/* 漢字中 */
0333.00 if(bOF == TRUE && ebcbuf[i] == ' '){/*OF の後続ブランク */
0334.00 bOF = FALSE; continue;
0335.00 }/*OF の後続ブランク */
0336.00 ebcrcd[j] = ebcbuf[i];
0337.00 j ++;
0338.00 }/*for-loop*/
0339.00 }/* レコード長を戻す */
0340.00 return rc;
0341.00 }

CRTCMOD MODULE(QTEMP/STMSRV) SRCFILE(MYSRCLIB/QCSRC2) AUT(*ALL)
CRTSRVPGM SRVPGM(MYLIB/STMSRV) MODULE(QTEMP/STMSRV) SRCFILE(MYSRCLIB/QSRVSRC)
BNDSRVPGM((ASNET.COM/CVTMOD4) (ASNET.COM/UNI_CODE)) AUT(*ALL)
IBM i の開発者の多くは C 言語には馴染みのない方も多いと思うが
最近では API は C 言語からの利用を想定しているので
C 言語も素養のひとつとして勉強されることをお勧めする。
Java が主流だと思われがちであるが 2019 年 1 月より Oracle が JDK の有償化を
公示したために今後は急速に Java 離れが進むと予想される。
IBM の世界においても Java で開発された IBM ACS (= Access Client Solutions) は既に
急速に敬遠しがちになっている。
Oracle は 1 人当たりの JDK の使用料金を 4300円 / 月 とか言い出しているので
100 クライアントの ACS の使用料は年間 500万円になってしまう。
Java の時代は急速に終焉を迎えつつある。
Java よりはやはり C 言語がすべての開発言語の基本であることは言うまでもない。
説明すべき大切な箇所は 2 つあって
(1) convert 関数のストリーム・ファイルからのコード変換
0301.00 switch(ccsid){/*switch*/
0302.00 case 819: case 943:
0303.00 rc = toEBCDIC(ebcbuf, stmrcd, EBCTBL, EBCLIB, TRUE);
0304.00 break;
0305.00 case UTF16: rc = fromUTF(stmrcd, ebcbuf, JPN5035, UTF16, stmlen);
0306.00 break;
0307.00 case UTF16LE: rc = fromUTF(stmrcd, ebcbuf, JPN5035, UTF16LE, stmlen);
0308.00 break;
0309.00 case UTF8: rc =fromUTF8(stmrcd, ebcbuf, JPN);
0310.00 break;
0311.00 default: rc = FALSE;
0312.00 break;
0313.00 }/*switch*/
の部分でストリーム・ファイルからのコードを EBCDIC に変換している。
ただし
toEBCDIC : ASCII CCSID : 819 , 943 から EBCDIC への変換
fromUTF : UTF16, UTF16LE から EBDCID への変換
fromUTF8 : UTF8 から EBCDIC への変換
であり、いずれも弊社製品ライブラリー ASNET.COM の
サービス・プログラム CVTMOD4 , UNI_CODE をバインドする必要がある。
製品のサービス・プログラムまでここで公開するわけにはいかないので
AutoWeb または EnterPriseServer のユーザー限定ということでご容赦頂きたい。
特に fromUTF は UTF16LE (CCSID : 1202) から EBCDIC への変換もサポートしている。
IBM i 自体は API を使っても CCSID : 1202 を変換することはできない。
その点でも弊社製品は機能が拡張されている。
0001.00 STRPGMEXP PGMLVL(*CURRENT) +
0002.00 SIGNATURE(X'000000000000000000000000958597D+
0003.00 6')
0004.00 EXPORT SYMBOL("Open")
0005.00 EXPORT SYMBOL("Read")
0006.00 EXPORT SYMBOL("Reset")
0007.00 EXPORT SYMBOL("AddData")
0008.00 EXPORT SYMBOL("Update")
0009.00 EXPORT SYMBOL("Close")
0010.00 EXPORT SYMBOL("m_MSG")
0011.00 EXPORT SYMBOL("m_RRN")
0012.00 EXPORT SYMBOL("m_CCSID")
0013.00 EXPORT SYMBOL("m_BYTE_RED")
0014.00 EXPORT SYMBOL("m_UPD_BYTE")
0015.00 ENDPGMEXP

原稿は長くなっているが内容はそんなに難しいものではないはずだ。
ストリーム・ファイルも EBCDIC で表示して自由にコードも変更できるようになれば
IFS の使用も身近なものになるはずである。
DSPSTM コマンドを是非、導入して大いに活用して頂きたい。