2 static char *RCSid
= "$Id$";
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1992-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.
42 double pow( double, double ) ;
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 ((bt
= TSD
->bui_tsd
= MallocTSD(sizeof(bui_tsd_t
))) == NULL
)
82 memset(bt
,0,sizeof(bui_tsd_t
)); /* correct for all values */
84 #if defined(HAVE_RANDOM)
85 srandom((int) (time((time_t *)0)+getpid())%(3600*24)) ;
87 srand((unsigned) (time((time_t *)0)+getpid())%(3600*24)) ;
92 static int contained_in( const char *first
, const char *fend
, const char *second
, const char *send
)
94 * Determines if one string exists in another string. Search is done
99 * Skip over any leading spaces in the search string
101 for (; (first
<fend
)&&(isspace(*first
)); first
++)
106 * Trim any trailing spaces in the search string
108 for (; (first
<fend
)&&(isspace(*(fend
-1))); fend
--)
113 * Skip over any leading spaces in the searched string
115 for (; (second
<send
)&&(isspace(*second
)); second
++)
120 * Trim any trailing spaces in the searched string
122 for (; (second
<send
)&&(isspace(*(send
-1))); send
--)
127 * If the length of the search string is less than the string to
128 * search we won't find a match
130 if (fend
-first
> send
-second
)
133 for (; (first
<fend
); )
135 for (; (first
<fend
)&&(!isspace(*first
)); first
++, second
++)
137 if ((*first
)!=(*second
))
141 if ((second
<send
)&&(!isspace(*second
)))
147 for (; (first
<fend
)&&(isspace(*first
)); first
++)
151 for (; (second
<send
)&&(isspace(*second
)); second
++)
160 /* ************************ contained_in() ************************
161 * Checks if the first string is a subphrase of the second string,
162 * A phrase differs from a substring in one significant way; a
163 * phrase is a set of words, separated by any number of blanks. So,
164 * this function ignores blanks spaces between any of the words
165 * contained within the strings.
167 * Passed pointers to the first and second strings. Also passed the
168 * pointers to the ends of the first and second strings (ie, so this
169 * works on non-null-terminated strings).
171 * Returns 1 if so, 0 if not.
173 * Note that if first string is an empty string (or one that contains
174 * all spaces), this will report a match regardless of what is in
175 * second string. It's up to the caller to check for such a condition.
177 * Also note that the caller should have stripped any leading spaces
178 * in first and second strings.
180 * Original routine re-written by J.Glatt 21 Nov 99
183 static int contained_in( const char *first
, const char *fend
, const char *second
, const char *send
)
186 * Uncomment this to allow this function to skip leading spaces
187 * and add skip: before while() loop after "skip leading spaces in first string"
190 Removed this code. goto inside a loop is bad karma! MH 21 Nov 99
195 * Another non-space char in first?
197 while ( (first
< fend
) && !isspace(*first
) )
200 * Another char in second? If so, compare this char with first's char
202 if ( (second
>= send
) || (*first
!= *second
) )
205 * If it doesn't match or second has no more chars, return 0
211 * These two strings match so far. Keep checking more chars for matches
217 * Does the second string either end at the same position as the first string,
218 * or does it have a space at the same position? If not, no match
220 if ( (second
< send
) && !isspace(*second
) )
226 * Skip leading spaces in first string
227 * Add skip: label if you want to ignore leading spaces
229 while ( (first
< fend
) && isspace(*first
) ) first
++;
232 * Skip leading spaces in second string
234 while ( (second
< send
) && isspace(*second
) ) second
++;
237 * Any more chars in the first string?
239 } while ( first
< fend
);
250 streng
*std_wordpos( tsd_t
*TSD
, cparamboxptr parms
)
252 streng
*seek
=NULL
, *target
=NULL
;
253 char *sptr
=NULL
, *tptr
=NULL
, *end
=NULL
, *send
=NULL
;
256 checkparam( parms
, 2, 3 , "WORDPOS" ) ;
257 seek
= parms
->value
;
258 target
= parms
->next
->value
;
259 if ( param( parms
, 3 ) )
260 start
= atopos( TSD
, parms
->next
->next
->value
, "WORDPOS", 3 ) ;
262 end
= target
->value
+ Str_len(target
) ;
263 /* Then lets position right in the target */
264 for (tptr
=target
->value
; (tptr
<end
) && isspace(*tptr
) ; tptr
++) /* FGC: ordered */
268 for (res
=1; (res
<start
); res
++)
270 for (; (tptr
<end
)&&(!isspace(*tptr
)); tptr
++ )
274 for (; (tptr
<end
) && isspace(*tptr
); tptr
++ )
280 send
= seek
->value
+ Str_len(seek
) ;
281 for (sptr
=seek
->value
; (sptr
<send
) && isspace(*sptr
); sptr
++)
287 for ( ; (sptr
<send
)&&(tptr
<end
); )
289 if (contained_in( sptr
, send
, tptr
, end
))
292 for (; (tptr
<end
)&&(!isspace(*tptr
)); tptr
++)
296 for (; (tptr
<end
)&&(isspace(*tptr
)); tptr
++)
303 if ((sptr
>=send
)||((sptr
<send
)&&(tptr
>=end
)))
306 return int_to_streng( TSD
, res
) ;
310 streng
*std_wordlength( tsd_t
*TSD
, cparamboxptr parms
)
313 streng
*string
=NULL
;
314 char *ptr
=NULL
, *end
=NULL
;
316 checkparam( parms
, 2, 2 , "WORDLENGTH" ) ;
317 string
= parms
->value
;
318 number
= atopos( TSD
, parms
->next
->value
, "WORDLENGTH", 2 ) ;
320 end
= (ptr
=string
->value
) + Str_len(string
) ;
321 for (; (ptr
<end
) && isspace(*ptr
); ptr
++)
325 for (i
=0; i
<number
-1; i
++)
327 for (; (ptr
<end
)&&(!isspace(*ptr
)); ptr
++)
331 for (; (ptr
<end
)&&(isspace(*ptr
)); ptr
++ )
337 for (i
=0; (((ptr
+i
)<end
)&&(!isspace(*(ptr
+i
)))); i
++)
341 return (int_to_streng( TSD
,i
)) ;
346 streng
*std_wordindex( tsd_t
*TSD
, cparamboxptr parms
)
349 streng
*string
=NULL
;
350 char *ptr
=NULL
, *end
=NULL
;
352 checkparam( parms
, 2, 2 , "WORDINDEX" ) ;
353 string
= parms
->value
;
354 number
= atopos( TSD
, parms
->next
->value
, "WORDINDEX", 2 ) ;
356 end
= (ptr
=string
->value
) + Str_len(string
) ;
357 for (; (ptr
<end
) && isspace(*ptr
); ptr
++)
361 for (i
=0; i
<number
-1; i
++)
363 for (; (ptr
<end
)&&(!isspace(*ptr
)); ptr
++)
367 for (; (ptr
<end
)&&(isspace(*ptr
)); ptr
++)
373 return ( int_to_streng( TSD
, (ptr
<end
) ? (ptr
- string
->value
+ 1 ) : 0) ) ;
377 streng
*std_delword( tsd_t
*TSD
, cparamboxptr parms
)
379 char *rptr
=NULL
, *cptr
=NULL
, *end
=NULL
;
380 streng
*string
=NULL
;
381 int length
=(-1), start
=0, i
=0 ;
383 checkparam( parms
, 2, 3 , "DELWORD" ) ;
384 string
= Str_dupTSD(parms
->value
) ;
385 start
= atopos( TSD
, parms
->next
->value
, "DELWORD", 2 ) ;
386 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
387 length
= atozpos( TSD
, parms
->next
->next
->value
, "DELWORD", 3 ) ;
389 end
= (cptr
=string
->value
) + Str_len(string
) ;
390 for (; (cptr
<end
) && isspace(*cptr
); cptr
++ )
394 for (i
=0; i
<(start
-1); i
++)
396 for (; (cptr
<end
)&&(!isspace(*cptr
)); cptr
++)
400 for (; (cptr
<end
) && isspace(*cptr
); cptr
++)
407 for (i
=0; (i
<(length
))||((length
==(-1))&&(cptr
<end
)); i
++)
409 for (; (cptr
<end
)&&(!isspace(*cptr
)); cptr
++ )
413 for (; (cptr
<end
) && isspace(*cptr
); cptr
++ )
421 for (; (cptr
<end
)&&(!isspace(*cptr
)); *(rptr
++) = *(cptr
++))
425 for (; (cptr
<end
) && isspace(*cptr
); *(rptr
++) = *(cptr
++))
431 string
->len
= (rptr
- string
->value
) ;
436 streng
*std_xrange( tsd_t
*TSD
, cparamboxptr parms
)
438 int start
=0, stop
=0xff, i
=0, length
=0 ;
439 streng
*result
=NULL
;
441 checkparam( parms
, 0, 2 , "XRANGE" ) ;
443 start
= (unsigned char) getonechar( TSD
, parms
->value
, "XRANGE", 1 ) ;
446 && ( parms
->next
->value
) )
447 stop
= (unsigned char) getonechar( TSD
, parms
->next
->value
, "XRANGE", 2 ) ;
449 length
= stop
- start
+ 1 ;
451 length
= 256 + length
;
453 result
= Str_makeTSD( length
) ;
454 for (i
=0; (i
<length
); i
++)
458 result
->value
[i
] = (char) start
++ ;
460 /* result->value[i] = (char) stop ; */
467 streng
*std_lastpos( tsd_t
*TSD
, cparamboxptr parms
)
469 int res
=0, start
=0, i
=0, j
=0, nomore
=0 ;
470 streng
*needle
=NULL
, *heystack
=NULL
;
472 checkparam( parms
, 2, 3 , "LASTPOS" ) ;
473 needle
= parms
->value
;
474 heystack
= parms
->next
->value
;
475 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
476 start
= atopos( TSD
, parms
->next
->next
->value
, "LASTPOS", 3 ) ;
478 start
= Str_len( heystack
) ;
480 nomore
= Str_len( needle
) ;
481 if (start
>Str_len(heystack
))
482 start
= Str_len( heystack
) ;
489 for (i
=start
-nomore
; i
>=0; i
-- )
492 * FGC: following loop was "<=nomore"
494 for (j
=0; (j
<nomore
)&&(needle
->value
[j
]==heystack
->value
[i
+j
]);j
++) ;
502 return (int_to_streng( TSD
,res
)) ;
507 streng
*std_pos( tsd_t
*TSD
, cparamboxptr parms
)
510 streng
*needle
=NULL
, *heystack
=NULL
;
511 checkparam( parms
, 2, 3 , "POS" ) ;
513 needle
= parms
->value
;
514 heystack
= parms
->next
->value
;
515 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
516 start
= atopos( TSD
, parms
->next
->next
->value
, "POS", 3 ) ;
520 || (start
>heystack
->len
))
524 res
= bmstrstr(heystack
, start
-1, needle
) + 1 ;
527 return (int_to_streng( TSD
, res
) ) ;
532 streng
*std_subword( tsd_t
*TSD
, cparamboxptr parms
)
534 int i
=0, length
=0, start
=0 ;
535 char *cptr
=NULL
, *eptr
=NULL
, *cend
=NULL
;
536 streng
*string
=NULL
, *result
=NULL
;
538 checkparam( parms
, 2, 3 , "SUBWORD" ) ;
539 string
= parms
->value
;
540 start
= atopos( TSD
, parms
->next
->value
, "SUBWORD", 2 ) ;
541 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
542 length
= atozpos( TSD
, parms
->next
->next
->value
, "SUBWORD", 3 ) ;
546 cptr
= string
->value
;
547 cend
= cptr
+ Str_len(string
) ;
548 for (i
=1; i
<start
; i
++)
550 for ( ; (cptr
<cend
)&&(isspace(*cptr
)); cptr
++) ;
554 for ( ; (cptr
<cend
)&&(!isspace(*cptr
)); cptr
++)
559 for ( ; (cptr
<cend
)&&(isspace(*cptr
)); cptr
++)
567 for( i
=0; (i
<length
); i
++ )
569 for (;(eptr
<cend
)&&(isspace(*eptr
)); eptr
++) /* wount hit 1st time */
573 for (;(eptr
<cend
)&&(!isspace(*eptr
)); eptr
++)
581 for(eptr
=cend
; (eptr
>cptr
)&&isspace(*(eptr
-1)); eptr
--)
587 result
= Str_makeTSD( eptr
-cptr
) ;
588 memcpy( result
->value
, cptr
, (eptr
-cptr
) ) ;
589 result
->len
= (eptr
-cptr
) ;
596 streng
*std_symbol( tsd_t
*TSD
, cparamboxptr parms
)
600 checkparam( parms
, 1, 1 , "SYMBOL" ) ;
602 type
= valid_var_symbol( parms
->value
) ;
603 if (type
==SYMBOL_BAD
)
604 return Str_creTSD("BAD") ;
606 if (type
!=SYMBOL_CONSTANT
)
608 assert(type
==SYMBOL_STEM
||type
==SYMBOL_SIMPLE
||type
==SYMBOL_COMPOUND
);
609 if (isvariable(TSD
, parms
->value
))
610 return Str_creTSD("VAR") ;
613 return Str_creTSD("LIT") ;
617 #if defined(TRACEMEM) && defined(HAVE_PUTENV)
618 static void mark_envirvars( const tsd_t
*TSD
)
620 struct envirlist
*ptr
=NULL
;
624 for (ptr
=bt
->first_envirvar
; ptr
; ptr
=ptr
->next
)
626 markmemory( ptr
, TRC_STATIC
) ;
627 markmemory( ptr
->ptr
, TRC_STATIC
) ;
631 static void add_new_env( const tsd_t
*TSD
, streng
*ptr
)
633 struct envirlist
*new=NULL
;
637 new = MallocTSD( sizeof( struct envirlist
)) ;
638 new->next
= bt
->first_envirvar
;
641 if (!bt
->first_envirvar
)
642 regmarker( TSD
, mark_envirvars
) ;
644 bt
->first_envirvar
= new ;
650 streng
*std_value( tsd_t
*TSD
, cparamboxptr parms
)
653 streng
*string
=NULL
, *ptr
=NULL
, *str_val
=NULL
;
654 streng
*value
=NULL
, *env
=NULL
;
655 #if defined(HAVE_SETENV) || defined(HAVE_MY_WIN32_SETENV)
656 streng
*strvalue
=NULL
;
659 checkparam( parms
, 1, 3 , "VALUE" ) ;
661 value
= (parms
->next
->value
) ? (parms
->next
->value
) : NULL
;
664 if ((parms
->next
) && (parms
->next
->next
) && (parms
->next
->next
->value
))
667 * External variable pool; ie environment variables in operating
670 string
= Str_dupstrTSD( parms
->value
) ;
671 env
= parms
->next
->next
->value
;
673 if (((Str_len(env
)==6) && (!strncmp(env
->value
,"SYSTEM",6)))
674 || ((Str_len(env
)==14) && (!strncmp(env
->value
,"OS2ENVIRONMENT",14)))
675 || ((Str_len(env
)==11) && (!strncmp(env
->value
,"ENVIRONMENT",11))))
678 * We have an external environment. Get the current value from the
679 * exit if we have one, or from the environment directly if not...
681 if (TSD
->systeminfo
->hooks
& HOOK_MASK(HOOK_GETENV
))
682 ok
= hookup_input_output( TSD
, HOOK_GETENV
, string
, &str_val
) ;
687 * Either there was no exit handler, or the exit handler didn't
688 * handle the GETENV. Get the environment variable directly from
692 ptr
= vms_resolv_symbol( TSD
, string
, value
, env
) ;
694 char *val
= mygetenv( TSD
, string
->value
, NULL
, 0 ) ;
697 ptr
= Str_creTSD( val
) ;
704 * Copy the returned value ASAP and free it.
706 ptr
= Str_dupstrTSD( str_val
) ;
713 * We are setting a value in the external environment
716 if ( TSD
->restricted
)
717 exiterror( ERR_RESTRICTED
, 2, "VALUE", 2 ) ;
719 if (TSD
->systeminfo
->hooks
& HOOK_MASK(HOOK_SETENV
))
720 ok
= hookup_output2( TSD
, HOOK_SETENV
, string
, value
) ;
724 # if defined(HAVE_PUTENV)
725 # if defined(FIX_PROTOS) && defined(ultrix)
728 streng
*new = Str_makeTSD( Str_len(string
) + Str_len(value
) + 2 ) ;
729 Str_catTSD( new, string
) ;
730 Str_catstrTSD( new, "=") ;
731 Str_catTSD( new, parms
->next
->value
) ;
732 new->value
[Str_len(new)] = 0x00 ;
734 /* Will generate warning under (e.g) Ultrix; don't bother! */
735 putenv( new->value
) ;
736 /* Note: we don't release this memory, because putenv might use */
737 /* the area for its own purposes. */
738 /* Free_stringTSD( new ) ; */ /* never to be used again */
740 add_new_env( TSD
, new ) ;
742 # elif defined(HAVE_SETENV)
743 strvalue
= Str_dupstrTSD( value
) ;
744 setenv(string
->value
, strvalue
->value
, 1 ) ;
745 # elif defined(HAVE_MY_WIN32_SETENV)
746 strvalue
= Str_dupstrTSD( value
) ;
747 my_win32_setenv(string
->value
, strvalue
->value
) ;
749 exiterror( ERR_SYSTEM_FAILURE
, 1, "No support for setting an environment variable" ) ;
750 # endif /* HAVE_PUTENV */
759 exiterror( ERR_INCORRECT_CALL
, 37, "VALUE", tmpstr_of( TSD
, env
) ) ;
761 Free_stringTSD( string
) ;
763 ptr
= nullstringptr() ;
768 * Internal variable pool; ie Rexx variables. According to ANSI standard
769 * need to uppercase the variable name first.
771 string
= Str_upper( Str_dupTSD( parms
->value
) );
772 ptr
= Str_dupTSD( get_it_anyway( TSD
, string
) ) ;
774 setvalue( TSD
, string
, Str_dupTSD( value
) ) ;
775 Free_stringTSD( string
);
780 streng
*std_abs( tsd_t
*TSD
, cparamboxptr parms
)
782 checkparam( parms
, 1, 1 , "ABS" ) ;
783 return str_abs( TSD
, parms
->value
) ;
787 streng
*std_condition( tsd_t
*TSD
, cparamboxptr parms
)
790 streng
*result
=NULL
;
795 checkparam( parms
, 0, 1 , "CONDITION" ) ;
797 if (parms
&&parms
->value
)
798 opt
= getoptionchar( TSD
, parms
->value
, "CONDITION", 1, "CEIDS", "" ) ;
801 sig
= getsigs(TSD
->currlevel
) ;
806 result
= Str_creTSD( signalnames
[sig
->type
] ) ;
810 result
= Str_creTSD( (sig
->invoke
) ? "SIGNAL" : "CALL" ) ;
815 result
= Str_dupTSD( sig
->descr
) ;
820 sprintf(buf
, "%d.%d", sig
->rc
, sig
->subrc
);
822 sprintf(buf
, "%d", sig
->rc
);
823 result
= Str_creTSD( buf
) ;
827 traps
= gettraps( TSD
, TSD
->currlevel
) ;
828 if (traps
[sig
->type
].delayed
)
829 result
= Str_creTSD( "DELAY" ) ;
831 result
= Str_creTSD( (traps
[sig
->type
].on_off
) ? "ON" : "OFF" ) ;
835 /* should not get here */
840 result
= nullstringptr() ;
846 streng
*std_format( tsd_t
*TSD
, cparamboxptr parms
)
848 streng
*number
=NULL
;
849 int before
=(-1), after
=(-1) ;
850 int esize
=(-1), trigger
=(-1) ;
853 checkparam( parms
, 1, 5, "FORMAT" ) ;
854 number
= (ptr
=parms
)->value
;
856 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
857 before
= atozpos( TSD
, ptr
->value
, "FORMAT", 2 ) ;
859 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
860 after
= atozpos( TSD
, ptr
->value
, "FORMAT", 3 ) ;
862 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
863 esize
= atozpos( TSD
, ptr
->value
, "FORMAT", 4 ) ;
865 if ((ptr
) && ((ptr
=ptr
->next
)!=NULL
) && (ptr
->value
))
866 trigger
= atozpos( TSD
, ptr
->value
, "FORMAT", 5 ) ;
868 return str_format( TSD
, number
, before
, after
, esize
, trigger
) ;
873 streng
*std_overlay( tsd_t
*TSD
, cparamboxptr parms
)
875 streng
*newstr
=NULL
, *oldstr
=NULL
, *retval
=NULL
;
877 int length
=0, spot
=0, oldlen
=0, i
=0, j
=0, k
=0 ;
878 paramboxptr tmpptr
=NULL
;
880 checkparam( parms
, 2, 5, "OVERLAY" ) ;
881 newstr
= parms
->value
;
882 oldstr
= parms
->next
->value
;
883 length
= Str_len(newstr
) ;
884 oldlen
= Str_len(oldstr
) ;
885 if (parms
->next
->next
)
887 tmpptr
= parms
->next
->next
;
888 if (parms
->next
->next
->value
)
889 spot
= atopos( TSD
, tmpptr
->value
, "OVERLAY", 3 ) ;
893 tmpptr
= tmpptr
->next
;
895 length
= atozpos( TSD
, tmpptr
->value
, "OVERLAY", 4 ) ;
896 if ((tmpptr
->next
)&&(tmpptr
->next
->value
))
897 padch
= getonechar( TSD
, tmpptr
->next
->value
, "OVERLAY", 5 ) ;
901 retval
= Str_makeTSD(((spot
+length
-1>oldlen
)?spot
+length
-1:oldlen
)) ;
902 for (j
=i
=0;(i
<spot
-1)&&(i
<oldlen
);retval
->value
[j
++]=oldstr
->value
[i
++]) ;
903 for (;j
<spot
-1;retval
->value
[j
++]=padch
) ;
904 for (k
=0;(k
<length
)&&(Str_in(newstr
,k
));retval
->value
[j
++]=newstr
->value
[k
++])
907 for (;k
++<length
;retval
->value
[j
++]=padch
) if (oldlen
>i
) i
++ ;
908 for (;oldlen
>i
;retval
->value
[j
++]=oldstr
->value
[i
++]) ;
914 streng
*std_insert( tsd_t
*TSD
, cparamboxptr parms
)
916 streng
*newstr
=NULL
, *oldstr
=NULL
, *retval
=NULL
;
918 int length
=0, spot
=0, oldlen
=0, i
=0, j
=0, k
=0 ;
919 paramboxptr tmpptr
=NULL
;
921 checkparam( parms
, 2, 5, "INSERT" ) ;
922 newstr
= parms
->value
;
923 oldstr
= parms
->next
->value
;
924 length
= Str_len(newstr
) ;
925 oldlen
= Str_len(oldstr
) ;
926 if (parms
->next
->next
)
928 tmpptr
= parms
->next
->next
;
929 if (parms
->next
->next
->value
)
930 spot
= atozpos( TSD
, tmpptr
->value
, "INSERT", 3 ) ;
934 tmpptr
= tmpptr
->next
;
936 length
= atozpos( TSD
, tmpptr
->value
, "INSERT", 4 ) ;
937 if ((tmpptr
->next
)&&(tmpptr
->next
->value
))
938 padch
= getonechar( TSD
, tmpptr
->next
->value
, "INSERT", 5) ;
942 retval
= Str_makeTSD(length
+((spot
>oldlen
)?spot
:oldlen
)) ;
943 for (j
=i
=0;(i
<spot
)&&(oldlen
>i
);retval
->value
[j
++]=oldstr
->value
[i
++]) ;
944 for (;j
<spot
;retval
->value
[j
++]=padch
) ;
945 for (k
=0;(k
<length
)&&(Str_in(newstr
,k
));retval
->value
[j
++]=newstr
->value
[k
++]) ;
946 for (;k
++<length
;retval
->value
[j
++]=padch
) ;
947 for (;oldlen
>i
;retval
->value
[j
++]=oldstr
->value
[i
++]) ;
954 streng
*std_time( tsd_t
*TSD
, cparamboxptr parms
)
957 time_t unow
=0, now
=0, rnow
=0 ;
958 long usec
=0L, sec
=0L, timediff
=0L ;
962 /* Fix a bug by checker: */
963 streng
*answer
=Str_makeTSD( 64 ) ;
965 streng
*answer
=Str_makeTSD( 50 ) ;
967 streng
*supptime
=NULL
;
968 streng
*str_suppformat
=NULL
;
969 char suppformat
= 'N' ;
970 paramboxptr tmpptr
=NULL
;
971 struct tm tmdata
, *tmptr
;
973 checkparam( parms
, 0, 3 , "TIME" ) ;
974 if ((parms
)&&(parms
->value
))
975 format
= getoptionchar( TSD
, parms
->value
, "TIME", 1, "CEHLMNORS", "JT" ) ;
979 tmpptr
= parms
->next
;
980 if (parms
->next
->value
)
981 supptime
= tmpptr
->value
;
985 tmpptr
= tmpptr
->next
;
988 str_suppformat
= tmpptr
->value
;
989 suppformat
= getoptionchar( TSD
, tmpptr
->value
, "TIME", 3, "CHLMNS", "T" ) ;
998 if (TSD
->currentnode
->now
)
1000 now
= TSD
->currentnode
->now
->sec
;
1001 unow
= TSD
->currentnode
->now
->usec
;
1005 getsecs(&now
, &unow
) ;
1006 TSD
->currentnode
->now
= MallocTSD( sizeof( rexx_time
) ) ;
1007 TSD
->currentnode
->now
->sec
= now
;
1008 TSD
->currentnode
->now
->usec
= unow
;
1013 if (unow
>=(500*1000)
1018 if ((tmptr
= localtime(&now
)) != NULL
)
1021 memset(&tmdata
,0,sizeof(tmdata
)); /* what shall we do in this case? */
1023 if (supptime
) /* time conversion required */
1025 if (convert_time(TSD
,supptime
,suppformat
,&tmdata
,&unow
))
1028 if (supptime
&& supptime
->value
)
1029 p1
= (char *) tmpstr_of( TSD
, supptime
) ;
1032 if (str_suppformat
&& str_suppformat
->value
)
1033 p2
= (char *) tmpstr_of( TSD
, str_suppformat
) ;
1036 exiterror( ERR_INCORRECT_CALL
, 19, "TIME", p1
, p2
) ;
1043 hour
= tmdata
.tm_hour
;
1044 ampm
= (hour
>11) ? "pm" : "am" ;
1045 if ((hour
=hour
%12)==0)
1047 sprintf(answer
->value
, "%d:%02d%s", hour
, tmdata
.tm_min
, ampm
) ;
1048 answer
->len
= strlen(answer
->value
);
1053 sec
= (TSD
->currlevel
->time
.sec
) ? rnow
-TSD
->currlevel
->time
.sec
: 0 ;
1054 usec
= (TSD
->currlevel
->time
.sec
) ? unow
-TSD
->currlevel
->time
.usec
: 0 ;
1062 assert( usec
>=0 && sec
>=0 ) ;
1063 if (!TSD
->currlevel
->time
.sec
|| format
=='R')
1065 TSD
->currlevel
->time
.sec
= rnow
;
1066 TSD
->currlevel
->time
.usec
= unow
;
1070 * We have to cast these since time_t can be 'any' type, and
1071 * the format specifier can not be set to correspond with time_t,
1072 * then be have to convert it. Besides, we use unsigned format
1073 * in order not to generate any illegal numbers
1076 sprintf(answer
->value
,"%ld.%06lu", (long)sec
, (unsigned long)usec
) ;
1078 sprintf(answer
->value
,".%06lu", (unsigned long)usec
) ;
1079 answer
->len
= strlen(answer
->value
);
1083 sprintf(answer
->value
, "%d", tmdata
.tm_hour
) ;
1084 answer
->len
= strlen(answer
->value
);
1088 sprintf(answer
->value
, "%.06f", cpu_time()) ;
1089 answer
->len
= strlen(answer
->value
);
1093 sprintf(answer
->value
, "%02d:%02d:%02d.%06ld", tmdata
.tm_hour
,
1094 tmdata
.tm_min
, tmdata
.tm_sec
, unow
) ;
1095 answer
->len
= strlen(answer
->value
);
1099 sprintf(answer
->value
, "%d", tmdata
.tm_hour
*60 + tmdata
.tm_min
) ;
1100 answer
->len
= strlen(answer
->value
);
1104 sprintf(answer
->value
, "%02d:%02d:%02d", tmdata
.tm_hour
,
1105 tmdata
.tm_min
, tmdata
.tm_sec
) ;
1106 answer
->len
= strlen(answer
->value
);
1111 timediff
= mktime(localtime(&now
));
1113 timediff
= mktime(localtime(&now
))-mktime(gmtime(&now
));
1115 sprintf(answer
->value
, "%ld%s",
1116 timediff
,(timediff
)?"000000":"");
1117 answer
->len
= strlen(answer
->value
);
1121 sprintf(answer
->value
, "%d", ((tmdata
.tm_hour
*60)+tmdata
.tm_min
)
1122 *60 + tmdata
.tm_sec
) ;
1123 answer
->len
= strlen(answer
->value
);
1127 rnow
= mktime( &tmdata
);
1128 sprintf(answer
->value
, "%ld", rnow
);
1129 answer
->len
= strlen(answer
->value
);
1133 /* should not get here */
1139 streng
*std_date( tsd_t
*TSD
, cparamboxptr parms
)
1141 static const char *fmt
= "%02d/%02d/%02d" ;
1142 static const char *iso
= "%04d%02d%02d" ;
1144 char suppformat
= 'N' ;
1146 const char *chptr
=NULL
;
1147 streng
*answer
=Str_makeTSD( 50 ) ;
1148 paramboxptr tmpptr
=NULL
;
1149 streng
*suppdate
=NULL
;
1150 streng
*str_suppformat
=NULL
;
1151 struct tm tmdata
, *tmptr
;
1152 time_t now
=0, unow
=0, rnow
=0 ;
1154 checkparam( parms
, 0, 3 , "DATE" ) ;
1155 if ((parms
)&&(parms
->value
))
1156 format
= getoptionchar( TSD
, parms
->value
, "DATE", 1, "BDEMNOSUW", "CIJT" ) ;
1160 tmpptr
= parms
->next
;
1161 if (parms
->next
->value
)
1162 suppdate
= tmpptr
->value
;
1166 tmpptr
= tmpptr
->next
;
1169 str_suppformat
= tmpptr
->value
;
1170 suppformat
= getoptionchar( TSD
, tmpptr
->value
, "DATE", 3, "BDENOSU", "IT" ) ;
1179 if (TSD
->currentnode
->now
)
1181 now
= TSD
->currentnode
->now
->sec
;
1182 unow
= TSD
->currentnode
->now
->usec
;
1186 getsecs(&now
, &unow
) ;
1187 TSD
->currentnode
->now
= MallocTSD( sizeof( rexx_time
) ) ;
1188 TSD
->currentnode
->now
->sec
= now
;
1189 TSD
->currentnode
->now
->usec
= unow
;
1194 * This should not be rounded up for dates. If this were
1195 * run at 11:59:59.500001 on 10 Jun, DATE would report back
1197 if (unow>=(500*1000))
1201 if ((tmptr
= localtime(&now
)) != NULL
)
1204 memset(&tmdata
,0,sizeof(tmdata
)); /* what shall we do in this case? */
1205 tmdata
.tm_year
+= 1900;
1207 if (suppdate
) /* date conversion required */
1209 if (convert_date(suppdate
,suppformat
,&tmdata
))
1212 if (suppdate
&& suppdate
->value
)
1213 p1
= (char *) tmpstr_of( TSD
, suppdate
) ;
1216 if (str_suppformat
&& str_suppformat
->value
)
1217 p2
= (char *) tmpstr_of( TSD
, str_suppformat
) ;
1220 exiterror( ERR_INCORRECT_CALL
, 19, "DATE", p1
, p2
) ;
1223 * Check for crazy years...
1225 if ( tmdata
.tm_year
< 0 || tmdata
.tm_year
> 9999 )
1226 exiterror( ERR_INCORRECT_CALL
, 18, "DATE" ) ;
1232 sprintf(answer
->value
,"%d", tmdata
.tm_yday
+ basedays(tmdata
.tm_year
));
1233 answer
->len
= strlen(answer
->value
);
1237 length
= tmdata
.tm_yday
+ basedays(tmdata
.tm_year
); /* was +1 */
1238 sprintf(answer
->value
,"%d", length
-basedays((tmdata
.tm_year
/100)*100)+1); /* bja */
1239 answer
->len
= strlen(answer
->value
);
1242 sprintf(answer
->value
, "%d", tmdata
.tm_yday
+ 1) ;
1243 answer
->len
= strlen(answer
->value
);
1247 sprintf(answer
->value
, fmt
, tmdata
.tm_mday
, tmdata
.tm_mon
+1,
1248 tmdata
.tm_year
%100) ;
1249 answer
->len
= strlen(answer
->value
);
1253 sprintf(answer
->value
, "%d", tmdata
.tm_yday
+ (basedays(tmdata
.tm_year
)-basedays(1978)) + 1);
1254 answer
->len
= strlen(answer
->value
);
1258 sprintf(answer
->value
, "%02d%d", tmdata
.tm_year
%100, tmdata
.tm_yday
+ 1);
1259 answer
->len
= strlen(answer
->value
);
1263 chptr
= months
[tmdata
.tm_mon
] ;
1264 answer
->len
= strlen(chptr
);
1265 memcpy(answer
->value
,chptr
,answer
->len
) ;
1269 chptr
= months
[tmdata
.tm_mon
] ;
1270 sprintf(answer
->value
,"%d %c%c%c %4d", tmdata
.tm_mday
, chptr
[0], chptr
[1],
1271 chptr
[2], tmdata
.tm_year
) ;
1272 answer
->len
= strlen(answer
->value
);
1276 sprintf(answer
->value
, fmt
, tmdata
.tm_year
%100, tmdata
.tm_mon
+1,
1278 answer
->len
= strlen(answer
->value
);
1282 sprintf(answer
->value
, iso
, tmdata
.tm_year
, tmdata
.tm_mon
+1,
1284 answer
->len
= strlen(answer
->value
);
1288 tmdata
.tm_year
-= 1900;
1289 rnow
= mktime( &tmdata
);
1290 answer
->len
= sprintf(answer
->value
, "%ld", rnow
);
1294 sprintf(answer
->value
, fmt
, tmdata
.tm_mon
+1, tmdata
.tm_mday
,
1295 tmdata
.tm_year
%100 ) ;
1296 answer
->len
= strlen(answer
->value
);
1300 chptr
= WeekDays
[tmdata
.tm_wday
] ;
1301 answer
->len
= strlen(chptr
);
1302 memcpy(answer
->value
, chptr
, answer
->len
) ;
1306 /* should not get here */
1314 streng
*std_words( tsd_t
*TSD
, cparamboxptr parms
)
1316 int space
=0, i
=0, j
=0 ;
1317 streng
*string
=NULL
;
1320 checkparam( parms
, 1, 1 , "WORDS" ) ;
1321 string
= parms
->value
;
1323 send
= Str_len(string
) ;
1325 for (i
=j
=0;send
>i
;i
++) {
1326 if ((!space
)&&(isspace(string
->value
[i
]))) j
++ ;
1327 space
= (isspace(string
->value
[i
])) ; }
1329 if ((!space
)&&(i
>0)) j
++ ;
1330 return( int_to_streng( TSD
, j
) ) ;
1334 streng
*std_word( tsd_t
*TSD
, cparamboxptr parms
)
1336 streng
*string
=NULL
, *result
=NULL
;
1337 int i
=0, j
=0, finished
=0, start
=0, stop
=0, number
=0, space
=0, slen
=0 ;
1339 checkparam( parms
, 2, 2 , "WORD" ) ;
1340 string
= parms
->value
;
1341 number
= atopos( TSD
, parms
->next
->value
, "WORD", 2 ) ;
1347 slen
= Str_len(string
) ;
1348 for (i
=j
=0;(slen
>i
)&&(!finished
);i
++)
1350 if ((space
)&&(!isspace(string
->value
[i
])))
1352 if ((!space
)&&(isspace(string
->value
[i
])))
1355 finished
= (++j
==number
) ;
1357 space
= (isspace(string
->value
[i
])) ;
1360 if ((!finished
)&&(((number
==j
+1)&&(!space
)) || ((number
==j
)&&(space
))))
1368 result
= Str_makeTSD(stop
-start
) ; /* problems with length */
1369 result
= Str_nocatTSD( result
, string
, stop
-start
, start
) ;
1370 result
->len
= stop
-start
;
1373 result
= nullstringptr() ;
1382 streng
*std_address( tsd_t
*TSD
, cparamboxptr parms
)
1386 checkparam( parms
, 0, 1 , "ADDRESS" ) ;
1388 if ( parms
&& parms
->value
)
1389 opt
= getoptionchar( TSD
, parms
->value
, "ADDRESS", 1, "EINO", "" ) ;
1391 update_envirs( TSD
, TSD
->currlevel
) ;
1392 return Str_dupTSD( TSD
->currlevel
->environment
) ;
1396 streng
*std_digits( tsd_t
*TSD
, cparamboxptr parms
)
1398 checkparam( parms
, 0, 0 , "DIGITS" ) ;
1399 return int_to_streng( TSD
, TSD
->currlevel
->currnumsize
) ;
1403 streng
*std_form( tsd_t
*TSD
, cparamboxptr parms
)
1405 checkparam( parms
, 0, 0 , "FORM" ) ;
1406 return Str_creTSD( numeric_forms
[TSD
->currlevel
->numform
] ) ;
1410 streng
*std_fuzz( tsd_t
*TSD
, cparamboxptr parms
)
1412 checkparam( parms
, 0, 0 , "FUZZ" ) ;
1413 return int_to_streng( TSD
, TSD
->currlevel
->numfuzz
) ;
1417 streng
*std_abbrev( tsd_t
*TSD
, cparamboxptr parms
)
1419 int length
=0, answer
=0, i
=0 ;
1420 streng
*longstr
=NULL
, *shortstr
=NULL
;
1422 checkparam( parms
, 2, 3 , "ABBREV" ) ;
1423 longstr
= parms
->value
;
1424 shortstr
= parms
->next
->value
;
1426 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
1427 length
= atozpos( TSD
, parms
->next
->next
->value
, "ABBREV", 3 ) ;
1429 length
= Str_len(shortstr
) ;
1431 answer
= (Str_ncmp(shortstr
,longstr
,length
)) ? 0 : 1 ;
1433 if ((length
>Str_len(shortstr
))||(Str_len(shortstr
)>Str_len(longstr
)))
1437 for (i
=length
; i
<Str_len(shortstr
); i
++)
1438 if (shortstr
->value
[i
] != longstr
->value
[i
])
1442 return int_to_streng( TSD
, answer
) ;
1446 streng
*std_qualify( tsd_t
*TSD
, cparamboxptr parms
)
1450 checkparam( parms
, 1, 1 , "QUALIFY" ) ;
1451 ret
= ConfigStreamQualified( TSD
, parms
->value
);
1452 if ( Str_len( ret
) == 0 )
1453 exiterror( ERR_INCORRECT_CALL
, 27, "QUALIFY", tmpstr_of( TSD
, parms
->value
) ) ;
1455 * Returned streng is always MAX_PATH long, so it should be safe
1456 * to Nul terminate the ret->value
1458 ret
->value
[ret
->len
] = '\0';
1462 streng
*std_queued( tsd_t
*TSD
, cparamboxptr parms
)
1464 checkparam( parms
, 0, 0 , "QUEUED" ) ;
1465 return int_to_streng( TSD
, lines_in_stack( TSD
, NULL
)) ;
1470 streng
*std_strip( tsd_t
*TSD
, cparamboxptr parms
)
1472 #if defined(_AMIGA) || defined(__AROS__)
1473 char option
='B', *padstr
=" ", alloc
=0;
1475 char option
='B', padch
=' ' ;
1477 streng
*input
=NULL
;
1478 int leading
=0, trailing
=0, start
=0, stop
=0 ;
1480 checkparam( parms
, 1, 3 , "STRIP" ) ;
1481 if ( ( parms
->next
)
1482 && ( parms
->next
->value
) )
1483 option
= getoptionchar( TSD
, parms
->next
->value
, "STRIP", 2, "LTB", "" );
1485 if ( ( parms
->next
)
1486 && ( parms
->next
->next
)
1487 && ( parms
->next
->next
->value
) )
1488 #if defined(_AMIGA) || defined(__AROS__)
1490 padstr
= str_of( TSD
, parms
->next
->next
->value
) ;
1494 padch
= getonechar( TSD
, parms
->next
->next
->value
, "STRIP", 3 ) ;
1497 input
= parms
->value
;
1498 leading
= ((option
=='B')||(option
=='L')) ;
1499 trailing
= ((option
=='B')||(option
=='T')) ;
1501 #if defined(_AMIGA) || defined(__AROS__)
1502 for (start
=0;(start
<Str_len(input
))&&strchr(padstr
,input
->value
[start
])&&(leading
);start
++) ;
1503 for (stop
=Str_len(input
)-1;(stop
>=start
)&&strchr(padstr
,input
->value
[stop
])&&(trailing
);stop
--) ;
1505 for (start
=0;(start
<Str_len(input
))&&(input
->value
[start
]==padch
)&&(leading
);start
++) ;
1506 for (stop
=Str_len(input
)-1;(stop
>=start
)&&(input
->value
[stop
]==padch
)&&(trailing
);stop
--) ;
1509 stop
= start
- 1 ; /* FGC: If this happens, it will crash */
1511 #if defined(_AMIGA) || defined(__AROS__)
1515 return Str_nocatTSD(Str_makeTSD(stop
-start
+2),input
,stop
-start
+1, start
) ;
1520 streng
*std_space( tsd_t
*TSD
, cparamboxptr parms
)
1522 streng
*retval
=NULL
, *string
=NULL
;
1524 int i
=0, j
=0, k
=0, l
=0, space
=1, length
=1, hole
=0 ;
1526 checkparam( parms
, 1, 3 , "SPACE" ) ;
1527 if ( ( parms
->next
)
1528 && ( parms
->next
->value
) )
1529 length
= atozpos( TSD
, parms
->next
->value
, "SPACE", 2 ) ;
1531 if ( ( parms
->next
)
1532 && ( parms
->next
->next
)
1533 && ( parms
->next
->next
->value
) )
1534 padch
= getonechar( TSD
, parms
->next
->next
->value
, "SPACE", 3 ) ;
1536 string
= parms
->value
;
1537 for ( i
= 0; Str_in( string
, i
); i
++ )
1539 if ((space
)&&(string
->value
[i
]!=' ')) hole
++ ;
1540 space
= (string
->value
[i
]==' ') ;
1544 retval
= Str_makeTSD(i
+ hole
*length
) ;
1545 for (j
=l
=i
=0;Str_in(string
,i
);i
++)
1547 if (!((space
)&&(string
->value
[i
]==' ')))
1549 if ((space
=(string
->value
[i
]==' '))!=0)
1550 for (l
=j
,k
=0;k
<length
;k
++)
1551 retval
->value
[j
++] = padch
;
1553 retval
->value
[j
++] = string
->value
[i
] ;
1559 retval
->len
-= length
;
1565 streng
*std_arg( tsd_t
*TSD
, cparamboxptr parms
)
1567 int number
=0, retval
=0, tmpval
=0 ;
1569 streng
*value
=NULL
;
1570 paramboxptr ptr
=NULL
;
1572 checkparam( parms
, 0, 2 , "ARG" ) ;
1574 && ( parms
->value
) )
1576 number
= atopos( TSD
, parms
->value
, "ARG", 1 ) ;
1578 flag
= getoptionchar( TSD
, parms
->next
->value
, "ARG", 2, "ENO", "" ) ;
1581 ptr
= TSD
->currlevel
->args
;
1584 for (retval
=0,tmpval
=1; ptr
; ptr
=ptr
->next
, tmpval
++)
1588 value
= int_to_streng( TSD
, retval
) ;
1593 for (retval
=1;(retval
<number
)&&(ptr
)&&((ptr
=ptr
->next
)!=NULL
);retval
++) ;
1597 retval
= ((ptr
)&&(ptr
->value
)) ;
1598 value
= int_to_streng( TSD
, retval
? 1 : 0 ) ;
1601 retval
= ((ptr
)&&(ptr
->value
)) ;
1602 value
= int_to_streng( TSD
, retval
? 0 : 1 ) ;
1605 if ((ptr
)&&(ptr
->value
))
1606 value
= Str_dupTSD(ptr
->value
) ;
1608 value
= nullstringptr() ;
1622 static char logic( char first
, char second
, int ltype
)
1626 case ( LOGIC_AND
) : return (char)( first
& second
) ;
1627 case ( LOGIC_OR
) : return (char)( first
| second
) ;
1628 case ( LOGIC_XOR
) : return (char)( first
^ second
) ;
1630 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
1632 /* not reached, next line only to satisfy compiler */
1637 static streng
*misc_logic( tsd_t
*TSD
, int ltype
, cparamboxptr parms
, const char *bif
, int argnum
)
1639 int length1
=0, length2
=0, i
=0 ;
1642 streng
*pad
=NULL
, *outstr
=NULL
, *str1
=NULL
, *str2
=NULL
;
1644 checkparam( parms
, 1, 3 , bif
) ;
1645 str1
= parms
->value
;
1647 str2
= (parms
->next
) ? (parms
->next
->value
) : NULL
;
1649 kill
= str2
= nullstringptr() ;
1653 if ((parms
->next
)&&(parms
->next
->next
))
1654 pad
= parms
->next
->next
->value
;
1659 padch
= getonechar( TSD
, pad
, bif
, argnum
) ;
1665 length1
= Str_len(str1
) ;
1666 length2
= Str_len(str2
) ;
1667 if (length2
> length1
)
1675 outstr
= Str_makeTSD( Str_len(str1
) ) ;
1677 for (i
=0; Str_in(str2
,i
); i
++)
1678 outstr
->value
[i
] = logic( str1
->value
[i
], str2
->value
[i
], ltype
) ;
1681 for (; Str_in(str1
,i
); i
++)
1682 outstr
->value
[i
] = logic( str1
->value
[i
], padch
, ltype
) ;
1684 for (; Str_in(str1
,i
); i
++)
1685 outstr
->value
[i
] = str1
->value
[i
] ;
1688 Free_stringTSD( kill
) ;
1694 streng
*std_bitand( tsd_t
*TSD
, cparamboxptr parms
)
1696 return misc_logic( TSD
, LOGIC_AND
, parms
, "BITAND", 3 ) ;
1699 streng
*std_bitor( tsd_t
*TSD
, cparamboxptr parms
)
1701 return misc_logic( TSD
, LOGIC_OR
, parms
, "BITOR", 3 ) ;
1704 streng
*std_bitxor( tsd_t
*TSD
, cparamboxptr parms
)
1706 return misc_logic( TSD
, LOGIC_XOR
, parms
, "BITXOR", 3 ) ;
1710 streng
*std_center( tsd_t
*TSD
, cparamboxptr parms
)
1712 int length
=0, i
=0, j
=0, start
=0, stop
=0, chars
=0 ;
1714 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1716 checkparam( parms
, 2, 3 , "CENTER" ) ;
1717 length
= atozpos( TSD
, parms
->next
->value
, "CENTER", 2 ) ;
1718 str
= parms
->value
;
1719 if (parms
->next
->next
!=NULL
)
1720 pad
= parms
->next
->next
->value
;
1724 chars
= Str_len(str
) ;
1728 padch
= getonechar( TSD
, pad
, "CENTER", 3 ) ;
1730 start
= (chars
>length
) ? ((chars
-length
)/2) : 0 ;
1731 stop
= (chars
>length
) ? (chars
-(chars
-length
+1)/2) : chars
;
1733 ptr
= Str_makeTSD( length
) ;
1734 for (j
=0;j
<((length
-chars
)/2);ptr
->value
[j
++]=padch
) ;
1735 for (i
=start
;i
<stop
;ptr
->value
[j
++]=str
->value
[i
++]) ;
1736 for (;j
<length
;ptr
->value
[j
++]=padch
) ;
1739 assert((ptr
->len
<=ptr
->max
) && (j
==length
));
1744 static unsigned num_sourcelines(const internal_parser_type
*ipt
)
1748 if (ipt
->first_source_line
!= NULL
)
1749 return ipt
->last_source_line
->lineno
;
1751 /* must be incore_source but that value may be NULL because of a failed
1752 * instore[0] of RexxStart!
1754 if ((otp
= ipt
->srclines
) == NULL
)
1755 return 0; /* May happen if the user doesn't provides the true
1756 * source. If you set it to 1 you must return anything
1757 * below for that line.
1761 return otp
->sum
+ otp
->num
;
1764 streng
*std_sourceline( tsd_t
*TSD
, cparamboxptr parms
)
1768 const internal_parser_type
*ipt
= &TSD
->systeminfo
->tree
;
1773 checkparam( parms
, 0, 1 , "SOURCELINE" ) ;
1775 return int_to_streng( TSD
, num_sourcelines( ipt
) ) ;
1777 line
= atopos( TSD
, parms
->value
, "SOURCELINE", 1 ) ;
1779 if (ipt
->first_source_line
== NULL
)
1780 { /* must be incore_source but that value may be NULL because of a failed
1781 * instore[0] of RexxStart!
1783 otp
= ipt
->srclines
; /* NULL if incore_source==NULL */
1786 while (otp
&& ((int) otp
->num
< line
))
1792 if ((otp
== NULL
) || /* line not found or error */
1795 exiterror( ERR_INCORRECT_CALL
, 34, "SOURCELINE", 1, line
, num_sourcelines( ipt
) ) ;
1799 i
= otp
->elems
[line
].length
;
1800 retval
= Str_makeTSD( i
) ;
1802 memcpy( retval
->value
, ipt
->incore_source
+ otp
->elems
[line
].offset
, i
) ;
1805 if (bt
->srcline_first
!= ipt
->first_source_line
)
1807 bt
->srcline_lineno
= 1 ;
1810 ipt
->first_source_line
;
1812 for (;(bt
->srcline_lineno
<line
);)
1814 if ((bt
->srcline_ptr
=bt
->srcline_ptr
->next
)==NULL
)
1816 exiterror( ERR_INCORRECT_CALL
, 34, "SOURCELINE", 1, line
, num_sourcelines( ipt
) ) ;
1818 bt
->srcline_lineno
= bt
->srcline_ptr
->lineno
;
1820 for (;(bt
->srcline_lineno
>line
);)
1822 if ((bt
->srcline_ptr
=bt
->srcline_ptr
->prev
)==NULL
)
1823 exiterror( ERR_INCORRECT_CALL
, 0 ) ;
1824 bt
->srcline_lineno
= bt
->srcline_ptr
->lineno
;
1827 return Str_dupTSD(bt
->srcline_ptr
->line
) ;
1831 streng
*std_compare( tsd_t
*TSD
, cparamboxptr parms
)
1834 streng
*pad
=NULL
, *str1
=NULL
, *str2
=NULL
;
1835 int i
=0, j
=0, value
=0 ;
1837 checkparam( parms
, 2, 3 , "COMPARE" ) ;
1838 str1
= parms
->value
;
1839 str2
= parms
->next
->value
;
1840 if (parms
->next
->next
)
1841 pad
= parms
->next
->next
->value
;
1848 padch
= getonechar( TSD
, pad
, "COMPARE", 3) ;
1851 while ((Str_in(str1
,i
))||(Str_in(str2
,j
))) {
1852 if (((Str_in(str1
,i
))?(str1
->value
[i
]):(padch
))!=
1853 ((Str_in(str2
,j
))?(str2
->value
[j
]):(padch
))) {
1854 value
= (i
>j
) ? i
: j
;
1856 if (Str_in(str1
,i
)) i
++ ;
1857 if (Str_in(str2
,j
)) j
++ ; }
1859 if ((!Str_in(str1
,i
))&&(!Str_in(str2
,j
)))
1864 return int_to_streng( TSD
, value
) ;
1868 streng
*std_errortext( tsd_t
*TSD
, cparamboxptr parms
)
1871 streng
*tmp
,*tmp1
,*tmp2
;
1872 int numdec
=0, errnum
, suberrnum
, pos
=0, i
;
1874 const char *err
=NULL
;
1877 checkparam( parms
, 1, 2 , "ERRORTEXT" ) ;
1879 if (parms
&&parms
->next
&&parms
->next
->value
)
1880 opt
= getoptionchar( TSD
, parms
->next
->value
, "ERRORTEXT", 2, "NS", "" ) ;
1881 tmp
= Str_dupTSD( parms
->value
);
1882 for (i
=0; i
<Str_len( tmp
); i
++ )
1884 if ( *( tmp
->value
+i
) == '.' )
1887 *( tmp
->value
+i
) = '\0';
1892 exiterror( ERR_INCORRECT_CALL
, 11, 1, tmpstr_of( TSD
, parms
->value
) ) ;
1896 tmp1
= Str_ncreTSD( tmp
->value
, pos
);
1897 tmp2
= Str_ncreTSD( tmp
->value
+pos
+1, Str_len( tmp
) - pos
- 1 );
1898 errnum
= atoposorzero( TSD
, tmp1
, "ERRORTEXT", 1 );
1899 suberrnum
= atopos( TSD
, tmp2
, "ERRORTEXT", 1 );
1900 Free_stringTSD( tmp1
) ;
1901 Free_stringTSD( tmp2
) ;
1905 errnum
= atoposorzero( TSD
, tmp
, "ERRORTEXT", 1 );
1909 * Only restrict the error number passed if STRICT_ANSI is in effect.
1911 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
)
1912 && ( errnum
> 90 || suberrnum
> 900 ) )
1913 exiterror( ERR_INCORRECT_CALL
, 17, "ERRORTEXT", tmpstr_of( TSD
, parms
->value
) ) ;
1915 Free_stringTSD( tmp
) ;
1918 if ( suberrnum
== 0)
1919 return Str_creTSD( errortext( errnum
) ) ;
1922 err
= suberrortext( errnum
, suberrnum
);
1924 return Str_creTSD( "" );
1926 return Str_creTSD( err
);
1929 return Str_creTSD( errortext( TSD
, errnum
, suberrnum
, (opt
=='S')?1:0, 1 ) ) ;
1934 streng
*std_length( tsd_t
*TSD
, cparamboxptr parms
)
1936 checkparam( parms
, 1, 1 , "LENGTH" ) ;
1937 return int_to_streng( TSD
, Str_len( parms
->value
)) ;
1941 streng
*std_left( tsd_t
*TSD
, cparamboxptr parms
)
1945 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1947 checkparam( parms
, 2, 3 , "LEFT" ) ;
1948 length
= atozpos( TSD
, parms
->next
->value
, "LEFT", 2 ) ;
1949 str
= parms
->value
;
1950 if (parms
->next
->next
!=NULL
)
1951 pad
= parms
->next
->next
->value
;
1958 padch
= getonechar( TSD
, pad
, "LEFT", 3) ;
1960 ptr
= Str_makeTSD( length
) ;
1961 for (i
=0;(i
<length
)&&(Str_in(str
,i
));i
++)
1962 ptr
->value
[i
] = str
->value
[i
] ;
1964 for (;i
<length
;ptr
->value
[i
++]=padch
) ;
1970 streng
*std_right( tsd_t
*TSD
, cparamboxptr parms
)
1972 int length
=0, i
=0, j
=0 ;
1974 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
1976 checkparam( parms
, 2, 3 , "RIGHT" ) ;
1977 length
= atozpos( TSD
, parms
->next
->value
, "RIGHT", 2 ) ;
1978 str
= parms
->value
;
1979 if (parms
->next
->next
!=NULL
)
1980 pad
= parms
->next
->next
->value
;
1987 padch
= getonechar( TSD
, pad
, "RIGHT", 3 ) ;
1989 ptr
= Str_makeTSD( length
) ;
1990 for (j
=0;Str_in(str
,j
);j
++) ;
1991 for (i
=length
-1,j
--;(i
>=0)&&(j
>=0);ptr
->value
[i
--]=str
->value
[j
--]) ;
1993 for (;i
>=0;ptr
->value
[i
--]=padch
) ;
2000 streng
*std_verify( tsd_t
*TSD
, cparamboxptr parms
)
2002 char tab
[256], ch
=' ' ;
2003 streng
*str
=NULL
, *ref
=NULL
;
2004 int inv
=0, start
=0, res
=0, i
=0 ;
2006 checkparam( parms
, 2, 4 , "VERIFY" ) ;
2008 str
= parms
->value
;
2009 ref
= parms
->next
->value
;
2010 if ( parms
->next
->next
)
2012 if ( parms
->next
->next
->value
)
2014 ch
= getoptionchar( TSD
, parms
->next
->next
->value
, "VERIFY", 3, "MN", "" ) ;
2018 if (parms
->next
->next
->next
)
2019 start
= atopos( TSD
, parms
->next
->next
->next
->value
, "VERIFY", 4 ) - 1 ;
2022 for (i
=0;i
<256;tab
[i
++]=0) ;
2023 for (i
=0;Str_in(ref
,i
);tab
[(unsigned char)(ref
->value
[i
++])]=1) ;
2024 for (i
=start
;(Str_in(str
,i
))&&(!res
);i
++)
2026 if (inv
==(tab
[(unsigned char)(str
->value
[i
])]))
2030 return int_to_streng( TSD
, res
) ;
2035 streng
*std_substr( tsd_t
*TSD
, cparamboxptr parms
)
2037 int rlength
=0, length
=0, start
=0, i
=0, j
=0 ;
2039 streng
*pad
=NULL
, *str
=NULL
, *ptr
=NULL
;
2040 paramboxptr bptr
=NULL
;
2042 checkparam( parms
, 2, 4 , "SUBSTR" ) ;
2043 str
= parms
->value
;
2044 rlength
= Str_len( str
) ;
2045 start
= atopos( TSD
, parms
->next
->value
, "SUBSTR", 2 ) ;
2046 if ( ( (bptr
= parms
->next
->next
) != NULL
)
2047 && ( parms
->next
->next
->value
) )
2048 length
= atozpos( TSD
, parms
->next
->next
->value
, "SUBSTR", 3 ) ;
2050 length
= ( rlength
>= start
) ? rlength
- start
+ 1 : 0;
2054 && ( bptr
->next
->value
) )
2055 pad
= parms
->next
->next
->next
->value
;
2060 padch
= getonechar( TSD
, pad
, "SUBSTR", 4) ;
2062 ptr
= Str_makeTSD( length
) ;
2063 i
= ((rlength
>=start
)?start
-1:rlength
) ;
2064 for (j
=0;j
<length
;ptr
->value
[j
++]=(char)((Str_in(str
,i
))?str
->value
[i
++]:padch
)) ;
2072 streng
*std_max( tsd_t
*TSD
, cparamboxptr parms
)
2074 double largest
=0, current
=0 ;
2075 cparamboxptr ptr
=NULL
;
2076 streng
*result
=NULL
;
2078 if (!(ptr
=parms
)->value
)
2079 exiterror( ERR_INCORRECT_CALL
, 3, "MAX", 1 ) ;
2081 largest
= myatof( TSD
, ptr
->value
) ;
2083 for(;ptr
;ptr
=ptr
->next
)
2084 if ((ptr
->value
)&&((current
=myatof(TSD
,ptr
->value
))>largest
))
2087 result
= Str_makeTSD( sizeof(double)*3+7 ) ;
2088 sprintf(result
->value
, "%G", largest
) ;
2089 result
->len
= strlen(result
->value
) ;
2095 streng
*std_min( tsd_t
*TSD
, cparamboxptr parms
)
2097 double smallest
=0, current
=0 ;
2098 cparamboxptr ptr
=NULL
;
2099 streng
*result
=NULL
;
2101 if (!(ptr
=parms
)->value
)
2102 exiterror( ERR_INCORRECT_CALL
, 3, "MIN", 1 ) ;
2104 smallest
= myatof( TSD
, ptr
->value
) ;
2106 for(;ptr
;ptr
=ptr
->next
)
2107 if ((ptr
->value
)&&((current
=myatof(TSD
,ptr
->value
))<smallest
))
2108 smallest
= current
;
2110 result
= Str_makeTSD( sizeof(double)*3+7 ) ;
2111 sprintf(result
->value
, "%G", smallest
) ;
2112 result
->len
= strlen(result
->value
) ;
2118 streng
*std_reverse( tsd_t
*TSD
, cparamboxptr parms
)
2123 checkparam( parms
, 1, 1 , "REVERSE" ) ;
2125 ptr
= Str_makeTSD(j
=Str_len(parms
->value
)) ;
2127 for (i
=0;j
>=0;ptr
->value
[i
++]=parms
->value
->value
[j
--]) ;
2132 streng
*std_random( tsd_t
*TSD
, cparamboxptr parms
)
2134 int min
=0, max
=999, result
=0 ;
2135 #if defined(HAVE_RANDOM)
2141 checkparam( parms
, 0, 3 , "RANDOM" ) ;
2147 min
= atozpos( TSD
, parms
->value
, "RANDOM", 1 ) ;
2150 max
= atozpos( TSD
, parms
->value
, "RANDOM", 1 ) ;
2152 exiterror( ERR_INCORRECT_CALL
, 31, "RANDOM", max
) ;
2155 if (parms
->next
!=NULL
)
2157 if (parms
->next
->value
!=NULL
)
2158 max
= atozpos( TSD
, parms
->next
->value
, "RANDOM", 2 ) ;
2160 if (parms
->next
->next
!=NULL
&&parms
->next
->next
->value
!=NULL
)
2162 seed
= atozpos( TSD
, parms
->next
->next
->value
, "RANDOM", 3 ) ;
2163 #if defined(HAVE_RANDOM)
2173 exiterror( ERR_INCORRECT_CALL
, 33, "RANDOM", min
, max
) ;
2174 if (max
-min
> 100000)
2175 exiterror( ERR_INCORRECT_CALL
, 32, "RANDOM", min
, max
) ;
2177 #if defined(HAVE_RANDOM)
2178 result
= (random() % (max
-min
+1)) + min
;
2180 # if RAND_MAX < 100000
2181 /* result = (((rand() * 100) + (clock() % 100)) % (max-min+1)) + min ; */
2182 result
= (((rand() * RAND_MAX
) + rand() ) % (max
-min
+1)) + min
; /* pgb */
2184 result
= (rand() % (max
-min
+1)) + min
;
2187 return int_to_streng( TSD
, result
) ;
2191 streng
*std_copies( tsd_t
*TSD
, cparamboxptr parms
)
2194 int copies
=0, i
=0, length
=0 ;
2196 checkparam( parms
, 2, 2 , "COPIES" ) ;
2198 length
= Str_len(parms
->value
) ;
2199 copies
= atozpos( TSD
, parms
->next
->value
, "COPIES", 2 ) * length
;
2200 ptr
= Str_makeTSD( copies
) ;
2201 for (i
=0;i
<copies
;i
+=length
)
2202 memcpy(ptr
->value
+i
,parms
->value
->value
,length
) ;
2209 streng
*std_sign( tsd_t
*TSD
, cparamboxptr parms
)
2213 checkparam( parms
, 1, 1 , "SIGN" ) ;
2215 number
= myatof( TSD
, parms
->value
) ;
2216 return int_to_streng( TSD
,(number
) ? ((number
>0) ? 1 : -1) : 0 ) ;
2220 streng
*std_trunc( tsd_t
*TSD
, cparamboxptr parms
)
2224 checkparam( parms
, 1, 2 , "TRUNC" ) ;
2225 if ((parms
->next
)&&(parms
->next
->value
))
2226 decimals
= atozpos( TSD
, parms
->next
->value
, "TRUNC", 2 ) ;
2228 return str_trunc( TSD
, parms
->value
, decimals
) ;
2232 streng
*std_translate( tsd_t
*TSD
, cparamboxptr parms
)
2234 streng
*iptr
=NULL
, *optr
=NULL
;
2236 streng
*string
=NULL
, *result
=NULL
;
2237 paramboxptr ptr
=NULL
;
2238 int olength
=0, i
=0, ii
=0 ;
2240 checkparam( parms
, 1, 4 , "TRANSLATE" ) ;
2242 string
= parms
->value
;
2243 if ( ( (ptr
= parms
->next
) != NULL
)
2244 && ( parms
->next
->value
) )
2246 optr
= parms
->next
->value
;
2247 olength
= Str_len( optr
) ;
2251 && ( (ptr
= ptr
->next
) != NULL
)
2258 && ( (ptr
= ptr
->next
) != NULL
)
2260 padch
= getonechar( TSD
, ptr
->value
, "TRANSLATE", 4 ) ;
2262 result
= Str_makeTSD( Str_len(string
) ) ;
2263 for (i
=0; Str_in(string
,i
); i
++)
2265 if ((!iptr
)&&(!optr
))
2266 result
->value
[i
] = (char) toupper(string
->value
[i
]) ;
2271 for (ii
=0; Str_in(iptr
,ii
); ii
++)
2272 if (iptr
->value
[ii
]==string
->value
[i
])
2275 if (ii
==Str_len(iptr
))
2277 result
->value
[i
] = string
->value
[i
] ;
2282 ii
= ((unsigned char*)string
->value
)[i
] ;
2284 if ((optr
)&&(ii
<olength
))
2285 result
->value
[i
] = optr
->value
[ii
] ;
2287 result
->value
[i
] = padch
;
2296 streng
*std_delstr( tsd_t
*TSD
, cparamboxptr parms
)
2298 int i
=0, j
=0, length
=0, sleng
=0, start
=0 ;
2299 streng
*string
=NULL
, *result
=NULL
;
2301 checkparam( parms
, 2, 3 , "DELSTR" ) ;
2303 sleng
= Str_len((string
= parms
->value
)) ;
2304 start
= atozpos( TSD
, parms
->next
->value
, "DELSTR", 2 ) ;
2306 if ((parms
->next
->next
)&&(parms
->next
->next
->value
))
2307 length
= atozpos( TSD
, parms
->next
->next
->value
, "DELSTR", 3 ) ;
2309 length
= Str_len( string
) - start
+ 1 ;
2314 result
= Str_makeTSD( (start
+length
>sleng
) ? start
: sleng
-length
) ;
2316 for (i
=j
=0; (Str_in(string
,i
))&&(i
<start
-1); result
->value
[i
++] = string
->value
[j
++]) ;
2318 for (; (j
<=sleng
)&&(Str_in(string
,j
)); result
->value
[i
++] = string
->value
[j
++] ) ;
2328 static int valid_hex_const( const streng
*str
)
2330 const char *ptr
=NULL
, *end_ptr
=NULL
;
2334 end_ptr
= ptr
+ str
->len
;
2336 if ((end_ptr
>ptr
) && ((isspace(*ptr
)) || (isspace(*(end_ptr
-1)))))
2338 return 0 ; /* leading or trailing space */
2342 for (; ptr
<end_ptr
; ptr
++)
2350 else if (space_stat
==1)
2352 /* non-even number of hex digits in non-first group */
2356 else if (isxdigit(*ptr
))
2359 space_stat
= ((space_stat
==1) ? 2 : 1) ;
2363 return 0 ; /* neither space nor hex digit */
2369 /* non-even number of digits in last grp, which not also first grp */
2373 /* note: the nullstring is a valid hexstring */
2374 return 1 ; /* a valid hex string */
2377 static int valid_binary_const( const streng
*str
)
2378 /* check for valid binary streng. returns 1 for TRUE, 0 for FALSE */
2385 if ((len
= Str_len(str
))==0)
2386 return(1); /* ANSI */
2387 len
--; /* on last char */
2389 if (isspace(ptr
[0]) || isspace(ptr
[len
]))
2390 return(0); /* leading or trailing space */
2391 /* ptr must consist of 0 1nd 1. After a blank follows a blank or a block
2392 * of four digits. Since the first block of binary digits may contain
2393 * less than four digits, we casn parse backwards and check only filled
2394 * block till we reach the start. Thanks to ANSI testing program. */
2395 for (digits
= 0; len
>= 0; len
--)
2400 if ((digits
% 4) != 0)
2403 else if ((c
!= '0') && (c
!= '1'))
2411 streng
*std_datatype( tsd_t
*TSD
, cparamboxptr parms
)
2413 streng
*string
=NULL
, *result
=NULL
;
2414 char option
=' ', ch
=' ', *cptr
=NULL
;
2417 checkparam( parms
, 1, 2 , "DATATYPE" ) ;
2419 string
= parms
->value
;
2421 if ((parms
->next
)&&(parms
->next
->value
))
2423 option
= getoptionchar( TSD
, parms
->next
->value
, "DATATYPE", 2, "ABLMNSUWX", "" ) ;
2425 cptr
= string
->value
;
2426 if ((Str_len(string
)==0)&&(option
!='X')&&(option
!='B'))
2432 for (; cptr
<Str_end(string
); res
= isalnum(*cptr
++) && res
) ;
2436 res
= valid_binary_const( string
);
2440 for (; cptr
<Str_end(string
); res
= islower(*cptr
++) && res
) ;
2444 for (; cptr
<Str_end(string
); res
= isalpha(*cptr
++) && res
) ;
2448 res
= myisnumber(string
) ;
2452 /* "... if string only contains characters that are valid
2453 * in REXX symbols ...", so it really does not say that
2454 * string should be a valid symbol. Actually, according
2455 * to this statement, '1234E+2' is a valid symbol, although
2456 * is returns false from datatype('1234E+2','S')
2458 for (; cptr
<Str_end(string
); cptr
++)
2461 res
&= ( ((ch
<='z')&&(ch
>='a')) || ((ch
<='Z')&&(ch
>='A'))
2462 || ((ch
<='9')&&(ch
>='0')) || (ch
=='.')
2463 || (ch
=='@') || (ch
=='#') || (ch
=='$')
2464 || (ch
=='?') || (ch
=='_') || (ch
=='!')) ;
2469 for (; cptr
<Str_end(string
); res
= isupper(*cptr
++) && res
) ;
2473 res
= myiswnumber(TSD
, string
) ;
2477 res
= valid_hex_const( string
) ;
2481 /* shouldn't get here */
2484 result
= int_to_streng( TSD
, res
) ;
2488 cptr
= ((string
->len
)&&(myisnumber(string
))) ? "NUM" : "CHAR" ;
2489 result
= Str_creTSD( cptr
) ;
2496 streng
*std_trace( tsd_t
*TSD
, cparamboxptr parms
)
2498 streng
*result
=NULL
, *string
=NULL
;
2501 checkparam( parms
, 0, 1 , "TRACE" ) ;
2503 result
= Str_makeTSD( 3 ) ;
2504 if (TSD
->systeminfo
->interactive
)
2505 result
->value
[i
++] = '?' ;
2507 result
->value
[i
++] = (char) TSD
->trace_stat
;
2512 if ((string
=parms
->value
))
2514 if (string
->value
[i
]=='?')
2517 TSD
->systeminfo
->interactive
= 1 ;
2521 TSD
->currlevel
->tracestat
=
2522 toupper( getoptionchar(TSD
, string
)) ;
2527 string
= Str_dupTSD( parms
->value
);
2528 for (i
= 0; i
< string
->len
; i
++ )
2530 if ( string
->value
[ i
] == '?' )
2531 TSD
->systeminfo
->interactive
= ( TSD
->systeminfo
->interactive
) ? 0 : 1;
2536 TSD
->currlevel
->tracestat
= getoptionchar( TSD
, Str_strp( string
, '?', STRIP_LEADING
),
2540 Free_stringTSD( string
);
2547 streng
*std_changestr( tsd_t
*TSD
, cparamboxptr parms
)
2549 streng
*needle
=NULL
, *heystack
=NULL
, *new_needle
=NULL
, *retval
=NULL
;
2550 int neelen
=0, heylen
=0, newlen
=0, newneelen
=0, cnt
=0, start
=0, i
=0, heypos
=0, retpos
=0 ;
2552 checkparam( parms
, 3, 3, "CHANGESTR" ) ;
2553 needle
= parms
->value
;
2554 heystack
= parms
->next
->value
;
2555 new_needle
= parms
->next
->next
->value
;
2557 neelen
= Str_len(needle
) ;
2558 heylen
= Str_len(heystack
) ;
2559 newneelen
= Str_len(new_needle
) ;
2561 /* find number of occurrences of needle in heystack */
2562 if ((!needle
->len
)||(!heystack
->len
)||(needle
->len
>heystack
->len
))
2568 start
= bmstrstr(heystack
, start
, needle
);
2572 start
+= needle
->len
;
2575 newlen
= 1 + heylen
+ ((newneelen
-neelen
) * cnt
);
2576 retval
= Str_makeTSD(newlen
) ;
2579 return (Str_ncpyTSD(retval
,heystack
,heylen
));
2581 start
=heypos
=retpos
=0;
2584 start
= bmstrstr(heystack
, start
, needle
);
2587 cnt
= heylen
-heypos
;
2588 for(i
=0;i
<cnt
;retval
->value
[retpos
++]=heystack
->value
[heypos
++],i
++) ;
2592 for(i
=0;i
<cnt
;retval
->value
[retpos
++]=heystack
->value
[heypos
++],i
++) ;
2593 for(i
=0;i
<neelen
;heypos
++,i
++) ;
2594 for(i
=0;i
<newneelen
;retval
->value
[retpos
++]=new_needle
->value
[i
++]) ;
2598 retval
->value
[retpos
] = '\0';
2603 streng
*std_countstr( tsd_t
*TSD
, cparamboxptr parms
)
2605 int start
=0, cnt
=0 ;
2606 streng
*needle
=NULL
, *heystack
=NULL
;
2607 checkparam( parms
, 2, 2 , "COUNTSTR" ) ;
2609 needle
= parms
->value
;
2610 heystack
= parms
->next
->value
;
2612 if ((!needle
->len
)||(!heystack
->len
))
2618 start
= bmstrstr(heystack
, start
, needle
);
2622 start
+= needle
->len
;
2626 return (int_to_streng( TSD
, cnt
) ) ;