In the last section, we wrote a routine that would read lines of text into a variable. This would make a nice utility routine that we can put into a service program.
In this section, we'll add another utility routine, one that can be used to send lines of text.
The requirements of this routine are a little different, because it's output-only. That means we don't need to write any data to a buffer, just take data that we already have and send it out. Since the routines that are calling this will often want to pass literals, constants, and expressions, it makes sense for us to accept an 'const' parameter, rather than a pointer.
Also, it'd be a bit of a pain, especially when working with literals, for the calling routine to have to calculate the length of the string each time it calls us. So, instead we'll figure that out ourselves by looking for the last non-blank character. We can still give an optional 'length' parameter, just in case the caller wishes to override this.
This method of searching for the last 'non-blank' character will be slow in most cases with a 32k buffer. Since 99% of the time, a line is less than 80 bytes long, this means that it'd have to search over 32,000 blank spaces each time we send a line. To make this a bit more realistic, the buffer on a call to the 'send line' procedure will only be 256 bytes.
Like the 'read line' routine, though, we still want to allow the caller the option of specifying different end-of-line characters. In RdLine() if the caller only wants one character to signify end-of-line, they can still do so... just make the extra parm be the same char, it won't hurt anything. When sending, however, that would cause problems. So, we'll determine how many chars to add for end-of-line based on how many parms are passed, instead of trying to use both like we did in RdLine().
I think that pretty much sums up the requirements. Here's the routine I actually came up with, check it out:
(This should be added to the member SOCKUTILR4 in the file QRPGLESRC)
P WrLine B Export D WrLine PI 10I 0 D peSock 10I 0 value D peLine 256A const D peLength 10I 0 value options(*nopass) D peXLate 1A const options(*nopass) D peEOL1 1A const options(*nopass) D peEOL2 1A const options(*nopass) D wwLine S 256A D wwLen S 10I 0 D wwXlate S 1A D wwEOL S 2A D wwEOLlen S 10I 0 D rc S 10I 0 C******************************************* C* Allow this procedure to figure out the C* length automatically if not passed, C* or if -1 is passed. C******************************************* c if %parms > 2 and peLength <> -1 c eval wwLen = peLength c else c eval wwLen = %len(%trim(peLine)) c endif C******************************************* C* Default 'translate' to *ON. Usually C* you want to type the data to send C* in EBCDIC, so this makes more sense: C******************************************* c if %parms > 3 c eval wwXLate = peXLate c else c eval wwXLate = *On c endif C******************************************* C* End-Of-Line chars: C* 1) If caller passed only one, set C* that one with length = 1 C* 2) If caller passed two, then use C* them both with length = 2 C* 3) If caller didn't pass either, C* use both CR & LF with length = 2 C******************************************* c eval wwEOL = *blanks c eval wwEOLlen = 0 c if %parms > 4 c eval %subst(wwEOL:1:1) = peEOL1 c eval wwEOLLen = 1 c endif c if %parms > 5 c eval %subst(wwEOL:2:1) = peEOL2 c eval wwEOLLen = 2 c endif c if wwEOLLen = 0 c eval wwEOL = x'0D0A' c eval wwEOLLen = 2 c endif C******************************************* C* Do translation if required: C******************************************* c eval wwLine = peLine c if wwXLate = *On and wwLen > 0 c callp Translate(wwLen: wwLine: 'QTCPASC') c endif C******************************************* C* Send the data, followed by the end-of-line: C* and return the length of data sent: C******************************************* c if wwLen > 0 c eval rc = send(peSock: %addr(wwLine): wwLen:0) c if rc < wwLen c return rc c endif c endif c eval rc = send(peSock:%addr(wwEOL):wwEOLLen:0) c if rc < 0 c return rc c endif c return (rc + wwLen) P E
Personally, I learn things better by typing them in, rather than reading them. Therefore, I recommend that you type the code examples in this tutorial in yours elf. However, if you'd like, you can download my copy of SOCKUTILR4 here: http://www.scottklement.com/rpg/socktut/qrpglesrc.sockutilr4