IBM Support

ASCII Runtime for IBM i



ASCII Runtime for IBM i provides developers a virtually seamless solution with little impact on performance between an ASCII application and the EBCDIC ILE environment of IBM i. By functioning as an "interface layer" between an application and an IBM i system, the changes required by developers are significantly lowered if not eliminated when this product is correctly implemented.


What happened to the ASCII Runtime PRPQ?

Welcome to the home page for the ASCII Runtime for IBM i. This page contains the latest information on this product.

ASCII Runtime for IBM i provides developers a virtually seamless solution with little impact on performance between an ASCII application and the EBCDIC ILE environment of IBM i. By functioning as an "interface layer" between an application and an IBM i system, the changes required by developers are significantly lowered if not eliminated when this product is correctly implemented.

ASCII Runtime provides the means for an ASCII application running on IBM i to send and receive EBCDIC string values and enables ASCII applications to interface with many common APIs, such as printf() and scanf(), that take and return EBCDIC strings. Specifically, ASCII Runtime enables an ASCII application to send EBCDIC output to an IBM i server and to receive EBCDIC input in an IBM i server. This allows ASCII and EBCDIC applications to "talk" and allows the use of standard I/O.

This product provides ASCII Runtime libraries for IBM i and supports ASCII/EBCDIC conversion as well as ASCII/UNICODE conversion. This product is intended to be used as a tool for porting ASCII applications to ILE and is not a replacement for the standard runtime libraries.

What happened to the ASCII Runtime Programming Request for Price Quotation (PRPQ)?

Beginning with V5R1, the ASCII Runtime service programs became part of OS/400. In V5R1 this support was made available via PTF. In V5R2, the support is shipped with the operating system. This means that the ASCII Runtime PRPQ (5799-AAS) will no longer be needed when running ASCII applications on V5R1 or later. Find instructions on how to remove the ASCII Runtime PRPQ from your system.

The operating system version of ASCII Runtime will support the same APIs that have been supported by the ASCII Runtime PRPQ. However, the header files and modules that are required for developing software that uses the ASCII Runtime will not be part of OS/400. If you plan on developing software for the ASCII Runtime, download the ASCII Runtime Development Kit.

ASCII Runtime Development Kit

The ASCII Runtime Development kit contains the headers files and modules that are required to develop software that uses the OS/400 ASCII Runtime. See Helpful Tips for more information.

To install the ASCII Runtime Development Kit, perform the following steps:

  1. Create a *SAVF on your IBM i by running the command CRTSAVF my_lib/QADRTDEV
  2. Download (zip, 200 KB) to your local PC or workstation.
  3. Unzip to generate qadrtdev.savf.
  4. FTP qadrtdev.savf to your IBM i. This can be done by executing the following from your PC or workstation:
    ftp my_iSeries
    bin put qadrtdev.savf my_lib/QADRTDEV.SAVF
  5. Restore the QADRT library by running the command RSTLIB SAVLIB(QADRT) DEV(*SAVF) SAVF(my_lib/QADRTDEV).
  6. Create the necessary symbolic links in IFS by calling QADRTSETUP. This can be done with the command CALL PGM(QADRT/QADRTSETUP).
  7. You are now ready to develop software that uses OS/400 ASCII Runtime.

Revisions to the ASCII Runtime Development Kit:

11/12/2021 A fix for vsnprintf_a() in stdio.h.
09/07/2021 Add snprintf_a() and vsnprintf_a() support to stdio.h (V7R3 and later releases, enabled by macro 'USE_ASCII_SNPRINTF' and 'USE_ASCII_VSNPRINTF').
           Add getaddrinfo_a() support to netdb.h (V7R3 and later releases, enabled by macro 'USE_ASCII_GETADDRINFO').
11/26/2014 Update time.h for _64_BIT_TIME macro support.
12/06/2013 Add ctime64_a() and ctime64_r_a() support to time.h, and refresh QADRTMAIN, QADRTMAIN2, and QADRTMAIN3 *MODULEs.
10/16/2008 Refresh QADRTMAIN, QADRTMAIN2, and QADRTMAIN3  *MODULEs to avoid requirement for OPTION(*DUPPROC *DUPVAR).
08/31/2007 Add ungetc_a() support to stdio.h (V5R3 and later releases  only)  04/16/2007 Updates to ctype.h.
09/15/2005 Changes to QADRTMAIN3 *MODULE to allow 16 byte argv  pointers.
06/15/2005 Refresh QADRTMAIN, QADRTMAIN2, and QADRTMAIN3   *MODULEs.
02/09/2005 Updates to stdio.h, stdlib.h, and sys/stat.h to fix 'qadrt_use_inline' problems.
11/07/2003 Original version.

Frequently Asked Questions

How does ASCII Runtime for IBM i work?

