2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
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.
38 double pow( double, double ) ;
41 #if defined(HAVE_PUTENV) && defined(FIX_PROTOS) && defined(ultrix)
45 #define UPPERLETTER(a) ((((a)&0xdf)>='A')&&(((a)&0xdf)<='Z'))
46 #define NUMERIC(a) (((a)>='0')&&((a)<='9'))
48 static const char *WeekDays
[] = { "Sunday", "Monday", "Tuesday", "Wednesday",
49 "Thursday", "Friday", "Saturday" } ;
50 const char *months
[] = { "January", "February", "March", "April", "May",
51 "June", "July", "August", "September", "October",
52 "November", "December" } ;
55 struct envirlist
*next
;
59 typedef struct { /* bui_tsd: static variables of this module (thread-safe) */
60 struct envirlist
* first_envirvar
;
61 lineboxptr srcline_ptr
; /* std_sourceline() */
62 lineboxptr srcline_first
; /* std_sourceline() */
63 int srcline_lineno
; /* std_sourceline() */
65 } bui_tsd_t
; /* thread-specific but only needed by this module. see
69 /* init_builtin initializes the module.
70 * Currently, we set up the thread specific data.
71 * The function returns 1 on success, 0 if memory is short.
73 int init_builtin( tsd_t
*TSD
)
77 if (TSD
->bui_tsd
!= NULL
)
80 if ( ( TSD
->bui_tsd
= MallocTSD( sizeof(bui_tsd_t
) ) ) == NULL
)
82 bt
= (bui_tsd_t
*)TSD
->bui_tsd
;
83 memset( bt
, 0, sizeof(bui_tsd_t
) ); /* correct for all values */
85 #if defined(HAVE_RANDOM)
86 srandom((int) (time((time_t *)0)+getpid())%(3600*24)) ;
88 srand((unsigned) (time((time_t *)0)+getpid())%(3600*24)) ;
93 static int contained_in( const char *first
, const char *fend
, const char *second
, const char *send
)
95 * Determines if one string exists in another string. Search is done
100 * Skip over any leading spaces in the search string
102 for (; (first
<fend
)&&(rx_isspace(*first
)); first
++)
107 * Trim any trailing spaces in the search string
109 for (; (first
<fend
)&&(rx_isspace(*(fend
-1))); fend
--)
114 * Skip over any leading spaces in the searched string
116 for (; (second
<send
)&&(rx_isspace(*second
)); second
++)
121 * Trim any trailing spaces in the searched string
123 for (; (second
<send
)&&(rx_isspace(*(send
-1))); send
--)
128 * If the length of the search string is less than the string to
129 * search we won't find a match
131 if (fend
-first
> send
-second
)
134 for (; (first
<fend
); )
136 for (; (first
<fend
)&&(!rx_isspace(*first
)); first
++, second
++)
138 if ((*first
)!=(*second
))
142 if ((second
<send
)&&(!rx_isspace(*second
)))
148 for (; (first
<fend
)&&(rx_isspace(*first
)); first
++)
152 for (; (second
<send
)&&(rx_isspace(*second
)); second
++)
162 streng
*std_wordpos( tsd_t
*TSD
, cparamboxptr parms
)
164 streng
*seek
=NULL
, *target
=NULL
;
165 char *sptr
=NULL
, *tptr
=NULL
, *end
=NULL
, *send
=NULL
;
168 checkparam( parms
, 2, 3 , "WORDPOS" ) ;
169 seek
= parms
->value
;
170 target
= parms
->next
->value
;
171 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
172 start
= atopos( TSD
, parms
->next
->next
->value
, "WORDPOS", 3 ) ;
174 end
= target
->value
+ Str_len(target
) ;
175 /* Then lets position right in the target */
176 for (tptr
=target
->value
; (tptr
<end
) && rx_isspace(*tptr
) ; tptr
++) /* FGC: ordered */
180 for (res
=1; (res
<start
); res
++)
182 for (; (tptr
<end
)&&(!rx_isspace(*tptr
)); tptr
++ )
186 for (; (tptr
<end
) && rx_isspace(*tptr
); tptr
++ )
192 send
= seek
->value
+ Str_len(seek
) ;
193 for (sptr
=seek
->value
; (sptr
<send
) && rx_isspace(*sptr
); sptr
++)
199 for ( ; (sptr
<send
)&&(tptr
<end
); )
201 if (contained_in( sptr
, send
, tptr
, end
))
204 for (; (tptr
<end
)&&(!rx_isspace(*tptr
)); tptr
++)
208 for (; (tptr
<end
)&&(rx_isspace(*tptr
)); tptr
++)
215 if ((sptr
>=send
)||((sptr
<send
)&&(tptr
>=end
)))
218 return int_to_streng( TSD
, res
) ;
222 streng
*std_wordlength( tsd_t
*TSD
, cparamboxptr parms
)
225 streng
*string
=NULL
;
226 char *ptr
=NULL
, *end
=NULL
;
228 checkparam( parms
, 2, 2 , "WORDLENGTH" ) ;
229 string
= parms
->value
;
230 number
= atopos( TSD
, parms
->next
->value
, "WORDLENGTH", 2 ) ;
232 end
= (ptr
=string
->value
) + Str_len(string
) ;
233 for (; (ptr
<end
) && rx_isspace(*ptr
); ptr
++)
237 for (i
=0; i
<number
-1; i
++)
239 for (; (ptr
<end
)&&(!rx_isspace(*ptr
)); ptr
++)
243 for (; (ptr
<end
)&&(rx_isspace(*ptr
)); ptr
++ )
249 for (i
=0; (((ptr
+i
)<end
)&&(!rx_isspace(*(ptr
+i
)))); i
++)
253 return (int_to_streng( TSD
,i
)) ;
258 streng
*std_wordindex( tsd_t
*TSD
, cparamboxptr parms
)
261 streng
*string
=NULL
;
262 char *ptr
=NULL
, *end
=NULL
;
264 checkparam( parms
, 2, 2 , "WORDINDEX" ) ;
265 string
= parms
->value
;
266 number
= atopos( TSD
, parms
->next
->value
, "WORDINDEX", 2 ) ;
268 end
= (ptr
=string
->value
) + Str_len(string
) ;
269 for (; (ptr
<end
) && rx_isspace(*ptr
); ptr
++)
273 for (i
=0; i
<number
-1; i
++)
275 for (; (ptr
<end
)&&(!rx_isspace(*ptr
)); ptr
++)
279 for (; (ptr
<end
)&&(rx_isspace(*ptr
)); ptr
++)
285 return ( int_to_streng( TSD
, (ptr
<end
) ? (ptr
- string
->value
+ 1 ) : 0) ) ;
289 streng
*std_delword( tsd_t
*TSD
, cparamboxptr parms
)
291 char *rptr
=NULL
, *cptr
=NULL
, *end
=NULL
;
292 streng
*string
=NULL
;
293 int length
=(-1), start
=0, i
=0 ;
295 checkparam( parms
, 2, 3 , "DELWORD" ) ;
296 string
= Str_dupTSD(parms
->value
) ;
297 start
= atopos( TSD
, parms
->next
->value
, "DELWORD", 2 ) ;
298 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
299 length
= atozpos( TSD
, parms
->next
->next
->value
, "DELWORD", 3 ) ;
301 end
= (cptr
=string
->value
) + Str_len(string
) ;
302 for (; (cptr
<end
) && rx_isspace(*cptr
); cptr
++ )
306 for (i
=0; i
<(start
-1); i
++)
308 for (; (cptr
<end
)&&(!rx_isspace(*cptr
)); cptr
++)
312 for (; (cptr
<end
) && rx_isspace(*cptr
); cptr
++)
319 for (i
=0; (i
<(length
))||((length
==(-1))&&(cptr
<end
)); i
++)
321 for (; (cptr
<end
)&&(!rx_isspace(*cptr
)); cptr
++ )
325 for (; (cptr
<end
) && rx_isspace(*cptr
); cptr
++ )
333 for (; (cptr
<end
)&&(!rx_isspace(*cptr
)); *(rptr
++) = *(cptr
++))
337 for (; (cptr
<end
) && rx_isspace(*cptr
); *(rptr
++) = *(cptr
++))
343 string
->len
= (rptr
- string
->value
) ;
348 streng
*std_xrange( tsd_t
*TSD
, cparamboxptr parms
)
350 int start
=0, stop
=0xff, i
=0, length
=0 ;
351 streng
*result
=NULL
;
353 checkparam( parms
, 0, 2 , "XRANGE" ) ;
355 start
= (unsigned char) getonechar( TSD
, parms
->value
, "XRANGE", 1 ) ;
358 && ( parms
->next
->value
) )
359 stop
= (unsigned char) getonechar( TSD
, parms
->next
->value
, "XRANGE", 2 ) ;
361 length
= stop
- start
+ 1 ;
363 length
= 256 + length
;
365 result
= Str_makeTSD( length
) ;
366 for (i
=0; (i
<length
); i
++)
370 result
->value
[i
] = (char) start
++ ;
372 /* result->value[i] = (char) stop ; */
379 streng
*std_lastpos( tsd_t
*TSD
, cparamboxptr parms
)
381 int res
=0, start
=0, i
=0, j
=0, nomore
=0 ;
382 streng
*needle
=NULL
, *heystack
=NULL
;
384 checkparam( parms
, 2, 3 , "LASTPOS" ) ;
385 needle
= parms
->value
;
386 heystack
= parms
->next
->value
;
387 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
388 start
= atopos( TSD
, parms
->next
->next
->value
, "LASTPOS", 3 ) ;
390 start
= Str_len( heystack
) ;
392 nomore
= Str_len( needle
) ;
393 if (start
>Str_len(heystack
))
394 start
= Str_len( heystack
) ;
401 for (i
=start
-nomore
; i
>=0; i
-- )
404 * FGC: following loop was "<=nomore"
406 for (j
=0; (j
<nomore
)&&(needle
->value
[j
]==heystack
->value
[i
+j
]);j
++) ;
414 return (int_to_streng( TSD
,res
)) ;
419 streng
*std_pos( tsd_t
*TSD
, cparamboxptr parms
)
422 streng
*needle
=NULL
, *heystack
=NULL
;
423 checkparam( parms
, 2, 3 , "POS" ) ;
425 needle
= parms
->value
;
426 heystack
= parms
->next
->value
;
427 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
428 start
= atopos( TSD
, parms
->next
->next
->value
, "POS", 3 ) ;
432 || (start
>heystack
->len
))
436 res
= bmstrstr(heystack
, start
-1, needle
, 0) + 1 ;
439 return (int_to_streng( TSD
, res
) ) ;
444 streng
*std_subword( tsd_t
*TSD
, cparamboxptr parms
)
446 int i
=0, length
=0, start
=0 ;
447 char *cptr
=NULL
, *eptr
=NULL
, *cend
=NULL
;
448 streng
*string
=NULL
, *result
=NULL
;
450 checkparam( parms
, 2, 3 , "SUBWORD" ) ;
451 string
= parms
->value
;
452 start
= atopos( TSD
, parms
->next
->value
, "SUBWORD", 2 ) ;
453 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
454 length
= atozpos( TSD
, parms
->next
->next
->value
, "SUBWORD", 3 ) ;
458 cptr
= string
->value
;
459 cend
= cptr
+ Str_len(string
) ;
460 for (i
=1; i
<start
; i
++)
462 for ( ; (cptr
<cend
)&&(rx_isspace(*cptr
)); cptr
++)
466 for ( ; (cptr
<cend
)&&(!rx_isspace(*cptr
)); cptr
++)
471 for ( ; (cptr
<cend
)&&(rx_isspace(*cptr
)); cptr
++)
479 for( i
=0; (i
<length
); i
++ )
481 for (;(eptr
<cend
)&&(rx_isspace(*eptr
)); eptr
++) /* wount hit 1st time */
485 for (;(eptr
<cend
)&&(!rx_isspace(*eptr
)); eptr
++)
494 /* fixes bug 1113373 */
495 while ((eptr
> cptr
) && rx_isspace(*(eptr
-1)))
500 result
= Str_makeTSD( eptr
-cptr
) ;
501 memcpy( result
->value
, cptr
, (eptr
-cptr
) ) ;
502 result
->len
= (eptr
-cptr
) ;
509 streng
*std_symbol( tsd_t
*TSD
, cparamboxptr parms
)
513 checkparam( parms
, 1, 1 , "SYMBOL" ) ;
515 type
= valid_var_symbol( parms
->value
) ;
516 if (type
==SYMBOL_BAD
)
517 return Str_creTSD("BAD") ;
519 if ( ( type
!= SYMBOL_CONSTANT
) && ( type
!= SYMBOL_NUMBER
) )
521 assert(type
==SYMBOL_STEM
||type
==SYMBOL_SIMPLE
||type
==SYMBOL_COMPOUND
);
522 if (isvariable(TSD
, parms
->value
))
523 return Str_creTSD("VAR") ;
526 return Str_creTSD("LIT") ;
530 #if defined(TRACEMEM)
531 static void mark_envirvars( const tsd_t
*TSD
)
533 struct envirlist
*ptr
=NULL
;
536 bt
= (bui_tsd_t
*) TSD
->bui_tsd
;
537 for (ptr
=bt
->first_envirvar
; ptr
; ptr
=ptr
->next
)
539 markmemory( ptr
, TRC_STATIC
) ;
540 markmemory( ptr
->ptr
, TRC_STATIC
) ;
544 static void add_new_env( const tsd_t
*TSD
, streng
*ptr
)
546 struct envirlist
*newElem
=NULL
;
549 bt
= (bui_tsd_t
*) TSD
->bui_tsd
;
550 newElem
= (struct envirlist
*) MallocTSD( sizeof( struct envirlist
)) ;
551 newElem
->next
= bt
->first_envirvar
;
554 if (!bt
->first_envirvar
)
555 regmarker( TSD
, mark_envirvars
) ;
557 bt
->first_envirvar
= newElem
;
562 * ext_pool_value processes the request of the BIF value() and putenv() for the external
563 * variable pool known as the "environment" in terms of the C library.
565 * name has to be a '\0'-terminated streng, value is either NULL or the
566 * new content of the variable called name.
568 streng
*ext_pool_value( tsd_t
*TSD
, streng
*name
, streng
*value
,
574 (env
= env
); /* Make the compiler happy */
577 * Get the current value from the exit if we have one, or from the
578 * environment directly if not...
580 if ( TSD
->systeminfo
->hooks
& HOOK_MASK( HOOK_GETENV
) )
581 ok
= hookup_input_output( TSD
, HOOK_GETENV
, name
, &retval
);
584 if ( ok
== HOOK_GO_ON
)
587 * Either there was no exit handler, or the exit handler didn't
588 * handle the GETENV. Get the environment variable directly from
591 retval
= vms_resolv_symbol( TSD
, name
, value
, env
);
594 exiterror( ERR_SYSTEM_FAILURE
, 1, "No support for setting an environment variable" );
596 * FIXME: What happens if value is set and HOOK_GO_ON isn't set?
597 * What happens with the different Pools SYMBOL, SYSTEM, LOGICAL?
601 if ( ok
== HOOK_GO_ON
)
603 char *val
= mygetenv( TSD
, name
->value
, NULL
, 0 );
606 retval
= Str_creTSD( val
);
612 * retval is prepared. Check for setting a new value.
617 * We are setting a value in the external environment
620 if ( TSD
->restricted
)
621 exiterror( ERR_RESTRICTED
, 2, "VALUE", 2 );
623 if ( TSD
->systeminfo
->hooks
& HOOK_MASK( HOOK_SETENV
) )
624 ok
= hookup_output2( TSD
, HOOK_SETENV
, name
, value
);
626 if ( ok
== HOOK_GO_ON
)
628 # if defined(HAVE_MY_WIN32_SETENV)
629 streng
*strvalue
= Str_dupstrTSD( value
);
631 TSD
->OS
->setenv(name
->value
, strvalue
->value
);
632 Free_stringTSD( strvalue
);
633 # elif defined(HAVE_SETENV)
634 streng
*strvalue
= Str_dupstrTSD( value
);
636 setenv(name
->value
, strvalue
->value
, 1 );
637 Free_stringTSD( strvalue
);
638 # elif defined(HAVE_PUTENV)
640 * Note: we don't release the allocated memory, because the runtime
641 * system might use the pointer itself, not the content.
642 * (See glibc's documentation)
644 streng
*newstr
= Str_makeTSD( Str_len( name
) + Str_len( value
) + 2 );
646 Str_catTSD( newstr
, name
);
647 Str_catstrTSD( newstr
, "=" );
648 Str_catTSD( newstr
, value
);
649 newstr
->value
[Str_len(newstr
)] = '\0';
651 putenv( newstr
->value
);
653 add_new_env( TSD
, newstr
);
656 exiterror( ERR_SYSTEM_FAILURE
, 1, "No support for setting an environment variable" );
657 # endif /* HAVE_PUTENV */
667 * FIXME: We are not throwing 40.36, but I'm not sure we should at all.
669 streng
*std_value( tsd_t
*TSD
, cparamboxptr parms
)
671 streng
*name
,*retval
;
672 streng
*value
=NULL
,*env
=NULL
;
675 checkparam( parms
, 1, 3 , "VALUE" );
676 name
= Str_dupstrTSD( parms
->value
);
680 value
= parms
->next
->value
;
681 if ( parms
->next
->next
)
682 env
= parms
->next
->next
->value
;
688 if ( ( ( i
== 6 ) && ( memcmp( env
->value
, "SYSTEM", 6 ) == 0 ) )
689 || ( ( i
== 14 ) && ( memcmp( env
->value
, "OS2ENVIRONMENT", 14 ) == 0 ) )
690 || ( ( i
== 11 ) && ( memcmp( env
->value
, "ENVIRONMENT", 11 ) == 0 ) ) )
692 retval
= ext_pool_value( TSD
, name
, value
, env
);
693 Free_stringTSD( name
);
694 if ( retval
== NULL
)
695 retval
= nullstringptr();
700 pool
= streng_to_int( TSD
, env
, &err
);
703 * Accept a builtin pool if it is a number >= 0.
707 if ( pool
> TSD
->currlevel
->pool
)
710 exiterror( ERR_INCORRECT_CALL
, 37, "VALUE", tmpstr_of( TSD
, env
) );
714 * Internal variable pool; ie Rexx variables. According to ANSI standard
715 * need to uppercase the variable name first.
717 if ( !valid_var_symbol( name
) )
719 Free_stringTSD( name
);
720 exiterror( ERR_INCORRECT_CALL
, 26, "VALUE", tmpstr_of( TSD
, parms
->value
) );
724 retval
= Str_dupTSD( get_it_anyway( TSD
, name
, pool
) );
726 setvalue( TSD
, name
, Str_dupTSD( value
), pool
);
727 Free_stringTSD( name
);
733 streng
*std_abs( tsd_t
*TSD
, cparamboxptr parms
)
735 checkparam( parms
, 1, 1 , "ABS" ) ;
736 return str_abs( TSD
, parms
->value
) ;
740 streng
*std_condition( tsd_t
*TSD
, cparamboxptr parms
)
743 streng
*result
=NULL
;
748 checkparam( parms
, 0, 1 , "CONDITION" ) ;
750 if (parms
&&parms
->value
)
751 opt
= getoptionchar( TSD
, parms
->value
, "CONDITION", 1, "CEIDS", "" ) ;
754 sig
= getsigs(TSD
->currlevel
) ;
759 result
= Str_creTSD( signalnames
[sig
->type
] ) ;
763 result
= Str_creTSD( (sig
->invoke
) ? "SIGNAL" : "CALL" ) ;
768 result
= Str_dupTSD( sig
->descr
) ;
773 sprintf(buf
, "%d.%d", sig
->rc
, sig
->subrc
);
775 sprintf(buf
, "%d", sig
->rc
);
776 result
= Str_creTSD( buf
) ;
780 traps
= gettraps( TSD
, TSD
->currlevel
) ;
781 if (traps
[sig
->type
].delayed
)
782 result
= Str_creTSD( "DELAY" ) ;
784 result
= Str_creTSD( (traps
[sig
->type
].on_off
) ? "ON" : "OFF" ) ;
788 /* should not get here */
793 result
= nullstringptr() ;
799 streng
*std_format( tsd_t
*TSD
, cparamboxptr parms
)
801 streng
*number
=NULL
;
802 int before
=(-1), after
=(-1) ;
803 int esize
=(-1), trigger
=(-1) ;
806 checkparam( parms
, 1, 5, "FORMAT" ) ;
807 number
= (ptr
=parms
)->value
;
809 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
810 before
= atozpos( TSD
, ptr
->value
, "FORMAT", 2 ) ;
812 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
813 after
= atozpos( TSD
, ptr
->value
, "FORMAT", 3 ) ;
815 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
816 esize
= atozpos( TSD
, ptr
->value
, "FORMAT", 4 ) ;
818 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
819 trigger
= atozpos( TSD
, ptr
->value
, "FORMAT", 5 ) ;
821 return str_format( TSD
, number
, before
, after
, esize
, trigger
) ;
826 streng
*std_overlay( tsd_t
*TSD
, cparamboxptr parms
)
828 streng
*newstr
=NULL
, *oldstr
=NULL
, *retval
=NULL
;
830 int length
=0, spot
=0, oldlen
=0, i
=0, j
=0, k
=0 ;
831 paramboxptr tmpptr
=NULL
;
833 checkparam( parms
, 2, 5, "OVERLAY" ) ;
834 newstr
= parms
->value
;
835 oldstr
= parms
->next
->value
;
836 length
= Str_len(newstr
) ;
837 oldlen
= Str_len(oldstr
) ;
838 if (parms
->next
->next
)
840 tmpptr
= parms
->next
->next
;
841 if (parms
->next
->next
->value
)
842 spot
= atopos( TSD
, tmpptr
->value
, "OVERLAY", 3 ) ;
846 tmpptr
= tmpptr
->next
;
848 length
= atozpos( TSD
, tmpptr
->value
, "OVERLAY", 4 ) ;
849 if ((tmpptr
->next
)&&(tmpptr
->next
->value
))
850 padch
= getonechar( TSD
, tmpptr
->next
->value
, "OVERLAY", 5 ) ;
854 retval
= Str_makeTSD(((spot
+length
-1>oldlen
)?spot
+length
-1:oldlen
)) ;
855 for (j
=i
=0;(i
<spot
-1)&&(i
<oldlen
);retval
->value
[j
++]=oldstr
->value
[i
++]) ;
856 for (;j
<spot
-1;retval
->value
[j
++]=padch
) ;
857 for (k
=0;(k
<length
)&&(Str_in(newstr
,k
));retval
->value
[j
++]=newstr
->value
[k
++])
860 for (;k
++<length
;retval
->value
[j
++]=padch
) if (oldlen
>i
) i
++ ;
861 for (;oldlen
>i
;retval
->value
[j
++]=oldstr
->value
[i
++]) ;
867 streng
*std_insert( tsd_t
*TSD
, cparamboxptr parms
)
869 streng
*newstr
=NULL
, *oldstr
=NULL
, *retval
=NULL
;
871 int length
=0, spot
=0, oldlen
=0, i
=0, j
=0, k
=0 ;
872 paramboxptr tmpptr
=NULL
;
874 checkparam( parms
, 2, 5, "INSERT" ) ;
875 newstr
= parms
->value
;
876 oldstr
= parms
->next
->value
;
877 length
= Str_len(newstr
) ;
878 oldlen
= Str_len(oldstr
) ;
879 if (parms
->next
->next
)
881 tmpptr
= parms
->next
->next
;
882 if (parms
->next
->next
->value
)
883 spot
= atozpos( TSD
, tmpptr
->value
, "INSERT", 3 ) ;
887 tmpptr
= tmpptr
->next
;
889 length
= atozpos( TSD
, tmpptr
->value
, "INSERT", 4 ) ;
890 if ((tmpptr
->next
)&&(tmpptr
->next
->value
))
891 padch
= getonechar( TSD
, tmpptr
->next
->value
, "INSERT", 5) ;
895 retval
= Str_makeTSD(length
+((spot
>oldlen
)?spot
:oldlen
)) ;
896 for (j
=i
=0;(i
<spot
)&&(oldlen
>i
);retval
->value
[j
++]=oldstr
->value
[i
++]) ;
897 for (;j
<spot
;retval
->value
[j
++]=padch
) ;
898 for (k
=0;(k
<length
)&&(Str_in(newstr
,k
));retval
->value
[j
++]=newstr
->value
[k
++]) ;
899 for (;k
++<length
;retval
->value
[j
++]=padch
) ;
900 for (;oldlen
>i
;retval
->value
[j
++]=oldstr
->value
[i
++]) ;
907 streng
*std_time( tsd_t
*TSD
, cparamboxptr parms
)
910 time_t unow
=0, now
=0, rnow
=0 ;
911 long usec
=0L, sec
=0L, timediff
=0L ;
915 /* Fix a bug by checker: */
916 streng
*answer
=Str_makeTSD( 64 ) ;
918 streng
*answer
=Str_makeTSD( 50 ) ;
920 streng
*supptime
=NULL
;
921 streng
*str_suppformat
=NULL
;
922 char suppformat
= 'N' ;
923 paramboxptr tmpptr
=NULL
;
924 struct tm tmdata
, *tmptr
;
926 checkparam( parms
, 0, 3 , "TIME" ) ;
927 if ((parms
)&&(parms
->value
))
928 format
= getoptionchar( TSD
, parms
->value
, "TIME", 1, "CEHLMNORS", "JT" ) ;
932 tmpptr
= parms
->next
;
933 if (parms
->next
->value
)
934 supptime
= tmpptr
->value
;
938 tmpptr
= tmpptr
->next
;
941 str_suppformat
= tmpptr
->value
;
942 suppformat
= getoptionchar( TSD
, tmpptr
->value
, "TIME", 3, "CHLMNS", "T" ) ;
951 if (TSD
->currentnode
->now
)
953 now
= TSD
->currentnode
->now
->sec
;
954 unow
= TSD
->currentnode
->now
->usec
;
958 getsecs(&now
, &unow
) ;
959 TSD
->currentnode
->now
= (rexx_time
*)MallocTSD( sizeof( rexx_time
) ) ;
960 TSD
->currentnode
->now
->sec
= now
;
961 TSD
->currentnode
->now
->usec
= unow
;
971 if ((tmptr
= localtime(&now
)) != NULL
)
974 memset(&tmdata
,0,sizeof(tmdata
)); /* what shall we do in this case? */
976 if (supptime
) /* time conversion required */
978 if (convert_time(TSD
,supptime
,suppformat
,&tmdata
,&unow
))
981 if (supptime
&& supptime
->value
)
982 p1
= (char *) tmpstr_of( TSD
, supptime
) ;
985 if (str_suppformat
&& str_suppformat
->value
)
986 p2
= (char *) tmpstr_of( TSD
, str_suppformat
) ;
989 exiterror( ERR_INCORRECT_CALL
, 19, "TIME", p1
, p2
) ;
996 hour
= tmdata
.tm_hour
;
997 ampm
= (char *)( ( hour
> 11 ) ? "pm" : "am" ) ;
998 if ((hour
=hour
%12)==0)
1000 sprintf(answer
->value
, "%d:%02d%s", hour
, tmdata
.tm_min
, ampm
) ;
1001 answer
->len
= strlen(answer
->value
);
1006 sec
= (long)((TSD
->currlevel
->rx_time
.sec
) ? rnow
-TSD
->currlevel
->rx_time
.sec
: 0) ;
1007 usec
= (long)((TSD
->currlevel
->rx_time
.sec
) ? unow
-TSD
->currlevel
->rx_time
.usec
: 0) ;
1015 /* assert( usec>=0 && sec>=0 ) ; */
1016 if (!TSD
->currlevel
->rx_time
.sec
|| format
=='R')
1018 TSD
->currlevel
->rx_time
.sec
= rnow
;
1019 TSD
->currlevel
->rx_time
.usec
= unow
;
1023 * We have to cast these since time_t can be 'any' type, and
1024 * the format specifier can not be set to correspond with time_t,
1025 * then be have to convert it. Besides, we use unsigned format
1026 * in order not to generate any illegal numbers
1029 sprintf(answer
->value
,"%ld.%06lu", (long)sec
, (unsigned long)usec
) ;
1031 sprintf(answer
->value
,".%06lu", (unsigned long)usec
) ;
1032 answer
->len
= strlen(answer
->value
);
1036 sprintf(answer
->value
, "%d", tmdata
.tm_hour
) ;
1037 answer
->len
= strlen(answer
->value
);
1041 sprintf(answer
->value
, "%.06f", cpu_time()) ;
1042 answer
->len
= strlen(answer
->value
);
1046 sprintf(answer
->value
, "%02d:%02d:%02d.%06ld", tmdata
.tm_hour
,
1047 tmdata
.tm_min
, tmdata
.tm_sec
, (long)unow
) ;
1048 answer
->len
= strlen(answer
->value
);
1052 sprintf(answer
->value
, "%d", tmdata
.tm_hour
*60 + tmdata
.tm_min
) ;
1053 answer
->len
= strlen(answer
->value
);
1057 sprintf(answer
->value
, "%02d:%02d:%02d", tmdata
.tm_hour
,
1058 tmdata
.tm_min
, tmdata
.tm_sec
) ;
1059 answer
->len
= strlen(answer
->value
);
1064 timediff
= mktime(localtime(&now
));
1066 timediff
= (long)(mktime(localtime(&now
))-mktime(gmtime(&now
)));
1067 tmptr
= localtime(&now
);
1068 if ( tmptr
->tm_isdst
)
1071 sprintf(answer
->value
, "%ld%s",
1072 timediff
,(timediff
)?"000000":"");
1073 answer
->len
= strlen(answer
->value
);
1077 sprintf(answer
->value
, "%d", ((tmdata
.tm_hour
*60)+tmdata
.tm_min
)
1078 *60 + tmdata
.tm_sec
) ;
1079 answer
->len
= strlen(answer
->value
);
1083 rnow
= mktime( &tmdata
);
1084 sprintf(answer
->value
, "%ld", (long)rnow
);
1085 answer
->len
= strlen(answer
->value
);
1089 /* should not get here */
1095 streng
*std_date( tsd_t
*TSD
, cparamboxptr parms
)
1097 static const char *fmt
= "%02d/%02d/%02d" ;
1098 static const char *sdate
= "%04d%02d%02d" ;
1099 // static const char *iso = "%04d-%02d-%02d" ; // Unused
1101 char suppformat
= 'N' ;
1103 const char *chptr
=NULL
;
1104 streng
*answer
=Str_makeTSD( 50 ) ;
1105 paramboxptr tmpptr
=NULL
;
1106 streng
*suppdate
=NULL
;
1107 streng
*str_suppformat
=NULL
;
1108 struct tm tmdata
, *tmptr
;
1109 time_t now
=0, unow
=0, rnow
=0 ;
1111 checkparam( parms
, 0, 3 , "DATE" ) ;
1112 if ((parms
)&&(parms
->value
))
1113 format
= getoptionchar( TSD
, parms
->value
, "DATE", 1, "BDEMNOSUW", "CIJT" ) ;
1117 tmpptr
= parms
->next
;
1118 if (parms
->next
->value
)
1119 suppdate
= tmpptr
->value
;
1123 tmpptr
= tmpptr
->next
;
1126 str_suppformat
= tmpptr
->value
;
1127 suppformat
= getoptionchar( TSD
, tmpptr
->value
, "DATE", 3, "BDENOSU", "IT" ) ;
1136 if (TSD
->currentnode
->now
)
1138 now
= TSD
->currentnode
->now
->sec
;
1139 unow
= TSD
->currentnode
->now
->usec
;
1143 getsecs(&now
, &unow
) ;
1144 TSD
->currentnode
->now
= (rexx_time
*)MallocTSD( sizeof( rexx_time
) ) ;
1145 TSD
->currentnode
->now
->sec
= now
;
1146 TSD
->currentnode
->now
->usec
= unow
;
1151 * This should not be rounded up for dates. If this were
1152 * run at 11:59:59.500001 on 10 Jun, DATE would report back
1154 if (unow>=(500*1000))
1158 if ( ( tmptr
= localtime( &now
) ) != NULL
)
1161 memset( &tmdata
, 0, sizeof( tmdata
) ); /* what shall we do in this case? */
1162 tmdata
.tm_year
+= 1900;
1164 if ( suppdate
) /* date conversion required */
1166 if ( convert_date( TSD
, suppdate
, suppformat
, &tmdata
) )
1169 if (suppdate
&& suppdate
->value
)
1170 p1
= (char *) tmpstr_of( TSD
, suppdate
) ;
1173 if (str_suppformat
&& str_suppformat
->value
)
1174 p2
= (char *) tmpstr_of( TSD
, str_suppformat
) ;
1177 exiterror( ERR_INCORRECT_CALL
, 19, "DATE", p1
, p2
) ;
1180 * Check for crazy years...
1182 if ( tmdata
.tm_year
< 0 || tmdata
.tm_year
> 9999 )
1183 exiterror( ERR_INCORRECT_CALL
, 18, "DATE" ) ;
1189 answer
->len
= sprintf( answer
->value
, "%d", tmdata
.tm_yday
+ basedays( tmdata
.tm_year
) );
1193 length
= tmdata
.tm_yday
+ basedays(tmdata
.tm_year
); /* was +1 */
1194 answer
->len
= sprintf( answer
->value
, "%d", length
-basedays( (tmdata
.tm_year
/100)*100)+1 ); /* bja */
1197 answer
->len
= sprintf( answer
->value
, "%d", tmdata
.tm_yday
+ 1 );
1201 answer
->len
= sprintf( answer
->value
, fmt
, tmdata
.tm_mday
, tmdata
.tm_mon
+1, tmdata
.tm_year
%100 );
1205 sprintf(answer
->value
, "%d", tmdata
.tm_yday
+ (basedays(tmdata
.tm_year
)-basedays(1978)) + 1);
1206 answer
->len
= strlen(answer
->value
);
1210 sprintf(answer
->value
, "%02d%d", tmdata
.tm_year
%100, tmdata
.tm_yday
+ 1);
1211 answer
->len
= strlen(answer
->value
);
1215 chptr
= months
[tmdata
.tm_mon
] ;
1216 answer
->len
= strlen( chptr
);
1217 memcpy( answer
->value
, chptr
, answer
->len
) ;
1221 chptr
= months
[tmdata
.tm_mon
] ;
1222 answer
->len
= sprintf( answer
->value
, "%d %c%c%c %4d", tmdata
.tm_mday
, chptr
[0], chptr
[1], chptr
[2], tmdata
.tm_year
);
1226 answer
->len
= sprintf( answer
->value
, fmt
, tmdata
.tm_year
%100, tmdata
.tm_mon
+1, tmdata
.tm_mday
);
1230 answer
->len
= sprintf(answer
->value
, sdate
, tmdata
.tm_year
, tmdata
.tm_mon
+1, tmdata
.tm_mday
);
1234 tmdata
.tm_year
-= 1900;
1235 rnow
= mktime( &tmdata
);
1236 answer
->len
= sprintf(answer
->value
, "%ld", (long)rnow
);
1240 answer
->len
= sprintf( answer
->value
, fmt
, tmdata
.tm_mon
+1, tmdata
.tm_mday
, tmdata
.tm_year
%100 );
1244 chptr
= WeekDays
[tmdata
.tm_wday
] ;
1245 answer
->len
= strlen(chptr
);
1246 memcpy(answer
->value
, chptr
, answer
->len
) ;
1250 /* should not get here */
1258 streng
*std_words( tsd_t
*TSD
, cparamboxptr parms
)
1260 int space
=0, i
=0, j
=0 ;
1261 streng
*string
=NULL
;
1264 checkparam( parms
, 1, 1 , "WORDS" ) ;
1265 string
= parms
->value
;
1267 send
= Str_len(string
) ;
1269 for (i
=j
=0;send
>i
;i
++) {
1270 if ((!space
)&&(rx_isspace(string
->value
[i
]))) j
++ ;
1271 space
= (rx_isspace(string
->value
[i
])) ; }
1273 if ((!space
)&&(i
>0)) j
++ ;
1274 return( int_to_streng( TSD
, j
) ) ;
1278 streng
*std_word( tsd_t
*TSD
, cparamboxptr parms
)
1280 streng
*string
=NULL
, *result
=NULL
;
1281 int i
=0, j
=0, finished
=0, start
=0, stop
=0, number
=0, space
=0, slen
=0 ;
1283 checkparam( parms
, 2, 2 , "WORD" ) ;
1284 string
= parms
->value
;
1285 number
= atopos( TSD
, parms
->next
->value
, "WORD", 2 ) ;
1291 slen
= Str_len(string
) ;
1292 for (i
=j
=0;(slen
>i
)&&(!finished
);i
++)
1294 if ((space
)&&(!rx_isspace(string
->value
[i
])))
1296 if ((!space
)&&(rx_isspace(string
->value
[i
])))
1299 finished
= (++j
==number
) ;
1301 space
= (rx_isspace(string
->value
[i
])) ;
1304 if ((!finished
)&&(((number
==j
+1)&&(!space
)) || ((number
==j
)&&(space
))))
1312 result
= Str_makeTSD(stop
-start
) ; /* problems with length */
1313 result
= Str_nocatTSD( result
, string
, stop
-start
, start
) ;
1314 result
->len
= stop
-start
;
1317 result
= nullstringptr() ;
1326 streng
*std_address( tsd_t
*TSD
, cparamboxptr parms
)
1330 checkparam( parms
, 0, 1 , "ADDRESS" ) ;
1332 if ( parms
&& parms
->value
)
1333 opt
= getoptionchar( TSD
, parms
->value
, "ADDRESS", 1, "EINO", "" ) ;
1335 update_envirs( TSD
, TSD
->currlevel
) ;
1337 return Str_dupTSD( TSD
->currlevel
->environment
) ;
1340 return get_envir_details( TSD
, opt
, TSD
->currlevel
->environment
);
1345 streng
*std_digits( tsd_t
*TSD
, cparamboxptr parms
)
1347 checkparam( parms
, 0, 0 , "DIGITS" ) ;
1348 return int_to_streng( TSD
, TSD
->currlevel
->currnumsize
) ;
1352 streng
*std_form( tsd_t
*TSD
, cparamboxptr parms
)
1354 checkparam( parms
, 0, 0 , "FORM" ) ;
1355 return Str_creTSD( numeric_forms
[TSD
->currlevel
->numform
] ) ;
1359 streng
*std_fuzz( tsd_t
*TSD
, cparamboxptr parms
)
1361 checkparam( parms
, 0, 0 , "FUZZ" ) ;
1362 return int_to_streng( TSD
, TSD
->currlevel
->numfuzz
) ;
1366 streng
*std_abbrev( tsd_t
*TSD
, cparamboxptr parms
)
1368 int length
=0, answer
=0, i
=0 ;
1369 streng
*longstr
=NULL
, *shortstr
=NULL
;
1371 checkparam( parms
, 2, 3 , "ABBREV" ) ;
1372 longstr
= parms
->value
;
1373 shortstr
= parms
->next
->value
;
1375 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
1376 length
= atozpos( TSD
, parms
->next
->next
->value
, "ABBREV", 3 ) ;
1378 length
= Str_len(shortstr
) ;
1380 answer
= (Str_ncmp(shortstr
,longstr
,length
)) ? 0 : 1 ;
1382 if ((length
>Str_len(shortstr
))||(Str_len(shortstr
)>Str_len(longstr
)))
1386 for (i
=length
; i
<Str_len(shortstr
); i
++)
1387 if (shortstr
->value
[i
] != longstr
->value
[i
])
1391 return int_to_streng( TSD
, answer
) ;
1395 streng
*std_qualify( tsd_t
*TSD
, cparamboxptr parms
)
1399 checkparam( parms
, 1, 1 , "QUALIFY" ) ;
1400 ret
= ConfigStreamQualified( TSD
, parms
->value
);
1402 * Returned streng is always MAX_PATH long, so it should be safe
1403 * to Nul terminate the ret->value
1405 ret
->value
[ret
->len
] = '\0';
1409 streng
*std_queued( tsd_t
*TSD
, cparamboxptr parms
)
1413 checkparam( parms
, 0, 0 , "QUEUED" );
1414 rc
= lines_in_stack( TSD
, NULL
);
1415 return int_to_streng( TSD
, ( rc
< 0 ) ? 0 : rc
);
1420 streng
*std_strip( tsd_t
*TSD
, cparamboxptr parms
)
1422 #if defined(_AMIGA) || defined(__AROS__)
1423 char option
='B', *padstr
=" ", alloc
=0;
1425 char option
='B', padch
=' ' ;
1427 streng
*input
=NULL
;
1428 int leading
=0, trailing
=0, start
=0, stop
=0 ;
1430 checkparam( parms
, 1, 3 , "STRIP" ) ;
1431 if ( ( parms
->next
)
1432 && ( parms
->next
->value
) )
1433 option
= getoptionchar( TSD
, parms
->next
->value
, "STRIP", 2, "LTB", "" );
1435 if ( ( parms
->next
)
1436 && ( parms
->next
->next
)
1437 && ( parms
->next
->next
->value
) )
1438 #if defined(_AMIGA) || defined(__AROS__)
1440 padstr
= str_of( TSD
, parms
->next
->next
->value
) ;
1444 padch
= getonechar( TSD
, parms
->next
->next
->value
, "STRIP", 3 ) ;
1447 input
= parms
->value
;
1448 leading
= ((option
=='B')||(option
=='L')) ;
1449 trailing
= ((option
=='B')||(option
=='T')) ;
1451 #if defined(_AMIGA) || defined(__AROS__)
1452 for (start
=0;(start
<Str_len(input
))&&strchr(padstr
,input
->value
[start
])&&(leading
);start
++) ;
1453 for (stop
=Str_len(input
)-1;(stop
>=start
)&&strchr(padstr
,input
->value
[stop
])&&(trailing
);stop
--) ;
1455 for (start
=0;(start
<Str_len(input
))&&(input
->value
[start
]==padch
)&&(leading
);start
++) ;
1456 for (stop
=Str_len(input
)-1;(stop
>=start
)&&(input
->value
[stop
]==padch
)&&(trailing
);stop
--) ;
1459 stop
= start
- 1 ; /* FGC: If this happens, it will crash */
1461 #if defined(_AMIGA) || defined(__AROS__)
1465 return Str_nocatTSD(Str_makeTSD(stop
-start
+2),input
,stop
-start
+1, start
) ;
1470 streng
*std_space( tsd_t
*TSD
, cparamboxptr parms
)
1472 streng
*retval
=NULL
, *string
=NULL
;
1474 int i
=0, j
=0, k
=0, l
=0, space
=1, length
=1, hole
=0 ;
1476 checkparam( parms
, 1, 3 , "SPACE" ) ;
1477 if ( ( parms
->next
)
1478 && ( parms
->next
->value
) )
1479 length
= atozpos( TSD
, parms
->next
->value
, "SPACE", 2 ) ;
1481 if ( ( parms
->next
)
1482 && ( parms
->next
->next
)
1483 && ( parms
->next
->next
->value
) )
1484 padch
= getonechar( TSD
, parms
->next
->next
->value
, "SPACE", 3 ) ;
1486 string
= parms
->value
;
1487 for ( i
= 0; Str_in( string
, i
); i
++ )
1489 if ((space
)&&(string
->value
[i
]!=' ')) hole
++ ;
1490 space
= (string
->value
[i
]==' ') ;
1494 retval
= Str_makeTSD(i
+ hole
*length
) ;
1495 for (j
=l
=i
=0;Str_in(string
,i
);i
++)
1497 if (!((space
)&&(string
->value
[i
]==' ')))
1499 if ((space
=(string
->value
[i
]==' '))!=0)
1500 for (l
=j
,k
=0;k
<length
;k
++)
1501 retval
->value
[j
++] = padch
;
1503 retval
->value
[j
++] = string
->value
[i
] ;
1509 retval
->len
-= length
;
1515 streng
*std_arg( tsd_t
*TSD
, cparamboxptr parms
)
1517 int number
=0, retval
=0, tmpval
=0 ;
1519 streng
*value
=NULL
;
1520 paramboxptr ptr
=NULL
;
1522 checkparam( parms
, 0, 2 , "ARG" ) ;
1524 && ( parms
->value
) )
1526 number
= atopos( TSD
, parms
->value
, "ARG", 1 ) ;
1528 flag
= getoptionchar( TSD
, parms
->next
->value
, "ARG", 2, "ENO", "" ) ;
1531 ptr
= TSD
->currlevel
->args
;
1534 for (retval
=0,tmpval
=1; ptr
; ptr
=ptr
->next
, tmpval
++)
1538 value
= int_to_streng( TSD
, retval
) ;
1543 for (retval
=1;(retval
<number
)&&(ptr
)&&((ptr
=ptr
->next
)!=NULL
);retval
++) ;
1547 retval
= ((ptr
)&&(ptr
->value
)) ;
1548 value
= int_to_streng( TSD
, retval
? 1 : 0 ) ;
1551 retval
= ((ptr
)&&(ptr
->value
)) ;
1552 value
= int_to_streng( TSD
, retval
? 0 : 1 ) ;
1555 if ((ptr
)&&(ptr
->value
))
1556 value
= Str_dupTSD(ptr
->value
) ;
1558 value
= nullstringptr() ;
1572 static char logic( char first
, char second
, int ltype
)
1576 case ( LOGIC_AND
) : return (char)( first
& second
) ;
1577 case ( LOGIC_OR
) : return (char)( first
| second
) ;
1578 case ( LOGIC_XOR
) : return (char)( first
^ second
) ;
1580 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
1582 /* not reached, next line only to satisfy compiler */
1587 static streng
*misc_logic( tsd_t
*TSD
, int ltype
, cparamboxptr parms
, const char *bif
, int argnum
)
1589 int length1
=0, length2
=0, i
=0 ;
1592 streng
*pad
=NULL
, *outstr
=NULL
, *str1
=NULL
, *str2
=NULL
;
1594 checkparam( parms
, 1, 3 , bif
) ;
1595 str1
= parms
->value
;
1597 str2
= (parms
->next
) ? (parms
->next
->value
) : NULL
;
1599 kill
= str2
= nullstringptr() ;
1603 if ((parms
->next
)&&(parms
->next
->next
))
1604 pad
= parms
->next
->next
->value
;
1609 padch
= getonechar( TSD
, pad
, bif
, argnum
) ;
1615 length1
= Str_len(str1
) ;
1616 length2
= Str_len(str2
) ;
1617 if (length2
> length1
)
1625 outstr
= Str_makeTSD( Str_len(str1
) ) ;
1627 for (i
=0; Str_in(str2
,i
); i
++)
1628 outstr
->value
[i
] = logic( str1
->value
[i
], str2
->value
[i
], ltype
) ;
1631 for (; Str_in(str1
,i
); i
++)
1632 outstr
->value
[i
] = logic( str1
->value
[i
], padch
, ltype
) ;
1634 for (; Str_in(str1
,i
); i
++)
1635 outstr
->value
[i
] = str1
->value
[i
] ;
1638 Free_stringTSD( kill
) ;
1644 streng
*std_bitand( tsd_t
*TSD
, cparamboxptr parms
)
1646 return misc_logic( TSD
, LOGIC_AND
, parms
, "BITAND", 3 ) ;
1649 streng
*std_bitor( tsd_t
*TSD
, cparamboxptr parms
)
1651 return misc_logic( TSD
, LOGIC_OR
, parms
, "BITOR", 3 ) ;
1654 streng
*std_bitxor( tsd_t
*TSD
, cparamboxptr parms
)
1656 return misc_logic( TSD
, LOGIC_XOR
, parms
, "BITXOR", 3 ) ;
1660 streng
*std_center( tsd_t
*TSD
, cparamboxptr parms
)
1662 int length
=0, i
=0, j
=0, start
=0, stop
=0, chars
=0 ;
1664 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1666 checkparam( parms
, 2, 3 , "CENTER" ) ;
1667 length
= atozpos( TSD
, parms
->next
->value
, "CENTER", 2 ) ;
1668 str
= parms
->value
;
1669 if (parms
->next
->next
!=NULL
)
1670 pad
= parms
->next
->next
->value
;
1674 chars
= Str_len(str
) ;
1678 padch
= getonechar( TSD
, pad
, "CENTER", 3 ) ;
1680 start
= (chars
>length
) ? ((chars
-length
)/2) : 0 ;
1681 stop
= (chars
>length
) ? (chars
-(chars
-length
+1)/2) : chars
;
1683 ptr
= Str_makeTSD( length
) ;
1684 for (j
=0;j
<((length
-chars
)/2);ptr
->value
[j
++]=padch
) ;
1685 for (i
=start
;i
<stop
;ptr
->value
[j
++]=str
->value
[i
++]) ;
1686 for (;j
<length
;ptr
->value
[j
++]=padch
) ;
1689 assert((ptr
->len
<=ptr
->max
) && (j
==length
));
1694 static unsigned num_sourcelines(const internal_parser_type
*ipt
)
1698 if (ipt
->first_source_line
!= NULL
)
1699 return ipt
->last_source_line
->lineno
;
1701 /* must be incore_source but that value may be NULL because of a failed
1702 * instore[0] of RexxStart!
1704 if ((otp
= ipt
->srclines
) == NULL
)
1705 return 0; /* May happen if the user doesn't provides the true
1706 * source. If you set it to 1 you must return anything
1707 * below for that line.
1711 return otp
->sum
+ otp
->num
;
1714 streng
*std_sourceline( tsd_t
*TSD
, cparamboxptr parms
)
1718 const internal_parser_type
*ipt
= &TSD
->systeminfo
->tree
;
1722 bt
= (bui_tsd_t
*)TSD
->bui_tsd
;
1723 checkparam( parms
, 0, 1 , "SOURCELINE" ) ;
1725 return int_to_streng( TSD
, num_sourcelines( ipt
) ) ;
1727 line
= atopos( TSD
, parms
->value
, "SOURCELINE", 1 ) ;
1729 if (ipt
->first_source_line
== NULL
)
1730 { /* must be incore_source but that value may be NULL because of a failed
1731 * instore[0] of RexxStart!
1733 otp
= ipt
->srclines
; /* NULL if incore_source==NULL */
1736 while (otp
&& ((int) otp
->num
< line
))
1742 if ((otp
== NULL
) || /* line not found or error */
1745 exiterror( ERR_INCORRECT_CALL
, 34, "SOURCELINE", 1, line
, num_sourcelines( ipt
) ) ;
1749 i
= otp
->elems
[line
].length
;
1750 retval
= Str_makeTSD( i
) ;
1752 memcpy( retval
->value
, ipt
->incore_source
+ otp
->elems
[line
].offset
, i
) ;
1755 if (bt
->srcline_first
!= ipt
->first_source_line
)
1757 bt
->srcline_lineno
= 1 ;
1760 ipt
->first_source_line
;
1762 for (;(bt
->srcline_lineno
<line
);)
1764 if ((bt
->srcline_ptr
=bt
->srcline_ptr
->next
)==NULL
)
1766 exiterror( ERR_INCORRECT_CALL
, 34, "SOURCELINE", 1, line
, num_sourcelines( ipt
) ) ;
1768 bt
->srcline_lineno
= bt
->srcline_ptr
->lineno
;
1770 for (;(bt
->srcline_lineno
>line
);)
1772 if ((bt
->srcline_ptr
=bt
->srcline_ptr
->prev
)==NULL
)
1773 exiterror( ERR_INCORRECT_CALL
, 0 ) ;
1774 bt
->srcline_lineno
= bt
->srcline_ptr
->lineno
;
1777 return Str_dupTSD(bt
->srcline_ptr
->line
) ;
1781 streng
*std_compare( tsd_t
*TSD
, cparamboxptr parms
)
1784 streng
*pad
=NULL
, *str1
=NULL
, *str2
=NULL
;
1785 int i
=0, j
=0, value
=0 ;
1787 checkparam( parms
, 2, 3 , "COMPARE" ) ;
1788 str1
= parms
->value
;
1789 str2
= parms
->next
->value
;
1790 if (parms
->next
->next
)
1791 pad
= parms
->next
->next
->value
;
1798 padch
= getonechar( TSD
, pad
, "COMPARE", 3) ;
1801 while ((Str_in(str1
,i
))||(Str_in(str2
,j
))) {
1802 if (((Str_in(str1
,i
))?(str1
->value
[i
]):(padch
))!=
1803 ((Str_in(str2
,j
))?(str2
->value
[j
]):(padch
))) {
1804 value
= (i
>j
) ? i
: j
;
1806 if (Str_in(str1
,i
)) i
++ ;
1807 if (Str_in(str2
,j
)) j
++ ; }
1809 if ((!Str_in(str1
,i
))&&(!Str_in(str2
,j
)))
1814 return int_to_streng( TSD
, value
) ;
1818 streng
*std_errortext( tsd_t
*TSD
, cparamboxptr parms
)
1821 streng
*tmp
,*tmp1
,*tmp2
;
1822 int numdec
=0, errnum
, suberrnum
, pos
=0, i
;
1824 const char *err
=NULL
;
1827 checkparam( parms
, 1, 2 , "ERRORTEXT" ) ;
1829 if (parms
&&parms
->next
&&parms
->next
->value
)
1830 opt
= getoptionchar( TSD
, parms
->next
->value
, "ERRORTEXT", 2, "NS", "" ) ;
1831 tmp
= Str_dupTSD( parms
->value
);
1832 for (i
=0; i
<Str_len( tmp
); i
++ )
1834 if ( *( tmp
->value
+i
) == '.' )
1837 *( tmp
->value
+i
) = '\0';
1842 exiterror( ERR_INCORRECT_CALL
, 11, 1, tmpstr_of( TSD
, parms
->value
) ) ;
1846 tmp1
= Str_ncreTSD( tmp
->value
, pos
);
1847 tmp2
= Str_ncreTSD( tmp
->value
+pos
+1, Str_len( tmp
) - pos
- 1 );
1848 errnum
= atoposorzero( TSD
, tmp1
, "ERRORTEXT", 1 );
1849 suberrnum
= atoposorzero( TSD
, tmp2
, "ERRORTEXT", 1 );
1850 Free_stringTSD( tmp1
) ;
1851 Free_stringTSD( tmp2
) ;
1855 errnum
= atoposorzero( TSD
, tmp
, "ERRORTEXT", 1 );
1859 * Only restrict the error number passed if STRICT_ANSI is in effect.
1861 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
)
1862 && ( errnum
> 90 || suberrnum
> 900 ) )
1863 exiterror( ERR_INCORRECT_CALL
, 17, "ERRORTEXT", tmpstr_of( TSD
, parms
->value
) ) ;
1865 Free_stringTSD( tmp
) ;
1867 return Str_dupTSD( errortext( TSD
, errnum
, suberrnum
, (opt
=='S')?1:0, 1 ) ) ;
1871 streng
*std_length( tsd_t
*TSD
, cparamboxptr parms
)
1873 checkparam( parms
, 1, 1 , "LENGTH" ) ;
1874 return int_to_streng( TSD
, Str_len( parms
->value
)) ;
1878 streng
*std_left( tsd_t
*TSD
, cparamboxptr parms
)
1882 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1884 checkparam( parms
, 2, 3 , "LEFT" ) ;
1885 length
= atozpos( TSD
, parms
->next
->value
, "LEFT", 2 ) ;
1886 str
= parms
->value
;
1887 if (parms
->next
->next
!=NULL
)
1888 pad
= parms
->next
->next
->value
;
1895 padch
= getonechar( TSD
, pad
, "LEFT", 3) ;
1897 ptr
= Str_makeTSD( length
) ;
1898 for (i
=0;(i
<length
)&&(Str_in(str
,i
));i
++)
1899 ptr
->value
[i
] = str
->value
[i
] ;
1901 for (;i
<length
;ptr
->value
[i
++]=padch
) ;
1907 streng
*std_right( tsd_t
*TSD
, cparamboxptr parms
)
1909 int length
=0, i
=0, j
=0 ;
1911 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1913 checkparam( parms
, 2, 3 , "RIGHT" ) ;
1914 length
= atozpos( TSD
, parms
->next
->value
, "RIGHT", 2 ) ;
1915 str
= parms
->value
;
1916 if (parms
->next
->next
!=NULL
)
1917 pad
= parms
->next
->next
->value
;
1924 padch
= getonechar( TSD
, pad
, "RIGHT", 3 ) ;
1926 ptr
= Str_makeTSD( length
) ;
1927 for (j
=0;Str_in(str
,j
);j
++) ;
1928 for (i
=length
-1,j
--;(i
>=0)&&(j
>=0);ptr
->value
[i
--]=str
->value
[j
--]) ;
1930 for (;i
>=0;ptr
->value
[i
--]=padch
) ;
1937 streng
*std_verify( tsd_t
*TSD
, cparamboxptr parms
)
1939 char tab
[256], ch
=' ' ;
1940 streng
*str
=NULL
, *ref
=NULL
;
1941 int inv
=0, start
=0, res
=0, i
=0 ;
1943 checkparam( parms
, 2, 4 , "VERIFY" ) ;
1945 str
= parms
->value
;
1946 ref
= parms
->next
->value
;
1947 if ( parms
->next
->next
)
1949 if ( parms
->next
->next
->value
)
1951 ch
= getoptionchar( TSD
, parms
->next
->next
->value
, "VERIFY", 3, "MN", "" ) ;
1955 if (parms
->next
->next
->next
)
1956 start
= atopos( TSD
, parms
->next
->next
->next
->value
, "VERIFY", 4 ) - 1 ;
1959 for (i
=0;i
<256;tab
[i
++]=0) ;
1960 for (i
=0;Str_in(ref
,i
);tab
[(unsigned char)(ref
->value
[i
++])]=1) ;
1961 for (i
=start
;(Str_in(str
,i
))&&(!res
);i
++)
1963 if (inv
==(tab
[(unsigned char)(str
->value
[i
])]))
1967 return int_to_streng( TSD
, res
) ;
1972 streng
*std_substr( tsd_t
*TSD
, cparamboxptr parms
)
1974 int rlength
=0, length
=0, start
=0, i
=0 ;
1975 int available
, copycount
;
1977 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1978 paramboxptr bptr
=NULL
;
1980 checkparam( parms
, 2, 4 , "SUBSTR" ) ;
1981 str
= parms
->value
;
1982 rlength
= Str_len( str
) ;
1983 start
= atopos( TSD
, parms
->next
->value
, "SUBSTR", 2 ) ;
1984 if ( ( (bptr
= parms
->next
->next
) != NULL
)
1985 && ( parms
->next
->next
->value
) )
1986 length
= atozpos( TSD
, parms
->next
->next
->value
, "SUBSTR", 3 ) ;
1988 length
= ( rlength
>= start
) ? rlength
- start
+ 1 : 0;
1992 && ( bptr
->next
->value
) )
1993 pad
= parms
->next
->next
->next
->value
;
1998 padch
= getonechar( TSD
, pad
, "SUBSTR", 4) ;
2000 ptr
= Str_makeTSD( length
) ;
2001 i
= ((rlength
>=start
)?start
-1:rlength
) ;
2003 * New algorithm by Julian Onions speeds up substr() by 50%
2005 available
= Str_len(str
) - i
;
2006 copycount
= length
> available
? available
: length
;
2007 memcpy(ptr
->value
, &str
->value
[i
], copycount
);
2008 if (copycount
< length
)
2009 memset(&ptr
->value
[copycount
], padch
, length
- copycount
);
2015 static streng
*minmax( tsd_t
*TSD
, cparamboxptr parms
, const char *name
,
2023 int ccns
,fuzz
,StrictAnsi
,result
,required
,argno
;
2025 StrictAnsi
= get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
);
2027 * Round the number according to NUMERIC DIGITS. This is rule 9.2.1.
2028 * Don't set DIGITS or FUZZ where it's possible to raise a condition.
2029 * We don't have a chance to set it back to the original value.
2031 ccns
= TSD
->currlevel
->currnumsize
;
2032 fuzz
= TSD
->currlevel
->numfuzz
;
2034 required
= count_params(parms
, PARAM_TYPE_HARD
);
2035 if ( !parms
->value
)
2036 exiterror( ERR_INCORRECT_CALL
, 3, name
, required
);
2037 m
= get_a_descr( TSD
, name
, 1, parms
->value
);
2040 str_round_lostdigits( TSD
, m
, ccns
);
2043 parms
= parms
->next
;
2048 if ( !parms
->value
)
2049 exiterror( ERR_INCORRECT_CALL
, 3, name
, required
); /* fixes bug 1109296 */
2051 test
= get_a_descr( TSD
, name
, argno
, parms
->value
);
2054 str_round_lostdigits( TSD
, test
, ccns
);
2057 if ( ( TSD
->currlevel
->currnumsize
= test
->size
) < m
->size
)
2058 TSD
->currlevel
->currnumsize
= m
->size
;
2059 TSD
->currlevel
->numfuzz
= 0;
2060 result
= string_test( TSD
, test
, m
) * sign
;
2061 TSD
->currlevel
->currnumsize
= ccns
;
2062 TSD
->currlevel
->numfuzz
= fuzz
;
2066 free_a_descr( TSD
, test
);
2070 free_a_descr( TSD
, m
);
2073 parms
= parms
->next
;
2076 m
->used_digits
= m
->size
;
2077 retval
= str_norm( TSD
, m
, NULL
);
2078 free_a_descr( TSD
, m
);
2082 streng
*std_max( tsd_t
*TSD
, cparamboxptr parms
)
2084 return minmax( TSD
, parms
, "MAX", 1 );
2089 streng
*std_min( tsd_t
*TSD
, cparamboxptr parms
)
2091 return minmax( TSD
, parms
, "MIN", -1 );
2096 streng
*std_reverse( tsd_t
*TSD
, cparamboxptr parms
)
2101 checkparam( parms
, 1, 1 , "REVERSE" ) ;
2103 ptr
= Str_makeTSD(j
=Str_len(parms
->value
)) ;
2105 for (i
=0;j
>=0;ptr
->value
[i
++]=parms
->value
->value
[j
--]) ;
2110 streng
*std_random( tsd_t
*TSD
, cparamboxptr parms
)
2112 int min
=0, max
=999, result
=0 ;
2113 #if defined(HAVE_RANDOM)
2119 checkparam( parms
, 0, 3 , "RANDOM" ) ;
2125 min
= atozpos( TSD
, parms
->value
, "RANDOM", 1 ) ;
2128 max
= atozpos( TSD
, parms
->value
, "RANDOM", 1 ) ;
2130 exiterror( ERR_INCORRECT_CALL
, 31, "RANDOM", max
) ;
2133 if (parms
->next
!=NULL
)
2135 if (parms
->next
->value
!=NULL
)
2136 max
= atozpos( TSD
, parms
->next
->value
, "RANDOM", 2 ) ;
2138 if (parms
->next
->next
!=NULL
&&parms
->next
->next
->value
!=NULL
)
2140 seed
= atozpos( TSD
, parms
->next
->next
->value
, "RANDOM", 3 ) ;
2141 #if defined(HAVE_RANDOM)
2151 exiterror( ERR_INCORRECT_CALL
, 33, "RANDOM", min
, max
) ;
2152 if (max
-min
> 100000)
2153 exiterror( ERR_INCORRECT_CALL
, 32, "RANDOM", min
, max
) ;
2155 #if defined(HAVE_RANDOM)
2156 result
= (random() % (max
-min
+1)) + min
;
2158 # if RAND_MAX < 100000
2159 /* result = (((rand() * 100) + (clock() % 100)) % (max-min+1)) + min ; */
2160 result
= (((rand() * RAND_MAX
) + rand() ) % (max
-min
+1)) + min
; /* pgb */
2162 result
= (rand() % (max
-min
+1)) + min
;
2165 return int_to_streng( TSD
, result
) ;
2169 streng
*std_copies( tsd_t
*TSD
, cparamboxptr parms
)
2172 int copies
=0, i
=0, length
=0 ;
2174 checkparam( parms
, 2, 2 , "COPIES" ) ;
2176 length
= Str_len(parms
->value
) ;
2177 copies
= atozpos( TSD
, parms
->next
->value
, "COPIES", 2 ) * length
;
2178 ptr
= Str_makeTSD( copies
) ;
2179 for (i
=0;i
<copies
;i
+=length
)
2180 memcpy(ptr
->value
+i
,parms
->value
->value
,length
) ;
2187 streng
*std_sign( tsd_t
*TSD
, cparamboxptr parms
)
2189 checkparam( parms
, 1, 1 , "SIGN" );
2191 return str_sign( TSD
, parms
->value
);
2195 streng
*std_trunc( tsd_t
*TSD
, cparamboxptr parms
)
2199 checkparam( parms
, 1, 2 , "TRUNC" );
2200 if ( parms
->next
&& parms
->next
->value
)
2201 decimals
= atozpos( TSD
, parms
->next
->value
, "TRUNC", 2 );
2203 return str_trunc( TSD
, parms
->value
, decimals
);
2207 streng
*std_translate( tsd_t
*TSD
, cparamboxptr parms
)
2209 streng
*iptr
=NULL
, *optr
=NULL
;
2211 streng
*string
=NULL
, *result
=NULL
;
2212 paramboxptr ptr
=NULL
;
2213 int olength
=0, i
=0, ii
=0 ;
2215 checkparam( parms
, 1, 4 , "TRANSLATE" ) ;
2217 string
= parms
->value
;
2218 if ( ( (ptr
= parms
->next
) != NULL
)
2219 && ( parms
->next
->value
) )
2221 optr
= parms
->next
->value
;
2222 olength
= Str_len( optr
) ;
2226 && ( (ptr
= ptr
->next
) != NULL
)
2233 && ( (ptr
= ptr
->next
) != NULL
)
2235 padch
= getonechar( TSD
, ptr
->value
, "TRANSLATE", 4 ) ;
2237 result
= Str_makeTSD( Str_len(string
) ) ;
2238 for (i
=0; Str_in(string
,i
); i
++)
2240 if ((!iptr
)&&(!optr
))
2241 result
->value
[i
] = (char) rx_toupper(string
->value
[i
]) ;
2246 for (ii
=0; Str_in(iptr
,ii
); ii
++)
2247 if (iptr
->value
[ii
]==string
->value
[i
])
2250 if (ii
==Str_len(iptr
))
2252 result
->value
[i
] = string
->value
[i
] ;
2257 ii
= ((unsigned char*)string
->value
)[i
] ;
2259 if ((optr
)&&(ii
<olength
))
2260 result
->value
[i
] = optr
->value
[ii
] ;
2262 result
->value
[i
] = padch
;
2271 streng
*std_delstr( tsd_t
*TSD
, cparamboxptr parms
)
2273 int i
=0, j
=0, length
=0, sleng
=0, start
=0 ;
2274 streng
*string
=NULL
, *result
=NULL
;
2276 checkparam( parms
, 2, 3 , "DELSTR" ) ;
2278 sleng
= Str_len((string
= parms
->value
)) ;
2280 * found while fixing bug 1108868, but fast-finding Walter will create
2281 * a new bug item before releasing the fix I suppose ;-) (was atozpos)
2283 start
= atopos( TSD
, parms
->next
->value
, "DELSTR", 2 ) ;
2285 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
2286 length
= atozpos( TSD
, parms
->next
->next
->value
, "DELSTR", 3 ) ;
2288 length
= Str_len( string
) - start
+ 1 ;
2293 result
= Str_makeTSD( (start
+length
>sleng
) ? start
: sleng
-length
) ;
2295 for (i
=j
=0; (Str_in(string
,i
))&&(i
<start
-1); result
->value
[i
++] = string
->value
[j
++]) ;
2297 for (; (j
<=sleng
)&&(Str_in(string
,j
)); result
->value
[i
++] = string
->value
[j
++] ) ;
2307 static int valid_hex_const( const streng
*str
)
2309 const char *ptr
=NULL
, *end_ptr
=NULL
;
2313 end_ptr
= ptr
+ str
->len
;
2315 if ((end_ptr
>ptr
) && ((rx_isspace(*ptr
)) || (rx_isspace(*(end_ptr
-1)))))
2317 return 0 ; /* leading or trailing space */
2321 for (; ptr
<end_ptr
; ptr
++)
2323 if (rx_isspace(*ptr
))
2329 else if (space_stat
==1)
2331 /* non-even number of hex digits in non-first group */
2335 else if (rx_isxdigit(*ptr
))
2338 space_stat
= ((space_stat
==1) ? 2 : 1) ;
2342 return 0 ; /* neither space nor hex digit */
2348 /* non-even number of digits in last grp, which not also first grp */
2352 /* note: the nullstring is a valid hexstring */
2353 return 1 ; /* a valid hex string */
2356 static int valid_binary_const( const streng
*str
)
2357 /* check for valid binary streng. returns 1 for TRUE, 0 for FALSE */
2364 if ((len
= Str_len(str
))==0)
2365 return(1); /* ANSI */
2366 len
--; /* on last char */
2368 if (rx_isspace(ptr
[0]) || rx_isspace(ptr
[len
]))
2369 return(0); /* leading or trailing space */
2370 /* ptr must consist of 0 1nd 1. After a blank follows a blank or a block
2371 * of four digits. Since the first block of binary digits may contain
2372 * less than four digits, we casn parse backwards and check only filled
2373 * block till we reach the start. Thanks to ANSI testing program. */
2374 for (digits
= 0; len
>= 0; len
--)
2379 if ((digits
% 4) != 0)
2382 else if ((c
!= '0') && (c
!= '1'))
2390 streng
*std_datatype( tsd_t
*TSD
, cparamboxptr parms
)
2392 streng
*string
=NULL
, *result
=NULL
;
2393 char option
=' ', *cptr
=NULL
;
2395 parambox parms_for_symbol
;
2397 checkparam( parms
, 1, 2 , "DATATYPE" ) ;
2399 string
= parms
->value
;
2401 if ((parms
->next
)&&(parms
->next
->value
))
2403 option
= getoptionchar( TSD
, parms
->next
->value
, "DATATYPE", 2, "ABLMNSUWX", "" ) ;
2405 cptr
= string
->value
;
2406 if ((Str_len(string
)==0)&&(option
!='X')&&(option
!='B'))
2412 for (; cptr
<Str_end(string
); res
= rx_isalnum(*cptr
++) && res
) ;
2413 res
= ( res
) ? 1 : 0;
2417 res
= valid_binary_const( string
);
2421 for (; cptr
<Str_end(string
); res
= rx_islower(*cptr
++) && res
) ;
2422 res
= ( res
) ? 1 : 0;
2426 for (; cptr
<Str_end(string
); res
= rx_isalpha(*cptr
++) && res
) ;
2427 res
= ( res
) ? 1 : 0;
2431 res
= myisnumber(TSD
, string
) ;
2436 * According to ANSI 9.3.8, this should return the result of:
2437 * Symbol( string ) \= 'BAD'
2440 parms_for_symbol
.next
= NULL
;
2441 parms_for_symbol
.dealloc
= 0;
2442 parms_for_symbol
.value
= string
;
2443 result
= std_symbol( TSD
, &parms_for_symbol
);
2444 if ( result
->len
== 3 && memcmp( result
->value
, "BAD", 3 ) == 0 )
2448 Free_string_TSD( TSD
,result
);
2452 for (; cptr
<Str_end(string
); res
= rx_isupper(*cptr
++) && res
) ;
2453 res
= ( res
) ? 1 : 0;
2457 res
= myiswnumber( TSD
, string
, NULL
, 0 );
2461 res
= valid_hex_const( string
) ;
2465 /* shouldn't get here */
2468 result
= int_to_streng( TSD
, res
) ;
2472 cptr
= (char *)( ( ( string
->len
) && ( myisnumber( TSD
, string
) ) ) ? "NUM" : "CHAR" ) ;
2473 result
= Str_creTSD( cptr
) ;
2480 streng
*std_trace( tsd_t
*TSD
, cparamboxptr parms
)
2482 streng
*result
=NULL
, *string
=NULL
;
2486 checkparam( parms
, 0, 1 , "TRACE" ) ;
2488 result
= Str_makeTSD( 3 ) ;
2489 if (TSD
->systeminfo
->interactive
)
2490 result
->value
[i
++] = '?' ;
2492 result
->value
[i
++] = (char) TSD
->trace_stat
;
2497 string
= Str_dupTSD( parms
->value
);
2498 for (i
= 0; i
< string
->len
; i
++ )
2500 if ( string
->value
[ i
] == '?' )
2501 set_trace_char( TSD
, '?' );
2506 * In opposite to ANSI this throws 40.21, too.
2507 * I assume this to be OK although "trace ?" throws 40.21.
2509 tc
= getoptionchar( TSD
, Str_strp( string
, '?', STRIP_LEADING
),
2513 set_trace_char( TSD
, tc
);
2514 Free_stringTSD( string
);
2520 streng
*std_changestr( tsd_t
*TSD
, cparamboxptr parms
)
2522 streng
*needle
=NULL
, *heystack
=NULL
, *new_needle
=NULL
, *retval
=NULL
;
2523 int neelen
=0, heylen
=0, newlen
=0, newneelen
=0, cnt
=0, start
=0, i
=0, heypos
=0, retpos
=0 ;
2525 checkparam( parms
, 3, 3, "CHANGESTR" ) ;
2526 needle
= parms
->value
;
2527 heystack
= parms
->next
->value
;
2528 new_needle
= parms
->next
->next
->value
;
2530 neelen
= Str_len(needle
) ;
2531 heylen
= Str_len(heystack
) ;
2532 newneelen
= Str_len(new_needle
) ;
2534 /* find number of occurrences of needle in heystack */
2535 if ((!needle
->len
)||(!heystack
->len
)||(needle
->len
>heystack
->len
))
2541 start
= bmstrstr(heystack
, start
, needle
, 0);
2545 start
+= needle
->len
;
2548 newlen
= 1 + heylen
+ ((newneelen
-neelen
) * cnt
);
2549 retval
= Str_makeTSD(newlen
) ;
2552 return (Str_ncpyTSD(retval
,heystack
,heylen
));
2554 start
=heypos
=retpos
=0;
2557 start
= bmstrstr(heystack
, start
, needle
, 0);
2560 cnt
= heylen
-heypos
;
2561 for(i
=0;i
<cnt
;retval
->value
[retpos
++]=heystack
->value
[heypos
++],i
++) ;
2565 for(i
=0;i
<cnt
;retval
->value
[retpos
++]=heystack
->value
[heypos
++],i
++) ;
2566 for(i
=0;i
<neelen
;heypos
++,i
++) ;
2567 for(i
=0;i
<newneelen
;retval
->value
[retpos
++]=new_needle
->value
[i
++]) ;
2571 retval
->value
[retpos
] = '\0';
2576 streng
*std_countstr( tsd_t
*TSD
, cparamboxptr parms
)
2578 int start
=0, cnt
=0 ;
2579 streng
*needle
=NULL
, *heystack
=NULL
;
2580 checkparam( parms
, 2, 2 , "COUNTSTR" ) ;
2582 needle
= parms
->value
;
2583 heystack
= parms
->next
->value
;
2585 if ((!needle
->len
)||(!heystack
->len
))
2591 start
= bmstrstr(heystack
, start
, needle
, 0);
2595 start
+= needle
->len
;
2599 return (int_to_streng( TSD
, cnt
) ) ;
2602 streng
*rex_poolid( tsd_t
*TSD
, cparamboxptr parms
)
2604 checkparam( parms
, 0, 0 , "POOLID" );
2606 return ( int_to_streng( TSD
, TSD
->currlevel
->pool
) );
2609 streng
*rex_lower( tsd_t
*TSD
, cparamboxptr parms
)
2611 int rlength
=0, length
=0, start
=1, i
=0 ;
2614 streng
*str
=NULL
, *ptr
=NULL
;
2615 paramboxptr bptr
=NULL
;
2618 * Check that we have between 1 and 4 args
2619 * ( str [,start[,length[,pad]]] )
2621 checkparam( parms
, 1, 4 , "LOWER" ) ;
2622 str
= parms
->value
;
2623 rlength
= Str_len( str
) ;
2625 * Get starting position, if supplied...
2627 if ( parms
->next
!= NULL
2628 && parms
->next
->value
)
2629 start
= atopos( TSD
, parms
->next
->value
, "LOWER", 2 ) ;
2631 * Get length, if supplied...
2633 if ( parms
->next
!= NULL
2634 && ( (bptr
= parms
->next
->next
) != NULL
)
2635 && ( parms
->next
->next
->value
) )
2636 length
= atozpos( TSD
, parms
->next
->next
->value
, "LOWER", 3 ) ;
2638 length
= ( rlength
>= start
) ? rlength
- start
+ 1 : 0;
2640 * Get pad character, if supplied...
2644 && ( bptr
->next
->value
) )
2645 padch
= getonechar( TSD
, parms
->next
->next
->next
->value
, "LOWER", 4) ;
2647 * Create our new starting; duplicate of input string
2649 ptr
= Str_makeTSD( length
);
2650 memcpy( Str_val( ptr
), Str_val( str
), Str_len( str
) );
2652 * Determine where to start changing case...
2654 i
= ((rlength
>=start
)?start
-1:rlength
) ;
2656 * Determine how many characters to change case...
2658 changecount
= length
> rlength
? rlength
: length
;
2662 mem_lower( &ptr
->value
[i
], changecount
);
2664 * Append pad characters if required...
2666 if (changecount
< length
)
2667 memset(&ptr
->value
[changecount
], padch
, length
- changecount
);
2669 * Determine length of return string...
2671 ptr
->len
= (length
> rlength
) ? length
: rlength
;