2 static char *RCSid
= "$Id$";
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1993-1994 Anders Christensen <anders@pvv.unit.no>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* JH 20-10-99 */ /* To make Direct setting of stems Direct and not Symbolic. */
24 #if defined(WIN32) && defined(__IBMC__)
26 # pragma warning(default: 4115 4201 4214)
28 # if defined(WIN32) && (defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
32 # if defined(__EMX__) && defined(OS2)
33 # define DONT_TYPEDEF_PFN
37 # if defined(__WATCOMC__) && defined(OS2)
39 # define DONT_TYPEDEF_PFN
42 # if defined(_MSC_VER) && !defined(__WINS__)
45 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
46 # pragma warning(disable: 4115 4201 4214)
50 # pragma warning(default: 4115 4201 4214)
60 #ifndef RXLIB /* need __regina_faked_main which is known with RXLIB only */
90 # define max(a,b) (((a) > (b)) ? (a) : (b))
93 static int ReMapHook( const tsd_t
*TSD
, int NetHook
) ;
95 typedef struct { /* cli_tsd: static variables of this module (thread-safe) */
96 char count_params_buf
[32]; /* handle_no_of_params() */
98 /* Buffering of external parameters allows a delayed deletion in case of
101 char * ExternalName
;
103 int * Lengths
; /* StringsCount + 1 elements */
104 char ** Strings
; /* StringsCount + 1 elements */
105 } cli_tsd_t
; /* thread-specific but only needed by this module. see
109 /* init_client initializes the module.
110 * Currently, we set up the thread specific data.
111 * The function returns 1 on success, 0 if memory is short.
113 int init_client( tsd_t
*TSD
)
117 if (TSD
->cli_tsd
!= NULL
)
120 if ((ct
= TSD
->cli_tsd
= MallocTSD(sizeof(cli_tsd_t
))) == NULL
)
122 memset(ct
,0,sizeof(cli_tsd_t
));
123 ct
->StringsCount
= -1;
128 /* wrapstring makes a streng from external (application) data. If you get
129 * an exception you may have a wild pointer in your application.
130 * Returns NULL if string==NULL or length<0.
132 static streng
*wrapstring( const tsd_t
*TSD
, const char *string
, int length
)
134 streng
*result
=NULL
;
136 if (length
>=0 && string
)
138 result
= Str_makeTSD( length
) ;
139 memcpy( result
->value
, string
, length
) ;
140 result
->len
= length
;
149 static int map_type( int in
)
151 if (in
==RX_TYPE_COMMAND
)
152 return INVO_COMMAND
;
153 else if (in
==RX_TYPE_FUNCTION
)
154 return INVO_FUNCTION
;
157 assert( in
== RX_TYPE_SUBROUTINE
) ;
158 return INVO_SUBROUTINE
;
163 static void closedown( const tsd_t
*TSD
)
165 CloseOpenFiles( TSD
);
166 if (TSD
->in_protected
)
170 memcpy(h
,TSD
->protect_return
,sizeof(jmp_buf));
171 /* cheat about the const, we go away anyway :-) */
172 ((tsd_t
*)(TSD
))->delayed_error_type
= PROTECTED_DelayedExit
;
173 ((tsd_t
*)(TSD
))->expected_exit_error
= 0;
179 static paramboxptr
parametrize( const tsd_t
*TSD
, int ArgCount
, const int *ParLengths
, const char **ParStrings
)
181 paramboxptr parms
=NULL
, root
=NULL
;
185 for (i
=0; count
--; i
++ )
189 parms
->next
= MallocTSD( sizeof(parambox
)) ;
190 parms
= parms
->next
;
193 parms
= root
= MallocTSD( sizeof(parambox
)) ;
195 parms
->value
= wrapstring( TSD
, ParStrings
[i
], ParLengths
[i
] ) ;
204 int IfcExecScript( int NameLen
, const char *Name
,
205 int ArgCount
, const int *ParLengths
, const char **ParStrings
,
206 int CallType
, int ExitFlags
, int EnvLen
, const char *EnvName
,
207 int SourceCode
, int restricted
,
208 const char *SourceString
, unsigned long SourceStringLen
,
209 const void *TinnedTree
, unsigned long TinnedTreeLen
,
210 int *RetLen
, char **RetString
, void **instore_buf
,
211 unsigned long *instore_length
)
213 streng
* volatile command
=NULL
;
218 volatile paramboxptr params
=NULL
;
219 jmp_buf panic
, *oldpanic
;
221 /* We need volatiles here to prevent variable clobbering by longjmp. */
222 volatile int panicked
=0;
223 volatile int hooks
=0, ctype
=0 ;
224 volatile streng
* volatile environment
=NULL
;
225 volatile streng
* volatile result
=NULL
;
226 volatile tsd_t
*volatile TSD
;
227 unsigned InterpreterStatus
[IPRT_BUFSIZE
];
229 TSD
= __regina_get_tsd(); /* The TSD should be fetched directly.
230 * see longjmp and below for more information.
232 wTSD
= (tsd_t
*) TSD
;
234 SaveInterpreterStatus(wTSD
,InterpreterStatus
);
237 command
= wrapstring( wTSD
, Name
, NameLen
) ;
239 params
= parametrize( wTSD
, ArgCount
, ParLengths
, ParStrings
) ;
241 ctype
= map_type(CallType
) ;
243 TSD
->restricted
= restricted
;
245 for (hooks
=num
=0; num
<30; num
++)
247 if ((ExitFlags
>>num
) & 0x01)
248 hooks
|= (1 << (ReMapHook(wTSD
, num
))) ;
251 environment
= wrapstring( wTSD
, EnvName
, EnvLen
) ;
253 environment
= Str_cre_TSD( wTSD
, "DEFAULT" ) ;
255 if ( !envir_exists( wTSD
, (streng
*)environment
) )
257 add_envir( wTSD
, Str_dup_TSD(wTSD
, (streng
*)environment
), ENVIR_PIPE
, 0 ) ;
261 /* It may be that TSD->systeminfo->panic is not set. This may lead to
262 * an exit() call, e.g. at Rexx "EXIT". We set TSD->systeminfo->panic if it
263 * is not set. If a problem occurs we will be informed by a longjmp and
264 * we will not completely been killed by an exit(). Remember: This
265 * function is typically called if a program uses "us" as a subroutine.
266 * Exiting is very harmful in this case.
267 * Note: The memory allocated within called subsoutines will NOT be
268 * freed. We must change many things to do this. Maybe, it's a good
269 * idea to traverse all called subroutine trees and free the leaves.
272 if ( ( oldpanic
= TSD
->systeminfo
->panic
) == NULL
)
274 TSD
->systeminfo
->panic
= &panic
;
275 assert(!TSD
->in_protected
);
276 if ( setjmp( *TSD
->systeminfo
->panic
) )
278 wTSD
= (tsd_t
*) TSD
; /* Values in(!!) TSD may have changes due longjmp */
280 result
= Str_make_TSD(wTSD
, 0);
286 wTSD
= (tsd_t
*) TSD
; /* Values in(!!) TSD may have changes due longjmp */
290 if (type
==RX_TYPE_EXTERNAL
)
292 result
=execute_external(wTSD
,command
,params
,(streng
*) environment
,
293 &RetCode
,hooks
,ctype
);
294 Free_string_TSD( wTSD
, command
);
296 else if (type
==RX_TYPE_INSTORE
)
298 result
=do_instore(wTSD
,command
,params
,(streng
*) environment
,&RetCode
,
300 TinnedTree
,TinnedTreeLen
,
301 SourceString
,SourceStringLen
,
305 else if (type
==RX_TYPE_MACRO
)
306 result
= Str_make_TSD(wTSD
, 0);
307 else if (type
==RX_TYPE_SOURCE
)
309 streng
*SrcStr
= wrapstring( wTSD
, SourceString
, SourceStringLen
) ;
310 internal_parser_type ipt
;
311 ipt
= enter_macro( wTSD
, SrcStr
, command
, instore_buf
, instore_length
) ;
312 if ( CallType
== RX_TYPE_COMMAND
316 && memcmp( "//T", *ParStrings
, 3 ) == 0 )
317 ; /* request for tokenisation only, don't execute */
321 result
=do_instore(wTSD
,command
,params
,(streng
*) environment
,&RetCode
,
327 /* do_instore already has deleted the internal structure */
332 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
337 TSD
->systeminfo
->panic
= oldpanic
;
339 del_envir( wTSD
, (streng
*) environment
) ;
340 Free_string_TSD( wTSD
, (streng
*) environment
) ;
341 RestoreInterpreterStatus(wTSD
,InterpreterStatus
);
343 if (result
&& result
->len
)
345 *RetLen
= result
->len
;
346 *RetString
=(char *)IfcAllocateMemory(result
->len
+1);
349 memcpy(*RetString
,(void *) result
->value
,result
->len
);
350 *(*RetString
+(result
->len
)) = '\0';
353 *RetLen
= RX_NO_STRING
;
356 *RetLen
= RX_NO_STRING
;
358 Free_TSD(wTSD
, (void *) result
);
364 static int handle_source( const tsd_t
*TSD
, int *Length
, char **String
)
366 int infile
=0, total
=0, invoked
=0 ;
367 const char *stype
=NULL
;
371 stype
= system_type() ;
372 sleng
= strlen( stype
) ;
373 infile
= TSD
->systeminfo
->input_file
->len
;
374 invoked
= strlen(invo_strings
[TSD
->systeminfo
->invoked
]) ;
375 total
= sleng
+ 1 + invoked
+ 1 + infile
;
377 ctmp
= *String
= MallocTSD( (*Length
=total
)+2 ) ;
378 sprintf( ctmp
, "%s %s ", stype
, invo_strings
[TSD
->systeminfo
->invoked
]) ;
379 strncat( ctmp
, TSD
->systeminfo
->input_file
->value
, infile
) ;
384 static int handle_param( tsd_t
*TSD
, int *Length
, char **String
)
386 paramboxptr ptr
=NULL
;
390 ptr
= TSD
->currlevel
->args
;
391 value
= wrapstring( TSD
, *String
, *Length
) ;
392 number
= atopos( TSD
, value
, "internal", 1 ) ;
393 Free_stringTSD( value
) ;
394 value
= get_parameter( ptr
, number
) ;
398 *(Length
+1) = value
->len
;
399 *(String
+1) = value
->value
;
402 *(Length
+1) = RX_NO_STRING
;
407 static int handle_no_of_params( const tsd_t
*TSD
, int *Length
, char **String
)
409 paramboxptr ptr
=NULL
;
414 ptr
= TSD
->currlevel
->args
;
415 count
= count_params( ptr
, PARAM_TYPE_HARD
) ;
417 sprintf( ct
->count_params_buf
, "%d", count
) ;
418 *String
= ct
->count_params_buf
;
419 *Length
= strlen(*String
) ;
426 static int get_next_var( tsd_t
*TSD
, int *Lengths
, char **Strings
)
428 variableptr value
=NULL
, rval
=NULL
, rrval
=NULL
;
431 if (TSD
->var_indicator
==0)
433 get_next_variable( TSD
, 1 ) ;
434 TSD
->var_indicator
= 1 ;
439 value
= get_next_variable( TSD
, 0 ) ;
440 for (rval
=value
; rval
&& rval
->realbox
; rval
=rval
->realbox
)
444 if (rval
&& !(rval
->flag
& VFLAG_STR
))
446 if (rval
->flag
& VFLAG_NUM
)
449 expand_to_str( TSD
, rval
) ;
451 expand_to_str( TSD
, rval
) ;
459 for (rrval
=rval
->stem
; rrval
&& rrval
->realbox
; rrval
=rrval
->realbox
)
463 if (rrval
&& !(rrval
->flag
& VFLAG_STR
))
465 if (rval
->flag
& VFLAG_NUM
)
468 expand_to_str( TSD
, rval
) ;
470 expand_to_str( TSD
, rval
) ;
485 l
= Lengths
[0] = rval
->stem
->name
->len
+ rval
->name
->len
;
486 Strings
[0] = MallocTSD( (l
< 1) ? 1 : l
) ;
487 memcpy(Strings
[0], rval
->stem
->name
->value
, rval
->stem
->name
->len
);
488 memcpy(Strings
[0]+rval
->stem
->name
->len
,
489 rval
->name
->value
, rval
->name
->len
) ;
493 Lengths
[0] = rval
->name
->len
;
494 Strings
[0] = rval
->name
->value
;
499 Lengths
[1] = rval
->value
->len
;
500 Strings
[1] = rval
->value
->value
;
504 assert( rval
->stem
&& rrval
->value
) ;
505 l
= Lengths
[1] = rval
->stem
->name
->len
+ rval
->name
->len
;
506 Strings
[1] = MallocTSD( (l
< 1) ? 1 : l
) ;
507 memcpy( Strings
[1], rval
->stem
->name
->value
, value
->stem
->name
->len
);
508 memcpy( Strings
[1]+value
->stem
->name
->len
,
509 rval
->name
->value
, rval
->name
->len
) ;
517 * Once we have reached the end of all variables, reset var_indicator
518 * so next time we can start from the beginning again.
520 TSD
->var_indicator
= 0 ;
526 static int MapHook( const tsd_t
*TSD
, int RexxHook
)
530 case HOOK_STDOUT
: return RX_EXIT_STDOUT
;
531 case HOOK_STDERR
: return RX_EXIT_STDERR
;
532 case HOOK_TRCIN
: return RX_EXIT_TRCIN
;
533 case HOOK_PULL
: return RX_EXIT_PULL
;
535 case HOOK_INIT
: return RX_EXIT_INIT
;
536 case HOOK_TERMIN
: return RX_EXIT_TERMIN
;
537 case HOOK_SUBCOM
: return RX_EXIT_SUBCOM
;
539 case HOOK_GETENV
: return RX_EXIT_GETENV
;
540 case HOOK_SETENV
: return RX_EXIT_SETENV
;
550 static int ReMapHook( const tsd_t
*TSD
, int NetHook
)
554 case RX_EXIT_STDOUT
: return HOOK_STDOUT
;
555 case RX_EXIT_STDERR
: return HOOK_STDERR
;
556 case RX_EXIT_TRCIN
: return HOOK_TRCIN
;
557 case RX_EXIT_PULL
: return HOOK_PULL
;
559 case RX_EXIT_TERMIN
: return HOOK_TERMIN
;
560 case RX_EXIT_INIT
: return HOOK_INIT
;
561 case RX_EXIT_SUBCOM
: return HOOK_SUBCOM
;
562 case RX_EXIT_FUNC
: return HOOK_FUNC
;
564 case RX_EXIT_GETENV
: return HOOK_GETENV
;
565 case RX_EXIT_SETENV
: return HOOK_SETENV
;
576 int hookup( const tsd_t
*TSD
, int hook
)
580 code
= MapHook ( TSD
, hook
);
581 assert (code
== RX_EXIT_INIT
|| code
== RX_EXIT_TERMIN
);
582 rcode
= IfcDoExit( TSD
, code
, 0, NULL
, 0, NULL
, NULL
, NULL
) ;
583 if (rcode
==RX_HOOK_ERROR
)
584 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
585 else if (rcode
==RX_HOOK_GO_ON
)
587 else if (rcode
==RX_HOOK_NOPE
)
590 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
594 int hookup_output( const tsd_t
*TSD
, int hook
, const streng
*outdata
)
596 int rcode
=0, code
=0 ;
600 code
= MapHook( TSD
, hook
);
601 assert (code
== RX_EXIT_STDOUT
|| code
== RX_EXIT_STDERR
);
604 str
= str_of( TSD
, outdata
) ;
609 str
= MallocTSD( 1 ) ;
614 rcode
= IfcDoExit( TSD
, code
, len
, str
, 0, NULL
, NULL
, NULL
) ;
616 if (rcode
==RX_HOOK_ERROR
)
617 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
618 else if (rcode
==RX_HOOK_GO_ON
)
620 else if (rcode
==RX_HOOK_NOPE
)
623 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
628 int hookup_output2( const tsd_t
*TSD
, int hook
, const streng
*outdata1
, const streng
*outdata2
)
630 int rcode
=0, code
=0 ;
632 int len1
= 0, len2
= 0;
634 code
= MapHook( TSD
, hook
);
635 assert (code
== RX_EXIT_SETENV
);
638 str1
= str_of( TSD
, outdata1
) ;
639 len1
= outdata1
->len
;
643 str1
= MallocTSD( 1 ) ;
649 str2
= str_of( TSD
, outdata2
) ;
650 len2
= outdata2
->len
;
654 str2
= MallocTSD( 1 ) ;
659 rcode
= IfcDoExit( TSD
, code
, len1
, str1
, len2
, str2
, NULL
, NULL
) ;
662 if (rcode
==RX_HOOK_ERROR
)
663 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
664 else if (rcode
==RX_HOOK_GO_ON
)
666 else if (rcode
==RX_HOOK_NOPE
)
669 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
674 int hookup_input( const tsd_t
*TSD
, int hook
, streng
**indata
)
676 int rcode
=0, code
=0 ;
677 /* The following value allows called programs to call "free" to the return
678 * parameters without destroying our stack.
680 #define ILLEGAL_USE_SIZE (8 * sizeof(void *))
681 char RetBuf
[ILLEGAL_USE_SIZE
+ 256] ;
685 code
= MapHook( TSD
, hook
);
686 assert (code
== RX_EXIT_PULL
|| code
== RX_EXIT_TRCIN
);
689 /* FIXME, FGC: The documentation says that the input of a PULL or TRCIN is
690 * undefined. Why do we provide a buffer?
692 rcode
= IfcDoExit( TSD
, code
, 0, NULL
, 0, NULL
, &retlen
, &retstr
) ;
693 if (rcode
==RX_HOOK_ERROR
)
694 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
695 else if (rcode
==RX_HOOK_GO_ON
)
697 else if (rcode
==RX_HOOK_NOPE
)
700 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
702 *indata
= wrapstring( TSD
, retstr
, retlen
) ;
703 FreeTSD( retstr
) ; /* retstr was always newly allocated */
704 #undef ILLEGAL_USE_SIZE
708 int hookup_input_output( const tsd_t
*TSD
, int hook
, const streng
*outdata
, streng
**indata
)
712 int rcode
=0, code
=0 ;
713 /* The following value allows called programs to call "free" to the return
714 * parameters without destroying our stack.
716 #define ILLEGAL_USE_SIZE (8 * sizeof(void *))
717 char RetBuf
[ILLEGAL_USE_SIZE
+ 256] ;
721 code
= MapHook( TSD
, hook
);
722 assert (code
== RX_EXIT_GETENV
);
726 str
= str_of( TSD
, outdata
) ;
731 str
= MallocTSD( 1 ) ;
737 /* FIXME, FGC: The documentation says that the input of a PULL or TRCIN is
738 * undefined. Why do we provide a buffer?
740 rcode
= IfcDoExit( TSD
, code
, len
, str
, 0, NULL
, &retlen
, &retstr
) ;
742 if (rcode
==RX_HOOK_ERROR
)
743 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
744 else if (rcode
==RX_HOOK_GO_ON
)
746 else if (rcode
==RX_HOOK_NOPE
)
749 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
751 *indata
= wrapstring( TSD
, retstr
, retlen
) ;
752 FreeTSD( retstr
) ; /* retstr was always newly allocated */
753 #undef ILLEGAL_USE_SIZE
759 streng
*SubCom( const tsd_t
*TSD
, const streng
*command
, const streng
*envir
, int *rc
)
765 *rc
= IfcSubCmd( TSD
,
766 envir
? envir
->len
: RX_NO_STRING
,
767 envir
? envir
->value
: NULL
,
768 command
->len
, command
->value
, &tmplen
, &tmpptr
) ;
770 retval
= wrapstring( TSD
, tmpptr
, tmplen
) ;
776 /****************************************************************************
778 * JH 13/12/1999 Trying to satisfy both BUG031 and BUG022.
780 * BUG022 To make Direct setting of stems Direct and not Symbolic.
781 * - Added new parameter, "Code". Assumed values are RX_GETSVAR, and
782 * RX_GETVAR. They denote that the actiion is symbolic, or direct
784 * - if direct call getdirvalue()
787 * - if default value is being returned, uppercase the whole name for
788 * symbolics, and only the stem for directs. This should be a moot
789 * issue, as there is code in variable.c to return default values.
791 ****************************************************************************/
792 static int GetVariable( tsd_t
*TSD
, int Code
, int *Lengths
, char *Strings
[] )
794 const streng
*value
;
795 streng
*retval
, *varbl
;
798 varbl
= wrapstring( TSD
, Strings
[0], Lengths
[0] ) ;
800 assert(varbl
); /* FIXME, FGC: Shouldn't this better result in
804 if (!valid_var_symbol(varbl
))
806 Free_stringTSD( varbl
) ;
807 Lengths
[1] = RX_NO_STRING
;
808 return RX_CODE_INVNAME
;
811 rcode
= RX_CODE_OK
; /* default value */
812 if (Code
== RX_GETSVAR
)
813 value
= getvalue( TSD
, varbl
, 1 ) ;
815 value
= getdirvalue( TSD
, varbl
, 1 ) ;
817 retval
= Str_dupTSD(value
) ;
818 if (!var_was_found( TSD
))
820 if (Code
== RX_GETSVAR
)
821 retval
= Str_upper(retval
) ;
824 /* JH 13-12-99 If this is a direct variable, only uppercase the
827 for(i
=0;i
<retval
->len
&& '.' != retval
->value
[i
];i
++)
828 retval
->value
[i
] = (unsigned char) toupper(retval
->value
[i
]);
830 rcode
= RX_CODE_NOVALUE
;
833 Lengths
[1] = retval
->len
;
834 Strings
[1] = IfcAllocateMemory(retval
->len
+ 1);
835 /* Must be accessible by the application. */
837 memcpy(Strings
[1],retval
->value
,retval
->len
);
838 Strings
[1][retval
->len
] = '\0'; /* termination may help bogus
842 Free_stringTSD( retval
) ;
843 Free_stringTSD( varbl
) ;
847 /****************************************************************************
849 * JH 13/12/1999 Trying to satisfy both BUG031 and BUG022.
851 * BUG022 To make Direct setting of stems Direct and not Symbolic.
852 * - Added new parameter, "Code". Assumed values are RX_SETSVAR, and
853 * RX_SETVAR. They denote that the actiion is symbolic, or direct
855 * Until this point setting and dropping variables have been treated as
856 * the same. If there is a value, then it is a set, otherwise drop it.
857 * - if direct call setdirvalue()
858 * - if direct call drop_dirvar()
860 * - uppercase the whole name for symbolics, and only the stem for directs.
862 ****************************************************************************/
863 static int SetVariable(const tsd_t
*TSD
, int Code
, int *Lengths
, char *Strings
[] )
865 streng
*varbl
, *varname
, *value
;
868 varbl
= wrapstring( TSD
, Strings
[0], Lengths
[0] ) ;
870 assert(varbl
); /* FIXME, FGC: Shouldn't this better result in
874 if (Code
== RX_SETSVAR
)
875 varname
= Str_upper(Str_dupTSD(varbl
)) ;
878 varname
= Str_dupTSD(varbl
) ;
879 for (i
=0;i
<varname
->len
&& '.' != varname
->value
[i
];i
++)
880 varname
->value
[i
] = (unsigned char) toupper(varname
->value
[i
]);
882 Free_stringTSD( varbl
) ;
883 varbl
= NULL
; /* For debugging purpose only */
885 if (!valid_var_symbol(varname
))
887 Free_stringTSD( varname
) ;
888 return RX_CODE_INVNAME
;
891 value
= wrapstring( TSD
, Strings
[1], Lengths
[1] ) ;
893 rcode
= RX_CODE_OK
; /* default value */
896 if (Code
== RX_SETSVAR
)
897 setvalue( TSD
, varname
, value
) ;
899 setdirvalue( TSD
, varname
, value
) ;
903 if (Code
== RX_SETSVAR
)
904 drop_var( TSD
, varname
) ;
906 drop_dirvar( TSD
, varname
) ;
908 if (!var_was_found( TSD
))
909 rcode
= RX_CODE_NOVALUE
;
911 Free_stringTSD( varname
) ;
915 static int handle_version( int *Length
, char **String
)
917 *Length
= strlen(PARSE_VERSION_STRING
) ;
918 *String
= PARSE_VERSION_STRING
;
923 static int handle_queue( int *Length
, char **String
)
926 *String
= "default" ;
933 /****************************************************************************
937 * BUG022 To make Direct setting of stems Direct and not Symbolic.
938 * - Added checks for the direct variable functions RX_GETVAR and RX_SETVAR.
942 ****************************************************************************/
943 int IfcVarPool( tsd_t
*TSD
, int Code
, int *Lengths
, char *Strings
[] )
947 if (Code
==RX_GETSVAR
||Code
==RX_GETVAR
)
948 rc
= GetVariable( TSD
, Code
, Lengths
, Strings
) ;
949 else if (Code
==RX_SETSVAR
||Code
==RX_SETVAR
)
950 rc
= SetVariable( TSD
, Code
, Lengths
, Strings
) ;
951 else if (Code
==RX_NEXTVAR
)
952 rc
= get_next_var( TSD
, Lengths
, Strings
) ;
953 else if (Code
==RX_CODE_VERSION
)
954 rc
= handle_version( Lengths
, Strings
) ;
955 else if (Code
==RX_CODE_SOURCE
)
956 rc
= handle_source( TSD
, Lengths
, Strings
) ;
957 else if (Code
==RX_CODE_QUEUE
)
958 rc
= handle_queue( Lengths
, Strings
) ;
959 else if (Code
==RX_CODE_PARAMS
)
960 rc
= handle_no_of_params( TSD
, Lengths
, Strings
) ;
961 else if (Code
==RX_CODE_PARAM
)
962 rc
= handle_param( TSD
, Lengths
, Strings
) ;
964 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
970 /* FGC, FIXME: IfcRegFunc never returns a code for RXFUNC_DUP! */
971 int IfcRegFunc( tsd_t
*TSD
, const char *Name
)
977 name
= Str_upper( Str_creTSD( Name
) );
978 rc
= addfunc( TSD
, name
, 1 ) ;
980 Free_stringTSD(name
);
983 return RX_CODE_NOMEM
;
988 int IfcDelFunc( tsd_t
*TSD
, const char *Name
)
994 name
= Str_upper( Str_creTSD( Name
) );
995 retval
= rex_rxfuncdlldrop(TSD
, name
);
996 Free_stringTSD(name
);
1000 int IfcQueryFunc( tsd_t
*TSD
, const char *Name
)
1006 name
= Str_upper( Str_creTSD( Name
) );
1007 retval
= rex_rxfuncdllquery(TSD
, name
);
1008 Free_stringTSD(name
);
1012 /* You are not allowed to use TSD or __regina_get_tsd() here! */
1013 void *IfcAllocateMemory( unsigned long size
)
1016 #if defined( WIN32 )
1017 /* We now use the Virtual-functions instead of Global... */
1018 ret
= VirtualAlloc( NULL
, size
, MEM_COMMIT
, PAGE_READWRITE
) ;
1020 #elif defined( __EMX__ ) && !defined(DOS)
1021 if (_osmode
== OS2_MODE
)
1023 if ( ( BOOL
)DosAllocMem( &ret
, size
, fPERM
|PAG_COMMIT
) )
1028 else /* DOS or something else */
1030 ret
= (void *)malloc( size
);
1033 #elif defined( OS2 )
1034 if ( ( BOOL
)DosAllocMem( &ret
, size
, fPERM
|PAG_COMMIT
) )
1039 ret
= (void *)malloc( size
);
1044 /* You are not allowed to use TSD or __regina_get_tsd() here! */
1045 unsigned long IfcFreeMemory( void *ptr
)
1047 #if defined( WIN32 )
1048 /* In opposite to most(!) of the documentation from Microsoft we shouldn't
1049 * decommit and release together. This won't work at least under NT4SP6a.
1050 * We can first decommit and then release or release at once. FGC.
1052 VirtualFree( ptr
, 0, MEM_RELEASE
) ;
1053 #elif defined( __EMX__ ) && !defined(DOS)
1054 if (_osmode
== OS2_MODE
)
1056 else /* DOS or something else */
1058 #elif defined( OS2 )
1067 /* Removes ct->Strings and ct->Lengths AND ct->ExternalName. */
1068 static void RemoveParams(const tsd_t
*TSD
)
1075 if ( ct
->Strings
&& ct
->Lengths
)
1077 for (i
= 0;i
< ct
->StringsCount
;i
++) /* The last one is always NULL */
1079 if ((ct
->Lengths
[i
] != RX_NO_STRING
) &&
1080 (ct
->Strings
[i
] != NULL
))
1081 FreeTSD( ct
->Strings
[i
] );
1086 FreeTSD( ct
->Lengths
) ;
1088 FreeTSD( ct
->Strings
) ;
1089 if ( ct
->ExternalName
)
1090 FreeTSD( ct
->ExternalName
) ;
1092 ct
->StringsCount
= -1;
1095 ct
->ExternalName
= NULL
;
1098 /* Creates (possibly after a removal of old values) ct->Strings and ct->Lengths
1099 * from the given parms. One hidden NULL string is appended.
1101 static void MakeParams(const tsd_t
*TSD
, cparamboxptr parms
)
1104 cparamboxptr p
=NULL
;
1109 /* Cleanup the old parameters before we set StringsCount */
1112 ct
->StringsCount
= 0; /* This is the default in case of unused parameters */
1113 /* Detect the index of the last valid parameter */
1114 for (i
=0,p
=parms
; p
; p
=p
->next
,i
++)
1117 ct
->StringsCount
=i
+1 ;
1120 /* add one NULL string at the end */
1121 ct
->Lengths
= MallocTSD( sizeof(int) * (ct
->StringsCount
+1) ) ;
1122 ct
->Strings
= MallocTSD( sizeof(char*) * (ct
->StringsCount
+1) ) ;
1124 for (i
=0,p
=parms
; i
< ct
->StringsCount
; p
=p
->next
,i
++)
1128 ct
->Lengths
[i
] = Str_len( p
->value
) ;
1129 ct
->Strings
[i
] = str_of( TSD
, p
->value
);
1133 ct
->Lengths
[i
] = RX_NO_STRING
;
1134 ct
->Strings
[i
] = NULL
;
1138 /* Provide a hidden NULL string at the end */
1139 ct
->Lengths
[ct
->StringsCount
] = RX_NO_STRING
;
1140 ct
->Strings
[ct
->StringsCount
] = NULL
;
1143 /* do_an_external calls IfcExecFunc with the appropriate parameters. Basically
1144 * it wraps the parameters. Either ExeName or box must be NULL.
1146 static streng
*do_an_external( tsd_t
*TSD
,
1147 const streng
*ExeName
,
1148 const struct library_func
*box
,
1154 char *RetString
=NULL
;
1160 volatile char *tmpExternalName
; /* used to save ct->ExternalName */
1165 MakeParams( TSD
, parms
) ;
1168 ct
->ExternalName
= str_of( TSD
, ExeName
);
1169 tmpExternalName
= tmpstr_of( TSD
, ExeName
);
1174 ct
->ExternalName
= str_of( TSD
, box
->name
);
1175 tmpExternalName
= tmpstr_of( TSD
, box
->name
);
1179 rc
= IfcExecFunc( TSD
, Func
, ct
->ExternalName
,
1180 ct
->StringsCount
, ct
->Lengths
, ct
->Strings
,
1181 &RetLength
, &RetString
, &RC
, exitonly
, called
);
1183 RemoveParams( TSD
) ;
1189 case ERR_ROUTINE_NOT_FOUND
:
1190 exiterror( ERR_ROUTINE_NOT_FOUND
, 1, tmpExternalName
);
1200 retval
= Str_makeTSD( RetLength
) ;
1201 memcpy( retval
->value
, RetString
, RetLength
) ;
1202 FreeTSD( RetString
);
1203 retval
->len
= RetLength
;
1209 streng
*do_an_external_exe( tsd_t
*TSD
, const streng
*name
, cparamboxptr parms
, char exitonly
, char called
)
1213 return( do_an_external( TSD
, name
, NULL
, parms
, exitonly
, called
) ) ;
1216 streng
*do_an_external_dll( tsd_t
*TSD
, const void *vbox
, cparamboxptr parms
, char called
)
1220 return( do_an_external( TSD
, NULL
, vbox
, parms
, 0, called
) ) ;
1223 int IfcCreateQueue( tsd_t
*TSD
, const char *qname
, const int qlen
, char *data
, unsigned long *dupflag
, unsigned long buflen
)
1225 streng
*queuename
=NULL
,*strdata
;
1230 queuename
= Str_makeTSD( qlen
) ;
1231 memcpy( queuename
->value
, qname
, qlen
) ;
1232 queuename
->len
= qlen
;
1234 rc
= create_queue( TSD
, queuename
, &strdata
);
1236 if ( rc
== 0 || rc
== 1 )
1239 * Return the new queue name
1241 memcpy( data
, strdata
->value
, max( strdata
->len
, (int) buflen
) - 1 );
1242 *(data
+(max( strdata
->len
, (int) buflen
) - 1)) = '\0';
1244 * If the returned queue name is different to
1245 * the one we requested, set the dupflag
1255 if ( queuename
) FreeTSD( queuename
);
1259 int IfcDeleteQueue( tsd_t
*TSD
, const char *qname
, const int qlen
)
1264 queuename
= Str_makeTSD( qlen
) ;
1265 memcpy( queuename
->value
, qname
, qlen
) ;
1266 queuename
->len
= qlen
;
1267 rc
= delete_queue( TSD
, queuename
);
1268 FreeTSD( queuename
);
1272 int IfcQueryQueue( tsd_t
*TSD
, const char *qname
, const int qlen
, unsigned long *count
)
1277 queuename
= Str_makeTSD( qlen
) ;
1278 memcpy( queuename
->value
, qname
, qlen
) ;
1279 queuename
->len
= qlen
;
1280 rc
= lines_in_stack( TSD
, queuename
);
1285 FreeTSD( queuename
);
1289 int IfcAddQueue( tsd_t
*TSD
, const char *qname
, const int qlen
, const char *data
, const int datalen
, unsigned long addlifo
)
1291 streng
*queuename
,*strdata
;
1294 queuename
= Str_makeTSD( qlen
) ;
1295 memcpy( queuename
->value
, qname
, qlen
) ;
1296 queuename
->len
= qlen
;
1298 strdata
= Str_makeTSD( datalen
) ;
1299 memcpy( strdata
->value
, data
, datalen
) ;
1300 strdata
->len
= datalen
;
1303 rc
= stack_lifo( TSD
, strdata
, queuename
);
1305 rc
= stack_fifo( TSD
, strdata
, queuename
);
1306 FreeTSD( queuename
);
1311 int IfcPullQueue( tsd_t
*TSD
, const char *qname
, const int qlen
, char **data
, int *datalen
, unsigned long waitforline
)
1313 streng
*queuename
,*strdata
;
1316 queuename
= Str_makeTSD( qlen
) ;
1317 memcpy( queuename
->value
, qname
, qlen
) ;
1318 queuename
->len
= qlen
;
1320 strdata
= popline( TSD
, queuename
, &rc
, waitforline
);
1322 if ( strdata
== NULL
)
1332 *data
= strdata
->value
;
1333 *datalen
= strdata
->len
;
1335 FreeTSD( queuename
);