RPG

323. ASCII エンコードするには

エンコード( = encode )とは日本語に直訳するとコード化することであるが
インターネットの TCP/IP 通信でのエンコードとは HEX コードを
%xx 形式で文字表現することを言う。
例えば 「 / 」という文字は ASCII では 0x2f であるのでこれを
%2F として表現する。
エンコードされた受け手はこれを元の 0x2f に戻す。
つまり文字「 / 」を再構築する。

エンコードとは何のためにするのかというと文字列の中にあって
ファイルの区切りなどの特殊な意味を持つコード( /、¥... )を
文字列として使用するときに特殊コードではない、ということを
処理するプログラムに知らせるためである。

URL に特殊文字が入力された場合はブラウザによって
エンコードされる。
しかし STRPCCMD に特殊文字が入力された場合は
エンコードされないので誤解されて誤動作の原因となる。
例えば CALL MY¥PGM という文字列は STRPCCMD で
確実にエラーとなってしまう。
このようなことを避けるためにエンコードが必要となる。

ついでに説明しておくと今は IBM i だけで完結する時代ではなく
ソースであっても PC にダウンロードしたりアップロードすることがある。
文字 ¥ は円という文字ではなく通貨記号であるので
PC にダウンロードすれば $ に変わることがある。
この逆もある。
IBM i の開発者は ¥、#、@ などの特殊記号を使いたがる傾向にあるが
特殊記号の使用は余計なトラブルを増やすだけに過ぎない。
特殊記号の使用は避けるほうが賢明である。

