RPG Free - Tutorial 4

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

/Free Tutorial 4

Shirey Consulting Services

Tutorial 4 Miscellaneous Stuff

There are a number of relatively small issues that I need to cover before we are done and now is as good a time as any. As we go through this section, you will notice that we are forced to use a number of built-in-functions. That is a hallmark of /Free, and should be a hallmark of your coding. BIFs can do many things easier and faster than you could do it and learning how to use them, while not directly a part of /Free, is imperative to using /Free effectively.

Data Movement I have to admit, several years ago when I first looked into /Free, I was a bit unsettled to find that the MOVE statements were one of the op codes that are not supported. Instead, you use the EVAL to move data from one spot to another. The problem is, while EVAL moves data, the MOVE codes would also translate it from one format to another. Without it, you need to do the translation and then do an EVAL to move it. I know, that sounds awful, and to begin with, it is. But you have lots of help in the built in functions, and in no time at all (really) you are able to do even complicated data transfers quickly and easily and never think twice about the missing Move. We will take a look at a couple of examples, but for a heavier treatment, see the Martin book or a standard, modern RPG reference manual. Character to Character This is no big deal and the Eval handles it easily. In fact, this is what Evals do best. Yes, there will be truncation if the to field is smaller than the from field, and left justification if its vice a versa but we all know that. Spaces will be used for any padding required. Since left justify is the default, you need to use EVALR to right adjust. This is identical to the MOVEP. Numeric to Numeric Again, no big deal. ILE (and /Free) support a number of numeric data types (like packed, signed, binary, floating point, zoned, integer, etc. or maybe thats it, cant remember) and the EVAL will automatically convert from one to another, centering everything around the decimal point. Zeros will be used for padding where necessary and if the receiver field is too small you will get an exception message during the run. An extender (h) can be used to do half adjust (EVAL(h)).

Page 1

/Free Tutorial 4 Numeric to Character

Shirey Consulting Services

This is where we start needing help. This is the kind of thing that MOVE did but which EVAL cant do without an assist from his little friend, the %CHAR built-in-function that converts a field to a character format. EVAL char_field = %CHAR(num_field); Char_field = %CHAR(num_field); Leading zeros will be automatically converted to spaces. If you want to convert embedded or trailing zeros to spaces then you have to use the %EDITC BIF. or without the EVAL op code

Character to Numeric This is the flip side, a little more complicated because we have to specify how many digits we want total and how many decimal places in the new numeric field, but the %DEC BIF does a splendid job of it. EVAL num_field = %DEC(char_field:length:decimals); num_field = %DEC(char_field:length:decimals); Obviously, if you have non numeric data in the character field there are going to be problems. A + or sign are allowed, but you need to pull out dollar signs, commas or anything like that before the translation. You can use the %XLATE within the %DEC to do this. Oh, and the length and decimals can be either a value or a variable.

Character to Date In order to take a character field and turn it into an L date field, use %DATE which is so much easier than what you had to do with the Move statement before. It can convert either a six or eight character field into a real date type field. EVAL date_field = %DATE(char_field:format-code); date_field = %DATE(char_field:format-code); where the format-code is the format the that character field date is in (*USA, etc.). The date_field will be in ISO format by default. You can do the same thing to time by using the %TIME BIF.

Page 2

/Free Tutorial 4 Date to Character or Decimal

Shirey Consulting Services

To take a date or time type field and convert it into either character or decimal, use the %CHAR and %DEC (depending on whether you want the final result in a character or decimal field). In addition, you have to specify the format you want that final field to be in (*ISO, etc.). EVAL char_field = %CHAR(date_field:format-code); EVAL dec_field = %DEC(date_field:format-code); I will let you imaging what the suppressed EVAL format looks like.

Math Statements Fixed format RPG uses ADD, SUB, MULT, and DIV to perform very stilted arithmetic calculations, often taking several statements to do even simple operations. /Free does not support these statements, but instead uses the EVAL and traditional arithmetic operators (like +, -, *, and /) to simply and easily carry out calculations. Hence, Eval Total_Cost = (Base_Cost * Qty_Ordered) Discount_Amt; Or if you like it in the format that suppresses the EVAL, Total_Cost = (Base_Cost * Qty_Ordered) Discount_Amt;

