Skip to content

Instantly share code, notes, and snippets.

@forstie
Last active July 2, 2023 05:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save forstie/22e52c397ce9dff94d4623f5cdbd995c to your computer and use it in GitHub Desktop.
Save forstie/22e52c397ce9dff94d4623f5cdbd995c to your computer and use it in GitHub Desktop.
The inspiration for this Gist came from a client. A piece of code had a long-standing problem where a variable was not initialized. Given the unpredictable nature of uninitialized made the topic hard to approach. This Gist shows how the IBM i Optimizing Translator can be used to find such problems within a dev or test environment.
-- Subject: Using initAuto to find uninitialized variable problems in ILE code
-- Author: Scott Forstie
-- Date : June, 2023
-- Features Used : This Gist uses SQL PL, INCLUDE, Change Program (CHGPGM) CL command, qsys2.joblog_info, qsys2.program_info, qsys2.qcmdexc, and QSYS2.BOUND_MODULE_INFO
--
-- A) Programmers use declared variables and structures to facilitate program logic.
-- B) Programmers should always initialize or assign declared variables and structures to contain known and expected values.
-- C) Programmers sometime miss step B.
--
-- This Gist shows how the IBM i Optimizing Translator can help.
-- ILE programs and service programs can be configured to use a supplied numeric value as the default value for any uninitialized automatic program storage.
--
-- Licensed Internal Code options (LICOPT) control for initAuto:
-- =============================================================
-- Initialize automatic storage to a sequence of bytes all having the specified value in binary representation.
-- If InitAuto is not specified, there is no automatic initialization.
-- When specifying the InitAuto LICOPT, it should be assigned an unsigned integer in the range 0-255.
-- Note:
-- 1) This control generates extra code and should only be used for error determination.
-- 2) LICOPT applies only to ILE code -- there is no OPM support of LICOPT
-- 3) LICOPT can be specified via many commands. This Gist will focus on CHGPGM.
--
stop;
--
-- Built an ILE C program that simply sends a message to the joblog.
-- The message text includes the value of the variable "the_length".
-- Note that "the_length" is NOT initialized or assigned a known value.
--
cl:addlible qsysinc;
cl:CRTSRCPF FILE(COOLSTUFF/QCSRC);
cl:addpfm file(COOLSTUFF/qcsrc) mbr(PRINT_IT);
insert into COOLSTUFF.qcsrc(srcdta) values
('int main(int argc, char **argv) '),
('{'),
('#include "qp0ztrc.h" /* for Qp0zLprintf */'),
('int the_length;'),
('Qp0zLprintf("The string length is:%d or in hex:%08X\n", the_length, the_length);'),
('}');
--
-- Create the ILE module and Program
--
cl: CRTCMOD MODULE(COOLSTUFF/PRINT_IT) SRCFILE(COOLSTUFF/QCSRC) DBGVIEW(*SOURCE);
cl: CRTPGM PGM(COOLSTUFF/PRINT_IT) MODULE(*PGM) ACTGRP(*CALLER) ;
stop;
--
-- Call the program
--
cl: call COOLSTUFF/PRINT_IT;
stop;
--
-- Examine the message that was sent to the joblog:
--
select message_text
from table (
qsys2.joblog_info('*')
)
where from_procedure = 'Qp0zVLprintf'
order by message_timestamp desc
limit 1;
stop;
--
-- Change Program (CHGPGM)
-- =======================
-- https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/cl/chgpgm.htm
--
-- Change Service Program (CHGSRVPGM)
-- ==================================
-- https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/cl/chgsrvpgm.htm
--
-- The Licensed Internal Code options that are currently defined are found here:
-- =============================================================================
-- https://www.ibm.com/docs/en/i/7.5?topic=options-currently-defined
-- (note: initAuto was not documented at the time this Gist was published, but was deemed safe and available for customer use)
--
-- Change the program to have a controlled value for uninitialized automatic storage.
-- In this case, the decimal value 91 will be used.
--
-- 91 == x'5B' == '01011011'B == the character '$'
--
cl: CHGPGM PGM(COOLSTUFF/PRINT_IT) LICOPT('initAuto=91');
stop;
--
-- Call the program once more
--
cl: call COOLSTUFF/PRINT_IT;
stop;
--
-- Examine the message that was sent to the joblog:
-- Note that if you see ZEROS, its because you got lucky. The variable is uninitialized!
--
select message_text
from table (
qsys2.joblog_info('*')
)
where from_procedure = 'Qp0zVLprintf'
order by message_timestamp desc
limit 1;
stop;
--
-- What does hex 5B look like in EBCDIC character form?
--
values x'5B5B5B5B';
--
-- Returns: $$$$
--
stop;
--
-- What is the decimal equivalent to hex 5B?
--
values hex(1532713819);
--
-- Returns: 5B5B5B5B
--
stop;
--
-- The BOUND_MODULE_INFO view returns information about modules bound into an ILE program or service program.
-- The Licensed Internal Code options that are in use by the module. Contains the null value if no LIC options were used for the module.
-- https://www.ibm.com/docs/en/i/7.5?topic=services-bound-module-info-view
--
--
-- Which programs have been configured to use initAuto?
--
select BOUND_MODULE_LIBRARY, BOUND_MODULE, lic_options, PROGRAM_LIBRARY, PROGRAM_NAME, OBJECT_TYPE
from QSYS2.BOUND_MODULE_INFO
where PROGRAM_LIBRARY = 'COOLSTUFF' and
upper(lic_options) like '%INITAUTO%';
stop;
--
-- Remove the InitAuto setting
--
cl: CHGPGM PGM(COOLSTUFF/PRINT_IT) LICOPT('*NONE');
stop;
--
-- Configure all ILE *PGMs in a library to use initAuto
--
select qsys2.qcmdexc('QSYS/CHGPGM PGM(' concat program_library concat '/' concat program_name concat ') LICOPT(''initAuto=91'')') as chgpgm_result
from QSYS2.PROGRAM_INFO
where PROGRAM_LIBRARY = 'COOLSTUFF' and object_type = '*PGM' and program_type = 'ILE';
stop;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment