libxml2: copy the xml2-config to the crosstoolsdir and patch the paths in the native...
[AROS-Contrib.git] / regina / tracing.c
blob3c779b39f6e48f45af373945e57a1213e6f9fb96
1 /*
2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "rexx.h"
21 #include <stdio.h>
22 #ifdef HAVE_UNISTD_H
23 # include <unistd.h>
24 #endif
25 #ifdef HAVE_ASSERT_H
26 # include <assert.h>
27 #endif
28 #include <string.h>
31 typedef struct { /* tra_tsd: static variables of this module (thread-safe) */
32 int traceflag; /* boolean: 1 indicates that trace output is NOT displayed */
33 int lasttracedline;
34 int intercount; /* number of times to execute trace without interaction */
35 int quiet; /* boolean: run quietly in interaction trace */
36 int notnow;
37 char tracestr[LINELENGTH+1];
38 char buf0[32];
39 int bufptr0;
40 char tracefmt[20];
41 } tra_tsd_t; /* thread-specific but only needed by this module. see
42 * init_tracing
46 /* init_tracing initializes the module.
47 * Currently, we set up the thread specific data.
48 * The function returns 1 on success, 0 if memory is short.
50 int init_tracing( tsd_t *TSD )
52 tra_tsd_t *tt;
54 if ( TSD->tra_tsd != NULL )
55 return 1;
57 if ( ( TSD->tra_tsd = MallocTSD( sizeof( tra_tsd_t ) ) ) == NULL )
58 return 0;
59 tt = (tra_tsd_t *)TSD->tra_tsd;
60 memset( tt, 0, sizeof( tra_tsd_t ) );
61 tt->lasttracedline = -1;
62 return 1;
65 int pushcallstack( const tsd_t *TSD, treenode *thisptr )
67 nodeptr *tmpptr;
69 if ( TSD->systeminfo->cstackcnt >= TSD->systeminfo->cstackmax )
71 assert( TSD->systeminfo->cstackcnt == TSD->systeminfo->cstackmax );
72 tmpptr = (nodeptr *)MallocTSD( ( TSD->systeminfo->cstackmax * 2 + 10 ) *
73 sizeof( nodeptr ) );
74 if ( TSD->systeminfo->callstack )
76 memcpy( tmpptr, TSD->systeminfo->callstack,
77 TSD->systeminfo->cstackcnt * sizeof( nodeptr ) );
78 FreeTSD( TSD->systeminfo->callstack );
80 TSD->systeminfo->callstack = tmpptr;
81 TSD->systeminfo->cstackmax *= 2;
82 TSD->systeminfo->cstackmax += 10;
85 TSD->systeminfo->callstack[TSD->systeminfo->cstackcnt++] = thisptr;
86 return TSD->systeminfo->cstackcnt;
89 void popcallstack( const tsd_t *TSD, int value )
91 if ( value >= 0 )
93 assert( TSD->systeminfo->cstackcnt >= value );
94 TSD->systeminfo->cstackcnt = value;
97 --TSD->systeminfo->cstackcnt;
99 assert( TSD->systeminfo->cstackcnt >= 0 );
102 static void printout( tsd_t *TSD, const streng *message )
104 int rc;
105 FILE *fp=stderr;
107 rc = HOOK_GO_ON;
108 if ( TSD->systeminfo->hooks & HOOK_MASK( HOOK_STDERR ) )
109 rc = hookup_output( TSD, HOOK_STDERR, message );
111 if ( rc == HOOK_GO_ON )
113 if ( get_options_flag( TSD->currlevel, EXT_STDOUT_FOR_STDERR ) )
114 fp = stdout;
115 if ( get_options_flag( TSD->currlevel, EXT_TRACE_HTML ) )
116 fwrite( "<FONT COLOR=#669933><PRE>", 25, 1, fp );
117 fwrite( message->value, message->len, 1, fp ) ;
118 if ( get_options_flag( TSD->currlevel, EXT_TRACE_HTML ) )
119 fwrite( "</PRE></FONT>", 13, 1, fp );
120 #if defined(DOS) || defined(OS2) || defined(WIN32)
122 * stdout is open in binary mode, so we need to add the
123 * extra CR to the end of the line.
125 fputc( REGINA_CR, fp );
126 #endif
127 fputc( REGINA_EOL, fp );
128 fflush( fp );
132 void traceerror( tsd_t *TSD, const treenode *thisptr, int RC )
134 streng *message;
136 if ( ( TSD->trace_stat == 'N' ) || ( TSD->trace_stat == 'F' ) )
137 traceline( TSD, thisptr, 'C', 0 );
139 if ( TSD->trace_stat != 'O' )
141 message = Str_makeTSD( 20 + sizeof( int ) * 3 ) ;
142 message->len = sprintf( message->value, " +++ RC=%d +++", RC );
144 printout( TSD, message );
145 Free_stringTSD( message );
149 void tracecompound( tsd_t *TSD, const streng *stem, int length,
150 const streng *index, char trch )
152 streng *message;
153 tra_tsd_t *tt;
154 int indent;
156 tt = (tra_tsd_t *)TSD->tra_tsd;
157 if ( tt->traceflag || ( TSD->trace_stat != 'I' ) || tt->quiet )
158 return;
160 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
161 message = Str_makeTSD( stem->len + index->len + 30 + indent );
163 sprintf( tt->tracestr, " >%c> %%%ds \"%%.%ds.%%.%ds\"",
164 trch, indent, length, index->len );
165 message->len = sprintf( message->value, tt->tracestr,
166 "", stem->value, index->value );
168 printout( TSD, message );
170 Free_stringTSD( message );
173 void starttrace( const tsd_t *TSD )
175 tra_tsd_t *tt;
177 tt = (tra_tsd_t *)TSD->tra_tsd;
178 tt->traceflag = 0;
179 tt->notnow = 1;
182 static void tracemsg( tsd_t *TSD )
184 streng *message;
185 const streng *msg;
187 msg = errortext( TSD, 0, 3, 0, 0 );
188 message = Str_makeTSD( 12 + Str_len( msg ) );
189 Str_catstrTSD( message, " +++ " );
190 Str_catTSD( message, msg );
191 printout( TSD, message );
192 Free_stringTSD( message );
195 int intertrace( tsd_t *TSD )
197 streng *str=NULL;
198 int retvalue1,rc;
199 tra_tsd_t *tt;
201 tt = (tra_tsd_t *)TSD->tra_tsd;
203 if ( tt->intercount )
205 tt->intercount -= 1;
206 if ( tt->intercount == 0 )
208 tt->quiet = 0;
209 tt->traceflag = 0;
211 else
212 return 0;
215 if ( tt->traceflag )
216 return 0;
218 if ( tt->notnow == 1 )
220 tt->notnow = 2;
221 return 0;
223 else if ( tt->notnow == 2 )
225 tt->notnow = 0;
226 tracemsg( TSD );
228 tt->traceflag = 1;
229 retvalue1 = -1;
231 for ( ; retvalue1 < 0; )
233 rc = HOOK_GO_ON;
234 if ( TSD->systeminfo->hooks & HOOK_MASK( HOOK_TRCIN ) )
235 rc = hookup_input( TSD, HOOK_TRCIN, &str );
237 if ( rc == HOOK_GO_ON )
238 str = readkbdline( TSD );
240 if ( str->len == 0 )
242 tt->traceflag = 0;
243 retvalue1 = 0;
246 if ( ( Str_len( str ) == 1 ) && (str->value[0] == '=' ) )
248 tt->traceflag = 0;
249 retvalue1 = 1;
251 else if ( str->len )
253 dointerpret( TSD, str );
254 if ( !TSD->systeminfo->interactive )
256 tt->intercount = tt->quiet = 0;
257 return 0;
259 if ( tt->intercount )
261 if ( tt->quiet )
262 tt->traceflag = 1;
263 else
264 tt->traceflag = 0;
265 return 0;
270 return retvalue1;
273 void tracenumber( tsd_t *TSD, const num_descr *num, char type )
275 char tmpch;
276 streng *message,*tmpstr;
277 tra_tsd_t *tt;
278 num_descr nd;
279 int indent;
281 tmpch = TSD->currlevel->tracestat;
282 if ( ( tmpch != 'I' ) && ( tmpch != 'R' ) )
283 return;
285 tt = (tra_tsd_t *)TSD->tra_tsd;
286 if ( tt->traceflag || tt->quiet )
287 return;
289 memset( &nd, 0, sizeof( num_descr ) );
290 descr_copy( TSD, num, &nd );
291 tmpstr = str_norm( TSD, &nd, NULL );
292 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
293 message = Str_makeTSD( 30 + indent + tmpstr->len );
294 sprintf( tt->tracestr, " >%%c> %%%ds \"%%.%ds\"",
295 indent, tmpstr->len );
296 message->len = sprintf( message->value, tt->tracestr,
297 type, "", tmpstr->value );
298 printout( TSD, message );
299 if ( nd.num != NULL )
300 FreeTSD( nd.num );
301 Free_stringTSD( message );
302 Free_stringTSD( tmpstr );
305 void tracebool( tsd_t *TSD, int value, char type )
307 char tmpch;
308 streng *message;
309 tra_tsd_t *tt;
310 int indent;
312 tmpch = TSD->currlevel->tracestat;
313 if ( ( tmpch != 'I' ) && ( tmpch != 'R' ) )
314 return;
316 tt = (tra_tsd_t *)TSD->tra_tsd;
317 if ( tt->traceflag || tt->quiet )
318 return;
320 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
321 message = Str_makeTSD( 35 + indent );
322 sprintf( tt->tracestr, " >%%c> %%%ds \"%%d\"",
323 indent );
324 message->len = sprintf( message->value, tt->tracestr,
325 type, "", value );
326 printout( TSD, message );
327 Free_stringTSD( message );
330 void tracevalue( tsd_t *TSD, const streng *str, char type )
332 char tmpch;
333 streng *message;
334 tra_tsd_t *tt;
335 int indent;
338 * ANSI 8.3.17 requires placeholders in PARSE to be traced with TRACE R
340 tmpch = TSD->currlevel->tracestat;
341 if ( ( tmpch != 'I' ) && ( tmpch != 'R' ) )
342 return;
344 tt = (tra_tsd_t *)TSD->tra_tsd;
345 if ( tt->traceflag || tt->quiet )
346 return;
348 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
349 message = Str_makeTSD( str->len + 30 + indent );
350 sprintf( tt->tracestr, " >%%c> %%%ds \"%%.%ds\"",
351 indent, str->len );
352 message->len = sprintf( message->value, tt->tracestr,
353 type, "", str->value );
354 printout( TSD, message );
355 Free_stringTSD( message );
358 void traceline( tsd_t *TSD, const treenode *thisptr, char tch, int offset )
360 streng *srcstr;
361 streng *message;
362 tra_tsd_t *tt;
363 int indent;
365 tt = (tra_tsd_t *)TSD->tra_tsd;
366 if ( tt->traceflag || tt->quiet )
367 return;
369 if ( ( thisptr->charnr < 0 ) || ( thisptr->lineno < 0 ) )
370 return;
372 switch ( tch )
374 case 'I':
375 case 'R':
376 case 'A':
377 break; /* Oh yes, break the IRA ;-) */
379 case 'L':
380 if ( thisptr->type == X_LABEL )
381 break;
382 return;
384 case 'C':
385 if ( ( thisptr->type == X_COMMAND )
386 || ( ( thisptr->type == X_ADDR_N ) && thisptr->p[0] ) )
387 break;
388 return;
390 default:
391 return;
394 srcstr = getsourceline( TSD, thisptr->lineno, thisptr->charnr,
395 &TSD->systeminfo->tree );
397 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
398 message = Str_makeTSD( indent + 20 + srcstr->len + offset );
399 if ( thisptr->lineno == tt->lasttracedline )
401 sprintf( tt->tracestr, " *-* %%%ds%%.%ds",
402 indent + offset, srcstr->len );
403 message->len = sprintf( message->value, tt->tracestr,
404 "", srcstr->value );
406 else
408 sprintf( tt->tracestr, "%%6d *-* %%%ds%%.%ds",
409 indent + offset, srcstr->len );
410 message->len = sprintf( message->value, tt->tracestr,
411 thisptr->lineno, "", srcstr->value );
414 printout( TSD, message );
415 tt->lasttracedline = thisptr->lineno;
416 Free_stringTSD( message );
417 Free_stringTSD( srcstr );
420 void traceback( tsd_t *TSD )
422 sysinfo ss;
423 streng *message;
424 streng *srcline;
425 nodeptr ptr;
426 int i,j,linesize=128,indent;
427 tra_tsd_t *tt;
429 tt = (tra_tsd_t *)TSD->tra_tsd;
431 * Allocate enough space for one line and control stuff. Count below
432 * characters for the needed size. Beware of the computed format
433 * entry.
435 indent = TSD->systeminfo->cstackcnt + TSD->systeminfo->ctrlcounter;
436 message = Str_makeTSD( linesize + indent * 3 + 20 );
437 if ( TSD->currentnode )
439 srcline = getsourceline( TSD,
440 TSD->currentnode->lineno,
441 TSD->currentnode->charnr,
442 &TSD->systeminfo->tree );
443 if ( srcline->len > linesize )
445 Free_stringTSD( message );
446 linesize = srcline->len;
447 message = Str_makeTSD( linesize + indent * 3 + 20 );
449 sprintf( tt->tracefmt, "%%6d +++ %%%ds%%.%ds",
450 indent * 3, srcline->len );
451 message->len = sprintf( message->value, tt->tracefmt,
452 TSD->currentnode->lineno, "",
453 srcline->value );
454 printout( TSD, message );
455 Free_stringTSD( srcline );
458 j = indent;
459 for ( ss = TSD->systeminfo; ss; ss = ss->previous )
461 for ( i = ss->cstackcnt - 1; i >= 0; i-- )
463 ptr = ss->callstack[i];
464 if ( !ptr )
465 continue;
467 srcline = getsourceline( TSD,
468 ptr->lineno,
469 ptr->charnr,
470 &ss->tree );
471 if ( srcline->len > linesize )
473 Free_stringTSD( message );
474 linesize = srcline->len;
475 message = Str_makeTSD( linesize + indent * 3 + 20 );
478 j--;
479 if ( ( j > 12 ) && get_options_flag( TSD->currlevel, EXT_PRUNE_TRACE ) )
480 sprintf( tt->tracefmt, "%%6d +++ [...] %%%ds%%.%ds",
481 30, srcline->len );
482 else
483 sprintf( tt->tracefmt, "%%6d +++ %%%ds%%.%ds",
484 j * 3, srcline->len );
485 message->len = sprintf( message->value, tt->tracefmt,
486 ptr->lineno, "",
487 srcline->value );
488 printout( TSD, message );
489 Free_stringTSD( srcline );
492 Free_stringTSD( message );
495 void queue_trace_char( const tsd_t *TSD, char ch2 )
497 tra_tsd_t *tt;
499 tt = (tra_tsd_t *)TSD->tra_tsd;
500 if ( tt->bufptr0 < 32 )
501 tt->buf0[tt->bufptr0++] = ch2;
502 else
503 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__,
504 "too many tracechars queued" );
507 void flush_trace_chars( tsd_t *TSD )
509 int cnt;
510 tra_tsd_t *tt;
512 tt = (tra_tsd_t *)TSD->tra_tsd;
513 for ( cnt = 0; cnt < tt->bufptr0; cnt++ )
514 set_trace_char( TSD, tt->buf0[cnt] );
516 tt->bufptr0 = 0;
519 void set_trace_char( tsd_t *TSD, char ch2 )
521 ch2 = (char) rx_toupper( ch2 );
522 switch ( ch2 )
524 case '?':
525 TSD->systeminfo->interactive = !TSD->systeminfo->interactive;
526 TSD->currlevel->traceint = (char) TSD->systeminfo->interactive;
527 if ( TSD->systeminfo->interactive )
528 starttrace( TSD );
529 break ;
531 case 'F':
532 case 'A':
533 case 'C':
534 case 'E':
535 case 'I':
536 case 'L':
537 case 'N':
538 case 'O':
539 case 'R':
540 TSD->currlevel->tracestat = ch2;
541 break;
543 default:
544 exiterror( ERR_INVALID_TRACE, 1, "ACEFILNOR", ch2 );
547 if ( ch2 == 'O' )
548 TSD->systeminfo->interactive = TSD->currlevel->traceint = 0;
549 TSD->trace_stat = TSD->currlevel->tracestat;
552 void set_trace( tsd_t *TSD, const streng *setting )
554 int cptr,error;
555 tra_tsd_t *tt;
557 if ( myisnumber( TSD, setting ) )
559 cptr = streng_to_int( TSD, setting, &error );
560 if ( error )
561 exiterror( ERR_INVALID_INTEGER, 7, tmpstr_of( TSD, setting ) );
564 * If the number is positive, interactive tracing continues
565 * for the supplied number of clauses, but no pausing is done.
566 * If the number is negative, no trace output is inhibited
567 * (as is the pauses) for the supplied number of clauses.
568 * If the number is zero, this is the same as TRACE OFF
570 tt = (tra_tsd_t *)TSD->tra_tsd;
571 if ( cptr == 0 )
573 TSD->currlevel->tracestat = 'O';
574 TSD->systeminfo->interactive = 0;
575 TSD->currlevel->traceint = 0;
576 TSD->trace_stat = TSD->currlevel->tracestat;
578 else if ( cptr > 0 )
580 tt->quiet = 0;
581 tt->intercount = cptr + 1;
583 else
585 tt->quiet = 1;
586 tt->intercount = -cptr + 1;
589 else
591 for ( cptr = 0; cptr < Str_len( setting ); cptr++ )
593 set_trace_char( TSD, setting->value[cptr] );
594 if ( rx_isalpha( setting->value[cptr] ) )
595 return;