Hallo allerseits,

diese Anforderung haben sicher noch mehr Leute außer mir, evtl. kann es ja der ein oder andere gebrauchen:


UTF-8 ist ein Format, in dem nicht jedes Zeichen eine feste Länge hat.
die unteren 127 Zeichen des ASCII sind identisch in UTF-8, höhere ASCII-Zeichen und andere werden mit 2, 3, oder mehr Byte dargestellt.
Wen der Aufbau näher interessiert: https://de.wikipedia.org/wiki/UTF-8

Es ist gar nicht so schwer, dieses Format zu generieren. Der Code ist so kurz, dass ich dies viel einfacher finde, als irgendwelche APIs zu bedienen, die dann bei den Feinheiten doch nicht das tun, was ich will.
Und wenn etwas fehlt, kann man es leicht anpassen/ergänzen.


Wen es interessiert, hier ein kurzer Abriss, wie das Programm arbeitet:

Eingangsparameter: fTxtC enthält den 2-Byte-Unicode String, dataLen ist die Länge (muss mind. 1 sein)
(1) Jedes Zeichen besteht aus 2 Byte, dies wird einzeln konvertiert,
(2) und hierfür in eine Zahl (binN) umgewandelt.
Abhängig von der Größe der Zahl ergibt sich als Länge der Zielzeichenkette:
(3a) 1 (ASC),
(3b) 2,
(3c) 3
oder 4 – hier nicht implementiert.
Am Ende hat man in fTxt8 den fertigen UTF-8 String.

Code:
D                 DS                         
D   binN                         9B 0        
D   binA1                 1      1A          
D   binA2                 2      2A          
D   binA3                 3      3A          
D   binA4                 4      4A          
 *                                           
D   fTxtE         S              1A   dim(2000)    
D   fTxt8         S              1A   dim(4000)  
D   fTxtC         S              2A   dim(4000)  
 *                                               
D                 DS          8002               
D   textCn                                       
D   textCnA               3   8002A              
 
 
 * 2-Byte Unicode ---> UTF-8                                                                               
C                   movea     *blank        fTxt8                   
C                   z-add     *zero         i8                5 0   
 *
C     1             do        dataLen       iC                5 0                                  (1)
C                   move      fTxtC(iC)     aE                2                                    
 *                                                                                                 
C                   z-add     0             binN                           CN-Zeichen binär        (2)
C                   movel     aE            binA3                          verarbeiten             
C                   move      aE            binA4                                                  
C                   select                                                                         
 *                                                                                                 
C                   when      binN  < x'80'                                bis 7f -> direkt        (3a)
C                   add       1             i8                                                     
C                   move      binA4         fTxt8(i8)                                              
 *                                                                                                 
C                   when      binN  < x'0800'                              bis '7ff' -> 2 Byte     (3b)
C                   eval      binN  = %bitand(binN : x'003f')                                      
C                                   + %bitand(binN *4: x'001f00')                                  
C                                   + x'c080'                                                   
C                   add       1             i8                                                  
C                   move      binA3         fTxt8(i8)                                           
C                   add       1             i8                                                  
C                   move      binA4         fTxt8(i8)                                           
 *                                                                                              
C                   when      binN  < x'010000'                            bis 'ffff' -> 3 Byte     (3c)
C                   eval      binN  = %bitand(binN : x'00003f')                                 
C                                   + %bitand(binN *4: x'003f00')                               
C                                   + %bitand(binN *16: x'0f0000')                              
C                                   + x'e08080'                                                 
C                   add       1             i8                                                  
C                   move      binA2         fTxt8(i8)                                           
C                   add       1             i8                                                  
C                   move      binA3         fTxt8(i8)                                           
C                   add       1             i8                                                  
C                   move      binA4         fTxt8(i8)                                           
 *                                                                                              
C                   other                                                                       
C                   add       1             i8                                                  
C                   move      x'3f'         fTxt8(i8)                      sonst ?              
C                   endsl                                                                       
 *                                                                                              
C                   enddo

Und der Vollständigkeit halber gleich noch eine einfache Konvertierung EBCDIC  UTF-8
Auch hier ein kurzer Abriss, wie das Programm arbeitet:

Eingangsparameter: data enthält den EBCDIC-String, dataLen ist die Länge
(1) Jedes Zeichen wird einzeln konvertiert,
(2) Die Position des Zeichens in c$ASC20 addiert mit 31 ergibt den ASC-Wert
(3) 8-Bit-Zeichen (über 127) oder Nicht-druckbare Zeichen frage ich explizit ab, das sind ja nicht viele.
Am Ende hat man in fTxt8 wieder den fertigen UTF-8 String.

Code:
D                 DS                         
D   binN                         9B 0        
D   binA1                 1      1A          
D   binA2                 2      2A          
D   binA3                 3      3A          
D   binA4                 4      4A          
 *                                           
D   fTxtE         S              1A   dim(2000)    
D   fTxt8         S              1A   dim(4000)  
D   fTxtC         S              2A   dim(4000)  
 *                                               
Dc$ASC20          S             95A   inz(' !"#$%&''()*+,-./- 
D                                     0123456789:;<=>?-       
D                                     @ABCDEFGHIJKLMNO-       
D                                     PQRSTUVWXYZ[\]^_-       
D                                     `abcdefghijklmno-       
D                                     pqrstuvwxyz{|}~')       
 *
 
 * EBCDIC ---> UTF-8                                                           
C                   movea     *blank        fTxtE                              
C                   movea     *blank        fTxt8                              
C                   movea     data          fTxtE                              
C                   z-add     *zero         i8                5 0              
C     1             do        dataLen       iE                5 0              (1)
C                   move      fTxtE(iE)     aE                1                
C                   add       1             i8                                 
 *                                                                             
C     aE            scan      c$ASC20       n                 5 0    50        (2)
C                   select                                                     
C     *in50         wheneq    *on                                              
C     n             add       31            binN                               
C                   move      binA4         fTxt8(i8)                          
C     aE            wheneq    'ä'                                          ä   (3)
C                   movea     x'c3a4'       fTxt8(i8)                          
C                   add       1             i8                                 
C     aE            wheneq    'ö'                                          ö   
C                   movea     x'c3b6'       fTxt8(i8)                          
C                   add       1             i8                                 
C     aE            wheneq    'ü'                                          ü   
C                   movea     x'c3bc'       fTxt8(i8)                          
C                   add       1             i8                                 
C     aE            wheneq    'ß'                                          ß   
C                   movea     x'c39f'       fTxt8(i8)                              
C                   add       1             i8                                     
C     aE            wheneq    'Ä'                                          Ä       
C                   movea     x'c384'       fTxt8(i8)                              
C                   add       1             i8                                     
C     aE            wheneq    'Ö'                                          Ö       
C                   movea     x'c396'       fTxt8(i8)                              
C                   add       1             i8                                     
C     aE            wheneq    'Ü'                                          Ü       
C                   movea     x'c39c'       fTxt8(i8)                              
C                   add       1             i8                                     
C     aE            wheneq    x'0d'                                        CR      
C                   movea     x'0d'         fTxt8(i8)                              
C     aE            wheneq    x'25'                                        LF      
C                   movea     x'0a'         fTxt8(i8)                              
C                   other                                                          
C                   move      x'3f'         fTxt8(i8)                      sonst ? 
C                   endsl                                                          
 *                                                                                 
C                   enddo