0
votes

I have in my database a set of records that concentrates information about my .W's, e.g. window name, parent directory, file name, procedure type (for internal treatments purposes), used to build my main menu. With this data I'm developing a new start procedure for the ERP that I maintain and using the opportunity in order to rewrite some really outdated functions and programs and implement new functionalities. Until now, I hadn't any problems but when I started to develop the .P procedure which will check the database register of a program that was called from the menu of this new start procedure - to check if it needs to receive fixed parameters to be run and its data types - I found a problem that I can't figure out a solution.

In this table, I have stored in one of the fields the parameters needed by the program, each with his correspondent data type. The problem is on how to pass different data types to procedures based only on the stored data. I tried to pre-convert data using a CASE clause and an include to check the parameter field for correct parameter sending but the include doesn't work as I've expected.

My database field is stored as this:

Description | DATATYPE | Content

I've declared some variables and converted properly the stored data into their correct datatype vars.

DEF VAR c-param-exec        AS CHAR     NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-param-exec        AS INT      NO-UNDO EXTENT 9 INIT ?.
DEF VAR de-param-exec       AS DEC      NO-UNDO EXTENT 9 INIT ?.
DEF VAR da-param-exec       AS DATE     NO-UNDO EXTENT 9 INIT ?.
DEF VAR l-param-exec        AS LOG      NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-count             AS INT      NO-UNDO.

blk-count:
DO i-count = 0 TO 8:
    IF TRIM(programa.parametro[i-count]) = '' THEN
        LEAVE blk-count.
    i-count = i-count + 1.

    CASE ENTRY(2,programa.parametro[i-count],CHR(1)):
        WHEN 'CHARACTER' THEN
            c-param-exec[i-count]   = ENTRY(3,programa.parametro[i-count],CHR(1)).
        WHEN 'INTEGER' THEN
            i-param-exec[i-count]   = INT(ENTRY(3,programa.parametro[i-count],CHR(1))).
        WHEN 'DECIMAL' THEN
            de-param-exec[i-count]  = DEC(ENTRY(3,programa.parametro[i-count],CHR(1))).
        WHEN 'DATE' THEN
            da-param-exec[i-count]  = DATE(ENTRY(3,programa.parametro[i-count],CHR(1))).
        WHEN 'LOGICAL' THEN
            l-param-exec[i-count]   = (ENTRY(3,programa.parametro[i-count],CHR(1)) = 'yes').
        OTHERWISE
            c-param-exec[i-count]   = ENTRY(3,programa.parametro[i-count],CHR(1)).
    END CASE.

END.

Then I tried to run the program using an include to pass parameters (in this example, the program have 3 INPUT parameters).

RUN VALUE(c-prog-exec) ({util\abrePrograma.i 1}, 
                        {util\abrePrograma.i 2}, 
                        {util\abrePrograma.i 3}).

Here is my abrePrograma.i

/* abrePrograma.i */

(IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'CHARACTER' THEN c-param-exec[{1}]  ELSE
 IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'INTEGER' THEN i-param-exec[{1}] ELSE
 IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DECIMAL' THEN de-param-exec[{1}] ELSE
 IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DATE' THEN da-param-exec[{1}] ELSE
 IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'LOGICAL' THEN l-param-exec[{1}]  ELSE
 c-param-exec[{1}])

If I suppress the 2nd, 3rd, 4th and 5th IF's from the include or use only one data type in all IF's (e.g. only CHAR, only DATE, etc.) the program works properly and executes like a charm but I need to call some old programs, which expects different datatypes in its INPUT parameters and using the programs as described OpenEdge doesn't compile the caller, triggering the error number 223.

---------------------------
Erro (Press HELP to view stack trace)
---------------------------
** Tipos de dados imcompativeis em expressao ou atribuicao. (223)
**  Nao entendi a linha 86. (196)
---------------------------
OK   Ajuda   
---------------------------

Can anyone help me with this ? Thanks in advance.

3

3 Answers

4
votes

Looks as if you're trying to use variable parameter definitions. Have a look at the "create call" statement in the ABL reference.

http://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/call-object-handle.html#wwconnect_header

Sample from the documentation

DEFINE VARIABLE hCall AS HANDLE NO-UNDO.

CREATE CALL hCall.

/* Invoke hello.p non-persistently */
hCall:CALL-NAME      = "hello.p".

/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.

/* Clean up */
DELETE OBJECT hCall.
1
votes

The best way to get to the bottom of those kind of preprocessor related issues is to do a compile with preprocess listing followed by a syntax check on the preprocessed file. Once you know where the error is in the resulting preprocessed file you have to find out which include / define caused the code that won't compile .

  1. In procedure editor compile source.w preprocess source.pp.
  2. Open source.pp in the procedure editor and do syntax check
  3. look at original source to find include or preprocessor construct that resulted in the code that does not compile.
0
votes

Okay, I am getting a little bit lost (often happens to me with lots of preprocessors) but am I missing that on the way in and out of the database fields you are storing values as characters, right? So when storing a parameter in the database you have to convert it to Char and on the way out of the database you have convert it back to its correct data-type. To not do it one way or the other would cause a type mismatch.

Also, just thinking out loud (without thinking it all the way through) wonder if using OOABL (Object Oriented ABL) depending on if you Release has it available wouldn't make it easier by defining signatures for the different datatypes and then depending on which type of input or output parameter you call it with, it will use the correct signature and correct conversion method.

Something like:

METHOD PUBLIC VOID storeParam(input cParam as char ): dbfield = cParam. RETURN.

END METHOD.
METHOD PUBLIC VOID storeParam(input iParam as int  ):
    dbfield = string(iParam).
    RETURN.

END METHOD.
METHOD PUBLIC VOID storeParam(input dParam as date  ):
    dbfield = string(dParam).
    RETURN.

END METHOD.

just a thought.