Wednesday, February 19, 2014

Defining variables in RPG all free

 rpg free tr7 dcl-s dcl-c dcl-ds end-ds dcl-subf

Prior to the new all free RPG variables (fields) would have been coded in the Definition specification, D-spec. With the new version of RPG the fixed format D-spec has gone. It has been replaced by new free form definition statements. At the time I am writing this post I have not found any other articles giving examples of how to code these new definition statements, therefore, I am going to give examples of how I have used them as I am starting to become this new version of the language.

The definitions I am going to discuss here are:

  • Define a standalone variable - dcl-s
  • Define a data structure - dcl-ds and end-ds
  • Define a data structure subfield - dcl-subf
  • Define a constant - dcl-c

I am going to give examples of the way I would have coded various type of variables using the fixed formal D-spec and how I am coding the same thing using the new free format definition statements. I am not going to go into too much detail as I am assuming that you, the reader, already has a basic knowledge of how to define variables.

Define standalone variable

The free form definition statement to define a standalone variable is dcl-s. This is followed by the variable’s name, its type and size, and then any relevant keywords which are the same as keywords used with the fixed format D-spec.

This is how I could define an alphanumeric field, and then define another using the like keyword. In the first free format statement, line 2, you can see that there is a char keyword, this defines the field as alphanumeric, and the number following is its size:

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Alpha1          S             10A
02   dcl-s Alpha1 char(10) ;

03  D Alpha2          S                   like(Alpha1)
    D                                       inz(*all'*')
04   dcl-s Alpha2 like(Alpha1) inz(*all'*') ;

I would say that packed numeric fields are the most common form of numeric fields in the environments I work in. I am sure it will come as no surprise to you that the keyword packed is used to define a packed field. Notice that in the first free statement, line 2, the number of decimal places is not given, while it is in the other free statement, line 4. If the number of decimal places is not given zero is assumed. Also notice that the length of the field is separated from the number of decimal places by a colon, :.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Packed1         S              7P 0
02     dcl-s Packed1 packed(7) ;

03  D Packed2         S              5  2
04     dcl-s Packed2 packed(5:2) ;

Signed numeric variables are now defined using the zoned keyword. Otherwise their definition is the same as packed numeric fields.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Signed1         S              7S 2
02     dcl-s Signed1 zoned(7:2) ;

To define integer, unsigned integer, and float numeric variables the int, uns, and float keywords are used.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Int1            S              3I 0
02     dcl-s Int1 int(3) ;

03  D Uns1            S              3U 0
04     dcl-s Uns1 uns(3) ;

05  D Float1          S              8F
06     dcl-s Float1 float(8) ;

As you would expect date variables defined using the date keyword, see line 2. I can define the date format, if needed, following the date keyword. A time variable is defined with the time keyword, line 4, if I do not want to use the default time format I can give it following the time keyword. Timestamp variables are defined using the timestamp keyword.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Date1           S               D   datfmt(*iso)
02     dcl-s Date1 date(*iso) ;

03  D Time1           S               T
04     dcl-s Time1 time ;

05  D TimeStamp1      S               Z
06     dcl-s TimeStamp1 timestamp ;

Indicator variables are defined using the ind keyword.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Ind1            S               N

02     dcl-s Ind1 ind ;

Very occasionally I have to use a binary variable, this would be defined using the bindec keyword.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Bin1            S              5B 0

02     dcl-s Bin1 bindec(5) ;

And pointers are defined using the pointer keyword.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Pointer1        S               *

02     dcl-s Pointer1 pointer ;

Arrays are defined pretty much the same way you did with the fixed format. You define your variable and then follow it with the dim keyword.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Array1          S              3    dim(100)

02     dcl-s Array1 char(3) dim(100) ;

Tables are more troublesome. When using the free format you must start the name of the table with "tab".

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Table1          S              7    dim(3) ctdata

02     dcl-s TabTable1 char(7) dim(3) ctdata ; 

One last example show how to define a variable to receive the data from a data area.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D TestDa1         S             10    dtaara('TESTDA')

02     dcl-s TestDa1 char(10) dtaara('TESTDA') ;

 

Define data structure and data structure subfield

I was not surprised to learn that the free form definition statement to define a standalone variable is dcl-ds. One new feature is that all data structures either require a name or *N to denote that the data structure is not named. The qualified keyword can be used, and I do use it. A semicolon is required at the end of the dcl-ds.

The declare subfield statement, dcl-subf is optional, and I do not use it.

After all of the data structure subfields have been defined a end-ds statement is needed.

Below is a data structure below is not named and I have define the equivalent twice, one with the dcl-subf and other without.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D                 DS
02  D   Telephone1                  12A
03  D   AreaCode1                    3A   overlay(Telephone1:2)

