2 * Amiga REXX functions for regina
3 * Copyright © 2002-2011, Staf Verhaegen
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* This files contains functions that are implemented in ARexx
21 * but that are not standard REXX functions. This file contains
22 * the functions that are only to be used on amiga or compatibles.
23 * arxfuncs.c contains the ARexx functions that are usable on all
26 #if defined(_AMIGA) || defined(__AROS__)
27 #define AROS_ALMOST_COMPATIBLE
36 #include <exec/lists.h>
37 #include <exec/ports.h>
38 #include <exec/memory.h>
39 #include <exec/execbase.h>
40 #include <rexx/rxslib.h>
41 #include <rexx/storage.h>
42 #include <rexx/errors.h>
44 #include <rexx/rexxcall.h>
47 #include <proto/alib.h>
48 #include <proto/dos.h>
49 #include <proto/exec.h>
50 #include <proto/rexxsyslib.h>
57 #include <aros/debug.h>
67 /* We can't use AROS_LC1NR, since 'offset'
70 #define CallRsrcFunc(libbase, offset, rsrc) \
72 int _offset=abs(offset)/6; \
73 AROS_LVO_CALL1NR(VOID, \
74 AROS_LCA(struct RexxRsrc *, rsrc, A0), \
75 struct Library *, libbase, _offset, rexxcall \
79 #elif defined(__MORPHOS__)
81 #include <ppcinline/macros.h>
83 #define CallRsrcFunc(libbase, offset, rsrc) \
84 LP1NR((-offset), __rsrcfunc, struct RexxRsrc *, rsrc, a0, \
85 struct Library *, libbase, 0, 0, 0, 0, 0, 0 \
90 #error define CallRsrcFunc
96 #define RX_PRIVATETYPE IPTR
100 #define rm_Private1 rm_TaskBlock
101 #define rm_Private2 rm_LibBase
102 #define RX_PRIVATETYPE APTR
107 #define BNULL ((BPTR)NULL)
111 #define RXADDRSRC 0xF0000000 /* Will register a resource node to call the clean up function
112 * from when the rexx script finishes
113 * The rexx implementation is free to use the list node fields
114 * for their own purpose. */
115 #define RXREMRSRC 0xF1000000 /* Will unregister an earlier registered resource node */
116 #define RXCHECKMSG 0xF2000000 /* Check if private fields are from the Rexx interpreter */
117 #define RXSETVAR 0xF3000000 /* Set a variable with a given to a given value */
118 #define RXGETVAR 0xF4000000 /* Get the value of a variable with the given name */
122 #define RX_RESULTTYPE IPTR
123 #define RX_ARGTYPE IPTR
125 #define RX_RESULTTYPE LONG
126 #define RX_ARGTYPE STRPTR
129 #if !defined(__GNUC__)
131 #define GetHead(_l) \
132 (((struct List *)_l)->lh_Head->ln_Succ ? ((struct List *)_l)->lh_Head : (struct Node *)0)
135 #define GetSucc(_n) \
136 (((struct Node *)_n)->ln_Succ->ln_Succ ? ((struct Node *)_n)->ln_Succ : (struct Node *)0)
141 struct MsgPort
*port
;
145 typedef struct _amiga_tsd_t
{
146 struct amiga_envir portenvir
;
147 struct RxsLib
*rexxsysbase
;
149 struct List resources
; /* List to store resources to clean up at the end */
150 struct MsgPort
*listenport
, *replyport
;
151 BYTE maintasksignal
, subtasksignal
;
152 struct Task
*parent
, *child
;
153 UBYTE
*value
; /* Here a temporary argstring will be stored for RXGETVAR */
155 void *ptrs
[PTRS_SIZE
];
159 GLOBAL_PROTECTION_VAR(createtask
)
162 #define RexxSysBase (((amiga_tsd_t *)TSD->ami_tsd)->rexxsysbase)
164 /* On AROS delete the allocated resources that are not recycled by the
165 * normal C exit handling
167 void exit_amigaf( amiga_tsd_t
*atsd
)
169 struct RexxRsrc
*rsrc
;
172 ForeachNode( &atsd
->resources
, rsrc
)
173 CallRsrcFunc( rsrc
->rr_Base
, rsrc
->rr_Func
, rsrc
);
175 #warning Fix calling resources
178 DeleteMsgPort( atsd
->replyport
);
179 Signal( atsd
->child
, 1<<atsd
->subtasksignal
);
180 if ( atsd
->rexxsysbase
!= NULL
)
181 CloseLibrary( (struct Library
*)atsd
->rexxsysbase
);
182 UnLock( CurrentDir( atsd
->startlock
) );
188 static void exit_amigaf_wrapper( void )
190 tsd_t
*TSD
= __regina_get_tsd();
191 exit_amigaf( (amiga_tsd_t
*)TSD
->ami_tsd
);
195 streng
*createstreng( tsd_t
*TSD
, char *value
, int length
)
200 retval
= TSD
->MTMalloc( TSD
, sizeof(streng
) );
201 if ( retval
!= NULL
)
203 retval
->value
= TSD
->MTMalloc( TSD
, length
);
204 if ( retval
->value
== NULL
)
206 TSD
->MTFree( retval
);
210 memcpy( retval
->value
, value
, length
);
213 retval
= TSD
->MTMalloc( TSD
, sizeof(streng
)-4*sizeof(char)+length
);
214 if ( retval
!= NULL
)
215 memcpy( retval
->value
, value
, length
);
217 retval
->len
= length
;
218 retval
->max
= length
;
223 /* ReginaHandleMessages will be executed in a subtask and will be
224 * able to handle messages send to it asynchronously
226 void ReginaHandleMessages(void)
228 tsd_t
*TSD
= subtask_tsd
;
229 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
233 struct MsgPort
*listenport
;
235 listenport
= CreateMsgPort();
236 atsd
->listenport
= listenport
;
237 if ( listenport
== NULL
)
240 atsd
->subtasksignal
= AllocSignal( -1 );
241 Signal( atsd
->parent
, 1<<atsd
->maintasksignal
);
243 mask
= 1<<atsd
->subtasksignal
| 1<<atsd
->listenport
->mp_SigBit
;
244 done
= listenport
== NULL
;
247 signals
= Wait( mask
);
249 done
= (signals
& 1<<atsd
->subtasksignal
) != 0;
251 while ( (msg
= (struct RexxMsg
*)GetMsg( atsd
->listenport
)) != NULL
)
253 if ( IsRexxMsg( msg
) )
254 switch ( msg
->rm_Action
& RXCODEMASK
)
257 AddTail( &atsd
->resources
, (struct Node
*)ARG0( msg
) );
258 msg
->rm_Result1
= RC_OK
;
262 Remove( (struct Node
*)ARG0( msg
) );
263 msg
->rm_Result1
= RC_OK
;
267 if ( ( msg
->rm_Action
& RXARGMASK
) != 2 )
269 msg
->rm_Result1
= RC_ERROR
;
270 msg
->rm_Result2
= (IPTR
)ERR10_017
;
274 streng
*name
, *value
;
276 /* Using own allocation so I can get a NULL return value when allocation
277 * and not Exiterror is called
279 name
= createstreng( TSD
, (char *)msg
->rm_Args
[0], LengthArgstring( (UBYTE
*)msg
->rm_Args
[0] ) );
280 value
= createstreng( TSD
, (UBYTE
*)msg
->rm_Args
[1], LengthArgstring( (UBYTE
*)msg
->rm_Args
[1] ) );
282 if ( name
== NULL
|| value
== NULL
)
284 if ( name
!= NULL
) Free_stringTSD( name
);
285 if ( value
!= NULL
) Free_stringTSD( value
);
286 msg
->rm_Result1
= RC_ERROR
;
287 msg
->rm_Result2
= ERR10_003
;
291 setvalue( TSD
, name
, value
, -1 );
292 Free_stringTSD( name
);
293 msg
->rm_Result1
= RC_OK
;
294 msg
->rm_Result2
= (IPTR
)NULL
;
300 if ( ( msg
->rm_Action
& RXARGMASK
) != 1 )
302 msg
->rm_Result1
= RC_ERROR
;
303 msg
->rm_Result2
= (IPTR
)ERR10_017
;
307 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
311 name
= createstreng( TSD
, (char *)msg
->rm_Args
[0], LengthArgstring( (UBYTE
*)msg
->rm_Args
[0] ) );
314 msg
->rm_Result1
= RC_ERROR
;
315 msg
->rm_Result2
= (IPTR
)ERR10_003
;
319 value
= isvariable( TSD
, name
);
320 Free_stringTSD( name
);
324 if ( atsd
->value
!= NULL
) DeleteArgstring( (UBYTE
*)atsd
->value
);
325 atsd
->value
= CreateArgstring( (STRPTR
)value
->value
, value
->len
);
327 msg
->rm_Result1
= RC_OK
;
328 msg
->rm_Result2
= (IPTR
)atsd
->value
;
332 msg
->rm_Result1
= RC_ERROR
;
333 msg
->rm_Result2
= (IPTR
)ERR10_039
;
340 msg
->rm_Result1
= RC_ERROR
;
341 msg
->rm_Result2
= ERR10_010
;
344 ReplyMsg( (struct Message
*)msg
);
348 FreeSignal(atsd
->subtasksignal
);
349 if ( listenport
!= NULL
)
350 DeletePort( listenport
);
353 /* Init amiga specific thread data, this function is called during initialisation
354 * of the thread specific data
356 int init_amigaf ( tsd_t
*TSD
)
358 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)malloc( sizeof(amiga_tsd_t
) );
363 if (atsd
==NULL
) return 0;
365 TSD
->ami_tsd
= (void *)atsd
;
367 /* Initialization of amiga environ handling message ports.
368 * This has to be kept up-to-date with changes made to
369 * add_envir()/clear_environpart() in envir.c
371 atsd
->portenvir
.envir
.e
.name
= NULL
;
372 atsd
->portenvir
.envir
.type
= ENVIR_AMIGA
;
373 ep
= &atsd
->portenvir
.envir
.e
.input
;
376 ep
->hdls
[2] = ep
->hdls
[1] = ep
->hdls
[0] = -1;
377 ep
->flags
.isinput
= 1;
378 ep
= &atsd
->portenvir
.envir
.e
.output
;
381 ep
->hdls
[2] = ep
->hdls
[1] = ep
->hdls
[0] = -1;
382 ep
= &atsd
->portenvir
.envir
.e
.error
;
385 ep
->hdls
[2] = ep
->hdls
[1] = ep
->hdls
[0] = -1;
386 ep
->flags
.iserror
= 1;
388 atsd
->rexxsysbase
= (struct RxsLib
*)OpenLibrary( "rexxsyslib.library", 44 );
389 if ( atsd
->rexxsysbase
== NULL
)
391 old
= CurrentDir(BNULL
);
392 atsd
->startlock
= DupLock( old
);
395 /* When in shared library, mt_amigalib.c will take care of cleaning up */
396 if (atexit( exit_amigaf_wrapper
) == -1)
399 NewList( &atsd
->resources
);
400 atsd
->replyport
= CreatePort( NULL
, 0 );
401 atsd
->maintasksignal
= AllocSignal( -1 );
402 atsd
->parent
= FindTask( NULL
);
406 THREAD_PROTECT(createtask
)
409 atsd
->child
= NewCreateTask( TASKTAG_NAME
, "Regina Helper", TASKTAG_PC
, (APTR
)ReginaHandleMessages
,
410 TASKTAG_CODETYPE
, CODETYPE_PPC
, TAG_END
413 atsd
->child
= CreateTask( "Regina Helper", 0, (APTR
)ReginaHandleMessages
, 8192 );
415 if ( atsd
->child
!= NULL
)
416 Wait(1<<atsd
->maintasksignal
);
417 THREAD_UNPROTECT(createtask
)
418 FreeSignal(atsd
->maintasksignal
);
420 if ( atsd
->child
== NULL
)
423 for(i
= 0; i
< PTRS_SIZE
; i
++)
424 atsd
->ptrs
[i
] = NULL
;
431 * Support function for exec lists
433 static streng
*getlistnames( tsd_t
*TSD
, struct List
*list
, const streng
*sep
)
437 streng
*retval
, *tmpstr
;
439 retval
= Str_cre_TSD( TSD
, "" );
440 ForeachNode( list
, ln
)
444 tmpstr
= Str_cat_TSD( TSD
, retval
, sep
);
445 if ( tmpstr
!= retval
)
447 Free_string_TSD( TSD
, retval
);
455 tmpstr
= Str_catstr_TSD( TSD
, retval
, ln
->ln_Name
);
456 if ( tmpstr
!= retval
)
458 Free_string_TSD( TSD
, retval
);
468 * SHOW a function the names available in different resource lists
470 streng
*amiga_show( tsd_t
*TSD
, cparamboxptr parm1
)
472 cparamboxptr parm2
= NULL
, parm3
= NULL
;
473 streng
*name
= NULL
, *sep
, *retval
= NULL
;
475 checkparam( parm1
, 1, 3, "SHOW" );
480 if ( parm2
!= NULL
&& parm2
->value
!= NULL
&& parm2
->value
->len
!= 0 )
483 if ( parm3
== NULL
|| parm3
->value
== NULL
|| parm3
->value
->len
== 0 )
484 sep
= Str_cre_TSD( TSD
, " " );
486 sep
= Str_dup_TSD( TSD
, parm3
->value
);
488 switch( getoptionchar( TSD
, parm1
->value
, "SHOW", 1, "", "CFLP" ) )
491 retval
= arexx_show( TSD
, parm1
);
497 retval
= getlistnames( TSD
, &RexxSysBase
->rl_ClipList
, sep
);
500 char *s
= str_of( TSD
, name
);
501 struct Node
*ln
= FindName( &RexxSysBase
->rl_ClipList
, s
);
502 retval
= int_to_streng( TSD
, ln
!= NULL
);
511 retval
= getlistnames( TSD
, &RexxSysBase
->rl_LibList
, sep
);
514 char *s
= str_of( TSD
, name
);
515 struct Node
*ln
= FindName( &RexxSysBase
->rl_LibList
, s
);
516 retval
= int_to_streng( TSD
, ln
!= NULL
);
525 retval
= getlistnames( TSD
, &SysBase
->PortList
, sep
);
528 char *s
= str_of( TSD
, name
);
529 struct Node
*ln
= FindName( &SysBase
->PortList
, s
);
530 retval
= int_to_streng( TSD
, ln
!= NULL
);
536 Free_string_TSD( TSD
, sep
);
542 /* amiga_find_envir will try to find the port with the given and
543 * create an envir function for that
545 struct envir
*amiga_find_envir( const tsd_t
*TSD
, const streng
*name
)
547 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
549 struct MsgPort
*port
;
551 s
= str_of( TSD
, name
);
552 port
= FindPort( s
);
558 if ( atsd
->portenvir
.envir
.e
.name
!= NULL
)
559 Free_stringTSD( atsd
->portenvir
.envir
.e
.name
);
561 atsd
->portenvir
.envir
.e
.name
= Str_dupTSD( name
);
562 atsd
->portenvir
.port
= port
;
564 return (struct envir
*)&(atsd
->portenvir
);
567 /* createreginamessage will create a RexxMsg filled with the necessary fields
568 * for regina specific things
570 struct RexxMsg
*createreginamessage( const tsd_t
*TSD
)
572 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
575 msg
= CreateRexxMsg( atsd
->replyport
, NULL
, NULL
);
578 msg
->rm_Private1
= (RX_PRIVATETYPE
)atsd
->listenport
;
579 msg
->rm_Private2
= (RX_PRIVATETYPE
)TSD
;
584 /* The function sendandwait will send a rexx message to a certain
585 * port and wait till it returns. It the mean time also other
586 * message (like variable can be handled
587 * The replyport of the msg has to be atsd->listenport
589 void sendandwait( const tsd_t
*TSD
, struct MsgPort
*port
, struct RexxMsg
*msg
)
591 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
592 struct RexxMsg
*msg2
;
594 PutMsg( port
, (struct Message
*)msg
);
597 while ( msg2
!= msg
)
599 WaitPort( atsd
->replyport
);
600 msg2
= (struct RexxMsg
*)GetMsg( atsd
->replyport
);
602 ReplyMsg( (struct Message
*)msg2
);
608 streng
*AmigaSubCom( const tsd_t
*TSD
, const streng
*command
, struct envir
*envir
, int *rc
)
611 struct MsgPort
*port
= ((struct amiga_envir
*)envir
)->port
;
612 streng
*retval
= NULL
;
614 D(bug("environment: %s\n", tmpstr_of( (tsd_t
*)TSD
, envir
->e
.name
)));
616 msg
= createreginamessage( TSD
);
617 /* Always ask for result, wether to set RESULT or not will be decided later */
618 msg
->rm_Action
= RXCOMM
| RXFF_RESULT
;
619 msg
->rm_Args
[0] = (RX_ARGTYPE
)CreateArgstring( (STRPTR
)command
->value
, command
->len
);
621 msg
->rm_Stdin
= Input();
622 msg
->rm_Stdout
= Output();
624 sendandwait( TSD
, port
, msg
);
626 *rc
= msg
->rm_Result1
;
627 if (msg
->rm_Result1
== 0)
629 if (msg
->rm_Result2
== 0)
630 retval
= Str_crestrTSD( "" );
633 retval
= Str_ncre_TSD( TSD
, (UBYTE
*)msg
->rm_Result2
, LengthArgstring( (UBYTE
*)msg
->rm_Result2
) );
634 DeleteArgstring( (UBYTE
*)msg
->rm_Result2
);
638 retval
= Str_crestrTSD( "" );
640 DeleteArgstring( (UBYTE
*)msg
->rm_Args
[0]);
641 DeleteRexxMsg( msg
);
648 * Here follows now the support function for ARexx style function hosts and libraries:
650 * Also here the try_func_amiga is defined which is called when a function is called
651 * in an ARexx script.
654 /* When addlib is called with two arguments the first argument is considered as a function
655 * host name. When it is called with three or four arguments a function library is assumed
657 streng
*amiga_addlib( tsd_t
*TSD
, cparamboxptr parm1
)
659 cparamboxptr parm2
= NULL
, parm3
= NULL
, parm4
= NULL
;
660 struct MsgPort
*rexxport
;
662 int pri
, offset
, version
, error
, count
;
666 checkparam( parm1
, 2, 4, "ADDLIB" );
668 pri
= streng_to_int( TSD
, parm2
->value
, &error
);
669 if (error
|| abs(pri
) > 100 )
670 exiterror( ERR_INCORRECT_CALL
, 11, "ADDLIB", 2, tmpstr_of( TSD
, parm2
->value
) );
673 if ( parm3
!= NULL
&& parm3
->value
!= NULL
&& parm3
->value
->len
== 0 )
674 exiterror( ERR_INCORRECT_CALL
, 21, "ADDLIB", 3 );
675 if ( parm3
== NULL
|| parm3
->value
== NULL
)
679 offset
= streng_to_int( TSD
, parm3
->value
, &error
);
680 if ( error
|| offset
>= 0 )
681 exiterror( ERR_INCORRECT_CALL
, 11, "ADDLIB", 3, tmpstr_of( TSD
, parm3
->value
) );
686 if ( parm4
== NULL
|| parm4
->value
== NULL
|| parm4
->value
->len
== 0 )
690 version
= streng_to_int( TSD
, parm4
->value
, &error
);
692 exiterror( ERR_INCORRECT_CALL
, 11, "ADDLIB", 4, tmpstr_of( TSD
, parm4
->value
) );
694 exiterror( ERR_INCORRECT_CALL
, 13, "ADDLIB", 4, tmpstr_of( TSD
, parm4
->value
) );
697 name
= str_of( TSD
, parm1
->value
);
698 msg
= createreginamessage( TSD
);
701 Free_TSD( TSD
, name
);
702 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
704 if ( parm3
== NULL
|| parm3
->value
== NULL
|| parm3
->value
->len
== 0 )
706 msg
->rm_Action
= RXADDFH
;
707 msg
->rm_Args
[0] = (RX_ARGTYPE
)name
;
708 msg
->rm_Args
[1] = (RX_ARGTYPE
)pri
;
710 if ( !FillRexxMsg( msg
, 2, 1<<1 ) )
712 Free_TSD( TSD
, name
);
713 DeleteRexxMsg( msg
);
714 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
719 msg
->rm_Action
= RXADDLIB
;
720 msg
->rm_Args
[0] = (RX_ARGTYPE
)name
;
721 msg
->rm_Args
[1] = (RX_ARGTYPE
)pri
;
722 msg
->rm_Args
[2] = (RX_ARGTYPE
)offset
;
723 msg
->rm_Args
[3] = (RX_ARGTYPE
)version
;
725 if ( !FillRexxMsg( msg
, 4, 1<<1 | 1<<2 | 1<<3 ) )
727 Free_TSD( TSD
, name
);
728 DeleteRexxMsg( msg
);
729 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
733 rexxport
= FindPort( "REXX" );
734 if (rexxport
== NULL
)
736 Free_TSD( TSD
, name
);
737 DeleteRexxMsg( msg
);
738 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
740 sendandwait( TSD
, rexxport
, msg
);
742 Free_TSD( TSD
, name
);
743 ClearRexxMsg( msg
, count
);
745 retval
= ( msg
->rm_Result1
== 0 ) ? Str_cre_TSD( TSD
, "1" ) : Str_cre_TSD( TSD
, "0" );
747 DeleteRexxMsg( msg
);
752 streng
*amiga_remlib( tsd_t
*TSD
, cparamboxptr parm1
)
754 struct MsgPort
*rexxport
;
758 checkparam( parm1
, 1, 1, "REMLIB" );
760 msg
= createreginamessage( TSD
);
762 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
764 msg
->rm_Action
= RXREMLIB
;
765 msg
->rm_Args
[0] = (RX_ARGTYPE
)CreateArgstring( parm1
->value
->value
, parm1
->value
->len
);
767 rexxport
= FindPort( "REXX" );
768 if (rexxport
== NULL
)
770 DeleteArgstring( (UBYTE
*)msg
->rm_Args
[0] );
771 DeleteRexxMsg( msg
);
772 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
774 sendandwait( TSD
, rexxport
, msg
);
776 retval
= ( msg
->rm_Result1
== 0 ) ? Str_cre_TSD( TSD
, "1" ) : Str_cre_TSD( TSD
, "0" );
778 DeleteArgstring( (UBYTE
*)msg
->rm_Args
[0] );
779 DeleteRexxMsg( msg
);
784 streng
*try_func_amiga( tsd_t
*TSD
, const streng
*name
, cparamboxptr parms
, char called
)
786 struct MsgPort
*port
;
788 struct RexxRsrc
*rsrc
;
791 IPTR result2
= (IPTR
)0;
793 unsigned int parmcount
;
795 streng
*retval
= NULL
;
797 msg
= createreginamessage( TSD
);
799 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
801 msg
->rm_Action
= RXFUNC
| RXFF_RESULT
;
802 msg
->rm_Args
[0] = (RX_ARGTYPE
)CreateArgstring( (char *)name
->value
, name
->len
);
804 for (parmit
= parms
, parmcount
= 0; parmit
!= NULL
; parmit
= parmit
->next
)
806 if ( parmit
->value
!= NULL
&& parmit
->value
->len
> 0 )
809 msg
->rm_Args
[parmcount
] = (RX_ARGTYPE
)CreateArgstring( parmit
->value
->value
, parmit
->value
->len
);
812 msg
->rm_Action
|= parmcount
;
813 msg
->rm_Stdin
= Input( );
814 msg
->rm_Stdout
= Output( );
818 for (rsrc
= (struct RexxRsrc
*)GetHead(&RexxSysBase
->rl_LibList
), result1
= 1;
819 rsrc
!= NULL
&& result1
== 1;
820 rsrc
= (struct RexxRsrc
*)GetSucc(rsrc
)
823 switch (rsrc
->rr_Node
.ln_Type
)
827 lib
= OpenLibrary(rsrc
->rr_Node
.ln_Name
, rsrc
->rr_Arg2
);
831 ClearRexxMsg( msg
, parmcount
+ 1 );
832 DeleteRexxMsg( msg
);
833 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
835 /* Can not pass &result2 directly because on systems where
836 * sizeof(IPTR)>sizeof(UBYTE *) this goes wrong
838 result1
= RexxCallQueryLibFunc(msg
, lib
, rsrc
->rr_Arg1
, &retstring
);
840 result2
= (IPTR
)retstring
;
845 port
= FindPort(rsrc
->rr_Node
.ln_Name
);
849 ClearRexxMsg( msg
, parmcount
+ 1 );
850 DeleteRexxMsg( msg
);
851 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
853 sendandwait( TSD
, port
, msg
);
855 result1
= (ULONG
)msg
->rm_Result1
;
856 result2
= msg
->rm_Result2
;
864 ClearRexxMsg( msg
, parmcount
+ 1 );
865 DeleteRexxMsg( msg
);
869 if ( (UBYTE
*)result2
== NULL
)
870 retval
= nullstringptr();
873 retval
= Str_ncre_TSD( TSD
, (const char *)result2
, LengthArgstring( (UBYTE
*)result2
) );
874 DeleteArgstring( (UBYTE
*)result2
);
877 else if ( result1
== 1 )
880 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
887 /* The clip handling functions for AROS/amiga: setclip, getclip */
889 streng
*amiga_setclip( tsd_t
*TSD
, cparamboxptr parm1
)
892 struct MsgPort
*rexxport
;
896 checkparam( parm1
, 1, 2, "SETCLIP" );
899 msg
= createreginamessage( TSD
);
901 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
903 if ( parm2
== NULL
|| parm2
->value
== NULL
|| parm2
->value
->len
== 0 )
905 msg
->rm_Action
= RXREMCON
;
906 msg
->rm_Args
[0] = (RX_ARGTYPE
)str_of( TSD
, parm1
->value
);
910 msg
->rm_Action
= RXADDCON
;
911 msg
->rm_Args
[0] = (RX_ARGTYPE
)str_of( TSD
, parm1
->value
);
912 msg
->rm_Args
[1] = (RX_ARGTYPE
)parm2
->value
->value
;
913 msg
->rm_Args
[2] = (RX_ARGTYPE
)parm2
->value
->len
;
916 rexxport
= FindPort( "REXX" );
917 if ( rexxport
== NULL
)
919 Free_TSD( TSD
, (void *)msg
->rm_Args
[0] );
920 DeleteRexxMsg( msg
);
921 exiterror( ERR_EXTERNAL_QUEUE
, 0 );
923 sendandwait( TSD
, rexxport
, msg
);
925 Free_TSD( TSD
, (void *)msg
->rm_Args
[0] );
927 retval
= ( msg
->rm_Result1
== 0 ) ? Str_cre_TSD( TSD
, "1" ) : Str_cre_TSD( TSD
, "0" );
928 DeleteRexxMsg( msg
);
933 streng
*amiga_getclip( tsd_t
*TSD
, cparamboxptr parm1
)
935 struct RexxRsrc
*rsrc
;
938 checkparam( parm1
, 1, 1, "GETCLIP" );
940 name
= str_of( TSD
, parm1
->value
);
943 rsrc
= (struct RexxRsrc
*)FindName( &RexxSysBase
->rl_ClipList
, name
);
946 Free_TSD( TSD
, name
);
949 return nullstringptr();
952 void *arg1
= (void *)rsrc
->rr_Arg1
;
953 return Str_ncre_TSD( TSD
, arg1
, LengthArgstring( arg1
) );
957 streng
*amiga_pragma( tsd_t
*TSD
, cparamboxptr parm1
)
960 streng
*retval
= NULL
;
961 static char buf
[1024];
963 checkparam( parm1
, 1, 2, "PRAGMA" );
966 switch( getoptionchar( TSD
, parm1
->value
, "PRAGMA", 1, "", "DPIS" ) )
970 BPTR lock
= CurrentDir( BNULL
);
972 NameFromLock( lock
, buf
, 1023 );
974 retval
= Str_cre_TSD( TSD
, buf
);
975 if ( parm2
!= NULL
&& parm2
->value
!= NULL
&& parm2
->value
->len
!= 0 )
977 struct FileInfoBlock
*fib
;
978 char *name
= str_of( TSD
, parm2
->value
);
980 lock
= Lock( name
, ACCESS_READ
);
982 Free_TSD( TSD
, name
);
984 fib
= AllocDosObject( DOS_FIB
, NULL
);
989 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
993 Examine( lock
, fib
);
995 if ( lock
== BNULL
|| fib
->fib_DirEntryType
<= 0 )
997 FreeDosObject( DOS_FIB
, fib
);
998 Free_string_TSD( TSD
, retval
);
999 retval
= nullstringptr();
1003 UnLock( CurrentDir( lock
) );
1004 FreeDosObject( DOS_FIB
, fib
);
1012 struct Task
*task
= FindTask( NULL
);
1013 retval
= int_to_streng( TSD
, (int)task
->tc_Node
.ln_Pri
);
1014 if ( parm2
!= NULL
&& parm2
->value
!= NULL
&& parm2
->value
->len
!= 0 )
1017 pri
= streng_to_int( TSD
, parm2
->value
, &error
);
1019 exiterror( ERR_INCORRECT_CALL
, 11, "PRAGMA", 2, tmpstr_of( TSD
, parm2
->value
) );
1020 if ( abs(pri
) > 127 )
1021 exiterror( ERR_INCORRECT_CALL
, 0 );
1022 SetTaskPri( task
, pri
);
1030 sprintf(s
, "%8lx", (unsigned long)FindTask( NULL
) );
1031 if ( parm2
!= NULL
&& parm2
->value
!= NULL
)
1032 exiterror( ERR_INCORRECT_CALL
, 4, "PRAGMA", 1 );
1033 retval
= Str_cre_TSD( TSD
, s
);
1039 struct Process
*process
= (struct Process
*)FindTask( NULL
);
1040 ULONG size
= (ULONG
)((char *)process
->pr_Task
.tc_SPUpper
- (char *)process
->pr_Task
.tc_SPLower
);
1041 retval
= int_to_streng( TSD
, size
);
1042 /* FIXME: second argument ignored because stack size increase is not implemented
1052 /* Support functions for os_amiga.c
1053 They are defined here so data can be stored in amiga_tsd_t, that is only
1054 defined in this file.
1056 int __amiga_ptr2int(const tsd_t
*TSD
, void *ptr
)
1058 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
1061 for ( i
= 0; i
< PTRS_SIZE
&& atsd
->ptrs
[i
] != NULL
; i
++ )
1064 if ( i
== PTRS_SIZE
)
1068 atsd
->ptrs
[i
] = ptr
;
1073 void *__amiga_getptr(const tsd_t
*TSD
, int index
)
1075 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
1077 return atsd
->ptrs
[index
- 1];
1080 void __amiga_clearptr(const tsd_t
*TSD
, int index
)
1082 amiga_tsd_t
*atsd
= (amiga_tsd_t
*)TSD
->ami_tsd
;
1084 atsd
->ptrs
[index
- 1] = NULL
;