Tools

73. ストリーム・ファイルを表示する DSPSTM

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= 前画面                                                      

のように終了画面が表示されて終了することができる。

それではソースを紹介しよう。

【 コマンド: DSPSTM 】

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)

【 CLP: DSPSTMCL 】

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)

【 DSPF: DSPSTMFM 】

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 を用意して交互に表示を切り替えている。

【 C/400: STMSRV 】

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 を変換することはできない。
その点でも弊社製品は機能が拡張されている。

【 QSRVSRC: STMSRV 】

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 コマンドを是非、導入して大いに活用して頂きたい。