Difference between revisions of "REXX"

From MidrangeWiki
Jump to: navigation, search
(External links)
(+ example Rexx to CL and back)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{AN}} is an interpreted language invented by IBM.  It is simple to learn and is available on many platforms, including i5/OS.  It was used as the macro language in the Code/400 GUI editor (precursor to [[WDSC]] and [[RDi]].)
+
{{SeealsoWP|REXX}}
 +
{{AN}} is an acronym for {{bu|RE|structured}} e{{bu|X|tended}} e{{bu|X|ecutor}}, an interpreted scripting/programming language developed by IBM.  It is simple to learn and is available on many platforms, including IBM i.  It was used as the macro language in the Code/400 GUI editor (precursor to [[WDSC]] and [[RDi]].)
  
On System i, REXX source is stored in a source member, the default is {{code|QREXSRC}}.  It is executed by {{code|STRREXPRC}}.  It might be helpful to define a [[PDM]] or [[WDSC]] option to invoke the REXX interpreter: {{code|?STRREXPRC SRCMBR(&N) SRCFILE(&L/&F)}}; however, [[PDM]] recognizes source members that have source type REXX and will execute STRREXPRC against them when option 16 ("Run procedure") is entered.  The question mark in front of the command signifies prompting, which will allow you to fill in any parameters you might want. If [[PDM]] option 16 is used, the <F4> key will perform prompting.
+
==IBM i implementation==
 +
On IBM i, REXX source is stored in a source member, the default is {{code|QREXSRC}}.  It is executed by {{code|STRREXPRC}}.  It might be helpful to define a [[PDM]] or [[WDSC]] option to invoke the REXX interpreter: {{code|?STRREXPRC SRCMBR(&N) SRCFILE(&L/&F)}}; however, [[PDM]] recognizes source members that have source type REXX and will execute STRREXPRC against them when option 16 ("Run procedure") is entered.  The question mark in front of the command signifies prompting, which will allow you to fill in any parameters you might want. If [[PDM]] option 16 is used, the {{keypress|F4}} key will perform prompting.
  
According to most manuals, all REXX programs should begin with a comment; but this seems to be no longer required, at least under i5/OS. (It is not required on most V5R3 and later systems. It is not clear when this was first allowed.)  White space is for programmer convenience and can be added or omitted as desired.
+
According to most manuals, all REXX programs should begin with a comment; but this seems to be no longer required, at least under IBM i. (It is not required on most V5R3 and later systems. It is not clear when this was first allowed.)  White space is for programmer convenience and can be added or omitted as desired.
  
 
===Hello world===
 
===Hello world===
Line 9: Line 11:
 
  say 'Hello, world!'  
 
  say 'Hello, world!'  
 
  return               
 
  return               
 +
 +
=== Rexx and CL ===
 +
Rexx can interact with CL via use of an API called QREXQ, It's not the same as CALL/PARM, so it needs coding on the
 +
CL side to add entries to the Rexx External Data Queue, and pull them off. Following is an example that demonstrates CL adding a library name to the queue, calling a Rexx program that does ADDLIBLE, then uses the Db2 service to retrieve the library list. Rexx puts the library list entries back onto the queue, then returns to the CL which pulls them off into CL variables.
 +
 +
<pre>
 +
REXXCLP *CLP
 +
 +
/* Pass 'parameters' back and forth to Rexx */
 +
pgm
 +
 +
dcl &len *int (4) value(10)
 +
dcl &rc *int (2)
 +
dcl &toCLP *char (10)
 +
 +
dcl &buffer *char (100)
 +
dcl &lib *char (10)
 +
dcl &type *char (15)
 +
dcl &text *char (50)
 +
 +
dcl &work_msg *char (50)
 +
 +
/* this is a demonstrator of passing info from CL to Rexx and back */
 +
/* This CLP will pass a library name to Rexx */
 +
/* Rexx will ADDLIBLE it and then pass back the current library list */
 +
 +
/* Yes, this can all be done in CL but the idea is to show how */
 +
/* the interface between CL and Rexx works */
 +
/* Additionally, it'll show how Rexx can use SQL directly */
 +
 +
