- THE PL/I NEWSLETTER -
|- THE PL/I NEWSLETTER -|
- THE PL/I NEWSLETTER -
GDDM is device-independent graphics program for IBM OS/390, VM and VSE systems. GDDM is a powerful system supporting a variety of terminals, printers, and plotters, and both raster and vector graphics. The API for GDDM is huge, consisting of nearly 500 functions! Despite this it is possible to generate reasonable graphics with a small number of calls. Best of all, IBM has provided a PL/I interface to GDDM.
This article is not a systematic description of the GDDM-PL/I interface.
It is a walk-through of a specific PL/I application that uses GDDM to generate graphics
UPTIME is a PL/I program which generates a line chart using the GDDM Presentation Graphics Facility (PGF). The data, obtained from SMF, is the daily uptime of several CICS subsystems for a one-month period. Only 31 lines of code are required to generate the chart. Here is the complete chart procedure; code has been rearranged to show the declarations with the code that uses them.
In the code that follows, MC is the number of subsystems being graphed (the number of different lines). CHART_CNT is the number of days in the current month (the number of data points for each line). Here is the procedure:
%INCLUDE(ADMUPINA); %INCLUDE(ADMUPINC); %INCLUDE(ADMUPIND); %INCLUDE(ADMUPINF); %INCLUDE(ADMUPING);
GDDM comes with 22 of these include files for different functions and options. On my system they live in 'GDDM.SADMSAM'. An easy way to remember these: all PL/I members begin with ADMUPI. The next character is N for the non-reentrant interface or R for the reentrant version. The last character corresponds to the first letter in the name of an entry point being called. I'm using the non-reentrant interface and making calls to functions whose names begin with A,C,D,F, and G.
DCL P_LIST (1)FIXED BIN(31); DCL N_LIST (1)CHAR(8) INIT('CHART'); CALL DSOPEN(0,4,'P38PPW3',0,P_LIST,1,N_LIST);P38PPW3 is a GDDM device token, a code describing the device type, media, pel density, etc. GDDM suppplies a large number of tokens for various output options and devices. If you don't like the supplied tokens, create your own: in this case, P38PPW3 is an IBM 3800 page-printer, 240ppi, page size 11×8, landscape. The other parameters say that this is the default output device , specify the device family [printer, plotter, terminal, etc] , provide miscellaneous options [0,P_LIST], and specify a device name [1,N_LIST].
In this example P_LIST is a dummy argument since the count  indicates this parameter is not used. N_LIST is used to specify the DDNAME of the output files: one DD named CHART.
DCL CHART_MARKS (8)FIXED BIN(31) INIT(8,7,6,4,3,2,1,5); DCL HEADING CHAR(120) VARYING; CALL CHMARK( FIXED(HBOUND(CHART_MARKS,1),31), CHART_MARKS ); HEADING = 'SUBSYSTEM UPTIME '||CHART_LBLS(1)|| ' TO '||CHART_LBLS(CHART_CNT); CALL CHHEAD(LENGTH(HEADING),HEADING); HEADING = 'UPTIME (HR)'; CALL CHYTTL(LENGTH(HEADING),HEADING); HEADING = 'DAY'; CALL CHXTTL(LENGTH(HEADING),HEADING);CHART_MARKS override the default identifying characters for the line representing each subsystem because I felt the defaults were hard to read. The other statements provide the title of the chart, and the X- and Y-axis descriptions.
DCL CHART_CNT FIXED BIN(31) INIT(0); DCL CHART_POINTS (*,*)FLOAT CONTROLLED; DCL CHART_LBLS (*)CHAR(10) CONTROLLED; DCL CHART_SCALE (*)FLOAT CONTROLLED;First the X-range:
CALL CHXRNG(1,CHART_CNT);The parameters are converted to FLOAT and represent the lowest and highest values of the X-axis data: one to the number of days in the month.
The X-axis labels:
CALL CHXDLB(CHART_CNT,LENGTH(CHART_LBLS(1)),CHART_SCALE,CHART_LBLS);CHART_SCALE is an array of values representing the X-axis value for each tick-mark. CHART_LBLS is an array of labels for the tick-marks (in this case the dates). GDDM will select some of these to be printed when the chart is generated; I have to provide all of them [CHART_CNT]. Labels in the array must be nonvarying character strings with a length indicated by the argument LENGTH(CHART_LBLS(1)).
The "datum-line" (optional):
CALL CHYDTM(FLOAT(PRIME_INT) / INT_PER_HOUR );CHYDTM specifies the Y-axis value the "datum" line is to pass through, in this case I specify a point equal to the number of hours in the prime shift (normally 7.5).
DCL MC FIXED BIN(15) INIT(0); DCL MONITOR_TASK (MAX_MON)CHAR(8); CALL CHKEY(MC,LENGTH(MONITOR_TASK(1)),MONITOR_TASK);MONITOR_TASK is an array of nonvarying character strings to be used to label the lines in the chart "key". The procedure is called with the number of labels [MC], the length of each label [LENGTH(MONITOR_TASK(1))], and the address of the array of labels.
DCL CHART_POINTSX (MC*CHART_CNT)FLOAT; CALL CHPLOT(MC,CHART_CNT,CHART_SCALE,CHART_POINTSX);That's all there is to it! CHART_POINTSX is an array of FLOAT values in row-major order containing values for each of MC subsystems for CHART_CNT days.
CALL CHTERM; CALL FSFRCE; CALL FSTERM;
The file uptimel.pdf is a larger example of the sample chart shown above [PDF format].
Regardless of whether TAB would or not become part of the language,
I have written some macro procedures that will allow a statement
like the one above to be written. The macro generates the verbose
DECLARE statement that sets the tabs. Of course, the INITIAL values
of the DECLARE statement
are set at link time, so the TAB option can be "executed" only once
in a program.
The accompanying TAB file implements such a facility using the macro facility of PL/I for OS/2.
The spring 2000 edition of the
COBOL and PL/I newsletter
has some topics about PL/I. The specific PL/I
topics may be viewed separately, or the entire newsletter in PDF
format may be downloaded.
Of particular interest is the use of PL/I as a programming language for the Common Gateway Interface (CGI).
The PL/I Connection newsletter.
The PL/I Connection Newsletter No. 11 , December 1997.
The PL/I Connection Newsletter No. 10 , April 1997.