Support for the ASCII Runtime is provided by four service programs: QADRTTS, QADRTTS2, QADRTDSM, and QADRTDSMT2.

The ASCII Runtime Development Kit provides three modules named QADRTMAIN, QADRTMAIN2 and QADRTMAIN3, which can be used as replacements for main. It also provides several header files such as stdio.h, ctype.h.

The ASCII Runtime for IBM i version of these header files is expanded in place of the standard header files that are included in the source code. However, they do not replace the standard header files. The runtime APIs are remapped to the ASCII Runtime for the IBM i APIs provided in the service program. The ASCII Runtime APIs make the necessary conversions and then call the regular runtime APIs.

What changes do I have to make to my source code?

Character literals need to be mapped to ASCII (CCSID 819). If the compiler you are using has an option to map the literals, then no changes to the source code are necessary. If no compiler option is available, a single line of "#pragma convert(819)" will need to be added to the beginning of each source file. It is also necessary to ensure that the build process is set up correctly. This requires changing the library list (if compiling on IBM i) or the search path (if using a cross compiler) to include the ASCII Runtime header files before any standard header files. This is necessary and will ensure that the appropriate functions are remapped to the proper conversion routines.

How does ASCII Runtime for IBM i affect performance?

ASCII Runtime for IBM i enables conversion between ASCII and EBCDIC with a minimal amount of performance impact. This is accomplished by the creation of mapping tables, which are stored as permanent objects in QUSRSYS on IBM i. The conversion routines themselves are all inlined to avoid the extra overhead of a function call. This method of inlining the conversion routines and creating permanent tables significantly increases performance over other conversion routines such as iconv().

Note that before tables are created the performance of a program that uses ASCII Runtime will be degraded. This results from the creation of the conversion tables that are created the first time a program is run. Conversion tables can also be created before hand by calling the program QADRTCINF, which is shipped with this product.

Support Information

ASCII Runtime is now part of OS/400 and is supported by IBM Worldwide Service and Support. Contact your service representative to report a problem.

Latest ASCII Runtime PTF's















Compiling a program

The ASCII Runtime was developed with the intent that compiling and running a program would be nearly transparent to users. Meaning that little or no change to the source code, such as an extra #include, #define, or other changes are necessary. The only modifications necessary are to the build process. With this in mind lets me explain what it takes to compile by using the ASCII Runtime.

These four items are necessary for a successful build:

  1. The program a program MUST bind with either of these two service programs: QADRTTS for teraspace enabled, or QADRTTS2 for full teraspace support.
  2. The preprocessor must pick up the ASCII Runtime include files before the standard include files.
  3. If parameters are passed to main(), it must be redefined to convert the parameters. The new main() must be used as the program entry point. *MODULE QADRTMAIN and *MODULE QADRTMAIN2 have been provided for this purpose. They can only handle character string parameters. If your program only accepts character strings as parameters, it is recommended that one of these modules is used as the program entry point. QADRTMAIN supports Dynamic Screen Manager (DSM) while QADRTMAIN2 does not. It is highly recommended that QADRTMAIN2 is used unless there is a definite requirement for DSM (If you have never heard of DSM, then you probably aren't using it). If your program must handle parameter types other than character strings, then you need to supply your own main() that will only convert character string parameters.
    If character parameters are passed to main() it must be redefined to convert those parameters from EBCDIC to ASCII. For more information, see the 'Providing a program entry point' section below.

These compiler parameters must also be set: system interface = *IFSIO, locale support = *LOCALE. Once these changes to the build process have been made the source can now be compiled by using an ASCII code page. The result is an ASCII IBM i program that can interact with EBCDIC data.

Running a program

Running a program that uses the ASCII Runtime is simple. If the program is correctly bound to one of the ASCII Runtime service programs, then the program can be run like any other IBM i program.

Performance note: The first time a program is run that uses the ASCII Runtime conversion tables are created and stored permanently in library QUSRSYS. The creation of conversion tables takes place only once and only affects a program running for the first time.

A program named QADRTCINF is provided and enables a user to create conversion tables before a program is run if wanted.

Providing a program entry point

String arguments to the program entry point (that is, the main() function) are encoded in job CCSID unless the caller explicitly coded the strings in a different CCSID. If a program is called from the command line or from a command object, then incoming text strings will always be in job CCSID. Job CCSID is always an EBCDIC CCSID, so string parameters need to be converted to ASCII before they can be used by an ASCII Runtime program. There are a couple of ways to accomplish this.

  1. If all of the parameters to the program are string parameters the ASCII runtime takes care of parameter conversion. The ASCII runtime header files will automatically map the existing main function to the name 'main_a'. When binding the program one of the provided QADRTMAIN modules need to be used to provide the actual 'main' routine. There are three provided QADRTMAIN modules: QADRTMAIN, QADRTMAIN2 and QADRTMAIN3. Each of these modules contains a main() function that converts all parameters from EBCDIC to ASCII and then calls main_a() with the updated parameter list. The QADRT/QADRTMAIN2 module is used for STGMDL(*SNGLVL) programs and the QADRT/QADRTMAIN3 module is used for STGMDL(*TERASPACE) programs. It is highly recommended that QADRT/QADRTMAIN2 or QADRT/QADRTMAIN3 be used unless there is a requirement for Dynamic Screen Manager (DSM). If you have never heard of DSM, then you are probably not using it, and QADRT/QADRTMAIN2 or QADRT/QADRTMAIN3 should be used. If DSM support is required, then the QADRT/QADRTMAIN module can be used.
  2. If the program takes no parameters, or if all of the parameters to the program are non-string parameters, the macro variable 'qadrt_no_main' can be defined and the special processing for main described in the previous item will not take place. Note: The first parameter to all C and C++ programs (argv[0]) is the program name. This will always be passed in EBCDIC, so if this option is chosen, it must be verified that the program does not use argv[0], or that the program can tolerate an argv[0] value in EBCDIC.
  3. If the program accepts a mix of string and non-string parameters, a custom main() routine needs to be used to do parameter conversion. Add the macro variable 'qadrt_no_main' define to the compile command to avoid the processing described in the first item. In the main() function, all string parameters need to be converted from job CCSID to ASCII. Non-string parameters should not be converted. After any parameter conversion has been done, the 'main_a' function should be called with the converted parameter list.


Using the native OS/400 compiler

  1. Place library QADRT at the top of the library list.
  2. Compile the source with these options: system interface = *IFSIO and locale object type = *LOCALE.

The following are examples of CRTCMOD and CRTPGM commands that use the OS/400 ILE C compiler.



It is recommended that the program runs in a new activation group. This is accomplished with the following parameter of CRTPGM:


Using a cross compiler

  1. Map a drive to the IBM i that has the product installed.
  2. Ensure that the IFS directory containing the ASCII Runtime include files are first in the search path, or if using a makefile the first to be included. The IFS directory containing these files are located at /QIBM/ProdData/qadrt/include.
  3. Compile the source with these options: system interface = IFS and locale object type = LOCALE (most likely default settings).
  4. Bind the service program QADRTTS or QADRTTS2 to your program.
  5. Use module QADRTMAIN as the program entry point (optional if you provide you own main() function).

The following is an example makefile used to compile with the Visual Age for IBM i Cross Compiler. Note that this makefile is not complete.

# Example Makefile                                                              #
# This makefile shows one method of implementing ASCII Run
# Time for IBM i along with a build process that doesn't implement
# ASCII Runtime in order to contrast the differences.
# The sample code contained herein has not been thoroughly tested
# under all conditions. Therefore, IBM does not warrant or guarantee
# its reliability, serviceability, or function. All sample code contained
# herein is provided to you "AS

# Assumptions                                                                       #
#Drive Z: is mounted to the IBM i where QADRT is installed
#Directory C:\cttasw\include contains standard include files
#on a local PC
# Macros                                                                                  #
SRC = example.c A_INCLUDE = Z:\QIBM\ProdData\qadrt\include;C:\cttasw\include;C:\cttasw \include\acl;Z:\QIBM\include E_INCLUDE = C:\cttasw\include;C\:cttasw\include\acl;Z:\QIBM\include .SUFFIXES : .c .eo .ao .ex .ax .c.eo: -$(ASCONN) iccas /I$(E_INCLUDE) /AScp37 $(SRC) -$(ASDIS) .eo.ex: -$(ASCONN) ctthcmd /ASnQADTEST CHGCURLIB curlib(TEST) ctthcmd /ASnQADTEST CRTPGM PGM(QGPL/EXAMPLE) MODULE(EXAMPLE) -$(ASCONN) iccas /I$(A_INCLUDE) /qifs=32 /ASwcharucs2+ /AScp819 $(SRC) -$(ASDIS) -$(ASCONN) ctthcmd /ASnQADTEST CHGCURLIB curlib(TEST) ctthcmd /ASnQADTEST CRTPGM PGM(QGPL/EXAMPLE) MODULE(EXAMPLE) BNDSRVPGM(QADRT/QADRTTS) ENTMOD(QADRT/QADRTMAIN)

Header files shipped with ASCII Runtime for IBM i

This list includes the header files of currently supported ASCII Runtime APIs. These files are contained in library QADRT. Corresponding files exist in IFS that are symbolically linked to these header files.

Header files contained in *FILE H:

ctype.h             dirent.h            fcntl.h
grp.h               iconv.h             ifs.h
langinfo.h          locale.h            netdb.h
pwd.h               qadrt.h             qascii.h
qleawi.h            spawn.h             stdio.h
stdlib.h            string.h            strings.h
time.h              unistd.h            utime.h

Header files contained in *FILE SYS:

ipc.h               stat.h              statvfs.h

Header files contained in *FILE ARPA:


Supported CCSID Mappings

Conversions between the following pairs of EBCDIC and ASCII CCSID's are currently supported by ASCII Runtime. This list can also be generated by typing the following command on the IBM i where ASCII Runtime is installed.


Format of Internal Files


Each record is 512 byte length and has the following fields. The record that has 0 for e_ccsid is interpreted as the end of record.

long          e_ccsid;          /* EBCDIC CCSID                 */
long          e_es;             /* EBCDIC Encoding Schema       */
long          a_ccsid;          /* ASCII CCSID                  */
long          a_es;             /* ASCII Encoding Schema        */
cnv_obj       tables;           /* work area                    */
char          reserved[81];
char          cnv_file[22];     /* conversion table file name   */
                                /* name in ASCII: 10 (lib) + 1  */
                                /* (/) + 10 (file) + 1 (NULL)   */
char          e_text[64];       /* text description for EBCDIC  */
                                /* CCSID in ASCII               */
char          a_text[64];       /* text description for ASCII   */
                                /* CCSID in ASCII               */
char          source_type;      /* 0x01: iconv, 0x02: file      */
long          timestamp;
long          version;


The first 4096 byte field is the header record and has the following fields. A series of mapping table records are following.

long          rec_size;         /* 4096                         */
long          data_rec;         /* the first data record number */
long          num_data_rec;     /* a number of data records     */
long          buffer_size;      /* required bytes for all tables*/
long          offset_u2a;
long          offset_a2u_sl;
long          offset_a2u_sv;
long          offset_a2u_d;
long          offset_a2e_sl;
long          offset_a2e_sv;
long          offset_a2e_d;
long          offset_e2a_s;
long          offset_e2a_d;
long          reserved1[3];
cnv_info_t    cnv_info;
char          mapping_file[256]; /* The original mapping file   */
                                 /* name of the conversion      */
                                 /* tables.                     */
char          reserved2[3526];   /* The record size is 4096.    */

The user has to verify that timestamp and version in CNVINFO file are the same as those in CNVxxxxx file. The user has to allocate a memory area with the size of buffer_size and load all mapping table records contiguously.

The structure cnv_obj is used for the actual conversion and has the following fields:

unsigned short *      u2a;       /* buffer_address+offset_u2a   */
unsigned char *       a2u_sl;    /* buffer_address+offset_a2u_sl*/
unsigned short *      a2u_sv;    /* buffer_address+offset_a2u_sv*/
unsigned short *      a2u_d;     /* buffer_address+offset_a2u_d */
unsigned short *      e2a_s;     /* buffer_address+offset_e2a_s */
unsigned short *      e2a_d;     /* buffer_address+offset_e2a_d */
unsigned char *       a2e_sl;    /* buffer_address+offset_a2e_sl*/
unsigned short *      a2e_sv;    /* buffer_address+offset_a2e_sv*/
unsigned short *      a2e_d;     /* buffer_address+offset_a2e_d */
unsigned char  *      buffer_address;
long                  buffer_size;
unsigned short        a_sub_d;
unsigned short        e_sub_d;
unsigned char         a_sub_s;
unsigned char         e_sub_s;
char                  reserved[86];  

These fields have to be initialized correctly before calling conversion routines.


The name of CNVxxxxvv file is assigned by QADRTCINF as below.

xxxxx   = five digit EBCDIC CCSID
vv      = version number from 00,01,..,0A,..,0Z,..9Z,A0,.. through ZZ  

APIs that are currently supported by QADRT are contained in both the QADRTTS and QADRTTS2 service programs.

Additional APIs provided by the ASCII Runtime

ASCII Runtime includes support for many of the most commonly used APIs. For APIs not supported, the built-in conversion routines are available by using the following functions.

long QadrtConvertA2U(unsigned char * dst,
                     const unsigned char * src,
                     const long dest_len,
                     const long src_len)
QadrtConvertU2A (unsigned char * dst,
                 const unsigned char * src,
                 const long dst_len,
                 const long src_len)
QadrtConvertA2E (unsigned char * dst,
                 const unsigned char * src,
                 const long dst_len,
                 const long src_len)
QadrtConvertE2A (unsigned char * dst,
                 const unsigned char * src,
                 const long dst_len,
                 const long src_len)
int QadrtGetASCII_CCSID(int)
int QadrtGetEBCDIC_CCSID(int)  

[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SWG60","label":"IBM i"},"ARM Category":[{"code":"a8m0z0000000CHtAAM","label":"Programming ILE Languages"}],"ARM Case Number":"","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"All Version(s)","Line of Business":{"code":"LOB57","label":"Power"}}]

Document Information

Modified date:
23 November 2021