/* Pass to Rexx */
 +
/* Can't use call/parm; use the API QREXQ instead */
 +
/* 'A' pushes an entry onto the Rexx external data queue */
 +
/* Rexx will pull parse from this into Rexx variables */
 +
/* https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_61 */
 +
/* /books_web/sc415729.pdf?view=kc */
 +
 +
chgvar &toCLP 'QSYS38'
 +
chgvar &len %size(&toCLP)
 +
call QREXQ ('A' &toCLP &len 0 &rc)
 +
 +
/* execute the Rexx program */
 +
/* it will read the 'parameter' from the External Data Queue */
 +
strrexprc rexxclp srcfile(buck/qrexsrc)
 +
 +
/* the diags are in the REXX queue */
 +
/* pull them out one by one */
 +
chgvar &len %size(&buffer)
 +
 +
loop_top:
 +
  /* pull a 'parameter' struc from the external data queue */
 +
  /* one entry per library in *LIBL */
 +
  call QREXQ ('P' &buffer &len 0 &rc)
 +
  if (&rc *ne 0) (goto endpgm)
 +
 +
    /* convert the buffer into individual variables */
 +
    /* this obviously needs to be matched up with the Rexx program */
 +
    chgvar &lib %sst(&buffer 1 10)
 +
    chgvar &type %sst(&buffer 12 15)
 +
    chgvar &text %sst(&buffer 28 50)
 +
 +
    /* in a real program we'd do something with this info */
 +
    /* here, let's display it */
 +
    chgvar &work_msg (&lib *cat ' ' *cat +
 +
                      &type *cat ' ' *cat +
 +
                      %sst(&text 1 22))
 +
    sndpgmmsg &work_msg
 +
  goto loop_top
 +
 +
endpgm:
 +
  return
 +
 +
endpgm
 +
 +
</pre>
 +
 +
<pre>
 +
REXXCLP Rexx program
 +
 +
/* rexxclp */
 +
 +
/* NOTE: STRREXPRC will not run this if it's open in RDi for editing */
 +
 +
/* example of passing 'parameters' from CL to Rexx and back */
 +
/* https://public.dhe.ibm.com/systems/power/docs/systemi/v6r1 */
 +
/* /en_US/sc415729.pdf?view=kc&origURL=ssw_ibm_i_61/books_web/sc415729.pdf */
 +
 +
  /* get the 'parameter' that CLP previously put on the External Data Queue */
 +
  /* via the QREXQ API */
 +
  parse pull library_name
 +
 +
  /* do the ADDLIBLE */
 +
  signal on error name skip_lible /* if error in addlible, skip it */
 +
  cmd = "addlible " || strip(library_name);
 +
  address command cmd;
 +
 +
skip_lible:
 +
  signal off error
 +
 +
  /* we're going to be issuing Db2 instructions */
 +
  address execsql
 +
 +
  /* use the Db2 service to retrieve the LIBL */
 +
  /* the CAST gets rid of the UTF-8 CCSID and makes a fixed-length variable */
 +
  sql_stmt = ,
 +
    "select ",
 +
      "cast(system_schema_name as char(10)), ",
 +
      "cast(type as char(15)), ",
 +
      "cast(coalesce(text_description, ' ') as char(50)) ",
 +
    "from qsys2.library_list_info"
 +
 +
  execsql "prepare STMT from :sql_stmt"
 +
  execsql "declare LIBL_CSR cursor for STMT"
 +
  execsql "open LIBL_CSR"
 +
 +
  do while 1 = 1
 +
    execsql "fetch LIBL_CSR into ",
 +
            ":lib, :type, :text"
 +
 +
    /* for a production program better status checking is needed */
 +
    /* this is the barest minimum to detect end of cursor */
 +
    if rc <> 0 then do
 +
      if sqlstate = "02000" then
 +
        leave
 +
      else do
 +
        say "SQLSTATE = " sqlstate
 +
        leave
 +
      end /* sqlstate  */
 +
    end /* rc */
 +
 +
    /* construct an outgoing 'structure' to pass back to CLP */
 +
    buffer = lib"*"type"*"text"*"
 +
 +
    /* put the value on the external queue */
 +
    /* This will allow the calling CLP to retrieve it */
 +
    /* note that this is one 'parameter' per entry in *LIBL */
 +
    queue (buffer)
 +
 +
  end /* do forever*/
 +
 +
 +