When you are doing division operations, since the DIV option is no longer supported, neither is the Mvr option (move remainder). To get your remainder you need to use the %REM BIF.

If you are just incrementing a field, like A = A + B, you can write that in short hand in /Free as A += B; There are similar operators for -=, *=, and /=. I dont really like them. Short hand is one thing, obscuring the meaning is another. I can just see myself looking at that some day in a hurry and seeing the += as just an =. It doesnt take that long to put in the whole equation. But, its up to you. No business of mine.

Page 3

/Free Tutorial 4

Shirey Consulting Services

If you want to raise something to a power, simply use ** as the operator. If you want the square root of something use the %Sqrt BIF. And, of course, parenthesis can be used (and should be) to clarify and organize what is happening in the equation. And dont forget the semicolon!

Call Options OK, if you are not now familiar with how to prototype a call in RPG you might want to brace yourself. /Free does not support the traditional CALL (or the similar but less traditional CALLB). Steady now, big fella, take a deep breath. Dont try to get up too quickly. Just let it sink in. Instead, /Free supports only the prototype call function, CALLP. The syntax for this is pretty simple (dont forget the semicolon), CALLP prog-id (parm1:parm2:. . .); In addition to that, you also will need to add some fields in the D-specs that represent what these parameters are. Specifically, In the calling program (that is, the one that is issuing the CALLP), D prog-id D parm1 D parm2 PR picture picture Extpgm(prog-id2)

Now in setting this up, the prog-id must be identical to the prog-id in the CALLP statement. PR is set in the Declaration Type field of the D-spec (where a DS would go for a data structure, column 27, 28). The value kept in the Extpgm keyword is the actual program ID that you are calling. Please note the difference between the prog-id and prog-id2. Normally, I would set progid2 equal to prog-id (that is, I would use the actual program name in the CALLP statement), but you dont have to. (This gives you the ability to call your program PGM1 but put something more descriptive, like DLT_RCDS in the prog-id field in the CALLP and the name of the PR d-spec.)

Page 4

/Free Tutorial 4

Shirey Consulting Services

Then list the parms and their pictures just like they were part of a data structure. The parm names in the D-spec must match the ones in the CALLP statement (this is where they are defined). See, thats not bad. You just set up your CALLP and then instead of coding up a PLIST and PARMS thing in the C-specs, you just set up a PR (Prototype) D-spec giving that same information. Piece of Cake. I thought it was strange when I first started using it but now it is just very normal. What about the program you are calling? How does it accept the CALLP? Patience my friend. Patience. The above option (using CALLP for a CALL) is an example of a dynamic call, a call between two modules that are not really linked in any way. There is another type of call supported in fixed format, the CALLB or Bound Call. This is a call between two modules that have been bound together in the compile process (generally for efficiency purposes but maybe just because they really like each other). I am guessing that most of you are not using the CALLB and so I will leave that discussion to Jimmy Martins book. But I will say that you set it up exactly like a CALLP except that in the PR D-spec, instead of using the keyword Extpgm, you use Extproc with no parm value on it. Otherwise it is the same.

Handling Incoming Parms When we created our stub program, we took out any *ENTRY code that we had on the front end making it a program without parameters. Now we will put some parms back in because most programs (even those in /Free) have input parms. Actually, there are two ways to do this. The first is to just stick some C-specs at the front of your procedure division and just before the /Free code line do *ENTRY and PARM in fixed format just like you have always done. I know that will be tempting and its not like youre evil or anything if you do it, but lets face it, thats the wimpy way out. What I believe by Dave Shirey: If youre going to do /Free then do stinkin /Free, dont mix fixed format foolishness in there. Good lord, man, pull yourself together and have some respect for yourself. The second way is to use the same format as you would if you were doing a prototype in fixed format. That is, you will set up two D-spec things and let them handle the input parms. The good thing about this is that it is consistent with what you are doing on the calling side. And its the modern thing to do. Not that bad really. First, you will need a PR D-spec group, exactly like the one that you used in your calling program. This is the Prototype D-spec. The PR name could be anything (it isnt referenced anywhere in the program logic) and could even be ENTRY_PARMS or

Page 5

/Free Tutorial 4

Shirey Consulting Services

