|
Dan, >>Don't give up on procedures. Think of them as programs that do >>one thing and accept parameters. Once you get the definition and >>declaration (prototype and interface) syntax down it's no big deal. > >You're right, of course. I just got to do the _FIRST_ one! >When I've got a few hours to burn. I know, I know, just DO it! Joel is absolutely right! Jump right in! I personally feel very comfortable putting in a procedure where I used to use a subroutine. The "trick" is to identify the subroutine's input and output, so you can make them parameters instead of allowing them to be accessed globally. I don't think I'd get much argument by saying that global variables should be used less than GOTO's, and for the same reasons. At the risk of completely wearing out my welcome, here is a "how I thought about building a procedure" example. This is a great place for anybody else to critique both my thinking and it's results. We could all learn some cool stuff this week! :-) A very typical place to start with new procedures is to prototype a system API, like the translate API. Original inline code looked like this: C CALL 'QDCXLATE' C PARM FLDLEN C PARM TEXT C PARM TBLNAM C PARM LIBNAM This code frag was in 3 places in the program: a perfect candidate for a subroutine. There were 3 different fields being translated to upper case: TEXT, DESC and TITLE. This meant inline code that looked like this: C MOVELTEXT XFIELD C EXSR UCASE C MOVELDESC XFIELD C EXSR UCASE C MOVELTITLE XFIELD C EXSR UCASE with a subr like: C UCASE BEGSR C CALL 'QDCXLATE' C PARM FLDLEN C PARM XFIELD C PARM TBLNAM C PARM LIBNAM C ENDSR This subr can easily be turned into a procedure: C CallP UCASE(Text) * Translate lower to upper case P UCASE B D UCASE PI D WorkString 50 C CALL 'QDCXLATE' C PARM FLDLEN C PARM WorkString C PARM TBLNAM C PARM LIBNAM C Return P UCASE E This procedure has a problem: it isn't stand-alone because of the three global variables FLDLEN, TBLNAM and LIBNAM. In order to use this procedure in another program, I'd need to define and populate these exact field names in the new program. Sounds like a perfect use for some more parameters: C CallP UCASE(Text:'QSYSTRNTBL':'QSYS') * Translate lower to upper case P UCASE B D UCASE PI D WorkString 50 D XlateTableNam 10 Value D XlateTableLib 10 Value D WorkStringLen S 5p 0 C Eval WorkStringLen = %len(WorkString) C CALL 'QDCXLATE' C PARM WorkStringLen C PARM WorkString C PARM XlateTableNam C PARM XlateTableLib C Return P UCASE E This is a bit better because if I decide to change the length of the input string, I don't need to change the guts of the code - it determines the length using the %len BIF. But still, it seems kind of goofy to specify the translate table name for every CALLP to a procedure named UCASE. This procedure really does the function TRANSLATE. If I rename this one TRANSLATE, I could make a new procedure called UCASE that will only perform the uppercase function: C CallP UCASE(Text) * Translate lower to upper case P UCASE B D UCASE PI D WorkString 50 C CallP Translate(WorkString:'QSYSTRNTBL':'QSYS') C Return P UCASE E * Translate string according to supplied table P Translate B D Translate PI D WorkString 50 D XlateTableNam 10 Value D XlateTableLib 10 Value D WorkStringLen S 5p 0 C Eval WorkStringLen = %len(WorkString) C CALL 'QDCXLATE' C PARM WorkStringLen C PARM WorkString C PARM XlateTableNam C PARM XlateTableLib C Return P Translate E If it turns out that I need to deal with French uppercasing next month, this will fail, because QDCXLATE doesn't do different CCSID's As our friend Bruce Vining has been patiently repeating, the QLGCNVCS API supports multiple CCSIDS, and is the recommended means for doing casing. It's a fairly simple matter to replace the call to QDCXLATE with a call to QLGCNVCS in the Translate procedure, despite the fact that the parameter lists are different. This is because those differences are "hidden" because we don't call Translate directly - we go through UCASE first. The parameters for UCASE won't change at all, so all the programs that need UCASE are unaffected by the changes to Translate. Here's the result of changing Translate to use QLGCNVCS: C CallP UCASE(Text) * Translate lower to upper case P UCASE B D UCASE PI D WorkString 50 C CallP Translate(WorkString:'U':0) C Return P UCASE E * Translate to upper/lower according to supplied CCSID P Translate B D Translate PI D WorkString 50 D CaseInp 1 Value D CCSIDInp 10u 0 Value * Request Control Block D ReqCtrlBlock Ds * Requesting CCSID based casing D ReqTyp 10u 0 Inz(1) * CCSID 0=job CCSID D CCSID 10u 0 Inz(0) * 0=to upper, 1=to lower D CaseFlag 10u 0 * Reserved for other casing types D Reserved 10a * API error structure D ErrStruc Ds D StrucSize 10i 0 D BytesReturned 10i 0 D ErrorID 7a D ErrReserved 1a D ErrorData 256a D Length S 5p 0 D Input S like(WorkString) D Output S like(WorkString) C Eval CCSID = CCSIDInp C Select C When CaseInp = 'U' C Eval CaseFlag = 0 C When CaseInp = 'L' C Eval CaseFlag = 1 C Other C Eval CaseFlag = 0 C EndSl C Eval Length = %len(WorkString) C Eval Input = WorkString C Eval Output = *Blanks C Eval StrucSize = %len(ErrStruc) C Eval BytesReturned = 0 C Eval Reserved = *Allx'00' C CALL 'QLGCNVCS' C PARM ReqCtrlBlock C PARM Input C PARM Output C PARM Length C PARM ErrStruc * Primitive error handling C If ErrorID <> *Blanks C Dump C Else C Eval WorkString = Output C EndIf C Return P Translate E I hope this was of some use to folks who are in the early stages of using RPG IV procedures. I'd really appreciate feedback good and bad. The clearer I can present this stuff to OUR folks, the better our shop will become! Many thanks for your patience, Buck Calabro +--- | This is the RPG/400 Mailing List! | To submit a new message, send your mail to RPG400-L@midrange.com. | To subscribe to this list send email to RPG400-L-SUB@midrange.com. | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: david@midrange.com +---
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.