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