【 TOWATSON 】
0001.00 H DFTNAME(TOWATSON) DATEDIT(*YMD/) BNDDIR('QC2LE')                      
0002.00 F********** 初めてのワトソン ****************************************** 
0003.00 FTOWATSONFMCF   E             WORKSTN                                   
0004.00 F********************************************************************** 
0005.00                                                                         
0006.00  * CRTRPGMOD  OBJ(QTEMP/TOWATSON)   SRCFILE(R610SRC/QRPGLESRC)          
0007.00  * DBGVIEW(*SOURCE) AUT(*ALL)                                           
0008.00  * CRTPGM PGM(QUATTRO/TOWATSON) MODULE(QTEMP/TOWATSON)                  
0009.00  *    BNDSRVPGM(ASNET.COM/HTTPSRV) ACTGRP(*NEW) AUT(*ALL)               
0010.00                                                                         
0011.00  *-------------------------------------------------------------------*  
0012.00  *  2017/05/01 : 作成                                                   
0013.00  *-------------------------------------------------------------------*  
0014.00  *( 作業変数 )                                                          
0015.00 D DCR             S              1A   DIM(15) CTDATA PERRCD(15)         
0016.00 D AR              S              1A   DIM(256)                          
0017.00 D N               S              4S 0                                   
0018.00 D M               S              4S 0                                   
0019.00 D TRUE#           S              4B 0 INZ(0)                            
0020.00 D FALSE#          S              4B 0 INZ(-1)                           
0021.00 D NULL            C                   CONST(X'00')           
0022.00                                                              
0023.00 D                 DS                                         
0024.00 D                         1     10A   INZ('enesfritja')      
0025.00 D  LANG                   1     10A   DIM(5)                 
0026.00                                                              
0027.00 D*( TRANSLATE のプロトタイプ宣言 )                           
0028.00 D TRANSLATE       PR                                         
0029.00 D  FROMLANG                      2A   VALUE                  
0030.00 D  TOLANG                        2A   VALUE                  
0031.00 D  FROMTXT                     120A   VALUE                  
0032.00 D  TOTXT                          *   VALUE                  
0033.00                                                              
0034.00 D*( ENCODE のプロトタイプ宣言 )                              
0035.00 D ENCODE          PR          1000A                          
0036.00 D  FROMSTR                     120A   VALUE                  
0037.00                                                              
0038.00 D*( HTTP_REQUEST のプロトタイプ宣言 )                        
0039.00 D HTTP_REQUEST    PR            10I 0                        
0040.00 D  URLPATH                        *   VALUE                  
0041.00 D  RTNVALUE                       *   VALUE                  
0042.00 D  RTNLEN                         *   VALUE                             
0043.00 D  MODE                         10I 0 VALUE                             
0044.00                                                                         
0045.00 C*( 明細画面 )                                                          
0046.00 C*----------------------------------------------------+                 
0047.00 C     DSPLY         TAG                                                 
0048.00 C                   EXFMT     DSPDTA01                                  
0049.00 C*----------------------------------------------------+                 
0050.00 C                   SETOFF                                       99     
0051.00 C*( CF03 )- 終了                                                        
0052.00 C     *IN03         IFEQ      *ON                                       
0053.00 C                   SETON                                        LR     
0054.00 C   LR              RETURN                                              
0055.00 C                   GOTO      DSPLY                                     
0056.00 C                   END                                                 
0057.00 C*( 実行キー )                                                          
0058.00 C                   SETON                                        80     
0059.00 C                   WRITE     DSPDTA01                                  
0060.00 C                   SETOFF                                       80     
0061.00  /FREE                                                                  
0062.00      TRANSLATE(LANG(FROMLG):LANG(TOLANG):FROMTXT:%ADDR(TOTXT));         
0063.00  /END-FREE                                                           
0064.00 C                   GOTO      DSPLY                                  
0065.00 C                   SETON                                        LR  
0066.00 C                   RETURN                                           
0067.00 C******************************************************              
0068.00 C     *INZSR        BEGSR                                            
0069.00 C******************************************************              
0070.00 C                   Z-ADD     1             FROMLG                   
0071.00 C                   Z-ADD     5             TOLANG                   
0072.00 C                   MOVEL(P)  'I アテ ア イナモ'  FROMTXT                  
0073.00 C                   ENDSR                                            
0074.00 C******************************************************              
0075.00 P TRANSLATE       B                   EXPORT                         
0076.00 C******************************************************              
0077.00 D                 PI                                                 
0078.00 D   FROMLANG                     2A   VALUE                          
0079.00 D   TOLANG                       2A   VALUE                          
0080.00 D   FROMTXT                    120A   VALUE                          
0081.00 D   TOTEXT_P                      *   VALUE                          
0082.00                                                                      
0083.00 D STR1            S           1000A                                  
0084.00 D STR2            S           1000A                              
0085.00 D RC              S             10I 0                            
0086.00 D TOTEXT          S            120A   BASED(TOTEXT_P)            
0087.00                                                                  
0088.00 D TEXTBACK        DS                  QUALIFIED                  
0089.00 D  LEN                    1      4S 0                            
0090.00 D  DATA                   5    260A                              
0091.00                                                                  
0092.00  /FREE                                                           
0093.00     STR2 = ENCODE(%TRIMR(FROMTXT));                              
0094.00     STR1 = *BLANKS;                                              
0095.00     STR1 = 'https://watson-api-explorer.ng.bluemix.net/' +       
0096.00             'language-translator/api/v2/translate?model_id=' +   
0097.00             FROMLANG + '-' + TOLANG + '&text=' + STR2 + NULL;    
0098.00     STR1 = %TRIMR(STR1);                                         
0099.00     RC = HTTP_REQUEST(%ADDR(STR1): %ADDR(TEXTBACK.DATA):         
0100.00                 %ADDR(TEXTBACK.LEN): 1);                         
0101.00     IF (TEXTBACK.LEN > 0);                                       
0102.00       TOTEXT = TEXTBACK.DATA;                                    
0103.00     ELSE;                                                        
0104.00       TOTEXT = *BLANKS;                                          
0105.00     ENDIF;                                                 
0106.00     RETURN;                                                
0107.00  /END-FREE                                                 
0108.00 P                 E                                        
0109.00 C******************************************************    
0110.00 P ENCODE          B                   EXPORT               
0111.00 C******************************************************    
0112.00 D                 PI          1000A                        
0113.00 D   FROMSTR                    120A   VALUE                
0114.00                                                            
0115.00 D TOSTR           S           1000A                        
0116.00 D BUFLEN          S              5P 0                      
0117.00 D STRING          S            256A                        
0118.00 D N               S              4S 0                      
0119.00 D POS             S              4S 0 INZ(1)               
0120.00 D AR              S              1A   DIM(256)             
0121.00 D BR              S              1A   DIM(3)               
0122.00 D FLD3            S              3A                        
0123.00 D UPPER           S              1A                        
0124.00 D LOWER           S              1A                        
0125.00                                                            
0126.00 D                 DS                                                 
0127.00 D CH01                    1      1    INZ(X'00')                     
0128.00 D CH02                    2      2                                   
0129.00 D BIN4                    1      2B 0                                
0130.00                                                                      
0131.00 C     FROMSTR       CAT(P)    NULL:0        STRING                   
0132.00 C                   EVAL      BUFLEN = %LEN(%TRIMR(FROMSTR))         
0133.00 C*----------------------------------------------------+              
0134.00 C                   CALL      'QDCXLATE'                           99
0135.00 C                   PARM                    BUFLEN                   
0136.00 C                   PARM                    STRING                   
0137.00 C                   PARM      'QASCII  '    TBL              10      
0138.00 C                   PARM      'QSYS    '    TBLLIB           10      
0139.00 C*----------------------------------------------------+              
0140.00 C                   MOVEA     *BLANKS       AR                       
0141.00 C                   MOVEA     *BLANKS       BR                       
0142.00 C                   EVAL      BR(1) = '%'                            
0143.00 C     1             DO        BUFLEN        N                        
0144.00 C                   EVAL      CH02 = %SUBST(STRING:N:1)              
0145.00 C     BIN4          DIV       16            BIN4                     
0146.00 C                   MVR                     AMARI             2 0    
0147.00  *( 上位ビット )                                          
0148.00 C                   EVAL      M = BIN4                    
0149.00 C                   MOVE      DCR(M)        UPPER         
0150.00  *( 下位ビット )                                          
0151.00 C     AMARI         IFGT      0                           
0152.00 C                   Z-ADD     AMARI         BIN4          
0153.00 C                   Z-ADD     AMARI         M             
0154.00 C                   MOVE      DCR(M)        LOWER         
0155.00 C                   ELSE                                  
0156.00 C                   MOVE      '0'           LOWER         
0157.00 C                   ENDIF                                 
0158.00  *                                                        
0159.00  /FREE                                                    
0160.00      FLD3 = '%' + UPPER + LOWER;                          
0161.00  /END-FREE                                                
0162.00 C                   MOVEA     FLD3          AR(POS)       
0163.00 C                   ADD       3             POS           
0164.00 C                   ENDDO                                 
0165.00 C                   MOVEA(P)  AR            TOSTR         
0166.00 C     TOSTR         CAT       NULL:0        TOSTR         
0167.00 C                   EVAL      TOSTR = %TRIMR(TOSTR)       
0168.00 C                   RETURN                  TOSTR
0169.00 P                 E                              
0170.00 ** DCR -  以下は配列
0171.00 123456789ABCDEF     

