RexxActivation.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Primitive Activation Class */
42 /* */
43 /* NOTE: activations are an execution time only object. They are never */
44 /* flattened or saved in the image, and hence will never be in old */
45 /* space. Because of this, activations "cheat" and do not use */
46 /* OrefSet to assign values to get better performance. Care must be */
47 /* used to maintain this situation. */
48 /* */
49 /******************************************************************************/
50 /******************************************************************************/
51 #include <ctype.h>
52 #include <string.h>
53 #include "RexxCore.h"
54 #include "StringClass.hpp"
55 #include "BufferClass.hpp"
56 #include "DirectoryClass.hpp"
58 #include "RexxActivation.hpp"
59 #include "RexxActivity.hpp"
60 #include "MethodClass.hpp"
61 #include "MessageClass.hpp"
62 #include "RexxCode.hpp"
63 #include "SourceFile.hpp"
64 #include "RexxInstruction.hpp"
65 #include "CallInstruction.hpp"
66 #include "DoBlock.hpp"
67 #include "DoInstruction.hpp"
68 #include "ProtectedObject.hpp"
69 #include "ActivityManager.hpp"
70 #include "Interpreter.hpp"
71 #include "SystemInterpreter.hpp"
72 #include "RexxInternalApis.h"
73 #include "PackageManager.hpp"
74 #include "RexxCompoundTail.hpp"
75 #include "CommandHandler.hpp"
76 #include "ActivationFrame.hpp"
77 #include "StackFrameClass.hpp"
78 #include "InterpreterInstance.hpp"
79 #include "PackageClass.hpp"
80 
81 /* max instructions without a yield */
82 #define MAX_INSTRUCTIONS 100
83  /* default template for a new */
84  /* activation. This must be changed */
85  /* whenever the settings definition */
86  /* changes */
88 // constants use for different activation settings
89 
90 const size_t RexxActivation::trace_off = 0x00000000; /* trace nothing */
91 const size_t RexxActivation::trace_debug = 0x00000001; /* interactive trace mode flag */
92 const size_t RexxActivation::trace_all = 0x00000002; /* trace all instructions */
93 const size_t RexxActivation::trace_results = 0x00000004; /* trace all results */
94 const size_t RexxActivation::trace_intermediates = 0x00000008; /* trace all instructions */
95 const size_t RexxActivation::trace_commands = 0x00000010; /* trace all commands */
96 const size_t RexxActivation::trace_labels = 0x00000020; /* trace all labels */
97 const size_t RexxActivation::trace_errors = 0x00000040; /* trace all command errors */
98 const size_t RexxActivation::trace_failures = 0x00000080; /* trace all command failures */
99 const size_t RexxActivation::trace_suppress = 0x00000100; /* tracing is suppressed during skips*/
100 const size_t RexxActivation::trace_flags = 0x000001ff; /* all tracing flags */
101  // the default trace setting
102 const size_t RexxActivation::default_trace_flags = trace_failures;
103 
104 // now the flag sets for different settings
105 const size_t RexxActivation::trace_all_flags = (trace_all | trace_labels | trace_commands);
106 const size_t RexxActivation::trace_results_flags = (trace_all | trace_labels | trace_results | trace_commands);
107 const size_t RexxActivation::trace_intermediates_flags = (trace_all | trace_labels | trace_results | trace_commands | trace_intermediates);
108 
111 
112 const size_t RexxActivation::single_step = 0x00000800; /* we are single stepping execution */
113 const size_t RexxActivation::single_step_nested = 0x00001000; /* this is a nested stepping */
114 const size_t RexxActivation::debug_prompt_issued = 0x00002000; /* debug prompt already issued */
115 const size_t RexxActivation::debug_bypass = 0x00004000; /* skip next debug pause */
116 const size_t RexxActivation::procedure_valid = 0x00008000; /* procedure instruction is valid */
117 const size_t RexxActivation::clause_boundary = 0x00010000; /* work required at clause boundary */
118 const size_t RexxActivation::halt_condition = 0x00020000; /* a HALT condition occurred */
119 const size_t RexxActivation::trace_on = 0x00040000; /* external trace condition occurred */
120 const size_t RexxActivation::source_traced = 0x00080000; /* source string has been traced */
121 const size_t RexxActivation::clause_exits = 0x00100000; /* need to call clause boundary exits*/
122 const size_t RexxActivation::external_yield = 0x00200000; /* activity wants us to yield */
123 const size_t RexxActivation::forwarded = 0x00400000; /* forward instruction active */
124 const size_t RexxActivation::reply_issued = 0x00800000; /* reply has already been issued */
125 const size_t RexxActivation::set_trace_on = 0x01000000; /* trace turned on externally */
126 const size_t RexxActivation::set_trace_off = 0x02000000; /* trace turned off externally */
127 const size_t RexxActivation::traps_copied = 0x04000000; /* copy of trap info has been made */
128 const size_t RexxActivation::return_status_set = 0x08000000; /* had our first host command */
129 const size_t RexxActivation::transfer_failed = 0x10000000; /* transfer of variable lock failure */
130 
131 const size_t RexxActivation::elapsed_reset = 0x20000000; // The elapsed time stamp was reset via time('r')
132 const size_t RexxActivation::guarded_method = 0x40000000; // this is a guarded method
133 
134 void * RexxActivation::operator new(size_t size)
135 /******************************************************************************/
136 /* Function: Create a new activation object */
137 /******************************************************************************/
138 {
139  /* Get new object */
140  return new_object(size, T_Activation);
141 }
142 
143 
144 /**
145  * Initialize an activation for direct caching in the activation
146  * cache. At this time, this is not an executable activation
147  */
149 {
150  this->setHasNoReferences(); // nothing referenced from this either
151 }
152 
153 
154 /**
155  * Initialize an activation for a method invocation.
156  *
157  * @param _activity The activity we're running under.
158  * @param _method The method being invoked.
159  * @param _code The code to execute.
160  */
162 {
163  this->clearObject(); /* start with a fresh object */
164  this->activity = _activity; /* save the activity pointer */
165  this->scope = _method->getScope(); // save the scope
166  this->code = _code; /* get the REXX method object */
167  this->executable = _method; // save this as the base executable
168  // save the source object reference also
169  this->sourceObject = _method->getSourceObject();
170  this->settings.intermediate_trace = false;
171  this->activation_context = METHODCALL; // the context is a method call
172  this->parent = OREF_NULL; // we don't have a parent stack frame when invoked as a method
173  this->execution_state = ACTIVE; /* we are now in active execution */
174  this->object_scope = SCOPE_RELEASED; /* scope not reserved yet */
175  /* create a new evaluation stack. This must be done before a */
176  /* local variable frame is created. */
177  this->setHasNoReferences(); /* during allocateStack.. */
178  /* a live marking can happen without */
179  /* a properly set up stack (::live() */
180  /* is called). Setting the NoRefBit */
181  /* when creating the stack avoids it.*/
182  _activity->allocateStackFrame(&this->stack, this->code->getMaxStackSize());
183  this->setHasReferences();
184 
185  RexxSource *referenceSource = this->sourceObject;
186  if (this->sourceObject->isBlock)
187  {
188  // get toplevelSource
190  while (parent != OREF_NULL)
191  {
192  referenceSource = parent;
193  parent = parent->parentSource;
194  }
195  }
196 
197  // get initial settings template
198  // NOTE: Anything that alters information in the settings must happen AFTER
199  // this point.
201  // and override with the package-defined settings
202  this->settings.numericSettings.digits = referenceSource->getDigits();
203  this->settings.numericSettings.fuzz = referenceSource->getFuzz();
204  this->settings.numericSettings.form = referenceSource->getForm();
205  setTrace(referenceSource->getTraceSetting(), referenceSource->getTraceFlags());
206  this->settings.enableCommands = referenceSource->getEnableCommands();
207  this->settings.enableMacrospace = referenceSource->getEnableMacrospace();
208 
209  // Get the RXTRACE settings from the parent activity.
210  // They override the package settings.
211  if (_parent != NULL && _parent->settings.externalTraceDepth != 0)
212  {
215  // The settings given by RXTRACE are taken in priority,
216  // except if the method is in the image (to avoid infinite recursion by tracing the trace monitor)
217  if (!this->code->isOldSpace())
218  {
219  setTrace(this->settings.externalTraceOption, this->settings.externalTraceFlags);
220  }
222  }
223  printf("activation for a method invocation: externalTraceDepth=%zx, externalTraceOption=%zx, externalTraceFlags=%zx\n", this->settings.externalTraceDepth, this->settings.externalTraceOption, this->settings.externalTraceFlags);
224  printf(" : traceOption=%zx, flags=%zx\n", this->settings.traceOption, this->settings.flags);
225  RexxString *methodName = _method->getName();
226  const char *methodNameStr = methodName ? methodName->getStringData() : "<NULL>";
227  RexxString *scope = (this->scope == TheNilObject ? this->scope->requestString() : this->scope->getId());
228  const char *scopeStr = scope ? scope->getStringData() : "<NULL>";
229  printf(" : method=%s, scope=%s\n", methodNameStr, scopeStr);
230 
231  this->settings.propagateNumericSettings = false;
232  if (_parent != NULL && _parent->settings.propagateNumericSettings)
233  {
235  this->settings.propagateNumericSettings = true;
236  }
237 
238  if (_method->isGuarded()) // make sure we set the appropriate guarded state
239  {
240  setGuarded();
241  }
242  /* save the source also */
243  this->settings.parent_code = this->code;
244 
245  /* allocate a frame for the local variables from activity stack */
248  /* set the initial and initial */
249  /* alternate address settings */
252  /* get initial random seed value */
253  this->random_seed = this->activity->getRandomSeed();
254  /* copy the source security manager */
256  if (this->settings.securityManager == OREF_NULL)
257  {
259  }
260  if (sourceObject->isBlock)
261  {
262  if (this->settings.securityManager == OREF_NULL || this->settings.securityManager->isManaged() == false)
263  {
264  this->settings.securityManager = referenceSource->getSecurityManager();
265  }
266  }
267  // and the call type is METHOD
268  this->settings.calltype = OREF_METHODNAME;
269 }
270 
271 
272 /**
273  * Create a new Rexx activation for an internal level call.
274  * An internal level call is an internal call, a call trap,
275  * an Interpret statement, or a debug pause execution.
276  *
277  * @param _activity The current activity.
278  * @param _parent The parent activation.
279  * @param _code The code to be executed. For interpret and debug pauses, this
280  * is a new code object. For call activations, this is the
281  * parent code object.
282  * @param context The type of call being made.
283  */
284 RexxActivation::RexxActivation(RexxActivity *_activity, RexxActivation *_parent, RexxCode *_code, int context)
285 {
286  this->clearObject(); /* start with a fresh object */
287  this->activity = _activity; /* save the activity pointer */
288  this->code = _code; /* get the REXX method object */
289 
290  if (context == DEBUGPAUSE) /* actually a debug pause? */
291  {
292  this->debug_pause = true; /* set up for debugging intercepts */
293  context = INTERPRET; /* this is really an interpret */
294  }
295  this->activation_context = context; /* save the context */
296  this->settings.intermediate_trace = false;
297  // the sender is our parent activity
298  this->parent = _parent;
299  this->execution_state = ACTIVE; /* we are now in active execution */
300  this->object_scope = SCOPE_RELEASED; /* scope not reserved yet */
301  /* create a new evaluation stack. This must be done before a */
302  /* local variable frame is created. */
303  this->setHasNoReferences(); /* during allocateStack.. */
304  /* a live marking can happen without */
305  /* a properly set up stack (::live() */
306  /* is called). Setting the NoRefBit */
307  /* when creating the stack avoids it.*/
308  _activity->allocateStackFrame(&stack, code->getMaxStackSize());
309  this->setHasReferences();
310  /* inherit parents settings */
311  _parent->putSettings(this->settings);
312  // step the trace indentation level for this internal nesting
314  // the random seed is copied from the calling activity, this led
315  // to reproducable random sequences even though no specific seed was given!
316  // see feat. 900 for example program.
318  if (context == INTERNALCALL) /* internal call? */
319  {
320  /* force a new copy of the traps */
321  /* table to be created whenever it */
322  /* is changed */
323  this->settings.flags &= ~traps_copied;
324  this->settings.flags &= ~reply_issued; /* this is a new activation that can use its own return */
325  /* invalidate the timestamp */
326  this->settings.timestamp.valid = false;
327  }
328  /* this is a nested call until we issue a procedure */
330  printf("activation for an internal level call: externalTraceDepth=%zx, externalTraceOption=%zx, externalTraceFlags=%zx\n", this->settings.externalTraceDepth, this->settings.externalTraceOption, this->settings.externalTraceFlags);
331  printf(" : traceOption=%zx, flags=%zx\n", this->settings.traceOption, this->settings.flags);
332  // get the executable from the parent.
333  this->executable = _parent->getExecutable();
334  // for internal calls, this is the same source object as the parent
336  {
337  // save the source object reference also
339  }
340  else
341  {
342  // use the source object for the interpret so error tracebacks are correct.
343  this->sourceObject = code->getSourceObject();
344  }
345 }
346 
347 
348 /**
349  * Create a top-level activation of Rexx code. This will
350  * either a toplevel program or an external call.
351  *
352  * @param _activity The current thread we're running on.
353  * @param _routine The routine to invoke.
354  * @param _code The code object to be executed.
355  * @param calltype Type type of call being made (function or subroutine)
356  * @param env The default address environment
357  * @param context The type of call context.
358  */
360  RexxString *calltype, RexxString *env, int context)
361 {
362  this->clearObject(); /* start with a fresh object */
363  this->activity = _activity; /* save the activity pointer */
364  this->code = _code; /* get the REXX method object */
365  this->executable = _routine; // save this as the base executable
366  // save the source object reference also
367  this->sourceObject = _routine->getSourceObject();
368 
369  this->activation_context = context; /* save the context */
370  this->settings.intermediate_trace = false;
371  this->parent = OREF_NULL; // there's no parent for a top level call
372  this->execution_state = ACTIVE; /* we are now in active execution */
373  this->object_scope = SCOPE_RELEASED; /* scope not reserved yet */
374  /* create a new evaluation stack. This must be done before a */
375  /* local variable frame is created. */
376  this->setHasNoReferences(); /* during allocateStack.. */
377  /* a live marking can happen without */
378  /* a properly set up stack (::live() */
379  /* is called). Setting the NoRefBit */
380  /* when creating the stack avoids it.*/
381  _activity->allocateStackFrame(&stack, code->getMaxStackSize());
382  this->setHasReferences();
383 
384  RexxSource *referenceSource = this->sourceObject;
385  if (this->sourceObject->isBlock)
386  {
387  // get toplevelSource
389  while (parent != OREF_NULL)
390  {
391  referenceSource = parent;
392  parent = parent->parentSource;
393  }
394  }
395 
396  /* get initial settings template */
398  // and override with the package-defined settings
399  this->settings.numericSettings.digits = referenceSource->getDigits();
400  this->settings.numericSettings.fuzz = referenceSource->getFuzz();
401  this->settings.numericSettings.form = referenceSource->getForm();
402  setTrace(referenceSource->getTraceSetting(), referenceSource->getTraceFlags());
403  this->settings.enableCommands = referenceSource->getEnableCommands();
404  this->settings.enableMacrospace = referenceSource->getEnableMacrospace();
405  /* save the source also */
406  this->settings.parent_code = this->code;
407 
408  // Get the RXTRACE settings from the parent activity.
409  // They override the package settings.
410  if (_parent != NULL && _parent->settings.externalTraceDepth != 0)
411  {
414  // The settings given by RXTRACE are taken in priority.
415  // except if the method is in the image (to avoid infinite recursion by tracing the trace monitor)
416  if (!this->code->isOldSpace())
417  {
418  setTrace(this->settings.externalTraceOption, this->settings.externalTraceFlags);
419  }
421  }
422  printf("activation for a toplevel program or an external call: externalTraceDepth=%zx, externalTraceOption=%zx, externalTraceFlags=%zx\n", this->settings.externalTraceDepth, this->settings.externalTraceOption, this->settings.externalTraceFlags);
423  printf(" : traceOption=%zx, flags=%zx\n", this->settings.traceOption, this->settings.flags);
424 
425  this->settings.propagateNumericSettings = false;
426  if (_parent != NULL && _parent->settings.propagateNumericSettings)
427  {
429  this->settings.propagateNumericSettings = true;
430  }
431 
432  /* allocate a frame for the local variables from activity stack */
435  /* set the initial and initial */
436  /* alternate address settings */
439  /* get initial random seed value */
440  this->random_seed = this->activity->getRandomSeed();
441  // the random seed is copied from the calling activity, this led
442  // to reproducable random sequences even though no specific seed was given!
443  // see feat. 900 for example program.
445  /* copy the source security manager */
447  // but use the default if not set
448  if (this->settings.securityManager == OREF_NULL)
449  {
451  }
452  if (sourceObject->isBlock)
453  {
454  if (this->settings.securityManager == OREF_NULL || this->settings.securityManager->isManaged() == false)
455  {
456  this->settings.securityManager = referenceSource->getSecurityManager();
457  }
458  }
459 
460  // if we have a default environment specified, apply the override.
461  if (env != OREF_NULL)
462  {
463  setDefaultAddress(env);
464  }
465  // set the call type
466  if (calltype != OREF_NULL)
467  {
468  this->settings.calltype = calltype;
469  }
470 }
471 
472 
474 /******************************************************************************/
475 /* Function: Re-dispatch an activation after a REPLY */
476 /******************************************************************************/
477 {
478  ProtectedObject r;
479  /* go run this */
481 }
482 
483 
484 RexxObject * RexxActivation::run(RexxObject *_receiver, RexxString *msgname, RexxArray *_arguments, RexxObject **_arglist,
485  size_t _argcount, size_t _named_argcount, RexxInstruction * start, ProtectedObject &resultObj)
486 /******************************************************************************/
487 /* Function: Run a REXX method...this is it! This is the heart of the */
488 /* interpreter that makes the whole thing run! */
489 /******************************************************************************/
490 {
491  // add the frame to the execution stack
492  RexxActivationFrame frame(activity, this);
493 
494  RexxActivity *oldActivity; /* old activity */
495 #ifndef FIXEDTIMERS /* currently disabled */
496  size_t instructionCount; /* instructions without yielding */
497 #endif
498  this->receiver = _receiver; /* save the message receiver */
499  // the "msgname" can also be the name of an external routine, the label
500  // name of an internal routine.
501  this->settings.msgname = msgname;
502  bool traceEntryDone = false;
503 
504  /* not a reply restart situation? */
505  if (this->execution_state != REPLIED)
506  {
507  /* exits possible? We don't use exits for methods in the image */
508  if (!this->code->isOldSpace() && this->activity->isClauseExitUsed())
509  {
510  /* check at the end of each clause */
511  this->settings.flags |= clause_boundary;
512  /* remember that we have sys exits */
513  this->settings.flags |= clause_exits;
514  }
515  this->arguments = _arguments; // Protect arglist against GC
516  this->arglist = _arglist; /* set the argument list */
517  this->argcount = _argcount;
518  this->named_argcount = _named_argcount;
519 
520  /* first entry into here? */
521  if (this->isTopLevelCall())
522  {
523  /* save entry argument list for */
524  /* variable pool fetch private */
525  /* access */
526  settings.parent_arguments = _arguments;
530  this->code->install(this); /* do any required installations */
531  this->next = this->code->getFirstInstruction(); /* ask the method for the start point*/
532  this->current = this->next; /* set the current too (for errors) */
533  /* not an internal method? */
534  if (this->isProgramLevelCall())
535  {
536  /* run initialization exit */
538  activity->getInstance()->setupProgram(this); /* do any system specific setup */
539  }
540  else
541  {
542  /* guarded method? */
543  if (isGuarded())
544  {
545  /* get the object variables */
547 
548  // For proper diagnostic in case of deadlock, do the trace now
549  if (tracingLabels() && isMethodOrRoutine())
550  {
551  traceEntry();
552  if (!tracingAll())
553  {
554  // we pause on the label only for ::OPTIONS TRACE LABELS
555  pauseLabel();
556  }
557  traceEntryDone = true;
558  }
559 
560  /* reserve the variable scope */
562  /* and remember for later */
564  }
565  /* initialize the this variable */
566  this->setLocalVariable(OREF_SELF, VARIABLE_SELF, this->receiver);
567  /* initialize the SUPER variable */
568  this->setLocalVariable(OREF_SUPER, VARIABLE_SUPER, this->receiver->superScope(this->scope));
569  }
570  }
571  else
572  {
573  if (start == OREF_NULL) /* no starting location given? */
574  {
575  this->next = this->code->getFirstInstruction(); /* ask the method for the start point*/
576  }
577  else
578  {
579  this->next = start; /* set that as the current */
580  }
581  this->current = this->next; /* set the current too (for errors) */
582  }
583  }
584  else
585  { /* resuming after a reply */
586  /* need to reaquire the lock? */
587  if (this->settings.flags&transfer_failed)
588  {
589  /* re-lock the variable dictionary */
591  /* turn off the failure flag */
592  this->settings.flags &= ~transfer_failed;
593  }
594  }
595  /* internal call? */
596  if (this->isInternalCall())
597  {
598  start = this->next; /* get the starting point */
599  /* scan over the internal labels */
600  while (start != OREF_NULL && start->isType(KEYWORD_LABEL))
601  {
602  start = start->nextInstruction; /* step to the next one */
603  }
604  /* this a procedure instruction */
605  if (start != OREF_NULL && start->isType(KEYWORD_PROCEDURE))
606  {
607  /* flip on the procedure flag */
608  this->settings.flags |= procedure_valid;
609  }
610  }
611  this->execution_state = ACTIVE; /* we are now actively processing */
612 
613  // we might have a package option that turned on tracing. If this
614  // is a routine or method invocation in one of those packages, give the
615  // initial entry trace so the user knows where we are.
616  // Must be one of ::OPTIONS TRACE ALL/RESULTS/INTERMEDIATES/LABELS
617  if (!traceEntryDone && tracingLabels() && isMethodOrRoutine())
618  {
619  traceEntry();
620  if (!tracingAll())
621  {
622  // we pause on the label only for ::OPTIONS TRACE LABELS
623  pauseLabel();
624  }
625  }
626 
627  while (true) // loop until we get a terminating condition
628  {
629  try
630  {
631  RexxExpressionStack *localStack = &this->stack; /* load up the stack */
632 #ifndef FIXEDTIMERS /* currently disabled */
633  instructionCount = 0; /* no instructions yet */
634 #endif
635  RexxInstruction *nextInst = this->next; /* get the next instruction */
636  /* loop until we get a terminating */
637  while (nextInst != OREF_NULL)
638  { /* condition */
639 
640 #ifdef FIXEDTIMERS /* currently disabled (active on Win)*/
641  /* has time Slice expired? */
643  {
644  this->activity->relinquish(); /* yield control to the activity */
645  }
646 #else
647  /* need to give someone else a shot? */
648  if (++instructionCount > MAX_INSTRUCTIONS)
649  {
650  this->activity->relinquish(); /* yield control to the activity */
651  instructionCount = 0; /* reset to zero */
652  }
653 #endif
654 
655  this->current = nextInst; /* set the next instruction */
656  this->next = nextInst->nextInstruction;/* prefetch the next clause */
657 
658  nextInst->execute(this, localStack); /* execute the instruction */
659  localStack->clear(); /* Force the stack clear */
660  this->settings.timestamp.valid = false;
661  /* need to process inter-clause stuff*/
662  if (this->settings.flags&clause_boundary)
663  {
664  this->processClauseBoundary(); /* go do the clause boundary stuff */
665  }
666  nextInst = this->next; /* get the next instruction */
667  }
668  if (this->execution_state == ACTIVE) /* implicit exit? */
669  {
670  this->implicitExit(); /* treat this like an EXIT */
671  }
672  /* is this a return situation? */
673  if (this->execution_state == RETURNED)
674  {
675  this->termination(); /* do activation termination process */
676  if (this->isInterpret())
677  {
678  /* save the nested setting */
679  bool nested = this->parent->settings.local_variables.isNested();
680  /* propagate parent's settings back */
681  this->parent->getSettings(this->settings);
682  if (!nested)
683  {
684  /* if our calling variable context was not nested, we */
685  /* need to clear it. */
687  }
688  /* merge any pending conditions */
689  this->parent->mergeTraps(this->condition_queue, this->handler_queue);
690  }
691  resultObj = this->result; /* save the result */
692  this->activity->popStackFrame(false); /* now pop the current activity */
693  /* now go run the uninit stuff */
695  }
696  else
697  { /* execution_state is REPLIED */
698  resultObj = this->result; /* save the result */
699  /* reset the next instruction */
700  this->next = this->current->nextInstruction;
701  oldActivity = this->activity; /* save the current activity */
702  /* clone the current activity */
703  this->activity = oldActivity->spawnReply();
704 
705  /* save the pointer to the start of our stack frame. We're */
706  /* going to need to release this after we migrate everything */
707  /* over. */
708  RexxObject **framePtr = localStack->getFrame();
709  /* migrate the local variables and the expression stack to the */
710  /* new activity. NOTE: these must be done in this order to */
711  /* get them allocated from the new activity in the correct */
712  /* order. */
713  localStack->migrate(this->activity);
715  /* if we have arguments, we need to migrate those also, as they are subject to overwriting once we return to the parent activation. */
716  if (arglist != OREF_NULL)
717  {
718  if ((argcount + (2 * named_argcount)) > 0)
719  {
720  RexxObject **newArguments = activity->allocateFrame(argcount + (2 * named_argcount));
721  memcpy(newArguments, arglist, sizeof(RexxObject *) * (argcount + (2 * named_argcount)));
722  this->arglist = newArguments; /* must be set on "this" */
723  this->arguments = OREF_NULL; // no need of protection against GC, the newArguments are not shared
724  settings.parent_arglist = newArguments;
726  }
727  }
728  /* return our stack frame space back to the old activity. */
729  oldActivity->releaseStackFrame(framePtr);
730 
731  this->activity->pushStackFrame(this);/* push it on to the activity stack */
732  // pop the old one off of the stack frame (but without returning it to
733  // the activation cache)
734  oldActivity->popStackFrame(true); /* pop existing one off the stack */
735  /* is the scope reserved? */
736  if (this->object_scope == SCOPE_RESERVED)
737  {
738  /* transfer the reservation */
739  if (!this->settings.object_variables->transfer(this->activity))
740  {
741  /* remember the failure */
742  this->settings.flags |= transfer_failed;
743  }
744  }
745  this->activity->run(); /* continue running the new activity */
746  oldActivity->relinquish(); /* give other activity a chance to go*/
747  }
748  return resultObj; /* return the result object */
749  }
750  catch (RexxActivation *t)
751  {
752  // if we're not the target of this throw, we've already been unwound
753  // keep throwing this until it reaches the target activation.
754  if (t != this )
755  {
756  throw;
757  }
758  // unwind the activation stack back to our frame
759  activity->unwindToFrame(this);
760 
761  this->stack.clear(); /* Force the stack clear */
762  /* invalidate the timestamp */
763  this->settings.timestamp.valid = false;
764  if (this->debug_pause)
765  { /* in a debug pause? */
766  this->execution_state = RETURNED;/* cause termination */
767  this->next = OREF_NULL; /* turn off execution engine */
768  }
769  /* have pending conditions? */
770  if (this->condition_queue != OREF_NULL)
771  {
772  /* get the pending count */
773  this->pending_count = this->condition_queue->getSize();
774  }
775  if (this->pending_count != 0)
776  { /* do we have trapped conditions? */
777  this->processTraps(); /* go dispatch the traps */
778  if (this->pending_count != 0) /* have deferred conditions? */
779  {
780  /* need to check each time around */
781  this->settings.flags |= clause_boundary;
782  }
783  }
784  }
785  }
786 }
787 
789 /******************************************************************************/
790 /* Function: process pending condition traps before going on to execute a */
791 /* clause */
792 /******************************************************************************/
793 {
794  size_t i = this->pending_count; /* get the pending count */
795  while (i--) /* while pending conditions */
796  {
797  /* get the handler off the queue */
798  RexxArray *trapHandler = (RexxArray *)this->handler_queue->pullRexx();
799  /* condition in DELAY state? */
800  if ((RexxString *)this->trapState((RexxString *)trapHandler->get(3)) == OREF_DELAY)
801  {
802  /* add to the end of the queue */
803  this->handler_queue->addLast(trapHandler);
804  /* move condition object to the end */
806  }
807  else
808  {
809  this->pending_count--; /* decrement the pending count */
810  /* get the current condition object */
811  RexxDirectory *conditionObj = (RexxDirectory *)this->condition_queue->pullRexx();
812  ProtectedObject p_conditionObj(conditionObj);
813  RexxObject *rc = conditionObj->at(OREF_RC); /* get any return code information */
814  if (rc != OREF_NULL) /* have something to assign to RC? */
815  {
816  /* initialize the RC variable */
817  this->setLocalVariable(OREF_RC, VARIABLE_RC, rc);
818  }
819  // it's possible that the condition can raise an error because of a
820  // missing label, so we need to catch any conditions that might be thrown
821  try
822  {
823  /* call the condition handler */
824  ((RexxInstructionCallBase *)trapHandler->get(1))->trap(this, conditionObj);
825  }
826  catch (RexxActivation *t)
827  {
828  // if we're not the target of this throw, we've already been unwound
829  // keep throwing this until it reaches the target activation.
830  if (t != this )
831  {
832  throw;
833  }
834  }
835  }
836  }
837 }
838 
839 
841  wholenumber_t skipcount, /* clauses to skip pausing */
842  bool notrace ) /* tracing suppression flag */
843 /******************************************************************************/
844 /* Function: Process a numeric "debug skip" TRACE instruction to suppress */
845 /* pauses or tracing for a given number of instructions. */
846 /******************************************************************************/
847 {
848  if (!this->debug_pause) /* not an allowed state? */
849  {
850  /* report the error */
852  }
853  /* copy the execution count */
854  this->settings.trace_skip = skipcount;
855  /* set the skip flag */
856  if (notrace) /* turning suppression on? */
857  {
858  /* flip on the flag */
859  this->settings.flags |= trace_suppress;
860  }
861  else /* skipping pauses only */
862  {
863  this->settings.flags &= ~trace_suppress;
864  }
865  this->settings.flags |= debug_bypass;/* let debug prompt know of changes */
866 }
867 
869 /******************************************************************************/
870 /* Function: Generate a string form of the current trace setting */
871 /******************************************************************************/
872 {
873  // have the source file process this
875 }
876 
877 
878 /**
879  * Set the trace using a dynamically evaluated string.
880  *
881  * @param setting The new trace setting.
882  */
883 void RexxActivation::setTrace(RexxString *setting, bool externalTrace, size_t depth)
884 {
885  size_t newsetting; /* new trace setting */
886  size_t traceFlags; // the optimized trace flags
887 
888  char traceOption = 0; // a potential bad character
889 
890  if (!RexxSource::parseTraceSetting(setting, newsetting, traceFlags, traceOption))
891  {
893  }
894  if (externalTrace)
895  {
896  this->settings.externalTraceOption = newsetting;
897  this->settings.externalTraceFlags = traceFlags;
898  this->settings.externalTraceDepth = depth;
899  }
900  /* now change the setting */
901  setTrace(newsetting, traceFlags);
902 }
903 
904 
905 /**
906  * Set a new trace setting for the context.
907  *
908  * @param traceOption
909  * The new trace setting option. This includes the
910  * setting option and any debug flag options, ANDed together.
911  */
912 void RexxActivation::setTrace(size_t traceOption, size_t traceFlags)
913 {
914  /* turn off the trace suppression */
915  this->settings.flags &= ~trace_suppress;
916  this->settings.trace_skip = 0; /* and allow debug pauses */
917 
918  // we might need to transfer some information from the
919  // current settings
920  if ((traceOption&RexxSource::DEBUG_TOGGLE) != 0)
921  {
922  // if nothing else was specified, this was a pure toggle
923  // operation, which maintains the existing settings
924  if (traceFlags == 0)
925  {
926  // pick up the existing flags
927  traceFlags = settings.flags&trace_flags;
928  traceOption = settings.traceOption;
929  }
930 
931  /* switch to the opposite setting */
932  /* already on? */
933  if ((this->settings.flags&trace_debug) != 0)
934  {
935  /* switch the setting off */
936  traceFlags &= ~trace_debug;
937  traceOption &= ~RexxSource::DEBUG_ON;
938  // flipping out of debug mode. Reissue the debug prompt when
939  // turned back on again
941  }
942  else
943  {
944  // switch the setting on in both the flags and the setting
945  traceFlags |= trace_debug;
946  traceOption |= RexxSource::DEBUG_ON;
947  }
948  }
949  // are we in debug mode already? A trace setting with no "?" maintains the
950  // debug setting, unless it is Trace Off
951  else if ((settings.flags&trace_debug) != 0)
952  {
953  if (traceFlags == 0)
954  {
955  // flipping out of debug mode. Reissue the debug prompt when
956  // turned back on again
958  }
959  else
960  {
961  // add debug mode into the new settings if on
962  traceFlags |= trace_debug;
963  traceOption |= RexxSource::DEBUG_ON;
964  }
965  }
966 
967  // save the option so it can be formatted back into a trace value
968  this->settings.traceOption = traceOption;
969  // clear the current trace options
971  // set the new flags
972  settings.flags |= traceFlags;
973  // if tracing intermediates, turn on the special fast check flag
975  {
976  /* turn on the special fast-path test */
977  this->settings.intermediate_trace = true;
978  }
979 
980  if (this->debug_pause) /* issued from a debug prompt? */
981  {
982  /* let debug prompt know of changes */
983  this->settings.flags |= debug_bypass;
984  }
985 }
986 
987 
988 /**
989  * Process a trace setting and reduce it to the component
990  * flag settings that can be used to set defaults.
991  *
992  * @param traceSetting
993  * The input trace setting.
994  *
995  * @return The set of flags that will be set in the debug flags
996  * when trace setting change.
997  */
998 size_t RexxActivation::processTraceSetting(size_t traceSetting)
999 {
1000  size_t flags = 0;
1001  switch (traceSetting & TRACE_DEBUG_MASK)
1002  {
1003  case RexxSource::DEBUG_ON: /* turn on interactive debug */
1004  /* switch the setting on */
1005  flags |= trace_debug;
1006  break;
1007 
1008  case RexxSource::DEBUG_OFF: /* turn off interactive debug */
1009  /* switch the setting off */
1010  flags &= ~trace_debug;
1011  break;
1012  // These two have no meaning in a staticically defined situation, so
1013  // they'll need to be handled at runtime.
1014  case RexxSource::DEBUG_TOGGLE: /* toggle interactive debug setting */
1015  case RexxSource::DEBUG_IGNORE: /* no changes to debug setting */
1016  break;
1017  }
1018  // now optimize the trace setting flags
1020  {
1021  case RexxSource::TRACE_ALL: /* TRACE ALL; */
1022  /* trace instructions, labels and */
1023  /* all commands */
1024  flags |= (trace_all | trace_labels | trace_commands);
1025  break;
1026 
1027  case RexxSource::TRACE_COMMANDS: /* TRACE COMMANDS; */
1028  flags |= trace_commands;
1029  break;
1030 
1031  case RexxSource::TRACE_LABELS: /* TRACE LABELS */
1032  flags |= trace_labels;
1033  break;
1034 
1035  case RexxSource::TRACE_NORMAL: /* TRACE NORMAL */
1036  case RexxSource::TRACE_FAILURES: /* TRACE FAILURES */
1037  /* just trace command failures */
1038  flags |= trace_failures;
1039  break;
1040 
1041  case RexxSource::TRACE_ERRORS: /* TRACE ERRORS */
1042  /* trace command failures and error */
1043  flags |= (trace_failures | trace_errors);
1044  break;
1045 
1046  case RexxSource::TRACE_RESULTS: /* TRACE RESULTS */
1048  break;
1049 
1050  case RexxSource::TRACE_INTERMEDIATES: /* TRACE INTERMEDIATES */
1051  /* trace just about every things */
1053  break;
1054 
1055  case RexxSource::TRACE_OFF: /* TRACE OFF */
1056  flags = trace_off; // turn of all trace options, including debug flags
1057  break;
1058 
1059  case RexxSource::TRACE_IGNORE: /* don't change trace setting */
1060  break;
1061  }
1062  return flags;
1063 }
1064 
1065 void RexxActivation::live(size_t liveMark)
1066 /******************************************************************************/
1067 /* Function: Normal garbage collection live marking */
1068 /******************************************************************************/
1069 {
1070  memory_mark(this->previous);
1071  memory_mark(this->executable);
1072  memory_mark(this->scope);
1073  memory_mark(this->code);
1075  memory_mark(this->receiver);
1076  memory_mark(this->activity);
1077  memory_mark(this->parent);
1078  memory_mark(this->dostack);
1079  /* the stack and the local variables handle their own marking. */
1080  this->stack.live(liveMark);
1081  this->settings.local_variables.live(liveMark);
1082  memory_mark(this->current);
1083  memory_mark(this->next);
1084  memory_mark(this->result);
1085  memory_mark(this->trapinfo);
1086  memory_mark(this->objnotify);
1088  memory_mark(this->handler_queue);
1090  memory_mark(this->settings.traps);
1095  memory_mark(this->settings.msgname);
1097  memory_mark(this->settings.calltype);
1098  memory_mark(this->settings.streams);
1100  memory_mark(this->contextObject);
1101  memory_mark(this->arguments); // arguments can be user-redefined (ex : yield), must be marked
1102 
1103  /* We're hold a pointer back to our arguments directly where they */
1104  /* are created. Since in some places, this argument list comes */
1105  /* from the C stack, we need to handle the marker ourselves. */
1106  size_t i;
1107  if (arglist != OREF_NULL)
1108  {
1109  for (i = 0; i < (argcount + (2 * named_argcount)); i++)
1110  {
1111  memory_mark(arglist[i]);
1112  }
1113  }
1114 
1115  memory_mark(settings.parent_arguments); // arguments can be user-redefined (ex : yield), must be marked
1117  {
1118  for (i = 0; i < (settings.parent_argcount + (2 * settings.parent_named_argcount)); i++)
1119  {
1121  }
1122  }
1123 }
1124 
1126 /******************************************************************************/
1127 /* Function: Generalized object marking */
1128 /******************************************************************************/
1129 {
1132  memory_mark_general(this->code);
1136  memory_mark_general(this->parent);
1138  /* the stack and the local variables handle their own marking. */
1139  this->stack.liveGeneral(reason);
1140  this->settings.local_variables.liveGeneral(reason);
1142  memory_mark_general(this->next);
1143  memory_mark_general(this->result);
1160  memory_mark_general(this->arguments); // arguments can be user-redefined (ex : yield), must be marked
1161 
1162  /* We're hold a pointer back to our arguments directly where they */
1163  /* are created. Since in some places, this argument list comes */
1164  /* from the C stack, we need to handle the marker ourselves. */
1165  size_t i;
1166  if (arglist != OREF_NULL)
1167  {
1168  for (i = 0; i < (argcount + (2 * named_argcount)); i++)
1169  {
1171  }
1172  }
1173 
1174  memory_mark_general(settings.parent_arguments); // arguments can be user-redefined (ex : yield), must be marked
1176  {
1177  for (i = 0; i < (settings.parent_argcount + (2 * settings.parent_named_argcount)); i++)
1178  {
1180  }
1181  }
1182 }
1183 
1184 
1186  RexxObject * resultObj) /* returned REPLY result */
1187 /******************************************************************************/
1188 /* Function: Process a REXX REPLY instruction */
1189 /******************************************************************************/
1190 {
1191  /* already had a reply issued? */
1192  if (this->settings.flags&reply_issued)
1193  {
1194  /* flag this as an error */
1196  }
1197  this->settings.flags |= reply_issued;/* turn on the replied flag */
1198  /* change execution state to */
1199  this->execution_state = REPLIED; /* terminate the main loop */
1200  this->next = OREF_NULL; /* turn off execution engine */
1201  this->result = resultObj; /* save the result value */
1202 }
1203 
1204 
1206  RexxObject * resultObj) /* returned RETURN/EXIT result */
1207 /******************************************************************************/
1208 /* Function: process a REXX RETURN instruction */
1209 /******************************************************************************/
1210 {
1211  /* already had a reply issued? */
1212  if (this->settings.flags&reply_issued && resultObj != OREF_NULL)
1213  {
1214  /* flag this as an error */
1216  }
1217  /* processing an Interpret */
1218  if (this->isInterpret())
1219  {
1220  this->execution_state = RETURNED; /* this is a returned state */
1221  this->next = OREF_NULL; /* turn off execution engine */
1222  /* cause a return in the parent */
1223  this->parent->returnFrom(resultObj); /* activity */
1224  }
1225  else
1226  {
1227  this->execution_state = RETURNED; /* the state is returned */
1228  this->next = OREF_NULL; /* turn off execution engine */
1229  this->result = resultObj; /* save the return result */
1230  /* real program call? */
1231  if (this->isProgramLevelCall())
1232  {
1233  /* run termination exit */
1235  }
1236  }
1237  /* switch debug off to avoid debug */
1238  /* pause after exit entered from an */
1239  this->settings.flags &= ~trace_debug;/* interactive debug prompt */
1240  this->settings.flags |= debug_bypass;/* let debug prompt know of changes */
1241 }
1242 
1243 
1245  RexxString * name ) /* name specified on iterate */
1246 /******************************************************************************/
1247 /* Function: Process a REXX ITERATE instruction */
1248 /******************************************************************************/
1249 {
1250  RexxDoBlock *doblock = this->topBlock(); /* get the first stack item */
1251 
1252  while (doblock != OREF_NULL)
1253  { /* while still DO blocks to process */
1254  RexxBlockInstruction *loop = doblock->getParent(); /* get the actual loop instruction */
1255  if (name == OREF_NULL) // leaving the inner-most loop?
1256  {
1257  // we only recognize LOOP constructs for this.
1258  if (loop->isLoop())
1259  {
1260  /* reset the indentation */
1261  this->setIndent(doblock->getIndent());
1262  ((RexxInstructionDo *)loop)->reExecute(this, &this->stack, doblock);
1263  return; /* we're finished */
1264  }
1265 
1266  }
1267  // a named LEAVE can be either a labeled block or a loop.
1268  else if (loop->isLabel(name))
1269  {
1270  if (!loop->isLoop())
1271  {
1273  }
1274  /* reset the indentation */
1275  this->setIndent(doblock->getIndent());
1276  ((RexxInstructionDo *)loop)->reExecute(this, &this->stack, doblock);
1277  return; /* we're finished */
1278  }
1279  this->popBlock(); /* cause termination cleanup */
1280  this->removeBlock(); /* remove the execution nest */
1281  doblock = this->topBlock(); /* get the new stack top */
1282  }
1283  if (name != OREF_NULL) /* have a name? */
1284  {
1285  /* report exception with the name */
1287  }
1288  else
1289  {
1290  /* have a misplaced ITERATE */
1292  }
1293 }
1294 
1295 
1297  RexxString * name ) /* name specified on leave */
1298 /******************************************************************************/
1299 /* Function: Process a REXX LEAVE instruction */
1300 /******************************************************************************/
1301 {
1302  RexxDoBlock *doblock = this->topBlock(); /* get the first stack item */
1303 
1304  while (doblock != OREF_NULL)
1305  { /* while still DO blocks to process */
1306  RexxBlockInstruction *loop = doblock->getParent(); /* get the actual loop instruction */
1307  if (name == OREF_NULL) // leaving the inner-most loop?
1308  {
1309  // we only recognize LOOP constructs for this.
1310  if (loop->isLoop())
1311  {
1312  loop->terminate(this, doblock); /* terminate the loop */
1313  return; /* we're finished */
1314  }
1315 
1316  }
1317  // a named LEAVE can be either a labeled block or a loop.
1318  else if (loop->isLabel(name))
1319  {
1320  loop->terminate(this, doblock); /* terminate the loop */
1321  return; /* we're finished */
1322  }
1323  this->popBlock(); /* cause termination cleanup */
1324  this->removeBlock(); /* remove the execution nest */
1325  /* get the first stack item again */
1326  doblock = this->topBlock(); /* get the new stack top */
1327  }
1328  if (name != OREF_NULL) /* have a name? */
1329  {
1330  /* report exception with the name */
1332  }
1333  else
1334  {
1335  /* have a misplaced LEAVE */
1337  }
1338 }
1339 
1341 /******************************************************************************/
1342 /* Function: Return the line number of the current instruction */
1343 /******************************************************************************/
1344 {
1345  if (this->current != OREF_NULL) /* have a current line? */
1346  {
1347  return this->current->getLineNumber(); /* return the line number */
1348  }
1349  else
1350  {
1351  return 1; /* error on the loading */
1352  }
1353 }
1354 
1355 
1357  RexxVariableBase **variables, size_t count)
1358 /******************************************************************************/
1359 /* Function: Expose variables for a PROCEDURE instruction */
1360 /******************************************************************************/
1361 {
1362  /* procedure not allowed here? */
1363  if (!(this->settings.flags&procedure_valid))
1364  {
1365  /* raise the appropriate error! */
1367  }
1368  /* disable further procedures */
1369  this->settings.flags &= ~procedure_valid;
1370 
1371  /* get a new */
1373  /* make sure we clear out the dictionary, otherwise we'll see the */
1374  /* dynamic entries from the previous level. */
1376 
1377  /* now expose each individual variable */
1378  for (size_t i = 0; i < count; i++)
1379  {
1380  variables[i]->procedureExpose(this, parent, &stack);
1381  }
1382 }
1383 
1384 
1386  RexxVariableBase **variables, size_t count)
1387 /******************************************************************************/
1388 /* Function: Expose variables for an EXPOSE instruction */
1389 /******************************************************************************/
1390 {
1391  /* get the variable set for this object */
1392  RexxVariableDictionary * object_variables = getObjectVariables();
1393 
1394  /* now expose each individual variable */
1395  for (size_t i = 0; i < count; i++)
1396  {
1397  variables[i]->expose(this, &stack, object_variables);
1398  }
1399 }
1400 
1401 
1403  RexxObject * target, /* target object */
1404  RexxString * message, /* message to send */
1405  RexxObject * superClass, /* class over ride */
1406  RexxObject ** _arguments, /* message arguments */
1407  size_t _argcount, /* count of message positional arguments */
1408  size_t _named_argcount,
1409  bool continuing) /* return/continue flag */
1410 /******************************************************************************/
1411 /* Function: Process a REXX FORWARD instruction */
1412 /******************************************************************************/
1413 {
1414  if (target == OREF_NULL) /* no target? */
1415  {
1416  target = this->receiver; /* use this */
1417  }
1418  if (message == OREF_NULL) /* no message override? */
1419  {
1420  message = this->settings.msgname; /* use same message name */
1421  }
1422  if (_arguments == OREF_NULL)
1423  { /* no arguments given? */
1424  _arguments = this->arglist; /* use the same arguments */
1425  _argcount = this->argcount;
1426  _named_argcount = this->named_argcount;
1427  }
1428  if (continuing)
1429  { /* just processing the message? */
1430  ProtectedObject r;
1431  if (superClass == OREF_NULL) /* no override? */
1432  {
1433  /* issue the message and return */
1434  target->messageSend(message, _arguments, _argcount, _named_argcount, r);
1435  }
1436  else
1437  {
1438  /* issue the message with override */
1439  target->messageSend(message, _arguments, _argcount, _named_argcount, superClass, r);
1440  }
1441  return(RexxObject *)r;
1442  }
1443  else
1444  { /* got to shut down and issue */
1445  this->settings.flags |= forwarded; /* we are now a phantom activation */
1446  /* already had a reply issued? */
1447  if (this->settings.flags&reply_issued && this->result != OREF_NULL)
1448  {
1449  /* flag this as an error */
1451  }
1452  this->execution_state = RETURNED; /* this is an EXIT for real */
1453  this->next = OREF_NULL; /* turn off execution engine */
1454  /* switch debug off to avoid debug */
1455  /* pause after exit entered from an */
1456  /* interactive debug prompt */
1457  this->settings.flags &= ~trace_debug;
1458  /* let debug prompt know of changes */
1459  this->settings.flags |= debug_bypass;
1460  ProtectedObject r;
1461  if (superClass == OREF_NULL) /* no over ride? */
1462  {
1463  /* issue the simple message */
1464  target->messageSend(message, _arguments, _argcount, _named_argcount, r);
1465  }
1466  else
1467  {
1468  /* use the full override */
1469  target->messageSend(message, _arguments, _argcount, _named_argcount, superClass, r);
1470  }
1471  this->result = (RexxObject *)r; /* save the result value */
1472  /* already had a reply issued? */
1473  if (this->settings.flags&reply_issued && this->result != OREF_NULL)
1474  {
1475  /* flag this as an error */
1477  }
1478  this->termination(); /* run "program" termination method */
1479  /* if there are stream objects */
1480  return OREF_NULL; /* just return nothing */
1481  }
1482 }
1483 
1485  RexxObject * resultObj) /* EXIT result */
1486 /******************************************************************************/
1487 /* Function: Process a REXX exit instruction */
1488 /******************************************************************************/
1489 {
1490  RexxActivation *activation; /* unwound activation */
1491 
1492  this->execution_state = RETURNED; /* this is an EXIT for real */
1493  this->next = OREF_NULL; /* turn off execution engine */
1494  this->result = resultObj; /* save the result value */
1495  /* switch debug off to avoid debug */
1496  /* pause after exit entered from an */
1497  this->settings.flags &= ~trace_debug;/* interactive debug prompt */
1498  this->settings.flags |= debug_bypass;/* let debug prompt know of changes */
1499  /* at a main program level? */
1500  if (this->isTopLevelCall())
1501  {
1502  /* already had a reply issued? */
1503  if (this->settings.flags&reply_issued && result != OREF_NULL)
1504  {
1505  /* flag this as an error */
1507  }
1508  /* real program call? */
1509  if (this->isProgramLevelCall())
1510  {
1511  /* run termination exit */
1513  }
1514  }
1515  else
1516  { /* internal routine or Interpret */
1517  /* start terminating with this level */
1518  activation = this;
1519  do
1520  {
1521  activation->termination(); /* make sure this level cleans up */
1522  ActivityManager::currentActivity->popStackFrame(false); /* pop this level off */
1523  /* get the next level */
1525  } while (!activation->isTopLevel());
1526 
1527  activation->exitFrom(resultObj); /* tell this level to terminate */
1528  /* unwind and process the termination*/
1529  throw activation; // throw this as an exception to start the unwinding
1530  }
1531 }
1532 
1533 #if 0
1535 /******************************************************************************/
1536 /* Function: Process a "fall of the end" exit condition */
1537 /******************************************************************************/
1538 {
1539  /* at a main program level or completing an INTERPRET */
1540  /* instruction? */
1541  if (this->isTopLevelCall() || this->isInterpret())
1542  {
1543  /* real program call? */
1544  if (this->isProgramLevelCall())
1545  {
1546  /* run termination exit */
1547  this->activity->callTerminationExit(this);
1548  }
1549  this->execution_state = RETURNED;/* this is an EXIT for real */
1550  return; /* we're finished here */
1551  }
1552  this->exitFrom(OREF_NULL); /* we've had a nested exit, we need to process this more fully */
1553 }
1554 #endif
1555 
1557 /******************************************************************************/
1558 /* Function: do any cleanup due to a program terminating. */
1559 /******************************************************************************/
1560 {
1561  this->guardOff(); /* Remove any guards for this activatio*/
1562 
1563  /* were there any SETLOCAL calls for */
1564  /* this method? And are there any */
1565  /* that didn't have a matching ENDLOC*/
1566  if (this->environmentList != OREF_NULL && this->environmentList->getSize() != 0)
1567  {
1568  /* Yes, then restore the environment */
1569  /* to the ist on added. */
1571  }
1572  this->environmentList = OREF_NULL; /* Clear out the env list */
1573  this->closeStreams(); /* close any open streams */
1574  /* release the stack frame, which also releases the frame for the */
1575  /* variable cache. */
1577  /* do the variable termination */
1579  // deactivate the context object if we created one.
1580  if (contextObject != OREF_NULL)
1581  {
1582  contextObject->detach();
1583  }
1584 }
1585 
1586 
1588 /******************************************************************************/
1589 /* Function: Create/copy a trap table as needed */
1590 /******************************************************************************/
1591 {
1592  /* no trap table created yet? */
1593  if (this->settings.traps == OREF_NULL)
1594  {
1595  /* create the trap table */
1596  this->settings.traps = new_directory();
1597  }
1598  /* have to copy the trap table for an*/
1599  /* internal routine call? */
1600  else if (this->isInternalCall() && !(this->settings.flags&traps_copied))
1601  {
1602  /* copy the table */
1603  this->settings.traps = (RexxDirectory *)this->settings.traps->copy();
1604  /* record that we've copied this */
1605  this->settings.flags |= traps_copied;
1606  }
1607 }
1608 
1610  RexxString * condition, /* condition name */
1611  /* handler for this trap */
1612  RexxInstructionCallBase * handler )
1613 /******************************************************************************/
1614 /* Function: Activate a condition trap */
1615 /******************************************************************************/
1616 {
1617  this->checkTrapTable(); /* make sure we have a table */
1618  /* add the trap to the table */
1619  this->settings.traps->put(new_array((RexxObject *)handler, OREF_ON, condition), condition);
1620  /* novalue condition or any? */
1621  if (condition->strCompare(CHAR_NOVALUE) || condition->strCompare(CHAR_ANY))
1622  {
1623  /* tag the method dictionary */
1625  }
1626 }
1627 
1628 
1630  RexxString * condition) /* condition name */
1631 /******************************************************************************/
1632 /* Function: Disable a condition trap */
1633 /******************************************************************************/
1634 {
1635  this->checkTrapTable(); /* make sure we have a table */
1636  /* remove the trap */
1637  this->settings.traps->remove(condition);
1638  /* novalue condition? */
1639  if (!this->isInternalCall() && condition->strCompare(CHAR_NOVALUE))
1640  {
1641  /* not also trapping ANY? */
1642  if (this->settings.traps->at(OREF_ANY) == OREF_NULL)
1643  {
1644  /* tag the method dictionary */
1646  }
1647  }
1648 }
1649 
1651 /******************************************************************************/
1652 /* Function: Return the top level external activation */
1653 /******************************************************************************/
1654 {
1655  /* if an internal call or an */
1656  /* interpret, we need to pass this */
1657  /* along */
1658  if (this->isInternalLevelCall())
1659  {
1660  return this->parent->external(); /* get our sender method */
1661  }
1662  else
1663  {
1664  return this; /* already at the top level */
1665  }
1666 }
1667 
1668 
1670  RexxString * condition, /* condition to raise */
1671  RexxObject * rc, /* information assigned to RC */
1672  RexxString * description, /* description of the condition */
1673  RexxObject * additional, /* extra descriptive information */
1674  RexxObject * resultObj, /* return result */
1675  RexxDirectory * conditionobj ) /* propagated condition object */
1676 /******************************************************************************/
1677 /* Function: Raise a condition using exit semantics for the returned value. */
1678 /******************************************************************************/
1679 {
1680  /* not internal routine or Interpret */
1681  /* instruction activation? */
1682  if (this->isTopLevelCall())
1683  {
1684  /* do the real condition raise */
1685  this->raise(condition, rc, description, additional, resultObj, conditionobj);
1686  return; /* return if processed */
1687  }
1688 
1689  /* reached the top level? */
1690  if (this->parent == OREF_NULL)
1691  {
1692  this->exitFrom(resultObj); /* turn into an exit instruction */
1693  }
1694  else
1695  {
1696  /* real program call? */
1697  if (this->isProgramLevelCall())
1698  {
1699  /* run termination exit */
1701  }
1702  ProtectedObject p(this);
1703  this->termination(); /* remove guarded status on object */
1704  this->activity->popStackFrame(false); /* pop ourselves off active list */
1705  /* propogate the condition backward */
1706  this->parent->raiseExit(condition, rc, description, additional, resultObj, conditionobj);
1707  }
1708 }
1709 
1710 
1712  RexxString * condition, /* condition to raise */
1713  RexxObject * rc, /* information assigned to RC */
1714  RexxString * description, /* description of the condition */
1715  RexxObject * additional, /* extra descriptive information */
1716  RexxObject * resultObj, /* return result */
1717  RexxDirectory * conditionobj ) /* propagated condition object */
1718 /******************************************************************************/
1719 /* Function: Raise a give REXX condition */
1720 /******************************************************************************/
1721 {
1722  ProtectedObject p_conditionobj;
1723  bool propagated; /* propagated syntax condition */
1724 
1725  /* propagating an existing condition?*/
1726  if (condition->strCompare(CHAR_PROPAGATE))
1727  {
1728  /* get the original condition name */
1729  condition = (RexxString *)conditionobj->at(OREF_CONDITION);
1730  propagated = true; /* this is propagated */
1731  /* fill in the propagation status */
1732  conditionobj->put(TheTrueObject, OREF_PROPAGATED);
1733  if (resultObj == OREF_NULL) /* no result specified? */
1734  {
1735  resultObj = conditionobj->at(OREF_RESULT);
1736  }
1737  }
1738  else
1739  { /* build a condition object */
1740  conditionobj = new_directory(); /* get a new directory */
1741  p_conditionobj = conditionobj;
1742  /* put in the condition name */
1743  conditionobj->put(condition, OREF_CONDITION);
1744  /* fill in default description */
1745  conditionobj->put(OREF_NULLSTRING, OREF_DESCRIPTION);
1746  /* fill in the propagation status */
1747  conditionobj->put(TheFalseObject, OREF_PROPAGATED);
1748  propagated = false; /* remember for later */
1749  }
1750  if (rc != OREF_NULL) /* have an RC value? */
1751  {
1752  conditionobj->put(rc, OREF_RC); /* add to the condition argument */
1753  }
1754  if (description != OREF_NULL) /* any description to add? */
1755  {
1756  conditionobj->put(description, OREF_DESCRIPTION);
1757  }
1758  if (additional != OREF_NULL) /* or additional information */
1759  {
1760  conditionobj->put(additional, OREF_ADDITIONAL);
1761  }
1762  if (resultObj != OREF_NULL) /* or a result object */
1763  {
1764  conditionobj->put(resultObj, OREF_RESULT);
1765  }
1766 
1767  /* fatal SYNTAX error? */
1768  if (condition->strCompare(CHAR_SYNTAX))
1769  {
1770  ProtectedObject p(this);
1771  if (propagated)
1772  { /* reraising a condition? */
1773  this->termination(); /* do the termination cleanup on ourselves */
1774  this->activity->popStackFrame(false); /* pop ourselves off active list */
1775  /* go propagate the condition */
1777  }
1778  else
1779  {
1780  /* go raise the error */
1781  ActivityManager::currentActivity->raiseException(((RexxInteger *)rc)->getValue(), description, (RexxArray *)additional, resultObj);
1782  }
1783  }
1784  else
1785  { /* normal condition trapping */
1786  /* get the sender object (if any) */
1787  // find a predecessor Rexx activation
1788  RexxActivation *_sender = this->senderActivation();
1789  /* do we have a sender that is */
1790  /* trapping this condition? */
1791  /* do we have a sender? */
1792  bool trapped = false;
1793  if (_sender != OREF_NULL)
1794  {
1795  /* "tickle them" with this */
1796  trapped = _sender->trap(condition, conditionobj);
1797  }
1798 
1799  /* is this an untrapped halt condition? Need to transform into a SYNTAX error */
1800  if (!trapped && condition->strCompare(CHAR_HALT))
1801  {
1802  /* raise as a syntax error */
1804  }
1805 
1806  this->returnFrom(resultObj); /* process the return part */
1807  throw this; /* unwind and process the termination*/
1808  }
1809 }
1810 
1811 
1813 /******************************************************************************/
1814 /* Function: Return the associated object variables vdict */
1815 /******************************************************************************/
1816 {
1817  /* no retrieved yet? */
1818  if (this->settings.object_variables == OREF_NULL)
1819  {
1820  /* get the object variables */
1822  if (isGuarded()) /* guarded method? */
1823  {
1824  /* reserve the variable scope */
1825  this->settings.object_variables->reserve(this->activity);
1826  /* and remember for later */
1827  this->object_scope = SCOPE_RESERVED;
1828  }
1829  }
1830  /* return the vdict */
1831  return this->settings.object_variables;
1832 }
1833 
1834 
1835 /**
1836  * Resolve a stream name for a BIF call.
1837  *
1838  * @param name The name of the stream.
1839  * @param stack The expression stack.
1840  * @param input The input/output flag.
1841  * @param fullName The returned full name of the stream.
1842  * @param added A flag indicating we added this.
1843  *
1844  * @return The backing stream object for the name.
1845  */
1846 RexxObject *RexxActivation::resolveStream(RexxString *name, bool input, RexxString **fullName, bool *added)
1847 {
1848  if (added != NULL)
1849  {
1850  *added = false; /* when caller requires stream table entry then initialize */
1851  }
1852  RexxDirectory *streamTable = getStreams(); /* get the current stream set */
1853  if (fullName) /* fullName requested? */
1854  {
1855  *fullName = name; /* initialize to name */
1856  }
1857  /* if length of name is 0, then it's the same as omitted */
1858  if (name == OREF_NULL || name->getBLength() == 0) /* no name? */
1859  {
1860  if (input) /* input operation? */
1861  {
1862  /* get the default output stream */
1863  return getLocalEnvironment(OREF_INPUT);
1864  }
1865  else
1866  {
1867  /* get the default output stream */
1868  return getLocalEnvironment(OREF_OUTPUT);
1869  }
1870  }
1871  /* standard input stream? */
1872  else if (name->strCaselessCompare(CHAR_STDIN) || name->strCaselessCompare(CHAR_CSTDIN))
1873  {
1874  /* get the default output stream */
1875  return getLocalEnvironment(OREF_INPUT);
1876  }
1877  /* standard output stream? */
1878  else if (name->strCaselessCompare(CHAR_STDOUT) || name->strCaselessCompare(CHAR_CSTDOUT))
1879  {
1880  /* get the default output stream */
1881  return getLocalEnvironment(OREF_OUTPUT);
1882  }
1883  /* standard error stream? */
1884  else if (name->strCaselessCompare(CHAR_STDERR) || name->strCaselessCompare(CHAR_CSTDERR))
1885  {
1886  /* get the default output stream */
1887  return getLocalEnvironment(OREF_ERRORNAME);
1888  }
1889  else
1890  {
1891  /* go get the qualified name */
1893  if (fullName) /* fullName requested? */
1894  {
1895  *fullName = qualifiedName; /* provide qualified name */
1896  }
1897  // protect from GC
1898  ProtectedObject p(qualifiedName);
1899  /* Note: stream name is pushed to the stack to be protected from GC; */
1900  /* e.g. it is used by the caller to remove stream from stream table. */
1901  /* The stack will be reset after the function was executed and the */
1902  /* protection is released */
1903  /* see if we've already opened this */
1904  RexxObject *stream = streamTable->at(qualifiedName);
1905  if (stream == OREF_NULL) /* not open */
1906  {
1908  stream = manager->checkStreamAccess(qualifiedName);
1909  if (stream != OREF_NULL)
1910  {
1911  streamTable->put(stream, qualifiedName);
1912  return stream; /* return the stream object */
1913  }
1914  /* get the stream class */
1915  RexxObject *streamClass = TheEnvironment->at(OREF_STREAM);
1916  /* create a new stream object */
1917  stream = streamClass->sendMessage(OREF_NEW, name);
1918 
1919  if (added) /* open the stream? begin */
1920  {
1921  /* add to the streams table */
1922  streamTable->put(stream, qualifiedName);
1923  *added = true; /* mark it as added to stream table */
1924  }
1925  }
1926  return stream; /* return the stream object */
1927  }
1928 }
1929 
1931 /******************************************************************************/
1932 /* Function: Return the associated object variables stream table */
1933 /******************************************************************************/
1934 {
1935  /* not created yet? */
1936  if (this->settings.streams == OREF_NULL)
1937  {
1938  /* first entry into here? */
1939  if (this->isProgramOrMethod())
1940  {
1941  /* always use a new directory */
1942  this->settings.streams = new_directory();
1943  }
1944  else
1945  {
1946  // get the caller frame. If it is not a Rexx one, then
1947  // we use a fresh stream table
1948  RexxActivationBase *callerFrame = getPreviousStackFrame();
1949  if (callerFrame == OREF_NULL || !callerFrame->isRexxContext())
1950  {
1951  this->settings.streams = new_directory();
1952  }
1953  else
1954  {
1955 
1956  /* alway's use caller's for internal */
1957  /* call, external call or interpret */
1958  this->settings.streams = ((RexxActivation *)callerFrame)->getStreams();
1959  }
1960  }
1961  }
1962  return this->settings.streams; /* return the stream table */
1963 }
1964 
1966  RexxInstruction * target ) /* target instruction */
1967 /******************************************************************************/
1968 /* Function: Signal to a targer instruction */
1969 /******************************************************************************/
1970 {
1971  /* internal routine or Interpret */
1972  /* instruction activation? */
1973  if (this->isInterpret())
1974  {
1975  this->execution_state = RETURNED; /* signal interpret termination */
1976  this->next = OREF_NULL; /* turn off execution engine */
1977  this->parent->signalTo(target); /* propogate the signal backward */
1978  }
1979  else
1980  {
1981  /* initialize the SIGL variable */
1982  size_t lineNum = this->current->getLineNumber();/* get the instruction line number */
1983  this->setLocalVariable(OREF_SIGL, VARIABLE_SIGL, new_integer(lineNum));
1984  this->next = target; /* set the new target location */
1985  this->dostack = OREF_NULL; /* clear the do loop stack */
1986  this->blockNest = 0; /* no more active blocks */
1987  this->settings.traceindent = 0; /* reset trace indentation */
1988  }
1989 }
1990 
1992 /******************************************************************************/
1993 /* Function: Toggle the address setting between the current and alternate */
1994 /******************************************************************************/
1995 {
1996  RexxString *temp = this->settings.current_env; /* save the current environment */
1997  /* make the alternate the current */
1999  this->settings.alternate_env = temp; /* old current is now the alternate */
2000 }
2001 
2002 
2004  RexxString * address ) /* new address environment */
2005 /******************************************************************************/
2006 /* Function: Set the new current address, moving the current one to the */
2007 /* alternate address */
2008 /******************************************************************************/
2009 {
2010  /* old current is now the alternate */
2012  this->settings.current_env = address;/* set new current environment */
2013 }
2014 
2015 
2017  RexxString * address ) /* new address environment */
2018 /******************************************************************************/
2019 /* Function: Set up a default address environment so that both the primary */
2020 /* and the alternate address are the same value */
2021 /******************************************************************************/
2022 {
2023  /* old current is the new one */
2024  this->settings.alternate_env = address;
2025  this->settings.current_env = address;/* set new current environment */
2026 }
2027 
2028 
2030  RexxString * name ) /* target label name */
2031 /******************************************************************************/
2032 /* Function: Signal to a computed label target */
2033 /******************************************************************************/
2034 {
2035  RexxInstruction *target = OREF_NULL; /* no target yet */
2036  RexxDirectory *labels = this->getLabels(); /* get the labels */
2037  if (labels != OREF_NULL) /* have labels? */
2038  {
2039  /* look up label and go to normal */
2040  /* signal processing */
2041  target = (RexxInstruction *)labels->at(name);
2042  }
2043  if (target == OREF_NULL) /* unknown label? */
2044  {
2045  /* raise an error */
2047  }
2048  this->signalTo(target); /* now switch to the label location */
2049 }
2050 
2051 
2053 /******************************************************************************/
2054 /* Function: Turn on the activations guarded state */
2055 /******************************************************************************/
2056 {
2057  /* currently in unguarded state? */
2058  if (this->object_scope == SCOPE_RELEASED)
2059  {
2060  /* not retrieved yet? */
2061  if (this->settings.object_variables == OREF_NULL)
2062  {
2063  /* get the object variables */
2065  }
2066  /* lock the variable dictionary */
2067  this->settings.object_variables->reserve(this->activity);
2068  /* set the state here also */
2069  this->object_scope = SCOPE_RESERVED;
2070  }
2071 }
2072 
2074 /******************************************************************************/
2075 /* Function: Return the current digits setting */
2076 /******************************************************************************/
2077 {
2078  return this->settings.numericSettings.digits;
2079 }
2080 
2082 /******************************************************************************/
2083 /* Function: Return the current fuzz setting */
2084 /******************************************************************************/
2085 {
2086  return this->settings.numericSettings.fuzz;
2087 }
2088 
2090 /******************************************************************************/
2091 /* Function: Return the current FORM setting */
2092 /******************************************************************************/
2093 {
2094  return this->settings.numericSettings.form;
2095 }
2096 
2098 /******************************************************************************/
2099 /* Function: Return the current numeric propagation setting */
2100 /******************************************************************************/
2101 {
2102  return this->settings.propagateNumericSettings;
2103 }
2104 
2106 /******************************************************************************/
2107 /* Function: Return the current COMMANDS setting */
2108 /******************************************************************************/
2109 {
2110  return this->settings.enableCommands;
2111 }
2112 
2114 /******************************************************************************/
2115 /* Function: Return the current MACROSPACE setting */
2116 /******************************************************************************/
2117 {
2118  return this->settings.enableMacrospace;
2119 }
2120 
2121 /**
2122  * Set the digits setting to the package-defined default
2123  */
2125 {
2127 }
2128 
2129 void RexxActivation::setDigits(size_t digitsVal)
2130 /******************************************************************************/
2131 /* Function: Set a new digits setting */
2132 /******************************************************************************/
2133 {
2134  this->settings.numericSettings.digits = digitsVal;
2135  if (isInterpret()) parent->setDigits(digitsVal);
2136 }
2137 
2138 /**
2139  * Set the fuzz setting to the package-defined default
2140  */
2142 {
2144 }
2145 
2146 
2147 
2148 void RexxActivation::setFuzz(size_t fuzzVal)
2149 /******************************************************************************/
2150 /* Function: Set a new FUZZ setting */
2151 /******************************************************************************/
2152 {
2153  this->settings.numericSettings.fuzz = fuzzVal;
2154  if (isInterpret()) parent->setFuzz(fuzzVal);
2155 }
2156 
2157 /**
2158  * Set the form setting to the package-defined default
2159  */
2161 {
2163 }
2164 
2165 
2166 
2167 void RexxActivation::setForm(bool formVal)
2168 /******************************************************************************/
2169 /* Function: Set the new current NUMERIC FORM setting */
2170 /******************************************************************************/
2171 {
2172  this->settings.numericSettings.form = formVal;
2173  if (isInterpret()) parent->setForm(formVal);
2174 }
2175 
2176 
2178 /******************************************************************************/
2179 /* Function: Set the new current numeric propagation setting */
2180 /******************************************************************************/
2181 {
2182  this->settings.propagateNumericSettings = status;
2184 }
2185 
2186 
2188 /******************************************************************************/
2189 /* Function: Set the new current COMMANDS setting */
2190 /******************************************************************************/
2191 {
2192  this->settings.enableCommands = status;
2193 }
2194 
2196 /******************************************************************************/
2197 /* Function: Set the new current MACROSPACE setting */
2198 /******************************************************************************/
2199 {
2200  this->settings.enableMacrospace = status;
2201 }
2202 
2203 
2204 /**
2205  * Return the Rexx context this operates under. Depending on the
2206  * context, this could be null.
2207  *
2208  * @return The parent Rexx context.
2209  */
2211 {
2212  return this; // I am my own grampa...I mean Rexx context.
2213 }
2214 
2215 
2216 /**
2217  * Return the Rexx context this operates under. Depending on the
2218  * context, this could be null.
2219  *
2220  * @return The parent Rexx context.
2221  */
2223 {
2224  return this; // I am my own grampa...I mean Rexx context.
2225 }
2226 
2227 
2228 /**
2229  * Indicate whether this activation is a Rexx context or not.
2230  *
2231  * @return true if this is a Rexx context, false otherwise.
2232  */
2234 {
2235  return true;
2236 }
2237 
2238 
2239 /**
2240  * Get the numeric settings for the current context.
2241  *
2242  * @return The new numeric settings.
2243  */
2245 {
2246  return &(this->settings.numericSettings);
2247 }
2248 
2249 
2250 /**
2251  * Get the message receiver
2252  *
2253  * @return The message receiver. Returns OREF_NULL if this is not
2254  * a message activation.
2255  */
2257 {
2258  if (this->isInterpret())
2259  {
2260  return parent->getReceiver();
2261  }
2262  return receiver;
2263 }
2264 
2265 
2267  RexxString * condition) /* condition trapped */
2268 /******************************************************************************/
2269 /* Function: Return the current state for a trap as either ON, OFF, or DELAY */
2270 /******************************************************************************/
2271 {
2272  RexxString *state = OREF_OFF; /* default to OFF state */
2273  /* actually have any traps? */
2274  if (this->settings.traps != OREF_NULL)
2275  {
2276  /* see if this trap is enabled */
2277  RexxArray *traphandler = (RexxArray *)this->settings.traps->at(condition);
2278  if (traphandler != OREF_NULL) /* have a trap for this? */
2279  {
2280  /* get the trap state */
2281  state = (RexxString *)traphandler->get(2);
2282  }
2283  }
2284  return state; /* return this state */
2285 }
2286 
2287 
2289  RexxString * condition) /* condition trapped */
2290 /******************************************************************************/
2291 /* Function: Put a condition trap into the delay state. */
2292 /******************************************************************************/
2293 {
2294  this->checkTrapTable(); /* make sure we've got the tables */
2295  /* see if this one is enabled */
2296  RexxArray *traphandler = (RexxArray *)this->settings.traps->at(condition);
2297  if (traphandler != OREF_NULL) /* have a trap for this? */
2298  {
2299  traphandler->put(OREF_DELAY, 2); /* change the trap state */
2300  }
2301 }
2302 
2303 
2305  RexxString * condition) /* condition trapped */
2306 /******************************************************************************/
2307 /* Function: Remove a trap from the DELAY state */
2308 /******************************************************************************/
2309 {
2310  this->checkTrapTable(); /* make sure we've got the tables */
2311  /* see if this one is enabled */
2312  RexxArray *traphandler = (RexxArray *)this->settings.traps->at(condition);
2313  if (traphandler != OREF_NULL) /* have a trap for this? */
2314  {
2315  traphandler->put(OREF_ON, 2); /* change the trap state */
2316  }
2317 }
2318 
2319 
2320 bool RexxActivation::trap( /* trap a condition */
2321  RexxString * condition, /* condition to process */
2322  RexxDirectory * exception_object) /* associated condition object */
2323 /******************************************************************************/
2324 /* Function: Check the activation to see if this is trapping a condition. */
2325 /* For SIGNAL traps, control goes back to the point of the trap */
2326 /* via throw. For CALL ON traps, the condition is saved, and */
2327 /* the method returns true to indicate the trap was handled. */
2328 /******************************************************************************/
2329 {
2330  if (this->settings.flags&forwarded)
2331  {/* in the act of forwarding? */
2332  RexxActivationBase *activation = this->getPreviousStackFrame(); /* get the sender activation */
2333  /* have a predecessor? */
2334  while (activation != OREF_NULL && isOfClass(Activation, activation))
2335  {
2336  if (!activation->isForwarded()) /* non forwarded? */
2337  {
2338  /* pretend he is we */
2339  return activation->trap(condition, exception_object);
2340  }
2341  activation = activation->getPreviousStackFrame(); /* step to the next one */
2342  }
2343  return false; /* not really here, can't handle */
2344  }
2345  /* do we need to notify a message */
2346  /*obj? */
2347  if (this->objnotify != OREF_NULL && condition->strCompare(CHAR_SYNTAX))
2348  {
2349  /* yes, send error message and */
2350  /*condition object */
2351  this->objnotify->error(exception_object);
2352  }
2353  bool handled = false; /* not handled yet */
2354  RexxArray *traphandler = OREF_NULL; /* no traps to process yet */
2355  if (this->debug_pause)
2356  { /* working from the debug prompt? */
2357  /* non-terminal condition? */
2358  if (!condition->strCompare(CHAR_SYNTAX))
2359  {
2360  return false; /* flag as not-handled */
2361  }
2362  /* go display the messages */
2363  this->activity->displayDebug(exception_object);
2364  throw this; /* unwind and process the trap */
2365  }
2366  /* no trap table yet? */
2367  if (this->settings.traps == OREF_NULL)
2368  {
2369  return false; /* can't very well handle this! */
2370  }
2371  /* see if this one is enabled */
2372  traphandler = (RexxArray *)this->settings.traps->at(condition);
2373 
2374  if (traphandler == OREF_NULL)
2375  { /* not there? try for an ANY handler*/
2376  /* get this from the same table */
2377  traphandler = (RexxArray *)this->settings.traps->at(OREF_ANY);
2378  if (traphandler != OREF_NULL)
2379  { /* have an any handler? */
2380  /* get the handler info */
2381  RexxInstructionCallBase *handler = (RexxInstructionCallBase *)traphandler->get(1);
2382  /* condition not trappable with CALL?*/
2383  if (handler->isType(KEYWORD_CALL) &&
2384  (condition->strCompare(CHAR_SYNTAX) ||
2385  condition->strCompare(CHAR_NOVALUE) ||
2386  condition->strCompare(CHAR_LOSTDIGITS) ||
2387  condition->strCompare(CHAR_NOMETHOD) ||
2388  condition->strCompare(CHAR_NOSTRING)))
2389  {
2390  return false; /* not trapped */
2391  }
2392  }
2393  }
2394  /* if the condition is being trapped, do the CALL or SIGNAL */
2395  if (traphandler != OREF_NULL)
2396  { /* have a trap for this? */
2397  /* if this is a HALT */
2398  if (condition->strCompare(CHAR_HALT))
2399  {
2400  /* call the sys exit to clear it */
2401  this->activity->callHaltClearExit(this);
2402  }
2403  /* get the handler info */
2404  RexxInstructionCallBase *handler = (RexxInstructionCallBase *)traphandler->get(1);
2405  /* no condition queue yet? */
2406  if (this->condition_queue == OREF_NULL)
2407  {
2408  /* create a pending queue */
2409  this->condition_queue = new_queue();
2410  /* and a handler queue */
2411  this->handler_queue = new_queue();
2412  }
2413 
2414  RexxString *instruction = OREF_CALL;
2415  if (handler->isType(KEYWORD_SIGNAL))
2416  {
2417  instruction = OREF_SIGNAL; /* this is trapped by a SIGNAL */
2418  }
2419  /* add the instruction trap info */
2420  exception_object->put(instruction, OREF_INSTRUCTION);
2421  /* create a new condition object and */
2422  /* add the condition object to queue */
2423  this->condition_queue->addLast(exception_object);
2424  /* and the corresponding trap info */
2425  this->handler_queue->addLast(traphandler);
2426  this->pending_count++; /* bump pending condition count */
2427  // clear this from the activity if we're trapping this here
2429  /* is this a signal instruction */
2430  /* no the non-returnable PROPAGATE? */
2431  if (handler->isType(KEYWORD_SIGNAL))
2432  {
2433  /* not an Interpret instruction? */
2434  if (!this->isInterpret())
2435  {
2436  throw this; /* unwind and process the trap */
2437  }
2438  else
2439  { /* unwind interpret activations */
2440  /* merge the traps */
2441  this->parent->mergeTraps(this->condition_queue, this->handler_queue);
2442  this->parent->unwindTrap(this);/* go unwind this */
2443  }
2444  }
2445  else
2446  {
2447  handled = true; /* tell caller we're processing later*/
2448  /* tell clause boundary to process */
2449  this->settings.flags |= clause_boundary;
2450  }
2451  }
2452  return handled; /* let call know if we've handled */
2453 }
2454 
2455 
2456 /**
2457  * Process a NOVALUE event for a variable.
2458  *
2459  * @param name The variable name triggering the event.
2460  * @param variable The resolved variable object for the variable.
2461  *
2462  * @return A value for that variable.
2463  */
2465 {
2466  RexxObject *value = this->novalueHandler(name);
2467  // If the handler returns anything other than .nil, this is a
2468  // value
2469  // JLF : Make it more robust: test also OREF_NULL (value returned when nothing returned by the handler)
2470  if (value != OREF_NULL && value != TheNilObject)
2471  {
2472  return value;
2473  }
2474  // give any external novalue handler a chance at this
2475  if (!activity->callNovalueExit(this, name, value))
2476  {
2477  // set this variable to the object found in the engine
2478  variable->set(value);
2479  return value;
2480  }
2481  // raise novalue?
2482  if (novalueEnabled())
2483  {
2484  reportNovalue(name);
2485  }
2486 
2487  // the provided default value is the returned value
2488  return defaultValue;
2489 }
2490 
2491 
2492 
2494  RexxQueue * source_condition_queue, /* previous condition queue */
2495  RexxQueue * source_handler_queue ) /* current condition handlers queue */
2496 /******************************************************************************/
2497 /* Function: Merge a list of trapped conditions from an interpret into the */
2498 /* parent activation's queues. */
2499 /******************************************************************************/
2500 {
2501  if (source_condition_queue != OREF_NULL)
2502  {
2503  /* no condition queue yet? */
2504  if (this->condition_queue == OREF_NULL)
2505  {
2506  /* just copy over */
2507  this->condition_queue = source_condition_queue;
2508  /* ...both queues */
2509  this->handler_queue = source_handler_queue;
2510  }
2511  else
2512  {
2513  /* get the item count */
2514  size_t items = source_condition_queue->getSize();
2515  while (items--)
2516  {
2517  /* add to the end of the queue */
2518  this->handler_queue->addLast(source_handler_queue->pullRexx());
2519  /* move condition object to the end */
2520  this->condition_queue->addLast(source_condition_queue->pullRexx());
2521  }
2522  }
2523  /* reset the counter size */
2524  this->pending_count = this->condition_queue->getSize();
2525  }
2526 }
2527 
2528 
2530 /******************************************************************************/
2531 /* Function: Unwind a chain of interpret activations to process a SIGNAL ON */
2532 /* or PROPAGATE condition trap. This ensures that the SIGNAL */
2533 /* or PROPAGATE returns to the correct condition level */
2534 /******************************************************************************/
2535 {
2536  /* still an interpret level? */
2537  if (this->isInterpret())
2538  {
2539  /* merge the traps */
2540  this->parent->mergeTraps(this->condition_queue, this->handler_queue);
2541  this->parent->unwindTrap(child); /* unwind another level */
2542  }
2543  else /* reached the "parent" level */
2544  {
2545  /* pull back the settings */
2546  child->putSettings(this->settings);
2547  throw this; /* unwind and process the trap */
2548  }
2549 }
2550 
2551 
2553 /******************************************************************************/
2554 /* Function: Retrieve the activation that activated this activation (whew) */
2555 /******************************************************************************/
2556 {
2557  /* get the sender from the activity */
2558  RexxActivationBase *_sender = this->getPreviousStackFrame();
2559  /* spin down to non-native activation*/
2560  while (_sender != OREF_NULL && isOfClass(NativeActivation, _sender))
2561  {
2562  _sender = _sender->getPreviousStackFrame();
2563  }
2564  return(RexxActivation *)_sender; /* return that activation */
2565 }
2566 
2568 /******************************************************************************/
2569 /* Function: Translate and interpret a string of data as a piece of REXX */
2570 /* code within the current program context. */
2571 /******************************************************************************/
2572 {
2573  ActivityManager::currentActivity->checkStackSpace(); /* have enough stack space? */
2574  /* translate the code */
2575  RexxCode * newCode = this->code->interpret(codestring, this->current->getLineNumber(), this);
2576  /* create a new activation */
2577  RexxActivation *newActivation = ActivityManager::newActivation(this->activity, this, newCode, INTERPRET);
2578  this->activity->pushStackFrame(newActivation); /* push on the activity stack */
2579  ProtectedObject r;
2580  /* run the internal routine on the */
2581  /* new activation */
2583 }
2584 
2585 
2586 void RexxActivation::debugInterpret( /* interpret interactive debug input */
2587  RexxString * codestring) /* entered instruction */
2588 /******************************************************************************/
2589 /* Function: Interpret a string created for interactive debug */
2590 /******************************************************************************/
2591 {
2592  this->debug_pause = true; /* now in debug pause */
2593  try
2594  {
2595  /* translate the code */
2596  RexxCode *newCode = this->code->interpret(codestring, this->current->getLineNumber(), this);
2597  /* create a new activation */
2598  RexxActivation *newActivation = ActivityManager::newActivation(this->activity, this, newCode, DEBUGPAUSE);
2599  this->activity->pushStackFrame(newActivation); /* push on the activity stack */
2600  ProtectedObject r;
2601  /* run the internal routine on the */
2602  /* new activation */
2604  // turn this off when done executing
2605  this->debug_pause = false;
2606  }
2607  catch (RexxActivation *t)
2608  {
2609  // turn this off unconditionally for any errors
2610  // if we're not the target of this throw, we've already been unwound
2611  // keep throwing this until it reaches the target activation.
2612  if (t != this )
2613  {
2614  throw;
2615  }
2616  }
2617 }
2618 
2619 RexxObject * RexxActivation::rexxVariable( /* retrieve a program entry */
2620  RexxString * name ) /* target program entry name */
2621 /******************************************************************************/
2622 /* Function: Retrieve a REXX defined "dot" environment variable */
2623 /******************************************************************************/
2624 {
2625  if (name->strCompare(CHAR_METHODS)) /* is this ".methods" */
2626  {
2627  /* get the methods directory */
2628  return(RexxObject *)this->settings.parent_code->getMethods();
2629  }
2630  else if (name->strCompare(CHAR_ROUTINES)) /* is this ".routines" */
2631  {
2632  /* get the methods directory */
2633  return(RexxObject *)this->settings.parent_code->getRoutines();
2634  }
2635  else if (name->strCompare(CHAR_RS)) /* command return status (".rs")? */
2636  {
2637  if (this->settings.flags&return_status_set)
2638  {
2639  /* returned as an integer object */
2640  return new_integer(this->settings.return_status);
2641  }
2642  else /* just return the name */
2643  {
2644  return name->concatToCstring(".");
2645  }
2646  }
2647  else if (name->strCompare(CHAR_LINE)) /* current line (".line")? */
2648  {
2649  // if this is an interpret, we need to report the line number of
2650  // the context that calls the interpret.
2651  if (this->isInterpret())
2652  {
2653  return parent->rexxVariable(name);
2654  }
2655  else
2656  {
2657 
2658  return new_integer(this->current->getLineNumber());
2659  }
2660  }
2661  else if (name->strCompare(CHAR_CONTEXT)) /* current execution context (".context")? */
2662  {
2663  // if this is an interpret, we need to report the line number of
2664  // the context that calls the interpret.
2665  if (this->isInterpret())
2666  {
2667  return parent->rexxVariable(name);
2668  }
2669  else
2670  {
2671  // retrieve the context object (potentially creating it on the first request)
2672  return getContextObject();
2673  }
2674  }
2675  else if (name->strCompare(CHAR_THREADLOCAL)) /* current thread variables */
2676  {
2677  return this->getThreadLocal();
2678  }
2679 #if 1 // Monitoring (temporary)
2680  else if (name->strCompare("YIELDCOUNTER"))
2681  {
2683  }
2684  else if (name->strCompare("ADDWAITINGACTIVITYCOUNTER"))
2685  {
2687  }
2688  else if (name->strCompare("RELINQUISHCOUNTER"))
2689  {
2691  }
2692  else if (name->strCompare("REQUESTACCESSCOUNTER"))
2693  {
2695  }
2696  else if (name->strCompare("GETAPIMANAGERCOUNTER"))
2697  {
2699  }
2700 #endif
2701  return OREF_NULL; // not recognized
2702 }
2703 
2704 
2705 /**
2706  * Get the context object for this activation.
2707  *
2708  * @return The created context object.
2709  */
2711 {
2712  // the context object is created on demand...much of the time, this
2713  // is not needed for an actvation
2714  if (contextObject == OREF_NULL)
2715  {
2716  contextObject = new RexxContext(this);
2717  }
2718  return contextObject;
2719 }
2720 
2721 
2722 /**
2723  * Return the line context information for a context.
2724  *
2725  * @return The current execution line.
2726  */
2728 {
2729  // if this is an interpret, we need to report the line number of
2730  // the context that calls the interpret.
2731  if (this->isInterpret())
2732  {
2733  return parent->getContextLine();
2734  }
2735  else
2736  {
2737 
2738  return new_integer(this->current->getLineNumber());
2739  }
2740 }
2741 
2742 
2743 /**
2744  * Return the line context information for a context.
2745  *
2746  * @return The current execution line.
2747  */
2749 {
2750  // if this is an interpret, we need to report the line number of
2751  // the context that calls the interpret.
2752  if (this->isInterpret())
2753  {
2754  return parent->getContextLineNumber();
2755  }
2756  else
2757  {
2758 
2759  return this->current->getLineNumber();
2760  }
2761 }
2762 
2763 
2764 /**
2765  * Return the RS context information for a activation.
2766  *
2767  * @return The current execution line.
2768  */
2770 {
2771  if (this->settings.flags&return_status_set)
2772  {
2773  /* returned as an integer object */
2774  return new_integer(this->settings.return_status);
2775  }
2776  else
2777  {
2778  return TheNilObject;
2779  }
2780 }
2781 
2782 
2783 /**
2784  * Get the context object for the parent of this activation.
2785  *
2786  * @return The created context object.
2787  */
2789 {
2790  RexxActivation *parentActivation = this->senderActivation();
2791  if (parentActivation == OREF_NULL) return TheNilObject;
2792  return parentActivation->getContextObject();
2793 }
2794 
2795 
2796 /**
2797  * Attempt to call a function stored in the macrospace.
2798  *
2799  * @param target The target function name.
2800  * @param arguments The argument pointer.
2801  * @param argcount The count of positional arguments,
2802  * @param calltype The type of call (FUNCTION or SUBROUTINE)
2803  * @param order The macrospace order flag.
2804  * @param result The function result.
2805  *
2806  * @return true if the macrospace function was located and called.
2807  */
2809  size_t _argcount, size_t _named_argcount, RexxString * calltype, int order, ProtectedObject &_result)
2810 {
2811  if (this->enableMacrospace())
2812  {
2813  unsigned short position; /* located macro search position */
2814  const char *macroName = target->getStringData(); /* point to the string data */
2815  /* did we find this one? */
2816  if (RexxQueryMacro(macroName, &position) == 0)
2817  {
2818  /* but not at the right time? */
2819  if (order == MS_PREORDER && position == RXMACRO_SEARCH_AFTER)
2820  {
2821  return false; /* didn't really find this */
2822  }
2823  /* unflatten the method now */
2824  RoutineClass *routine = getMacroCode(target);
2825  // not restoreable is a call failure
2826  if (routine == OREF_NULL)
2827  {
2828  return false;
2829  }
2830  /* run as a call */
2831  routine->call(activity, target, _arguments, _argcount, _named_argcount, calltype, OREF_NULL, EXTERNALCALL, _result);
2832  // merge (class) definitions from macro with current settings
2834  return true; /* return success we found it flag */
2835  }
2836  }
2837  return false; /* nope, nothing to find here */
2838 }
2839 
2840 
2841 /**
2842  * Main method for performing an external routine call. This
2843  * orchestrates the search order for locating an external routine.
2844  *
2845  * @param target The target function name.
2846  * @param _argcount The count of positional arguments for the call.
2847  * @param _stack The expression stack holding the arguments.
2848  * @param calltype The type of call (FUNCTION or SUBROUTINE)
2849  * @param resultObj The returned result.
2850  *
2851  * @return The function result (also returned in the resultObj protected
2852  * object reference.
2853  */
2854 RexxObject *RexxActivation::externalCall(RexxString *target, RexxObject **_arguments, size_t _argcount,
2855  size_t _named_argcount, RexxString *calltype, ProtectedObject &resultObj)
2856 {
2857  // Step 1: Check the global functions directory
2858  // this is actually considered part of the built-in functions, but these are
2859  // written in ooRexx. The names are also case sensitive
2860  RoutineClass *routine = (RoutineClass *)TheFunctionsDirectory->get(target);
2861  if (routine != OREF_NULL) /* not found yet? */
2862  {
2863  // call and return the result
2864  routine->call(this->activity, target, _arguments, _argcount, _named_argcount, calltype, OREF_NULL, EXTERNALCALL, resultObj);
2865  return(RexxObject *)resultObj;
2866  }
2867 
2868  // Step 2: Check for a ::ROUTINE definition in the local context
2869  routine = this->settings.parent_code->findRoutine(target);
2870  if (routine != OREF_NULL)
2871  {
2872  // call and return the result
2873  routine->call(this->activity, target, _arguments, _argcount, _named_argcount, calltype, OREF_NULL, EXTERNALCALL, resultObj);
2874  return(RexxObject *)resultObj;
2875  }
2876  // Step 2a: See if the function call exit fields this one
2877  if (!activity->callObjectFunctionExit(this, target, calltype, resultObj, _arguments, _argcount, _named_argcount))
2878  {
2879  return(RexxObject *)resultObj;
2880  }
2881 
2882  // Step 2b: See if the function call exit fields this one
2883  if (!activity->callFunctionExit(this, target, calltype, resultObj, _arguments, _argcount))
2884  {
2885  return(RexxObject *)resultObj;
2886  }
2887 
2888  // Step 3: Perform all platform-specific searches
2889  if (SystemInterpreter::invokeExternalFunction(this, this->activity, target, _arguments, _argcount, _named_argcount, calltype, resultObj))
2890  {
2891  return(RexxObject *)resultObj;
2892  }
2893 
2894  // Step 4: Check scripting exit, which is after most of the checks
2895  if (!activity->callScriptingExit(this, target, calltype, resultObj, _arguments, _argcount))
2896  {
2897  return(RexxObject *)resultObj;
2898  }
2899 
2900  // if it's made it through all of these steps without finding anything, we
2901  // finally have a routine non found situation
2903  return OREF_NULL; // prevent compile error
2904 }
2905 
2906 
2907 
2908 
2909 /**
2910  * Call an external program as a function or subroutine.
2911  *
2912  * @param target The target function name.
2913  * @param parent The name of the parent program (used for resolving extensions).
2914  * @param _arguments The arguments to the call.
2915  * @param _argcount The count of positional arguments for the call.
2916  * @param calltype The type of call (FUNCTION or SUBROUTINE)
2917  * @param resultObj The returned result.
2918  *
2919  * @return True if an external program was located and called. false for
2920  * any failures.
2921  */
2923  RexxString * target, /* Name of external function */
2924  RexxObject ** _arguments, /* Argument array */
2925  size_t _argcount, /* number of positional arguments in the call */
2926  size_t _named_argcount,
2927  RexxString * calltype, /* Type of call */
2928  ProtectedObject &resultObj) /* Result of function call */
2929 /******************************************************************************/
2930 /* Function: Call a rexx protram as an external routine */
2931 /******************************************************************************/
2932 {
2933  /* Get full name including path */
2934  RexxString *filename = resolveProgramName(target);
2935  if (filename != OREF_NULL) /* found something? */
2936  {
2937  this->stack.push(filename); /* protect the file name here */
2938  // try for a saved program or translate anew.
2939  RoutineClass *routine = RoutineClass::fromFile(filename);
2940  this->stack.pop(); /* remove the protected name */
2941  if (routine == OREF_NULL) /* Do we have a method??? */
2942  {
2943  return false; /* No, return not found */
2944  }
2945  else /* Try to run method */
2946  {
2947  ProtectedObject p(routine);
2948  /* run as a call */
2949  routine->call(this->activity, target, _arguments, _argcount, _named_argcount, calltype, this->settings.current_env, EXTERNALCALL, resultObj);
2950  /* now merge all of the public info */
2952  return true; /* Return routine found flag */
2953  }
2954  }
2955  else
2956  {
2957  return false; /* this wasn't found */
2958  }
2959 }
2960 
2961 
2962 /**
2963  * Retrieve a macro image file from the macro space.
2964  *
2965  * @param macroName The name of the macro to retrieve.
2966  *
2967  * @return If available, the unflattened method image.
2968  */
2970 {
2971  RXSTRING macroImage;
2972  RoutineClass * macroRoutine = OREF_NULL;
2973 
2974  macroImage.strptr = NULL;
2975  const char *name = macroName->getStringData();
2976  int rc;
2977  {
2978  UnsafeBlock releaser;
2979 
2980  rc = RexxResolveMacroFunction(name, &macroImage);
2981  }
2982 
2983  if (rc == 0)
2984  {
2985  macroRoutine = RoutineClass::restore(&macroImage, macroName);
2986  // return the allocated buffer
2987  if (macroImage.strptr != NULL)
2988  {
2990  }
2991  }
2992  return macroRoutine;
2993 }
2994 
2995 
2996 /**
2997  * This is resolved in the context of the calling program.
2998  *
2999  * @param name The name to resolve.
3000  *
3001  * @return The fully resolved program name, or OREF_NULL if this can't be
3002  * located.
3003  */
3005 {
3006  return code->resolveProgramName(activity, name);
3007 }
3008 
3009 
3010 /**
3011  * Resolve a class in this activation's context.
3012  *
3013  * @param name The name to resolve.
3014  *
3015  * @return The resolved class, or OREF_NULL if not found.
3016  */
3018 {
3019  RexxClass *classObject = getSourceObject()->findClass(name);
3020  // we need to filter this to always return a class object
3021  if (classObject != OREF_NULL && classObject->isInstanceOf(TheClassClass))
3022  {
3023  return classObject;
3024  }
3025  return OREF_NULL;
3026 }
3027 
3028 
3029 /**
3030  * Resolve a class in this activation's context.
3031  *
3032  * @param name The name to resolve.
3033  *
3034  * @return The resolved class, or OREF_NULL if not found.
3035  */
3037 {
3038  // if not an interpret, then resolve directly.
3040  {
3041  return getSourceObject()->findClass(name);
3042  }
3043  else
3044  {
3045  // otherwise, send this up the call chain and resolve in the
3046  // original source context
3047  return parent->resolveDotVariable(name);
3048  }
3049 }
3050 
3051 
3052 /**
3053  * Load a ::REQUIRES directive when the source file is first
3054  * invoked.
3055  *
3056  * @param target The name of the ::REQUIRES
3057  * @param instruction
3058  * The directive instruction being processed.
3059  */
3061 {
3062  // this will cause the correct location to be used for error reporting
3063  this->current = instruction;
3064 
3065  // the loading/merging is done by the source object
3066  return getSourceObject()->loadRequires(activity, target);
3067 }
3068 
3069 
3070 /**
3071  * Load a package defined by a ::REQUIRES name LIBRARY
3072  * directive.
3073  *
3074  * @param target The name of the package.
3075  * @param instruction
3076  * The ::REQUIRES directive being loaded.
3077  */
3079 {
3080  // this will cause the correct location to be used for error reporting
3081  this->current = instruction;
3082  // have the package manager resolve the package
3084 }
3085 
3086 
3087 /**
3088  * Process an internal function or subroutine call.
3089  *
3090  * @param name The name of the target label.
3091  * @param target The target instruction where we start executing (this is the label)
3092  * @param _argcount The count of positional arguments
3093  * @param _stack The context stack holding the arguments
3094  * @param returnObject
3095  * A holder for the return value
3096  *
3097  * @return The return value object
3098  */
3100  RexxObject **_arguments, size_t _argcount, size_t _named_argcount, ProtectedObject &returnObject)
3101 {
3102  RexxActivation * newActivation; /* new activation for call */
3103  size_t lineNum; /* line number of the call */
3104 
3105  lineNum = this->current->getLineNumber(); /* get the current line number */
3106  /* initialize the SIGL variable */
3107  this->setLocalVariable(OREF_SIGL, VARIABLE_SIGL, new_integer(lineNum));
3108  /* create a new activation */
3109  newActivation = ActivityManager::newActivation(this->activity, this, this->settings.parent_code, INTERNALCALL);
3110 
3111  this->activity->pushStackFrame(newActivation); /* push on the activity stack */
3112  /* run the internal routine on the */
3113  /* new activation */
3114  return newActivation->run(receiver, name, OREF_NULL, _arguments, _argcount, _named_argcount, target, returnObject);
3115 }
3116 
3117 /**
3118  * Processing a call to an internal trap subroutine.
3119  *
3120  * @param name The label name of the internal call.
3121  * @param target The target instruction for the call (the label)
3122  * @param conditionObj
3123  * The associated condition object
3124  * @param resultObj A holder for a result object
3125  *
3126  * @return Any return result
3127  */
3129  RexxDirectory *conditionObj, ProtectedObject &resultObj)
3130 {
3131 
3132  this->stack.push(conditionObj); /* protect the condition object */
3133  size_t lineNum = this->current->getLineNumber(); /* get the current line number */
3134  /* initialize the SIGL variable */
3135  this->setLocalVariable(OREF_SIGL, VARIABLE_SIGL, new_integer(lineNum));
3136  /* create a new activation */
3138  /* set the new condition object */
3139  newActivation->setConditionObj(conditionObj);
3140  this->activity->pushStackFrame(newActivation); /* push on the activity stack */
3141  /* run the internal routine on the */
3142  /* new activation */
3143  return newActivation->run(OREF_NULL, name, OREF_NULL, NULL, 0, 0, target, resultObj);
3144 }
3145 
3146 
3147 
3149 /******************************************************************************/
3150 /* Function: Wait for a variable in a guard expression to get updated. */
3151 /******************************************************************************/
3152 {
3153  int initial_state = this->object_scope; /* save the initial state */
3154  /* have the scope reserved? */
3155  if (this->object_scope == SCOPE_RESERVED)
3156  {
3157  /* tell the receiver to release this */
3158  this->settings.object_variables->release(this->activity);
3159  /* and change our local state */
3160  this->object_scope = SCOPE_RELEASED; /* do an assignment! */
3161  }
3162  this->activity->guardWait(); /* wait on a variable inform event */
3163  /* did we release the scope? */
3164  if (initial_state == SCOPE_RESERVED)
3165  {
3166  /* tell the receiver to reserve this */
3167  this->settings.object_variables->reserve(this->activity);
3168  /* and change our local state */
3169  this->object_scope = SCOPE_RESERVED; /* do an assignment! */
3170  }
3171 }
3172 
3173 
3174 /**
3175  * Get a traceback line for the current instruction.
3176  *
3177  * @return The formatted string traceback.
3178  */
3180 {
3181  return formatTrace(this->current, getSourceObject());
3182 }
3183 
3184 
3186 /******************************************************************************/
3187 /* Function: Retrieve the current activation timestamp, retrieving a new */
3188 /* timestamp if this is the first call for a clause */
3189 /******************************************************************************/
3190 {
3191  /* not a valid time stamp? */
3192  if (!this->settings.timestamp.valid)
3193  {
3194  // IMPORTANT: If a time call resets the elapsed time clock, we don't
3195  // clear the value out. The time needs to stay valid until the clause is
3196  // complete. The time stamp value that needs to be used for the next
3197  // elapsed time call is the timstamp that was valid at the point of the
3198  // last call, which is our current old invalid one. So, we need to grab
3199  // that value and set the elapsed time start point, then clear the flag
3200  // so that it will remain current.
3201  if (isElapsedTimerReset())
3202  {
3205  }
3206  /* get a fresh time stamp */
3208  /* got a new one */
3209  this->settings.timestamp.valid = true;
3210  }
3211  /* return the current time */
3212  return this->settings.timestamp;
3213 }
3214 
3215 
3217 /******************************************************************************/
3218 /* Function: Retrieve the current elapsed time counter start time, starting */
3219 /* the counter from the current time stamp if this is the first */
3220 /* call */
3221 /******************************************************************************/
3222 {
3223  // no active elapsed time clock yet?
3224  if (this->settings.elapsed_time == 0)
3225  {
3226 
3228  }
3229  return settings.elapsed_time;
3230 }
3231 
3232 
3233 void RexxActivation::resetElapsed() /* reset activation elapsed time */
3234 /******************************************************************************/
3235 /* Function: Retrieve the current elapsed time counter start time, starting */
3236 /* the counter from the current time stamp if this is the first */
3237 /* call */
3238 /******************************************************************************/
3239 {
3240  // Just invalidate the flat so that we'll refresh this the next time we
3241  // obtain a new timestamp value.
3243 }
3244 
3245 
3246 #define DEFAULT_MIN 0 /* default random minimum value */
3247 #define DEFAULT_MAX 999 /* default random maximum value */
3248 #define MAX_DIFFERENCE 999999999 /* max spread between min and max */
3249 
3250 
3252 {
3253  /* currently in an internal routine */
3254  /* or interpret instruction? */
3255  if (this->isInternalLevelCall())
3256  {
3257  /* forward along */
3258  return this->parent->getRandomSeed(seed);
3259  }
3260  /* have a seed supplied? */
3261  if (seed != OREF_NULL)
3262  {
3263  wholenumber_t seed_value = seed->getValue(); /* get the value */
3264  if (seed_value < 0) /* negative value? */
3265  {
3266  /* got an error */
3267  reportException(Error_Incorrect_call_nonnegative, CHAR_RANDOM, OREF_positional, IntegerThree, seed);
3268  }
3269  /* set the saved seed value */
3270  this->random_seed = seed_value;
3271  /* flip all of the bits */
3272  this->random_seed = ~this->random_seed;
3273  /* randomize the seed number a bit */
3274  for (size_t i = 0; i < 13; i++)
3275  {
3276  /* scramble the seed a bit */
3277  this->random_seed = RANDOMIZE(this->random_seed);
3278  }
3279  }
3280  /* step the randomization */
3281  this->random_seed = RANDOMIZE(this->random_seed);
3282  /* set the seed at the activity level*/
3283  this->activity->setRandomSeed(this->random_seed);
3284  return this->random_seed; /* return the seed value */
3285 }
3286 
3287 
3289  RexxInteger * randmin, /* RANDOM minimum range */
3290  RexxInteger * randmax, /* RANDOM maximum range */
3291  RexxInteger * randseed ) /* RANDOM seed */
3292 /******************************************************************************/
3293 /* Function: Process the random function, using the current activation */
3294 /* seed value. */
3295 /******************************************************************************/
3296 {
3297  size_t i; /* loop counter */
3298 
3299  /* go get the seed value */
3300  uint64_t seed = this->getRandomSeed(randseed);
3301 
3302  wholenumber_t minimum = DEFAULT_MIN; /* get the default MIN value */
3303  wholenumber_t maximum = DEFAULT_MAX; /* get the default MAX value */
3304  /* minimum specified? */
3305  if (randmin != OREF_NULL)
3306  {
3307  /* no maximum value specified */
3308  /* and no seed specified */
3309  if ((randmax == OREF_NULL) && (randseed == OREF_NULL))
3310  {
3311  maximum = randmin->getValue(); /* this is actually a max value */
3312  }
3313  /* minimum value specified */
3314  /* maximum value not specified */
3315  /* seed specified */
3316  else if ((randmin != OREF_NULL) && (randmax == OREF_NULL) && (randseed != OREF_NULL))
3317  {
3318  minimum = randmin->getValue();
3319  }
3320  else
3321  {
3322  minimum = randmin->getValue(); /* give both max and min values */
3323  maximum = randmax->getValue();
3324  }
3325  }
3326  else if (randmax != OREF_NULL) /* only given a maximum? */
3327  {
3328  maximum = randmax->getValue(); /* use the supplied maximum */
3329  }
3330 
3331  if (maximum < minimum) /* range problem? */
3332  {
3333  /* this is an error */
3334  reportException(Error_Incorrect_call_random, randmin, randmax);
3335  }
3336  /* too big of a spread ? */
3337  if (maximum - minimum > MAX_DIFFERENCE)
3338  {
3339  /* this is an error */
3341  }
3342 
3343  /* have real work to do? */
3344  if (minimum != maximum)
3345  {
3346  // this will invert the bits of the value
3347  uint64_t work = 0; /* start with zero */
3348  for (i = 0; i < sizeof(uint64_t) * 8; i++)
3349  {
3350  work <<= 1; /* shift working num left one */
3351  /* add in next seed bit value */
3352  work = work | (seed & 0x01LL);
3353  seed >>= 1; /* shift off the right most seed bit */
3354  }
3355  /* adjust for requested range */
3356  minimum += (wholenumber_t)(work % (uint64_t)(maximum - minimum + 1));
3357  }
3358  return new_integer(minimum); /* return the random number */
3359 }
3360 
3361 static const char * trace_prefix_table[] = { /* table of trace prefixes */
3362  "*-*", /* TRACE_PREFIX_CLAUSE */
3363  "+++", /* TRACE_PREFIX_ERROR */
3364  ">>>", /* TRACE_PREFIX_RESULT */
3365  ">.>", /* TRACE_PREFIX_DUMMY */
3366  ">V>", /* TRACE_PREFIX_VARIABLE */
3367  ">E>", /* TRACE_PREFIX_DOTVARIABLE */
3368  ">L>", /* TRACE_PREFIX_LITERAL */
3369  ">F>", /* TRACE_PREFIX_FUNCTION */
3370  ">P>", /* TRACE_PREFIX_PREFIX */
3371  ">O>", /* TRACE_PREFIX_OPERATOR */
3372  ">C>", /* TRACE_PREFIX_COMPOUND */
3373  ">M>", /* TRACE_PREFIX_MESSAGE */
3374  ">A>", /* TRACE_PREFIX_ARGUMENT */
3375  ">=>", /* TRACE_PREFIX_ASSIGNMENT */
3376  ">I>", /* TRACE_PREFIX_INVOCATION */
3377  ">N>", /* TRACE_PREFIX_NAMED_ARGUMENT */
3378 };
3379 
3380  /* extra space required to format a */
3381  /* result line. This overhead is */
3382  /* 6 leading spaces for the line */
3383  /* number, + 1 space + length of the */
3384  /* message prefix (3) + 1 space + */
3385  /* 2 for an indent + 2 for the */
3386  /* quotes surrounding the value */
3387 #define TRACE_OVERHEAD 15
3388  /* overhead for a traced instruction */
3389  /* (6 digit line number, blank, */
3390  /* 3 character prefix, and a blank */
3391 #define INSTRUCTION_OVERHEAD 11
3392 #define LINENUMBER 6 /* size of a line number */
3393 #define PREFIX_OFFSET (LINENUMBER + 1) /* location of the prefix field */
3394 #define PREFIX_LENGTH 3 /* length of the prefix flag */
3395 #define INDENT_SPACING 2 /* spaces per indentation amount */
3396 // over head for adding quotes
3397 #define QUOTES_OVERHEAD 2
3398 
3399 /**
3400  * Trace program entry for a method or routine
3401  */
3403 {
3404  // since we're advertising the entry location up front, we want to disable
3405  // the normal trace-turn on notice. We'll get one or the other, but not
3406  // both
3407  this->settings.flags |= source_traced;
3408 
3409  RexxArray *info = OREF_NULL;
3410 
3411  if (isMethod())
3412  {
3413  RexxString *scopeName = (scope == TheNilObject ? scope->requestString() : scope->getId());
3414  ProtectedObject pscopeName(scopeName);
3415  info = new_array(getMessageName(), scopeName, getPackage()->getName());
3416  }
3417  else
3418  {
3419  info = new_array(getExecutable()->getName(), getPackage()->getName());
3420  }
3421  ProtectedObject p(info);
3422 
3424  p = message;
3425 
3426  /* get a string large enough to */
3427  sizeB_t outBlength = message->getBLength() + INSTRUCTION_OVERHEAD;
3428  RexxString *buffer = raw_string(outBlength); /* get an output string */
3429  /* insert the leading blanks */
3430  buffer->set(0, ' ', INSTRUCTION_OVERHEAD);
3431  /* add the trace prefix */
3433  /* copy the string value */
3434  buffer->put(INSTRUCTION_OVERHEAD, message->getStringData(), message->getBLength());
3435  /* write out the line */
3436  activity->traceOutput(this, buffer);
3437 }
3438 
3439 
3440 void RexxActivation::traceValue( /* trace an intermediate value */
3441  RexxObject * value, /* value to trace */
3442  int prefix ) /* traced result type */
3443 /******************************************************************************/
3444 /* Function: Trace an intermediate value or instruction result value */
3445 /******************************************************************************/
3446 {
3447  /* tracing currently suppressed or */
3448  /* no value was received? */
3449  if (this->settings.flags&trace_suppress || this->debug_pause || value == OREF_NULL)
3450  {
3451  return; /* just ignore this call */
3452  }
3453 
3454  if (!this->code->isTraceable()) /* if we don't have real source */
3455  {
3456  return; /* just ignore for this */
3457  }
3458  /* get the string version */
3459  RexxString *stringvalue = value->stringValue();
3460  /* get a string large enough to */
3461  sizeB_t outlength = stringvalue->getBLength() + TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING;
3462  RexxString *buffer = raw_string(outlength); /* get an output string */
3463  ProtectedObject p(buffer);
3464  /* insert the leading blanks */
3465  buffer->set(0, ' ', TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING);
3466  /* add the trace prefix */
3468  /* add a quotation mark */
3469  buffer->putCharB(TRACE_OVERHEAD - 2 + this->settings.traceindent * INDENT_SPACING, '\"');
3470  /* copy the string value */
3471  buffer->put(TRACE_OVERHEAD - 1 + this->settings.traceindent * INDENT_SPACING, stringvalue->getStringData(), stringvalue->getBLength());
3472  buffer->putCharB(outlength - 1, '\"');/* add the trailing quotation mark */
3473  /* write out the line */
3474  this->activity->traceOutput(this, buffer);
3475 }
3476 
3477 
3478 /**
3479  * Trace an entry that's of the form 'tag => "value"'.
3480  *
3481  * @param prefix The trace prefix tag to use.
3482  * @param tagPrefix Any prefix string added to the tag. Use mostly for adding
3483  * the "." to traced environment variables.
3484  * @param quoteTag Indicates whether the tag should be quoted or not. Operator
3485  * names are quoted.
3486  * @param tag The tag name.
3487  * @param value The associated trace value.
3488  * @param quoteValue Indicates whether the value should be quoted or not.
3489  */
3490 void RexxActivation::traceTaggedValue(int prefix, const char *tagPrefix, bool quoteTag,
3491  RexxString *tag, const char *marker, RexxObject * value, bool quoteValue)
3492 {
3493  // the trace settings would normally require us to trace this, but there are conditions
3494  // where we just skip doing this anyway.
3495  if (this->settings.flags&trace_suppress || this->debug_pause || value == OREF_NULL || !code->isTraceable())
3496  {
3497  return;
3498  }
3499 
3500  // get the string value from the traced object.
3501  RexxString *stringVal = value->stringValue();
3502 
3503  // now calculate the length of the traced string
3504  stringsizeB_t outLength = tag->getBLength() + stringVal->getBLength();
3505  // these are fixed overheads
3506  outLength += TRACE_OVERHEAD + strlen(marker);
3507  // now the indent spacing
3508  outLength += this->settings.traceindent * INDENT_SPACING;
3509  // now other conditionals
3510  outLength += quoteTag ? QUOTES_OVERHEAD : 0;
3511  // this is usually null, but dot variables add a "." to the tag.
3512  outLength += tagPrefix == NULL ? 0 : strlen(tagPrefix);
3513  // jlf: by default, TRACE_OVERHEAD includes 2 for the quotes around the value. Must substract 2 if quotes not displayed.
3514  if (quoteValue == false) outLength -= 2;
3515 
3516  // now get a buffer to write this out into
3517  RexxString *buffer = raw_string(outLength);
3518  ProtectedObject p(buffer);
3519 
3520  // get a cursor for filling in the formatted data
3521  stringsizeB_t dataOffset = TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING - 2;
3522  /* insert the leading blanks */
3523  buffer->set(0, ' ', TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING);
3524  /* add the trace prefix */
3526 
3527  // if this is a quoted tag (operators do this), add quotes before coping the tag
3528  if (quoteTag)
3529  {
3530  buffer->putCharB(dataOffset, '\"');
3531  dataOffset++;
3532  }
3533  // is the tag prefixed? Add this before the name
3534  if (tagPrefix != NULL)
3535  {
3536  stringsize_t prefixLength = strlen(tagPrefix);
3537  buffer->put(dataOffset, tagPrefix, prefixLength);
3538  dataOffset += prefixLength;
3539  }
3540 
3541  // add in the tag name
3542  buffer->put(dataOffset, tag);
3543  dataOffset += tag->getBLength();
3544 
3545  // might need a closing quote.
3546  if (quoteTag)
3547  {
3548  buffer->putCharB(dataOffset, '\"');
3549  dataOffset++;
3550  }
3551 
3552  // now add the data marker
3553  buffer->put(dataOffset, marker, strlen(marker));
3554  dataOffset += strlen(marker);
3555 
3556  // the leading quote around the value
3557  if (quoteValue)
3558  {
3559  buffer->putCharB(dataOffset, '\"');
3560  dataOffset++;
3561  }
3562 
3563  // the traced value
3564  buffer->put(dataOffset, stringVal);
3565  dataOffset += stringVal->getBLength();
3566 
3567  // and finally, the trailing quote
3568  if (quoteValue)
3569  {
3570  buffer->putCharB(dataOffset, '\"');
3571  dataOffset++;
3572  }
3573  /* write out the line */
3574  this->activity->traceOutput(this, buffer);
3575 }
3576 
3577 
3578 /**
3579  * Trace an entry that's of the form 'tag => "value"'.
3580  *
3581  * @param prefix The trace prefix tag to use.
3582  * @param tagPrefix Any prefix string added to the tag. Use mostly for adding
3583  * the "." to traced environment variables.
3584  * @param quoteTag Indicates whether the tag should be quoted or not. Operator
3585  * names are quoted.
3586  * @param tag The tag name.
3587  * @param value The associated trace value.
3588  */
3589 void RexxActivation::traceOperatorValue(int prefix, const char *tag, RexxObject *value)
3590 {
3591  // the trace settings would normally require us to trace this, but there are conditions
3592  // where we just skip doing this anyway.
3593  if (this->settings.flags&trace_suppress || this->debug_pause || value == OREF_NULL || !code->isTraceable())
3594  {
3595  return;
3596  }
3597 
3598  // get the string value from the traced object.
3599  RexxString *stringVal = value->stringValue();
3600 
3601  // now calculate the length of the traced string
3602  stringsizeB_t outLength = strlen(tag) + stringVal->getBLength();
3603  // these are fixed overheads
3604  outLength += TRACE_OVERHEAD + strlen(VALUE_MARKER);
3605  // now the indent spacing
3606  outLength += this->settings.traceindent * INDENT_SPACING;
3607  // now other conditionals
3608  outLength += QUOTES_OVERHEAD;
3609 
3610  // now get a buffer to write this out into
3611  RexxString *buffer = raw_string(outLength);
3612  ProtectedObject p(buffer);
3613 
3614  // get a cursor for filling in the formatted data
3615  stringsizeB_t dataOffset = TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING - 2;
3616  /* insert the leading blanks */
3617  buffer->set(0, ' ', TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING);
3618  /* add the trace prefix */
3620 
3621  // operators are quoted.
3622  buffer->putCharB(dataOffset, '\"');
3623  dataOffset++;
3624 
3625  // add in the tag name
3626  buffer->put(dataOffset, tag, strlen(tag));
3627  dataOffset += strlen(tag);
3628 
3629  // need a closing quote.
3630  buffer->putCharB(dataOffset, '\"');
3631  dataOffset++;
3632 
3633  // now add the data marker
3634  buffer->put(dataOffset, VALUE_MARKER, strlen(VALUE_MARKER));
3635  dataOffset += strlen(VALUE_MARKER);
3636 
3637  // the leading quote around the value
3638  buffer->putCharB(dataOffset, '\"');
3639  dataOffset++;
3640 
3641  // the traced value
3642  buffer->put(dataOffset, stringVal);
3643  dataOffset += stringVal->getBLength();
3644 
3645  // and finally, the trailing quote
3646  buffer->putCharB(dataOffset, '\"');
3647  dataOffset++;
3648  /* write out the line */
3649  this->activity->traceOutput(this, buffer);
3650 }
3651 
3652 
3653 /**
3654  * Trace a compound variable entry that's of the form 'tag =>
3655  * "value"'.
3656  *
3657  * @param prefix The trace prefix tag to use.
3658  * @param stem The stem name of the compound.
3659  * @param tails The array of tail elements (unresolved).
3660  * @param tailCount The count of tail elements.
3661  * @param value The resolved tail element
3662  */
3663 void RexxActivation::traceCompoundValue(int prefix, RexxString *stemName, RexxObject **tails, size_t tailCount,
3664  RexxCompoundTail *tail)
3665 {
3666  traceCompoundValue(TRACE_PREFIX_COMPOUND, stemName, tails, tailCount, VALUE_MARKER, tail->createCompoundName(stemName));
3667 }
3668 
3669 
3670 /**
3671  * Trace a compound variable entry that's of the form 'tag =>
3672  * "value"'.
3673  *
3674  * @param prefix The trace prefix tag to use.
3675  * @param stem The stem name of the compound.
3676  * @param tails The array of tail elements (unresolved).
3677  * @param tailCount The count of tail elements.
3678  * @param value The associated trace value.
3679  * @quoteValue Indicates whether the value should be quoted or not.
3680  */
3681 void RexxActivation::traceCompoundValue(int prefix, RexxString *stemName, RexxObject **tails, size_t tailCount, const char *marker,
3682  RexxObject * value, bool quoteValue)
3683 {
3684  // the trace settings would normally require us to trace this, but there are conditions
3685  // where we just skip doing this anyway.
3686  if (this->settings.flags&trace_suppress || this->debug_pause || value == OREF_NULL || !code->isTraceable())
3687  {
3688  return;
3689  }
3690 
3691  // get the string value from the traced object.
3692  RexxString *stringVal = value->stringValue();
3693 
3694  // now calculate the length of the traced string
3695  stringsizeB_t outLength = stemName->getBLength() + stringVal->getBLength();
3696 
3697  // build an unresolved tail name
3698  RexxCompoundTail tail(tails, tailCount, false);
3699 
3700  outLength += tail.getLength();
3701 
3702  // add in the number of added dots
3703  // [jlf: the dots are already included] outLength += tailCount - 1;
3704 
3705  // these are fixed overheads
3706  outLength += TRACE_OVERHEAD + strlen(marker);
3707  // jlf: by default, TRACE_OVERHEAD includes 2 for the quotes around the value. Must substract 2 if quotes not displayed.
3708  if (quoteValue == false) outLength -= 2;
3709  // now the indent spacing
3710  outLength += this->settings.traceindent * INDENT_SPACING;
3711 
3712  // now get a buffer to write this out into
3713  RexxString *buffer = raw_string(outLength);
3714  ProtectedObject p(buffer);
3715 
3716  // get a cursor for filling in the formatted data
3717  stringsizeB_t dataOffset = TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING - 2;
3718  /* insert the leading blanks */
3719  buffer->set(0, ' ', TRACE_OVERHEAD + this->settings.traceindent * INDENT_SPACING);
3720  /* add the trace prefix */
3722 
3723  // add in the stem name
3724  buffer->put(dataOffset, stemName);
3725  dataOffset += stemName->getBLength();
3726 
3727  // copy the tail portion of the compound name
3728  buffer->put(dataOffset, tail.getTail(), tail.getLength());
3729  dataOffset += tail.getLength();
3730 
3731  // now add the data marker
3732  buffer->put(dataOffset, marker, strlen(marker));
3733  dataOffset += strlen(marker);
3734 
3735  // the leading quote around the value
3736  if (quoteValue)
3737  {
3738  buffer->putCharB(dataOffset, '\"');
3739  dataOffset++;
3740  }
3741 
3742  // the traced value
3743  buffer->put(dataOffset, stringVal);
3744  dataOffset += stringVal->getBLength();
3745 
3746  // and finally, the trailing quote
3747  if (quoteValue)
3748  {
3749  buffer->putCharB(dataOffset, '\"');
3750  dataOffset++;
3751  }
3752  /* write out the line */
3753  this->activity->traceOutput(this, buffer);
3754 }
3755 
3756 
3758 /******************************************************************************/
3759 /* Function: Trace the source string at debug mode start */
3760 /******************************************************************************/
3761 {
3762  /* already traced? */
3763  if (this->settings.flags&source_traced)
3764  {
3765  return; /* don't do it again */
3766  }
3767  /* tag this as traced */
3768  this->settings.flags |= source_traced;
3769  /* get the string version */
3770  RexxString *string = this->sourceString(); /* get the source string */
3771  /* get a string large enough to */
3772  sizeB_t outlength = string->getBLength() + INSTRUCTION_OVERHEAD + 2;
3773  RexxString *buffer = raw_string(outlength); /* get an output string */
3774  /* insert the leading blanks */
3775  buffer->set(0, ' ', INSTRUCTION_OVERHEAD);
3776  /* add the trace prefix */
3778  /* add a quotation mark */
3779  buffer->putCharB(INSTRUCTION_OVERHEAD, '\"');
3780  /* copy the string value */
3781  buffer->put(INSTRUCTION_OVERHEAD + 1, string->getStringData(), string->getBLength());
3782  buffer->putCharB(outlength - 1, '\"');/* add the trailing quotation mark */
3783  /* write out the line */
3784  this->activity->traceOutput(this, buffer);
3785 }
3786 
3787 
3789  RexxInstruction * instruction, /* instruction to trace */
3790  RexxSource * _source ) /* program source */
3791 /******************************************************************************/
3792 /* Function: Format a source line for traceback or tracing */
3793 /******************************************************************************/
3794 {
3795  if (instruction == OREF_NULL) /* no current instruction? */
3796  {
3797  return OREF_NULL; /* nothing to trace here */
3798  }
3799  // get the instruction location
3800  SourceLocation location = instruction->getLocation();
3801  /* extract the source string */
3802  /* (formatted for tracing) */
3804  {
3805  return _source->traceBack(this, location, this->settings.traceindent, true);
3806  }
3807  else
3808  {
3809  return _source->traceBack(this, location, MAX_TRACEBACK_INDENT, true);
3810  }
3811 }
3812 
3813  /* process clause boundary stuff */
3815 /******************************************************************************/
3816 /* Function: Handle all clause boundary processing (raising of halt */
3817 /* conditions, turning on of external traces, and calling of halt */
3818 /* and trace clause boundary exits */
3819 /******************************************************************************/
3820 {
3821  if (this->pending_count != 0) /* do we have trapped conditions? */
3822  {
3823  this->processTraps(); /* go dispatch the traps */
3824  }
3825 
3826  this->activity->callHaltTestExit(this); /* Sys exit want to raise a halt? */
3827  /* did sysexit change trace state */
3828  if (!this->activity->callTraceTestExit(this, this->isExternalTraceOn()))
3829  {
3830  /* remember new state... */
3831  if (this->isExternalTraceOn()) /* if current setting is on */
3832  {
3833  this->setExternalTraceOff(); /* turn it off */
3834  }
3835  else /* otherwise */
3836  {
3837  this->setExternalTraceOn(); /* turn it on */
3838  }
3839  }
3840  /* yield situation occurred? */
3841  if (this->settings.flags&external_yield)
3842  {
3843  /* turn off the yield flag */
3844  this->settings.flags &= ~external_yield;
3845  this->activity->relinquish(); /* yield control to the activity */
3846  }
3847  /* halt condition occurred? */
3848  if (this->settings.flags&halt_condition)
3849  {
3850  /* turn off the halt flag */
3851  this->settings.flags &= ~halt_condition;
3852  /* yes, raise the flag */
3853  /* process as common condition */
3855  {
3856  /* raise as a syntax error */
3858  }
3859  }
3860  /* need to turn on tracing? */
3861  if (this->settings.flags&set_trace_on)
3862  {
3863  /* turn off the trace flag */
3864  this->settings.flags &= ~set_trace_on;
3865  this->setExternalTraceOn(); /* and save the current state */
3866  /* turn on tracing */
3868  // this->setTrace(this->settings.externalTraceOption, this->settings.externalTraceFlags);
3869  }
3870  /* need to turn off tracing? */
3871  if (this->settings.flags&set_trace_off)
3872  {
3873  /* turn off the trace flag */
3874  this->settings.flags &= ~set_trace_off;
3875  this->setExternalTraceOff(); /* and save the current state */
3876  /* turn on tracing */
3878  }
3879  /* no clause exits and all conditions*/
3880  /* have been processed? */
3881  if (!(this->settings.flags&clause_exits) && this->pending_count == 0)
3882  {
3883  /* turn off boundary processing */
3884  this->settings.flags &= ~clause_boundary;
3885  }
3886 }
3887 
3888 
3889 /**
3890  * Turn on external trace at program startup (e.g, because
3891  * RXTRACE is set)
3892  */
3893 void RexxActivation::enableExternalTrace(const char *option)
3894 {
3895  //this->setTrace(TRACE_RESULTS | DEBUG_ON, trace_results_flags | trace_debug);
3896 
3897  // The trace option can be followed by an optional "colon <depth>".
3898  const char *colon = strchr(option, ':');
3899  RexxString *s = (colon == NULL) ? new_string(option) : new_string(option, stringsizeB_v(colon - option));
3900  if (s->strCaselessCompare("ON"))
3901  {
3902  // ignore the depth
3904  }
3905  else
3906  {
3907  ProtectedObject p(s);
3908  size_t depth = (colon == NULL) ? SIZE_MAX : atoi(colon+1); // will be zero if not a valid integer
3909  this->setTrace(s, true, depth);
3910  }
3911 }
3912 
3913 
3914 /**
3915  * Halt the activation
3916  *
3917  * @param description
3918  * The description for the halt condition (if any).
3919  *
3920  * @return true if this halt was recognized, false if there is a
3921  * previous halt condition still to be processed.
3922  */
3924 {
3925  // if there's no halt condition pending, set this
3926  if ((settings.flags&halt_condition) == 0)
3927  {
3928  /* store the description */
3929  this->settings.halt_description = description;
3930  /* turn on the HALT flag */
3931  this->settings.flags |= halt_condition;
3932  /* turn on clause boundary checking */
3933  this->settings.flags |= clause_boundary;
3934  return true;
3935  }
3936  else
3937  {
3938  // we're not in a good position to process this
3939  return false;
3940  }
3941 }
3942 
3944 /******************************************************************************/
3945 /* Function: Flip ON the externally activated TRACE bit. */
3946 /******************************************************************************/
3947 {
3948  /* turn on the yield flag */
3949  this->settings.flags |= external_yield;
3950  /* turn on clause boundary checking */
3951  this->settings.flags |= clause_boundary;
3952 }
3953 
3955 /******************************************************************************/
3956 /* Function: Flip ON the externally activated TRACE bit. */
3957 /******************************************************************************/
3958 {
3959  this->settings.flags |= set_trace_on;/* turn on the tracing flag */
3960  /* turn on clause boundary checking */
3961  this->settings.flags |= clause_boundary;
3962  /* turn on tracing */
3964  // this->setTrace(this->settings.externalTraceOption, this->settings.externalTraceFlags);
3965 }
3966 
3968 /******************************************************************************/
3969 /* Function: Flip OFF the externally activated TRACE bit. */
3970 /******************************************************************************/
3971 {
3972  /* turn off the tracing flag */
3973  this->settings.flags |= set_trace_off;
3974  /* turn on clause boundary checking */
3975  this->settings.flags |= clause_boundary;
3976 }
3977 
3978 
3980 /******************************************************************************/
3981 /* Function: Process an individual debug pause for an instruction */
3982 /******************************************************************************/
3983 {
3984  if (this->debug_pause) /* instruction during debug pause? */
3985  {
3986  return false; /* just get out quick */
3987  }
3988 
3989  if (this->settings.flags&debug_bypass)
3990  {
3991  /* turn off for the next time */
3992  this->settings.flags &= ~debug_bypass;
3993  }
3994  /* debug pauses suppressed? */
3995  else if (this->settings.trace_skip > 0)
3996  {
3997  this->settings.trace_skip--; /* account for this one */
3998  if (this->settings.trace_skip == 0)/* gone to zero? */
3999  {
4000  /* turn tracing back on again (this */
4001  /* ensures the next pause also has */
4002  /* the instruction traced */
4003  this->settings.flags &= ~trace_suppress;
4004  }
4005  }
4006  else
4007  {
4008  if (!this->code->isTraceable()) /* if we don't have real source */
4009  {
4010  return false; /* just ignore for this */
4011  }
4012  /* newly into debug mode? */
4013  if (!(this->settings.flags&debug_prompt_issued))
4014  {
4015  /* write the initial prompt */
4017  /* remember we've issued this */
4019  }
4020  RexxInstruction *currentInst = this->next; /* save the next location target */
4021  for (;;)
4022  {
4023  RexxString *response;
4024  /* read a line from the screen */
4025  response = this->activity->traceInput(this);
4026 
4027  if (response->getBLength() == 0) /* just a "null" line entered? */
4028  {
4029  break; /* just end the pausing */
4030  }
4031  /* a re-execute request? */
4032  else if (response->getBLength() == 1 && response->getCharB(0) == '=')
4033  {
4034  this->next = this->current; /* reset the execution pointer */
4035  return true; /* finished (inform block instrs) */
4036  }
4037  else
4038  {
4039  this->debugInterpret(response);/* go execute this */
4040  if (currentInst != this->next) /* flow of control change? */
4041  {
4042  break; /* end of this pause */
4043  }
4044  /* has the use changed the trace */
4045  /* setting on us? */
4046  else if (this->settings.flags&debug_bypass)
4047  {
4048  /* turn off for the next time */
4049  this->settings.flags &= ~debug_bypass;
4050  break; /* we also skip repausing */
4051  }
4052  }
4053  }
4054  }
4055  return false; /* no re-execute */
4056 }
4057 
4058 void RexxActivation::traceClause( /* trace a REXX instruction */
4059  RexxInstruction * clause, /* value to trace */
4060  int prefix ) /* prefix to use */
4061 /******************************************************************************/
4062 /* Function: Trace an individual line of a source file */
4063 /******************************************************************************/
4064 {
4065  /* tracing currently suppressed? */
4066  if (this->settings.flags&trace_suppress || this->debug_pause)
4067  {
4068  return; /* just ignore this call */
4069  }
4070  if (!this->code->isTraceable()) /* if we don't have real source */
4071  {
4072  return; /* just ignore for this */
4073  }
4074  /* format the line */
4075  RexxString *line = this->formatTrace(clause, this->code->getSourceObject());
4076  if (line != OREF_NULL) /* have a source line? */
4077  {
4078  /* newly into debug mode? */
4079  if ((this->settings.flags&trace_debug && !(this->settings.flags&source_traced)))
4080  {
4081  this->traceSourceString(); /* trace the source string */
4082  }
4083  /* write out the line */
4084  this->activity->traceOutput(this, line);
4085  }
4086 }
4087 
4088 /**
4089  * Issue a command to a named host evironment
4090  *
4091  * @param commandString
4092  * The command to issue
4093  * @param address The target address
4094  *
4095  * @return The return code object
4096  */
4097 void RexxActivation::command(RexxString *address, RexxString *commandString)
4098 {
4099  bool instruction_traced; /* instruction has been traced */
4100  ProtectedObject condition;
4101  ProtectedObject commandResult;
4102 
4103  /* instruction already traced? */
4104  if (tracingAll() || tracingCommands())
4105  {
4106  instruction_traced = true; /* remember we traced this */
4107  }
4108  else
4109  {
4110  instruction_traced = false; /* not traced yet */
4111  }
4112  /* if exit declines call */
4113  if (this->activity->callCommandExit(this, address, commandString, commandResult, condition))
4114  {
4115  // first check for registered command handlers
4116  CommandHandler *handler = activity->resolveCommandHandler(address);
4117  if (handler != OREF_NULL)
4118  {
4119  handler->call(activity, this, address, commandString, commandResult, condition);
4120  }
4121  else
4122  {
4123  // No handler for this environment
4124  commandResult = new_integer(RXSUBCOM_NOTREG); // just use the not registered return code
4125  // raise the condition when things are done
4126  condition = activity->createConditionObject(OREF_FAILURENAME, (RexxObject *)commandResult, commandString, OREF_NULL, OREF_NULL);
4127  }
4128  }
4129 
4130  RexxObject *rc = (RexxObject *)commandResult;
4131  RexxDirectory *conditionObj = (RexxDirectory *)(RexxObject *)condition;
4132 
4133  bool failureCondition = false; // don't have a failure condition yet
4134 
4135  int returnStatus = RETURN_STATUS_NORMAL;
4136  // did a handler raise a condition? We need to pull the rc value from the
4137  // condition object
4138  if (conditionObj != OREF_NULL)
4139  {
4140  RexxObject *temp = conditionObj->at(OREF_RC);
4141  if (temp == OREF_NULL)
4142  {
4143  // see if we have a result and make sure the condition object
4144  // fills this as the RC value
4145  temp = conditionObj->at(OREF_RESULT);
4146  if (temp != OREF_NULL)
4147  {
4148  conditionObj->put(temp, OREF_RC);
4149  }
4150  }
4151  // replace the RC value
4152  if (temp != OREF_NULL)
4153  {
4154  rc = temp;
4155  }
4156 
4157  RexxString *conditionName = (RexxString *)conditionObj->at(OREF_CONDITION);
4158  // check for an error or failure condition, since these get special handling
4159  if (conditionName->strCompare(CHAR_FAILURENAME))
4160  {
4161  // unconditionally update the RC value
4162  conditionObj->put(temp, OREF_RC);
4163  // failure conditions require special handling when raising the condition
4164  // we'll need to reraise this as an ERROR condition if not trapped.
4165  failureCondition = true;
4166  // set the appropriate return status
4167  returnStatus = RETURN_STATUS_FAILURE;
4168  }
4169  if (conditionName->strCompare(CHAR_ERROR))
4170  {
4171  // unconditionally update the RC value
4172  conditionObj->put(temp, OREF_RC);
4173  // set the appropriate return status
4174  returnStatus = RETURN_STATUS_ERROR;
4175  }
4176  }
4177 
4178  // a handler might not return a value, so default the return code to zero
4179  // if nothing is received.
4180  if (rc == OREF_NULL)
4181  {
4182  rc = TheFalseObject;
4183  }
4184 
4185  // if this was done during a debug pause, we don't update RC
4186  // and .RS.
4187  if (!this->debug_pause)
4188  {
4189  // set the RC value before anything
4190  this->setLocalVariable(OREF_RC, VARIABLE_RC, rc);
4191  /* tracing command errors or fails? */
4192  if ((returnStatus == RETURN_STATUS_ERROR && tracingErrors()) ||
4193  (returnStatus == RETURN_STATUS_FAILURE && (tracingFailures())))
4194  {
4195  /* trace the current instruction */
4196  this->traceClause(this->current, TRACE_PREFIX_CLAUSE);
4197  /* then we always trace full command */
4198  this->traceValue(commandString, TRACE_PREFIX_RESULT);
4199  instruction_traced = true; /* we've now traced this */
4200  }
4201 
4202  wholenumber_t rcValue;
4203  /* need to trace the RC info too? */
4204  if (instruction_traced && rc->numberValue(rcValue) && rcValue != 0)
4205  {
4206  /* get RC as a string */
4207  RexxString *rc_trace = rc->stringValue();
4208  /* tack on the return code */
4209  rc_trace = rc_trace->concatToCstring("RC(");
4210  /* add the closing part */
4211  rc_trace = rc_trace->concatWithCstring(")");
4212  /* trace the return code */
4213  this->traceValue(rc_trace, TRACE_PREFIX_ERROR);
4214  }
4215  // set the return status
4216  setReturnStatus(returnStatus);
4217 
4218  // now handle any conditions we might need to raise
4219  // these are also not raised if it's a debug pause.
4220  if (conditionObj != OREF_NULL)
4221  {
4222  // try to raise the condition, and if it isn't handled, we might
4223  // munge this into an ERROR condition
4224  if (!activity->raiseCondition(conditionObj))
4225  {
4226  // untrapped failure condition? Turn into an ERROR condition and
4227  // reraise
4228  if (failureCondition)
4229  {
4230  // just change the condition name
4231  conditionObj->put(OREF_ERRORNAME, OREF_CONDITION);
4232  activity->raiseCondition(conditionObj);
4233  }
4234  }
4235  }
4236  // do debug pause if necessary. necessary is defined by: we are
4237  // tracing ALL or COMMANDS, OR, we /* using TRACE NORMAL and a FAILURE
4238  // return code was received OR we receive an ERROR return code and
4239  // have TRACE ERROR in effect.
4240  if (instruction_traced && inDebug())
4241  {
4242  this->debugPause(); /* do the debug pause */
4243  }
4244  }
4245 }
4246 
4247 /**
4248  * Set the return status flag for an activation context.
4249  *
4250  * @param status The new status value.
4251  */
4253 {
4254  this->settings.return_status = status;
4255  this->settings.flags |= return_status_set;
4256 }
4257 
4258 
4260 /******************************************************************************/
4261 /* Function: Return the name of the current program file */
4262 /******************************************************************************/
4263 {
4264  return this->code->getProgramName(); /* get the name from the code */
4265 }
4266 
4268 /******************************************************************************/
4269 /* Function: Return the directory of labels for this method */
4270 /******************************************************************************/
4271 {
4272  return this->code->getLabels(); /* get the labels from the code */
4273 }
4274 
4276 /******************************************************************************/
4277 /* Function: Create the source string returned by parse source */
4278 /******************************************************************************/
4279 {
4280  /* produce the system specific string*/
4281  return SystemInterpreter::getSourceString(this->settings.calltype, this->code->getProgramName());
4282 }
4283 
4284 
4285 /**
4286  * Add a local routine to the current activation's routine set.
4287  *
4288  * @param name The name to add this under.
4289  * @param method The method associated with the name.
4290  */
4292 {
4293  // get the directory of external functions
4295 
4296  // if it does not exist, it will be created
4297  if (routines == OREF_NULL)
4298  {
4299 
4301  routines = settings.parent_code->getLocalRoutines();
4302  }
4303  // if a method by that name exists, it will be OVERWRITTEN!
4304  routines->setEntry(name, _method);
4305 }
4306 
4307 
4308 /**
4309  * Retrieve the directory of public routines associated with the
4310  * current activation.
4311  *
4312  * @return A directory of the public routines.
4313  */
4315 {
4316  return code->getPublicRoutines();
4317 }
4318 
4319 
4320 
4322  RexxMessage * notify) /* activation to notify */
4323 /******************************************************************************/
4324 /* Function: Set an error notification tag on the activation. */
4325 /******************************************************************************/
4326 {
4327  this->objnotify = notify;
4328 }
4329 
4330 
4332  RexxObject * environment) /* new local environment buffer */
4333 /******************************************************************************/
4334 /* Function: Push the new environment buffer onto the EnvLIst */
4335 /******************************************************************************/
4336 {
4337  /* internal call or interpret? */
4338  if (this->isTopLevelCall())
4339  {
4340  /* nope, push environment here. */
4341  /* DO we have a environment list? */
4342  if (!this->environmentList)
4343  {
4344  /* nope, create one */
4345  this->environmentList = new_list();
4346  }
4347  this->environmentList->addFirst(environment);
4348  }
4349  else /* nope, process up the chain. */
4350  {
4351  /* Yes, forward on the message. */
4352  this->parent->pushEnvironment(environment);
4353  }
4354 }
4355 
4357 /******************************************************************************/
4358 /* Function: return the top level local Environemnt */
4359 /******************************************************************************/
4360 {
4361  /* internal call or interpret? */
4362  if (this->isTopLevelCall())
4363  {
4364  /* nope, we puop Environemnt here */
4365  /* DO we have a environment list? */
4366  if (this->environmentList)
4367  {
4368  /* yup, return first element */
4369  return this->environmentList->removeFirst();
4370 
4371  }
4372  else /* nope, return .nil */
4373  {
4374  return TheNilObject;
4375  }
4376  }
4377  else
4378  { /* nope, pass on up the chain. */
4379  /* Yes, forward on the message. */
4380  return this->parent->popEnvironment();
4381  }
4382 }
4383 
4385 /******************************************************************************/
4386 /* Function: Close any streams opened by the I/O builtin functions */
4387 /******************************************************************************/
4388 {
4389  RexxString *index; /* index for stream directory */
4390 
4391  /* exiting a bottom level? */
4392  if (this->isProgramOrMethod())
4393  {
4394  RexxDirectory *streams = this->settings.streams; /* get the streams directory */
4395  /* actually have a table? */
4396  if (streams != OREF_NULL)
4397  {
4398  /* traverse this */
4399  for (HashLink j = streams->first(); (index = (RexxString *)streams->index(j)) != OREF_NULL; j = streams->next(j))
4400  {
4401  /* closing each stream */
4402  streams->at(index)->sendMessage(OREF_CLOSE);
4403  }
4404  }
4405  }
4406 }
4407 
4408 
4410  RexxString *name ) /* name to retrieve */
4411 /******************************************************************************/
4412 /* Function: process unitialized variable over rides */
4413 /******************************************************************************/
4414 {
4415  /* get the handler from .local */
4416  RexxObject *novalue_handler = getLocalEnvironment(OREF_NOVALUE);
4417  if (novalue_handler != OREF_NULL) /* have a novalue handler? */
4418  {
4419  /* ask it to process this */
4420  return novalue_handler->sendMessage(OREF_NOVALUE, name);
4421  }
4422  return TheNilObject; /* return the handled result */
4423 }
4424 
4425 /**
4426  * Retrieve the package for the current execution context.
4427  *
4428  * @return The Package holding the code for the current execution
4429  * context.
4430  */
4432 {
4433  return executable->getPackage();
4434 }
4435 
4436 
4437 RexxObject *RexxActivation::evaluateLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
4438 {
4439  /* new tail for compound */
4440  RexxCompoundTail resolved_tail(this, tail, tailCount);
4441 
4442  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4443  RexxObject *value = stem_table->evaluateCompoundVariableValue(this, stemName, &resolved_tail);
4444  /* need to trace? */
4445  if (tracingIntermediates())
4446  {
4447  traceCompoundName(stemName, tail, tailCount, &resolved_tail);
4448  /* trace variable value */
4449  traceCompound(stemName, tail, tailCount, value);
4450  }
4451  return value;
4452 }
4453 
4454 
4455 RexxObject *RexxActivation::getLocalCompoundVariableValue(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
4456 {
4457  /* new tail for compound */
4458  RexxCompoundTail resolved_tail(this, tail, tailCount);
4459 
4460  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4461  return stem_table->getCompoundVariableValue(&resolved_tail);
4462 }
4463 
4464 
4465 RexxObject *RexxActivation::getLocalCompoundVariableRealValue(RexxString *localstem, size_t index, RexxObject **tail, size_t tailCount)
4466 {
4467  /* new tail for compound */
4468  RexxCompoundTail resolved_tail(this, tail, tailCount);
4469 
4470  RexxStem *stem_table = getLocalStem(localstem, index); /* get the stem entry from this dictionary */
4471  return stem_table->getCompoundVariableRealValue(&resolved_tail);
4472 }
4473 
4474 
4475 RexxCompoundElement *RexxActivation::getLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
4476 {
4477  /* new tail for compound */
4478  RexxCompoundTail resolved_tail(this, tail, tailCount);
4479 
4480  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4481  return stem_table->getCompoundVariable(&resolved_tail);
4482 }
4483 
4484 
4486 {
4487  /* new tail for compound */
4488  RexxCompoundTail resolved_tail(this, tail, tailCount);
4489 
4490  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4491  return stem_table->exposeCompoundVariable(&resolved_tail);
4492 }
4493 
4494 
4495 bool RexxActivation::localCompoundVariableExists(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
4496 {
4497  /* new tail for compound */
4498  RexxCompoundTail resolved_tail(this, tail, tailCount);
4499 
4500  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4501  return stem_table->compoundVariableExists(&resolved_tail);
4502 }
4503 
4504 
4505 void RexxActivation::assignLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
4506 {
4507  /* new tail for compound */
4508  RexxCompoundTail resolved_tail(this, tail, tailCount);
4509 
4510  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4511  /* and set the value */
4512  stem_table->setCompoundVariable(&resolved_tail, value);
4513  /* trace resolved compound name */
4514  if (tracingIntermediates())
4515  {
4516  traceCompoundName(stemName, tail, tailCount, &resolved_tail);
4517  /* trace variable value */
4518  traceCompoundAssignment(stemName, tail, tailCount, value);
4519  }
4520 }
4521 
4522 
4523 void RexxActivation::setLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
4524 {
4525  /* new tail for compound */
4526  RexxCompoundTail resolved_tail(this, tail, tailCount);
4527 
4528  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4529  /* and set the value */
4530  stem_table->setCompoundVariable(&resolved_tail, value);
4531 }
4532 
4533 
4534 void RexxActivation::dropLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
4535 {
4536  /* new tail for compound */
4537  RexxCompoundTail resolved_tail(this, tail, tailCount);
4538 
4539  RexxStem *stem_table = getLocalStem(stemName, index); /* get the stem entry from this dictionary */
4540  /* and set the value */
4541  stem_table->dropCompoundVariable(&resolved_tail);
4542  // jlf: I want a trace
4543  if (tracingIntermediates())
4544  {
4545  traceCompoundName(stemName, tail, tailCount, &resolved_tail);
4546  /* trace variable value */
4547  traceCompoundAssignment(stemName, tail, tailCount, OREF_TRACE_is_dropped, false);
4548  }
4549 }
4550 
4551 
4552 /**
4553  * Get the security manager in effect for a given context.
4554  *
4555  * @return The security manager defined for this activation
4556  * context.
4557  */
4559 {
4560  return this->settings.securityManager;
4561 }
4562 
4563 
4564 /**
4565  * Get the security manager in used by this activation.
4566  *
4567  * @return Either the defined security manager or the instance-global security
4568  * manager.
4569  */
4571 {
4572  SecurityManager *manager = this->settings.securityManager;
4573  if (manager != OREF_NULL)
4574  {
4575  return manager;
4576  }
4578 }
4579 
4580 
4581 /**
4582  * Retrieve a value from the instance local environment.
4583  *
4584  * @param name The name of the .local object.
4585  *
4586  * @return The object stored at the given name.
4587  */
4589 {
4590  return activity->getLocalEnvironment(name);
4591 }
4592 
4593 
4594 /**
4595  * @return The directory of thread's local variables.
4596  */
4598 {
4599  return activity->getThreadLocal();
4600 }
4601 
4602 
4603 /**
4604  * Create a stack frame for exception tracebacks.
4605  *
4606  * @return A StackFrame instance for this activation.
4607  */
4609 {
4610  const char *type = FRAME_METHOD;
4612  RexxObject *target = OREF_NULL;
4613 
4614  if (isInterpret())
4615  {
4617  }
4618  else if (isInternalCall())
4619  {
4621  arguments = getArguments();
4622  }
4623  else if (isMethod())
4624  {
4625  type = FRAME_METHOD;
4626  arguments = getArguments();
4627  target = receiver;
4628  }
4629  else if (isProgram())
4630  {
4631  type = FRAME_PROGRAM;
4632  arguments = getArguments();
4633  }
4634  else if (isRoutine())
4635  {
4636  type = FRAME_ROUTINE;
4637  arguments = getArguments();
4638  }
4639 
4640  ProtectedObject p_arguments(arguments); // getArguments() returns a new array, so must be protected
4641  // construct the traceback line before we allocate the stack frame object.
4642  // calling this in the constructor argument list can cause the stack frame instance
4643  // to be inadvertently reclaimed if a GC is triggered while evaluating the constructor
4644  // arguments.
4645  RexxString *traceback = getTraceBack();
4646  ProtectedObject p_traceback(traceback);
4648 }
4649 
4650 /**
4651  * Format a more informative trace line when giving
4652  * traceback information for code when no source code is
4653  * available.
4654  *
4655  * @param packageName
4656  * The package name to use (could be "REXX" for internal code)
4657  *
4658  * @return A formatted descriptive string for the invocation.
4659  */
4661 {
4662  // if this is a method invocation, then we can give the method name and scope.
4663  if (isMethod())
4664  {
4665  RexxString *scopeName = (scope == TheNilObject ? scope->requestString() : scope->getId());
4666  ProtectedObject pscopeName(scopeName);
4667  RexxArray *info = new_array(getMessageName(), scopeName, packageName);
4668  ProtectedObject p(info);
4669 
4671  }
4672  else if (isRoutine())
4673  {
4674  RexxArray *info = new_array(getMessageName(), packageName);
4675  ProtectedObject p(info);
4676 
4678  }
4679  else
4680  {
4681  RexxArray *info = new_array(packageName);
4682  ProtectedObject p(info);
4683 
4685  }
4686 }
4687 
4688 
4689 /**
4690  * Generate the stack frames for the current context.
4691  *
4692  * @return A list of the stackframes.
4693  */
4695 {
4696  return activity->generateStackFrames(skipFirst);
4697 }
4698 
4699 
4700 /**
4701  * Store user-redefined arguments.
4702  */
4703 void RexxActivation::setArguments(RexxArray *positionalArguments, RexxDirectory *namedArguments)
4704 {
4705  size_t count = positionalArguments->size(); // count of positional arguments
4706  RexxArray *arguments = (RexxArray *)positionalArguments->copy();
4708  size_t namedCount = 0;
4709  if (namedArguments != OREF_NULL && namedArguments != TheNilObject)
4710  {
4711  namedCount = namedArguments->appendAllIndexesItemsTo(arguments, /*from*/ count+1); // from is 1-based index
4712  }
4713  this->arglist = arguments->data();
4714  this->argcount = count;
4715  this->named_argcount = namedCount;
4716  this->arguments = arguments; // Protect against GC as long as the activation exists and uses it
4717 }
4718 
void reportNovalue(RexxString *description)
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Activation
RexxDirectory * new_directory()
RexxInteger * new_integer(wholenumber_t v)
RexxList * new_list()
Definition: ListClass.hpp:147
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
#define PREFIX_LENGTH
#define TRACE_OVERHEAD
#define INDENT_SPACING
#define DEFAULT_MIN
static ActivationSettings activationSettingsTemplate
#define QUOTES_OVERHEAD
#define INSTRUCTION_OVERHEAD
static const char * trace_prefix_table[]
#define PREFIX_OFFSET
#define MAX_DIFFERENCE
#define DEFAULT_MAX
#define MAX_INSTRUCTIONS
#define RETURN_STATUS_NORMAL
#define INTERPRET
#define RETURN_STATUS_ERROR
#define RETURNED
#define DEBUGPAUSE
#define ACTIVE
#define INTERNALCALL
#define RETURN_STATUS_FAILURE
#define REPLIED
#define EXTERNALCALL
#define MS_PREORDER
#define METHODCALL
uint64_t RANDOMIZE(uint64_t seed)
#define SCOPE_RESERVED
#define SCOPE_RELEASED
@ TRACE_PREFIX_CLAUSE
@ TRACE_PREFIX_ERROR
@ TRACE_PREFIX_COMPOUND
@ TRACE_PREFIX_INVOCATION
@ TRACE_PREFIX_RESULT
#define MAX_TRACEBACK_INDENT
#define VALUE_MARKER
#define OREF_NULL
Definition: RexxCore.h:60
#define IntegerThree
Definition: RexxCore.h:192
#define TheEnvironment
Definition: RexxCore.h:174
#define TheClassClass
Definition: RexxCore.h:148
#define TheTrueObject
Definition: RexxCore.h:186
#define TheFunctionsDirectory
Definition: RexxCore.h:176
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
#define Error_Incorrect_call_random
#define Error_Execution_reply
#define Error_Execution_reply_return
#define Message_Translations_sourceless_method_invocation
#define Message_Translations_debug_prompt
#define Message_Translations_sourceless_routine_invocation
#define Message_Translations_sourceless_program_invocation
#define Message_Translations_method_invocation
#define Error_Program_interrupted_condition
#define Error_Incorrect_call_random_range
#define Error_Invalid_leave_leavevar
#define Error_Invalid_trace_trace
#define Message_Translations_routine_invocation
#define Error_Unexpected_procedure_call
#define Error_Label_not_found_name
#define Error_Incorrect_call_nonnegative
#define Error_Invalid_leave_iteratevar
#define Error_Invalid_leave_iterate
#define Error_Routine_not_found_name
#define Error_Invalid_leave_leave
#define Error_Execution_reply_exit
#define Error_Invalid_trace_debug
#define Error_Invalid_leave_iterate_name
size_t HashLink
RexxReturnCode REXXENTRY RexxResolveMacroFunction(const char *, PRXSTRING)
#define VARIABLE_SUPER
#define VARIABLE_RC
#define VARIABLE_SIGL
#define VARIABLE_SELF
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
const size_t TRACE_OFF
Definition: SourceFile.hpp:82
const size_t TRACE_DEBUG_MASK
Definition: SourceFile.hpp:99
const int DEBUG_ON
Definition: SourceFile.hpp:93
const int DEBUG_OFF
Definition: SourceFile.hpp:94
const size_t TRACE_RESULTS
Definition: SourceFile.hpp:80
#define FRAME_METHOD
#define FRAME_PROGRAM
#define FRAME_ROUTINE
#define FRAME_INTERNAL_CALL
#define FRAME_INTERPRET
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
RexxString * raw_string(stringsizeB_t bl, stringsizeC_t cl=-1)
#define KEYWORD_SIGNAL
Definition: Token.hpp:169
#define KEYWORD_CALL
Definition: Token.hpp:148
#define KEYWORD_PROCEDURE
Definition: Token.hpp:161
#define KEYWORD_LABEL
Definition: Token.hpp:187
RexxObject ** parent_arglist
RexxDateTime timestamp
RexxDirectory * streams
RexxLocalVariables local_variables
RexxString * current_env
RexxDirectory * traps
NumericSettings numericSettings
RexxArray * parent_arguments
RexxString * alternate_env
RexxVariableDictionary * object_variables
wholenumber_t trace_skip
SecurityManager * securityManager
RexxDirectory * conditionObj
RexxString * halt_description
static wholenumber_t addWaitingActivityCounter()
static RexxActivation * newActivation(RexxActivity *activity, RexxActivation *parent, RoutineClass *routine, RexxCode *code, RexxString *calltype, RexxString *environment, int context)
static wholenumber_t yieldCounter()
static RexxActivity *volatile currentActivity
static wholenumber_t relinquishCounter()
PackageClass * getPackage()
RexxString * getName()
Definition: MethodClass.hpp:93
RexxSource * getSourceObject()
Definition: MethodClass.hpp:85
void call(RexxActivity *activity, RexxActivation *activation, RexxString *address, RexxString *command, ProtectedObject &rc, ProtectedObject &condition)
static bool hasTimeSliceElapsed()
void setupProgram(RexxActivation *activation)
RexxString * getDefaultEnvironment()
static LibraryPackage * getLibrary(RexxString *name)
RexxActivationBase * previous
virtual bool trap(RexxString *, RexxDirectory *)
virtual bool isRexxContext()
RexxObject * getExecutableObject()
BaseExecutable * executable
RexxActivationBase * getPreviousStackFrame()
BaseExecutable * getExecutable()
virtual bool isForwarded()
RexxQueue * handler_queue
RexxList * environmentList
RexxString * formatTrace(RexxInstruction *, RexxSource *)
RexxObject * externalCall(RexxString *, RexxObject **, size_t, size_t, RexxString *, ProtectedObject &)
RexxSource * getSourceObject()
RexxObject * internalCall(RexxString *, RexxInstruction *, RexxObject **, size_t, size_t, ProtectedObject &)
RexxObject * getLocalCompoundVariableRealValue(RexxString *localstem, size_t index, RexxObject **tail, size_t tailCount)
bool tracingFailures(void)
virtual bool isRexxContext()
bool isInternalLevelCall()
RexxArray * getStackFrames(bool skipFirst)
RexxInstruction * next
RexxActivation * external()
RexxString * getMessageName()
RexxCompoundElement * getLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
void iterate(RexxString *)
void traceClause(RexxInstruction *, int)
void exitFrom(RexxObject *)
RexxObject * getParentContextObject()
bool callExternalRexx(RexxString *, RexxObject **, size_t, size_t, RexxString *, ProtectedObject &)
RexxString * sourceString()
RexxArray * arguments
void traceCompoundAssignment(RexxString *stemVar, RexxObject **tails, size_t tailCount, RexxObject *value, bool quoteValue=true)
RexxSource * sourceObject
RexxArray * getArguments()
void signalTo(RexxInstruction *)
void traceCompoundName(RexxString *stemVar, RexxObject **tails, size_t tailCount, RexxCompoundTail *tail)
void traceTaggedValue(int prefix, const char *tagPrefix, bool quoteTag, RexxString *tag, const char *marker, RexxObject *value, bool quoteValue=true)
static const size_t trace_off
void debugSkip(wholenumber_t, bool)
RexxMessage * objnotify
void loadLibrary(RexxString *target, RexxInstruction *instruction)
static const size_t trace_all_flags
RexxQueue * condition_queue
void raise(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *, RexxDirectory *)
RexxStem * getLocalStem(RexxString *name, size_t index)
bool isElapsedTimerReset()
RexxObject * handleNovalueEvent(RexxString *name, RexxObject *defaultValue, RexxVariable *variable)
static const size_t trace_commands
RexxString * trapState(RexxString *)
RexxActivation * senderActivation()
RexxVariableDictionary * getObjectVariables()
static const size_t single_step_nested
static const size_t trace_debug
void assignLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
RexxArray * trapinfo
SecurityManager * getEffectiveSecurityManager()
RexxObject * result
bool tracingCommands(void)
static const size_t trace_intermediates
virtual RexxObject * getReceiver()
void pushEnvironment(RexxObject *)
RexxString * traceSetting()
bool tracingLabels(void)
void setReturnStatus(int status)
void setDigits(size_t)
void trapOn(RexxString *, RexxInstructionCallBase *)
void dropLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
void setLocalVariable(RexxString *name, size_t index, RexxObject *value)
RexxClass * findClass(RexxString *name)
RexxString * formatSourcelessTraceLine(RexxString *packageName)
void interpret(RexxString *)
RexxActivity * activity
void raiseExit(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *, RexxDirectory *)
void liveGeneral(int reason)
static const size_t trace_errors
void processClauseBoundary()
RexxObject * getLocalEnvironment(RexxString *name)
void setFuzz(size_t)
RexxObject * receiver
void leaveLoop(RexxString *)
static const size_t trace_suppress
void debugInterpret(RexxString *)
static const bool default_enable_macrospace
void setAddress(RexxString *)
RexxObject * evaluateLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
void setDefaultAddress(RexxString *)
void signalValue(RexxString *)
static const size_t trace_results
static const size_t set_trace_on
void procedureExpose(RexxVariableBase **variables, size_t count)
RexxObject * getContextLine()
RexxClass * scope
static const size_t guarded_method
void setObjNotify(RexxMessage *)
static const size_t set_trace_off
void enableExternalTrace(const char *option)
void setExternalTraceOff()
RexxExpressionStack stack
RexxCompoundElement * exposeLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
static const size_t debug_bypass
void setTrace(size_t, size_t)
void traceOperatorValue(int prefix, const char *tag, RexxObject *value)
void trapDelay(RexxString *)
bool localCompoundVariableExists(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
RexxObject * resolveDotVariable(RexxString *name)
static const size_t trace_failures
RexxObject * getContextReturnStatus()
static const size_t forwarded
bool debugPause(RexxInstruction *instr=OREF_NULL)
static const size_t reply_issued
StackFrameClass * createStackFrame()
void live(size_t)
ActivationSettings settings
virtual RexxActivation * getRexxContext()
RexxDirectory * getThreadLocal()
RexxDateTime getTime()
RexxObject * getLocalCompoundVariableValue(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
virtual RexxActivation * findRexxContext()
PackageClass * loadRequires(RexxString *, RexxInstruction *)
RexxObject * getContextObject()
bool tracingAll(void)
void command(RexxString *, RexxString *)
void putSettings(ActivationSettings &s)
RexxObject * internalCallTrap(RexxString *, RexxInstruction *, RexxDirectory *, ProtectedObject &)
static const size_t trace_labels
void traceCompoundValue(int prefix, RexxString *stemName, RexxObject **tails, size_t tailCount, RexxCompoundTail *tail)
RexxObject * novalueHandler(RexxString *)
void addLocalRoutine(RexxString *name, RexxMethod *method)
static size_t processTraceSetting(size_t traceSetting)
void setIndent(size_t v)
void getSettings(ActivationSettings &s)
void traceCompound(RexxString *stemVar, RexxObject **tails, size_t tailCount, RexxObject *value)
bool tracingErrors(void)
void mergeTraps(RexxQueue *, RexxQueue *)
bool callMacroSpaceFunction(RexxString *, RexxObject **, size_t, size_t, RexxString *, int, ProtectedObject &)
static const size_t return_status_set
static RoutineClass * getMacroCode(RexxString *macroName)
RexxInstruction * current
RexxObject ** arglist
uint64_t getRandomSeed(RexxInteger *)
static const size_t clause_exits
void unwindTrap(RexxActivation *)
void setElapsedTimerInvalid()
static const size_t default_trace_flags
void trapOff(RexxString *)
RexxDirectory * getLabels()
void setLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
RexxInteger * random(RexxInteger *, RexxInteger *, RexxInteger *)
static const size_t trace_all
static const size_t clause_boundary
static const size_t elapsed_reset
bool halt(RexxString *)
RexxObject * forward(RexxObject *, RexxString *, RexxObject *, RexxObject **, size_t, size_t, bool)
void setArguments(RexxArray *positionalArguments, RexxDirectory *namedArguments)
SecurityManager * getSecurityManager()
PackageClass * getPackage()
RexxDirectory * getPublicRoutines()
void trapUndelay(RexxString *)
RexxContext * contextObject
void returnFrom(RexxObject *result)
static const size_t halt_condition
void reply(RexxObject *)
RexxObject * rexxVariable(RexxString *)
bool tracingIntermediates()
static const size_t debug_prompt_issued
RexxString * resolveProgramName(RexxString *name)
void expose(RexxVariableBase **variables, size_t count)
static const size_t single_step
RexxObject * dispatch()
RexxDoBlock * topBlock()
void setElapsedTimerValid()
bool trap(RexxString *, RexxDirectory *)
RexxString * getTraceBack()
static const size_t trace_results_flags
static const size_t trace_on
void setConditionObj(RexxDirectory *condition)
RexxDoBlock * dostack
bool propagateNumericSettings()
RexxDirectory * getStreams()
size_t getContextLineNumber()
RexxActivation * parent
static const size_t trace_intermediates_flags
static const size_t external_yield
RexxObject * popEnvironment()
void cleanupLocalVariables()
static const size_t traps_copied
RexxObject * run(RexxObject *_receiver, RexxString *msgname, RexxArray *_arguments, RexxObject **_arglist, size_t _argcount, size_t _named_argcount, RexxInstruction *start, ProtectedObject &resultObj)
static const size_t source_traced
void traceValue(RexxObject *, int)
RexxObject * resolveStream(RexxString *name, bool input, RexxString **fullName, bool *added)
static const bool default_enable_commands
static const size_t transfer_failed
RexxString * getProgramName()
static const size_t procedure_valid
static const size_t trace_flags
virtual NumericSettings * getNumericSettings()
bool callTraceTestExit(RexxActivation *, bool)
CommandHandler * resolveCommandHandler(RexxString *)
uint64_t getRandomSeed()
void pushStackFrame(RexxActivationBase *new_activation)
void releaseStackFrame(RexxObject **frame)
bool callScriptingExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t)
RexxDirectory * getThreadLocal()
void callTerminationExit(RexxActivation *)
static wholenumber_t requestAccessCounter()
bool callHaltTestExit(RexxActivation *)
RexxObject * displayDebug(RexxDirectory *)
bool callObjectFunctionExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t, size_t)
bool callNovalueExit(RexxActivation *, RexxString *, RexxObject *&)
void traceOutput(RexxActivation *, RexxString *)
void callInitializationExit(RexxActivation *)
RexxObject * getLocalEnvironment(RexxString *name)
bool callFunctionExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t)
void raiseException(wholenumber_t, RexxString *, RexxArray *, RexxObject *)
void allocateLocalVariableFrame(RexxLocalVariables *locals)
void popStackFrame(bool reply)
RexxActivity * spawnReply()
void checkStackSpace()
RexxString * buildMessage(wholenumber_t, RexxArray *)
void allocateStackFrame(RexxExpressionStack *stack, size_t entries)
void reraiseException(RexxDirectory *)
void unwindToFrame(RexxActivation *frame)
void setRandomSeed(uint64_t seed)
InterpreterInstance * getInstance()
SecurityManager * getInstanceSecurityManager()
void clearCurrentCondition()
RexxDirectory * createConditionObject(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
bool callHaltClearExit(RexxActivation *)
RexxObject ** allocateFrame(size_t entries)
bool callCommandExit(RexxActivation *, RexxString *, RexxString *, ProtectedObject &result, ProtectedObject &condition)
RexxArray * generateStackFrames(bool skipFirst)
bool raiseCondition(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
RexxActivation * getCurrentRexxFrame()
RexxString * traceInput(RexxActivation *)
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxObject * copy()
Definition: ArrayClass.cpp:122
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxObject ** data()
Definition: ArrayClass.hpp:204
virtual bool isLabel(RexxString *)
virtual void terminate(RexxActivation *, RexxDoBlock *)
RexxString * getId()
Definition: ClassClass.cpp:254
RexxString * getProgramName()
Definition: RexxCode.cpp:203
void install(RexxActivation *activation)
Definition: RexxCode.hpp:87
RexxCode * interpret(RexxString *s, size_t n, RexxActivation *activation)
Definition: RexxCode.hpp:88
RexxDirectory * getLocalRoutines()
Definition: RexxCode.hpp:79
size_t getMaxStackSize()
Definition: RexxCode.hpp:77
RexxDirectory * getRoutines()
Definition: RexxCode.hpp:90
RexxDirectory * getMethods()
Definition: RexxCode.hpp:89
RexxInstruction * getFirstInstruction()
Definition: RexxCode.hpp:75
bool isTraceable()
Definition: RexxCode.hpp:83
RexxSource * getSourceObject()
Definition: RexxCode.hpp:74
RexxString * resolveProgramName(RexxActivity *activity, RexxString *name)
Definition: RexxCode.hpp:92
RexxDirectory * getPublicRoutines()
Definition: RexxCode.hpp:80
RoutineClass * findRoutine(RexxString *n)
Definition: RexxCode.hpp:91
void mergeRequired(RexxSource *s)
Definition: RexxCode.hpp:93
RexxDirectory * getLabels()
Definition: RexxCode.hpp:76
SecurityManager * getSecurityManager()
Definition: RexxCode.hpp:86
size_t getLocalVariableSize()
Definition: RexxCode.hpp:78
const char * getTail()
RexxString * createCompoundName(RexxString *)
int64_t getUTCBaseTime()
RexxObject * copy()
RexxObject * at(RexxString *)
RexxObject * setEntry(RexxString *, RexxObject *)
RexxObject * put(RexxObject *, RexxString *)
size_t appendAllIndexesItemsTo(RexxArray *array, size_t from)
RexxObject * remove(RexxString *)
RexxBlockInstruction * getParent()
Definition: DoBlock.hpp:67
size_t getIndent()
Definition: DoBlock.hpp:73
void push(RexxObject *value)
RexxObject ** getFrame()
void liveGeneral(int reason)
void migrate(RexxActivity *)
HashLink next(HashLink pos)
RexxObject * index(HashLink pos)
const SourceLocation & getLocation()
virtual void execute(RexxActivation *, RexxExpressionStack *)
RexxInstruction * nextInstruction
bool isType(size_t type)
RexxObject * getValue(RexxActivation *)
virtual RexxObject * getValue(RexxActivation *)
size_t getSize()
Definition: ListClass.hpp:126
RexxObject * lastItem()
Definition: ListClass.cpp:697
RexxObject * removeFirst()
Definition: ListClass.hpp:109
void addLast(RexxObject *value)
Definition: ListClass.cpp:455
void addFirst(RexxObject *value)
Definition: ListClass.cpp:486
void procedure(RexxActivation *activation)
void migrate(RexxActivity *)
void liveGeneral(int reason)
void init(RexxActivation *creator, size_t poolSize)
void checkUninitQueue()
Definition: RexxMemory.hpp:200
void error(RexxDirectory *)
bool isGuarded()
RexxClass * getScope()
bool messageSend(RexxString *, RexxObject **, size_t, size_t, ProtectedObject &, bool processUnknown=true)
RexxVariableDictionary * getObjectVariables(RexxObject *)
RexxObject * superScope(RexxObject *)
RexxString * stringValue()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxString * requestString()
virtual bool numberValue(wholenumber_t &result, size_t precision)
bool isInstanceOf(RexxClass *)
RexxObject * pullRexx()
Definition: QueueClass.cpp:64
static const size_t TRACE_COMMANDS
Definition: SourceFile.hpp:423
PackageClass * loadRequires(RexxActivity *activity, RexxString *target)
static const size_t TRACE_ERRORS
Definition: SourceFile.hpp:427
static const size_t TRACE_INTERMEDIATES
Definition: SourceFile.hpp:429
static const size_t TRACE_SETTING_MASK
Definition: SourceFile.hpp:436
bool getEnableCommands()
Definition: SourceFile.hpp:417
bool getForm()
Definition: SourceFile.hpp:412
RexxString * traceBack(RexxActivation *, SourceLocation &, size_t, bool)
RexxSource * parentSource
Definition: SourceFile.hpp:476
size_t getDigits()
Definition: SourceFile.hpp:411
static const size_t TRACE_LABELS
Definition: SourceFile.hpp:424
SecurityManager * getSecurityManager()
Definition: SourceFile.hpp:379
size_t getTraceFlags()
Definition: SourceFile.hpp:415
size_t getFuzz()
Definition: SourceFile.hpp:413
static const size_t DEBUG_ON
Definition: SourceFile.hpp:443
static RexxString * formatTraceSetting(size_t source)
static const size_t TRACE_IGNORE
Definition: SourceFile.hpp:431
static const size_t DEBUG_OFF
Definition: SourceFile.hpp:444
static const size_t TRACE_NORMAL
Definition: SourceFile.hpp:425
size_t getTraceSetting()
Definition: SourceFile.hpp:414
void mergeRequired(RexxSource *)
void setLocalRoutines(RexxDirectory *r)
Definition: SourceFile.hpp:383
static const size_t TRACE_RESULTS
Definition: SourceFile.hpp:428
static const size_t TRACE_OFF
Definition: SourceFile.hpp:430
bool getEnableMacrospace()
Definition: SourceFile.hpp:418
RexxClass * findClass(RexxString *)
static const size_t DEBUG_IGNORE
Definition: SourceFile.hpp:442
static const size_t TRACE_ALL
Definition: SourceFile.hpp:422
static bool parseTraceSetting(RexxString *, size_t &, size_t &, char &)
static const size_t DEBUG_TOGGLE
Definition: SourceFile.hpp:445
static const size_t TRACE_FAILURES
Definition: SourceFile.hpp:426
RexxCompoundElement * getCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:574
RexxObject * getCompoundVariableValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:764
RexxCompoundElement * exposeCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:586
RexxObject * getCompoundVariableRealValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:814
void dropCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:634
void setCompoundVariable(RexxCompoundTail *name, RexxObject *value)
Definition: StemClass.cpp:674
RexxObject * evaluateCompoundVariableValue(RexxActivation *context, RexxString *stemVariableName, RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:712
bool compoundVariableExists(RexxCompoundTail *resolved_tail)
Definition: StemClass.hpp:138
bool strCaselessCompare(const char *s)
const char * getStringData()
char putCharB(sizeB_t p, char c)
char getCharB(sizeB_t p)
RexxString * concatWithCstring(const char *)
void set(sizeB_t s, int c, sizeB_t l)
RexxString * concatToCstring(const char *)
bool strCompare(const char *s)
void put(sizeB_t s, const void *b, sizeB_t l)
sizeB_t getBLength()
virtual void procedureExpose(RexxActivation *, RexxActivation *, RexxExpressionStack *)
virtual void expose(RexxActivation *, RexxExpressionStack *, RexxVariableDictionary *)
void set(RexxObject *value)
void call(RexxActivity *, RexxString *, RexxObject **, size_t, size_t, RexxString *, RexxString *, int, ProtectedObject &)
static RoutineClass * restore(RexxBuffer *, char *, size_t length)
static RoutineClass * fromFile(RexxString *filename)
RexxObject * checkStreamAccess(RexxString *name)
static RexxString * qualifyFileSystemName(RexxString *name)
static void getCurrentTime(RexxDateTime *Date)
static bool invokeExternalFunction(RexxActivation *, RexxActivity *, RexxString *, RexxObject **, size_t, size_t, RexxString *, ProtectedObject &)
static RexxString * getSourceString(RexxString *callType, RexxString *programName)
static RexxString * getMessageText(wholenumber_t code)
static void releaseResultMemory(void *)
static void restoreEnvironment(void *CurrentEnv)
int type
Definition: cmdparse.cpp:383
wholenumber_t REXXENTRY getAPIManagerCounter()
stringsize_t stringsizeB_t
Definition: rexx.h:247
#define stringsizeB_v(X)
Definition: rexx.h:249
RexxReturnCode REXXENTRY RexxQueryMacro(CONSTANT_STRING, unsigned short *)
ssize_t wholenumber_t
Definition: rexx.h:230
stringsizeB_t sizeB_t
Definition: rexx.h:248
size_t stringsize_t
Definition: rexx.h:228
#define RXSUBCOM_NOTREG
Definition: rexxapidefs.h:90
#define RXMACRO_SEARCH_AFTER
Definition: rexxapidefs.h:221
char * strptr
Definition: rexx.h:158
char work[256]
char line[LINEBUFSIZE]
#define SIZE_MAX
signed __int64 int64_t
unsigned __int64 uint64_t