REXX FAQ
Источник: https://ossite.ru/index.php?dir=os/os2/&file=rexxfaq
REXX FAQ
Часто задаваемые вопросы по REXX
1. Что такое REXX ? Язык командных файлов OS/2 ?
2. Как получить список доступных дисков под REXX ?
3. Как вызывать REXX-функции из своей программы ?
4. Как добавлять свои функции к REXX-интерпретатору ?
5. Как реализовать Rexx subcommand handler ?
6. Какие библиотеки для программирования на Rexx существуют ?
7. Как проверить существование файла в REXX (if exist) ?
1. Что такое REXX ? Язык командных файлов OS/2 ?
И командных файлов - тоже. В том случае, когда интеpпpетатоp pекса вызывается из cmd.exe (или 4os2.exe) он исполняет командный файл. Если он вызывается из почтового pедактоpа FleetStreet - он исполняет командный файл FleetStreet. Сам по себе REXX не пpивязан к конкpетной части системы и может использоваться любой пpогpаммой как "свой" язык, пpи этом каждая из использующих REXX пpогpамм может добавить к нему свои функции и опеpатоpы, котоpые будут доступны только пpи pаботе pекса в контексте этой пpогpаммы. Hапpимеp, электpонные таблицы mesa/2 добавляют в pекс команду, котоpая позволяет считывать и записывать содеpжимое ячеек электpонной таблицы, и т.п.
2. Как получить список доступных дисков под REXX ?
С помощью следующего кода можно получить список имён дисков типа A: C: D: E:, сетевых - Novell, NFS, LanServer и дp.
if RxFuncQuery("SysLoadFuncs") then
do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
call SysLoadFuncs;
end
DrvMap = SysDriveMap() ;
Say DrvMap
Say "-------------------------------------"
i = 1
Do While Word( DrvMap, i ) \= ""
Say SysDriveInfo( Word( DrvMap, i ) )
i = i + 1 ;
End
Exit( 0 ) ;
3. Как вызывать REXX-функции из своей программы ?
Это - кусок кода из U1 - выложен как пример.
RXSTRING arg[2]; // argument string for REXX
RXSTRING rexxretval; // return value from REXX
APIRET rc; // return code from REXX
SHORT rexxrc = 0; // return code from function
if( prog == NULL || strlen(prog) == 0 )
return Err;
// By setting the strlength of the output RXSTRING to zero,
// we force the interpreter to allocate memory and return
// it to us. We could provide a buffer for the interpreter
// to use instead.
rexxretval.strlength = 0L; // initialize return to empty
if( a1 == NULL ) a1 = "";
MAKERXSTRING(arg[0], a1, strlen(a1)); // input argument
if( a2 == NULL ) a2 = "";
MAKERXSTRING(arg[1], a2, strlen(a2)); // input argument
// Here we call the interpreter. We don't really need
// to use all the casts in this call; they just help
// illustrate the data types used.
rc=RexxStart(
(LONG) 2, // number of arguments
(PRXSTRING) &arg, // array of arguments
(PSZ) prog, // name of REXX file
(PRXSTRING) 0, // No INSTORE used
(PSZ) "U1", // Command env. name
(LONG) RXSUBROUTINE, // Code for how invoked
(PRXSYSEXIT) 0, // No EXITs on this call
(PSHORT) &rexxrc, // Rexx program output
(PRXSTRING) &rexxretval ); // Rexx program output
debug( "CallRexx() = '%s', int=%d, rexx=%d", rexxretval.strptr, rc, (int)rexxrc );
// printf("Interpreter Return Code: %d\n", rc);
// printf("Function Return Code: %d\n", (int) rexxrc);
// printf("Args: '%s', '%s'\n", arg[0].strptr, arg[1].strptr );
// printf("Ret : '%s'\n", rexxretval.strptr);
if( rexxretval.strptr != NULL )
out = rexxretval.strptr;
DosFreeMem(rexxretval.strptr); // Release storage
// given to us by REXX.
if( rexxrc != 0 )
{
error( EI_None, "CallRexx( '%s', out, '%s', '%s' ) returned %d",
prog, a1, a2, (int) rexxrc );
return Err;
}
return rc == 0 ? Ok : Err;
}
4. Как добавлять свои функции к REXX-интерпретатору ?
Пример из U1. После выполнения Register_Rexx_Function_Handlers() любая REXX-процедура, работающая в контексте вашей программы, сможет использовать REXX-функцию MatchAKA.
#define INCL_RXFUNC
#define INCL_RXSUBCOM
#define INCL_RXSHV
#define INCL_REXXSAA
#include <rexxsaa.h> /* needed for RexxStart() */
#include <stdio.h> /* needed for printf() */
#include <string.h> /* needed for strlen() */
#include <strng.h> /* needed for strlen() */
LONG EXPENTRY MatchAKA(
PSZ name, /* function name */
LONG argc, /* count of arguments */
PRXSTRING argv, /* argument RXSTRINGs */
PSZ queue, /* current Rexx queue */
PRXSTRING retstr ); /* returned string value */
extern "SYSTEM" void
DeRegister_Rexx_Function_Handlers( void )
{
RexxDeregisterFunction("MatchAKA");
}
bool
Register_Rexx_Function_Handlers( void )
{
atexit( DeRegister_Rexx_Function_Handlers );
RexxRegisterFunctionExe("MatchAKA", (PFN)MatchAKA );
return Ok;
}
// MatchAKA - External Rexx function
LONG EXPENTRY MatchAKA(
PSZ name, /* function name */
LONG argc, /* count of arguments */
PRXSTRING argv, /* argument RXSTRINGs */
PSZ queue, /* current Rexx queue */
PRXSTRING retstr ) /* returned string value */
{
fido_addr a;
ftn_def def;
const char *in = RXSTRPTR(argv[0]);
a.aparse( in );
ftn::match( def, a ); // Это C++-ная функция, которая
//выполняет саму работу.
const char *res = ((string)def.fido_a).c_str();
strcpy(RXSTRPTR(*retstr), res);
// copy over current precision
retstr->strlength = strlen(res); // set new length
return 0; // completed successfully
}
5. Какреализовать Rexx subcommand handler ?
Вот пример из U1:
#define INCL_RXFUNC
#define INCL_RXSUBCOM
#define INCL_RXSHV
#define INCL_REXXSAA
#include <rexxsaa.h> /* needed for RexxStart() */
#include <stdio.h> /* needed for printf() */
#include <string.h> /* needed for strlen() */
#include <strng.h> /* needed for strlen() */
APIRET EXPENTRY U1_Command(PRXSTRING cmd, PUSHORT flags, PRXSTRING ret );
bool
Register_Rexx_Subcommand_Handler( void )
{
RexxRegisterSubcomExe("U1", (PFN)U1_Command, NULL);
return Ok;
}
#define TEST( v, s ) ( strncmp( v, s, sizeof( s ) - 1 ) == 0 )
#defineSC_SUCCESS { strcpy(ret->strptr, "0"); ret->strlength = 1; return 0; }
#defineSC_FAILURE(code) { *flags = RXSUBCOM_FAILURE; strcpy(ret->strptr, code); ret->strlength = 1; return 0; }
#defineSC_ERROR(code) { *flags = RXSUBCOM_ERROR; strcpy(ret->strptr, code); ret->strlength = 1; return 0; }
#define CMD( tail ) { if( (rc = sc_##tail( cmd )) != 0 ) { sprintf( rcs, "%d", rc ); SC_ERROR(rcs); } }
static sc_log( string & );
static sc_warning( string & );
static sc_error( string & );
static sc_fatal( string & );
APIRET EXPENTRY
U1_Command(PRXSTRING r_cmd, PUSHORT flags, PRXSTRING ret )
{
string cmd( r_cmd->strptr );
const char *p1, *p2;
const maxv = 25;
char verb[maxv];
// for CMD macro
int rc;
char rcs[10];
p1 = cmd.c_str();
p2 = strpbrk( p1, " \t" );
strncpy( verb, p1, min( maxv, p2-p1 ) );
verb[min( maxv, p2-p1 )] = '\0';
strlwr( verb );
while( *p2 == ' ' || *p2 == '\t' )
p2++;
cmd = p2;
debug( "Rexx cmd got verb '%s' and tail '%s'", verb, cmd.c_str() );
if( TEST( verb, "log" ) ) CMD( log ) else
if( TEST( verb, "warning" ) ) CMD( warning ) else
if( TEST( verb, "error" ) ) CMD( error ) else
if( TEST( verb, "fatal" ) ) CMD( fatal ) else
{
error( EI_None, "Rexx subcommand: unknown verb '%s'", verb );
SC_FAILURE("33");
}
SC_SUCCESS;
}
static int
sc_log( string &s )
{
log( "x#", "%s", s.c_str() );
return 0;
}
static int
sc_warning( string &s )
{
warning( EI_None, "%s", s.c_str() );
return 0;
}
static int
sc_error( string &s )
{
error( EI_None, "%s", s.c_str() );
return 0;
}
static int
sc_fatal( string &s )
{
fatal( EC_Dunno, EI_None, "%s", s.c_str() );
return 0;
}
6. Какие библиотеки для программирования на Rexx существуют ?
Для начала - ydbautil. Наиболее полная библиотека того, чего в REXX обычно недостает с начала работы.
Вторая библиотека - rxasync, предназначена для работы с COM-портами. Полный набор функций низкого уровня, т.е. без протоколов, упаковки, модемов.
Rxsocket - набор функций для работы с TCP/IP из REXX.
Rxipc - Inter Process Communication для REXX. Перекрывается возможностями ydbautil.
EPMBBS - пакет для написания макро к EPM на REXX и собственном макроязыке EPM.
Есть еще библиотеки, позволяющие использовать некоторый набор controls в PM-программах из REXX, обычно Message Box, Input Line с кнопками Ok и Cancel, List Box и т.п.
7. Как проверить существование файла в REXX (if exist) ?
File_Exist.cmd:
Parse Arg Name
Call SysFileTree Name, Result
if Result.0 = 0 then
Return 0
else
Return 1
Использование:
do while( file_exist(netdir'\Hold.!!!') ) call syssleep 10 end
Вариант:
if stream( 'myfile.txt', 'c', 'query exists' ) \= '' then say 'Ok!'