上記のソースのうちでエンコードは

0093.00     STR2 = ENCODE(%TRIMR(FROMTXT));
           :
0109.00 C******************************************************    
0110.00 P ENCODE          B                   EXPORT               
0111.00 C******************************************************    
0112.00 D                 PI          1000A                        
0113.00 D   FROMSTR                    120A   VALUE                
0114.00                                                            
0115.00 D TOSTR           S           1000A                        
0116.00 D BUFLEN          S              5P 0                      
0117.00 D STRING          S            256A                        
0118.00 D N               S              4S 0                      
0119.00 D POS             S              4S 0 INZ(1)               
0120.00 D AR              S              1A   DIM(256)             
0121.00 D BR              S              1A   DIM(3)               
0122.00 D FLD3            S              3A                        
0123.00 D UPPER           S              1A                        
0124.00 D LOWER           S              1A                        
0125.00                                                            
0126.00 D                 DS                                                 
0127.00 D CH01                    1      1    INZ(X'00')                     
0128.00 D CH02                    2      2                                   
0129.00 D BIN4                    1      2B 0                                
0130.00                                                                      
0131.00 C     FROMSTR       CAT(P)    NULL:0        STRING                   
0132.00 C                   EVAL      BUFLEN = %LEN(%TRIMR(FROMSTR))         
0133.00 C*----------------------------------------------------+              
0134.00 C                   CALL      'QDCXLATE'                           99
0135.00 C                   PARM                    BUFLEN                   
0136.00 C                   PARM                    STRING                   
0137.00 C                   PARM      'QASCII  '    TBL              10      
0138.00 C                   PARM      'QSYS    '    TBLLIB           10      
0139.00 C*----------------------------------------------------+              
0140.00 C                   MOVEA     *BLANKS       AR                       
0141.00 C                   MOVEA     *BLANKS       BR                       
0142.00 C                   EVAL      BR(1) = '%'                            
0143.00 C     1             DO        BUFLEN        N                        
0144.00 C                   EVAL      CH02 = %SUBST(STRING:N:1)              
0145.00 C     BIN4          DIV       16            BIN4                     
0146.00 C                   MVR                     AMARI             2 0    
0147.00  *( 上位ビット )                                          
0148.00 C                   EVAL      M = BIN4                    
0149.00 C                   MOVE      DCR(M)        UPPER         
0150.00  *( 下位ビット )                                          
0151.00 C     AMARI         IFGT      0                           
0152.00 C                   Z-ADD     AMARI         BIN4          
0153.00 C                   Z-ADD     AMARI         M             
0154.00 C                   MOVE      DCR(M)        LOWER         
0155.00 C                   ELSE                                  
0156.00 C                   MOVE      '0'           LOWER         
0157.00 C                   ENDIF                                 
0158.00  *                                                        
0159.00  /FREE                                                    
0160.00      FLD3 = '%' + UPPER + LOWER;                          
0161.00  /END-FREE                                                
0162.00 C                   MOVEA     FLD3          AR(POS)       
0163.00 C                   ADD       3             POS           
0164.00 C                   ENDDO                                 
0165.00 C                   MOVEA(P)  AR            TOSTR         
0166.00 C     TOSTR         CAT       NULL:0        TOSTR         
0167.00 C                   EVAL      TOSTR = %TRIMR(TOSTR)       
0168.00 C                   RETURN                  TOSTR
0169.00 P                 E                              
0170.00 ** DCR -  以下は配列
0171.00 123456789ABCDEF     

