1 /*
2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #include "rexx.h"
21 #include "rxiface.h"
22 #include <string.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include <time.h>
26
27 static streng *conflict_close( tsd_t *TSD, cparamboxptr parms );
28 static streng *conflict_eof( tsd_t *TSD, cparamboxptr parms );
29 static streng *conflict_open( tsd_t *TSD, cparamboxptr parms );
30
31 struct function_type
32 {
33 int compat ;
34 streng *(*function)(tsd_t *,cparamboxptr) ;
35 const char *funcname ;
36 } ;
37
38 /*
39 * A 0 in the first column of this table indicates that this BIF is ANSI.
40 * Any other value
41 */
42 static const struct function_type functions[] = {
43 { 0, std_abbrev, "ABBREV" },
44 { 0, std_abs, "ABS" },
45 { 0, std_address, "ADDRESS" },
46 #ifdef TRACEMEM
47 { EXT_REGINA_BIFS,dbg_allocated, "ALLOCATED" },
48 #endif
49 { 0, std_arg, "ARG" },
50 { EXT_AREXX_BIFS, arexx_b2c, "B2C" },
51 { 0, std_b2x, "B2X" },
52 { EXT_REGINA_BIFS,os2_beep, "BEEP" },
53 { 0, std_bitand, "BITAND" },
54 { EXT_AREXX_BIFS, arexx_bitchg, "BITCHG" },
55 { EXT_AREXX_BIFS, arexx_bitclr, "BITCLR" },
56 { EXT_AREXX_BIFS, arexx_bitcomp, "BITCOMP" },
57 { 0, std_bitor, "BITOR" },
58 { EXT_AREXX_BIFS, arexx_bitset, "BITSET" },
59 { EXT_AREXX_BIFS, arexx_bittst, "BITTST" },
60 { 0, std_bitxor, "BITXOR" },
61 { EXT_BUFTYPE_BIF,cms_buftype, "BUFTYPE" },
62 { EXT_AREXX_BIFS, arexx_c2b, "C2B" },
63 { 0, std_c2d, "C2D" },
64 { 0, std_c2x, "C2X" },
65 { EXT_REGINA_BIFS,unx_chdir, "CD" },
66 { 0, std_center, "CENTER" },
67 { 0, std_center, "CENTRE" },
68 { 0, std_changestr, "CHANGESTR" }, /* ANSI Std 1996 - MH 10-06-96 */
69 { 0, std_charin, "CHARIN" },
70 { 0, std_charout, "CHAROUT" },
71 { 0, std_chars, "CHARS" },
72 { EXT_REGINA_BIFS,unx_chdir, "CHDIR" },
73 { EXT_REGINA_BIFS,conflict_close, "CLOSE" },
74 { 0, std_compare, "COMPARE" },
75 { EXT_AREXX_BIFS, arexx_compress, "COMPRESS" },
76 { 0, std_condition, "CONDITION" },
77 { 0, std_copies, "COPIES" },
78 { 0, std_countstr, "COUNTSTR" }, /* ANSI Std 1996 - MH 10-06-96 */
79 { EXT_REGINA_BIFS,unx_crypt, "CRYPT" },
80 { 0, std_d2c, "D2C" },
81 { 0, std_d2x, "D2X" },
82 { 0, std_datatype, "DATATYPE" },
83 { 0, std_date, "DATE" },
84 { 0, std_delstr, "DELSTR" },
85 { 0, std_delword, "DELWORD" },
86 { EXT_DESBUF_BIF, cms_desbuf, "DESBUF" },
87 { 0, std_digits, "DIGITS" },
88 { EXT_REGINA_BIFS,os2_directory, "DIRECTORY" },
89 { EXT_DROPBUF_BIF,cms_dropbuf, "DROPBUF" },
90 #ifndef NDEBUG
91 { EXT_REGINA_BIFS,dbg_dumpfiles, "DUMPFILES" },
92 { EXT_REGINA_BIFS,dbg_dumptree, "DUMPTREE" },
93 { EXT_REGINA_BIFS,dbg_dumpvars, "DUMPVARS" },
94 #endif
95 { EXT_REGINA_BIFS,conflict_eof, "EOF" },
96 { 0, std_errortext, "ERRORTEXT" },
97 { EXT_AREXX_BIFS, arexx_exists, "EXISTS" },
98 { EXT_AREXX_BIFS, arexx_export, "EXPORT" },
99 #ifdef VMS
100 { EXT_REGINA_BIFS,vms_f_cvsi, "F$CVSI" },
101 { EXT_REGINA_BIFS,vms_f_cvtime, "F$CVTIME" },
102 { EXT_REGINA_BIFS,vms_f_cvui, "F$CVUI" },
103 { EXT_REGINA_BIFS,vms_f_directory, "F$DIRECTORY" },
104 { EXT_REGINA_BIFS,vms_f_element, "F$ELEMENT" },
105 { EXT_REGINA_BIFS,vms_f_extract, "F$EXTRACT" },
106 { EXT_REGINA_BIFS,vms_f_fao, "F$FAO" },
107 { EXT_REGINA_BIFS,vms_f_file_attributes, "F$FILE_ATTRIBUTES" },
108 { EXT_REGINA_BIFS,vms_f_getdvi, "F$GETDVI" },
109 { EXT_REGINA_BIFS,vms_f_getjpi, "F$GETJPI" },
110 { EXT_REGINA_BIFS,vms_f_getqui, "F$GETQUI" },
111 { EXT_REGINA_BIFS,vms_f_getsyi, "F$GETSYI" },
112 { EXT_REGINA_BIFS,vms_f_identifier, "F$IDENTIFIER" },
113 { EXT_REGINA_BIFS,vms_f_integer, "F$INTEGER" },
114 { EXT_REGINA_BIFS,vms_f_length, "F$LENGTH" },
115 { EXT_REGINA_BIFS,vms_f_locate, "F$LOCATE" },
116 { EXT_REGINA_BIFS,vms_f_logical, "F$LOGICAL" },
117 { EXT_REGINA_BIFS,vms_f_message, "F$MESSAGE" },
118 { EXT_REGINA_BIFS,vms_f_mode, "F$MODE" },
119 { EXT_REGINA_BIFS,vms_f_parse, "F$PARSE" },
120 { EXT_REGINA_BIFS,vms_f_pid, "F$PID" },
121 { EXT_REGINA_BIFS,vms_f_privilege, "F$PRIVILEGE" },
122 { EXT_REGINA_BIFS,vms_f_process, "F$PROCESS" },
123 { EXT_REGINA_BIFS,vms_f_search, "F$SEARCH" },
124 { EXT_REGINA_BIFS,vms_f_setprv, "F$SETPRV" },
125 { EXT_REGINA_BIFS,vms_f_string, "F$STRING" },
126 { EXT_REGINA_BIFS,vms_f_time, "F$TIME" },
127 { EXT_REGINA_BIFS,vms_f_trnlnm, "F$TRNLNM" },
128 { EXT_REGINA_BIFS,vms_f_type, "F$TYPE" },
129 { EXT_REGINA_BIFS,vms_f_user, "F$USER" },
130 /*{ EXT_REGINA_BIFS,vms_f_verify, "F$VERIFY" }, */
131 #endif
132 { EXT_REGINA_BIFS,os2_filespec, "FILESPEC" },
133 { EXT_REGINA_BIFS,cms_find, "FIND" },
134 #ifdef OLD_REGINA_FEATURES
135 { EXT_REGINA_BIFS,unx_close, "FINIS" },
136 #endif /* OLD_REGINA_FEATURES */
137 { EXT_REGINA_BIFS,unx_fork, "FORK" },
138 { 0, std_form, "FORM" },
139 { 0, std_format, "FORMAT" },
140 #if defined(REGINA_DEBUG_MEMORY)
141 { EXT_REGINA_BIFS,dbg_freelists, "FREELISTS" },
142 #endif
143 { EXT_AREXX_BIFS, arexx_freespace, "FREESPACE" },
144 { 0, std_fuzz, "FUZZ" },
145 #ifdef HAVE_GCI
146 { EXT_REGINA_BIFS,rex_gciprefixchar, "GCIPREFIXCHAR" },
147 #endif
148 { EXT_REGINA_BIFS,rex_getcaller, "GETCALLER" },
149 { EXT_REGINA_BIFS,rex_getcallstack, "GETCALLSTACK" },
150 { EXT_REGINA_BIFS,unx_getenv, "GETENV" },
151 { EXT_REGINA_BIFS,unx_getpid, "GETPID" },
152 { EXT_AREXX_BIFS, arexx_getspace, "GETSPACE" },
153 { EXT_REGINA_BIFS,unx_gettid, "GETTID" },
154 { EXT_AREXX_BIFS, arexx_hash, "HASH" },
155 { EXT_AREXX_BIFS, arexx_import, "IMPORT" },
156 { EXT_REGINA_BIFS,cms_index, "INDEX" },
157 { 0, std_insert, "INSERT" },
158 { EXT_REGINA_BIFS,cms_justify, "JUSTIFY" },
159 { 0, std_lastpos, "LASTPOS" },
160 { 0, std_left, "LEFT" },
161 { 0, std_length, "LENGTH" },
162 { 0, std_linein, "LINEIN" },
163 { 0, std_lineout, "LINEOUT" },
164 { 0, std_lines, "LINES" },
165 #ifdef TRACEMEM
166 { EXT_REGINA_BIFS,dbg_listleaked, "LISTLEAKED" },
167 #endif
168 { EXT_REGINA_BIFS,rex_lower, "LOWER" },
169 { EXT_MAKEBUF_BIF,cms_makebuf, "MAKEBUF" },
170 { 0, std_max, "MAX" },
171 #ifdef TRACEMEM
172 { EXT_REGINA_BIFS,dbg_memorystats, "MEMORYSTATS" },
173 #endif
174 { 0, std_min, "MIN" },
175 { EXT_REGINA_BIFS,conflict_open, "OPEN" },
176 { 0, std_overlay, "OVERLAY" },
177 { EXT_REGINA_BIFS,rex_poolid, "POOLID" },
178 { EXT_REGINA_BIFS,unx_popen, "POPEN" },
179 { 0, std_pos, "POS" },
180 { EXT_REGINA_BIFS,unx_putenv, "PUTENV" },
181 { 0, std_qualify, "QUALIFY" },
182 { 0, std_queued, "QUEUED" },
183 { 0, std_random, "RANDOM" },
184 { EXT_AREXX_BIFS, arexx_randu, "RANDU" },
185 { EXT_AREXX_BIFS, arexx_readch, "READCH" },
186 { EXT_AREXX_BIFS, arexx_readln, "READLN" },
187 { 0, std_reverse, "REVERSE" },
188 { 0, std_right, "RIGHT" },
189
190 { 0, rex_rxfuncadd, "RXFUNCADD" },
191 #ifdef HAVE_GCI
192 { EXT_REGINA_BIFS,rex_rxfuncdefine, "RXFUNCDEFINE" },
193 #endif
194 { 0, rex_rxfuncdrop, "RXFUNCDROP" },
195 { EXT_REGINA_BIFS,rex_rxfuncerrmsg, "RXFUNCERRMSG" },
196 { 0, rex_rxfuncquery, "RXFUNCQUERY" },
197 { 0, rex_rxqueue, "RXQUEUE" },
198
199 { EXT_AREXX_BIFS, arexx_seek, "SEEK" },
200 { EXT_AREXX_BIFS, arexx_show, "SHOW" },
201 { 0, std_sign, "SIGN" },
202 { EXT_REGINA_BIFS,cms_sleep, "SLEEP" },
203 { 0, std_sourceline, "SOURCELINE" },
204 { 0, std_space, "SPACE" },
205 { EXT_REGINA_BIFS,cms_state, "STATE" },
206 { EXT_AREXX_BIFS, arexx_storage, "STORAGE" },
207 { 0, std_stream, "STREAM" },
208 { 0, std_strip, "STRIP" },
209 { 0, std_substr, "SUBSTR" },
210 { 0, std_subword, "SUBWORD" },
211 { 0, std_symbol, "SYMBOL" },
212 { 0, std_time, "TIME" },
213 { 0, std_trace, "TRACE" },
214
215 { EXT_REGINA_BIFS,dbg_traceback, "TRACEBACK" },
216
217 { 0, std_translate, "TRANSLATE" },
218 { EXT_AREXX_BIFS, arexx_trim, "TRIM" },
219 { 0, std_trunc, "TRUNC" },
220 { EXT_REGINA_BIFS,unx_uname, "UNAME" },
221 { EXT_REGINA_BIFS,unx_unixerror, "UNIXERROR" },
222 { EXT_REGINA_BIFS,arexx_upper, "UPPER" },
223 { EXT_REGINA_BIFS,rex_userid, "USERID" },
224 { 0, std_value, "VALUE" },
225 { 0, std_verify, "VERIFY" },
226 { 0, std_word, "WORD" },
227 { 0, std_wordindex, "WORDINDEX" },
228 { 0, std_wordlength, "WORDLENGTH" },
229 { 0, std_wordpos, "WORDPOS" },
230 { 0, std_words, "WORDS" },
231 { EXT_AREXX_BIFS, arexx_writech, "WRITECH" },
232 { EXT_AREXX_BIFS, arexx_writeln, "WRITELN" },
233 { 0, std_x2b, "X2B" },
234 { 0, std_x2c, "X2C" },
235 { 0, std_x2d, "X2D" },
236 { 0, std_xrange, "XRANGE" },
237 { 0, NULL, NULL }
238 } ;
239
240 static const int num_funcs = sizeof(functions) / (sizeof(functions[0])) - 1 ;
241
242 static const int MonthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
243 static const int DaysInYear[] = {0,31,59,90,120,151,181,212,243,273,304,334};
244
245 static int leapyear(long year) ;
246 static void base2date(long basedate,void *conv_tmdata) ;
247
248 #ifdef TRACEMEM
mark_listleaked_params(const tsd_t * TSD)249 void mark_listleaked_params( const tsd_t *TSD )
250 {
251 paramboxptr pptr=NULL ;
252
253 for (pptr=TSD->listleaked_params; pptr; pptr=pptr->next)
254 {
255 markmemory( pptr, TRC_PROCARG ) ;
256 if (pptr->value)
257 markmemory( pptr->value, TRC_PROCARG ) ;
258 }
259 }
260 #endif
261
buildtinfunc(tsd_t * TSD,nodeptr thisptr)262 streng *buildtinfunc( tsd_t *TSD, nodeptr thisptr )
263 {
264 int low=0, topp=0, mid=0, end=1, up=num_funcs-1, i=0 ;
265 streng *ptr;
266 struct entry_point *vptr;
267 streng *(*func)(tsd_t *,cparamboxptr)=NULL ;
268 const char *BIFname = NULL; /* set to non-NULL only in case of a BIF */
269 void *BIFfunc = NULL; /* set to non-NULL only in case of a BIF */
270
271 /*
272 * Look for a function registered in a DLL
273 */
274 vptr = loaded_lib_func( TSD, thisptr->name ) ;
275 if ( vptr )
276 func = std_center ; /* e.g. */
277
278 /*
279 * If no function registered in a DLL or EXE, look for a builtin
280 */
281 if (!func)
282 {
283 topp = Str_len( thisptr->name ) ;
284
285 if (thisptr->u.func)
286 func = thisptr->u.func ;
287 else
288 {
289 mid = 0 ; /* to keep the compiler happy */
290 while ((end)&&(up>=low))
291 {
292 mid = (up+low)/2 ;
293 for (i=0; i<topp; i++ )
294 if (thisptr->name->value[i] != functions[mid].funcname[i])
295 break ;
296
297 if (i==topp)
298 end = (functions[mid].funcname[i]!=0x00) ;
299 else
300 end = ( functions[mid].funcname[i] - thisptr->name->value[i] ) ;
301
302 if (end>0)
303 up = mid-1 ;
304 else
305 low = mid+1 ;
306 }
307 if (!end)
308 {
309 /*
310 * Check if the function is an extension. If it is and it matches
311 * an extension specified with the OPTIONS keyword, then allow it.
312 * If the OPTION; STRICT_ANSI is in effect however, this overrides
313 * the extension.
314 */
315 BIFname = functions[mid].funcname;
316 if (functions[mid].compat)
317 {
318 if ( get_options_flag( TSD->currlevel, EXT_STRICT_ANSI ) )
319 exiterror( ERR_NON_ANSI_FEATURE, 1, functions[mid].funcname );
320 if ( ! get_options_flag( TSD->currlevel, functions[mid].compat ) )
321 func = NULL ;
322 else
323 {
324 func = functions[mid].function ;
325 if ( get_options_flag( TSD->currlevel, EXT_CACHEEXT ) )
326 thisptr->u.func = func ;
327 }
328 }
329 else
330 thisptr->u.func = func = functions[mid].function ;
331 }
332 }
333 BIFfunc = (void *) func;
334 }
335
336 if (func)
337 {
338 if (TSD->bif_first)
339 deallocplink( TSD, TSD->bif_first ) ;
340 TSD->bif_first = NULL; /* NEVER delete this! initplist
341 * may setjmp to the line above
342 * which results to a twice-called
343 * deallocplink. FGC
344 */
345
346 TSD->bif_first = initplist( TSD, thisptr ) ;
347 TSD->BIFname = BIFname;
348 TSD->BIFfunc = (void *) BIFfunc;
349 if (vptr)
350 ptr = call_known_external( TSD, vptr, TSD->bif_first, (char) thisptr->o.called ) ;
351 else
352 ptr = (*func)(TSD, TSD->bif_first /* ->next */ ) ;
353 TSD->BIFname = NULL;
354 TSD->BIFfunc = NULL;
355
356 deallocplink( TSD, TSD->bif_first ) ;
357 TSD->bif_first = NULL ;
358 return ptr ;
359 }
360 else
361 {
362 if (IfcHaveFunctionExit( TSD )) /* we have an exit handler */
363 {
364 if (TSD->bif_first)
365 deallocplink( TSD, TSD->bif_first ) ;
366 TSD->bif_first = NULL; /* NEVER delete this! initplist
367 * may setjmp to the line above
368 * which results to a twice-called
369 * deallocplink. FGC
370 */
371
372
373 TSD->bif_first = initplist( TSD, thisptr ) ;
374 ptr = call_unknown_external( TSD, thisptr->name, TSD->bif_first, (char) thisptr->o.called ) ;
375 deallocplink( TSD, TSD->bif_first ) ;
376 TSD->bif_first = NULL ;
377 }
378 else
379 ptr = NOFUNC;
380 }
381 return ptr;
382 }
383
initplist(tsd_t * TSD,cnodeptr thisptr)384 paramboxptr initplist( tsd_t *TSD, cnodeptr thisptr )
385 {
386 paramboxptr first,newptr,currnt;
387
388 first = currnt = NULL ;
389 for (thisptr=thisptr->p[0]; thisptr; thisptr=thisptr->p[1])
390 {
391 if (TSD->par_stack)
392 {
393 newptr = TSD->par_stack ;
394 TSD->par_stack = newptr->next ;
395 }
396 else
397 newptr = (paramboxptr)MallocTSD( sizeof( parambox )) ;
398
399 if (!first)
400 first = currnt = newptr ;
401 else
402 {
403 currnt->next = newptr ;
404 currnt = newptr ;
405 }
406
407 if (thisptr->type==X_CEXPRLIST && TSD->trace_stat!='I')
408 {
409 if (thisptr->u.strng)
410 currnt->value = thisptr->u.strng ;
411 else
412 currnt->value = NULL ;
413
414 currnt->dealloc = 0 ;
415 }
416 else if ( !thisptr->p[0] )
417 {
418 currnt->dealloc = 1;
419 currnt->value = NULL;
420 }
421 else
422 {
423 /*
424 * This fixes bug 590589 and others.
425 * Always force a fresh new return value of evaluate.
426 * Imagine this code, it will produce a crash otherwise:
427 * call func x
428 * return
429 * func:
430 * x = "new" || "value"
431 * say arg(1)
432 */
433 currnt->dealloc = 1;
434 currnt->value = evaluate( TSD, thisptr->p[0], NULL );
435 }
436 }
437 #ifdef TRACEMEM
438 TSD->listleaked_params = first ;
439 #endif
440 if ( currnt )
441 currnt->next = NULL ;
442 return first ;
443 }
444
445
initargs(tsd_t * TSD,int argc,const int * lengths,const char ** strings)446 paramboxptr initargs( tsd_t *TSD, int argc, const int *lengths,
447 const char **strings )
448 {
449 paramboxptr first,newptr,currnt;
450 int i;
451
452 first = currnt = NULL;
453 for ( i = 0; i < argc; i++ )
454 {
455 if ( TSD->par_stack )
456 {
457 newptr = TSD->par_stack;
458 TSD->par_stack = newptr->next;
459 }
460 else
461 newptr = (paramboxptr)MallocTSD( sizeof( parambox ) );
462
463 if ( !first )
464 first = currnt = newptr;
465 else
466 {
467 currnt->next = newptr;
468 currnt = newptr;
469 }
470
471 if ( lengths[i] == RX_NO_STRING )
472 {
473 currnt->dealloc = 1;
474 currnt->value = NULL;
475 }
476 else
477 {
478 currnt->value = Str_ncreTSD( strings[i], lengths[i] );
479 currnt->dealloc = 1;
480 }
481 }
482
483 #ifdef TRACEMEM
484 TSD->listleaked_params = first;
485 #endif
486
487 if ( currnt )
488 currnt->next = NULL;
489 return first;
490 }
491
492
deallocplink(tsd_t * TSD,paramboxptr first)493 void deallocplink( tsd_t *TSD, paramboxptr first )
494 {
495 paramboxptr thisptr;
496
497 for (;first;)
498 {
499 thisptr = first ;
500 first = first->next ;
501 if (thisptr->dealloc && thisptr->value)
502 {
503 Free_stringTSD( thisptr->value ) ;
504 thisptr->value = NULL;
505 }
506
507 #if defined(CHECK_MEMORY)
508 FreeTSD(thisptr);
509 #else
510 /* Back to the freed-parbox stack: */
511 thisptr->next = TSD->par_stack ;
512 TSD->par_stack = thisptr ;
513 #endif
514 }
515 }
516
517
518 #ifdef TRACEMEM
mark_param_cache(const tsd_t * TSD)519 void mark_param_cache( const tsd_t *TSD )
520 {
521 paramboxptr ptr=NULL ;
522
523 ptr = TSD->par_stack ;
524 for (; ptr; ptr=ptr->next )
525 markmemory( ptr, TRC_P_CACHE ) ;
526 }
527 #endif
528
529
530
myatol(const tsd_t * TSD,const streng * text)531 int myatol( const tsd_t *TSD, const streng *text )
532 {
533 int num, error ;
534
535 num = streng_to_int( TSD, text, &error ) ;
536 if (error)
537 exiterror( ERR_INVALID_INTEGER, 0 ) ;
538
539 return num ;
540 }
541
myintatol(tsd_t * TSD,const streng * text,int suberr,const char * bif,int argnum)542 static int myintatol( tsd_t *TSD, const streng *text, int suberr, const char *bif, int argnum )
543 {
544 int num, error ;
545
546 num = streng_to_int( TSD, text, &error ) ;
547 if ( error )
548 exiterror( ERR_INCORRECT_CALL, suberr, bif, argnum, tmpstr_of( TSD, text ) ) ;
549
550 return num ;
551 }
552
myintatoll(tsd_t * TSD,const streng * text,int suberr,const char * bif,int argnum)553 static rx_64 myintatoll( tsd_t *TSD, const streng *text, int suberr, const char *bif, int argnum )
554 {
555 rx_64 num;
556 int error ;
557
558 num = streng_to_rx64( TSD, text, &error ) ;
559 if ( error )
560 exiterror( ERR_INCORRECT_CALL, suberr, bif, argnum, tmpstr_of( TSD, text ) ) ;
561
562 return num ;
563 }
564
565
atozpos(tsd_t * TSD,const streng * text,const char * bif,int argnum)566 int atozpos( tsd_t *TSD, const streng *text, const char *bif, int argnum )
567 {
568 int result=0 ;
569
570 /* fixes bug 1108868 */
571 if ( ( result = myintatol( TSD, text, 12, bif, argnum ) ) < 0 )
572 exiterror( ERR_INCORRECT_CALL, 13, bif, argnum, tmpstr_of( TSD, text ) ) ;
573
574 return result ;
575 }
576
atozposrx64(tsd_t * TSD,const streng * text,const char * bif,int argnum)577 rx_64 atozposrx64( tsd_t *TSD, const streng *text, const char *bif, int argnum )
578 {
579 rx_64 result=0 ;
580
581 if ( ( result = myintatoll( TSD, text, 12, bif, argnum ) ) < 0 )
582 exiterror( ERR_INCORRECT_CALL, 13, bif, argnum, tmpstr_of( TSD, text ) ) ;
583
584 return result ;
585 }
586
587
getoptionchar(tsd_t * TSD,const streng * text,const char * bif,int argnum,const char * ansi_choices,const char * regina_choices)588 char getoptionchar( tsd_t *TSD, const streng *text, const char* bif, int argnum, const char *ansi_choices, const char *regina_choices )
589 {
590 char ch=0 ;
591 const char *ptr = NULL;
592 char tmp[50];
593
594 if (text->len == 0)
595 exiterror( ERR_INCORRECT_CALL, 21, bif, argnum ) ;
596
597 ch = (char) rx_toupper( text->value[0] ) ;
598 /*
599 * If the option supplied is ANSI, then return when we find it.
600 */
601 for ( ptr = ansi_choices; *ptr; ptr++ )
602 {
603 if ( *ptr == ch )
604 return ch ;
605 }
606 /*
607 * If the option supplied is a Regina extension, and we are NOT running in
608 * ANSI mode, then return when we find it.
609 */
610 for ( ptr = regina_choices; *ptr; ptr++ )
611 {
612 if ( *ptr == ch )
613 {
614 if ( get_options_flag( TSD->currlevel, EXT_STRICT_ANSI ) )
615 exiterror( ERR_NON_ANSI_FEATURE, 3, bif, argnum, ansi_choices, tmpstr_of( TSD, text ) );
616 else
617 return ch ;
618 }
619 }
620
621 if ( get_options_flag( TSD->currlevel, EXT_STRICT_ANSI ) )
622 exiterror( ERR_INCORRECT_CALL, 28, bif, argnum, ansi_choices, tmpstr_of( TSD, text ) );
623 else
624 {
625 strcpy( tmp, ansi_choices );
626 strcat( tmp, regina_choices );
627 exiterror( ERR_INCORRECT_CALL, 28, bif, argnum, tmp, tmpstr_of( TSD, text ) );
628 }
629 return 0 ;
630 }
631
632
getonechar(tsd_t * TSD,const streng * text,const char * bif,int argnum)633 char getonechar( tsd_t *TSD, const streng *text, const char *bif, int argnum )
634 {
635 if ( !text )
636 exiterror( ERR_INCORRECT_CALL, 23, bif, argnum, "" ) ;
637 if ( Str_len( text ) != 1 )
638 exiterror( ERR_INCORRECT_CALL, 23, bif, argnum, tmpstr_of( TSD, text ) ) ;
639
640 return text->value[0] ;
641 }
642
getonespecialchar(tsd_t * TSD,const streng * text,const char * bif,int argnum)643 char getonespecialchar( tsd_t *TSD, const streng *text, const char *bif, int argnum )
644 {
645 if ( !text )
646 exiterror( ERR_INCORRECT_CALL, 43, bif, argnum, "" ) ;
647 if ( Str_len( text ) != 1 )
648 exiterror( ERR_INCORRECT_CALL, 43, bif, argnum, tmpstr_of( TSD, text ) ) ;
649 if ( rx_isalnum( text->value[0] ) )
650 exiterror( ERR_INCORRECT_CALL, 43, bif, argnum, tmpstr_of( TSD, text ) ) ;
651
652 return text->value[0] ;
653 }
654
atopos(tsd_t * TSD,const streng * text,const char * bif,int argnum)655 int atopos( tsd_t *TSD, const streng *text, const char *bif, int argnum )
656 {
657 int result=0 ;
658
659 /* fixes bug 1108868 */
660 if ( ( result = myintatol( TSD, text, 12, bif, argnum ) ) <= 0 )
661 exiterror( ERR_INCORRECT_CALL, 14, bif, argnum, tmpstr_of( TSD, text ) ) ;
662
663 return result ;
664 }
665
atoposrx64(tsd_t * TSD,const streng * text,const char * bif,int argnum)666 rx_64 atoposrx64( tsd_t *TSD, const streng *text, const char *bif, int argnum )
667 {
668 rx_64 result=0 ;
669
670 if ( ( result = myintatoll( TSD, text, 12, bif, argnum ) ) <= 0 )
671 exiterror( ERR_INCORRECT_CALL, 14, bif, argnum, tmpstr_of( TSD, text ) ) ;
672
673 return result ;
674 }
675
atoposorzero(tsd_t * TSD,const streng * text,const char * bif,int argnum)676 int atoposorzero( tsd_t *TSD, const streng *text, const char *bif, int argnum )
677 {
678 int result=0 ;
679
680 if ( ( result = myintatol( TSD, text, 11, bif, argnum ) ) < 0 )
681 exiterror( ERR_INCORRECT_CALL, 13, bif, argnum, tmpstr_of( TSD, text ) ) ;
682
683 return result ;
684 }
685
686
687
int_to_streng(const tsd_t * TSD,int input)688 streng *int_to_streng( const tsd_t *TSD, int input )
689 {
690 streng *output=NULL ;
691 char *cptr=NULL, *start=NULL, *top=NULL ;
692
693 output = Str_makeTSD( sizeof(int)*3 + 2 ) ;
694 start = output->value ;
695 cptr = start + sizeof(int)*3 + 2 ;
696 if (input)
697 {
698 if (input<0)
699 {
700 input = - input ;
701 *(start++) = '-' ;
702 }
703
704 for (top=cptr;input;)
705 {
706 *(--cptr) = (char) (input % 10 + '0') ;
707 input = input / 10 ;
708 }
709
710 memmove( start, cptr, top-cptr ) ;
711 output->len = top-cptr + start-output->value ;
712 }
713 else
714 {
715 *start = '0' ;
716 output->len = 1 ;
717 }
718
719 return output ;
720 }
721
rx64_to_streng(const tsd_t * TSD,rx_64 input)722 streng *rx64_to_streng( const tsd_t *TSD, rx_64 input )
723 {
724 streng *output=NULL ;
725 char *cptr=NULL, *start=NULL, *top=NULL ;
726
727 output = Str_makeTSD( sizeof(rx_64)*3 + 2 ) ;
728 start = output->value ;
729 cptr = start + sizeof(rx_64)*3 + 2 ;
730 if (input)
731 {
732 if (input<0)
733 {
734 input = - input ;
735 *(start++) = '-' ;
736 }
737
738 for (top=cptr;input;)
739 {
740 *(--cptr) = (char) (input % 10 + '0') ;
741 input = input / 10 ;
742 }
743
744 memmove( start, cptr, top-cptr ) ;
745 output->len = top-cptr + start-output->value ;
746 }
747 else
748 {
749 *start = '0' ;
750 output->len = 1 ;
751 }
752
753 return output ;
754 }
755
rx64u_to_streng(const tsd_t * TSD,rx_64u input)756 streng *rx64u_to_streng( const tsd_t *TSD, rx_64u input )
757 {
758 streng *output=NULL ;
759 char *cptr=NULL, *start=NULL, *top=NULL ;
760
761 output = Str_makeTSD( sizeof(rx_64u)*3 + 2 ) ;
762 start = output->value ;
763 cptr = start + sizeof(rx_64u)*3 + 2 ;
764 if (input)
765 {
766 for (top=cptr;input;)
767 {
768 *(--cptr) = (char) (input % 10 + '0') ;
769 input = input / 10 ;
770 }
771
772 memmove( start, cptr, top-cptr ) ;
773 output->len = top-cptr + start-output->value ;
774 }
775 else
776 {
777 *start = '0' ;
778 output->len = 1 ;
779 }
780
781 return output ;
782 }
783
784
checkparam(cparamboxptr params,int min,int max,const char * name)785 void checkparam( cparamboxptr params, int min, int max, const char *name )
786 {
787 int i=0 ;
788
789 for (i=0;i<min;i++,params=(cparamboxptr) (params->next))
790 {
791 /* if ((!params)||(!params->value)) */
792 if ((!params))
793 exiterror( ERR_INCORRECT_CALL, 3, name, min ) ;
794 if ( !params->value )
795 exiterror( ERR_INCORRECT_CALL, 5, name, i+1 );
796 }
797
798 for (;(i<max)&&(params);i++,params=(cparamboxptr) (params->next)) ;
799 if (((i==max)&&(params))&&((max)||(params->value)))
800 exiterror( ERR_INCORRECT_CALL, 4, name, max ) ;
801 }
802
803
804 /*
805 * These functions are rather ugly, but they works :-)
806 */
807 /*
808 * Converts a date supplied in an external format (specified by suppformat)
809 * into a struct tm (individual values for year, month, day, year_days and
810 * base days).
811 */
convert_date(tsd_t * TSD,const streng * suppdate,char suppformat,struct tm * indate,char isep)812 int convert_date(tsd_t *TSD, const streng *suppdate, char suppformat, struct tm *indate, char isep)
813 {
814 int rc,i=0,off=0,save_year=indate->tm_year,ilen;
815 long num1=0,num2=0,num3=0;
816 char buf[20];
817 char *ptr=(char*)suppdate->value;
818 struct tm *tmpTime;
819 time_t num64;
820
821 ilen = (isep == '\0' ? 0 : 1);
822 indate->tm_sec = indate->tm_min = indate->tm_hour = 0;
823 switch(suppformat)
824 {
825 case 'B': /* 99999... */
826 case 'D': /* 99999... */
827 if (suppdate->len > 19)
828 return(1);
829 memcpy(buf,ptr,suppdate->len);
830 buf[suppdate->len] = '\0';
831 if ((num1 = atol(buf)) == 0)
832 {
833 for (i=0;i<suppdate->len;i++)
834 {
835 if (buf[i] != '0')
836 return(1);
837 }
838 }
839 if ( suppformat == 'B' )
840 base2date(num1,indate);
841 else
842 base2date(num1+basedays(indate->tm_year)-1,indate);
843 break;
844 #if 0
845 case 'I': /* WHAT IS THIS? */
846 if (suppdate->len > 19)
847 return(1);
848 memcpy(buf,ptr,suppdate->len);
849 buf[suppdate->len] = '\0';
850 if ((num1 = atol(buf)) == 0)
851 {
852 for (i=0;i<suppdate->len;i++)
853 {
854 if (buf[i] != '0')
855 return(1);
856 }
857 }
858 base2date(num1+basedays(1978)-1,indate);
859 break;
860 #endif
861 case 'E': /* dd/mm/yy or ddmmyy (where '/' is isep) */
862 case 'O': /* yy/mm/dd or yymmdd (where '/' is isep) */
863 case 'U': /* mm/dd/yy or mmddyy (where '/' is isep) */
864 if (suppdate->len != 6+(ilen*2))
865 return(1);
866 memcpy(buf,ptr,2);
867 buf[2] = '\0';
868 if ( !rx_isdigit( buf[0] ) || !rx_isdigit( buf[1] ) )
869 return( 1 );
870 num1 = atol( buf );
871 memcpy(buf,(ptr+2+ilen),2);
872 buf[2] = '\0';
873 if ( !rx_isdigit( buf[0] ) || !rx_isdigit( buf[1] ) )
874 return( 1 );
875 num2 = atol( buf );
876 memcpy(buf,(ptr+4+(ilen*2)),2);
877 buf[2] = '\0';
878 if ( !rx_isdigit( buf[0] ) || !rx_isdigit( buf[1] ) )
879 return( 1 );
880 /* if we have an input separator, validate that it matches */
881 if ( ilen )
882 {
883 if (*(ptr+2) != isep && *(ptr+5) != isep)
884 return( 2 );
885 }
886 num3 = atol( buf );
887 switch(suppformat)
888 {
889 case 'E':
890 if ( num1 == 0 || num2 == 0 )
891 return( 1 );
892 indate->tm_mday = num1;
893 indate->tm_mon = num2-1;
894 indate->tm_year = num3;
895 break;
896 case 'O':
897 if ( num3 == 0 || num2 == 0 )
898 return( 1 );
899 indate->tm_mday = num3;
900 indate->tm_mon = num2-1;
901 indate->tm_year = num1;
902 break;
903 case 'U':
904 if ( num2 == 0 || num1 == 0 )
905 return( 1 );
906 indate->tm_mday = num2;
907 indate->tm_mon = num1-1;
908 indate->tm_year = num3;
909 break;
910 }
911 /*
912 * Work out the century based on a sliding year
913 */
914 if (indate->tm_year < 100) /* do something with century ... */
915 indate->tm_year += ( indate->tm_year <= (save_year - 2000 ) + 50 ) ? 2000 : 1900;
916 break;
917 case 'N': /* dd mmm yyyy or d mmm yyyy or ddmmmyyyy or dmmmyyyy */
918 if (suppdate->len < 8 || suppdate->len > 11)
919 return(1);
920 if (suppdate->len == 10 || suppdate->len == 8)
921 off = 1;
922 memcpy(buf,ptr,2-off);
923 buf[2-off] = '\0';
924 if ((num1 = atol(buf)) == 0)
925 return(1);
926 memcpy(buf,(ptr+2-off+ilen),3);
927 buf[3] = '\0';
928 /* find month */
929 num2 = (-1);
930 for (i=0;i<12;i++)
931 {
932 if (strncmp(months[i],buf,3) == 0)
933 {
934 num2 = i;
935 break;
936 }
937 }
938 if (num2 == (-1))
939 return(1);
940 memcpy(buf,(ptr+5-off+(ilen*2)),4);
941 buf[4] = '\0';
942 if ((num3 = atol(buf)) == 0 && strcmp("0000",buf) != 0)
943 return(1);
944 /* if we have an input separator, validate that it matches */
945 if ( ilen )
946 {
947 if (*(ptr+2-off) != isep && *(ptr+6-off) != isep)
948 return( 2 );
949 }
950 indate->tm_mday = num1;
951 indate->tm_mon = num2;
952 indate->tm_year = num3;
953 break;
954 case 'S': /* yyyymmdd (where '' is isep) */
955 case 'I': /* yyyy-mm-dd (where '-' is isep */
956 if ( suppdate->len != 8+(ilen*2) )
957 return(1);
958 memcpy( buf, ptr, 4 );
959 buf[4] = '\0';
960 if ( ( num1 = atol( buf ) ) == 0 )
961 return(1);
962 memcpy( buf, (ptr+4+(ilen)), 2 );
963 buf[2] = '\0';
964 if ( ( num2 = atol( buf ) ) == 0 )
965 return(1);
966 memcpy( buf, (ptr+6+(ilen*2)), 2 );
967 buf[2] = '\0';
968 if ( ( num3 = atol( buf ) ) == 0 )
969 return(1);
970 /* if we have an input separator, validate that it matches */
971 if ( ilen )
972 {
973 if (*(ptr+4) != isep && *(ptr+7) != isep)
974 return( 2 );
975 }
976 indate->tm_mday = num3;
977 indate->tm_mon = num2-1;
978 indate->tm_year = num1;
979 break;
980 case 'T': /* +|-999999... */
981 num64 = streng_to_rx64( TSD, suppdate, &rc );
982 if ( rc )
983 return 1;
984 tmpTime = localtime( (time_t *)&num64 );
985 *indate = *tmpTime;
986 indate->tm_year += 1900;
987 /*
988 * Reset time to 00:00:00
989 */
990 indate->tm_sec = indate->tm_hour = indate->tm_min = 0;
991 break;
992 default:
993 /* should not get here */
994 break;
995 }
996 if (indate->tm_mday > ( MonthDays[indate->tm_mon] + ( (indate->tm_mon == 1) ? leapyear(indate->tm_year) : 0 ) )
997 || indate->tm_mday < 1
998 || indate->tm_mon > 11
999 || indate->tm_mon < 0
1000 || indate->tm_year < 0)
1001 return(1);
1002
1003 indate->tm_yday = DaysInYear[indate->tm_mon]+
1004 ((leapyear(indate->tm_year)&&indate->tm_mon>1)?1:0)+
1005 indate->tm_mday - 1;
1006 indate->tm_wday = (((indate->tm_yday+basedays(indate->tm_year))+8) % 7);
1007 return(0);
1008 }
1009
1010 /*
1011 * Converts a year (MUST have century) to a number of days
1012 * Base year is 0001 - hence the date 01 Jan 0001 is base day 1
1013 */
basedays(int year)1014 int basedays(int year)
1015 {
1016 return((year-1)*365 + (year-1)/4 - (year-1)/100 + (year-1)/400);
1017 }
1018
1019 /*
1020 * Determines if a year (MUST have a century) is a leap year
1021 */
leapyear(long year)1022 static int leapyear(long year)
1023 {
1024 if ((year%4 == 0 && year%100 != 0) || year%400 == 0)
1025 return(1);
1026 else
1027 return(0);
1028 }
1029
1030 /*
1031 * Converts a number (representing the number of days since 01 Jan 0001)
1032 * to a struct tm value (individual fields for year, month, day and days in year)
1033 */
base2date(long basedate,void * conv_tmdata)1034 static void base2date(long basedate,void *conv_tmdata)
1035 {
1036 struct tm *outdate=(struct tm *)conv_tmdata;
1037 int i=0;
1038 long day=0L,year=0L,month=0L,yeardays=0L,thismonth=0L;
1039
1040 day = basedate + 1L;
1041 year = day / 366;
1042 day -= ((year*365) + (year/4) - (year/100) + (year/400));
1043 year++;
1044 while (day > (365 + leapyear(year)))
1045 {
1046 day -= (365 + leapyear(year));
1047 year++;
1048 }
1049
1050 yeardays = day;
1051 for (i=0;i<11;i++)
1052 {
1053 thismonth = (MonthDays[i]) + ((i == 1) ? leapyear(year) : 0);
1054 if (day <= thismonth)
1055 break;
1056 day -= thismonth;
1057 }
1058 month = i;
1059 outdate->tm_year = year;
1060 outdate->tm_mon = month;
1061 outdate->tm_mday = day;
1062 outdate->tm_yday = yeardays;
1063 outdate->tm_wday = ((basedate+8) % 7);
1064 return;
1065 }
1066
1067 /*
1068 * Converts a time supplied in an external format (specified by suppformat)
1069 * into a struct tm (individual values for hour, minute, second).
1070 */
convert_time(const tsd_t * TSD,const streng * supptime,char suppformat,struct tm * intime,time_t * unow)1071 int convert_time( const tsd_t *TSD, const streng *supptime, char suppformat, struct tm *intime, time_t *unow)
1072 {
1073 int rc,offset;
1074 long num1=0,num2=0,num3=0,num4=0;
1075 char buf[20];
1076 char *ptr=(char*)supptime->value;
1077 struct tm *tmpTime;
1078 time_t num64;
1079
1080 switch(suppformat)
1081 {
1082 case 'C': /* hh:mmXX */
1083 /*
1084 * Format of time can be "3:45pm", or "11:45pm"; ie hour can be 1 or
1085 * two digits. Use of "offset" below fixes bug 742725
1086 */
1087 if (*(ptr+2) == ':')
1088 offset = 1;
1089 else if (*(ptr+1) == ':')
1090 offset = 0;
1091 else
1092 return(1);
1093 if (memcmp("am",ptr+4+offset,2) != 0 && memcmp("pm",ptr+4+offset,2) != 0)
1094 return(1);
1095 memcpy(buf,ptr,1+offset);
1096 buf[1+offset] = '\0';
1097 if ((num1 = atol(buf)) == 0 && strcmp("00",buf) != 0)
1098 return(1);
1099 if (num1 > 12)
1100 return(1);
1101 memcpy(buf,ptr+2+offset,2);
1102 buf[2] = '\0';
1103 if ((num2 = atol(buf)) == 0 && strcmp("00",buf) != 0)
1104 return(1);
1105 if (num2 > 59)
1106 return(1);
1107 intime->tm_sec = 0;
1108 if (memcmp("am",ptr+4+offset,2)==0)
1109 {
1110 if (num1 == 12)
1111 intime->tm_hour = 0;
1112 else
1113 intime->tm_hour = num1;
1114 }
1115 else
1116 {
1117 if (num1 == 12)
1118 intime->tm_hour = num1;
1119 else
1120 intime->tm_hour = num1+12;
1121 }
1122 intime->tm_min = num2;
1123 *unow = 0;
1124 break;
1125 case 'H': /* 99999... */
1126 case 'M': /* 99999... */
1127 case 'S': /* 99999... */
1128 /*
1129 * Convert supptime to whole number using streng_to_int()
1130 * rather than atoi(). Bug #20000922-78622
1131 */
1132 num1 = streng_to_int( TSD, supptime, &rc );
1133 if ( rc
1134 || num1 < 0 )
1135 return(1);
1136 switch(suppformat)
1137 {
1138 case 'H':
1139 intime->tm_hour = num1;
1140 intime->tm_min = intime->tm_sec = 0;
1141 break;
1142 case 'M':
1143 intime->tm_hour = num1 / 60;
1144 intime->tm_min = num1 % 60;
1145 intime->tm_sec = 0;
1146 break;
1147 case 'S':
1148 intime->tm_hour = num1 / 3600;
1149 intime->tm_min = (num1 % 3600) / 60;
1150 intime->tm_sec = (num1 % 3600) % 60;
1151 break;
1152 }
1153 if ( intime->tm_sec > 59 || intime->tm_hour > 23 || intime->tm_min > 59 )
1154 return(1);
1155 *unow = 0;
1156 break;
1157 case 'L': /* hh:mm:ss.mmmmmm */
1158 case 'N': /* hh:mm:ss */
1159 if (suppformat == 'N' && supptime->len != 8)
1160 return(1);
1161 if (suppformat == 'L' && supptime->len != 15)
1162 return(1);
1163 if (*(ptr+2) != ':' && *(ptr+5) != ':')
1164 return(1);
1165 memcpy(buf,ptr,2);
1166 buf[2] = '\0';
1167 if ((num1 = atol(buf)) == 0 && strcmp("00",buf) != 0)
1168 return(1);
1169 if (num1 < 0 || num1 > 23)
1170 return(1);
1171
1172 memcpy(buf,ptr+3,2);
1173 buf[2] = '\0';
1174 if ((num2 = atol(buf)) == 0 && strcmp("00",buf) != 0)
1175 return(1);
1176 if (num2 < 0 || num2 > 59)
1177 return(1);
1178
1179 memcpy(buf,ptr+6,2);
1180 buf[2] = '\0';
1181 if ((num3 = atol(buf)) == 0 && strcmp("00",buf) != 0)
1182 return(1);
1183 if (num3 < 0 || num3 > 59)
1184 return(1);
1185 intime->tm_sec = num3;
1186 intime->tm_hour = num1;
1187 intime->tm_min = num2;
1188 if (suppformat == 'N')
1189 {
1190 *unow = 0;
1191 break;
1192 }
1193 if (*(ptr+8) != '.')
1194 return(1);
1195 memcpy(buf,ptr+9,6);
1196 buf[6] = '\0';
1197 if ((num4 = atol(buf)) == 0 && strcmp("000000",buf) != 0)
1198 return(1);
1199 if (num4 < 0)
1200 return(1);
1201 *unow = num4;
1202 break;
1203 case 'T': /* +|-999999... */
1204 num64 = streng_to_int( TSD, supptime, &rc );
1205 if ( rc )
1206 return 1;
1207 tmpTime = localtime( (time_t *)&num64 );
1208 *intime = *tmpTime;
1209 *unow = 0;
1210 break;
1211 default:
1212 /* should not get here */
1213 break;
1214 }
1215
1216 return(0);
1217 }
1218 /*
1219 * The following functions are wrappers for BIFs that are syntactically different
1220 * depending on the OPTONS used.
1221 */
1222
conflict_close(tsd_t * TSD,cparamboxptr parms)1223 static streng *conflict_close( tsd_t *TSD, cparamboxptr parms )
1224 {
1225 if ( get_options_flag( TSD->currlevel, EXT_AREXX_SEMANTICS ) )
1226 return( arexx_close( TSD, parms ) );
1227 else
1228 return( unx_close( TSD, parms ) );
1229 }
1230
conflict_eof(tsd_t * TSD,cparamboxptr parms)1231 static streng *conflict_eof( tsd_t *TSD, cparamboxptr parms )
1232 {
1233 if ( get_options_flag( TSD->currlevel, EXT_AREXX_SEMANTICS ) )
1234 return( arexx_eof( TSD, parms ) );
1235 else
1236 return( unx_eof( TSD, parms ) );
1237 }
1238
conflict_open(tsd_t * TSD,cparamboxptr parms)1239 static streng *conflict_open( tsd_t *TSD, cparamboxptr parms )
1240 {
1241 if ( get_options_flag( TSD->currlevel, EXT_AREXX_SEMANTICS ) )
1242 return( arexx_open( TSD, parms ) );
1243 else
1244 return( unx_open( TSD, parms ) );
1245 }
1246
1247 /*
1248 * BIFname tries to guess the name of the BIF we currently evaluate.
1249 * We try to identify cached functions pointers.
1250 */
BIFname(tsd_t * TSD)1251 const char *BIFname( tsd_t *TSD )
1252 {
1253 int i;
1254 void *func;
1255
1256 assert( TSD->currentnode );
1257
1258 if ( TSD->BIFname != NULL )
1259 {
1260 return TSD->BIFname;
1261 }
1262
1263 if ( TSD->BIFfunc != NULL )
1264 {
1265 func = TSD->BIFfunc;
1266 }
1267 else
1268 {
1269 func = (void *) TSD->currentnode->u.func;
1270
1271 }
1272 for ( i = 0; i < num_funcs; i++ )
1273 {
1274 if ( (void *) functions[i].function == func )
1275 {
1276 return functions[i].funcname;
1277 }
1278 }
1279 return "(internal)";
1280 }
1281