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