の部分である。
まず入力された FROMSTR に NULL を追加して
API : QDCXLATE によって ASCII コードに STRING という変数に変換する。
戻された長さ BUFLEN の長さの分だけ LOOP して STRING より 1 バイトずつ
CH02 として取り出す。
CH02 は次のように BIN4 の一部として定義されている。

0126.00 D                 DS                                                 
0127.00 D CH01                    1      1    INZ(X'00')                     
0128.00 D CH02                    2      2                                   
0129.00 D BIN4                    1      2B 0 

つまり CH02 がもし X'2F' であれば BIN4 は X'002F' となる。
そこで

0145.00 C     BIN4          DIV       16            BIN4                     
0146.00 C                   MVR                     AMARI             2 0 

として BIN4 を 16 ( =X'10' )で割り算すると
BIN4 = 2 で余りは AMARI = X'0F'( 15 ) となる。

配列 DCR は

0015.00 D DCR             S              1A   DIM(15) CTDATA PERRCD(15)
 :
0170.00 ** DCR -  以下は配列
0171.00 123456789ABCDEF 

として定義されているので DCR( M ) が 求める値となる。
( M は BIN4 または AMARI )

ENCODE はプロシージャーとして定義されているので
いろいろな上位プログラムから呼び出して使うことができる。

この ENCODE プロシージャーは RPG プログラムで上位ビットや下位ビットを
調べたいときにその方法を示唆している。