04     dcl-ds *N ;
05        dcl-subf Telephone1 char(12) ;
06        dcl-subf AreaCode1 char(3) overlay(Telephone1:2) ;
07     end-ds ;

08     dcl-ds *N ;
09       Telephone2 char(12) ;
10       AreaCode2 char(3) overlay(Telephone2:2) ;
11     end-ds ;

If I defined the data structure with subfield starting and ending positions, lines 1 – 3, I would need to use the pos keyword to say where the subfield starts, lines 5 and 6.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D                 DS             
02  D  Telephone1             1    12
03  D  AreaCode1              2     4     
                                 
04     dcl-ds *N ;                   
05        Telephone2 char(12) pos(1) ;
06       AreaCode2 char(3) pos(2) ;  
07     end-ds ;

Those of you who are regular reader of this blog know that I use an externally described data structure to define the Program Status data structure (PSDS), see Externally described Data Structures. If you notice that the dcl-ds does not end with a semicolon as there are no subfields defined.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D PgmDs         ESDS                  extname(RPG4DS) qualified

02     dcl-ds PgmDs
03        extname('RPG4DS') psds qualified
04     end-ds ;

For those who code their PDS the other way would code it like this.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D PgmDs          SDS                  qualified
02  D PgmName           *proc
03  D Status            *status

04     dcl-ds PgmDs psds qualified ;
05        PgmName *proc ;
06        Status *status ;
07     end-ds ;

Regular readers will also know that I use an Indicator data structure to communicate (define the indicators) for display and printer files, see No More Number Indicators.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D IndDs           DS                  qualified
02  D   Exit                  3      3N
03  D   Errors               50     59A
04  D   ErrControlGroupNotFound...
05  D                        50     50N
06  D   ErrStrRangeGreaterThanEndRange...
07  D                        51     51N

08     dcl-ds IndDs qualified ;
09        Exit ind pos(3) ;
10        Errors char(10) pos(50) ;
11        ErrControlGroupNotFound ind pos(50) ;
12        ErrStrRangeGreaterThanEndRange ind pos(51) ;
13      end-ds ;

I have to admit I do not use data structures that much to split or put data together. I use the %subst to break data apart into "subfields", and concatenate with the +.

 

Define a constant

The free form definition statement dcl-c is used to define a constant. As with the fixed format version I do not have to use the const keyword, I can just enter the values.

    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords
01  D Constant1       C                   const('ABCDEFG')
02  D Constant2       C                   'ABCDEFG'

03     dcl-c Constant1 const('ABCDEFG') ;
04     dcl-c Constant2 'ABCDEFG' ;

 

If there is anything I have missed please add a Comment below.

 

You should read my other posts introducing all free RPG:

