21st-Century CL

21st-Century CL

21st-Century CL Ted Holt Senior Software Developer, Profound Logic Software Senior Technical Editor, The Four Hundred [email protected] 1 Today well discuss . . . 1. 2. 3. 4. 5. 6. 7. 8.

Scope Data Structured programming Subroutines Built-in functions Files and database Miscellaneous enhancements Final thoughts 2 Scope 3 Scope Q: If you were designing a new computer language, would you include support for arithmetic? A: It depends. First you have to tell me the purpose of the language.

4 Scope CL falls into the category of job control languages. (It is fair to say that CL is more than a JCL, since CL not only controls jobs, but all the operations on the system.) Job control languages do not need many of the capabilities of RPG and other high-level application languages. CL was introduced in 1980 with the first shipment of the System/38 and remained largely unchanged until 2002 (V5R3). Somebody with clout persuaded IBM that CL was not robust enough. 5 Thus was born 21st-Century CL! 20th-Century CL

21st-Century CL dcl &Libs *char 80 dcl &Libs *char 80

dcl &Lib *char 10 dcl &Lib *char 10 + stg(*defined) defvar(&Libs 1) Next:

chgvar &lib %sst(&Libs 1 10) call somepgm chgvar &Libs parm(&Lib) %sst(&Libs 11 70) if (&Libs *ne ' ') then(goto Next) dountil (&Lib *eq ' ')

call somepgm parm(&Lib) chgvar &Libs %sst(&Libs 11 70) enddo 6 Data 7

New Data Types Signed integer (*INT) Unsigned integer (*UINT) Pointer (*PTR) These are the first new data types since 1980. 8 Integer Data Types Signed integer (*INT) Unsigned integer (*UINT) Signed integer type is more straightforward than the %BINARY (%BIN) function (but the %BIN function is not obsolete). Signed integer type is used by many APIs. Length is in bytes, not digits, and must be 2, 4 or 8. 9

dcl &Dta *char 80 dcl &BytesRtn *int 4 stg(*defined) defvar(&Dta dcl &BytesAvail *int 4 stg(*defined) defvar(&Dta dcl &Msglen *int 4 stg(*defined) defvar(&Dta dcl &Keylen *int 4 stg(*defined) defvar(&Dta dcl &Sequence *char 1 stg(*defined) defvar(&Dta dcl &IncSender *char 1 stg(*defined) defvar(&Dta dcl &Force *char 1 stg(*defined) defvar(&Dta

dcl &Text *char 50 stg(*defined) defvar(&Dta dcl &NbrMsgs *int 4 stg(*defined) defvar(&Dta dcl &NbrEntries *int 4 stg(*defined) defvar(&Dta dcl &DSLength dcl &QualDtaq *int 4 *char 20 chgvar %size(&Dta)

&DSLength 1) 5) 9) 13) 17) 18) 19) 20) 73) 77) /* Retrieve the data queue description. */ call qmhqrdqd (&Dta &DSLength 'RDQD0100' &QualDtaq) 10 Defined-on variables

Allow one variable to overlay another in memory Similar in function (but not in syntax) to data structures in RPG Syntax: STG(*DEFINED) DEFVAR(defined-on-variable beginning-position) Default beginning position is 1 11 Defined-on variable example dcl dcl dcl dcl dcl dcl &WorkDate

&Century &DateYMD &Year &Month &Day 0 9 8 *char *char *char *char *char *char

1 2 7 1 6 2 2 2 2 stg(*defined) stg(*defined) stg(*defined) stg(*defined)

stg(*defined) defvar(&WorkDate defvar(&WorkDate defvar(&DateYMD defvar(&DateYMD defvar(&DateYMD 1) 2) 1) 3) 5) 5 &WorkDate &Century &DateYMD

&Year &Month &Day 12 Pointers A pointer variable stores a memory address. You can use the ADDRESS parameter of DCL to initialize a pointer to the address of another variable. The %ADDRESS (or %ADDR) function lets you set a pointer. The %OFFSET (or %OFS) function lets you do pointer arithmetic. Pointers may be set to or tested for the *NULL constant. 13 Not the true size of the list, but we