something like that. The value in the EXTPGM keyword, however, must be the name of this program (not the one that called this program, but this program). Then, immediately below that (I guess it doesnt matter where you put it, its just like Rock and Roll, it makes good, good sense to put them together) you need another Dspec group, an exact copy of the PR one, but this one with a PI Declaration Type. This is the Prototype Interface D-spec group. The PI group does not need the EXTPGM keyword. And thats it. No biggie really. But using this format you do not need anything in the main body of the logic, everything is handled in the D-specs. The example for this is below. This is what you have to do to bring parms into a program. And remember, you can easily make prog-id and pgm-id2 the same value. D prog-id D parm1 D parm2 D D prog-id D parm1 D parm2 PR picture picture PI picture picture EXTPGM(pgm-id2)

One other thing I should mention is that when you define a field in a PI, that defines it for the rest of the program and you can play with it without having to do a separate S D-spec. The same is not true if you just have a PR (as you would when you are calling a program). In this case, you cant refer to this field in your program (except for in the CALLP). You would have to define it separately in another D-spec before you could play with it.

More Thoughts on CALLP I would be willing to bet that the changes that ILE and /Free have introduced on the CALL operation are probably some of the most upsetting and frightening that we have seen and a main reason why ILE and /Free have not been more universally adopted. That and natural laziness, of course. But CALLP is the way of the future. Not only does it give you a lot more control over your parms and how they are passed, but it is the only way to call the newer APIs or other modules using C or Java. I go into a bit more below but for a somewhat more indepth treatment of prototyping, please see my prototyping tutorial on the Systemi page of my web site (www.shireyllc.com).

Page 6

/Free Tutorial 4

Shirey Consulting Services

Now, I want to cover one more thing about the prototypes. Remember the D-spec fields under the PR and PI D-specs? Well, you can put keywords on those fields when doing a prototyped call (a CALLP) that control how those fields are handled when they are passed. Note if no keywords are specified, then the default pass option is pass by reference. Value Using this keyword on the field level D-specs means that the actual value of the field (not its address) will be passed to the called program. You can change the value of that parm in the called program but you CANNOT pass it back to the calling program and change the value in the calling program. Const This keyword is more like the pass by reference that is the default on the old CALL op code, it lets you pass changes in the parm back to the calling program. In addition, it helps the system deal with differences in parm length or data type between the calling and called program, thereby eliminating the need for programmers to define work fields and manipulate things through them. Its totally perkin. Options( ) This keyword can have a number of values with it. *NOPASS Indicates that the parm is option and does not have to be passed. All parms after his one must also be set up as *NOPASS. *OMIT This will omit a parm (in a list of parms) from being passed. It is an optional thing also and is the kind of thing you would use if you had a standard parm list that worked in a dozen different programs but some programs passed some parms and some others. In the called program you can see if the parm was passed by using the %Addr (address) BIF and see if it is *NULL. If you are using this, you really should consider seeking treatment for Complex Methods Syndrome. Just code up separate parm lists for separate programs and call it good. Too much danger of linkage problems with this method. *VARSIZE Permits a character size to be shorter than the parm length (no keyword is needed to handle a size larger than the parm length, it just truncates). This option can only be used if you are passing by reference (that is, not VALUES).

Page 7

/Free Tutorial 4 *STRING / *TRIM / *RIGHTADJ I think you can figure these out.

Shirey Consulting Services

Page 8

/Free Tutorial 4 The End

Shirey Consulting Services

So now we are here, at the end. You should now be able to take almost any program and convert it to /Free and to write one from scratch. And now is the perfect time to start using it. Dont let people dissuade you, dont say its something youll do one of these days, just do it. Get into the 21st century. Stop using a form of RPG that helps make people feel RPG and the i are dinosaurs. Do you know everything there is to know about /Free? No, of course not. Do you think I would teach you everything that I know (I actually have but lets pretend that I know more, lots more)? Get the Jimmys book. Its only 189 pages and there are lots of examples, especially of weird things that I havent covered (especially in terms of data conversion issues). Its worth it. So good luck and happy coding. Your taking your first step into the future! Honestly, sometimes even I dont know where I get this stuff from.

Questions or Comments?

For more information on how /Free can help you, contact Shirey Consulting Services at 616-452-6398 or support@shireyllc.com.

Page 9

You might also like