34 comments:

  1. Am I the only one who thinks this syntax is just ugly? And we're still defining integer values as 3, 5 and 10 digit numbers? This is so confusing to non RPG programmers. Can you define more than one variable in a dcl-s/end-s block? That would make it slightly more tolerable. Having to type that dcl-s prefix on every variable and the wordy data type names is just tedious and unnecessary.

    ReplyDelete
    Replies
    1. In regards to question on DCL-S - what I do is DCL-DS - put in my variables and END-DS - has the same effect.

      Delete
  2. Do you know how the program parameters will be coded?
    I've always been annoyed by the EXTPGM('pgmname')

    ReplyDelete
    Replies
    1. You can do it like this.

      dcl-pi *N;
      parm1 char(10);
      parm2 zoned(10 : 0);
      parm3 like(someField);
      end-pi;

      Delete
  3. Do you know how the programe parameters will need to be coded in All-Free.
    I always hated the EXTPGM('pgmname')

    ReplyDelete
    Replies
    1. If you want to stay in free you do have to use the EXTPGM to call another program.

      As you no longer have to /end-free to enter fixed format code it is more pleasing on the eye (in my opinion) to code a CALL in fixed format code in a mostly free program.

      Delete
    2. My apologies, I may not have asked my question properly.
      I was not referring to how to call other programs with parameters.
      I was asking how to define the current program's parameters.
      What we currently define in the d cards with PR and PI for the program interface.

      Delete
    3. The way to code the Procedure interfaces, etc. will be covered in a future post.

      Delete
    4. Thank you.
      I'm looking forward to it.
      My current client is still on V6R1 so I won't get to enjoy this new All-Free RPG soon but I'm already drooling at the thought of if.
      Thank you for your posts.

      Delete
  4. Sometimes I'm lazy and create a data structure - DCL-DS and put all of the "stand alone fields" underneath that - this way I don't have to specify DCL-S in front of them all...

    ReplyDelete
  5. Can this be type anyplace in the program??

    ReplyDelete
    Replies
    1. The dcl-s has to be placed at the top of the program/procedure in the same place you would have put the D-specifications.

      The dcl-s cannot be placed in the "C-specifications".

      Delete
  6. Hi;

    I'm needing a bit of help with a Dcl-DS as I can't find anything in my books or via Google. I'm sure the fault is mine and relates to search criteria..

    The problem: I'm trying to specify a simple 6,2 packed field that is comprised of a 4,0 length feet and 2,0 length inches. I thought I had it, but I get a data decimal error when trying to use the built field.

    The definition:
    Dcl-Ds *N;
    BrdMat Packed(6:2);
    BMLtF Packed(4:0) Pos(1);
    BMLtI Packed(2:0) Pos(5);
    End-Ds;

    I load 20 & 0 to the feet & inches, and each field shows fine. But when I look at the field BrdMat, I see this: 0020. X4 (the X is the reversed imaged block indicating bad data).

    I'd rather do this right, so can anybody help???

    Thanks,

    Michael

    ReplyDelete
    Replies
    1. I get the same result when using a fixed form DS.

      I am wondering why you are making this so complicated. In this situation I would do something like:

      dcl-s Length packed(6:2) ;

      Length = %dec((%char(Feet) + '.' + %editc(Inches:'X')):6:2) ;

      Delete
  7. Can one define a long "inz" value in free (without using the c-specs)? example:
    D Ds
    D Dta 84 Inz('abcdefghijklmnopqrstuvwxyz-
    D ABCDEFGHIJKLMNOPQRSTUVWXYZ-
    D 0123456789/-?:(-).,'' +§*$%')

    ReplyDelete
    Replies
    1. Did you solve this? We have the same issue here.

      Delete
    2. How about this....

      dcl-s Var1 char(200) inz('first,second,+
                                          third') ;

      Delete
  8. Can't wait for the day when we can define variables, within the scope they have to be used - just like in C#. So stupid that a counter for a 3 line do loop has to be defined in the beginning of the program, etc.

    ReplyDelete
    Replies
    1. You mean like RPGIII, where you can define a variable anywhere within the Calc-specs.

      Personally I like having all the definitions in one place. It make is easier, in my opinion, to find how a variable is defined rather than having to search all of the source.

      Delete
    2. I don't know what Brian was thinking, but when I saw his comment, I thought about variables that only exist within the scope of a loop. In c# you can define an index variable in the for statement and it only exists inside that for loop.

      Delete
  9. hi,
    can you give me any example of DS parameters in free from?
    example:
    I have *module A with a DS
    dcl-ds tryDs Ext End-ds;
    ...

    and I would Like a function i Service PGM that get tryDs

    thank you

    ReplyDelete
  10. Hi Simon: I am trying to load a numeric field in a DS, and I am getting an error, I am doing this: dcl-ds endDat2 ;
    endMM Zoned(2:0) ;
    endDD Zoned(2:0) ;
    endYY Zoned(4:0) ;
    end-ds ;
    endDat2 is a Numeric field. RPG is converting endDat2 to alpha and giving me an error. Thanks

    ReplyDelete
    Replies
    1. Yes, if you use the name of the data structure it will regard it as character. What I do is to define a subfield, and then have sub-subfields like this:

      I know the formatting in these comments are going to mess this up, so here goes:

      dcl-ds *n ;
        endDat2 zoned(8) pos(1) ;
          endMM zoned(2) pos(1) ;
          endDD zoned(2) pos(3) ;
          endYY zoned(4) pos(5) ;
      end-ds ;

      Delete
  11. how do you declare a variable of graphic type?

    ReplyDelete
    Replies
    1. dcl-s Variable1 graph(20) ;

      - Or

      dcl-s Variable2 vargraph(50) ;

      Delete
  12. I am getting the SYNTAX error while declaring the DCL-S. How Can i Avoid and which is the place suitable to declare.

    ReplyDelete
  13. Hi Simon

    I am trying to load the values of LDA to a file. I have an external file named LDA to which i wish to move the values.Currently I am using the below syntax:

    DCL-DS LDA Dtaara(*LDA);
    A Char(250);
    END-DS;
    DCL-DS L Extname('LDA');
    END-DS;
    In LDA;
    L = A;

    Is there any better way to write it?

    ReplyDelete
  14. Hi, I have a problem. I have two table definitions with the same field and record names. in my program I declare some DS of those files exterena DCL-ds GlvnSaldoDs EXTNAME ('TABLA01') End-ds; DCL-ds GlvnSaldoDs EXTNAME ('TABLA02') End-ds; this is historical. As I rename the fields in the definition of the DS so that no Field error has already been referred

    ReplyDelete
    Replies
    1. 1. You cannot have two data structures with the same name.

      2. Qualify the subfields using the QUALIFIED keyword.

      Delete
  15. We all, have a program with several subroutines. I really need to declare a Variable at the beginning of one subroutine, that could have a different long every time that subroutine is invoked.

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.