× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.




I get the following compile error when try to assign a pointer to a
const variable.  Did I do something wrong?

RNF7586 20     52 001800  The address of a constant value is used
incorrectly.

If you read my previous message carefully, you'll see that I already told you that would happen :) The compiler won't let you assign the address of a CONST field to a pointer because the compiler doesn't want you to be able to modify the CONST field. If you had a pointer to the field, you'd be able to modify it... and it's trying to prevent that.

Like I said, it only does this checking at compile time. You get an error in your compile listing (indeed, the very error you show above) and your program isn't created.

My message was discussing *tricking* the compiler. The goal is to trick the compiler into thinking you're doing everything legitimately so that it lets you by...

And again, like I said before -- I don't consider this a good practice. I don't recommend that you do it. You're deliberately bypassing the compiler's safeguards, and I never recommend that.

However, I still do it because there are times when I must. I'm always very careful not to modify the field -- but I absoltely must get a pointer to it, even if I don't use the pointer to change the data. This same technique can be used to solve the optional parameter dilemna -- but all I'm saying is that it CAN be used, not that I recommend it.

Clear as mud?  Thought so.  So I'll illustrate what I mean with code.

The following is a complete program. You can copy/paste it into WDSC (or Notepad, and then upload it to your system -- or, if you're like me, you can copy/paste it into vi. I'm sure that's the route Jon Paris would take, since I know he loves vi -- but anyway...)

Take this program and try it out. Step through it in debug. See how it works...

     H DFTACTGRP(*NO)

     D HandleOptParm   PR              *   extproc('REAL_HANDLEOPTPARM')
     D   Num                         10I 0 value
     D   Total                       10I 0 value
     D   parm                     65535A   const options(*varsize:*omit)
     D   local                    65535A   options(*varsize)
     D real_HandleOptParm...
     D                 PR              *
     D   Num                         10I 0 value
     D   Total                       10I 0 value
     D   parm                          *   value
     D   local                         *   value
     D my_sub_proc     PR
     D    field1                     10A   const
     D    optField2                  10A   const options(*nopass:*omit)
     D    optField3                  10A   const options(*nopass:*omit)

     D var1            s             10A   inz('BlahBlah')
     D var2            s             10A   inz('HalbHalb')


      /free

            dsply ('Using default values, you get:');
            my_sub_proc('nopass');

            dsply ('Using *OMIT, you get:');
            my_sub_proc('omit': *omit: *omit);

            dsply ('Passing only one value, you get:');
            my_sub_proc('oneval': 'foo foo');

            dsply ('Omitting only one value, you get:');
            my_sub_proc('omitone': *omit : 'bar bar');

            dsply ('Using literals you get:');
            my_sub_proc('literal': 'one': 'two');

            dsply ('Using variables you get:');
            my_sub_proc('variable': var1: var2);

            *inlr = *on;

      /end-free


      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * demonstration of calling HandleOptParm
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P my_sub_proc     B
     D my_sub_proc     PI
     D    field1                     10A   const
     D    optField2                  10A   const options(*nopass:*omit)
     D    optField3                  10A   const options(*nopass:*omit)

     D dftField2       s                   like(Field2) inz('DefaultVal')
     D dftField3       s                   like(Field3) inz('OtherDft')

     D Field2          s                   like(optField2)
     D                                     based(p_Field2)
     D Field3          s                   like(optField3)
     D                                     based(p_Field3)

      /free

          p_Field2 = HandleOptParm(2:%parms:optField2:dftField2);
          p_Field3 = HandleOptParm(3:%parms:optField3:dftField3);

          // do whatever you need to do.  Always reference
          // "Field2" or "Field3" (never the "opt" or "dft" copies)

          // For the sake of demonstration, I'll use DSPLY to show
          // the values of Field1, Field2 and Field3

          dsply ('field1=' + field1);
          dsply ('field2=' + field2);
          dsply ('field3=' + field3);

      /end-free
     P                 E


      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      *  HandleOptParm():  Handle optional parameters
      *
      * Note: Never call this via the "real_HandleOptParm" interface.
      *       that's only there to trick the compiler.
      *
      *      Num = (input) parameter number
      *    Total = (input) total number of parameters (%parms)
      *     parm = (input) parameter to handle
      *    local = (input) local workspace if parm was not passed
      *
      *  Returns the address of the parmeter, or the local space
      *      if the parameter wasn't passed.
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P real_HandleOptParm...
     P                 B                   export
     D real_HandleOptParm...
     D                 PI              *
     D   Num                         10I 0 value
     D   Total                       10I 0 value
     D   parm                          *   value
     D   local                         *   value
      /free
         if ( Total >= Num and parm<>*NULL );
             return parm;
         else;
             return local;
         endif;
      /end-free
     P                 E

Note: Under ordinary circumstances, the "real_HandleOptParm" procedure would go into a service program. The prototype for "real_HandleOptParm" (which I don't expect anyone to ever use) would go into the same member as the subprocedure itself, and would never be in a /COPY book.

The HandleOptParm prototype would go in the copy book. Also, this demonstration only shows character fields. You can use the same technique with any data type, you just need to make a different "HandleOptParm" prototype (the subprocedure itself doesn't need to be diplicated, only the prototype -- if you understand how the subproc works, you should see why.)

Anyway, you put that in a service program and copy book so that you don't have to repeat them in every program/procedure. All you need to do in the actual program/procedure is this part:

          p_Field2 = HandleOptParm(2:%parms:optField2:dftField2);
          p_Field3 = HandleOptParm(3:%parms:optField3:dftField3);

Plus, of course, the field defifinions for the "dftField" fields, and the "Field1, Field2" etc definitions... But I think coding those two lines of code is cleaner than lots of the following in every single procedure:

        if %parms>=2 and %addr(optField2);
          // do this
        else;
          // do that;
        endif;
        if %parms>=3 and %addr(optField3);
          // do this
        else;
          // do that;
        endif;

Anway, let me know what you think....

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

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.