don't care. pgm parm(&inList) dcl &inList *char dcl dcl dcl dcl dcl &pInList &ListSize &pElement

&CurElement &Ndx *ptr *int *ptr *char *int chgvar &pInList chgvar &pElement chgvar %offset(&pElement) dofor 1 2 10 2

stg(*based) basptr(&pInList) stg(*based) basptr(&pElement) %addr(&inList) &pInList (%offset(&pElement) + 2) &Ndx from(1) to(&ListSize) /* do something with &CurElement */ chgvar %offset(&pElement) enddo (%offset(&pElement) + 10) Move forward to the next

element. 14 This example processes a list (&inList) that is passed in by a command. &pInList is a pointer to the input parameter. The first two bytes of the parameter tell how many elements are in the list. If you run the following command for this program: DOIT OBJECT(SQUEEZLE PUCKERT SNOOFLE GRIPPICK) &ListSize has the value 4, because there are four elements in the list. &CurElement assumes the following values on each iteration of the DOFOR loop. SQUEEZLE (offset 3 of &inList) PUCKERT (offset 13 of &inList) SNOOFLE (offset 23 of &inList) GRIPPICK (offset 33 of &inList) Important: If the number of elements of the list changes in the command definition, the program does not require modification!!! CMD

PARM PROMPT('Do something') KWD(OBJECT) TYPE(*CHAR) LEN(10) MAX(12) + EXPR(*YES) PROMPT('List of objects') 15 Structured programming 16 Looping DOWHILE Top-tested loop Body of loop may not be executed at all Terminated by ENDDO 17

DOWHILE example dcl dcl &Libs &Lib *char *char 80 10 Not executed if &LIBS is blank! dowhile (&Libs *ne ' ') /* process the first library in the list */

chgvar &Lib &Libs . . . do something with &Lib /* remove the library that was just processed */ chgvar &Libs %sst(&Libs 11 70) enddo 18 1. &LIBS is a list of library names, such as: MYLIB YOURLIB HISLIB

HERLIB BIGLIBNAME 2. &LIB is one library name. 3. The first CHGVAR command copies the first 10 bytes of &LIBS to &LIB. (We dont need %SST (substring) because CHGVAR truncates, but we could use %SST if we wanted to clarify our intentions.) MYLIB 4. After the system has done something with that library name, the second CHGVAR removes the first library name from the list. After the first iteration, &LIBS looks like this: YOURLIB HISLIB HERLIB

BIGLIBNAME 5. The loop continues until all libraries have been processed. 19 Looping DOUNTIL Bottom-tested loop Body is always executed at least once Terminated by ENDDO 20 DOUNTIL example Executed at least once.

dountil (&Status *eq '0') call qrcvdtaq (&DtaQ &DtaQLib &DtaLen &Dta &Wait) select when (%sst(&Dta 1 1) *lt '1') then( chgvar &Status '0') when (%sst(&Dta 1 1) *eq '1') then( call Pgm1) when (%sst(&Dta 1 1) *eq 2') then( call Pgm2) when (%sst(&Dta 1 1) *eq 3') then( call Pgm3) endselect enddo 21 Looping DOFOR Top-tested loop Counted loop Terminating condition evaluated on each iteration (a moving target) Terminated by ENDDO Control variable must be an integer

Loop increment can be positive or negative 22 DOFOR example dcl dcl dcl dcl dcl &inOptions &Ndx &Option &OptOffset &ToReport chgvar

*char *uint *char *uint *lgl &OptOffset 82 2 8 2 /* list of options */ /* offset into the list */ 3

