RexxActivity.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 Activity Class */
42 /* */
43 /* NOTE: activities 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, activities "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 #include <stdlib.h>
51 #include <ctype.h>
52 #include "RexxCore.h"
53 #include "StringClass.hpp"
54 #include "StackClass.hpp"
55 #include "RexxActivity.hpp"
56 #include "RexxActivation.hpp"
57 #include "RexxNativeActivation.hpp"
58 #include "MessageClass.hpp"
59 #include "ArrayClass.hpp"
60 #include "TableClass.hpp"
61 #include "DirectoryClass.hpp"
62 #include "SourceFile.hpp"
64 #include "RexxCode.hpp"
65 #include "RexxInstruction.hpp"
66 #include "RexxMemory.hpp"
68 #include "ProtectedObject.hpp"
69 #include "PointerClass.hpp"
70 #include "InterpreterInstance.hpp"
71 #include "ActivityDispatcher.hpp"
72 #include "MessageDispatcher.hpp"
73 #include "Interpreter.hpp"
74 #include "PackageClass.hpp"
75 #include "SystemInterpreter.hpp"
76 #include "ActivationFrame.hpp"
77 #include "StackFrameClass.hpp"
79 
80 const size_t ACT_STACK_SIZE = 20;
81 
82 /**
83  * The main entry point for spawned activities.
84  */
86 {
87  bool firstDispatch = true; // some things only occur on subsequent requests
88  /* establish the stack base pointer */
90 
91  for (;;)
92  {
93  // save the actitivation level in case there's an error unwind for an unhandled
94  // exception;
95  size_t activityLevel = 0;
96  // the thread might have terminated for a control stack issue
97  // so make sure checking is turned back on before trying to run
98  // anything
99  this->stackcheck = true;
100 
101  try
102  {
103  this->runsem.wait("RexxActivity::runThread", 0); /* wait for run permission */
104  if (this->exit) /* told to exit? */
105  {
106  break; /* we're out of here */
107  }
108  this->requestAccess(); /* now get the kernel lock */
109  // we're already marked as active when first called to keep us from
110  // getting terminated prematurely before we get a chance to run
111  if (!firstDispatch)
112  {
113  this->activate(); // make sure this is marked as active
114  }
115  firstDispatch = false; // we need to activate every time after this
116  activityLevel = getActivationLevel();
117 
118  // if we have a dispatch message set, send it the send message to kick everything off
119  if (dispatchMessage != OREF_NULL)
120  {
122  run(dispatcher);
123  }
124  else
125  {
126 
127  // this is a reply message start, just dispatch the Rexx code
128  this->topStackFrame->dispatch();
129  }
130  }
131  catch (ActivityException) // we've had a termination event, raise an error
132  {
133  // it's possible that we might not have the kernel lock when
134  // control returns to here. Make sure we have it.
136  {
137  this->requestAccess();
138  }
139  this->error();
140  }
141 
142  // make sure we get restored to the same base activation level.
143  restoreActivationLevel(activityLevel);
144  memoryObject.verboseMessage("Calling runUninits from RexxActivity::runThread\n");
145  memoryObject.runUninits(); /* run any needed UNINIT methods now */
146 
147  this->deactivate(); // no longer an active activity
148 
149  dispatchMessage = OREF_NULL; // we're done with the message object
150 
151  runsem.reset(); /* reset the run semaphore and the */
152  guardsem.reset(); /* guard semaphore */
153 
154  // try to pool this. If the ActivityManager doesn't take, we go into termination mode
155  if (!instance->poolActivity(this))
156  {
157  this->releaseAccess();
158  break;
159  }
160  // release the kernel lock and go wait for more work
161  this->releaseAccess();
162  }
163  // tell the activity manager we're going away
165  return; /* finished */
166 }
167 
168 
169 /**
170  * Do cleanup of activity resources when an activity is completely
171  * shutdown and discarded.
172  */
174 {
175  runsem.close();
176  guardsem.close();
178 }
179 
180 
181 /**
182  * We're leaving the current thread. So we need to deactivate
183  * this.
184  */
186 {
187  // deactivate the nesting level
188  deactivate();
189  // if we're inactive, try to run any pending uninits
190  if (isInactive())
191  {
192  memoryObject.verboseMessage("Calling runUninits from RexxActivity::exitCurrentThread\n");
194  }
195  // this activity owned the kernel semaphore before entering here...release it
196  // now.
197  releaseAccess();
198 }
199 
200 /**
201  * Enter the current thread for an API call.
202  */
204 {
205  /* Activity already existed for this */
206  /* get kernel semophore in activity */
207  requestAccess();
208  activate(); // let the activity know it's in use, potentially nested
209  // belt-and-braces. Make sure the current activity is explicitly set to
210  // this activity before leaving.
212 }
213 
214 
215 void *RexxActivity::operator new(size_t size)
216 /******************************************************************************/
217 /* Function: Create a new activity */
218 /******************************************************************************/
219 {
220  /* get the new activity storage */
221  return new_object(size, T_Activity);
222 }
223 
224 
225 /**
226  * Initialize an Activity object.
227  *
228  * @param createThread
229  * Indicates whether we're going to be running on the
230  * current thread, or creating a new thread.
231  */
232 RexxActivity::RexxActivity(bool createThread)
233 : runsem("RexxActivity::runsem"), guardsem("RexxActivity::guardsem")
234 {
235  // we need to protect this from garbage collection while constructing.
236  // unfortunately, we can't use ProtectedObject because that requires an
237  // active activity, which we can't guarantee at this point.
238  GlobalProtectedObject p(this);
239 
240  this->clearObject(); /* globally clear the object */
241 
242  // clearObject overwrites the pointer to variable name of the semaphores...
243  // must reassign those pointers !!! otherwise, you see that in debug output :
244  // (SysSemaphore)(null).wait ... i.e. (null) instead of the variable name.
245  this->runsem.setSemVariable("RexxActivity::runsem");
246  this->guardsem.setSemVariable("RexxActivity::guardsem");
247 
248  /* create an activation stack */
250  this->frameStack.init(); /* initialize the frame stack */
251  this->runsem.create(); /* create the run and */
252  this->guardsem.create(); /* guard semaphores */
253  this->activationStackSize = ACT_STACK_SIZE; /* set the activation stack size */
254  this->stackcheck = true; /* start with stack checking enabled */
255  /* use default settings set */
256  /* set up current usage set */
258  this->generateRandomNumberSeed(); /* get a fresh random seed */
259  /* Create table for progream being */
260  this->requiresTable = new_table(); /*installed vial ::REQUIRES */
261  // create a stack frame for this running context
264 
265  if (createThread) /* need to create a thread? */
266  {
267  runsem.reset(); /* set the run semaphore */
268  // we need to enter this thread already marked as active, otherwise
269  // the main thread might shut us down before we get a chance to perform
270  // whatever function we're getting asked to run.
271  activate();
272  /* create a thread */
274  }
275  else /* thread already exists */
276  {
277  // run on the current thread
279  /* establish the stack base pointer */
281  }
282 }
283 
284 
285 /**
286  * Initialize an Activity object that's being recycled for
287  * another use.
288  */
290 {
291  /* Make sure any left over */
292  /* ::REQUIRES is cleared out. */
293  this->resetRunningRequires();
294 }
295 
296 
297 /**
298  * Create a new activity for processing a method reply
299  * instruction.
300  *
301  * @return The newly created activity.
302  */
304 {
305  // recreate a new activiy in the same instance
306  return instance->spawnActivity(this);
307 }
308 
310 /******************************************************************************/
311 /* Function: Generate a fresh random number seed. */
312 /******************************************************************************/
313 {
314  // a good random value for a starting point would be the address of the
315  // activity.
316  uint64_t rnd = (uint64_t)(uintptr_t)this;
317  // flip the bits to generate a little more noise. This value is
318  // largely to ensure that the timestamp value doesn't produce similar
319  // seeds because of low timer resolution.
320  rnd = ~rnd;
321 
322  RexxDateTime timestamp; /* current timestamp */
323  SystemInterpreter::getCurrentTime(&timestamp); /* get a fresh time stamp */
324  /* take the seed from the time */
325  randomSeed = rnd + timestamp.getBaseTime();
326  for (int i = 0; i < 13; i++)
327  { /* randomize the seed number a bit */
328  /* scramble the seed a bit */
330  }
331 }
332 
333 
335 /******************************************************************************/
336 /* Function: Force error termination on an activity, returning the resulting */
337 /* REXX error code. */
338 /******************************************************************************/
339 {
340  // unwind to a base activation
341  while (!topStackFrame->isStackBase())
342  {
343  // if we're not to the stack very base of the stack, terminate the frame
344  this->topStackFrame->termination();
345  this->popStackFrame(false);
346  }
347 
348  // go display
349  return displayCondition(this->conditionobj);
350 }
351 
352 
354 /******************************************************************************/
355 /* Function: Force error termination on an activity, returning the resulting */
356 /* REXX error code. */
357 /******************************************************************************/
358 {
359  // if not passed an explicit error object, use whatever we have in our
360  // local holder.
361  if (errorInfo == OREF_NULL)
362  {
363  errorInfo = this->conditionobj;
364  }
365 
366  // unwind to a base activation
367  while (topStackFrame != activation)
368  {
369  // if we're not to the stack very base of the stack, terminate the frame
370  this->topStackFrame->termination();
371  this->popStackFrame(false);
372  }
373 
374  // go display
375  return displayCondition(errorInfo);
376 }
377 
378 /**
379  * Display error information and traceback lines for a
380  * Syntax condition.
381  *
382  * @param errorInfo The condition object with the error information
383  *
384  * @return The major error code for the syntax error, if this is
385  * indeed a syntax conditon.
386  */
388 {
389  // no condition object? This is a nop
390  if (errorInfo == OREF_NULL)
391  {
392  return 0; // no error condition to return
393  }
394 
395  RexxString *condition = (RexxString *)errorInfo->at(OREF_CONDITION);
396  // we only display syntax conditions
397  if (condition == OREF_NULL || !condition->isEqual(OREF_SYNTAX))
398  {
399  return 0; // no error condition to return
400  }
401  // display the information
402  this->display(errorInfo);
403 
404  wholenumber_t rc = Error_Interpretation/1000; /* set default return code */
405  // try to convert. Leaves unchanged if not value
406  errorInfo->at(OREF_RC)->numberValue(rc);
407  return rc; /* return the error code */
408 }
409 
410 
411 /**
412  * Extract an error number from a syntax condition object.
413  *
414  * @param conditionObject
415  * The condition object for the extract.
416  *
417  * @return The RC value associated with the condition.
418  */
420 {
421  wholenumber_t rc = Error_Interpretation/1000; /* set default return code */
422  /* did we get a condtion object? */
423  if (conditionObject != OREF_NULL)
424  {
425  // try to convert. Leaves unchanged if not value
426  conditionObject->at(OREF_RC)->numberValue(rc);
427  }
428  return rc; /* return the error code */
429 }
430 
431 
432 /**
433  * Raise a condition, with potential trapping.
434  *
435  * @param condition The condition name.
436  * @param rc The rc value
437  * @param description
438  * The description value.
439  * @param additional the exception additional information.
440  * @param result The condition result info.
441  *
442  * @return true if this was trapped via CALL ON, false for untrapped
443  * conditions.
444  */
445 bool RexxActivity::raiseCondition(RexxString *condition, RexxObject *rc, RexxString *description, RexxObject *additional, RexxObject *result)
446 {
447  // just create a condition object and process the traps.
448  RexxDirectory *conditionObj = createConditionObject(condition, rc, description, additional, result);
449  return raiseCondition(conditionObj);
450 }
451 
452 /**
453  * Process condition trapping for a condition or syntax
454  * error.
455  *
456  * @param conditionObj
457  * The condition object that describes the condition.
458  *
459  * @return true if this was trapped, false otherwise. If trapped
460  * via a SIGNAL ON, this will NOT return to here.
461  */
463 {
464  bool handled = false; /* condition not handled yet */
465  RexxString *condition = (RexxString *)conditionObj->at(OREF_CONDITION);
466 
467  /* invoke the error traps, on all */
468  /* nativeacts until reach 1st */
469  /* also give 1st activation a shot. */
470  for (RexxActivationBase *activation = this->getTopStackFrame() ; !activation->isStackBase(); activation = activation->getPreviousStackFrame())
471  {
472  handled = activation->trap(condition, conditionObj);
473  if (isOfClass(Activation, activation)) /* reached our 1st activation yet. */
474  {
475  break; /* yes, break out of loop */
476  }
477  }
478 
479  /* Control will not return here if the condition was trapped via*/
480  /* SIGNAL ON SYNTAX. For CALL ON conditions, handled will be */
481  /* true if a trap is pending. */
482 
483  return handled; /* this has been handled */
484 }
485 
486 
487 /**
488  * Create a condition object from the provided information.
489  *
490  * @param condition The name of the raised condition.
491  * @param rc The rc value (can be null)
492  * @param description
493  * The description string.
494  * @param additional Additional information.
495  * @param result result information.
496  *
497  * @return The constructed condition object (a directory).
498  */
500 {
501  // condition objects are directories
502  RexxDirectory *conditionObj = new_directory();
503  ProtectedObject p(conditionObj);
504  /* put in the condition name */
505  conditionObj->put(condition, OREF_CONDITION);
506  /* fill in default description */
507  conditionObj->put(description == OREF_NULL ? OREF_NULLSTRING : description, OREF_DESCRIPTION);
508  /* fill in the propagation status */
509  conditionObj->put(TheFalseObject, OREF_PROPAGATED);
510  if (rc != OREF_NULL) /* have an RC value? */
511  {
512  conditionObj->put(rc, OREF_RC); /* add to the condition argument */
513  }
514  if (additional != OREF_NULL) /* or additional information */
515  {
516  conditionObj->put(additional, OREF_ADDITIONAL);
517  }
518  if (result != OREF_NULL) /* given a return result? */
519  {
520  conditionObj->put(result, OREF_RESULT);
521  }
522 
523  // add in all location-specific information
524  generateProgramInformation(conditionObj);
525  return conditionObj;
526 }
527 
529  wholenumber_t errcode ) /* REXX error code */
530 /******************************************************************************/
531 /* Function: Forward on an exception condition */
532 /******************************************************************************/
533 {
534  /* send along with nothing */
535  this->raiseException(errcode, OREF_NULL, OREF_NULL, OREF_NULL);
536 }
537 
539  wholenumber_t errcode, /* REXX error code */
540  RexxObject *substitution1 ) /* substitution information */
541 /******************************************************************************/
542 /* Function: Forward on an exception condition */
543 /******************************************************************************/
544 {
545  RexxArray *substitutions = new_array(substitution1);
546  ProtectedObject p(substitutions);
547  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
548 }
549 
551  wholenumber_t errcode, /* REXX error code */
552  RexxObject *substitution1, /* substitution information */
553  RexxObject *substitution2 ) /* substitution information */
554 /******************************************************************************/
555 /* Function: Forward on an exception condition */
556 /******************************************************************************/
557 {
558  RexxArray *substitutions = new_array(substitution1, substitution2);
559  ProtectedObject p(substitutions);
560  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
561 }
562 
564  wholenumber_t errcode, /* REXX error code */
565  RexxObject *substitution1, /* substitution information */
566  RexxObject *substitution2, /* substitution information */
567  wholenumber_t integer)
568 /******************************************************************************/
569 /* Function: Forward on an exception condition */
570 /******************************************************************************/
571 {
572  RexxInteger *iinteger = new_integer(integer);
573  ProtectedObject pinteger(iinteger);
574  RexxArray *substitutions = new_array(substitution1, substitution2, iinteger);
575  ProtectedObject p(substitutions);
576  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
577 }
578 
580  wholenumber_t errcode, /* REXX error code */
581  RexxObject *substitution1, /* substitution information */
582  RexxObject *substitution2, /* substitution information */
583  const char *string)
584 /******************************************************************************/
585 /* Function: Forward on an exception condition */
586 /******************************************************************************/
587 {
588  RexxString *sstring = new_string(string);
589  ProtectedObject pstring(sstring);
590  RexxArray *substitutions = new_array(substitution1, substitution2, sstring);
591  ProtectedObject p(substitutions);
592  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
593 }
594 
596  wholenumber_t errcode, /* REXX error code */
597  RexxObject *substitution1, /* substitution information */
598  RexxObject *substitution2, /* substitution information */
599  RexxObject *substitution3 ) /* substitution information */
600 /******************************************************************************/
601 /* Function: Forward on an exception condition */
602 /******************************************************************************/
603 {
604  RexxArray *substitutions = new_array(substitution1, substitution2, substitution3);
605  ProtectedObject p(substitutions);
606  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
607 }
608 
610  wholenumber_t errcode, /* REXX error code */
611  RexxObject *substitution1, /* substitution information */
612  RexxObject *substitution2, /* substitution information */
613  RexxObject *substitution3, /* substitution information */
614  RexxObject *substitution4 ) /* substitution information */
615 /******************************************************************************/
616 /* Function: Forward on an exception condition */
617 /******************************************************************************/
618 {
619  RexxArray *substitutions = new_array(substitution1, substitution2, substitution3, substitution4);
620  ProtectedObject p(substitutions);
621  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
622 }
623 
625  wholenumber_t errcode, /* REXX error code */
626  RexxObject *substitution1, /* substitution information */
627  RexxObject *substitution2, /* substitution information */
628  RexxObject *substitution3, /* substitution information */
629  RexxObject *substitution4, /* substitution information */
630  RexxObject *substitution5 ) /* substitution information */
631 /******************************************************************************/
632 /* Function: Forward on an exception condition */
633 /******************************************************************************/
634 {
635  RexxArray *substitutions = new_array(substitution1, substitution2, substitution3, substitution4, substitution5);
636  ProtectedObject p(substitutions);
637  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
638 }
639 
641  wholenumber_t errcode, /* REXX error code */
642  const char *substitution1, /* substitution information */
643  RexxObject *substitution2, /* substitution information */
644  const char *substitution3, /* substitution information */
645  RexxObject *substitution4 ) /* substitution information */
646 /******************************************************************************/
647 /* Function: Forward on an exception condition */
648 /******************************************************************************/
649 {
650  RexxString *ssubstitution1 = new_string(substitution1);
651  ProtectedObject psubstitution1 = ssubstitution1;
652  RexxString *ssubstitution3 = new_string(substitution3);
653  ProtectedObject psubstitution3 = ssubstitution3;
654  RexxArray *substitutions = new_array(ssubstitution1, substitution2, ssubstitution3, substitution4);
655  ProtectedObject p(substitutions);
656  this->raiseException(errcode, OREF_NULL, substitutions, OREF_NULL);
657 }
658 
660  wholenumber_t errcode, /* REXX error code */
661  const char *string ) /* single string sustitution parm */
662 /******************************************************************************/
663 /* Function: Raise an error using a single REXX character string only */
664 /* as a substitution parameter */
665 /******************************************************************************/
666 {
667  /* convert and forward along */
668  this->reportAnException(errcode, new_string(string));
669 }
670 
671 
673  wholenumber_t errcode, /* REXX error code */
674  const char *string1,
675  const char *string2)
676 /******************************************************************************/
677 /* Function: Raise an error using a single REXX character string only */
678 /* as a substitution parameter */
679 /******************************************************************************/
680 {
681  /* convert and forward along */
682  RexxString *sstring1 = new_string(string1);
683  ProtectedObject pstring1(sstring1);
684  RexxString *sstring2 = new_string(string2);
685  ProtectedObject pstring2(sstring2);
686  this->reportAnException(errcode, sstring1, sstring2);
687 }
688 
690  wholenumber_t errcode, /* REXX error code */
691  const char *string1,
692  const char *string2,
693  wholenumber_t integer)
694 /******************************************************************************/
695 /* Function: Raise an error using a single REXX character string only */
696 /* as a substitution parameter */
697 /******************************************************************************/
698 {
699  /* convert and forward along */
700  RexxString *sstring1 = new_string(string1);
701  ProtectedObject pstring1(sstring1);
702  RexxString *sstring2 = new_string(string2);
703  ProtectedObject pstring2(sstring2);
704  RexxInteger *iinteger = new_integer(integer);
705  ProtectedObject pinteger(iinteger);
706  this->reportAnException(errcode, sstring1, sstring2, iinteger);
707 }
708 
710  wholenumber_t errcode, /* REXX error code */
711  const char *string, /* single string sustitution parm */
712  wholenumber_t integer ) /* single integer substitution parm */
713 /******************************************************************************/
714 /* Function: Raise an error using a single REXX character string only */
715 /* as a substitution parameter */
716 /******************************************************************************/
717 {
718  /* convert and forward along */
719  RexxString *sstring = new_string(string);
720  ProtectedObject pstring(sstring);
721  RexxInteger *iinteger = new_integer(integer);
722  ProtectedObject pinteger(iinteger);
723  this->reportAnException(errcode, sstring, iinteger);
724 }
725 
727  wholenumber_t errcode, /* REXX error code */
728  const char *string, /* string value sustitution parm */
729  wholenumber_t integer, /* single integer substitution parm */
730  RexxObject *obj) /* and object sub parm */
731 /******************************************************************************/
732 /* Function: Raise an error using a single REXX character string only */
733 /* as a substitution parameter */
734 /******************************************************************************/
735 {
736  /* convert and forward along */
737  RexxString *sstring = new_string(string);
738  ProtectedObject pstring(sstring);
739  RexxInteger *iinteger = new_integer(integer);
740  ProtectedObject pinteger(iinteger);
741  this->reportAnException(errcode, sstring, iinteger, obj);
742 }
743 
745  wholenumber_t errcode, /* REXX error code */
746  RexxObject *obj1 , /* object value sustitution parm */
747  wholenumber_t integer, /* single integer substitution parm */
748  RexxObject *obj2) /* and object sub parm */
749 /******************************************************************************/
750 /* Function: Raise an error using a single REXX character string only */
751 /* as a substitution parameter */
752 /******************************************************************************/
753 {
754  /* convert and forward along */
755  RexxInteger *iinteger = new_integer(integer);
756  ProtectedObject pinteger(iinteger);
757  this->reportAnException(errcode, obj1, iinteger, obj2);
758 }
759 
761  wholenumber_t errcode, /* REXX error code */
762  const char *string, /* string value sustitution parm */
763  RexxObject *obj, /* and object sub parm */
764  wholenumber_t integer) /* single integer substitution parm */
765 /******************************************************************************/
766 /* Function: Raise an error using a single REXX character string only */
767 /* as a substitution parameter */
768 /******************************************************************************/
769 {
770  /* convert and forward along */
771  RexxString *sstring = new_string(string);
772  ProtectedObject pstring(sstring);
773  RexxInteger *iinteger = new_integer(integer);
774  ProtectedObject pinteger(iinteger);
775  this->reportAnException(errcode, sstring, obj, iinteger);
776 }
777 
779  wholenumber_t errcode, /* REXX error code */
780  const char *string, /* string value sustitution parm */
781  RexxObject *obj1, /* and object sub parm */
782  wholenumber_t integer, /* single integer substitution parm */
783  RexxObject *obj2)
784 /******************************************************************************/
785 /* Function: Raise an error using a single REXX character string only */
786 /* as a substitution parameter */
787 /******************************************************************************/
788 {
789  /* convert and forward along */
790  RexxString *sstring = new_string(string);
791  ProtectedObject pstring(sstring);
792  RexxInteger *iinteger = new_integer(integer);
793  ProtectedObject pinteger(iinteger);
794  this->reportAnException(errcode, sstring, obj1, iinteger, obj2);
795 }
796 
798  wholenumber_t errcode, /* REXX error code */
799  RexxObject *obj, /* object value sustitution parm */
800  const char *string, /* and object sub parm */
801  wholenumber_t integer) /* single integer substitution parm */
802 /******************************************************************************/
803 /* Function: Raise an error using a single REXX character string only */
804 /* as a substitution parameter */
805 /******************************************************************************/
806 {
807  /* convert and forward along */
808  RexxString *sstring = new_string(string);
809  ProtectedObject pstring(sstring);
810  RexxInteger *iinteger = new_integer(integer);
811  ProtectedObject pinteger(iinteger);
812  this->reportAnException(errcode, obj, sstring, iinteger);
813 }
814 
816  wholenumber_t errcode, /* REXX error code */
817  RexxObject *obj, /* and object sub parm */
818  wholenumber_t integer) /* single integer substitution parm */
819 /******************************************************************************/
820 /* Function: Raise an error using a single REXX character string only */
821 /* as a substitution parameter */
822 /******************************************************************************/
823 {
824  /* convert and forward along */
825  RexxInteger *iinteger = new_integer(integer);
826  ProtectedObject pinteger(iinteger);
827  this->reportAnException(errcode, obj, iinteger);
828 }
829 
831  wholenumber_t errcode, /* REXX error code */
832  RexxObject *obj, /* and object sub parm */
833  const char *string) /* string value sustitution parm */
834 /******************************************************************************/
835 /* Function: Raise an error using a single REXX character string only */
836 /* as a substitution parameter */
837 /******************************************************************************/
838 {
839  /* convert and forward along */
840  RexxString *sstring = new_string(string);
841  ProtectedObject pstring(sstring);
842  this->reportAnException(errcode, obj, sstring);
843 }
844 
846  wholenumber_t errcode, /* REXX error code */
847  const char *string, /* string value sustitution parm */
848  RexxObject *obj) /* and object sub parm */
849 /******************************************************************************/
850 /* Function: Raise an error using a single REXX character string only */
851 /* as a substitution parameter */
852 /******************************************************************************/
853 {
854  /* convert and forward along */
855  RexxString *sstring = new_string(string);
856  ProtectedObject pstring(sstring);
857  this->reportAnException(errcode, sstring, obj);
858 }
859 
861  wholenumber_t errcode, /* REXX error code */
862  const char *string, /* string value sustitution parm */
863  RexxObject *obj1, /* and object sub parm */
864  RexxObject *obj2)
865 /******************************************************************************/
866 /* Function: Raise an error using a single REXX character string only */
867 /* as a substitution parameter */
868 /******************************************************************************/
869 {
870  /* convert and forward along */
871  RexxString *sstring = new_string(string);
872  ProtectedObject pstring(sstring);
873  this->reportAnException(errcode, sstring, obj1, obj2);
874 }
875 
877  wholenumber_t errcode, /* REXX error code */
878  const char *string1, /* string value sustitution parm */
879  RexxObject *obj1, /* and object sub parm */
880  RexxObject *obj2,
881  const char *string2,
882  RexxObject *obj3)
883 /******************************************************************************/
884 /* Function: Raise an error using a single REXX character string only */
885 /* as a substitution parameter */
886 /******************************************************************************/
887 {
888  /* convert and forward along */
889  RexxString *sstring1 = new_string(string1);
890  ProtectedObject pstring1(sstring1);
891  RexxString *sstring2 = new_string(string2);
892  ProtectedObject pstring2(sstring2);
893  this->reportAnException(errcode, sstring1, obj1, obj2, sstring2, obj3);
894 }
895 
897  wholenumber_t errcode, /* REXX error code */
898  const char *string, /* string value sustitution parm */
899  RexxObject *obj1, /* and object sub parm */
900  RexxObject *obj2,
901  wholenumber_t integer)
902 /******************************************************************************/
903 /* Function: Raise an error using a single REXX character string only */
904 /* as a substitution parameter */
905 /******************************************************************************/
906 {
907  /* convert and forward along */
908  RexxString *sstring = new_string(string);
909  ProtectedObject pstring(sstring);
910  RexxInteger *iinteger = new_integer(integer);
911  ProtectedObject pinteger(iinteger);
912  this->reportAnException(errcode, sstring, obj1, obj2, iinteger);
913 }
914 
916  wholenumber_t errcode, /* REXX error code */
917  const char *string, /* string value sustitution parm */
918  RexxObject *obj1, /* and object sub parm */
919  RexxObject *obj2,
920  RexxObject *obj3)
921 /******************************************************************************/
922 /* Function: Raise an error using a single REXX character string only */
923 /* as a substitution parameter */
924 /******************************************************************************/
925 {
926  /* convert and forward along */
927  RexxString *sstring = new_string(string);
928  ProtectedObject pstring(sstring);
929  this->reportAnException(errcode, sstring, obj1, obj2, obj3);
930 }
931 
933  wholenumber_t errcode, /* REXX error code */
934  const char *string, /* string value sustitution parm */
935  RexxObject *obj1, /* and object sub parm */
936  RexxObject *obj2,
937  RexxObject *obj3,
938  wholenumber_t integer)
939 /******************************************************************************/
940 /* Function: Raise an error using a single REXX character string only */
941 /* as a substitution parameter */
942 /******************************************************************************/
943 {
944  /* convert and forward along */
945  RexxString *sstring = new_string(string);
946  ProtectedObject pstring(sstring);
947  RexxInteger *iinteger = new_integer(integer);
948  ProtectedObject pinteger(iinteger);
949  this->reportAnException(errcode, sstring, obj1, obj2, obj3, iinteger);
950 }
951 
953  wholenumber_t errcode, /* REXX error code */
954  const char *string, /* string value sustitution parm */
955  RexxObject *obj1, /* and object sub parm */
956  RexxObject *obj2,
957  RexxObject *obj3,
958  RexxObject *obj4)
959 /******************************************************************************/
960 /* Function: Raise an error using a single REXX character string only */
961 /* as a substitution parameter */
962 /******************************************************************************/
963 {
964  /* convert and forward along */
965  RexxString *sstring = new_string(string);
966  ProtectedObject pstring(sstring);
967  this->reportAnException(errcode, sstring, obj1, obj2, obj3, obj4);
968 }
969 
971  wholenumber_t errcode, /* REXX error code */
972  wholenumber_t integer ) /* single integer substitution parm */
973 /******************************************************************************/
974 /* Function: Raise an error using a single REXX integer value only */
975 /* as a substitution parameter */
976 /******************************************************************************/
977 {
978  /* convert and forward along */
979  RexxInteger *iinteger = new_integer(integer);
980  ProtectedObject pinteger(iinteger);
981  this->reportAnException(errcode, iinteger);
982 }
983 
985  wholenumber_t errcode, /* REXX error code */
986  wholenumber_t integer, /* single integer substitution parm */
987  wholenumber_t integer2) /* single integer substitution parm */
988 /******************************************************************************/
989 /* Function: Raise an error using a single REXX integer value only */
990 /* as a substitution parameter */
991 /******************************************************************************/
992 {
993  /* convert and forward along */
994  RexxInteger *iinteger = new_integer(integer);
995  ProtectedObject pinteger(iinteger);
996  RexxInteger *iinteger2 = new_integer(integer2);
997  ProtectedObject pinteger2(iinteger2);
998  this->reportAnException(errcode, iinteger, iinteger2);
999 }
1000 
1002  wholenumber_t errcode, /* REXX error code */
1003  wholenumber_t a1, /* single integer substitution parm */
1004  RexxObject * a2) /* single object substitution parm */
1005 /******************************************************************************/
1006 /* Function: Raise an error using a single REXX integer value only */
1007 /* as a substitution parameter */
1008 /******************************************************************************/
1009 {
1010  /* convert and forward along */
1011  RexxInteger *ia1 = new_integer(a1);
1012  ProtectedObject pa1(ia1);
1013  this->reportAnException(errcode, ia1, a2);
1014 }
1015 
1016 
1017 /**
1018  * Raise an exception on the current activity.
1019  *
1020  * @param errcode The syntax error code.
1021  * @param description
1022  * The associated description string.
1023  * @param additional The message substitution parameters.
1024  * @param result The message result.
1025  */
1026 void RexxActivity::raiseException(wholenumber_t errcode, RexxString *description, RexxArray *additional, RexxObject *result)
1027 /******************************************************************************/
1028 /* This routine is used for SYNTAX conditions only. */
1029 /* */
1030 /* The inserts are passed as objects because that happens to be more */
1031 /* convenient for the calling code in the two cases where this facility */
1032 /* is used. */
1033 /* */
1034 /* NOTE: The building of the excepption obejct (EXOBJ) has been re-arranged */
1035 /* so that a garbage collection in the middle of building traceBack/etc */
1036 /* doesn't clean up the newly built objects. SO we create exobj early on */
1037 /* save it, and add newlly built objects to exobj as we go. */
1038 /******************************************************************************/
1039 {
1040  // during error processing, we need to request the string value of message
1041  // substitution objects. It is possible that the string process will also
1042  // cause a syntax error, resulting in a recursion loop. We snip that off here,
1043  // by disallowing a nested error condition.
1044  if (requestingString)
1045  {
1046  throw RecursiveStringError;
1047  }
1048 
1049  RexxActivationBase *topFrame = this->getTopStackFrame();
1050 
1051  RexxActivation *activation = this->getCurrentRexxFrame(); /* get the current activation */
1052  // if we're raised within a real Rexx context, we need to deal with forwarded
1053  // frames
1054  if (topFrame == activation)
1055  {
1056  // unwind the stack until we find
1057  while (activation != OREF_NULL && activation->isForwarded())
1058  {
1059  // terminate and remove this stack frame
1060  popStackFrame(activation);
1061  // grab the new current frame
1062  activation = this->getCurrentRexxFrame();
1063  }
1064  }
1065  else {
1066  activation = NULL; // raised from a native context, don't add to stack trace
1067  }
1068 
1069  this->conditionobj = createExceptionObject(errcode, description, additional, result);
1070 
1071  /* process as common condition */
1072  if (!this->raiseCondition(conditionobj))
1073  {
1074  /* fill in the propagation status */
1075  conditionobj->put(TheTrueObject, OREF_PROPAGATED);
1076  // if we have an Rexx context to work with, unwind to that point,
1077  if (activation != OREF_NULL)
1078  {
1079  // unwind the frame to this point
1080  unwindToFrame(activation);
1081  popStackFrame(activation); // remove it from the stack
1082  }
1083  this->raisePropagate(conditionobj); /* pass on down the chain */
1084  }
1085 }
1086 
1087 
1088 /**
1089  * Create a new error exception object.
1090  *
1091  * @param errcode The error code to raise.
1092  * @param description
1093  * The description string.
1094  * @param additional Message substitution information.
1095  * @param result The result object.
1096  *
1097  * @return The created exception dictionary.
1098  */
1100  RexxString *description, RexxArray *additional, RexxObject *result )
1101 /******************************************************************************/
1102 /* This routine is used for SYNTAX conditions only. */
1103 /* */
1104 /* The inserts are passed as objects because that happens to be more */
1105 /* convenient for the calling code in the two cases where this facility */
1106 /* is used. */
1107 /* */
1108 /* NOTE: The building of the exception obejct (EXOBJ) has been re-arranged */
1109 /* so that a garbage collection in the middle of building traceBack/etc */
1110 /* doesn't clean up the newly built objects. SO we create exobj early on */
1111 /* save it, and add newly built objects to exobj as we go. */
1112 /******************************************************************************/
1113 {
1114  /* All error detection done. we can */
1115  /* build and save exobj now. */
1116  /* get an exception directory */
1118  // this is the anchor for anything else
1119  ProtectedObject p(exobj);
1120 
1121  wholenumber_t primary = (errcode / 1000) * 1000; /* get the primary message number */
1122 
1123  char work[32];
1124  /* format the number (string) into */
1125  /* work buffer. */
1126  sprintf(work,"%ld.%1ld", errcode/1000, errcode - primary);
1127  RexxString *code = new_string(work); /* get the formatted code */
1128  exobj->put(code, OREF_CODE);
1129 
1130  wholenumber_t newVal = primary/1000;
1131  RexxInteger *rc = new_integer(newVal); /* get the primary message number */
1132  exobj->put(rc, OREF_RC); /* add the return code */
1133  /* get the primary message text */
1134  RexxString *errortext = SystemInterpreter::getMessageText(primary);
1135  if (errortext == OREF_NULL) /* no corresponding message */
1136  {
1137  /* this is an error */
1139  }
1140  exobj->put(errortext, OREF_ERRORTEXT);
1141 
1142  // handle the message substitution values (raw form)
1143  if (additional == OREF_NULL)
1144  {
1145  /* use a zero size array */
1146  additional = new_array((size_t)0);
1147  }
1148  // add this in
1149  exobj->put(additional, OREF_ADDITIONAL);
1150 
1151  if (primary != errcode) /* have a secondary message to issue?*/
1152  {
1153  /* retrieve the secondary message */
1154  RexxString *message = buildMessage(errcode, additional);
1155  /* replace the original message text */
1156  exobj->put(message, OREF_NAME_MESSAGE);
1157  }
1158  else
1159  {
1160  /* don't give a secondary message */
1161  /* fill in the decimal error code */
1162  exobj->put(TheNilObject, OREF_NAME_MESSAGE);
1163  }
1164 
1165  // the description string (rare for exceptions)
1166  if (description == OREF_NULL) /* no description? */
1167  {
1168  // use an explicit null string
1169  exobj->put(OREF_NULLSTRING, OREF_DESCRIPTION);
1170  }
1171  else
1172  {
1173  exobj->put(description, OREF_DESCRIPTION);
1174  }
1175 
1176  if (result != OREF_NULL)
1177  {
1178  exobj->put(result, OREF_RESULT);
1179  }
1180 
1181  // add in all location-specific information
1183 
1184  // the condition name is always SYNTAX
1185  exobj->put(OREF_SYNTAX, OREF_CONDITION);
1186  /* fill in the propagation status */
1187  exobj->put(TheFalseObject, OREF_PROPAGATED);
1188 
1189  return exobj;
1190 }
1191 
1192 
1193 /**
1194  * Add program location-specific information to a condition object.
1195  *
1196  * @param exobj The exception object being constructed.
1197  */
1199 {
1200  // create lists for both the stack frames and the traceback lines
1201  RexxList *stackFrames = new_list();
1202  /* add to the exception object */
1203  exobj->put(stackFrames, OREF_STACKFRAMES);
1204 
1205  RexxList *traceback = new_list(); /* create a traceback list */
1206  /* add to the exception object */
1207  exobj->put(traceback, OREF_TRACEBACK);
1208 
1210 
1211  RexxSource *source = OREF_NULL;
1212  StackFrameClass *firstFrame = OREF_NULL;
1213 
1214  while (frame != NULL)
1215  {
1216  StackFrameClass *stackFrame = frame->createStackFrame();
1217  // save the topmost source object we can find for error reporting
1218  if (source == OREF_NULL && frame->getSource() != OREF_NULL)
1219  {
1220  firstFrame = stackFrame;
1221  source = frame->getSource();
1222  }
1223  stackFrames->append(stackFrame);
1224  traceback->append(stackFrame->getTraceLine());
1225  frame = frame->next;
1226  }
1227 
1228  if (firstFrame != OREF_NULL)
1229  {
1230  RexxObject *lineNumber = firstFrame->getLine();
1231  if (lineNumber != TheNilObject)
1232  {
1233  // add the line number information
1234  exobj->put(lineNumber, OREF_POSITION);
1235  }
1236  }
1237 
1238  // if we have source, and this is not part of the interpreter image,
1239  // add program information
1240  if (source != OREF_NULL && !source->isOldSpace()) /* have source for this? */
1241  {
1242  exobj->put(source->getProgramName(), OREF_PROGRAM);
1243  exobj->put(source->getPackage(), OREF_PACKAGE);
1244  }
1245  else
1246  {
1247  // if not available, then this is explicitly a NULLSTRING.
1248  exobj->put(OREF_NULLSTRING, OREF_PROGRAM);
1249  }
1250 }
1251 
1252 
1253 /**
1254  * Generate a list of stack frames for an Exception object.
1255  *
1256  * @param skipFirst Determines if we should skip the first frame. Used primarily
1257  * for the RexxContext stackFrames() method to avoid returning
1258  * the stackframes method as the first item.
1259  *
1260  * @return An array of the stack frames in the call context.
1261  */
1263 {
1264  // create lists for both the stack frames and the traceback lines
1265  RexxArray *stackFrames = new_array((size_t)0);
1266  ProtectedObject p(stackFrames);
1267 
1269 
1270  while (frame != NULL)
1271  {
1272  // if asked to skip the first frame, just turn the flag off
1273  // and go around again
1274  if (skipFirst)
1275  {
1276  skipFirst = false;
1277  }
1278  else {
1279  StackFrameClass *stackFrame = frame->createStackFrame();
1280  stackFrames->append(stackFrame);
1281  }
1282  frame = frame->next;
1283  }
1284  return stackFrames;
1285 }
1286 
1287 /**
1288  * Build a message and perform the indicated substitutions.
1289  *
1290  * @param messageCode
1291  * The target message code
1292  * @param substitutions
1293  * An array of substitution values
1294  *
1295  * @return The message with the substitution values inserted.
1296  */
1298 {
1299  /* retrieve the secondary message */
1300  RexxString *message = SystemInterpreter::getMessageText(messageCode);
1301  if (message == OREF_NULL) /* no corresponding message */
1302  {
1303  /* this is an error */
1305  }
1306  /* do required substitutions */
1307  return messageSubstitution(message, substitutions);
1308 }
1309 
1310 
1312  RexxString *message, /* REXX error message */
1313  RexxArray *additional ) /* substitution information */
1314 /******************************************************************************/
1315 /* Function: Perform any required message substitutions on the secondary */
1316 /* error message. */
1317 /******************************************************************************/
1318 {
1319  size_t substitutions = additional->size(); /* get the substitution count */
1320  RexxString *newmessage = OREF_NULLSTRING; /* start with a null string */
1321  ProtectedObject p_newmessage(newmessage);
1322  /* loop through and substitute values*/
1323  for (size_t i = 1; i <= substitutions; i++)
1324  {
1325  /* search for a substitution */
1326  sizeC_t subposition = message->pos(OREF_AND, 0);
1327  if (subposition == 0) /* not found? */
1328  {
1329  break; /* get outta here... */
1330  }
1331  /* get the leading part */
1332  RexxString *front = message->extractC(0, subposition - 1);
1333  ProtectedObject p_front(front);
1334  /* pull off the remainder */
1335  RexxString *back = message->extractC(subposition + 1, message->getCLength() - (subposition + 1));
1336  ProtectedObject p_back(back);
1337  /* get the descriptor position */
1338  codepoint_t selector = message->getCharC(subposition);
1339  /* not a good number? */
1340  RexxString *stringVal = OREF_NULLSTRING;
1341  if (selector < '0' || selector > '9') // todo m17n : DecimalDigitNumber (careful : 'U+0BEF TAMIL DIGIT NINE \u0BEF 9)
1342  {
1343  /* use a default message */
1344  stringVal = new_string("<BAD MESSAGE>"); /* must be stringValue, not value, otherwise trap */
1345  }
1346  else
1347  {
1348  selector -= '0'; /* convert to a number */ // todo m17n : DecimalDigitNumber (careful : 'U+0BEF TAMIL DIGIT NINE \u0BEF 9)
1349  // still in range?
1350  if (selector <= substitutions) /* out of our range? */
1351  {
1352  RexxObject *value = additional->get(selector);
1353  if (value != OREF_NULL) /* have a value? */
1354  {
1355  /* set the reentry flag */
1356  this->requestingString = true;
1357  this->stackcheck = false; /* disable the checking */
1358  // save the actitivation level in case there's an error unwind for an unhandled
1359  // exception;
1360  size_t activityLevel = getActivationLevel();
1361  /* now protect against reentry */
1362  try
1363  {
1364  /* force to character form */
1365  stringVal = value->stringValue();
1366  }
1367  catch (ActivityException)
1368  {
1369  stringVal = value->defaultName();
1370  }
1371 
1372  // make sure we get restored to the same base activation level.
1373  restoreActivationLevel(activityLevel);
1374  /* we're safe again */
1375  this->requestingString = false;
1376  this->stackcheck = true; // reenable the checking
1377  }
1378  }
1379  }
1380  ProtectedObject p_stringval(stringVal);
1381  /* accumulate the front part */
1382  RexxString *front_stringVal = front->concat(stringVal);
1383  ProtectedObject p_front_stringVal(front_stringVal);
1384  newmessage = newmessage->concat(front_stringVal);
1385  p_newmessage = newmessage;
1386  message = back; /* replace with the remainder */
1387  }
1388  /* add on any remainder */
1389  newmessage = newmessage->concat(message);
1390  return newmessage; /* return the message */
1391 }
1392 
1393 /**
1394  * Reraise an exception object in a prior context.
1395  *
1396  * @param exobj The exception object with the syntax information.
1397  */
1399 {
1400  RexxActivation *activation = this->getCurrentRexxFrame();/* get the current activation */
1401  /* have a target activation? */
1402  if (activation != OREF_NULL)
1403  {
1404  RexxSource *source = activation->getSourceObject();
1405  // set the position and program name
1406  exobj->put(new_integer(activation->currentLine()), OREF_POSITION);
1407  exobj->put(source->getProgramName(), OREF_PROGRAM);
1408  exobj->put(source->getPackage(), OREF_PACKAGE);
1409  }
1410  else
1411  {
1412  exobj->remove(OREF_POSITION); /* remove the position */
1413  exobj->remove(OREF_PROGRAM); /* remove the program name */
1414  exobj->remove(OREF_PACKAGE); /* remove the program name */
1415  }
1416 
1417  RexxObject *errorcode = exobj->at(OREF_CODE); /* get the error code */
1418  /* convert to a decimal */
1419  wholenumber_t errornumber = Interpreter::messageNumber((RexxString *)errorcode);
1420  /* get the primary message number */
1421  wholenumber_t primary = (errornumber / 1000) * 1000;
1422  if (errornumber != primary)
1423  { /* have an actual secondary message? */
1424  char work[10]; /* temp buffer for formatting */
1425  /* format the number (string) into */
1426  /* work buffer. */
1427  sprintf(work,"%1ld%3.3ld", errornumber/1000, errornumber - primary);
1428  errornumber = atol(work); /* convert to a long value */
1429  /* retrieve the secondary message */
1430  RexxString *message = SystemInterpreter::getMessageText(errornumber);
1431  /* Retrieve any additional parameters*/
1432  RexxArray *additional = (RexxArray *)exobj->at(OREF_ADDITIONAL);
1433  /* do required substitutions */
1434  message = this->messageSubstitution(message, additional);
1435  /* replace the original message text */
1436  exobj->put(message, OREF_NAME_MESSAGE);
1437  }
1438  this->raisePropagate(exobj); /* pass on down the chain */
1439 }
1440 
1442  RexxDirectory *conditionObj ) /* condition descriptive information */
1443 /******************************************************************************/
1444 /* Function: Propagate a condition down the chain of activations */
1445 /******************************************************************************/
1446 {
1447  /* get the condition */
1448  RexxString *condition = (RexxString *)conditionObj->at(OREF_CONDITION);
1449  RexxActivationBase *activation = getTopStackFrame(); /* get the current activation */
1450 
1451  /* loop to the top of the stack */
1452  while (activation != OREF_NULL)
1453  {
1454  /* give this one a chance to trap */
1455  /* (will never return for trapped */
1456  /* PROPAGATE conditions) */
1457  activation->trap(condition, conditionObj);
1458  /* this is a propagated condition */
1459  conditionObj->put(TheTrueObject, OREF_PROPAGATED);
1460  // if we've unwound to the stack base and not been trapped, we need
1461  // to fall through to the kill processing. The stackbase should have trapped
1462  // this. We never cleanup the stackbase activation though.
1463  if (activation->isStackBase())
1464  {
1465  break;
1466  }
1467  // clean up this stack frame
1468  popStackFrame(activation);
1469  activation = this->getTopStackFrame(); /* get the sender's sender */
1470  }
1471  /* now kill the activity, using the */
1472  this->kill(conditionObj); /* imbedded description object */
1473 }
1474 
1476  /* display exception object info */
1477  /* target exception object */
1478 /******************************************************************************/
1479 /* Function: Display information from an exception object */
1480 /******************************************************************************/
1481 {
1482  /* get the traceback info */
1483  RexxList *trace_backList = (RexxList *)exobj->at(OREF_TRACEBACK);
1484  if (trace_backList != OREF_NULL) /* have a traceback? */
1485  {
1486  /* convert to an array */
1487  RexxArray *trace_back = trace_backList->makeArray();
1488  ProtectedObject p(trace_back);
1489  /* get the traceback size */
1490  size_t tracebackSize = trace_back->size();
1491 
1492  for (size_t i = 1; i <= tracebackSize; i++) /* loop through the traceback starttrc */
1493  {
1494  RexxString *text = (RexxString *)trace_back->get(i);
1495  /* have a real line? */
1496  if (text != OREF_NULL && text != TheNilObject)
1497  {
1498  /* write out the line */
1499  this->traceOutput(currentRexxFrame, text);
1500  }
1501  }
1502  }
1503  RexxObject *rc = exobj->at(OREF_RC); /* get the error code */
1504  /* get the message number */
1506  /* get the header */
1508  if (text == OREF_NULL) /* no header available? */
1509  {
1510  /* get the leading part */
1512  }
1513  else /* add to the message text */
1514  {
1516  }
1517  ProtectedObject p_text(text);
1518  /* get the name of the program */
1519  RexxString *programname = (RexxString *)exobj->at(OREF_PROGRAM);
1520  /* add on the error number */
1521  RexxString *rcString = REQUEST_STRING(rc);
1522  ProtectedObject p_rcString(rcString);
1523  text = text->concatWith(rcString, ' ');
1524  p_text = text;
1525  /* if program exists, add the name */
1526  /* of the program to the message */
1527  if (programname != OREF_NULL && programname != OREF_NULLSTRING)
1528  {
1529  /* add on the "running" part */
1531  p_text = text;
1532  /* add on the program name */
1533  text = text->concatWith(programname, ' ');
1534  p_text = text;
1535  /* Get the position/Line number info */
1536  RexxObject *position = exobj->at(OREF_POSITION);
1537  if (position != OREF_NULL) /* Do we have position/Line no info? */
1538  {
1539  /* Yes, add on the "line" part */
1541  p_text = text;
1542  /* add on the line number */
1543  RexxString *positionString = REQUEST_STRING(position);
1544  ProtectedObject p_positionString(positionString);
1545  text = text->concatWith(positionString, ' ');
1546  p_text = text;
1547  /* add on the ": " */
1548  }
1549  }
1550  text = text->concatWithCstring(": ");
1551  p_text = text;
1552  /* and finally the error message */
1553  text = text->concat((RexxString *)exobj->at(OREF_ERRORTEXT));
1554  p_text = text;
1555  /* write out the line */
1556  this->traceOutput(currentRexxFrame, text);
1557  /* get the secondary message */
1558  RexxString *secondary = (RexxString *)exobj->at(OREF_NAME_MESSAGE);
1559  /* have a real message? */
1560  if (secondary != OREF_NULL && secondary != (RexxString *)TheNilObject)
1561  {
1562  rc = exobj->at(OREF_CODE); /* get the error code */
1563  /* get the message number */
1564  errorCode = Interpreter::messageNumber((RexxString *)rc);
1565  /* get the header */
1566  text = SystemInterpreter::getMessageHeader(errorCode);
1567  if (text == OREF_NULL) /* no header available? */
1568  {
1569  /* get the leading part */
1571  }
1572  else /* add to the message text */
1573  {
1575  }
1576  p_text = text;
1577  /* add on the error number */
1578  text = text->concatWith((RexxString *)rc, ' ');
1579  p_text = text;
1580  /* add on the ": " */
1581  text = text->concatWithCstring(": ");
1582  p_text = text;
1583  /* and finally the error message */
1584  text = text->concat(secondary);
1585  p_text = text;
1586  /* write out the line */
1587  this->traceOutput(currentRexxFrame, text);
1588  }
1589  return TheNilObject; /* just return .nil */
1590 }
1591 
1593  /* display exception object info */
1594  /* target exception object */
1595 /******************************************************************************/
1596 /* Function: Display information from an exception object */
1597 /******************************************************************************/
1598 {
1599  RexxString *secondary; /* secondary message */
1600  RexxString *text; /* constructed final message */
1601  ProtectedObject p_text;
1602 
1603  /* get the leading part */
1605  /* add on the error number */
1606  RexxString *rcString = REQUEST_STRING(exobj->at(OREF_RC));
1607  ProtectedObject p_rcString(rcString);
1608  text = text->concatWith(rcString, ' ');
1609  p_text = text;
1610  /* add on the ": " */
1611  text = text->concatWithCstring(": ");
1612  p_text = text;
1613  /* and finally the error message */
1614  text = text->concatWith((RexxString *)exobj->at(OREF_ERRORTEXT), ' ');
1615  p_text = text;
1616  /* write out the line */
1617  this->traceOutput(currentRexxFrame, text);
1618  /* get the secondary message */
1619  secondary = (RexxString *)exobj->at(OREF_NAME_MESSAGE);
1620  /* have a real message? */
1621  if (secondary != OREF_NULL && secondary != (RexxString *)TheNilObject) {
1622  /* get the leading part */
1624  /* add on the error number */
1625  text = text->concatWith((RexxString *)exobj->at(OREF_CODE), ' ');
1626  p_text = text;
1627  /* add on the ": " */
1628  text = text->concatWithCstring(": ");
1629  p_text = text;
1630  /* and finally the error message */
1631  text = text->concat(secondary);
1632  p_text = text;
1633  /* write out the line */
1634  this->traceOutput(getCurrentRexxFrame(), text);
1635  }
1636  return TheNilObject; /* just return .nil */
1637 }
1638 
1639 void RexxActivity::live(size_t liveMark)
1640 /******************************************************************************/
1641 /* Function: Normal garbage collection live marking */
1642 /******************************************************************************/
1643 {
1644  memory_mark(this->activations);
1645  memory_mark(this->topStackFrame);
1647  memory_mark(this->conditionobj);
1648  memory_mark(this->requiresTable);
1649  memory_mark(this->waitingObject);
1652 
1653  /* have the frame stack do its own marking. */
1654  frameStack.live(liveMark);
1655  // mark any protected objects we've been watching over
1656 
1658  while (p != NULL)
1659  {
1661  p = p->next;
1662  }
1663 }
1665 /******************************************************************************/
1666 /* Function: Generalized object marking */
1667 /******************************************************************************/
1668 {
1677 
1678  /* have the frame stack do its own marking. */
1679  frameStack.liveGeneral(reason);
1680 
1682  while (p != NULL)
1683  {
1685  p = p->next;
1686  }
1687 }
1688 
1690 /******************************************************************************/
1691 /* Function: Flatten an object */
1692 /******************************************************************************/
1693 {
1694  /* Activities don't get moved, */
1695  /* we just return OREF_NULL. we may */
1696  /* create a special proxy for this */
1697  /* to re-establish an activation on */
1698  /* system. */
1699  return;
1700 }
1701 
1702 
1703 
1705 /******************************************************************************/
1706 /* Function: Release an activity to run */
1707 /******************************************************************************/
1708 {
1709  guardsem.post(); /* and the guard semaphore */
1710  runsem.post(); /* post the run semaphore */
1711  SysActivity::yield(); /* yield the thread */
1712 }
1713 
1714 
1715 
1716 /**
1717  * Run a message object on a spawned thread.
1718  *
1719  * @param target The target message object.
1720  */
1722 {
1723  dispatchMessage = target;
1724 
1725  guardsem.post(); /* and the guard semaphore */
1726  runsem.post(); /* post the run semaphore */
1727  SysActivity::yield(); /* yield the thread */
1728 }
1729 
1730 
1731 /**
1732  * Check the activation stack to see if we need to expand the size.
1733  */
1735 {
1736  // no room for a new stack frame? need to expand the stack
1737  if (this->stackFrameDepth == this->activationStackSize)
1738  {
1739  // allocate a larger stack
1741  // now copy all of the entries over to the new frame stack
1742  for (size_t i = this->activationStackSize; i != 0; i--)
1743  {
1744  newstack->push(this->activations->peek(i-1));
1745  }
1746  // update the frame information
1747  this->activations = newstack;
1749  }
1750 }
1751 
1752 
1753 /**
1754  * Update the top of the stack markers after a push or a pop
1755  * operation on the stack frame.
1756  */
1758 {
1759  // we have a new top entry...get this from the stack and adjust
1760  // the markers appropriately
1762  // the new activation is the new top and there may or may not be
1763  // a rexx context to deal with
1765 
1766  // update the numeric settings
1768  // this should be tree, but make sure we don't clobber the global settings accidentally
1770  {
1772  }
1773 }
1774 
1775 
1776 /**
1777  * Push a Rexx code activation on to the stack frame.
1778  *
1779  * @param new_activation
1780  * The new activation to add.
1781  */
1783 {
1784  checkActivationStack(); // make sure the stack is not filled
1785  // push on to the stack and bump the depth
1786  activations->push((RexxObject *)new_activation);
1787  stackFrameDepth++;
1788  // update the frame information.
1789  // if we're not creating a new frame set, link up the new frame with its predecessor
1790  if (!new_activation->isStackBase())
1791  {
1792  new_activation->setPreviousStackFrame(topStackFrame);
1793  }
1795 }
1796 
1797 
1798 /**
1799  * Create a new set of activation stack frames on this activity.
1800  * The new frame will have a RexxNativeActivation that's marked
1801  * as a stack base frame. Additional call frames are pushed on
1802  * top of that activation. Any operations that unwind the
1803  * stack frames will stop when they hit the activation stack
1804  * base.
1805  */
1807 {
1808  // make sure we have a new stack
1810  // This is a root activation that will allow API functions to be called
1811  // on this thread without having an active bit of ooRexx code first.
1813  new_activation->setStackBase();
1814  // create a new root element on the stack and bump the depth indicator
1815  activations->push((RexxObject *)new_activation);
1816  stackFrameDepth++;
1817  // update the frame information.
1819 }
1820 
1821 
1822 /**
1823  * Pop the top activation from the frame stack.
1824  *
1825  * @param reply Indicates we're popping the frame for a reply operation. In that
1826  * case, we can't return the frame to the activation cache.
1827  */
1829 {
1830  // pop off the top elements and reduce the depth
1831  RexxActivationBase *poppedStackFrame = (RexxActivationBase *)activations->fastPop();
1832  stackFrameDepth--;
1833 
1834  // did we just pop off the last element of a stack frame? This should not happen, so
1835  // push it back on to the stack
1836  if (poppedStackFrame->isStackBase())
1837  {
1838  activations->push((RexxObject *)poppedStackFrame);
1839  stackFrameDepth++;
1840  }
1841  else
1842  {
1843  // update the frame information.
1845 
1846  // if this is not a reply operation and the frame we just removed is
1847  // a Rexx activation, we can just cache this.
1848  if (!reply)
1849  {
1850  // the popped stack frame might still be in the save stack, but can
1851  // also contain pointers back to locations on the C stack. Make sure
1852  // that this never tries to mark anything in case of a garbage collection
1853  poppedStackFrame->setHasNoReferences();
1854  }
1855  }
1856 }
1857 
1858 
1860 {
1861  // make sure this frame is terminated first
1862  poppedStackFrame->termination();
1863  // ensure this never marks anything
1864  poppedStackFrame->setHasNoReferences();
1865 }
1866 
1867 
1868 /**
1869  * Pop entries off the stack frame upto and including the
1870  * target activation.
1871  *
1872  * @param target The target for the pop operation.
1873  */
1875 {
1876  RexxActivationBase *poppedStackFrame = (RexxActivationBase *)activations->fastPop();
1877  stackFrameDepth--;
1878  // pop off the top elements and reduce the depth
1879  while (poppedStackFrame != target)
1880  {
1881  // clean this up and potentially cache
1882  cleanupStackFrame(poppedStackFrame);
1883  poppedStackFrame = (RexxActivationBase *)activations->fastPop();
1884  stackFrameDepth--;
1885  }
1886 
1887  // clean this up and potentially cache
1888  cleanupStackFrame(poppedStackFrame);
1889  // update the frame information.
1891 }
1892 
1893 
1895 /******************************************************************************/
1896 /* Function: Remove an activation marker from the activity stack */
1897 /******************************************************************************/
1898 {
1899  // pop activations off until we find the one at the base of the stack.
1900  while (stackFrameDepth > 0)
1901  {
1902  // check the top activation. If it's a stack base item, then
1903  // we've reached the unwind point.
1904  RexxActivationBase *poppedActivation = (RexxActivationBase *)activations->fastPop();
1905  stackFrameDepth--;
1906  if (poppedActivation->isStackBase())
1907  {
1908  // at the very base of the activity, we keep a base item. If this
1909  // is the bottom stack frame here, then push it back on.
1910  if (stackFrameDepth == 0)
1911  {
1912  activations->push((RexxObject *)poppedActivation);
1913  stackFrameDepth++;
1914  }
1915  break;
1916  }
1917  }
1918 
1919  // update the frame information.
1921 }
1922 
1923 
1925 /******************************************************************************/
1926 /* Function: Remove an activation marker from the activity stack */
1927 /******************************************************************************/
1928 {
1929  // pop elements until we unwind to the target
1930  while (stackFrameDepth > depth)
1931  {
1932  activations->fastPop();
1933  stackFrameDepth--;
1934  }
1935 
1936  // update the frame information.
1938 }
1939 
1940 
1941 /**
1942  * Unwind to a particular stack frame, terminating each frame
1943  * in turn;
1944  *
1945  * @param frame The target frame
1946  */
1948 {
1949  RexxActivationBase *activation;
1950 
1951  /* unwind the activation stack */
1952  while ((activation = getTopStackFrame()) != frame)
1953  {
1954  activation->termination(); /* prepare the activation for termin */
1955  popStackFrame(false); /* pop the activation off the stack */
1956  }
1957 }
1958 
1959 
1960 /**
1961  * Set up an activity as a root activity used either for a main
1962  * interpreter thread or an attached thread.
1963  *
1964  * @param interpreter
1965  * The interpreter instance this thread belongs to.
1966  */
1968 {
1969  // associate this with the instance
1970  addToInstance(interpreter);
1971 
1972  // mark this as an attached activity
1973  attached = true;
1974  // This is a root activation that will allow API functions to be called
1975  // on this thread without having an active bit of ooRexx code first.
1977 }
1978 
1979 
1980 /**
1981  * Set up an activity as a root activity used either for a main
1982  * interpreter thread or an attached thread.
1983  *
1984  * @param interpreter
1985  * The interpreter instance this thread belongs to.
1986  */
1988 {
1989  // we're associated with this instance
1990  instance = interpreter;
1991  // create a thread context that we can hand out when needed.
1995 
1996  // go copy the exit definitions
1997  setupExits();
1998 }
1999 
2000 
2001 /**
2002  * Process for copying the exit definitions from the
2003  * hosting instance.
2004  */
2006 {
2007 
2008  // copy all of the system exits
2009  for (int i = 0; i < LAST_EXIT; i++)
2010  {
2011  sysexits[i] = instance->getExitHandler(i + 1);
2012  }
2013  // set the appropriate exit interlocks
2014  queryTrcHlt();
2015 }
2016 
2017 
2018 /**
2019  * Complete initialization of the thread context function
2020  * vector by filling in the constant objects.
2021  */
2023 {
2028 }
2029 
2030 
2031 /**
2032  * Detach a thread from the interpreter instance,
2033  */
2035 {
2036  instance->detachThread(this);
2037 }
2038 
2039 /**
2040  * Cleanup the resources for a detached activity, including
2041  * removing the suspended state from a pushed activity nest.
2042  */
2044 {
2045  // Undo this attached status
2046  instance = OREF_NULL;
2047  attached = false;
2048  // if there's a nesting situation, restore the activity to active state.
2049  if (nestedActivity != OREF_NULL)
2050  {
2051  nestedActivity->setSuspended(false);
2052  }
2053 }
2054 
2055 
2057 /******************************************************************************/
2058 /* Function: Release the kernel access because code is going to "leave" */
2059 /* the kernel. This prepares for this by adding a native */
2060 /* activation on to the stack to act as a server for the */
2061 /* external call. This way new native methods do not need to */
2062 /* be created just to get an activation created */
2063 /******************************************************************************/
2064 {
2065  // create new activation frame using the current Rexx frame (which can be null, but
2066  // is not likely to be).
2068  // this becomes the new top activation. We also turn on the variable pool for
2069  // this situation.
2070  this->pushStackFrame(new_activation);
2071  new_activation->enableVariablepool();
2072  // release the kernel in preparation for exiting
2073  releaseAccess();
2074 }
2075 
2076 
2078 /******************************************************************************/
2079 /* Function: Recover the kernel access and pop the native activation */
2080 /* created by activity_exit_kernel from the activity stack. */
2081 /******************************************************************************/
2082 {
2083  requestAccess(); /* get the kernel lock back */
2084  this->popStackFrame(false); /* pop the top activation */
2085 }
2086 
2087 
2089  RexxActivity *targetActivity) /* activity currently reserving */
2090 /******************************************************************************/
2091 /* Function: Check for a circular wait dead lock error */
2092 /******************************************************************************/
2093 {
2094  RexxActivity *owningActivity; /* activity owning the resource */
2095  /* currently waiting on something? */
2096  if (this->waitingObject != OREF_NULL) {
2097  /* waiting on a message object? */
2098  if (isOfClass(Message, this->waitingObject))
2099  /* get the activity message is on */
2100  owningActivity = ((RexxMessage *)this->waitingObject)->getActivity();
2101  else
2102  /* get the locking activity for vdict*/
2103  owningActivity = ((RexxVariableDictionary *)this->waitingObject)->getReservingActivity();
2104  /* have a circular wait */
2105  if (owningActivity == targetActivity)
2106  /* have a deaklock */
2108  if (owningActivity != OREF_NULL) /* have a real activity? */
2109  /* pass it along the chain */
2110  owningActivity->checkDeadLock(targetActivity);
2111  }
2112 }
2113 
2115  RexxObject *resource ) /* resource we are waiting on */
2116 /******************************************************************************/
2117 /* Function: Wait for a new run event to occur */
2118 /******************************************************************************/
2119 {
2120  runsem.reset(); /* clear the run semaphore */
2121  this->waitingObject = resource; /* save the waiting resource */
2122  releaseAccess(); /* release the kernel access */
2123  runsem.wait("RexxActivity::waitReserve", 0); /* wait for the run to be posted */
2124  requestAccess(); /* reaquire the kernel access */
2125 }
2126 
2128 /******************************************************************************/
2129 /* Function: Wait for a guard post event */
2130 /******************************************************************************/
2131 {
2132  releaseAccess(); /* release kernel access */
2133  guardsem.wait("RexxActivity::guardWait", 0); /* wait on the guard semaphore */
2134  requestAccess(); /* reaquire the kernel lock */
2135 }
2136 
2138 /******************************************************************************/
2139 /* Function: Post a guard expression wake up notice */
2140 /******************************************************************************/
2141 {
2142  guardsem.post(); /* OK for it to already be posted */
2143 }
2144 
2146 /******************************************************************************/
2147 /* Function: Clear a guard expression semaphore in preparation to perform a */
2148 /* guard wait */
2149 /******************************************************************************/
2150 {
2151  guardsem.reset(); /* set up for guard call */
2152 }
2153 
2155 /******************************************************************************/
2156 /* Function: Post an activities run semaphore */
2157 /******************************************************************************/
2158 {
2159  this->waitingObject = OREF_NULL; /* no longer waiting */
2160  runsem.post(); /* OK for it to already be posted */
2161 }
2162 
2164  RexxDirectory *conditionObj) /* associated "kill" object */
2165 /******************************************************************************/
2166 /* Function: Kill a running activity, */
2167 /******************************************************************************/
2168 {
2169  this->conditionobj = conditionObj; /* save the condition object */
2170  throw UnhandledCondition; // we have a fatal error condition
2171 }
2172 
2174 /******************************************************************************/
2175 /* Function: Relinquish to other system processes */
2176 /******************************************************************************/
2177 {
2179 }
2180 
2181 /**
2182  * Tap the current running activation on this activity to
2183  * give up control at the next reasonsable boundary.
2184  */
2186 {
2187  /* get the current activation */
2188  RexxActivation *activation = currentRexxFrame;
2189  // if we're in the context of Rexx code, request that it yield control
2190  if (activation != NULL)
2191  {
2192  activation->yield();
2193  }
2194 }
2195 
2196 
2197 /**
2198  * Tap the current running activation on this activity to halt
2199  * as soon as possible.
2200  *
2201  * @param d The description string for the halt.
2202  *
2203  * @return true if we have an activation to tell to stop, false if the
2204  * activity's not really working.
2205  */
2207 {
2208  /* get the current activation */
2209  RexxActivation *activation = currentRexxFrame;
2210  /* got an activation? */
2211  if (activation != NULL)
2212  {
2213  // please make it stop :-)
2214  return activation->halt(d);
2215  }
2216  return true;
2217 }
2218 
2219 
2220 /**
2221  * Tap the current running activation on this activity to halt
2222  * as soon as possible.
2223  *
2224  * @param d The description string for the halt.
2225  *
2226  * @return true if we have an activation to tell to stop, false if the
2227  * activity's not really working.
2228  */
2230 {
2231  /* get the current activation */
2232  RexxActivation *activation = currentRexxFrame;
2233  /* got an activation? */
2234  if (activation != NULL)
2235  {
2236  if (on) /* turning this on? */
2237  {
2238  /* turn tracing on */
2239  activation->externalTraceOn();
2240  }
2241  else
2242  {
2243  /* turn tracing off */
2244  activation->externalTraceOff();
2245  }
2246  return true;
2247  }
2248  return false;
2249 }
2250 
2252 /******************************************************************************/
2253 /* Function: Release exclusive access to the kernel */
2254 /******************************************************************************/
2255 {
2256  // make sure we're really the holder on this
2258  {
2259  // reset the numeric settings
2262  }
2263 }
2264 
2266 
2268 {
2269  return requestAccessCount;
2270 }
2271 
2273 /******************************************************************************/
2274 /* Function: Acquire exclusive access to the kernel */
2275 /******************************************************************************/
2276 {
2277  requestAccessCount += 1;
2278  /* only one there? */
2280  {
2281  ActivityManager::currentActivity = this; /* set new current activity */
2282  /* and new active settings */
2284  return; /* get out if we have it */
2285  }
2286  /* can't get it, go stand in line */
2288  // belt and braces to ensure this is done on this thread
2289  ActivityManager::currentActivity = this; /* set new current activity */
2290 }
2291 
2293 /******************************************************************************/
2294 /* Function: Make sure there is enough stack space to run a method */
2295 /******************************************************************************/
2296 {
2297 #ifdef STACKCHECK
2298  size_t temp; // if checking and there isn't room
2299 #if 0
2300  printf("RexxActivity::checkStackSpace : SP=%16.16x stackBase=%16.16x delta=%i MIN_C_STACK=%i %i %i\n",
2301  (char *)&temp,
2302  (char *)this->stackBase,
2303  ((char *)&temp - (char *)this->stackBase),
2304  MIN_C_STACK,
2305  ((char *)&temp - (char *)this->stackBase) < MIN_C_STACK,
2306  this->stackcheck == true
2307  );
2308 #endif
2309  if (((char *)&temp - (char *)this->stackBase) < MIN_C_STACK && this->stackcheck == true)
2310  {
2311  // go raise an exception
2313  }
2314 #endif
2315 }
2316 
2317 
2319 /******************************************************************************/
2320 /* Function: Retrive the activities local environment */
2321 /******************************************************************************/
2322 {
2323  return instance->getLocal(); // just return the .local directory
2324 }
2325 
2327 /******************************************************************************/
2328 /* Function: Retrive the directory of thread's local variables */
2329 /******************************************************************************/
2330 {
2331  return this->threadLocalEnvironment;
2332 }
2333 
2335 /******************************************************************************/
2336 /* Function: Retrieve the activities threadid */
2337 /******************************************************************************/
2338 {
2339  return currentThread.getThreadID(); /* just return the thread id info */
2340 }
2341 
2343 /******************************************************************************/
2344 /* Function: Determine if Halt or Trace System exits are set */
2345 /* and set a flag to indicate this. */
2346 /******************************************************************************/
2347 { /* is HALT sys exit set */
2348  if (isExitEnabled(RXHLT))
2349  {
2350  this->clauseExitUsed = true; /* set flag to indicate one is found */
2351  return; /* and return */
2352  }
2353  /* is TRACE sys exit set */
2354  if (isExitEnabled(RXTRC))
2355  {
2356  this->clauseExitUsed = true; /* set flag to indicate one is found */
2357  return; /* and return */
2358  }
2359 
2360  this->clauseExitUsed = false; /* remember that none are set */
2361 }
2362 
2363 
2364 /**
2365  * Call an individual exit handler.
2366  *
2367  * @param activation The activation this is in the context of.
2368  * @param exitName The logical name of the handler.
2369  * @param function The exit function.
2370  * @param subfunction
2371  * The exit subfunction.
2372  * @param exitbuffer The parameter structure for the exit in question.
2373  *
2374  * @return The exit handling state.
2375  */
2377  const char *exitName, int function,
2378  int subfunction, void *exitbuffer)
2379 {
2380  ExitHandler &handler = getExitHandler(function);
2381 
2382  int rc = handler.call(this, activation, function, subfunction, exitbuffer);
2383 
2384  /* got an error case? */
2385  if (rc == RXEXIT_RAISE_ERROR || rc < 0)
2386  {
2387  if (function == RXSIO) /* this the I/O function? */
2388  {
2389  /* disable the I/O exit from here to */
2390  /* prevent recursive error conditions */
2391  disableExit(RXSIO);
2392  }
2393  /* go raise an error */
2395  }
2396  return rc == RXEXIT_HANDLED; /* Did exit handle task? */
2397 }
2398 
2399 
2401  RexxActivation *activation) /* sending activation */
2402 /******************************************************************************/
2403 /* Function: Calls the SysExitHandler method on the System Object to run */
2404 /* the initialization system exit. */
2405 /******************************************************************************/
2406 {
2407  if (isExitEnabled(RXINI)) // is the exit enabled?
2408  {
2409  /* add the variable RXPROGRAMNAME to */
2410  /* the variable pool, it contains the*/
2411  /* script name that is currently run */
2412  /* call the handler */
2413  callExit(activation, "RXINI", RXINI, RXINIEXT, NULL);
2414  }
2415 }
2416 
2418  RexxActivation *activation) /* sending activation */
2419 /******************************************************************************/
2420 /* Function: Calls the SysExitHandler method on the System Object to run */
2421 /* the termination system exit. */
2422 /******************************************************************************/
2423 {
2424  if (isExitEnabled(RXTER)) // is the exit enabled?
2425  {
2426  callExit(activation, "RXTER", RXTER, RXTEREXT, NULL);
2427  }
2428 }
2429 
2431  RexxActivation *activation, /* sending activation */
2432  RexxString *sayoutput) /* line to write out */
2433 /******************************************************************************/
2434 /* Function: Calls the SysExitHandler method on the System Object to run */
2435 /* the I/O system exit. */
2436 /******************************************************************************/
2437 {
2438  if (isExitEnabled(RXSIO)) // is the exit enabled?
2439  {
2440  RXSIOSAY_PARM exit_parm; /* exit parameters */
2441 
2442  sayoutput->toRxstring(exit_parm.rxsio_string);
2443  return !callExit(activation, "RXSIO", RXSIO, RXSIOSAY, &exit_parm);
2444  }
2445  return true; /* exit didn't handle */
2446 }
2447 
2449  RexxActivation *activation, /* sending activation */
2450  RexxString *traceoutput) /* line to write out */
2451 /******************************************************************************/
2452 /* Function: Calls the SysExitHandler method on the System Object to run */
2453 /* the I/O system exit. */
2454 /******************************************************************************/
2455 {
2456  if (isExitEnabled(RXSIO)) // is the exit enabled?
2457  {
2458  RXSIOSAY_PARM exit_parm; /* exit parameters */
2459  traceoutput->toRxstring(exit_parm.rxsio_string);
2460  return !callExit(activation, "RXSIO", RXSIO, RXSIOTRC, &exit_parm);
2461  }
2462  return true; /* exit didn't handle */
2463 }
2464 
2466  RexxActivation *activation, /* sending activation */
2467  RexxString *&inputstring) /* returned input string */
2468 /******************************************************************************/
2469 /* Function: Calls the SysExitHandler method on the System Object to run */
2470 /* the I/O system exit. */
2471 /******************************************************************************/
2472 {
2473  if (isExitEnabled(RXSIO)) // is the exit enabled?
2474  {
2475  RXSIOTRD_PARM exit_parm; /* exit parameters */
2476  char retbuffer[DEFRXSTRING];/* Default result buffer */
2477 
2478  *retbuffer = '\0';
2479  /* Pass along default RXSTRING */
2480  MAKERXSTRING(exit_parm.rxsiotrd_retc, retbuffer, DEFRXSTRING);
2481  if (!callExit(activation, "RXSIO", RXSIO, RXSIOTRD, &exit_parm))
2482  {
2483  return true;
2484  }
2485  /* Get input string and return it */
2486  inputstring = new_string(exit_parm.rxsiotrd_retc);
2487  /* user give us a new buffer? */
2488  if (exit_parm.rxsiotrd_retc.strptr != retbuffer)
2489  {
2490  /* free it */
2492 
2493  }
2494  return false; /* this was handled */
2495  }
2496  return true; /* not handled */
2497 }
2498 
2500  RexxActivation *activation, /* sending activation */
2501  RexxString *&inputstring) /* returned input value */
2502 /******************************************************************************/
2503 /* Function: Calls the SysExitHandler method on the System Object to run */
2504 /* the I/O system exit. */
2505 /******************************************************************************/
2506 {
2507  if (isExitEnabled(RXSIO)) // is the exit enabled?
2508  {
2509  RXSIOTRD_PARM exit_parm; /* exit parameters */
2510  char retbuffer[DEFRXSTRING];/* Default result buffer */
2511 
2512  *retbuffer = '\0';
2513  /* Pass along default RXSTRING */
2514  MAKERXSTRING(exit_parm.rxsiotrd_retc, retbuffer, DEFRXSTRING);
2515  if (!callExit(activation, "RXSIO", RXSIO, RXSIODTR, &exit_parm))
2516  {
2517  return true;
2518  }
2519  /* Get input string and return it */
2520  inputstring = new_string(exit_parm.rxsiotrd_retc);
2521  /* user give us a new buffer? */
2522  if (exit_parm.rxsiotrd_retc.strptr != retbuffer)
2523  {
2524  /* free it */
2526 
2527  }
2528  return false; /* this was handled */
2529  }
2530  return true; /* not handled */
2531 }
2532 
2534  RexxActivation *activation, /* calling activation */
2535  RexxString *rname, /* routine name */
2536  RexxObject *calltype, /* type of call */
2537  ProtectedObject &funcresult, /* function result */
2538  RexxObject **arguments, /* argument array */
2539  size_t argcount) /* argument count */
2540 /******************************************************************************/
2541 /* Function: Calls the SysExitHandler method on the System Object to run */
2542 /* the function system exit. */
2543 /******************************************************************************/
2544 {
2545 
2546  if (isExitEnabled(RXFNC)) // is the exit enabled?
2547  {
2548  RXFNCCAL_PARM exit_parm; /* exit parameters */
2549  char retbuffer[DEFRXSTRING];/* Default result buffer */
2550  /* Start building the exit block */
2551  exit_parm.rxfnc_flags.rxfferr = 0; /* Initialize error codes to zero */
2552  exit_parm.rxfnc_flags.rxffnfnd = 0;
2553 
2554 
2555  exit_parm.rxfnc_flags.rxffsub = calltype == OREF_FUNCTIONNAME ? 0 : 1;
2556  /* fill in the name parameter */
2557  exit_parm.rxfnc_namel = (unsigned short)size_v(rname->getBLength());
2558  exit_parm.rxfnc_name = rname->getStringData();
2559 
2560  /* Get current active queue name */
2562  /* fill in the name */
2563  exit_parm.rxfnc_que = stdqueue->getStringData();
2564  /* and the length */
2565  exit_parm.rxfnc_quel = (unsigned short)size_v(stdqueue->getBLength());
2566  /* Build arg array of RXSTRINGs */
2567  /* get number of args */
2568  exit_parm.rxfnc_argc = (unsigned short)argcount;
2569 
2570 
2571  /* allocate enough memory for all arguments. */
2572  /* At least one item needs to be allocated in order to avoid an error */
2573  /* in the sysexithandler! */
2575  sizeof(CONSTRXSTRING) * Numerics::maxVal((size_t)exit_parm.rxfnc_argc, (size_t)1));
2576  if (argrxarray == OREF_NULL) /* memory error? */
2577  {
2579  }
2580  /* give the arg array pointer */
2581  exit_parm.rxfnc_argv = argrxarray;
2582  /* construct the arg array */
2583  for (size_t argindex=0; argindex < exit_parm.rxfnc_argc; argindex++)
2584  {
2585  // classic REXX style interface
2586  RexxString *temp = (RexxString *)arguments[argindex];
2587  if (temp != OREF_NULL) /* got a real argument? */
2588  {
2589  /* force the argument to a string */
2590  temp = (RexxString *)REQUEST_STRING(temp);
2591  /* point to the string */
2592  temp->toRxstring(argrxarray[argindex]);
2593  }
2594  else
2595  {
2596  /* empty argument */
2597  argrxarray[argindex].strlength = 0;
2598  argrxarray[argindex].strptr = (const char *)NULL;
2599  }
2600  }
2601  /* Pass default result RXSTRING */
2602  MAKERXSTRING(exit_parm.rxfnc_retc, retbuffer, DEFRXSTRING);
2603  /* call the handler */
2604  bool wasHandled = callExit(activation, "RXFNC", RXFNC, RXFNCCAL, (void *)&exit_parm);
2605 
2607 
2608  if (!wasHandled)
2609  {
2610  return true; /* this wasn't handled */
2611  }
2612 
2613 
2614  if (exit_parm.rxfnc_flags.rxfferr) /* function error? */
2615  {
2616  /* raise an error */
2618  }
2619  /* Did we find the function?? */
2620  else if (exit_parm.rxfnc_flags.rxffnfnd)
2621  {
2622  /* also an error */
2624  }
2625  /* Was it a function call?? */
2626  if (exit_parm.rxfnc_retc.strptr == OREF_NULL && calltype == OREF_FUNCTIONNAME)
2627  {
2628  /* Have to return data */
2630  }
2631 
2632  if (exit_parm.rxfnc_retc.strptr) /* If we have result, return it */
2633  {
2634  /* Get input string and return it */
2635  funcresult = new_string(exit_parm.rxfnc_retc);
2636  /* user give us a new buffer? */
2637  if (exit_parm.rxfnc_retc.strptr != retbuffer)
2638  {
2639  /* free it */
2641  }
2642  }
2643  return false; /* this was handled */
2644  }
2645  return true; /* not handled */
2646 }
2647 
2648 
2650  RexxActivation *activation, /* calling activation */
2651  RexxString *rname, /* routine name */
2652  RexxObject *calltype, /* type of call */
2653  ProtectedObject &funcresult, /* function result */
2654  RexxObject **arguments, /* argument array */
2655  size_t argcount, /* argument count */
2656  size_t named_argcount)
2657 /******************************************************************************/
2658 /* Function: Calls the SysExitHandler method on the System Object to run */
2659 /* the function system exit. */
2660 /******************************************************************************/
2661 {
2662  // give the security manager the first pass
2663  SecurityManager *manager = activation->getEffectiveSecurityManager();
2664  if (manager != OREF_NULL)
2665  {
2666  if (manager->checkFunctionCall(rname, argcount, named_argcount, arguments, funcresult))
2667  {
2668  return false;
2669  }
2670  }
2671 
2672  if (isExitEnabled(RXOFNC)) // is the exit enabled?
2673  {
2674  RXOFNCCAL_PARM exit_parm; /* exit parameters */
2675  /* Start building the exit block */
2676  exit_parm.rxfnc_flags.rxfferr = 0; /* Initialize error codes to zero */
2677  exit_parm.rxfnc_flags.rxffnfnd = 0;
2678 
2679 
2680  exit_parm.rxfnc_flags.rxffsub = calltype == OREF_FUNCTIONNAME ? 0 : 1;
2681  /* fill in the name parameter */
2682  rname->toRxstring(exit_parm.rxfnc_name);
2683 
2684  /* get number of args */
2685  exit_parm.rxfnc_argc = argcount;
2686  // the argument pointers get passed as is
2687  exit_parm.rxfnc_argv = (RexxObjectPtr *)arguments;
2688  // no result value
2689  exit_parm.rxfnc_retc = NULLOBJECT;
2690  /* call the handler */
2691  if (!callExit(activation, "RXOFNC", RXOFNC, RXOFNCCAL, (void *)&exit_parm))
2692  {
2693  return true; /* this wasn't handled */
2694  }
2695 
2696  if (exit_parm.rxfnc_flags.rxfferr) /* function error? */
2697  {
2698  /* raise an error */
2700  }
2701  /* Did we find the function?? */
2702  else if (exit_parm.rxfnc_flags.rxffnfnd)
2703  {
2704  /* also an error */
2706  }
2707  /* Was it a function call?? */
2708  if (exit_parm.rxfnc_retc == NULLOBJECT && calltype == OREF_FUNCTIONNAME)
2709  {
2710  /* Have to return data */
2712  }
2713  // set the function result back
2714  funcresult = (RexxObject *)exit_parm.rxfnc_retc;
2715  return false; /* this was handled */
2716  }
2717  return true; /* not handled */
2718 }
2719 
2720 
2722  RexxActivation *activation, /* calling activation */
2723  RexxString *rname, /* routine name */
2724  RexxObject *calltype, /* type of call */
2725  ProtectedObject &funcresult, /* function result */
2726  RexxObject **arguments, /* argument array */
2727  size_t argcount) /* argument count */
2728 /******************************************************************************/
2729 /* Function: Calls the SysExitHandler method on the System Object to run */
2730 /* the function system exit. */
2731 /******************************************************************************/
2732 {
2733  if (isExitEnabled(RXEXF)) // is the exit enabled?
2734  {
2735  RXEXFCAL_PARM exit_parm; /* exit parameters */
2736  /* Start building the exit block */
2737  exit_parm.rxfnc_flags.rxfferr = 0; /* Initialize error codes to zero */
2738  exit_parm.rxfnc_flags.rxffnfnd = 0;
2739 
2740 
2741  exit_parm.rxfnc_flags.rxffsub = calltype == OREF_FUNCTIONNAME ? 0 : 1;
2742  /* fill in the name parameter */
2743  rname->toRxstring(exit_parm.rxfnc_name);
2744 
2745  /* get number of args */
2746  exit_parm.rxfnc_argc = argcount;
2747  // the argument pointers get passed as is
2748  exit_parm.rxfnc_argv = (RexxObjectPtr *)arguments;
2749  // no result value
2750  exit_parm.rxfnc_retc = NULLOBJECT;
2751  /* call the handler */
2752  if (!callExit(activation, "RXEXF", RXEXF, RXEXFCAL, (void *)&exit_parm))
2753  {
2754  return true; /* this wasn't handled */
2755  }
2756 
2757  if (exit_parm.rxfnc_flags.rxfferr) /* function error? */
2758  {
2759  /* raise an error */
2761  }
2762  /* Did we find the function?? */
2763  else if (exit_parm.rxfnc_flags.rxffnfnd)
2764  {
2765  /* also an error */
2767  }
2768  /* Was it a function call?? */
2769  if (exit_parm.rxfnc_retc == NULLOBJECT && calltype == OREF_FUNCTIONNAME)
2770  {
2771  /* Have to return data */
2773  }
2774  // set the function result back
2775  funcresult = (RexxObject *)exit_parm.rxfnc_retc;
2776  return false; /* this was handled */
2777  }
2778  return true; /* not handled */
2779 }
2780 
2781 
2782 bool RexxActivity::callCommandExit(RexxActivation *activation, RexxString *address, RexxString *command, ProtectedObject &result, ProtectedObject &condition)
2783 {
2784  // give the security manager the first pass
2785  SecurityManager *manager = activation->getEffectiveSecurityManager();
2786  if (manager != OREF_NULL)
2787  {
2788  if (manager->checkCommand(this, address, command, result, condition))
2789  {
2790  return false;
2791  }
2792  }
2793 
2794  if (isExitEnabled(RXCMD)) // is the exit enabled?
2795  {
2796  RXCMDHST_PARM exit_parm; /* exit parameters */
2797  char retbuffer[DEFRXSTRING];/* Default result buffer */
2798  /* Start building the exit block */
2799  exit_parm.rxcmd_flags.rxfcfail = 0;/* Initialize failure/error to zero */
2800  exit_parm.rxcmd_flags.rxfcerr = 0;
2801  /* fill in the environment parm */
2802  exit_parm.rxcmd_addressl = (unsigned short)size_v(address->getBLength());
2803  exit_parm.rxcmd_address = address->getStringData();
2804  /* make cmdaname into RXSTRING form */
2805  command->toRxstring(exit_parm.rxcmd_command);
2806 
2807  exit_parm.rxcmd_dll = NULL; /* Currently no DLL support */
2808  exit_parm.rxcmd_dll_len = 0; /* 0 means .EXE style */
2809  /* Pass default result RXSTRING */
2810  MAKERXSTRING(exit_parm.rxcmd_retc, retbuffer, DEFRXSTRING);
2811  /* call the handler */
2812  if (!callExit(activation, "RXCMD", RXCMD, RXCMDHST, (void *)&exit_parm))
2813  {
2814  return true; /* this wasn't handled */
2815  }
2816  if (exit_parm.rxcmd_flags.rxfcfail)/* need to raise failure condition? */
2817  {
2818  // raise the condition when things are done
2819  condition = createConditionObject(OREF_FAILURENAME, (RexxObject *)result, command, OREF_NULL, OREF_NULL);
2820  }
2821 
2822  /* Did we find the function?? */
2823  else if (exit_parm.rxcmd_flags.rxfcerr)
2824  {
2825  // raise the condition when things are done
2826  condition = createConditionObject(OREF_ERRORNAME, (RexxObject *)result, command, OREF_NULL, OREF_NULL);
2827  }
2828  /* Get input string and return it */
2829  result = new_string(exit_parm.rxcmd_retc);
2830  /* user give us a new buffer? */
2831  if (exit_parm.rxcmd_retc.strptr != retbuffer)
2832  {
2833  /* free it */
2835  }
2836  return false; /* this was handled */
2837  }
2838  return true; /* not handled */
2839 }
2840 
2841 
2843  RexxActivation *activation, /* sending activation */
2844  RexxString *&inputstring) /* returned input string */
2845 /******************************************************************************/
2846 /* Function: Calls the SysExitHandler method on the System Object to run */
2847 /* the External Data queue system exit. */
2848 /******************************************************************************/
2849 {
2850  if (isExitEnabled(RXMSQ)) // is the exit enabled?
2851  {
2852  RXMSQPLL_PARM exit_parm; /* exit parameters */
2853  char retbuffer[DEFRXSTRING];/* Default result buffer */
2854 
2855  /* Pass along default RXSTRING */
2856  MAKERXSTRING(exit_parm.rxmsq_retc, retbuffer, DEFRXSTRING);
2857  /* call the handler */
2858  if (!callExit(activation, "RXMSQ", RXMSQ, RXMSQPLL, (void *)&exit_parm))
2859  {
2860  return true; /* this wasn't handled */
2861  }
2862  if (exit_parm.rxmsq_retc.strptr == NULL)/* if rxstring not null */
2863  {
2864  /* no value returned, */
2865  /* return NIL to note empty stack */
2866  inputstring = (RexxString *)TheNilObject;
2867  }
2868  else /* return resulting object */
2869  {
2870  inputstring = new_string(exit_parm.rxmsq_retc);
2871  /* user give us a new buffer? */
2872  if (exit_parm.rxmsq_retc.strptr != retbuffer)
2873  {
2874  /* free it */
2876  }
2877  }
2878  return false; /* this was handled */
2879  }
2880  return true; /* not handled */
2881 }
2882 
2884  RexxActivation *activation, /* sending activation */
2885  RexxString *inputstring, /* string to be placed on the queue */
2886  int lifo_flag) /* flag to indicate LIFO or FIFO */
2887 /******************************************************************************/
2888 /* Function: Calls the SysExitHandler method on the System Object to run */
2889 /* the External Data queue system exit. */
2890 /******************************************************************************/
2891 {
2892  if (isExitEnabled(RXMSQ)) // is the exit enabled?
2893  {
2894  RXMSQPSH_PARM exit_parm; /* exit parameters */
2895 
2896  /* get the exit handler */
2897  if (lifo_flag == QUEUE_LIFO) /* LIFO queuing requested? */
2898  {
2899  /* set the flag appropriately */
2900  exit_parm.rxmsq_flags.rxfmlifo = 1;
2901  }
2902  else
2903  {
2904  /* this is a FIFO request */
2905  exit_parm.rxmsq_flags.rxfmlifo = 0;
2906  }
2907  /* make into RXSTRING form */
2908  inputstring->toRxstring(exit_parm.rxmsq_value);
2909  /* call the handler */
2910  if (!callExit(activation, "RXMSQ", RXMSQ, RXMSQPSH, (void *)&exit_parm))
2911  {
2912  return true; /* this wasn't handled */
2913  }
2914  return false; /* this was handled */
2915  }
2916  return true; /* not handled */
2917 }
2918 
2919 
2921  RexxActivation *activation, /* sending activation */
2922  RexxInteger *&returnsize) /* returned queue size */
2923 /******************************************************************************/
2924 /* Function: Calls the SysExitHandler method on the System Object to run */
2925 /* the External Data queue system exit. */
2926 /******************************************************************************/
2927 {
2928  if (isExitEnabled(RXMSQ)) // is the exit enabled?
2929  {
2930  RXMSQSIZ_PARM exit_parm; /* exit parameters */
2931  /* call the handler */
2932  if (!callExit(activation, "RXMSQ", RXMSQ, RXMSQSIZ, (void *)&exit_parm))
2933  {
2934  return true; /* this wasn't handled */
2935  }
2936  /* Get queue size and return it */
2937  returnsize = new_integer(exit_parm.rxmsq_size);
2938 
2939  return false; /* this was handled */
2940  }
2941  return true; /* not handled */
2942 }
2943 
2944 
2946  RexxActivation *activation, /* sending activation */
2947  RexxString *&inputstring ) /* name of external queue */
2948 /******************************************************************************/
2949 /* Function: Calls the SysExitHandler method on the System Object to run */
2950 /* the External Data queue system exit. */
2951 /******************************************************************************/
2952 {
2953  if (isExitEnabled(RXMSQ)) // is the exit enabled?
2954  {
2955  RXMSQNAM_PARM exit_parm; /* exit parameters */
2956  char retbuffer[DEFRXSTRING];/* Default result buffer */
2957 
2958  MAKERXSTRING(exit_parm.rxmsq_name, retbuffer, size_v(inputstring->getBLength()));
2959  memcpy(exit_parm.rxmsq_name.strptr, inputstring->getStringData(), size_v(inputstring->getBLength()));
2960  /* call the handler */
2961  if (!callExit(activation, "RXMSQ", RXMSQ, RXMSQNAM, (void *)&exit_parm))
2962  {
2963  return true; /* this wasn't handled */
2964  }
2965  inputstring = new_string(exit_parm.rxmsq_name);
2966  /* user give us a new buffer? */
2967  if (exit_parm.rxmsq_name.strptr != retbuffer)
2968  {
2969  /* free it */
2971  }
2972  return false; /* this was handled */
2973  }
2974  return true; /* not handled */
2975 }
2976 
2977 
2979  RexxActivation *activation) /* sending activation */
2980 /******************************************************************************/
2981 /* Function: Calls the SysExitHandler method on the System Object to run */
2982 /* the Test Halt system exit. */
2983 /******************************************************************************/
2984 {
2985  if (isExitEnabled(RXHLT)) // is the exit enabled?
2986  {
2987  RXHLTTST_PARM exit_parm; /* exit parameters */
2988 
2989  /* Clear halt so as not to be sloppy */
2990  exit_parm.rxhlt_flags.rxfhhalt = 0;
2991  /* call the handler */
2992  if (!callExit(activation, "RXHLT", RXHLT, RXHLTTST, (void *)&exit_parm))
2993  {
2994  return true; /* this wasn't handled */
2995  }
2996  /* Was halt requested? */
2997  if (exit_parm.rxhlt_flags.rxfhhalt == 1)
2998  {
2999  /* Then honor the halt request */
3000  activation->halt(OREF_NULL);
3001  }
3002  return false; /* this was handled */
3003  }
3004  return true; /* not handled */
3005 }
3006 
3007 
3009  RexxActivation *activation) /* sending activation */
3010 /******************************************************************************/
3011 /* Function: Calls the SysExitHandler method on the System Object to run */
3012 /* the Clear Halt system exit. */
3013 /******************************************************************************/
3014 {
3015  if (isExitEnabled(RXHLT)) // is the exit enabled?
3016  {
3017  RXHLTTST_PARM exit_parm; /* exit parameters */
3018  /* call the handler */
3019  if (!callExit(activation, "RXHLT", RXHLT, RXHLTCLR, (void *)&exit_parm))
3020  {
3021  return true; /* this wasn't handled */
3022  }
3023  return false; /* this was handled */
3024  }
3025  return true; /* not handled */
3026 }
3027 
3028 
3030  RexxActivation *activation, /* sending activation */
3031  bool currentsetting) /* sending activation */
3032 /******************************************************************************/
3033 /* Function: Calls the SysExitHandler method on the System Object to run */
3034 /* the Test external trace indicator system exit. */
3035 /******************************************************************************/
3036 {
3037  if (isExitEnabled(RXTRC)) // is the exit enabled?
3038  {
3039  RXTRCTST_PARM exit_parm; /* exit parameters */
3040  /* Clear Trace bit before call */
3041  exit_parm.rxtrc_flags.rxftrace = 0;
3042  /* call the handler */
3043  if (!callExit(activation, "RXTRC", RXTRC, RXTRCTST, (void *)&exit_parm))
3044  {
3045  return true; /* this wasn't handled */
3046  }
3047  /* if not tracing, and now it is */
3048  /* requsted */
3049  if (!currentsetting && (exit_parm.rxtrc_flags.rxftrace == 1))
3050  {
3051  /* call routine to handle this */
3052  activation->externalTraceOn();
3053  return false; /* this was handled */
3054  }
3055  // this could be a request to stop tracing
3056  else if (currentsetting && (exit_parm.rxtrc_flags.rxftrace != 1))
3057  {
3058  /* call routine to handle this */
3059  activation->externalTraceOff();
3060  return false; /* this was handled */
3061  }
3062  }
3063  return true; /* not handled */
3064 }
3065 
3066 
3068  RexxActivation *activation, /* sending activation */
3069  RexxString *variableName, /* name to look up */
3070  RexxObject *&value) /* the returned value */
3071 /******************************************************************************/
3072 /* Function: Calls the novalue handler for uninitialized variables */
3073 /******************************************************************************/
3074 {
3075  if (isExitEnabled(RXNOVAL)) // is the exit enabled?
3076  {
3077  RXVARNOVALUE_PARM exit_parm; /* exit parameters */
3078  // the name is passed as a RexxStringObject
3079  exit_parm.variable_name = (RexxStringObject)variableName;
3080  // the value is returned as an object
3081  exit_parm.value = NULLOBJECT; /* no value at the start */
3082  /* call the handler */
3083  if (callExit(activation, "RXNOVAL", RXNOVAL, RXNOVALCALL, (void *)&exit_parm))
3084  {
3085  value = (RexxObject *)exit_parm.value;
3086  return false;
3087  }
3088  }
3089  return true; /* exit didn't handle */
3090 }
3091 
3092 
3094  RexxActivation *activation, /* sending activation */
3095  RexxString *selector, /* the variable set selector */
3096  RexxString *variableName, /* name to look up */
3097  RexxObject *newValue, // new value for the variable
3098  RexxObject *&value) /* the returned value */
3099 /******************************************************************************/
3100 /* Function: Calls the exit for the VALUE() BIF */
3101 /******************************************************************************/
3102 {
3103  if (isExitEnabled(RXVALUE)) // is the exit enabled?
3104  {
3105  RXVALCALL_PARM exit_parm; /* exit parameters */
3106  // copy the selector and variable parts
3107  exit_parm.selector = (RexxStringObject)selector;
3108  exit_parm.variable_name = (RexxStringObject)variableName;
3109  // the value is returned as an object, and the old value is
3110  // also passed that way
3111  exit_parm.value = (RexxObjectPtr)newValue;
3112  /* call the handler */
3113  if (callExit(activation, "RXVALUE", RXVALUE, RXVALUECALL, (void *)&exit_parm))
3114  {
3115  value = (RexxObject *)exit_parm.value;
3116  return false;
3117  }
3118  }
3119  return true; /* exit didn't handle */
3120 }
3121 
3122 
3123 /**
3124  * Retrieve the current security manager instance.
3125  *
3126  * @return the security manager instance in effect for the
3127  * activity.
3128  */
3130 {
3131  // get the security manager for the top stack frame. If there is none defined, default to
3132  // ghe global security manager.
3134 
3135  if (manager != OREF_NULL)
3136  {
3137  return manager;
3138  }
3139 
3140  // return the manager from the instance
3141  return instance->getSecurityManager();
3142 }
3143 
3144 
3145 /**
3146  * Return the security manager in effect for this instance.
3147  *
3148  * @return The globally defined security manager.
3149  */
3151 {
3152  // return the manager from the instance
3153  return instance->getSecurityManager();
3154 }
3155 
3156 
3157 
3158 void RexxActivity::traceOutput( /* write a line of trace information */
3159  RexxActivation *activation, /* sending activation */
3160  RexxString *line) /* line to write out */
3161 /******************************************************************************/
3162 /* Function: Write a line of trace output to the .ERROR stream */
3163 /******************************************************************************/
3164 {
3165  ProtectedObject p_line;
3166  p_line = line->stringTrace(); /* get traceable form of this */
3167  /* if exit declines the call */
3168 
3170  {
3171  // Add thread id, activation id and lock flag.
3172  // Should help to analyze the traces of a multithreaded script...
3173  char buffer[CONCURRENCY_BUFFER_SIZE];
3174  Utilities::snprintf(buffer, sizeof buffer - 1, CONCURRENCY_TRACE,
3176  activation,
3177  (activation) ? activation->getVariableDictionary() : NULL,
3178  (activation) ? activation->getReserveCount() : 0,
3179  (activation && activation->isObjectScopeLocked()) ? '*' : ' ');
3180  p_line = ((RexxString*)p_line)->concatToCstring(buffer);
3181  }
3182 
3183  dbgprintf("%s\n", ((RexxString*)p_line)->getStringData());
3184 
3185  if (this->callTraceExit(activation, (RexxString*)p_line))
3186  {
3187  /* get the default output stream */
3188  RexxObject *stream = getLocalEnvironment(OREF_TRACEOUTPUT);
3189  /* have .local set up yet? */
3190  if (stream != OREF_NULL && stream != TheNilObject)
3191  {
3192  stream->sendMessage(OREF_LINEOUT, (RexxString*)p_line);
3193  }
3194  /* do the lineout */
3195  else /* use the "real" default stream */
3196  {
3197  this->lineOut((RexxString*)p_line);
3198  }
3199  }
3200 }
3201 
3202 void RexxActivity::sayOutput( /* write a line of say information */
3203  RexxActivation *activation, /* sending activation */
3204  RexxString *line) /* line to write out */
3205 /******************************************************************************/
3206 /* Function: Write a line of SAY output to the .OUTPUT stream */
3207 /******************************************************************************/
3208 {
3209  if (this->callSayExit(activation, line))
3210  {
3211  /* get the default output stream */
3212  RexxObject *stream = getLocalEnvironment(OREF_OUTPUT);
3213  /* have .local set up yet? */
3214  if (stream != OREF_NULL && stream != TheNilObject)
3215  {
3216  /* do the lineout */
3217  stream->sendMessage(OREF_SAY, line);
3218  }
3219  else /* use the "real" default stream */
3220  {
3221  this->lineOut(line);
3222  }
3223  }
3224 }
3225 
3226 RexxString *RexxActivity::traceInput( /* read a line of trace input */
3227  RexxActivation *activation) /* sending activation */
3228 /******************************************************************************/
3229 /* Function: Read a line for interactive debug input */
3230 /******************************************************************************/
3231 {
3232  RexxString *value;
3233 
3234  /* if exit declines the call */
3235  if (this->callDebugInputExit(activation, value))
3236  {
3237  /* get the input stream */
3238  RexxObject *stream = getLocalEnvironment(OREF_DEBUGINPUT);
3239  if (stream != OREF_NULL) /* have a stream? */
3240  {
3241  /* read from it */
3242  value = (RexxString *)stream->sendMessage(OREF_LINEIN);
3243  /* get something real? */
3244  if (value == (RexxString *)TheNilObject)
3245  {
3246  value = OREF_NULLSTRING; /* just us a null string if not */
3247  }
3248  }
3249  else
3250  {
3251  value = OREF_NULLSTRING; /* default to a null string */
3252  }
3253  }
3254  return value; /* return value from exit */
3255 }
3256 
3257 
3258 RexxString *RexxActivity::pullInput( /* read a line of pull input */
3259  RexxActivation *activation) /* sending activation */
3260 /******************************************************************************/
3261 /* Function: Read a line for the PULL instruction */
3262 /******************************************************************************/
3263 {
3264  RexxString *value;
3265 
3266  /* if exit declines call */
3267  if (this->callPullExit(activation, value))
3268  {
3269  /* get the external data queue */
3270  RexxObject *stream = getLocalEnvironment(OREF_REXXQUEUE);
3271  if (stream != OREF_NULL) /* have a data queue? */
3272  {
3273  /* pull from the queue */
3274  value = (RexxString *)stream->sendMessage(OREF_PULL);
3275  /* get something real? */
3276  if (value == (RexxString *)TheNilObject)
3277  {
3278  /* read from the linein stream */
3279  value = this->lineIn(activation);
3280  }
3281  }
3282  }
3283  return value; /* return the read value */
3284 }
3285 
3287  RexxString *line) /* line to write out */
3288 /******************************************************************************/
3289 /* Function: Write a line out to the real default I/O stream */
3290 /******************************************************************************/
3291 {
3292  size_t length; /* length to write out */
3293  const char *data; /* data pointer */
3294 
3295  length = size_v(line->getBLength()); /* get the string length and the */
3296  data = line->getStringData(); /* data pointer */
3297  printf("%.*s\n",(int)length, data); /* print it */ // todo m17n
3298  return (RexxObject *)IntegerZero; /* return on residual count */
3299 }
3300 
3302  RexxActivation *activation) /* sending activation */
3303 /******************************************************************************/
3304 /* Function: Read a line for the PARSE LINEIN instruction */
3305 /******************************************************************************/
3306 {
3307  RexxString *value;
3308 
3309  /* if exit declines call */
3310  if (this->callTerminalInputExit(activation, value))
3311  {
3312  /* get the input stream */
3313  RexxObject *stream = getLocalEnvironment(OREF_INPUT);
3314  if (stream != OREF_NULL) /* have a stream? */
3315  {
3316  /* read from it */
3317  value = (RexxString *)stream->sendMessage(OREF_LINEIN);
3318  /* get something real? */
3319  if (value == (RexxString *)TheNilObject)
3320  {
3321  value = OREF_NULLSTRING; /* just use a null string if not */
3322  }
3323  }
3324  else
3325  {
3326  value = OREF_NULLSTRING; /* default to a null string */
3327  }
3328  }
3329  return value; /* return value from exit */
3330 }
3331 
3332 
3333 void RexxActivity::queue( /* write a line to the queue */
3334  RexxActivation *activation, /* sending activation */
3335  RexxString *line, /* line to write */
3336  int order) /* LIFO or FIFO order */
3337 /******************************************************************************/
3338 /* Function: Write a line to the external data queue */
3339 /******************************************************************************/
3340 {
3341  /* if exit declines call */
3342  if (this->callPushExit(activation, line, order))
3343  {
3344  /* get the default queue */
3345  RexxObject *targetQueue = getLocalEnvironment(OREF_REXXQUEUE);
3346  if (targetQueue != OREF_NULL) /* have a data queue? */
3347  {
3348  /* pull from the queue */
3349  if (order == QUEUE_LIFO) /* push instruction? */
3350  {
3351  /* push a line */
3352  targetQueue->sendMessage(OREF_PUSH, (RexxObject *)line);
3353 
3354  }
3355  else
3356  {
3357  /* queue a line */
3358  targetQueue->sendMessage(OREF_QUEUENAME, (RexxObject *)line);
3359  }
3360  }
3361  }
3362 }
3363 
3365 /******************************************************************************/
3366 /* Function: Mark this FREE activity for termination. Set its exit flag to 1 */
3367 /* and POST its run semaphore. */
3368 /******************************************************************************/
3369 {
3370  this->exit = true; /* Activity should exit */
3371  this->runsem.post(); /* let him run so he knows to exi*/
3372 }
3373 
3374 
3375 /**
3376  * Run a task that needs to enter the interpreter on a thread.
3377  * The activity will set up the root activation and run the
3378  * task under that context to ensure proper error handling and
3379  * kernel access.
3380  *
3381  * @param target The dispatcher object that implements the call out.
3382  */
3384 {
3385  size_t startDepth; /* starting depth of activation stack*/
3386 
3387  /* make sure we have the stack base */
3389  this->generateRandomNumberSeed(); /* get a fresh random seed */
3390  startDepth = stackFrameDepth; /* Remember activation stack depth */
3391  /* Push marker onto stack so we know */
3392  this->createNewActivationStack(); /* what level we entered. */
3393 
3394  // save the actitivation level in case there's an error unwind for an unhandled
3395  // exception;
3396  size_t activityLevel = getActivationLevel();
3397  // create a new native activation
3399  pushStackFrame(newNActa); /* push it on the activity stack */
3400 
3401  try
3402  {
3403  // go run the target under the new activation
3404  newNActa->run(target);
3405  }
3406  catch (ActivityException)
3407  {
3408  // if we're not the current kernel holder when things return, make sure we
3409  // get the lock before we continue
3411  {
3412  requestAccess();
3413  }
3414 
3415  // now do error processing
3416  wholenumber_t rc = this->error(); /* do error cleanup */
3417  target.handleError(rc, conditionobj);
3418  }
3419 
3420  // make sure we get restored to the same base activation level.
3421  restoreActivationLevel(activityLevel);
3422  // give uninit objects a chance to run
3423  memoryObject.verboseMessage("Calling runUninits from RexxActivity::run(ActivityDispatcher &target)\n");
3425  // unwind to the same stack depth as the start, removing all new entries
3426  unwindToDepth(startDepth);
3427  // if a condition occurred, make sure we inject this into the API-level
3428  // native activation so the caller can check to see if an error occurred.
3429  if (target.conditionData != OREF_NULL)
3430  {
3432  }
3433  // make sure we clear this from the activity
3435 }
3436 
3437 
3438 /**
3439  * Run a task under the context of an activity. This will be
3440  * a task that calls out from the interpreter, which the
3441  * kernel lock released during the call.
3442  *
3443  * @param target The dispatcher object that implements the call out.
3444  */
3446 {
3447  // create new activation frame using the current Rexx frame (which can be null, but
3448  // is not likely to be).
3450  // this becomes the new top activation. We also turn on the variable pool for
3451  // this situation.
3452  this->pushStackFrame(new_activation);
3453  new_activation->enableVariablepool();
3454 
3455  // go run this
3456  new_activation->run(target);
3457  this->popStackFrame(new_activation); /* pop the top activation */
3458 }
3459 
3460 
3461 /**
3462  * Run a task under the context of an activity. This will be
3463  * a task that runs with a nested error trapping without
3464  * releasing the kernel lock.
3465  *
3466  * @param target The dispatcher object that implements the call out.
3467  */
3469 {
3470  // create new activation frame using the current Rexx frame (which can be null, but
3471  // is not likely to be).
3473  // this becomes the new top activation.
3474  this->pushStackFrame(new_activation);
3475  // go run this
3476  new_activation->run(target);
3477  // and pop the activation when we're done.
3478  this->popStackFrame(new_activation);
3479 }
3480 
3481 
3482 /**
3483  * Inherit all activity-specific settings from a parent activity.
3484  *
3485  * @param parent The source of the setting information.
3486  */
3488 {
3489  // copy all of the system exits
3490  for (int i = 0; i < LAST_EXIT; i++)
3491  {
3492  sysexits[i] = parent->sysexits[i];
3493  }
3494  clauseExitUsed = parent->clauseExitUsed;
3495 }
3496 
3497 
3498 /**
3499  * Set up a method context for use before a call out.
3500  *
3501  * @param context The method context to initialize.
3502  * @param owner The native activation that owns this context.
3503  */
3505 {
3506  // hook this up with the activity
3509  context.context = owner;
3510 }
3511 
3512 
3513 /**
3514  * Set up a call context for use before a call out.
3515  *
3516  * @param context The method context to initialize.
3517  * @param owner The native activation that owns this context.
3518  */
3520 {
3521  // hook this up with the activity
3524  context.context = owner;
3525 }
3526 
3528 
3529 /**
3530  * Set up an exit context for use before a call out.
3531  *
3532  * @param context The method context to initialize.
3533  * @param owner The native activation that owns this context.
3534  */
3535 {
3536  // hook this up with the activity
3539  context.context = owner;
3540 }
3541 
3542 
3543 /**
3544  * Resolve a program using the activity context information.
3545  *
3546  * @param name The name we're interested in.
3547  * @param dir A parent directory to use as part of the search.
3548  * @param ext Any parent extension name.
3549  *
3550  * @return The fully resolved file name, if it exists. Returns OREF_NULL for
3551  * non-located files.
3552  */
3554 {
3555  return instance->resolveProgramName(name, dir, ext);
3556 }
3557 
3558 
3559 /**
3560  * Retrieve a value from the instance local environment.
3561  *
3562  * @param name The name of the .local object.
3563  *
3564  * @return The object stored at the given name.
3565  */
3567 {
3568  return instance->getLocalEnvironment(name);
3569 }
3570 
3571 
3572 /**
3573  * Resolve a command handler from the interpreter
3574  * instance.
3575  *
3576  * @param name The name of the command environment.
3577  *
3578  * @return A configured command environment, or OREF_NULL if the
3579  * target environment is not found.
3580  */
3582 {
3583  return instance->resolveCommandHandler(name);
3584 }
3585 
3586 
3587 /**
3588  * Validate that an API call is occuring on the correct thread.
3589  */
3591 {
3593  {
3595  }
3596 
3597 }
3598 
3599 
3600 /**
3601  * Get the name of the last message invocation.
3602  *
3603  * @return The last message name.
3604  */
3606 {
3607  return activationFrames->messageName();
3608 }
3609 
3610 
3611 /**
3612  * Get the method for the last method invocation.
3613  *
3614  * @return The last message name.
3615  */
3617 {
3618  return activationFrames->method();
3619 }
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Activity
RexxDirectory * new_directory()
RexxInteger * new_integer(wholenumber_t v)
RexxList * new_list()
Definition: ListClass.hpp:147
uint64_t RANDOMIZE(uint64_t seed)
const size_t ACT_STACK_SIZE
wholenumber_t requestAccessCount
ActivityException
@ RecursiveStringError
@ UnhandledCondition
#define LAST_EXIT
#define OREF_NULL
Definition: RexxCore.h:60
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:283
#define TheTrueObject
Definition: RexxCore.h:186
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
#define IntegerZero
Definition: RexxCore.h:189
#define Message_Translations_debug_error
#define Error_Function_no_data_function
#define Error_System_resources
#define Error_Interpretation
#define Message_Translations_running
#define Error_Control_stack_full
#define Error_Execution_invalid_thread
#define Message_Translations_error
#define Error_System_service_service
#define Message_Translations_line
#define Error_Execution_error_condition
#define Error_Incorrect_call_external
#define Error_Routine_not_found_name
#define Error_Execution_deadlock
RexxInternalStack * new_internalstack(size_t s)
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
@ QUEUE_LIFO
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
RexxTable * new_table()
Definition: TableClass.hpp:76
#define CONCURRENCY_TRACE
Definition: Utilities.hpp:50
#define CONCURRENCY_BUFFER_SIZE
Definition: Utilities.hpp:53
ActivationFrame * next
virtual RexxMethod * method()=0
virtual StackFrameClass * createStackFrame()=0
virtual RexxString * messageName()=0
virtual RexxSource * getSource()=0
virtual void handleError(wholenumber_t, RexxDirectory *)
RexxDirectory * conditionData
static RexxNativeActivation * newNativeActivation(RexxActivity *activity, RexxActivation *parent)
static void relinquish(RexxActivity *activity)
static bool lockKernelImmediate()
static void unlockKernel()
static void activityEnded(RexxActivity *)
static void addWaitingActivity(RexxActivity *a, bool release)
static RexxActivity *volatile currentActivity
int call(RexxActivity *activity, RexxActivation *activation, int major, int minor, void *parms)
Definition: ExitHandler.cpp:59
static wholenumber_t messageNumber(RexxString *)
static RexxString * getCurrentQueue()
bool poolActivity(RexxActivity *activity)
RexxObject * getLocalEnvironment(RexxString *)
RexxInstance * getInstanceContext()
ExitHandler & getExitHandler(int exitNum)
SecurityManager * getSecurityManager()
RexxDirectory * getLocal()
RexxActivity * spawnActivity(RexxActivity *parent)
RexxString * resolveProgramName(RexxString *name, RexxString *dir, RexxString *ext)
CommandHandler * resolveCommandHandler(RexxString *name)
static NumericSettings * setDefaultSettings()
Definition: Numerics.hpp:113
static NumericSettings * getDefaultSettings()
Definition: Numerics.hpp:114
static wholenumber_t maxVal(wholenumber_t n1, wholenumber_t n2)
Definition: Numerics.hpp:122
static void setCurrentSettings(NumericSettings *s)
Definition: Numerics.hpp:112
RexxObject * protectedObject
ProtectedObject * next
virtual NumericSettings * getNumericSettings()
virtual bool trap(RexxString *, RexxDirectory *)
virtual RexxObject * dispatch()
virtual void termination()
virtual bool isStackBase()
virtual SecurityManager * getSecurityManager()=0
virtual RexxActivation * findRexxContext()
void setPreviousStackFrame(RexxActivationBase *p)
RexxSource * getSourceObject()
bool isObjectScopeLocked()
SecurityManager * getEffectiveSecurityManager()
unsigned short getReserveCount()
RexxVariableDictionary * getVariableDictionary()
bool halt(RexxString *)
void liveGeneral(int reason)
size_t getActivationLevel()
bool callTraceTestExit(RexxActivation *, bool)
RexxActivity * nestedActivity
CommandHandler * resolveCommandHandler(RexxString *)
void queue(RexxActivation *, RexxString *, int)
void pushStackFrame(RexxActivationBase *new_activation)
void requestAccess()
void setupAttachedActivity(InterpreterInstance *interpreter)
static void initializeThreadContext()
void restoreActivationLevel(size_t l)
bool callScriptingExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t)
RexxDirectory * getThreadLocal()
void reportAnException(wholenumber_t, const char *)
RexxNativeActivation * getApiContext()
wholenumber_t error()
static MethodContextInterface methodContextFunctions
void callTerminationExit(RexxActivation *)
RexxActivation * currentRexxFrame
void kill(RexxDirectory *)
static wholenumber_t requestAccessCounter()
thread_id_t threadIdMethod()
void enterCurrentThread()
bool halt(RexxString *)
bool callHaltTestExit(RexxActivation *)
bool callQueueNameExit(RexxActivation *, RexxString *&)
RexxActivationStack frameStack
void generateProgramInformation(RexxDirectory *exObj)
ExitHandler sysexits[LAST_EXIT]
SecurityManager * getEffectiveSecurityManager()
RexxObject * displayDebug(RexxDirectory *)
RexxString * pullInput(RexxActivation *)
bool callObjectFunctionExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t, size_t)
void inheritSettings(RexxActivity *parent)
bool callNovalueExit(RexxActivation *, RexxString *, RexxObject *&)
void traceOutput(RexxActivation *, RexxString *)
void callInitializationExit(RexxActivation *)
static ExitContextInterface exitContextFunctions
RexxObject * getLocalEnvironment(RexxString *name)
void createMethodContext(MethodContext &context, RexxNativeActivation *owner)
bool callFunctionExit(RexxActivation *, RexxString *, RexxObject *, ProtectedObject &, RexxObject **, size_t)
RexxString * messageSubstitution(RexxString *, RexxArray *)
void raiseException(wholenumber_t, RexxString *, RexxArray *, RexxObject *)
void terminatePoolActivity()
RexxString * getLastMessageName()
size_t activationStackSize
RexxInternalStack * activations
ActivationFrame * activationFrames
RexxActivationBase * topStackFrame
void disableExit(int exitNum)
void validateThread()
SysSemaphore guardsem
void popStackFrame(bool reply)
SysActivity currentThread
void cleanupActivityResources()
RexxActivity * spawnReply()
void liveGeneral(int reason)
void checkStackSpace()
RexxDirectory * threadLocalEnvironment
bool callTraceExit(RexxActivation *, RexxString *)
void unwindToDepth(size_t depth)
InterpreterInstance * instance
RexxString * buildMessage(wholenumber_t, RexxArray *)
NumericSettings * numericSettings
void addToInstance(InterpreterInstance *interpreter)
void reraiseException(RexxDirectory *)
bool isExitEnabled(int exitNum)
wholenumber_t displayCondition(RexxDirectory *conditionObject)
RexxString * lineIn(RexxActivation *)
void updateFrameMarkers()
void unwindToFrame(RexxActivation *frame)
void releaseAccess()
RexxDirectory * conditionobj
void createNewActivationStack()
void detachInstance()
bool callPullExit(RexxActivation *, RexxString *&)
void createCallContext(CallContext &context, RexxNativeActivation *owner)
void resetRunningRequires()
void runThread()
void createExitContext(ExitContext &context, RexxNativeActivation *owner)
SecurityManager * getInstanceSecurityManager()
wholenumber_t errorNumber(RexxDirectory *conditionObject)
RexxMessage * dispatchMessage
SysSemaphore runsem
void checkActivationStack()
void clearCurrentCondition()
void raisePropagate(RexxDirectory *)
bool callPushExit(RexxActivation *, RexxString *, int)
RexxDirectory * createConditionObject(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
RexxMethod * getLastMethod()
static CallContextInterface callContextFunctions
bool callHaltClearExit(RexxActivation *)
static RexxThreadInterface threadContextFunctions
void exitCurrentThread()
RexxTable * requiresTable
bool callExit(RexxActivation *activation, const char *exitName, int function, int subfunction, void *exitbuffer)
void live(size_t)
RexxString * resolveProgramName(RexxString *, RexxString *, RexxString *)
void generateRandomNumberSeed()
RexxActivationBase * getTopStackFrame()
void sayOutput(RexxActivation *, RexxString *)
bool callQueueSizeExit(RexxActivation *, RexxInteger *&)
bool callCommandExit(RexxActivation *, RexxString *, RexxString *, ProtectedObject &result, ProtectedObject &condition)
RexxDirectory * getLocal()
ActivityContext threadContext
RexxArray * generateStackFrames(bool skipFirst)
bool callValueExit(RexxActivation *, RexxString *, RexxString *, RexxObject *, RexxObject *&)
RexxObject * display(RexxDirectory *)
void flatten(RexxEnvelope *)
void checkDeadLock(RexxActivity *)
RexxDirectory * createExceptionObject(wholenumber_t, RexxString *, RexxArray *, RexxObject *)
void setSuspended(bool s)
RexxObject * waitingObject
ProtectedObject * protectedObjects
ExitHandler & getExitHandler(int exitNum)
bool callSayExit(RexxActivation *, RexxString *)
RexxObject * lineOut(RexxString *)
void unwindStackFrame()
void cleanupStackFrame(RexxActivationBase *poppedStackFrame)
bool callTerminalInputExit(RexxActivation *, RexxString *&)
void waitReserve(RexxObject *)
size_t stackFrameDepth
uint64_t randomSeed
bool setTrace(bool)
bool raiseCondition(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
bool callDebugInputExit(RexxActivation *, RexxString *&)
RexxActivation * getCurrentRexxFrame()
RexxString * traceInput(RexxActivation *)
size_t append(RexxObject *)
Definition: ArrayClass.cpp:485
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
int64_t getBaseTime()
RexxObject * at(RexxString *)
RexxObject * put(RexxObject *, RexxString *)
RexxObject * remove(RexxString *)
RexxObject * fastPop()
RexxObject * peek(size_t v)
void push(RexxObject *value)
RexxObject * getTop()
RexxObject * append(RexxObject *)
Definition: ListClass.cpp:538
RexxArray * makeArray()
Definition: ListClass.cpp:873
void runUninits()
Definition: RexxMemory.cpp:520
void verboseMessage(const char *message)
Definition: RexxMemory.hpp:240
void run(RexxMethod *_method, RexxNativeMethod *_code, RexxObject *_receiver, RexxString *_msgname, RexxObject **_arglist, size_t _argcount, size_t _named_argcount, ProtectedObject &resultObj)
void setConditionInfo(RexxDirectory *info)
RexxString * stringValue()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
virtual bool numberValue(wholenumber_t &result, size_t precision)
virtual RexxString * defaultName()
RexxString * getProgramName()
Definition: SourceFile.hpp:300
PackageClass * getPackage()
RexxString * extractC(sizeC_t offset, sizeC_t sublength)
void toRxstring(CONSTRXSTRING &r)
const char * getStringData()
RexxString * concatWithCstring(const char *)
bool isEqual(RexxObject *)
RexxString * concat(RexxString *)
RexxString * concatWith(RexxString *, char)
sizeC_t pos(RexxString *, sizeC_t)
sizeC_t getCLength()
codepoint_t getCharC(sizeC_t p)
sizeB_t getBLength()
bool checkFunctionCall(RexxString *functionName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)
bool checkCommand(RexxActivity *, RexxString *address, RexxString *command, ProtectedObject &result, ProtectedObject &condition)
RexxString * getTraceLine()
RexxObject * getLine()
static void yield()
thread_id_t getThreadID()
void create(RexxActivity *activity, size_t stackSize)
char * getStackBase(size_t stackSize)
void wait(const char *ds, int di)
void setSemVariable(const char *variable)
static void getCurrentTime(RexxDateTime *Date)
static RexxString * getMessageText(wholenumber_t code)
static RexxString * getMessageHeader(wholenumber_t code)
static void * allocateResultMemory(sizeB_t)
static void releaseResultMemory(void *)
static wholenumber_t currentThreadId()
static bool traceConcurrency()
static int snprintf(char *buffer, size_t count, const char *format,...)
stringsizeC_t sizeC_t
Definition: rexx.h:242
struct _RexxStringObject * RexxStringObject
Definition: rexx.h:128
ssize_t codepoint_t
Definition: rexx.h:232
CONSTANT_RXSTRING * PCONSTRXSTRING
Definition: rexx.h:186
struct _RexxObjectPtr * RexxObjectPtr
Definition: rexx.h:127
#define NULLOBJECT
Definition: rexx.h:147
ssize_t wholenumber_t
Definition: rexx.h:230
#define MAKERXSTRING(r, p, l)
Definition: rexx.h:182
#define size_v(X)
Definition: rexx.h:237
#define RXINIEXT
Definition: rexxapidefs.h:192
#define RXTRCTST
Definition: rexxapidefs.h:190
#define RXTER
Definition: rexxapidefs.h:193
#define RXEXIT_RAISE_ERROR
Definition: rexxapidefs.h:147
#define RXSIOSAY
Definition: rexxapidefs.h:181
#define RXMSQ
Definition: rexxapidefs.h:175
#define RXSIO
Definition: rexxapidefs.h:180
#define RXSIOTRC
Definition: rexxapidefs.h:182
#define RXHLTCLR
Definition: rexxapidefs.h:187
#define RXSIOTRD
Definition: rexxapidefs.h:183
#define RXHLTTST
Definition: rexxapidefs.h:188
#define RXCMDHST
Definition: rexxapidefs.h:174
#define RXFNCCAL
Definition: rexxapidefs.h:172
#define RXFNC
Definition: rexxapidefs.h:171
#define RXEXFCAL
Definition: rexxapidefs.h:197
#define RXINI
Definition: rexxapidefs.h:191
#define RXMSQSIZ
Definition: rexxapidefs.h:178
#define RXMSQPLL
Definition: rexxapidefs.h:176
#define RXNOVALCALL
Definition: rexxapidefs.h:199
#define RXHLT
Definition: rexxapidefs.h:186
#define RXTRC
Definition: rexxapidefs.h:189
#define RXSIODTR
Definition: rexxapidefs.h:184
#define RXOFNCCAL
Definition: rexxapidefs.h:203
#define RXVALUE
Definition: rexxapidefs.h:200
#define RXVALUECALL
Definition: rexxapidefs.h:201
#define RXOFNC
Definition: rexxapidefs.h:202
#define RXEXF
Definition: rexxapidefs.h:196
#define RXMSQNAM
Definition: rexxapidefs.h:179
#define RXCMD
Definition: rexxapidefs.h:173
#define RXEXIT_HANDLED
Definition: rexxapidefs.h:145
#define RXMSQPSH
Definition: rexxapidefs.h:177
#define RXTEREXT
Definition: rexxapidefs.h:194
#define RXNOVAL
Definition: rexxapidefs.h:198
unsigned rxfcfail
Definition: rexx.h:693
unsigned rxfcerr
Definition: rexx.h:694
RXSTRING rxcmd_retc
Definition: rexx.h:704
RXCMD_FLAGS rxcmd_flags
Definition: rexx.h:698
CONSTANT_STRING rxcmd_address
Definition: rexx.h:699
unsigned short rxcmd_dll_len
Definition: rexx.h:702
unsigned short rxcmd_addressl
Definition: rexx.h:700
CONSTANT_STRING rxcmd_dll
Definition: rexx.h:701
CONSTANT_RXSTRING rxcmd_command
Definition: rexx.h:703
unsigned rxfferr
Definition: rexx.h:677
unsigned rxffsub
Definition: rexx.h:679
unsigned rxffnfnd
Definition: rexx.h:678
CONSTANT_RXSTRING rxfnc_name
Definition: rexx.h:684
RexxObjectPtr rxfnc_retc
Definition: rexx.h:687
RexxObjectPtr * rxfnc_argv
Definition: rexx.h:686
size_t rxfnc_argc
Definition: rexx.h:685
RXEXF_FLAGS rxfnc_flags
Definition: rexx.h:683
unsigned rxfferr
Definition: rexx.h:639
unsigned rxffsub
Definition: rexx.h:641
unsigned rxffnfnd
Definition: rexx.h:640
PCONSTRXSTRING rxfnc_argv
Definition: rexx.h:651
unsigned short rxfnc_namel
Definition: rexx.h:647
RXSTRING rxfnc_retc
Definition: rexx.h:652
RXFNC_FLAGS rxfnc_flags
Definition: rexx.h:645
CONSTANT_STRING rxfnc_que
Definition: rexx.h:648
unsigned short rxfnc_quel
Definition: rexx.h:649
unsigned short rxfnc_argc
Definition: rexx.h:650
CONSTANT_STRING rxfnc_name
Definition: rexx.h:646
unsigned rxfhhalt
Definition: rexx.h:774
RXHLT_FLAGS rxhlt_flags
Definition: rexx.h:778
unsigned rxfmlifo
Definition: rexx.h:718
RXSTRING rxmsq_name
Definition: rexx.h:738
RXSTRING rxmsq_retc
Definition: rexx.h:711
RXMSQ_FLAGS rxmsq_flags
Definition: rexx.h:723
CONSTANT_RXSTRING rxmsq_value
Definition: rexx.h:724
size_t rxmsq_size
Definition: rexx.h:731
unsigned rxfferr
Definition: rexx.h:659
unsigned rxffnfnd
Definition: rexx.h:660
unsigned rxffsub
Definition: rexx.h:661
CONSTANT_RXSTRING rxfnc_name
Definition: rexx.h:666
RexxObjectPtr rxfnc_retc
Definition: rexx.h:669
RexxObjectPtr * rxfnc_argv
Definition: rexx.h:668
RXOFNC_FLAGS rxfnc_flags
Definition: rexx.h:665
size_t rxfnc_argc
Definition: rexx.h:667
CONSTANT_RXSTRING rxsio_string
Definition: rexx.h:746
RXSTRING rxsiotrd_retc
Definition: rexx.h:760
char * strptr
Definition: rexx.h:158
unsigned rxftrace
Definition: rexx.h:785
RXTRC_FLAGS rxtrc_flags
Definition: rexx.h:790
RexxStringObject variable_name
Definition: rexx.h:802
RexxStringObject selector
Definition: rexx.h:801
RexxObjectPtr value
Definition: rexx.h:803
RexxStringObject variable_name
Definition: rexx.h:795
RexxObjectPtr value
Definition: rexx.h:796
RexxActivity * owningActivity
RexxThreadContext threadContext
RexxNativeActivation * context
RexxCallContext threadContext
RexxNativeActivation * context
RexxExitContext threadContext
RexxNativeActivation * context
RexxMethodContext threadContext
CallContextInterface * functions
Definition: oorexxapi.h:2201
RexxThreadContext * threadContext
Definition: oorexxapi.h:2200
RexxThreadContext * threadContext
Definition: oorexxapi.h:2972
ExitContextInterface * functions
Definition: oorexxapi.h:2973
MethodContextInterface * functions
Definition: oorexxapi.h:1431
RexxThreadContext * threadContext
Definition: oorexxapi.h:1430
RexxThreadInterface * functions
Definition: oorexxapi.h:717
RexxInstance * instance
Definition: oorexxapi.h:716
RexxStringObject RexxNullString
Definition: oorexxapi.h:604
RexxObjectPtr RexxFalse
Definition: oorexxapi.h:603
RexxObjectPtr RexxTrue
Definition: oorexxapi.h:602
RexxObjectPtr RexxNil
Definition: oorexxapi.h:601
#define C_STACK_SIZE
#define TOTAL_STACK_SIZE
#define MIN_C_STACK
#define DEFRXSTRING
void dbgprintf(const char *format,...)
pthread_t thread_id_t
char work[256]
char line[LINEBUFSIZE]
UINT_PTR uintptr_t
unsigned __int64 uint64_t