return
 +
 +
</pre>
  
 
==Other System i REXX programs==
 
==Other System i REXX programs==
Line 16: Line 162:
 
* [http://www.google.com/base/a/1079085/D2777053214771168713?hl=en_US Factorial recursion]
 
* [http://www.google.com/base/a/1079085/D2777053214771168713?hl=en_US Factorial recursion]
 
* [http://www.google.com/base/a/1079085/D8025156647175713805?hl=en_US Copy table to delimited file with headers]
 
* [http://www.google.com/base/a/1079085/D8025156647175713805?hl=en_US Copy table to delimited file with headers]
 +
 
==External links==
 
==External links==
* [http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/rzahg/rzahgrexx.htm System i REXX V5R4M0 documentation]
+
* [https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzahg/rzahgrexx.htm IBM i 7.4 Rexx documentation]
* [http://en.wikipedia.org/wiki/REXX Wikipedia entry for REXX]
+
* [http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/rzahg/rzahgrexx.htm IBM i REXX V5R4M0 documentation]
 
* [http://www-306.ibm.com/software/awdtools/rexx/library/index.html IBM general REXX information]
 
* [http://www-306.ibm.com/software/awdtools/rexx/library/index.html IBM general REXX information]
 
* [http://www.rexxla.org/ REXX Language Association]
 
* [http://www.rexxla.org/ REXX Language Association]
Line 24: Line 171:
 
* [http://www.rexswain.com/rexx.html Rex Swain's VM REXX page]
 
* [http://www.rexswain.com/rexx.html Rex Swain's VM REXX page]
 
* [http://www.rexxinfo.org/ http://www.rexxinfo.org/]
 
* [http://www.rexxinfo.org/ http://www.rexxinfo.org/]
 +
* [http://www.mcpressonline.com/tips-techniques/sql/techtip-calling-sql-from-rexx.html "TechTip: Calling SQL from REXX"] Written by Joe Pluta, Thursday, 24 February 2005
  
 
==Categories==
 
==Categories==
 
[[Category:Programming languages]]
 
[[Category:Programming languages]]
{{stub}}
+
[[Category:REXX/400 Examples]]

Latest revision as of 14:30, 20 August 2019

See also on Wikipedia: REXX

REXX is an acronym for REstructured eXtended eXecutor, an interpreted scripting/programming language developed by IBM. It is simple to learn and is available on many platforms, including IBM i. It was used as the macro language in the Code/400 GUI editor (precursor to WDSC and RDi.)

IBM i implementation

On IBM i, REXX source is stored in a source member, the default is QREXSRC. It is executed by STRREXPRC. It might be helpful to define a PDM or WDSC option to invoke the REXX interpreter: ?STRREXPRC SRCMBR(&N) SRCFILE(&L/&F); however, PDM recognizes source members that have source type REXX and will execute STRREXPRC against them when option 16 ("Run procedure") is entered. The question mark in front of the command signifies prompting, which will allow you to fill in any parameters you might want. If PDM option 16 is used, the F4 key will perform prompting.

According to most manuals, all REXX programs should begin with a comment; but this seems to be no longer required, at least under IBM i. (It is not required on most V5R3 and later systems. It is not clear when this was first allowed.) White space is for programmer convenience and can be added or omitted as desired.

Hello world

/* Hello, world */ 
say 'Hello, world!' 
return              

Rexx and CL

Rexx can interact with CL via use of an API called QREXQ, It's not the same as CALL/PARM, so it needs coding on the CL side to add entries to the Rexx External Data Queue, and pull them off. Following is an example that demonstrates CL adding a library name to the queue, calling a Rexx program that does ADDLIBLE, then uses the Db2 service to retrieve the library list. Rexx puts the library list entries back onto the queue, then returns to the CL which pulls them off into CL variables.

REXXCLP *CLP

/* Pass 'parameters' back and forth to Rexx */
pgm

dcl &len *int (4) value(10)
dcl &rc *int (2)
dcl &toCLP *char (10)

dcl &buffer *char (100)
dcl &lib *char (10)
dcl &type *char (15)
dcl &text *char (50)

dcl &work_msg *char (50)

/* this is a demonstrator of passing info from CL to Rexx and back */
/* This CLP will pass a library name to Rexx */
/* Rexx will ADDLIBLE it and then pass back the current library list */

/* Yes, this can all be done in CL but the idea is to show how */
/* the interface between CL and Rexx works */
/* Additionally, it'll show how Rexx can use SQL directly */

/* Pass to Rexx */
/* Can't use call/parm; use the API QREXQ instead */
/* 'A' pushes an entry onto the Rexx external data queue */
/* Rexx will pull parse from this into Rexx variables */
/* https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_61 */
/* /books_web/sc415729.pdf?view=kc */

chgvar &toCLP 'QSYS38'
chgvar &len %size(&toCLP)
call QREXQ ('A' &toCLP &len 0 &rc)

/* execute the Rexx program */
/* it will read the 'parameter' from the External Data Queue */
strrexprc rexxclp srcfile(buck/qrexsrc)

/* the diags are in the REXX queue */
/* pull them out one by one */
chgvar &len %size(&buffer)

loop_top:
   /* pull a 'parameter' struc from the external data queue */
   /* one entry per library in *LIBL */
   call QREXQ ('P' &buffer &len 0 &rc)
   if (&rc *ne 0) (goto endpgm)

     /* convert the buffer into individual variables */
     /* this obviously needs to be matched up with the Rexx program */
     chgvar &lib %sst(&buffer 1 10)
     chgvar &type %sst(&buffer 12 15)
     chgvar &text %sst(&buffer 28 50)

     /* in a real program we'd do something with this info */
     /* here, let's display it */
     chgvar &work_msg (&lib *cat ' ' *cat +
                       &type *cat ' ' *cat +
                       %sst(&text 1 22))
     sndpgmmsg &work_msg
   goto loop_top

endpgm:
   return

endpgm

REXXCLP Rexx program

/* rexxclp */

/* NOTE: STRREXPRC will not run this if it's open in RDi for editing */

/* example of passing 'parameters' from CL to Rexx and back */
/* https://public.dhe.ibm.com/systems/power/docs/systemi/v6r1 */
/* /en_US/sc415729.pdf?view=kc&origURL=ssw_ibm_i_61/books_web/sc415729.pdf */

  /* get the 'parameter' that CLP previously put on the External Data Queue */
  /* via the QREXQ API */
  parse pull library_name

  /* do the ADDLIBLE */
  signal on error name skip_lible /* if error in addlible, skip it */
  cmd = "addlible " || strip(library_name);
  address command cmd;

skip_lible:
  signal off error

  /* we're going to be issuing Db2 instructions */
  address execsql

  /* use the Db2 service to retrieve the LIBL */
  /* the CAST gets rid of the UTF-8 CCSID and makes a fixed-length variable */
  sql_stmt = ,
    "select ",
      "cast(system_schema_name as char(10)), ",
      "cast(type as char(15)), ",
      "cast(coalesce(text_description, ' ') as char(50)) ",
    "from qsys2.library_list_info"

  execsql "prepare STMT from :sql_stmt"
  execsql "declare LIBL_CSR cursor for STMT"
  execsql "open LIBL_CSR"

  do while 1 = 1
    execsql "fetch LIBL_CSR into ",
            ":lib, :type, :text"

    /* for a production program better status checking is needed */
    /* this is the barest minimum to detect end of cursor */
    if rc <> 0 then do
      if sqlstate = "02000" then
        leave
      else do
        say "SQLSTATE = " sqlstate
        leave
      end /* sqlstate  */
    end /* rc */

    /* construct an outgoing 'structure' to pass back to CLP */
    buffer = lib"*"type"*"text"*"

    /* put the value on the external queue */
    /* This will allow the calling CLP to retrieve it */
    /* note that this is one 'parameter' per entry in *LIBL */
    queue (buffer)

  end /* do forever*/


return

Other System i REXX programs

External links

Categories