dofor var(&Ndx) from(1) to(%bin(&inOptions 1 2)) chgvar &Option %sst(&inOptions &OptOffset 8) select when (&Option *eq REPORT) then(chgvar &ToReport '1') when (&Option *eq NOREPORT) then(chgvar &ToReport '0') endselect chgvar &OptOffset (&OptOffset + 8) enddo (See https://www.itjungle.com/2014/07/09/fhg070914-story02/ for the complete example.) 24 LEAVE and ITERATE

LEAVE jumps to the statement immediately following the end of the loop ITERATE jumps to the loop-control test Optional CMDLBL parameter allows you to specify which loop you wish to LEAVE or ITERATE 25 Looping Middle-tested loops Implemented with DOWHILE DOWHILE 1 . . . code that must run at least once IF COND(. . .) THEN(LEAVE) . . . code that might not run at all ENDDO Must include a conditioned LEAVE to stop the loop

26 Middle-tested loop example dclf Schedule opnid(s) dowhile '1' Must be done at least once. Test to leave loop or not rcvf opnid(s) monmsg cpf0864 exec(leave)

May not be done at all. if (&s_active *ne A) then(iterate) . . . do something to active record enddo 27 Case construct Implemented with SELECT/WHEN/OTHER/ENDSELECT keywords THEN may be null to ignore a case May be nested up to 25 levels deep 28 SELECT example (with keywords) select when (&Option *eq O) +

then(chgvar &DevOption ('OUTQ(' *cat &OptValue *tcat ')')) when (&Option *eq D) + then(chgvar &DevOption ('DEV(' *cat &OptValue *tcat ')')) otherwise + cmd(chgvar &DevOption ('OUTQ(*DEV)')) endselect 29 SELECT example (without keywords) select when (&Option *eq O) + chgvar &DevOption ('OUTQ(' *cat &OptValue *tcat ')') when (&Option *eq D) + chgvar &DevOption ('DEV(' *cat &OptValue *tcat ')')

otherwise + chgvar &DevOption ('OUTQ(*DEV)') endselect 30 Limitations Maximum of 25 levels of DOxxx commands Maximum of 25 levels of SELECT commands 31 Subroutines 32 Subroutines Follow the main routine and precede ENDPGM

Bounded by SUBR and ENDSUBR commands Invoked by CALLSUBR command RTNSUBR and ENDSUBR leave a subroutine RTNSUBR and ENDSUBR may return a signed integer value Labels are local Recursive subroutine calls are permitted GOTO is not allowed into or out of subroutines Stack size is 99 levels, and may be changed to 20 thru 9999 in the SUBRSTACK parameter of the DCLPRCOPT command DMPCLPGM includes the subroutine stack 33 Subroutine with RTNVAL dcl dcl dcl &SubrStatus

&Stat &RecCount *int *int *dec 4 4 10 callsubr Prepare rtnval(&SubrStatus) select if (&SubrStatus *eq 2) do sndpgmmsg msgid(usr1001) msgf(myusrmsgf) + msgdta('Prepare routine requires file POST40.') + msgtype(*escape) subr Prepare

/* /* /* /* Return code 0 = all OK 1 = completed with warnings 2 = not completed due to a fatal error chgvar &Stat chkobj monmsg

post40 *file aut(*objexist) cpf9801 exec(rtnsubr rtnval(2)) */ */ */ */ 0 rtvmbrd file(post40) nbrcurrcd(&RecCount) if (&RecCount *eq 0) chgvar &Stat '1' . . . do something else endsubr rtnval(&Stat) 34 A more realistic example Use subroutines to divide a program into logically-related pieces.

callsubr callsubr callsubr return PrcParms CrtWorkF Updt /* process parameters */ /* create the work files */ /* update the database */ subr PrcParms . . . code to process the parameters endsubr subr CrtWrkF . . . code to create work files

endsubr subr Updt . . . code to update the database endsubr 35 Built-in Functions 36 Trim Functions %TRIM, %TRIML, %TRIMR First parameter is the character value to trim Second parameter is the group of characters to trim If no second parameter, these functions trim blanks 37

%TRIM example dcl dcl dcl &File &Lib &Stmf *char *char *char chgvar var(&Stmf) + value('/QSYS.LIB/' %trim(&Lib) %trim(&File) %trim(&File)

*cat *cat *cat *cat 10 10 128 + '.LIB/' *cat + '.FILE/' *cat + '.MBR') If &File is TEMP01 and &Lib is QTEMP, then &Stmf has a value like this: /QSYS.LIB/QTEMP.LIB/TEMP01.FILE/TEMP01.MBR 38

Case-conversion Functions %UPPER, %LOWER First parameter is the character value to convert Second parameter is the CCSID in which the data is stored. The default is zero, which means the jobs CCSID. 39 Case-conversion example Allow the operator to enter a value in uppercase, lowercase, or mixed case. dcl &Response *char

8 chgvar var(&Response) value(%upper(&Reponse)) if (&Response *eq RETRY) do 40 Scan Functions %SCAN find the position of one string within another one %CHECK search a string for a character that is not part of a set %CHECKR like %CHECK but search backwards from the end You may specify *LDA as the string to be searched/checked. 41 Example Does the list of options contain the value *REPORT?

dcl dcl &Options &CrtRpt chgvar &CrtRpt *char *lgl 82 (%scan('*REPORT ' &Options) *gt 0) 42

Type-conversion functions %CHAR %DEC %INT %UINT 43 Example dcl &DeleteCt *dec 7

call PurgePgm parm (&DeleteCt) SndPgmMsg ('Deleted' *bcat %char(&DeleteCt) *bcat 'orders.') Sample output: Deleted 105 orders. %CHAR discards leading zeros 44 Test Passed Parameters %PARMS returns the number of parameters passed by the caller Avoids referencing unpassed parameters More reliable than monitoring for MCH3601 pgm (&pOption) dcl &pOption *char

8 dcl &Option *char 8 value('NONE') if (%parms *ge 1) then(chgvar &Option &pOption) https://www.itjungle.com/2018/10/08/guru-learn-parms-solve-two-cl-problems/ 45 Memory-allocation functions %SIZE returns the number of bytes occupied by a variable

%LEN returns the number of digits (if numeric) or characters in a variable For character data, both functions return the same value. For numeric data, the functions return different values. Example: packed decimal 7,0 %LEN = 7 %SIZE = 4 46 Example dcl dcl &Cmd &CmdLen *char *dec

96 (15 5) chgvar chgvar &Cmd &CmdLen . . . whatever . . . %size(&Cmd) call qcmdexc (&Cmd &CmdLen)

If someone changes the size of &Cmd, no mod is required here. 47 Files and database 48 File support - Multiple Files Up to five declared files in one CL procedure OPNID parameter assigns an identifier to each open file One file may have an OPNID of *NONE CL variables are prefixed with the OPNID value and an underscore OPNID is used for all file-related commands: DCLF, CLOSE, RCVF, SNDF, SNDRCVF, WAIT, ENDRCV

49 Example dclf QAFDMBRL opnid(MbrList) dspfd file(&srclib/&srcfile) type(*mbrlist) + output(*outfile) outfile(qtemp/fdmbrl) ovrdbf qafdmbrl tofile(qtemp/fdmbrl) dowhile '1' rcvf opnid(MbrList)

monmsg cpf0864 exec(leave) . . . do something with one or more &MBRLIST_ fields. . . enddo 50 File Support CLOSE Allows you to close a file so it can be re-read A RCVF against a closed file opens the file 51 File Support RUNSQL Allows you to execute a single SQL statement in a CL procedure Work on those concatenation skills! 52

dcl dcl dcl dcl &FromDate &ThruDate &Comma &SQL *dec *dec *char *char 7 7 1

256 value(',') chgvar &SQL ('declare global temporary table SltData + (FromDate dec(7), ThruDate dec(7)) + with replace') runsql sql(&Sql) commit(*none) chgvar &SQL ('insert into session.SltData + values (' *cat %char(&FromDate) *cat + &Comma *cat %char(&ThruDate) *cat ')') runsql sql(&Sql) commit(*none) 53 Miscellaneous enhancements 54

INCLUDE Tells the compiler to copy in source code Like /COPY and /INCLUDE in RPG SRCMBR is the source member to copy SRCFILE is the file containing the copy member SRCFILE(*INCFILE) refers to the INCFILE parameter in CRTBNDCL, CRTCLPGM, CRTCLMOD 55 INCLUDE pgm include srcmbr(ErrorDcl) srcfile(qclsrc) . . . more code include srcmbr(ErrorRtn) srcfile(qclsrc) endpgm 56

Compile from a stream file CRTBNDCL PGM(QGPL/MYPGM) SRCSTMF('/home/mydir/mypgm.cl') Applies to CRTBNDCL, CRTCLMOD and CRTCMD, but not to CRTCLPGM. 57 Pass Parameters by Value Allowed on CALLPRC (specify *BYREF or *BYVAL) Useful for binding to C and MI routines Also works for calling RPG routines! 58 dcl &Dest *char (11) dcl &Src

*dec (10) value(-12652) dcl &Mask *char (18) value(x'34b1404e346034b2b2b2b2b2b2b2b2b2b2b2') dcl &DestLen *uint dcl &SrcLen

*uint dcl &MaskLen *uint chgvar &DestLen value(%size(&Dest)) chgvar &SrcLen

value(%len( &Src )) chgvar &MaskLen value(%size(&Mask)) callprc prc('edit_packed') parm((&Dest) (&DestLen *byval) + (&Src) (&SrcLen *byval) + (&Mask) (&MaskLen *byval))

59 Increased maximums Maximum number of parameters on PGM command increased from 40 to 255 Maximum number of parameters on CALL and TFRCTL commands increased to 255 Maximum number of PARM commands in command source increased from 75 to 99 Maximum size of *CHAR variables increased from 9999 to 32,767 61 Final thoughts 62 Final thoughts

CL is probably more or less what it will be when it comes to end of life, so you may as well master whats there. New RFE: Allow expressions in PARM parameter of CALL and CALLPRC commands!!! Please consider adding your vote!!! https://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=125376 63 Final thoughts CL is probably more or less what it will be when it comes to end of life, so you may as well master whats there. We could already do what many of these enhancements do by calling HLL programs. Dont try to replace RPG. 64

Take the pledge! I pledge . . . . . . to code loops with structured commands; . . . to divide big programs into subroutines; . . . to master the built-in functions; . . . never to write 20th-century CL again! 65 ENDPGM 66

Recently Viewed Presentations

  • Reviewing the Controller and Auditor General's reports for 2008/9

    Reviewing the Controller and Auditor General's reports for 2008/9

    The M&E framework has been developed with milestones under each KRA that monitor the results produced. DPs have organized their participation with DP leads established for each of the 5 KRAs. This is expected to enhance collaboration between DPs and...
  • Landmark Supreme Court Cases

    Landmark Supreme Court Cases

    In an 8-0 decision, the court ruled that "to read the Article II powers of the president as providing an absolute privilege. . .would upset the constitutional balance of a 'workable government' and gravely impair the role of the courts...
  • The Role of Background Knowledge in Reading Instruction

    The Role of Background Knowledge in Reading Instruction

    "Juicy Sentences"—Lily Wong Fillmore. Some texts are harder to read than others. Before CCSS, teachers could give students books at their instructional level. With CCSS, there is a reversal of that practice. There is no firm base of research to...
  • File Organizations and Indexing - UH

    File Organizations and Indexing - UH

    Heap File Implemented as a List The header page id and Heap file name must be stored someplace. Each page contains 2 `pointers' plus data. Heap File Using a Page Directory The entry for a page can include the number...
  • Databases at UCSC

    Databases at UCSC

    Databases at UCSC It just *looks* like 200,000 columns. The Databases Genome databases - one for each assembly of each organism: hg16, mm4, sacCer1, etc. hgFixed - mostly microarray data.
  • Chapter Five - Faculty Server Contact

    Chapter Five - Faculty Server Contact

    Forerunners of Control Theory: Durkheim's Anomie Theory. The nature of "man" argues that any person is a blend of two aspects: The social self or the aspect of self that looks to society and is a product of socialization and...
  • National Hydrology Project International Seminar Pune, India Building

    National Hydrology Project International Seminar Pune, India Building

    Floodzoom. DELWP. Web- and app-based, publically available. Water register. Web-based, publically available. Not publically available. Web-based, publically available. Verified data — monthly. BoM. Real-time data. Monitoring and maintenance. Extra Works (25% of total budget)
  • Public Forums - Connecticut

    Public Forums - Connecticut