RexxNativeActivation.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 RexxNativeActivation.cpp */
40 /* */
41 /* Primitive Native Activation Class */
42 /* */
43 /******************************************************************************/
44 #include "RexxCore.h"
45 #include "StringClass.hpp"
46 #include "ArrayClass.hpp"
47 #include "DirectoryClass.hpp"
48 #include "MethodClass.hpp"
49 #include "RexxNativeCode.hpp"
50 #include "RexxActivation.hpp"
51 #include "RexxNativeActivation.hpp"
52 #include "BufferClass.hpp"
53 #include "MessageClass.hpp"
55 #include "SourceFile.hpp"
56 #include "RexxCode.hpp"
57 #include "RexxInstruction.hpp"
59 #include "ProtectedObject.hpp"
60 #include "PointerClass.hpp"
61 #include "ActivityDispatcher.hpp"
62 #include "CallbackDispatcher.hpp"
63 #include "TrappingDispatcher.hpp"
64 #include "Interpreter.hpp"
65 #include "SystemInterpreter.hpp"
66 #include "ActivationFrame.hpp"
67 #include "StackFrameClass.hpp"
68 #include "MutableBufferClass.hpp"
69 
70 #include <math.h>
71 #include <limits.h>
72 
73 #include "SysDebug.hpp"
74 
75 
76 /**
77  * Initialize an activation for direct caching in the activation
78  * cache. At this time, this is not an executable activation
79  */
81 {
82  this->setHasNoReferences(); // nothing referenced from this either
83 }
84 
85 
86 /**
87  * Constructor for a new native activation used to create a
88  * callback context for exit call outs.
89  *
90  * @param _activity The activity we're running under.
91  */
93 {
94  this->clearObject(); /* start with a fresh object */
95  this->activity = _activity; /* the activity running on */
96  this->activation = _activation; // our parent context
97 }
98 
99 
100 /**
101  * Constructor for a new native activation used to create a
102  * callback context for exit call outs.
103  *
104  * @param _activity The activity we're running under.
105  */
107 {
108  this->clearObject(); /* start with a fresh object */
109  this->activity = _activity; /* the activity running on */
110 }
111 
112 
113 void RexxNativeActivation::live(size_t liveMark)
114 /******************************************************************************/
115 /* Function: Normal garbage collection live marking */
116 /******************************************************************************/
117 {
118  memory_mark(this->previous);
119  memory_mark(this->executable);
120  memory_mark(this->argArray);
121  memory_mark(this->argDirectory);
122  memory_mark(this->receiver);
123  memory_mark(this->activity);
124  memory_mark(this->activation);
125  memory_mark(this->msgname);
126  memory_mark(this->savelist);
127  memory_mark(this->result);
128  memory_mark(this->nextstem);
130  memory_mark(this->nextcurrent);
132  memory_mark(this->conditionObj);
134 
135  /* We're hold a pointer back to our arguments directly where they */
136  /* are created. Since in some places, this argument list comes */
137  /* from the C stack, we need to handle the marker ourselves. */
138  size_t i;
139  for (i = 0; i < (argcount + (2 * named_argcount)); i++)
140  {
141  memory_mark(arglist[i]);
142  }
143 }
144 
146 /******************************************************************************/
147 /* Function: Generalized object marking */
148 /******************************************************************************/
149 {
166 
167  /* We're hold a pointer back to our arguments directly where they */
168  /* are created. Since in some places, this argument list comes */
169  /* from the C stack, we need to handle the marker ourselves. */
170  size_t i;
171  for (i = 0; i < (argcount + (2 * named_argcount)); i++)
172  {
174  }
175 }
176 
177 
179 /******************************************************************************/
180 /* Function: Report a method signature error */
181 /******************************************************************************/
182 {
184  {
186  }
187  else
188  {
190  }
191 }
192 
193 
194 void RexxNativeActivation::reportStemError(size_t position, RexxObject *object)
195 /******************************************************************************/
196 /* Function: Report a method signature error */
197 /******************************************************************************/
198 {
200  {
201  reportException(Error_Incorrect_method_nostem, position + 1, object);
202  }
203  else
204  {
205  reportException(Error_Incorrect_call_nostem, OREF_POSITIONAL, position + 1, object);
206  }
207 }
208 
209 
210 /**
211  * Process the arguments for a typed function/method call.
212  *
213  * @param argcount The count of arguments.
214  * @param arglist The original Rexx arguments.
215  * @param argumentTypes
216  * The type descriptor from the target.
217  * @param descriptors
218  * The maximum argument count for the target.
219  * @param maximumArgumentCount
220  */
221 void RexxNativeActivation::processArguments(size_t _argcount, RexxObject **_arglist, uint16_t *argumentTypes,
222  ValueDescriptor *descriptors, size_t maximumArgumentCount)
223 {
224  size_t inputIndex = 0; // no arguments used yet */
225  size_t outputIndex = 1; // we start filling in from the second (first is return value)
226  bool usedArglist = false; // if we request the argument list, then there's no requirement
227  // to use up all of the passed arguments individually.
228 
229  // set up the return value descriptor
230  descriptors[0].type = *argumentTypes;
231  descriptors[0].value.value_int64_t = 0;
232  // the first type in the signature is the return value, which we skip for now
233  uint16_t *currentType = argumentTypes + 1;
234  // now loop through the type information. Some of the types are "created"
235  // arguments that don't appear directly in the method/function invocation.
236  // We can't directly do a 1-for-1 mapping
237  for (; *currentType != REXX_ARGUMENT_TERMINATOR; currentType++)
238  {
239  // make sure we don't get a buffer overload
240  if (outputIndex >= maximumArgumentCount)
241  {
243  }
244 
245  uint16_t type = ARGUMENT_TYPE(*currentType);
246  bool isOptional = IS_OPTIONAL_ARGUMENT(*currentType);
247 
248  descriptors[outputIndex].type = type; // fill in the type
249  switch (type)
250  {
251  // reference to the receiver object...if this is a function call,
252  // then this will be OREF NULL.
253  case REXX_VALUE_OSELF: /* reference to SELF */
254  {
255  // this doesn't make any sense for a function call
257  {
259  }
260  // fill in the receiver object and mark it...
261  descriptors[outputIndex].value.value_RexxObjectPtr = (RexxObjectPtr)this->receiver;
262  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
263  break;
264  }
265 
266  // reference to the method scope...if this is a function call,
267  // then this will be OREF NULL.
268  case REXX_VALUE_SCOPE:
269  {
270  // this doesn't make any sense for a function call
272  {
274  }
275  // fill in the receiver object and mark it...
276  descriptors[outputIndex].value.value_RexxObjectPtr = (RexxObjectPtr)this->getScope();
277  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
278  break;
279  }
280 
281  // reference to the superclass scope...if this is a function call,
282  // then this will be OREF NULL.
283  case REXX_VALUE_SUPER:
284  {
285  // this doesn't make any sense for a function call
287  {
289  }
290  // fill in the receiver object and mark it...
291  descriptors[outputIndex].value.value_RexxObjectPtr = (RexxClassObject)this->getSuper();
292  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
293  break;
294  }
295 
296  case REXX_VALUE_CSELF: /* reference to CSELF */
297  {
298  // this doesn't make any sense for a function call
300  {
302  }
303  descriptors[outputIndex].value.value_POINTER = this->cself();
304  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
305  break;
306  }
307 
308  case REXX_VALUE_ARGLIST: /* need the argument list */
309  {
310  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
312  // we've used this
313  usedArglist = true;
314  break;
315  }
316 
317  // This is either the message name used to invoke a method or
318  // the name used to call a function
319  case REXX_VALUE_NAME:
320  {
321  descriptors[outputIndex].flags = ARGUMENT_EXISTS | SPECIAL_ARGUMENT;
322  descriptors[outputIndex].value.value_CSTRING = (CSTRING)this->msgname->getStringData();
323  break;
324  }
325 
326  // this is a real argument taken from the argument list
327  default: /* still within argument bounds? */
328  {
329  if (inputIndex < _argcount && _arglist[inputIndex] != OREF_NULL)
330  {
331  // all of these arguments exist
332  descriptors[outputIndex].flags = ARGUMENT_EXISTS;
333  RexxObject *argument = _arglist[inputIndex]; /* get the next argument */
334  switch (type)
335  { /* process this type */
336 
337  case REXX_VALUE_RexxObjectPtr: /* arbitrary object reference */
338  {
339  descriptors[outputIndex].value.value_RexxObjectPtr = (RexxObjectPtr)argument;
340  break;
341  }
342 
343  case REXX_VALUE_int: /* integer value */
344  {
345  // convert and copy */
346  descriptors[outputIndex].value.value_int = (int)signedIntegerValue(argument, inputIndex, INT_MAX, INT_MIN);
347  break;
348  }
349 
350  case REXX_VALUE_int8_t: /* 8-bit integer value */
351  {
352  descriptors[outputIndex].value.value_int8_t = (int8_t)signedIntegerValue(argument, inputIndex, INT8_MAX, INT8_MIN);
353  break;
354  }
355 
356  case REXX_VALUE_int16_t: /* integer value */
357  {
358  descriptors[outputIndex].value.value_int16_t = (int16_t)signedIntegerValue(argument, inputIndex, INT16_MAX, INT16_MIN);
359  break;
360  }
361 
362  case REXX_VALUE_int32_t: /* integer value */
363  {
364  descriptors[outputIndex].value.value_int32_t = (int32_t)signedIntegerValue(argument, inputIndex, INT32_MAX, INT32_MIN);
365  break;
366  }
367 
368  case REXX_VALUE_int64_t: /* integer value */
369  {
370  descriptors[outputIndex].value.value_int64_t = (int64_t)int64Value(argument, inputIndex);
371  break;
372  }
373 
374  case REXX_VALUE_ssize_t: /* integer value */
375  {
376  descriptors[outputIndex].value.value_ssize_t = (ssize_t)signedIntegerValue(argument, inputIndex, SSIZE_MAX, -SSIZE_MAX - 1);
377  break;
378  }
379 
380  case REXX_VALUE_intptr_t: /* integer value */
381  {
382  descriptors[outputIndex].value.value_intptr_t = (intptr_t)signedIntegerValue(argument, inputIndex, INTPTR_MAX, INTPTR_MIN);
383  break;
384  }
385 
386  case REXX_VALUE_uint8_t: /* 8-bit integer value */
387  {
388  descriptors[outputIndex].value.value_uint8_t = (uint8_t)unsignedIntegerValue(argument, inputIndex, UINT8_MAX);
389  break;
390  }
391 
392  case REXX_VALUE_uint16_t: /* integer value */
393  {
394  descriptors[outputIndex].value.value_uint16_t = (uint16_t)unsignedIntegerValue(argument, inputIndex, UINT16_MAX);
395  break;
396  }
397 
398  case REXX_VALUE_uint32_t: /* integer value */
399  {
400  descriptors[outputIndex].value.value_uint32_t = (uint32_t)unsignedIntegerValue(argument, inputIndex, UINT32_MAX);
401  break;
402  }
403 
404  case REXX_VALUE_uint64_t: /* integer value */
405  {
406  descriptors[outputIndex].value.value_uint64_t = (uint64_t)unsignedInt64Value(argument, inputIndex);
407  break;
408  }
409 
410  case REXX_VALUE_size_t: /* integer value */
411  {
412  descriptors[outputIndex].value.value_size_t = (size_t)unsignedIntegerValue(argument, inputIndex, SIZE_MAX);
413  break;
414  }
415 
416  case REXX_VALUE_uintptr_t: /* integer value */
417  {
418  descriptors[outputIndex].value.value_uintptr_t = (uintptr_t)unsignedIntegerValue(argument, inputIndex, UINTPTR_MAX);
419  break;
420  }
421 
422  case REXX_VALUE_logical_t: /* integer value */
423  {
424  descriptors[outputIndex].value.value_logical_t = argument->truthValue(Error_Logical_value_method);
425  break;
426  }
427 
428  // The Rexx whole number one is checked against the human digits limit
429  case REXX_VALUE_wholenumber_t: /* number value */
430  {
432  break;
433  }
434 
435  // an unsigned string number value
437  {
438  descriptors[outputIndex].value.value_stringsize_t = (stringsize_t)unsignedIntegerValue(argument, inputIndex, Numerics::MAX_STRINGSIZE);
439  break;
440  }
441 
442  case REXX_VALUE_double: /* double value */
443  {
444  descriptors[outputIndex].value.value_double = this->getDoubleValue(argument, inputIndex);
445  break;
446  }
447 
448 
449  case REXX_VALUE_float: /* float value */
450  {
451  descriptors[outputIndex].value.value_float = (float)this->getDoubleValue(argument, inputIndex);
452  break;
453  }
454 
455  case REXX_VALUE_CSTRING: /* ASCII-Z string value */
456  {
457  descriptors[outputIndex].value.value_CSTRING = this->cstring(argument);
458  break;
459  }
460 
461  case REXX_VALUE_RexxStringObject: /* Required STRING object */
462  {
463  /* force to a string value */
464  RexxString *temp = stringArgument(argument, OREF_POSITIONAL, inputIndex + 1);
465  // if this forced a string object to be created,
466  // we need to protect it here.
467  if (temp != argument)
468  {
469  /* make it safe */
470  createLocalReference(temp);
471  }
472  /* set the result in */
473  descriptors[outputIndex].value.value_RexxStringObject = (RexxStringObject)temp;
474  break;
475 
476  }
477 
478  case REXX_VALUE_RexxArrayObject: /* Required ARRAY object */
479  {
480  /* force to a string value */
481  RexxArray *temp = arrayArgument(argument, OREF_POSITIONAL, inputIndex + 1);
482  // if this forced a string object to be created,
483  // we need to protect it here.
484  if (temp != argument)
485  {
486  /* make it safe */
487  createLocalReference(temp);
488  }
489  /* set the result in */
490  descriptors[outputIndex].value.value_RexxArrayObject = (RexxArrayObject)temp;
491  break;
492 
493  }
494 
495  case REXX_VALUE_RexxStemObject: /* Required Stem object */
496  {
497  // Stem arguments get special handling. If the argument
498  // object is already a stem object, we're done. Otherwise,
499  // we get the string value of the argument and use that
500  // to resolve a stem name in the current context. If the
501  // trailing period is not given on the name, one will be added.
502  // Note that the second form is only available if this is a
503  // call context. This is an error for a method context.
504 
505  // is this a stem already?
506  if (isStem(argument))
507  {
508  /* set the result in */
509  descriptors[outputIndex].value.value_RexxStemObject = (RexxStemObject)argument;
510  break;
511  }
512 
513  // this spesn't make any sense for a function call
515  {
516  reportStemError(inputIndex, argument);
517  }
518 
519  /* force to a string value */
520  RexxString *temp = argument->requestString();
521  if ((RexxObject *)temp == TheNilObject)
522  {
523  reportStemError(inputIndex, argument);
524  }
525  // if this forced a string object to be created,
526  // we need to protect it here.
527  if (temp != argument)
528  {
529  /* make it safe */
530  createLocalReference(temp);
531  }
532 
533  // see if we can retrieve this stem
534  RexxObject *stem = getContextStem(temp);
535  if (stem == OREF_NULL)
536  {
537  reportStemError(inputIndex, argument);
538  }
539  /* set the result in */
540  descriptors[outputIndex].value.value_RexxStemObject = (RexxStemObject)stem;
541  break;
542  }
543 
544  case REXX_VALUE_RexxClassObject: // required class object
545  {
546  // this must be a class object
547  if (!argument->isInstanceOf(TheClassClass))
548  {
549  reportException(Error_Invalid_argument_noclass, OREF_POSITIONAL, inputIndex + 1, TheClassClass->getId());
550  }
551  /* set the result in */
552  descriptors[outputIndex].value.value_RexxClassObject = (RexxClassObject)argument;
553  break;
554  }
555 
556  case REXX_VALUE_POINTER:
557  {
558  // this must be a pointer object
559  if (!argument->isInstanceOf(ThePointerClass))
560  {
561  reportException(Error_Invalid_argument_noclass, OREF_POSITIONAL, inputIndex + 1, ThePointerClass->getId());
562  }
563  descriptors[outputIndex].value.value_POINTER = this->pointer(argument);
564  break;
565  }
566 
568  {
569  descriptors[outputIndex].value.value_POINTERSTRING = this->pointerString(argument, inputIndex);
570  break;
571  }
572 
574  {
575  // this must be a pointer object
576  if (!argument->isInstanceOf(TheMutableBufferClass))
577  {
578  reportException(Error_Invalid_argument_noclass, OREF_POSITIONAL, inputIndex + 1, TheMutableBufferClass->getId());
579  }
580  descriptors[outputIndex].value.value_RexxMutableBufferObject = (RexxMutableBufferObject)argument;
581  break;
582  }
583 
584  default: /* something messed up */
585  {
587  break;
588  }
589  }
590  }
591  else
592  {
593  // if this was not an option argument
594  if (!isOptional)
595  {
596  /* just raise the error */
597  reportException(Error_Invalid_argument_noarg, OREF_POSITIONAL, inputIndex + 1);
598  }
599 
600  // this is a non-specified argument
601  descriptors[outputIndex].flags = 0;
602  switch (type)
603  {
604 
605  case REXX_VALUE_RexxObjectPtr: // no object here
606  case REXX_VALUE_int: // non-integer value
607  case REXX_VALUE_wholenumber_t: // non-existent long
608  case REXX_VALUE_CSTRING: // missing character string
609  case REXX_VALUE_POINTER:
610  case REXX_VALUE_RexxStringObject: // no object here
611  case REXX_VALUE_stringsize_t: // non-existent long
612  case REXX_VALUE_int8_t: // non-integer value
613  case REXX_VALUE_int16_t: // non-integer value
614  case REXX_VALUE_int32_t: // non-integer value
615  case REXX_VALUE_int64_t: // non-integer value
616  case REXX_VALUE_uint8_t: // non-integer value
617  case REXX_VALUE_uint16_t: // non-integer value
618  case REXX_VALUE_uint32_t: // non-integer value
619  case REXX_VALUE_uint64_t: // non-integer value
620  case REXX_VALUE_size_t:
621  case REXX_VALUE_ssize_t:
622  case REXX_VALUE_intptr_t:
624  case REXX_VALUE_logical_t: // this must be a boolean value
625  case REXX_VALUE_RexxArrayObject: // no object here
630  {
631  // set this as a 64-bit value to clear everything out
632  descriptors[outputIndex].value.value_int64_t = 0;
633  break;
634  }
635  case REXX_VALUE_double: /* non-existent double */
636  {
637  descriptors[outputIndex].value.value_double = 0.0;
638  break;
639  }
640  case REXX_VALUE_float: /* non-existent double */
641  {
642  descriptors[outputIndex].value.value_float = 0.0;
643  break;
644  }
645  /* still an error if not there */
646  default: /* something messed up */
647  {
649  break;
650  }
651  }
652  }
653  inputIndex++; // we've used up one more input argument
654  break;
655  }
656  }
657  outputIndex++; /* step to the next argument */
658  argumentTypes++; // and the next output position pointer
659  }
660  if (inputIndex < _argcount && !usedArglist) /* extra, unwanted arguments? */
661  {
662  /* got too many */
663  reportException(Error_Invalid_argument_maxarg, OREF_POSITIONAL, inputIndex);
664  }
665 }
666 
667 
668 /**
669  * Convert an collection of value descriptors into a Rexx array
670  * object. This is useful for creating arrays of arguments for
671  * the various call APIs.
672  *
673  * @param value The self-describing value descriptors.
674  * @param count The number of descriptors in the list.
675  *
676  * @return The described value converted to an appropriate Rexx object.
677  */
679 {
680  RexxArray *r = new_array(count);
681  ProtectedObject p(r);
682 
683  for (size_t i = 0; i < count; i++)
684  {
685  // convert each of the values in turn
686  r->put(valueToObject(value++), i);
687  }
688  return r;
689 }
690 
691 
692 /**
693  * Convert an API value descriptor into a Rexx object.
694  *
695  * @param value The self-describing value descriptor.
696  *
697  * @return The described value converted to an appropriate Rexx object.
698  */
700 {
701  switch (value->type)
702  {
703  case REXX_VALUE_RexxObjectPtr: // object reference. All object types get
704  case REXX_VALUE_RexxStringObject: // returned as a Rexx object
709  {
710  return (RexxObject *)value->value.value_RexxObjectPtr; // just return the object value
711  }
712 
713  case REXX_VALUE_int: /* integer value */
714  {
716  }
717 
718  case REXX_VALUE_int8_t: /* integer value */
719  {
721  }
722 
723  case REXX_VALUE_int16_t: /* integer value */
724  {
726  }
727 
728  case REXX_VALUE_int32_t: /* integer value */
729  {
731  }
732 
733  case REXX_VALUE_int64_t: /* integer value */
734  {
736  }
737 
738  case REXX_VALUE_intptr_t: /* integer value */
739  {
741  }
742 
743  case REXX_VALUE_uint8_t: /* integer value */
744  {
746  }
747 
748  case REXX_VALUE_uint16_t: /* integer value */
749  {
751  }
752 
753  case REXX_VALUE_uint32_t: /* integer value */
754  {
756  }
757 
758  case REXX_VALUE_uint64_t: /* integer value */
759  {
761  }
762 
763  case REXX_VALUE_uintptr_t: /* integer value */
764  {
766  }
767 
768  case REXX_VALUE_logical_t: /* logical value */
769  {
770  return value->value.value_logical_t == 0 ? TheFalseObject : TheTrueObject;
771  }
772 
773  case REXX_VALUE_size_t: /* integer value */
774  {
776  }
777 
778  case REXX_VALUE_ssize_t: /* integer value */
779  {
781  }
782 
783  case REXX_VALUE_wholenumber_t: /* long integer value */
784  {
786  }
787 
788  case REXX_VALUE_stringsize_t: /* long integer value */
789  {
791  }
792 
793  case REXX_VALUE_double: /* double value */
794  {
795  return new_string(value->value.value_double);
796  }
797 
798  case REXX_VALUE_float: /* float value */
799  {
800  return new_string(value->value.value_float);
801  }
802 
803  case REXX_VALUE_CSTRING: /* ASCII-Z string */
804  {
805  const char *string = value->value.value_CSTRING;
806  // return return nothing if a null pointer is returned.
807  if (string == NULL)
808  {
809  return OREF_NULL;
810  }
811  return new_string(string); // make a Rexx string from this
812  }
813 
814  case REXX_VALUE_POINTER:
815  {
816  // just wrap the pointer in a pointer object
817  return new_pointer(value->value.value_POINTER);
818  }
819 
821  {
822  // format this into a chracter string
824  }
825 
826  case 0:
827  {
828  // useful for creating argument lists. This is an omitted value, so just return
829  // a null value
830  return OREF_NULL;
831  }
832 
833  default:
834  {
835  reportSignatureError(); // bad method signature problem
836  break;
837  }
838  }
839  return OREF_NULL;
840 }
841 
842 
843 /**
844  * Convert a Rexx object into the requested value type, if possible.
845  *
846  * @param o The source object.
847  * @param value The receiving value structure, which also defines the type.
848  *
849  * @return true if the value was convertable, false otherwise.
850  */
852 {
853  switch (value->type)
854  {
855  case REXX_VALUE_RexxObjectPtr: /* Object reference */
856  {
857  // silly, but this always works.
859  return true;
860  }
861  case REXX_VALUE_RexxClassObject: // required class object
862  {
863  // this must be a class object
864  if (!o->isInstanceOf(TheClassClass))
865  {
866  return false;
867  }
868  /* set the result in */
870  return true;
871  }
872  case REXX_VALUE_RexxMutableBufferObject: // required mutablebuffer object
873  {
874  // this must be a mutablebuffer object
876  {
877  return false;
878  }
879  /* set the result in */
881  return true;
882  }
883  case REXX_VALUE_int: /* integer value */
884  {
885  ssize_t temp = 0;
886  // convert and copy */
887  bool success = Numerics::objectToSignedInteger(o, temp, INT_MAX, INT_MIN);
888  value->value.value_int = (int)temp;
889  return success;
890  }
891 
892  case REXX_VALUE_int8_t: /* 8-bit integer value */
893  {
894  ssize_t temp = 0;
895  // convert and copy */
896  bool success = Numerics::objectToSignedInteger(o, temp, INT8_MAX, INT8_MIN);
897  value->value.value_int8_t = (int8_t)temp;
898  return success;
899  }
900 
901  case REXX_VALUE_int16_t: /* integer value */
902  {
903  ssize_t temp = 0;
904  // convert and copy */
905  bool success = Numerics::objectToSignedInteger(o, temp, INT16_MAX, INT16_MIN);
906  value->value.value_int16_t = (int16_t)temp;
907  return success;
908  }
909 
910  case REXX_VALUE_int32_t: /* integer value */
911  {
912  ssize_t temp = 0;
913  // convert and copy */
914  bool success = Numerics::objectToSignedInteger(o, temp, INT32_MAX, INT32_MIN);
915  value->value.value_int32_t = (int32_t)temp;
916  return success;
917  }
918 
919  case REXX_VALUE_intptr_t: /* integer value */
920  {
921  intptr_t temp = 0;
922  // convert and copy */
923  bool success = Numerics::objectToIntptr(o, temp);
924  value->value.value_intptr_t = (intptr_t)temp;
925  return success;
926  }
927 
928  case REXX_VALUE_int64_t: /* integer value */
929  {
930  int64_t temp = 0;
931  // convert and copy */
932  bool success = Numerics::objectToInt64(o, temp);
933  value->value.value_int64_t = (int64_t)temp;
934  return success;
935  }
936 
937  case REXX_VALUE_uint8_t: /* 8-bit integer value */
938  {
939  size_t temp = 0;
940  // convert and copy */
941  bool success = Numerics::objectToUnsignedInteger(o, temp, UINT8_MAX);
942  value->value.value_uint8_t = (uint8_t)temp;
943  return success;
944  }
945 
946  case REXX_VALUE_uint16_t: /* integer value */
947  {
948  size_t temp = 0;
949  // convert and copy */
950  bool success = Numerics::objectToUnsignedInteger(o, temp, UINT16_MAX);
951  value->value.value_uint16_t = (uint16_t)temp;
952  return success;
953  }
954 
955  case REXX_VALUE_uint32_t: /* integer value */
956  {
957  size_t temp = 0;
958  // convert and copy */
959  bool success = Numerics::objectToUnsignedInteger(o, temp, UINT32_MAX);
960  value->value.value_uint32_t = (uint32_t)temp;
961  return success;
962  }
963 
964  case REXX_VALUE_uintptr_t: /* integer value */
965  {
966  uintptr_t temp = 0;
967  // convert and copy */
968  bool success = Numerics::objectToUintptr(o, temp);
969  value->value.value_uintptr_t = (uintptr_t)temp;
970  return success;
971  }
972 
973  case REXX_VALUE_uint64_t: /* integer value */
974  {
975  uint64_t temp = 0;
976  // convert and copy */
977  bool success = Numerics::objectToUnsignedInt64(o, temp);
978  value->value.value_uint64_t = (uint64_t)temp;
979  return success;
980  }
981 
982  case REXX_VALUE_size_t: /* integer value */
983  {
984  size_t temp = 0;
985  // convert and copy */
986  bool success = Numerics::objectToUnsignedInteger(o, temp, SIZE_MAX);
987  value->value.value_size_t = (size_t)temp;
988  return success;
989  }
990 
991  case REXX_VALUE_logical_t: /* integer value */
992  {
993  // this converts without raising an error
994  return o->logicalValue(value->value.value_logical_t);
995  }
996 
997  // The Rexx whole number one is checked against the human digits limit
998  case REXX_VALUE_wholenumber_t: /* number value */
999  {
1000  wholenumber_t temp = 0;
1001  // convert and copy */
1003  value->value.value_wholenumber_t = (wholenumber_t)temp;
1004  return success;
1005  }
1006 
1007  // The Rexx whole number one is checked against the human digits limit
1008  case REXX_VALUE_ssize_t: /* ssize_t value */
1009  {
1010  ssize_t temp = 0;
1011  // convert and copy */
1012  // NB: SSIZE_MIN appears to be defined as 0 for some bizarre reason on some platforms,
1013  // so we'll make things relative to SIZE_MAX.
1014  bool success = Numerics::objectToSignedInteger(o, temp, SSIZE_MAX, (-SSIZE_MAX) - 1);
1015  value->value.value_wholenumber_t = (wholenumber_t)temp;
1016  return success;
1017  }
1018 
1019  // an unsigned string number value
1021  {
1022  stringsize_t temp = 0;
1023  // convert and copy */
1024  bool success = Numerics::objectToStringSize(o, temp, Numerics::MAX_STRINGSIZE);
1025  value->value.value_stringsize_t = temp;
1026  return success;
1027  }
1028 
1029  case REXX_VALUE_double: /* double value */
1030  {
1031  return o->doubleValue(value->value.value_double);
1032  }
1033 
1034 
1035  case REXX_VALUE_float: /* float value */
1036  {
1037  double temp = 0.0;
1038  bool success = o->doubleValue(temp);
1039  value->value.value_float = (float)temp;
1040  return success;
1041  }
1042 
1043  case REXX_VALUE_CSTRING: /* ASCII-Z string value */
1044  {
1045  value->value.value_CSTRING = this->cstring(o);
1046  return true;
1047  }
1048 
1049  case REXX_VALUE_RexxStringObject: /* Required STRING object */
1050  {
1051  /* force to a string value */
1052  RexxString *temp = stringArgument(o, OREF_POSITIONAL, 1);
1053  // if this forced a string object to be created,
1054  // we need to protect it here.
1055  if (temp != o)
1056  {
1057  /* make it safe */
1058  createLocalReference(temp);
1059  }
1060  /* set the result in */
1062  return true;
1063 
1064  }
1065 
1066  case REXX_VALUE_RexxArrayObject: /* Required ARRAY object */
1067  {
1068  /* force to a string value */
1069  RexxArray *temp = arrayArgument(o, OREF_positional, 1);
1070  // if this forced a string object to be created,
1071  // we need to protect it here.
1072  if (temp != o)
1073  {
1074  /* make it safe */
1075  createLocalReference(temp);
1076  }
1077  /* set the result in */
1079  return true;
1080 
1081  }
1082 
1083  case REXX_VALUE_RexxStemObject: /* Required Stem object */
1084  {
1085  // Stem os get special handling. If the o
1086  // object is already a stem object, we're done. Otherwise,
1087  // we get the string value of the o and use that
1088  // to resolve a stem name in the current context. If the
1089  // trailing period is not given on the name, one will be added.
1090  // Note that the second form is only available if this is a
1091  // call context. This is an error for a method context.
1092 
1093  // is this a stem already?
1094  if (isStem(o))
1095  {
1096  /* set the result in */
1098  return true;
1099  }
1100 
1101  // this doesn't make any sense for a function call
1103  {
1104  return false;
1105  }
1106 
1107  /* force to a string value */
1108  RexxString *temp = stringArgument(o, OREF_positional, 1);
1109  // if this forced a string object to be created,
1110  // we need to protect it here.
1111  if (temp != o)
1112  {
1113  /* make it safe */
1114  createLocalReference(temp);
1115  }
1116 
1117  // see if we can retrieve this stem
1118  RexxObject *stem = getContextStem(temp);
1119  if (stem == OREF_NULL)
1120  {
1121  return false;
1122  }
1123  /* set the result in */
1124  value->value.value_RexxStemObject = (RexxStemObject)stem;
1125  return true;
1126  }
1127 
1128  case REXX_VALUE_POINTER:
1129  {
1130  value->value.value_POINTER = this->pointer(o);
1131  return true;
1132  }
1133 
1135  {
1136  /* force to a string value */
1137  RexxString *string = o->stringValue();
1138 
1139  void *pointerVal;
1140  if (sscanf(string->getStringData(), "0x%p", &pointerVal) != 1)
1141  {
1142  return false;
1143  }
1144 
1145  value->value.value_POINTER = pointerVal;
1146  return true;
1147  }
1148 
1149  default: /* something messed up */
1150  {
1151  return false;
1152  }
1153  }
1154  return false;
1155 }
1156 
1157 
1158 /**
1159  * Create a local reference for an object. The protects the object
1160  * from GC until the environment terminates.
1161  *
1162  * @param objr The object to protect.
1163  */
1165 {
1166  // if we have a real object, then add to the list
1167  if (objr != OREF_NULL)
1168  {
1169  // make sure we protect this from a GC triggered by this table creation.
1170  ProtectedObject p1(objr);
1171  if (this->savelist == OREF_NULL) /* first saved object? */
1172  {
1173  /* create the save list now */
1174  this->savelist = new_identity_table();
1175  }
1176  /* add to the save table */
1177  this->savelist->put(objr, objr);
1178  }
1179 }
1180 
1181 
1182 /**
1183  * Remove an object from the local reference table.
1184  *
1185  * @param objr The object to remove.
1186  */
1188 {
1189  // if the reference is non-null
1190  if (objr != OREF_NULL)
1191  {
1192  // make sure we have a savelist before trying to remove this
1193  if (savelist != OREF_NULL)
1194  {
1195  // NB...this is a special remove that functions using the object
1196  // identify to avoid false positives or potential exceptions caused
1197  // by calling EQUALS methods.
1198  savelist->remove(objr);
1199  }
1200  }
1201 }
1202 
1203 
1204 /**
1205  * Run a native method or function under the context of this activation.
1206  *
1207  * @param _receiver The receiver object (NULL if not a method invocation).
1208  * @param _msgname The message name.
1209  * @param _argcount The argument count
1210  * @param _arglist The list of arguments.
1211  * @param resultObj The returned result object.
1212  */
1214  RexxString *_msgname, RexxObject **_arglist, size_t _argcount, size_t _named_argcount, ProtectedObject &resultObj)
1215 {
1216  // add the frame to the execution stack
1217  NativeActivationFrame frame(activity, this);
1218  // anchor the relevant context information
1219  executable = _method;
1220  receiver = _receiver;
1221  msgname = _msgname;
1222  arglist = _arglist;
1223  argcount = _argcount;
1224  named_argcount = _named_argcount;
1225  activationType = METHOD_ACTIVATION; // this is for running a method
1226 
1228 
1229  MethodContext context; // the passed out method context
1230 
1231  // sort out our active security manager
1233  if (securityManager == OREF_NULL)
1234  {
1236  }
1237 
1238  // build a context pointer to pass out
1239  activity->createMethodContext(context, this);
1240 
1241  context.threadContext.arguments = arguments;
1242 
1243  // get the entry point address of the target method
1244  PNATIVEMETHOD methp = _code->getEntry();
1245 
1246  // retrieve the argument signatures and process them
1247  uint16_t *types = (*methp)((RexxMethodContext *)&context, NULL);
1249 
1250  // TODO named arguments
1251 
1252  size_t activityLevel = this->activity->getActivationLevel();
1253  trapErrors = true; // we trap errors from here
1254  try
1255  {
1256  activity->releaseAccess(); /* force this to "safe" mode */
1257  /* process the method call */
1258  (*methp)((RexxMethodContext *)&context, arguments);
1259  activity->requestAccess(); /* now in unsafe mode again */
1260 
1261  // process the returned result
1262  result = valueToObject(arguments);
1263  }
1264  catch (RexxNativeActivation *)
1265  {
1266  }
1267  // there is a subtle interaction between native and rexx activations when
1268  // native calls make calls to APIs that in turn invoke Rexx code. When conditions
1269  // occur and the stack is being unwound, the ApiContext destructors will release
1270  // the kernel access, which can leave us with no active Activity. Bad things happen
1271  // when that occurs. We'll grab the exception when it goes past and make sure
1272  // things remain consistent.
1273  catch (RexxActivation *r)
1274  {
1275  // if we're not the current kernel holder when things return, make sure we
1276  // get the lock before we continue
1278  {
1280  }
1281  throw r;
1282  }
1283 
1284  // if we're not the current kernel holder when things return, make sure we
1285  // get the lock before we continue
1287  {
1289  }
1290  this->guardOff(); /* release any variable locks */
1291  this->argcount = 0; /* make sure we don't try to mark any arguments */
1292  this->named_argcount = 0;
1293  // the lock holder gets here by longjmp from a kernel reentry. We need to
1294  // make sure the activation count gets reset, else we'll accumulate bogus
1295  // nesting levels that will make it look like this activity is still in use
1296  // when in fact we're done with it.
1297  this->activity->restoreActivationLevel(activityLevel);
1298 
1299  /* give up reference to receiver so that it can be garbage collected */
1300  this->receiver = OREF_NULL;
1301 
1302  checkConditions(); // see if we have conditions to raise now
1303 
1304  // set the return value and get outta here
1305  resultObj = this->result;
1306  this->argcount = 0; /* make sure we don't try to mark any arguments */
1307  this->named_argcount = 0;
1308 
1309 
1310  this->activity->popStackFrame(this); /* pop this from the activity */
1311  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1312 }
1313 
1314 
1315 /**
1316  * Process a native function call.
1317  *
1318  * @param routine The routine we're executing (used for context resolution).
1319  * @param code The code object.
1320  * @param functionName
1321  * The name of the function.
1322  * @param list The list of arguments.
1323  * @param count The number of arguments.
1324  * @param resultObj The return value.
1325  */
1327  RexxObject **list, size_t count, size_t named_count, ProtectedObject &resultObj)
1328 {
1329  NativeActivationFrame frame(activity, this);
1330 
1331  // anchor the context stuff
1332  executable = _routine;
1333  msgname = functionName;
1334  arglist = list;
1335  argcount = count;
1336  named_argcount = named_count;
1337  activationType = FUNCTION_ACTIVATION; // this is for running a method
1338  accessCallerContext(); // we need this to access the caller's context
1339 
1341 
1342  CallContext context; // the passed out method context
1343 
1344  // sort out our active security manager
1346  if (securityManager == OREF_NULL)
1347  {
1349  }
1350 
1351  // build a context pointer to pass out
1352  activity->createCallContext(context, this);
1353 
1354  context.threadContext.arguments = arguments;
1355 
1356  // get the entry point address of the target method
1357  PNATIVEROUTINE methp = _code->getEntry();
1358 
1359  // retrieve the argument signatures and process them
1360  uint16_t *types = (*methp)((RexxCallContext *)&context, NULL);
1362 
1363  size_t activityLevel = this->activity->getActivationLevel();
1364  trapErrors = true; // we trap error conditions now
1365  try
1366  {
1367  enableVariablepool(); // enable the variable pool interface here
1368  activity->releaseAccess(); /* force this to "safe" mode */
1369  /* process the method call */
1370  (*methp)((RexxCallContext *)&context, arguments);
1371  activity->requestAccess(); /* now in unsafe mode again */
1372 
1373  // process the returned result
1374  result = valueToObject(arguments);
1375  }
1376  catch (RexxNativeActivation *)
1377  {
1378  }
1379  // JLF: apply also here the fix for bug 1402. Needed, isn't it ?
1380  catch (RexxActivation *r)
1381  {
1382  // if we're not the current kernel holder when things return, make sure we
1383  // get the lock before we continue
1385  {
1387  }
1388  throw r;
1389  }
1390 
1391  // if we're not the current kernel holder when things return, make sure we
1392  // get the lock before we continue
1394  {
1396  }
1397 
1398  disableVariablepool(); // disable the variable pool from here
1399  // belt and braces...this restores the activity level to whatever
1400  // level we had when we made the callout.
1401  this->activity->restoreActivationLevel(activityLevel);
1402 
1403  /* give up reference to receiver so that it can be garbage collected */
1404  this->receiver = OREF_NULL;
1405 
1406  checkConditions(); // see if we have conditions to raise now
1407 
1408  // set the return value and get outta here.
1409  resultObj = this->result;
1410  this->argcount = 0; /* make sure we don't try to mark any arguments */
1411  this->named_argcount = 0;
1412 
1413  this->activity->popStackFrame(this); /* pop this from the activity */
1414  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1415 }
1416 
1417 
1418 /**
1419  * Process a native function call.
1420  *
1421  * @param entryPoint The target function entry point.
1422  * @param list The list of arguments.
1423  * @param count The number of arguments.
1424  * @param result A protected object to receive the function result.
1425  */
1427  RexxObject **list, size_t count, size_t named_count, ProtectedObject &resultObj)
1428 {
1429  NativeActivationFrame frame(activity, this);
1430 
1431  // anchor the context stuff
1432  msgname = functionName;
1433  executable = _routine;
1434  arglist = list;
1435  argcount = count;
1436  named_argcount = named_count;
1437  accessCallerContext(); // we need this to access the caller's context
1438 
1439  activationType = FUNCTION_ACTIVATION; // this is for running a method
1440  // use the default security manager
1442 
1443 
1444  // get the entry point address of the target method
1445  RexxRoutineHandler *methp = _code->getEntry();
1446 
1448  CONSTRXSTRING *argPtr = arguments;
1449 
1450  // unlike the other variants, we don't have a cap on arguments. If we have more than the preallocated
1451  // set, then dynamically allocate a buffer object to hold the memory and anchor it in the
1452  // activation saved objects.
1453  if (count > MAX_NATIVE_ARGUMENTS)
1454  {
1455  RexxBuffer *argBuffer = new_buffer(sizeof(CONSTRXSTRING) * count);
1456  // this keeps the buffer alive until the activation is popped.
1457  createLocalReference(argBuffer);
1458  argPtr = (CONSTRXSTRING *)argBuffer->getData();
1459  }
1460 
1461  // all of the arguments now need to be converted to string arguments
1462  for (size_t argindex = 0; argindex < count; argindex++)
1463  {
1464  /* get the next argument */
1465  RexxObject *argument = list[argindex];
1466  if (argument != OREF_NULL) /* have an argument? */
1467  {
1468  /* force to string form */
1469  RexxString *stringArgument = argument->stringValue();
1470  // if the string version is not the same, we're going to need to make
1471  // sure the string version is protected from garbage collection until
1472  // the call is finished
1473  if (stringArgument != argument)
1474  {
1475  // make sure this is protected
1477  }
1478  stringArgument->toRxstring(argPtr[argindex]);
1479  }
1480  else /* have an omitted argument */
1481  {
1482  /* give it zero length */
1483  argPtr[argindex].strlength = 0;
1484  /* and a zero pointer */
1485  argPtr[argindex].strptr = NULL;
1486  }
1487  }
1488  /* get the current queue name */
1489  const char *queuename = Interpreter::getCurrentQueue()->getStringData();
1490  RXSTRING funcresult;
1491  int functionrc; /* Return code from function */
1492  /* default return code buffer */
1493  char default_return_buffer[DEFRXSTRING];
1494 
1495  /* make the RXSTRING result */
1496  MAKERXSTRING(funcresult, default_return_buffer, sizeof(default_return_buffer));
1497 
1498  size_t activityLevel = this->activity->getActivationLevel();
1499 
1500  trapErrors = true; // trap errors from here
1501  try
1502  {
1503  enableVariablepool(); // enable the variable pool interface here
1504  activity->releaseAccess(); /* force this to "safe" mode */
1505  // now process the function call
1506  // Something TODO for named arguments ???
1507  functionrc = (int)(*methp)(functionName->getStringData(), count, argPtr, queuename, &funcresult);
1508  activity->requestAccess(); /* now in unsafe mode again */
1509  }
1510  catch (RexxActivation *)
1511  {
1512  // if we're not the current kernel holder when things return, make sure we
1513  // get the lock before we continue
1515  {
1517  }
1518 
1519  this->argcount = 0; /* make sure we don't try to mark any arguments */
1520  this->named_argcount = 0;
1521  // the lock holder gets here by longjmp from a kernel reentry. We need to
1522  // make sure the activation count gets reset, else we'll accumulate bogus
1523  // nesting levels that will make it look like this activity is still in use
1524  // when in fact we're done with it.
1525  this->activity->restoreActivationLevel(activityLevel);
1526  // IMPORTANT NOTE: We don't pop our activation off the stack. This will be
1527  // handled by the catcher. Attempting to pop the stack when an error or condition has
1528  // occurred can munge the activation stack, resulting bad stuff.
1529  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1530  // now rethrow the trapped condition so that real target can handle this.
1531  throw;
1532  }
1533  catch (RexxNativeActivation *)
1534  {
1535  // if we're not the current kernel holder when things return, make sure we
1536  // get the lock before we continue
1538  {
1540  }
1541  this->argcount = 0; /* make sure we don't try to mark any arguments */
1542  this->named_argcount = 0;
1543  // the lock holder gets here by longjmp from a kernel reentry. We need to
1544  // make sure the activation count gets reset, else we'll accumulate bogus
1545  // nesting levels that will make it look like this activity is still in use
1546  // when in fact we're done with it.
1547  this->activity->restoreActivationLevel(activityLevel);
1548  this->activity->popStackFrame(this); /* pop this from the activity */
1549  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1550  // set the return value and get outta here
1551  resultObj = this->result;
1552  return;
1553  }
1554 
1555  trapErrors = false; // no more error trapping
1556  disableVariablepool(); // disable the variable pool from here
1557 
1558  // belt and braces...this restores the activity level to whatever
1559  // level we had when we made the callout.
1560  this->activity->restoreActivationLevel(activityLevel);
1561 
1562  // now process the function return value
1563  if (functionrc == 0) /* If good rc from function */
1564  {
1565  if (funcresult.strptr != NULL) /* If we have a result, return it */
1566  {
1567  /* make a string result */
1568  resultObj = new_string(funcresult);
1569  /* user give us a new buffer? */
1570  if (funcresult.strptr != default_return_buffer)
1571  {
1572  /* free it */
1574  }
1575  }
1576  }
1577  else /* Bad rc from function, signal */
1578  {
1579  /* error */
1581  }
1582 
1583  this->argcount = 0; /* make sure we don't try to mark any arguments */
1584  this->named_argcount = 0;
1585  this->activity->popStackFrame(this); /* pop this from the activity */
1586  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1587 }
1588 
1589 
1590 /**
1591  * Run a task under the scope of a native activation. This is
1592  * generally a bootstrapping call, such as a top-level program call,
1593  * method translation, etc.
1594  *
1595  * @param dispatcher The dispatcher instance we're going to run.
1596  */
1598 {
1599  activationType = DISPATCHER_ACTIVATION; // this is for running a dispatcher
1600  size_t activityLevel = this->activity->getActivationLevel();
1601  // use the default security manager
1603 
1604  // make the activation hookup
1605  dispatcher.setContext(activity, this);
1606  trapErrors = true; // we trap errors from here
1607  try
1608  {
1609  // we run this under a callback trap so that the exceptions get processed.
1610  dispatcher.run();
1611  }
1612  catch (ActivityException)
1613  {
1614  }
1615  catch (RexxNativeActivation *)
1616  {
1617  }
1618  trapErrors = false; // disable the error trapping
1619 
1620  // if we're not the current kernel holder when things return, make sure we
1621  // get the lock before we continue
1623  {
1625  }
1626 
1627  // belt and braces...this restores the activity level to whatever
1628  // level we had when we made the callout.
1629  this->activity->restoreActivationLevel(activityLevel);
1630  if (conditionObj != OREF_NULL)
1631  {
1632  // pass the condition information on to the dispatch unig
1633  dispatcher.handleError(conditionObj);
1634  }
1635 
1636  this->activity->popStackFrame(this); /* pop this from the activity */
1637  this->setHasNoReferences(); /* mark this as not having references in case we get marked */
1638  return; /* and finished */
1639 }
1640 
1641 
1642 /**
1643  * Run a callback under the scope of a native actvation. This is
1644  * generally a call out, such as a system exit, argument
1645  * callback, etc.
1646  *
1647  * @param dispatcher The dispatcher instance we're going to run.
1648  */
1650 {
1651  activationType = CALLBACK_ACTIVATION; // we're handling a callback
1652  // use the default security manager
1654  size_t activityLevel = this->activity->getActivationLevel();
1655  trapErrors = true; // trap errors on
1656  try
1657  {
1658  // make the activation hookup
1659  dispatcher.setContext(activity, this);
1660  activity->releaseAccess(); /* force this to "safe" mode */
1661  dispatcher.run();
1662  activity->requestAccess(); /* now in unsafe mode again */
1663  }
1664  catch (ActivityException)
1665  {
1666  }
1667  catch (RexxNativeActivation *)
1668  {
1669  }
1670  // if we're not the current kernel holder when things return, make sure we
1671  // get the lock before we continue
1673  {
1675  }
1676 
1677  trapErrors = false; // back to normal mode for error trapping
1678 
1679  // belt and braces...this restores the activity level to whatever
1680  // level we had when we made the callout.
1681  this->activity->restoreActivationLevel(activityLevel);
1682  // make sure we handle the error notifications
1683  if (conditionObj != OREF_NULL)
1684  {
1685  // pass the condition information on to the dispatch unig
1686  dispatcher.handleError(conditionObj);
1687  }
1688  return; /* and finished */
1689 }
1690 
1691 
1692 /**
1693  * Run a some type of activity using a fresh activation stack.
1694  * This generally us a method call such as an uninit method
1695  * where we wish to run the method and ignore errors. This runs
1696  * without releasing the kernel lock.
1697  *
1698  * @param dispatcher The dispatcher instance we're going to run.
1699  */
1701 {
1702  activationType = TRAPPING_ACTIVATION; // we're handling a callback
1703  size_t activityLevel = this->activity->getActivationLevel();
1704  trapErrors = true; // trap errors on
1705  try
1706  {
1707  // make the activation hookup and run it. Note that this
1708  // version does not release the kernel lock
1709  dispatcher.setContext(activity, this);
1710  dispatcher.run();
1711  }
1712  catch (ActivityException)
1713  {
1714  }
1715  catch (RexxNativeActivation *)
1716  {
1717  }
1718  // if we're not the current kernel holder when things return, make sure we
1719  // get the lock before we continue
1721  {
1723  }
1724 
1725  trapErrors = false; // back to normal mode for error trapping
1726 
1727  // belt and braces...this restores the activity level to whatever
1728  // level we had when we made the callout.
1729  this->activity->restoreActivationLevel(activityLevel);
1730  // make sure we handle the error notifications
1731  if (conditionObj != OREF_NULL)
1732  {
1733  // pass the condition information on to the dispatch unig
1734  dispatcher.handleError(conditionObj);
1735  }
1736  return; /* and finished */
1737 }
1738 
1739 
1740 /**
1741  * Establish the caller's context for native activations
1742  * that require access to the caller's context.
1743  */
1745 {
1747 }
1748 
1749 
1750 /**
1751  * Check to see if there are deferred syntax errors that need
1752  * to be raised on return from a native activation.
1753  */
1755 {
1756  trapErrors = false; // no more error trapping
1757 
1758  // if we have a stashed condition object, we need to raise this now
1759  if (conditionObj != OREF_NULL)
1760  {
1761  // we're raising this in the previous stack frame. If we're actually the
1762  // base of the stack, there's nothing left to handle this.
1763  if (!isStackBase())
1764  {
1765  /* get the original condition name */
1766  RexxString *condition = (RexxString *)conditionObj->at(OREF_CONDITION);
1767 
1768  /* fatal SYNTAX error? */
1769  if (condition->strCompare(CHAR_SYNTAX))
1770  {
1771  // this prevents us from trying to trap this again
1772  trapErrors = false;
1773  /* go propagate the condition */
1775  }
1776  else
1777  { /* normal condition trapping */
1778  /* get the sender object (if any) */
1779  // find a predecessor Rexx activation
1780  RexxActivationBase *_sender = this->getPreviousStackFrame();
1781  /* do we have a sender that is */
1782  /* trapping this condition? */
1783  /* do we have a sender? */
1784 
1785  if (_sender != OREF_NULL)
1786  {
1787  /* "tickle them" with this */
1788  _sender->trap(condition, conditionObj);
1789  }
1790  // if the trap is not handled, then we return directly. The return
1791  // value (if any) is stored in the condition object
1792  result = conditionObj->at(OREF_RESULT);
1793  }
1794  }
1795  }
1796 }
1797 
1798 
1800 /******************************************************************************/
1801 /* Function: Retrieve the set of method variables */
1802 /******************************************************************************/
1803 {
1804  /* first retrieval? */
1805  if (this->objectVariables == OREF_NULL)
1806  {
1807  // not a method invocation?
1808  if (receiver == OREF_NULL)
1809  {
1810  /* retrieve the method variables */
1811  this->objectVariables = ((RexxActivation *)this->receiver)->getLocalVariables(); // SUSPECT!
1812  }
1813  else
1814  {
1815  RexxMethod *method = (RexxMethod *)executable;
1816  /* must be wanting the ovd set of */
1817  /*variables */
1818  this->objectVariables = this->receiver->getObjectVariables(method->getScope());
1819  /* guarded method? */
1820  if (this->object_scope == SCOPE_RELEASED && method->isGuarded())
1821  {
1822  /* reserve the variable scope */
1823  this->objectVariables->reserve(this->activity);
1824  /* and remember for later */
1825  this->object_scope = SCOPE_RESERVED;
1826  }
1827  }
1828  }
1829  return this->objectVariables; /* return the dictionary */
1830 }
1831 
1832 
1834  RexxObject *object) /* object to validate */
1835 /******************************************************************************/
1836 /* Function: Validate that an object has an integer value */
1837 /******************************************************************************/
1838 {
1839  wholenumber_t temp;
1840  return object->numberValue(temp, this->digits());
1841 }
1842 
1843 /**
1844  * Convert a value to a wholenumber value.
1845  *
1846  * @param o The object to convert.
1847  * @param position The argument position.
1848  * @param maxValue The maximum value allowed in the range.
1849  * @param minValue The minimum range value.
1850  *
1851  * @return The converted number.
1852  */
1854 {
1855  ssize_t temp;
1856 
1857  // convert using the whole value range
1858  if (!Numerics::objectToSignedInteger(o, temp, maxValue, minValue))
1859  {
1861  }
1862  return temp;
1863 }
1864 
1865 
1866 
1867 /**
1868  * Convert a value to a size_t value.
1869  *
1870  * @param o The object to convert.
1871  * @param position The argument position.
1872  * @param maxValue The maximum value allowed in the range.
1873  *
1874  * @return The converted number.
1875  */
1877 {
1878  size_t temp;
1879 
1880  // convert using the whole value range
1881  if (!Numerics::objectToUnsignedInteger(o, temp, maxValue))
1882  {
1884  }
1885  return temp;
1886 }
1887 
1888 
1889 /**
1890  * Convert a value to an int64_t value
1891  *
1892  * @param o The object to convert.
1893  * @param position The argument position.
1894  *
1895  * @return The converted number.
1896  */
1898 {
1899  int64_t temp;
1900 
1901  // convert using the whole value range
1902  if (!Numerics::objectToInt64(o, temp))
1903  {
1905  }
1906  return temp;
1907 }
1908 
1909 
1910 /**
1911  * Convert a value to a uint64_t value
1912  *
1913  * @param o The object to convert.
1914  * @param position The argument position.
1915  *
1916  * @return The converted number.
1917  */
1919 {
1920  uint64_t temp;
1921 
1922  // convert using the whole value range
1923  if (!Numerics::objectToUnsignedInt64(o, temp))
1924  {
1926  }
1927  return temp;
1928 }
1929 
1930 
1932  RexxObject *object) /* object to convert */
1933 /******************************************************************************/
1934 /* Function: Return an object as a CSTRING */
1935 /******************************************************************************/
1936 {
1937  /* force to a string value */
1938  RexxString *string = (RexxString *)object->stringValue();
1939  if (string != object) /* different value? */
1940  {
1941  /* make it safe */
1942  createLocalReference(string);
1943  }
1944  return string->getStringData(); /* just point to the string data */
1945 }
1946 
1947 
1948 /**
1949  * Convert a string in the format 0xnnnnnnnnn into a pointer value.
1950  *
1951  * @param object The object to convert.
1952  *
1953  * @return The pointer value.
1954  */
1955 void *RexxNativeActivation::pointerString(RexxObject *object, size_t position)
1956 {
1957  /* force to a string value */
1958  RexxString *string = (RexxString *)object->stringValue();
1959 
1960  void *pointerVal;
1961  if (sscanf(string->getStringData(), "0x%p", &pointerVal) != 1)
1962  {
1963  reportException(Error_Invalid_argument_pointer, OREF_positional, position + 1, string);
1964  }
1965 
1966  return pointerVal;
1967 }
1968 
1969 
1970 double RexxNativeActivation::getDoubleValue(RexxObject *object, size_t position)
1971 /******************************************************************************/
1972 /* Function: Convert an object to a double */
1973 /******************************************************************************/
1974 {
1975  double r; /* returned result */
1976  /* convert and check result */
1977  if (!object->doubleValue(r))
1978  {
1979  /* conversion error */
1980  reportException(Error_Invalid_argument_double, OREF_positional, position + 1, object);
1981  }
1982  return r; /* return converted number */
1983 }
1984 
1985 
1987  RexxObject *object) /* object to check */
1988 /******************************************************************************/
1989 /* Function: Test to see if an object is a valid double */
1990 /******************************************************************************/
1991 {
1992  double r; /* returned result */
1993  /* convert and check result */
1994  return object->doubleValue(r);
1995 }
1996 
1998 /******************************************************************************/
1999 /* Function: Returns "unwrapped" C or C++ object associated with this */
2000 /* object instance. If the variable CSELF does not exist, then */
2001 /* NULL is returned. */
2002 /******************************************************************************/
2003 {
2004  // if this is a method invocation, ask the receiver object to figure this out.
2005  if (receiver != OREF_NULL)
2006  {
2007  // this is necessary to get turn on a guard lock if the method
2008  // is guarded. Failure to do this can cause multithreading problems.
2009  methodVariables();
2010  return receiver->getCSelf(((RexxMethod *)executable)->getScope());
2011  }
2012  // nope, call context doesn't allow this
2013  return OREF_NULL;
2014 }
2015 
2016 
2018  RexxObject *object) /* object to convert */
2019 /******************************************************************************/
2020 /* Function: Return as a pointer the value of an integer */
2021 /******************************************************************************/
2022 {
2023  if (!object->isInstanceOf(ThePointerClass))
2024  {
2025  return NULL;
2026  }
2027  // just unwrap thee pointer
2028  return ((RexxPointer *)object)->pointer();
2029 }
2030 
2031 
2033 /******************************************************************************/
2034 /* Function: Redispatch an activation on a different activity */
2035 /******************************************************************************/
2036 {
2037  ProtectedObject r;
2038  this->run((RexxMethod *)executable, (RexxNativeMethod *)code, receiver, msgname, arglist, argcount, named_argcount, r); /* just do a method run */
2039  return (RexxObject *)r;
2040 }
2041 
2043 /******************************************************************************/
2044 /* Function: Return the current digits setting */
2045 /******************************************************************************/
2046 {
2047  /* have a real one? */
2048  if (activation == OREF_NULL)
2049  {
2050  return Numerics::DEFAULT_DIGITS; /* no, just return default value */
2051  }
2052  else
2053  {
2054  return activation->digits(); /* pass on the the sender */
2055  }
2056 }
2057 
2059 /******************************************************************************/
2060 /* Function: Return the current fuzz setting */
2061 /******************************************************************************/
2062 {
2063  /* have a real one? */
2064  if (activation == OREF_NULL)
2065  {
2066  return Numerics::DEFAULT_FUZZ; /* no, just return default value */
2067  }
2068  else
2069  {
2070  return activation->fuzz(); /* pass on the the sender */
2071  }
2072 }
2073 
2075 /******************************************************************************/
2076 /* Function: Return the curren form setting */
2077 /******************************************************************************/
2078 {
2079  /* have a real one? */
2080  if (activation == OREF_NULL)
2081  {
2082  return Numerics::DEFAULT_FORM; /* no, just return default value */
2083  }
2084  else
2085  {
2086  return activation->form(); /* pass on the the sender */
2087  }
2088 }
2089 
2091  size_t _digits) /* new NUMERIC DIGITS value */
2092 /******************************************************************************/
2093 /* Function: Set a new numeric digits setting */
2094 /******************************************************************************/
2095 {
2096  /* have a real one? */
2097  if (activation != OREF_NULL)
2098  {
2099  activation->setDigits(_digits); /* just forward the set */
2100  }
2101 }
2102 
2104  size_t _fuzz) /* new NUMERIC FUZZ value */
2105 /******************************************************************************/
2106 /* Function: Set a new numeric fuzz setting */
2107 /******************************************************************************/
2108 {
2109  /* have a real one? */
2110  if (activation != OREF_NULL)
2111  {
2112  activation->setFuzz(_fuzz); /* just forward the set */
2113  }
2114 }
2115 
2117  bool _form) /* new NUMERIC FORM value */
2118 /******************************************************************************/
2119 /* Function: Set a new numeric form setting */
2120 /******************************************************************************/
2121 {
2122  /* have a real one? */
2123  if (activation != OREF_NULL)
2124  {
2125  activation->setForm(_form); /* just forward the set */
2126  }
2127 }
2128 
2129 
2130 /**
2131  * Get the numeric settings for this native activation. If we're
2132  * running in the direct call context from a Rexx activation, then
2133  * the settings are those inherited from the Rexx context. Otherwise,
2134  * we just return the default numeric settings.
2135  *
2136  * @return The current Numeric settings.
2137  */
2139 {
2140  if (activation == OREF_NULL)
2141  {
2143  }
2144  else
2145  {
2146  return activation->getNumericSettings();
2147  }
2148 }
2149 
2150 
2151 /**
2152  * Indicate whether this activation represents the base of the call
2153  * stack.
2154  *
2155  * @return true if this is a base activation.
2156  */
2158 {
2159  return stackBase;
2160 }
2161 
2162 
2163 /**
2164  * Return the Rexx context this operates under. Depending on the
2165  * context, this could be null.
2166  *
2167  * @return The parent Rexx context.
2168  */
2170 {
2171  return activation; // this might be null
2172 }
2173 
2174 
2175 /**
2176  * Return the Rexx executable context that is our immediate
2177  * caller. Depending on the
2178  * context, this could be null.
2179  *
2180  * @return The parent Rexx context.
2181  */
2183 {
2184  // since this should only be used for exit calls, in theory, we always
2185  // have one of these.
2186  if (activation != OREF_NULL)
2187  {
2188  return activation->getExecutable();
2189  }
2190  return OREF_NULL;
2191 }
2192 
2193 
2194 /**
2195  * Return the Rexx context object for our immediate caller.
2196  * Depending on the context, this could be null.
2197  *
2198  * @return The parent Rexx context.
2199  */
2201 {
2202  // since this should only be used for exit calls, in theory, we always
2203  // have one of these.
2204  if (activation != OREF_NULL)
2205  {
2206  return activation->getContextObject();
2207  }
2208  return OREF_NULL;
2209 }
2210 
2211 
2212 /**
2213  * Return the Rexx context this operates under. Depending on the
2214  * context, this could be null.
2215  *
2216  * @return The parent Rexx context.
2217  */
2219 {
2220  // if this is attached to a Rexx context, we can stop here
2221  if (activation != OREF_NULL)
2222  {
2223  return activation;
2224  }
2225  // otherwise, have our predecessor see if it can figure this out. It's likely
2226  // that is the one we need.
2227  if (previous != OREF_NULL)
2228  {
2229  return previous->findRexxContext();
2230  }
2231  // at the base of the stack, no context.
2232  return OREF_NULL;
2233 }
2234 
2235 
2236 /**
2237  * Get the message receiver
2238  *
2239  * @return The message receiver. Returns OREF_NULL if this is not
2240  * a message activation.
2241  */
2243 {
2244  return receiver;
2245 }
2246 
2247 
2248 /**
2249  * Get the security manager context
2250  *
2251  * @return The security manager, if there is one.
2252  */
2254 {
2255  RexxSource *s = getSourceObject();
2256  if (s != OREF_NULL)
2257  {
2258  return s->getSecurityManager();
2259  }
2260  return OREF_NULL; // no security manager on this context.
2261 }
2262 
2263 
2265 /******************************************************************************/
2266 /* Function: Release a variable pool guard lock */
2267 /******************************************************************************/
2268 {
2269  /* currently locked? */
2270  if (this->object_scope == SCOPE_RESERVED)
2271  {
2272  /* release the variable dictionary */
2273  this->objectVariables->release(this->activity);
2274  /* set the state to released */
2275  this->object_scope = SCOPE_RELEASED;
2276  }
2277 }
2278 
2280 /******************************************************************************/
2281 /* Function: Acquire a variable pool guard lock */
2282 /******************************************************************************/
2283 {
2284  // if there's no receiver object, then this is not a true method call.
2285  // there's nothing to lock
2286  if (receiver == OREF_NULL)
2287  {
2288  return;
2289  }
2290  /* first retrieval? */
2291  if (this->objectVariables == OREF_NULL)
2292  {
2293  /* grab the object variables associated with this object */
2295  }
2296  /* not currently holding the lock? */
2297  if (this->object_scope == SCOPE_RELEASED)
2298  {
2299  /* reserve the variable scope */
2300  this->objectVariables->reserve(this->activity);
2301  /* and remember for later */
2302  this->object_scope = SCOPE_RESERVED;
2303  }
2304 }
2305 
2307 /******************************************************************************/
2308 /* Function: Enable the variable pool */
2309 /******************************************************************************/
2310 {
2311  this->resetNext(); /* reset fetch next calls */
2312  this->vpavailable = true; /* allow the calls */
2313 }
2314 
2316 /******************************************************************************/
2317 /* Function: Disable the variable pool */
2318 /******************************************************************************/
2319 {
2320  this->resetNext(); /* reset fetch next calls */
2321  this->vpavailable = false; /* no more external calls */
2322 }
2323 
2325 /******************************************************************************/
2326 /* Function: Reset the next state of the variable pool */
2327 /******************************************************************************/
2328 {
2329  this->nextvariable = SIZE_MAX; /* turn off next index */
2330  this->nextcurrent = OREF_NULL; /* clear the next value */
2331  this->nextstem = OREF_NULL; /* clear the secondary pointer */
2332  this->compoundelement = OREF_NULL;
2333 }
2334 
2335 
2337  RexxString **name, /* the returned name */
2338  RexxObject **value) /* the return value */
2339 /******************************************************************************/
2340 /* Function: Fetch the next variable of a variable pool traversal */
2341 /******************************************************************************/
2342 {
2343  RexxVariable *variable; /* retrieved variable value */
2344  RexxCompoundElement *compound; /* retrieved variable value */
2345  RexxStem *stemVar; /* a potential stem variable collection */
2346 
2347  /* starting off fresh? */
2348  if (nextCurrent() == OREF_NULL)
2349  {
2350  /* grab the activation context */
2352  setNextVariable(SIZE_MAX); /* request the first item */
2353  /* Get the local variable dictionary from the context. */
2355  /* we are not on a stem */
2358  }
2359 
2360  for (;;) /* loop until we get something */
2361  {
2362  variable = nextStem(); /* see if we're processing a stem variable */
2363  if (variable != OREF_NULL) /* were we in the middle of processing a stem? */
2364  {
2365  stemVar = (RexxStem *)variable->getVariableValue();
2366  compound = stemVar->nextVariable(this);
2367  if (compound != OREF_NULL) /* if we still have elements here */
2368  {
2369  // create a full stem name
2370  // NOTE: We're using the stem name from the variable, not the
2371  // stem OBJECT we're iterating over.
2372  *name = compound->createCompoundName(variable->getName());
2373  /* get the value */
2374  *value = compound->getVariableValue();
2375  return true;
2376  }
2377  else /* we've reached the end of the stem, reset */
2378  {
2379  /* to the main dictionary and continue */
2382  }
2383  }
2384  /* get the next variable */
2385  variable = nextCurrent()->nextVariable(this);
2386  if (variable == OREF_NULL) /* reached the end of the table */
2387  {
2388  return false;
2389  }
2390  else /* have a real variable */
2391  {
2392  /* get the value */
2393  RexxObject *variable_value = variable->getVariableValue();
2394  /* found a stem item? */
2395  if (variable->isStem())
2396  {
2397  /* we are now on a stem */
2398  setNextStem(variable);
2399  setCompoundElement(((RexxStem *)variable_value)->first());
2400  /* set up an iterator for the stem */
2401  }
2402  else /* found a real variable */
2403  {
2404  *value = variable_value; /* pass back the value (name already set) */
2405  *name = variable->getName();
2406  return true; /* we have another variable to return */
2407  }
2408  }
2409  }
2410 }
2411 
2412 
2413 
2414 /**
2415  * Trap a condition at this level of the activation stack.
2416  *
2417  * @param condition The name of the condition.
2418  * @param exception_object
2419  * The exception object containing the specifics of the condition.
2420  *
2421  * @return false if this activation takes a pass on the condition. Does not
2422  * return at all if the condition is handled.
2423  */
2424 bool RexxNativeActivation::trap(RexxString *condition, RexxDirectory * exception_object)
2425 {
2426  // There are two possibilities here. We're either seeing this because of a
2427  // propagating syntax condition. for this case, we trap this and hold it.
2428  // The other possibility is a condition being raised by an API callback. That should
2429  // be the only situation where we see any other condition type. We also trap that
2430  // one so it can be raised in the caller's context.
2431 
2432  // we end up seeing this a second time if we're raising the exception on
2433  // return from an external call or method.
2434  if (condition->isEqual(OREF_SYNTAX))
2435  {
2436  if (trapErrors)
2437  {
2438  // record this in case any callers want to know about it.
2439  setConditionInfo(exception_object);
2440  // this will unwind back to the calling level, with the
2441  // exception information recorded.
2442  throw this;
2443  }
2444 
2445  }
2446  else if (trapConditions)
2447  {
2448  // pretty much the same deal, but we're only handling conditions, and
2449  // only one condtion, so reset the trap flag
2450  trapConditions = false;
2451  // record this in case any callers want to know about it.
2452  setConditionInfo(exception_object);
2453  // this will unwind back to the calling level, with the
2454  // exception information recorded.
2455  throw this;
2456  }
2457  return false; /* this wasn't handled */
2458 }
2459 
2460 
2461 /**
2462  * Raise a condition on behalf of a native method. This method
2463  * does not return.
2464  *
2465  * @param condition The condition type to raise.
2466  * @param description
2467  * The condition description string.
2468  * @param additional The additional information associated with this condition.
2469  * @param result The result object.
2470  */
2471 void RexxNativeActivation::raiseCondition(RexxString *condition, RexxString *description, RexxObject *additional, RexxObject *_result)
2472 {
2473  this->result = (RexxObject *)_result; /* save the result */
2474  /* go raise the condition */
2475  this->activity->raiseCondition(condition, OREF_NULL, description, additional, result);
2476 
2477  // We only return here if no activation above us has trapped this. If we do return, then
2478  // we terminate the call by throw this up the stack.
2479  throw this;
2480 }
2481 
2482 
2483 /**
2484  * Return the method context positional arguments as an array.
2485  *
2486  * @return An array containing the method positional arguments.
2487  */
2489 {
2490  // if we've not requested this before, convert the positional arguments to an
2491  // array object.
2492  if (argArray == OREF_NULL)
2493  {
2494  /* create the argument array */
2496  // make sure the array is anchored in our activation
2498  }
2499  return argArray;
2500 }
2501 
2502 /**
2503  * Retrieve a specific positional argument from the method invocation context.
2504  *
2505  * @param index The positional argument of interest.
2506  *
2507  * @return The object mapped to that argument. Returns OREF_NULL for
2508  * omitted arguments.
2509  */
2511 {
2512  if (index <= argcount)
2513  {
2514  return arglist[index - 1];
2515  }
2516  return OREF_NULL;
2517 }
2518 
2519 /**
2520  * Return the method context named arguments as a directory.
2521  *
2522  * @return A directory containing the method named arguments.
2523  */
2525 {
2526  // if we've not requested this before, convert the named arguments to a
2527  // directory object.
2528  if (argDirectory == OREF_NULL)
2529  {
2530  /* create the named argument directory */
2531  if (arglist == OREF_NULL) argDirectory = new_directory(); // Empty directory
2532  else
2533  {
2534  if (named_argcount == 0) argDirectory = new_directory(); // Empty directory
2535  else argDirectory = RexxDirectory::fromIndexItemArray(arglist + argcount, named_argcount); // Here we are sure to have a directory on return (and not OREF_NULL)
2536  }
2537 
2538  // make sure the directory is anchored in our activation
2540  }
2541  return argDirectory;
2542 }
2543 
2544 /**
2545  * Return the super class scope of the current method context.
2546  *
2547  * @return The superclass scope object.
2548  */
2550 {
2552 }
2553 
2554 /**
2555  * Return the current method scope.
2556  *
2557  * @return The current method scope object.
2558  */
2560 {
2561  return ((RexxMethod *)executable)->getScope();
2562 }
2563 
2564 /**
2565  * Resolve an argument object into a stem object. The argument
2566  * object may already be a stem, or may the a variable name
2567  * used to resolve a stem.
2568  *
2569  * @param s The source object used for the resolution.
2570  *
2571  * @return A resolved stem object. Returns a NULLOBJECT if there is
2572  * a resolution problem.
2573  */
2575 {
2576  // is this a stem already?
2577  if (isStem(s))
2578  {
2579  return (RexxStem *)s;
2580  }
2581 
2582  /* force to a string value */
2583  RexxString *temp = stringArgument(s, OREF_positional, 1);
2584  // see if we can retrieve this stem
2585  return (RexxStem *)getContextStem(temp);
2586 }
2587 
2588 
2590 /******************************************************************************/
2591 /* Function: retrieve a stem variable stem from the current context. */
2592 /******************************************************************************/
2593 {
2594  // if this is not a stem name, add it now
2595  if (name->getChar(name->getLength() - 1) != '.')
2596  {
2597  name = name->concatWithCstring(".");
2598  }
2599 
2601  // if this didn't parse, it's an illegal name
2602  // it must also resolve to a stem type...this could be a compound one
2603  if (retriever == OREF_NULL || !isOfClass(StemVariableTerm, retriever))
2604  {
2605  return OREF_NULL;
2606  }
2607  // get the variable value
2608  return retriever->getValue(activation);
2609 }
2610 
2611 
2612 /**
2613  * Retrieve the value of a context variable via the API calls.
2614  * Returns OREF_NULL if the variable does not exist.
2615  *
2616  * @param name The variable name.
2617  *
2618  * @return The variable value, if any.
2619  */
2621 {
2623  // if this didn't parse, it's an illegal name
2624  if (retriever == OREF_NULL)
2625  {
2626  return OREF_NULL;
2627  }
2628  this->resetNext(); // all next operations must be reset
2629 
2630  // have a non-name retriever?
2631  if (isString((RexxObject *)retriever))
2632  {
2633  // the value is the retriever
2634  return (RexxObject *)retriever;
2635  }
2636  else
2637  {
2638  // get the variable value
2639  return retriever->getRealValue(activation);
2640  }
2641 }
2642 
2643 /**
2644  * Set a context variable on behalf of an API call.
2645  *
2646  * @param name The name of the variable.
2647  * @param value The variable value.
2648  */
2650 {
2651  // get the REXX activation for the target context
2653  // if this didn't parse, it's an illegal name
2654  if (retriever == OREF_NULL || isString((RexxObject *)retriever))
2655  {
2656  return;
2657  }
2658  this->resetNext(); // all next operations must be reset
2659 
2660  // do the assignment
2661  retriever->set(activation, value);
2662 }
2663 
2664 
2665 /**
2666  * Drop a context variable for an API call.
2667  *
2668  * @param name The target variable name.
2669  */
2671 {
2672  // get the REXX activation for the target context
2674  // if this didn't parse, it's an illegal name
2675  if (retriever == OREF_NULL || isString((RexxObject *)retriever))
2676  {
2677  return;
2678  }
2679  this->resetNext(); // all next operations must be reset
2680 
2681  // perform the drop
2682  retriever->drop(activation);
2683 }
2684 
2685 
2687 /******************************************************************************/
2688 /* Function: Retriev a list of all variables in the current context. */
2689 /******************************************************************************/
2690 {
2691  this->resetNext(); // all next operations must be reset
2692  return activation->getAllLocalVariables();
2693 }
2694 
2695 
2696 /**
2697  * Get nn object variable in the current method scope. Returns
2698  * a NULL object reference if the variable does not exist.
2699  *
2700  * @param name The variable name.
2701  *
2702  * @return The variable value or OREF_NULL if the variable does not
2703  * exist.
2704  */
2706 {
2707  RexxString *target = new_string(name);
2708  ProtectedObject p1(target);
2709  // get the REXX activation for the target context
2711  ProtectedObject p2(retriever);
2712  // if this didn't parse, it's an illegal name
2713  // we also don't allow compound variables here because the source for
2714  // resolving the tail pieces is not defined.
2715  if (retriever == OREF_NULL || isString((RexxObject *)retriever) || isOfClassType(CompoundVariableTerm, retriever))
2716  {
2717  return OREF_NULL;
2718  }
2719  // retrieve the value
2720  return retriever->getRealValue(methodVariables());
2721 }
2722 
2723 /**
2724  * The an object variable to a new value.
2725  *
2726  * @param name The name of the variable.
2727  * @param value The new variable value.
2728  */
2730 {
2731  RexxString *target = new_string(name);
2732  ProtectedObject p1(target);
2733  // get the REXX activation for the target context
2735  ProtectedObject p2(retriever);
2736  // if this didn't parse, it's an illegal name
2737  // we also don't allow compound variables here because the source for
2738  // resolving the tail pieces is not defined.
2739  if (retriever == OREF_NULL || isString((RexxObject *)retriever) || isOfClassType(CompoundVariableTerm, retriever))
2740  {
2741  return;
2742  }
2743  // do the assignment
2744  retriever->set(methodVariables(), value);
2745 }
2746 
2747 /**
2748  * Drop an object variable in the current method scope.
2749  *
2750  * @param name The name of the variable.
2751  */
2753 {
2754  RexxString *target = new_string(name);
2755  ProtectedObject p1(target);
2756  // get the REXX activation for the target context
2758  ProtectedObject p2(retriever);
2759  // if this didn't parse, it's an illegal name
2760  // we also don't allow compound variables here because the source for
2761  // resolving the tail pieces is not defined.
2762  if (retriever == OREF_NULL || isString((RexxObject *)retriever) || isOfClassType(CompoundVariableTerm, retriever))
2763  {
2764  return;
2765  }
2766  // do the assignment
2767  retriever->drop(methodVariables());
2768 }
2769 
2770 
2771 /**
2772  * Resolve a class in the context of the current execution context.
2773  *
2774  * @param className The target class name.
2775  *
2776  * @return The resolved class (if any).
2777  */
2779 {
2780  RexxClass *classObject;
2781 
2782  // if we have an executable context, use that as the context.
2783  if (executable != OREF_NULL)
2784  {
2785  classObject = executable->findClass(className);
2786  }
2787  else
2788  {
2789  classObject = Interpreter::findClass(className);
2790  }
2791  // we need to filter this to always return a class object
2792  if (classObject != OREF_NULL && classObject->isInstanceOf(TheClassClass))
2793  {
2794  return classObject;
2795  }
2796  return OREF_NULL;
2797 }
2798 
2799 
2800 /**
2801  * Resolve a class in the context of the caller's execution
2802  * context.
2803  *
2804  * @param className The target class name.
2805  *
2806  * @return The resolved class (if any).
2807  */
2809 {
2810  RexxClass *classObject;
2811  // have a caller context? if not, just do the default environment searches
2812  if (activation == OREF_NULL)
2813  {
2814  classObject = Interpreter::findClass(className);
2815  }
2816  else
2817  {
2818  // use the caller activation to resolve this
2819  classObject = activation->findClass(className);
2820  }
2821  // we need to filter this to always return a class object
2822  if (classObject != OREF_NULL && classObject->isInstanceOf(TheClassClass))
2823  {
2824  return classObject;
2825  }
2826  return OREF_NULL;
2827 }
2828 
2829 
2830 /**
2831  * Retrieve the source object for the current context, if there is one.
2832  *
2833  * @return The source object associated with any Method or Routine currently
2834  * being run.
2835  */
2837 {
2838  if (executable != OREF_NULL)
2839  {
2840  return executable->getSourceObject();
2841  }
2842  return OREF_NULL;
2843 }
2844 
2845 
2846 /**
2847  * Allocate a new native Activation.
2848  *
2849  * @param size the allocation size.
2850  *
2851  * @return A pointer to the newly allocated object.
2852  */
2853 void * RexxNativeActivation::operator new(size_t size)
2854 {
2855  /* Get new object */
2856  RexxObject *newObject = new_object(size, T_NativeActivation);
2857  newObject->clearObject(); /* clear out at start */
2858  return newObject; /* return the new object */
2859 }
2860 
2861 
2862 /**
2863  * Handle a request chain for the variable pool interface API.
2864  *
2865  * @param pshvblock The shared variable block for the request.
2866  *
2867  * @return The composit return code for the chain of requests.
2868  */
2870 {
2871  // this is not allowed asynchronously
2872  if (!getVpavailable())
2873  {
2874  return RXSHV_NOAVL;
2875  }
2876 
2877  RexxReturnCode retcode = 0; /* initialize composite rc */
2878 
2879  try
2880  {
2881  while (pshvblock)
2882  { /* while more request blocks */
2883  variablePoolRequest(pshvblock);
2884  retcode |= pshvblock->shvret; /* accumulate the return code */
2885  pshvblock = pshvblock->shvnext; /* step to the next block */
2886  }
2887  return retcode; /* return composite return code */
2888 
2889  }
2890  // intercept any termination failures
2891  catch (ActivityException)
2892  {
2893  /* set failure in current */
2894  pshvblock->shvret |= (uint8_t)RXSHV_MEMFL;
2895  retcode |= pshvblock->shvret; /* OR with the composite */
2896  return retcode; /* stop processing requests now */
2897  }
2898 }
2899 
2900 
2901 /**
2902  * Get a variable retriever for the target variable.
2903  *
2904  * @param pshvblock The variable pool request block.
2905  * @param symbolic The symbolic vs. direct indicator.
2906  *
2907  * @return A variable retriever for the variable. Returns OREF_NULL
2908  * if the variable is not resolvable from the name.
2909  */
2911 {
2912  /* no name given? */
2913  if (pshvblock->shvname.strptr == NULL)
2914  {
2915  pshvblock->shvret |= RXSHV_BADN; /* this is bad */
2916  }
2917  else
2918  {
2919  /* get the variable as a string */
2920  RexxString *variable = new_string(pshvblock->shvname);
2921  RexxVariableBase *retriever = OREF_NULL;
2922  /* symbolic access? */
2923  if (symbolic)
2924  {
2925  /* get a symbolic retriever */
2926  retriever = RexxVariableDictionary::getVariableRetriever(variable);
2927  }
2928  else /* need a direct retriever */
2929  {
2931  }
2932  if (retriever == OREF_NULL) /* have a bad name? */
2933  {
2934  pshvblock->shvret |= RXSHV_BADN; /* this is bad */
2935  }
2936  else
2937  {
2938  resetNext(); /* reset any next operations */
2939  return retriever;
2940  }
2941  }
2942  return OREF_NULL;
2943 }
2944 
2945 /**
2946  * Perform a variable pool fetch operation.
2947  *
2948  * @param pshvblock The operation shared variable block.
2949  */
2951 {
2952  RexxVariableBase *retriever = variablePoolGetVariable(pshvblock, pshvblock->shvcode == RXSHV_SYFET);
2953  RexxObject *value = OREF_NULL;
2954  if (retriever != OREF_NULL)
2955  {
2956  /* have a non-name retriever? */
2957  if (isString((RexxObject *)retriever))
2958  {
2959  /* the value is the retriever */
2960  value = (RexxObject *)retriever;
2961  }
2962  else
2963  {
2964  /* have a non-name retriever */
2965  /* and a new variable? */
2966  if (!retriever->exists(activation))
2967  {
2968  /* flag this in the block */
2969  pshvblock->shvret |= RXSHV_NEWV;
2970  }
2971  /* get the variable value */
2972  value = retriever->getValue(activation);
2973  }
2974 
2975  /* copy the value */
2976  pshvblock->shvret |= copyValue(value, &pshvblock->shvvalue, (size_t *)&pshvblock->shvvaluelen);
2977  }
2978  else
2979  {
2980  /* this is bad */
2981  pshvblock->shvret = RXSHV_BADN;
2982  }
2983 }
2984 
2985 
2986 /**
2987  * Perform a variable pool set operation.
2988  *
2989  * @param pshvblock The operation shared variable block.
2990  */
2992 {
2993  RexxVariableBase *retriever = variablePoolGetVariable(pshvblock, pshvblock->shvcode == RXSHV_SYSET);
2994  if (retriever != OREF_NULL)
2995  {
2996  /* have a non-name retriever? */
2997  if (isString((RexxObject *)retriever))
2998  {
2999  /* this is bad */
3000  pshvblock->shvret = RXSHV_BADN;
3001  }
3002  else
3003  {
3004  /* have a non-name retriever */
3005  /* and a new variable? */
3006  if (!retriever->exists(activation))
3007  {
3008  /* flag this in the block */
3009  pshvblock->shvret |= RXSHV_NEWV;
3010  }
3011  /* do the assignment */
3012  retriever->set(activation, new_string(pshvblock->shvvalue));
3013  }
3014  }
3015 }
3016 
3017 
3018 /**
3019  * Perform a variable pool drop operation.
3020  *
3021  * @param pshvblock The operation shared variable block.
3022  */
3024 {
3025  RexxVariableBase *retriever = variablePoolGetVariable(pshvblock, pshvblock->shvcode == RXSHV_SYDRO);
3026  if (retriever != OREF_NULL)
3027  {
3028  /* have a non-name retriever? */
3029  if (isString((RexxObject *)retriever))
3030  {
3031  /* this is bad */
3032  pshvblock->shvret = RXSHV_BADN;
3033  }
3034  else
3035  {
3036  /* have a non-name retriever */
3037  /* and a new variable? */
3038  if (!retriever->exists(activation))
3039  {
3040  /* flag this in the block */
3041  pshvblock->shvret |= RXSHV_NEWV;
3042  }
3043  /* perform the drop */
3044  retriever->drop(activation);
3045  }
3046  }
3047 }
3048 
3049 
3050 /**
3051  * Perform a variable pool fetch next operation.
3052  *
3053  * @param pshvblock The operation shared variable block.
3054  */
3056 {
3057  RexxString *name;
3058  RexxObject *value;
3059  /* get the next variable */
3060  if (!this->fetchNext(&name, &value))
3061  {
3062  pshvblock->shvret |= RXSHV_LVAR; /* flag as such */
3063  }
3064  else
3065  { /* need to copy the name and value */
3066  /* copy the name */
3067  pshvblock->shvret |= copyValue(name, &pshvblock->shvname, &pshvblock->shvnamelen);
3068  /* copy the value */
3069  pshvblock->shvret |= copyValue(value, &pshvblock->shvvalue, &pshvblock->shvvaluelen);
3070  }
3071 }
3072 
3073 
3074 /**
3075  * Perform a variable pool fetch private operation.
3076  *
3077  * @param pshvblock The operation shared variable block.
3078  */
3080 {
3081  /* and VP is enabled */
3082  /* private block should always be enabled */
3083  /* no name given? */
3084  if (pshvblock->shvname.strptr == NULL)
3085  {
3086  pshvblock->shvret |= RXSHV_BADN; /* this is bad */
3087  }
3088  else
3089  {
3090  /* get the variable as a string */
3091  const char *variable = pshvblock->shvname.strptr;
3092  /* want the version string? */
3093  if (strcmp(variable, "VERSION") == 0)
3094  {
3095  /* copy the value */
3096  pshvblock->shvret |= copyValue(Interpreter::getVersionNumber(), &pshvblock->shvvalue, &pshvblock->shvvaluelen);
3097  }
3098  /* want the the current queue? */
3099  else if (strcmp(variable, "QUENAME") == 0)
3100  {
3101  /* copy the value */
3102  pshvblock->shvret |= copyValue(Interpreter::getCurrentQueue(), &pshvblock->shvvalue, &pshvblock->shvvaluelen);
3103  }
3104  /* want the version string? */
3105  else if (strcmp(variable, "SOURCE") == 0)
3106  {
3107  /* retrieve the source string */
3108  RexxString *value = activation->sourceString();
3109  /* copy the value */
3110  pshvblock->shvret |= copyValue(value, &pshvblock->shvvalue, &pshvblock->shvvaluelen);
3111  }
3112  /* want the parameter count? */
3113  else if (strcmp(variable, "PARM") == 0)
3114  {
3116  /* copy the value */
3117  pshvblock->shvret |= copyValue(value, &pshvblock->shvvalue, &pshvblock->shvvaluelen);
3118  }
3119  /* some other parm form */
3120  else if (!memcmp(variable, "PARM.", sizeof("PARM.") - 1))
3121  {
3122  wholenumber_t value_position;
3123  /* extract the numeric piece */
3124  RexxString *tail = new_string(variable + strlen("PARM."));
3125  /* get the binary value */
3126  /* not a good number? */
3127  if (!tail->numberValue(value_position) || value_position <= 0)
3128  {
3129  /* this is a bad name */
3130  pshvblock->shvret |= RXSHV_BADN;
3131  }
3132  else
3133  {
3134  /* get the arcgument from the parent activation */
3135  RexxObject *value = activation->getProgramArgument(value_position);
3136  if (value == OREF_NULL)
3137  { /* doesn't exist? */
3138  value = OREF_NULLSTRING; /* return a null string */
3139  }
3140  /* copy the value */
3141  pshvblock->shvret |= copyValue(value, &pshvblock->shvvalue, (size_t *)&pshvblock->shvvaluelen);
3142  }
3143  }
3144  else
3145  {
3146  pshvblock->shvret |= RXSHV_BADN; /* this is a bad name */
3147  }
3148  }
3149 }
3150 
3151 
3152 /**
3153  * Process a single variable pool request.
3154  *
3155  * @param pshvblock The request block for this request.
3156  */
3158 {
3159  pshvblock->shvret = 0; /* set the block return code */
3160 
3161  switch (pshvblock->shvcode)
3162  {
3163  case RXSHV_FETCH:
3164  case RXSHV_SYFET:
3165  {
3166  variablePoolFetchVariable(pshvblock);
3167  break;
3168  }
3169  case RXSHV_SET:
3170  case RXSHV_SYSET:
3171  {
3172  variablePoolSetVariable(pshvblock);
3173  break;
3174  }
3175  case RXSHV_DROPV:
3176  case RXSHV_SYDRO:
3177  {
3178  variablePoolDropVariable(pshvblock);
3179  break;
3180  }
3181  case RXSHV_NEXTV:
3182  {
3183  variablePoolNextVariable(pshvblock);
3184  break;
3185  }
3186  case RXSHV_PRIV:
3187  {
3188  variablePoolFetchPrivate(pshvblock);
3189  break;
3190  }
3191  default:
3192  {
3193  pshvblock->shvret |= RXSHV_BADF; /* bad function */
3194  break;
3195  }
3196  }
3197 }
3198 
3199 
3200 /**
3201  * Copy a value for a variable pool request, with checks for
3202  * truncation.
3203  *
3204  * @param value The value to copy.
3205  * @param rxstring The target RXSTRING.
3206  * @param length The max length we can copy.
3207  *
3208  * @return A return code to be included in the composite return value.
3209  */
3211 {
3212  RXSTRING temp;
3213 
3214  temp.strptr = const_cast<char *>(rxstring->strptr);
3215  temp.strlength = rxstring->strlength;
3216 
3217  RexxReturnCode rc = copyValue(value, &temp, length);
3218 
3219  rxstring->strptr = temp.strptr;
3220  rxstring->strlength = temp.strlength;
3221  return rc;
3222 }
3223 
3224 
3225 /**
3226  * Copy a value for a variable pool request, with checks for
3227  * truncation.
3228  *
3229  * @param value The value to copy.
3230  * @param rxstring The target RXSTRING.
3231  * @param length The max length we can copy.
3232  *
3233  * @return A return code to be included in the composite return value.
3234  */
3236 {
3237  RexxString * stringVal; /* converted object value */
3238  size_t string_length; /* length of the string */
3239  uint32_t rc; /* return code */
3240 
3241  rc = 0; /* default to success */
3242  /* get the string value */
3243  stringVal = value->stringValue();
3244  string_length = stringVal->getLength();/* get the string length */
3245  // caller allowing use to allocate this?
3246  if (rxstring->strptr == NULL)
3247  {
3248  rxstring->strptr = (char *)SystemInterpreter::allocateResultMemory(string_length + 1);
3249  if (rxstring->strptr == NULL)
3250  {
3251  return RXSHV_MEMFL; /* couldn't allocate, return flag */
3252  }
3253  rxstring->strlength = string_length + 1;
3254  }
3255  /* buffer too short? */
3256  if (string_length > rxstring->strlength)
3257  {
3258  rc = RXSHV_TRUNC; /* set truncated return code */
3259  /* copy the short piece */
3260  memcpy(rxstring->strptr, stringVal->getStringData(), rxstring->strlength);
3261  }
3262  else
3263  {
3264  /* copy entire string */
3265  memcpy(rxstring->strptr, stringVal->getStringData(), string_length);
3266  /* room for a null? */
3267  if (rxstring->strlength > string_length)
3268  {
3269  /* yes, add one */
3270  rxstring->strptr[string_length] = '\0';
3271  }
3272  rxstring->strlength = string_length; /* string length doesn't include terminating 0 */
3273  }
3274  *length = string_length; /* return actual string length */
3275  return rc; /* give back the return code */
3276 }
3277 
3278 int RexxNativeActivation::stemSort(const char *stemname, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
3279 /******************************************************************************/
3280 /* Function: Perform a sort on stem data. If everything works correctly, */
3281 /* this returns zero, otherwise an appropriate error value. */
3282 /******************************************************************************/
3283 {
3284  size_t position; /* scan position within compound name */
3285  size_t length; /* length of tail section */
3286 
3287  /* if access is enabled */
3288  // NB: The braces here are to ensure the ProtectedObjects get released before the
3289  // currentActivity gets zeroed out.
3290  {
3291  /* get the stem name as a string */
3292  RexxString *variable = new_string(stemname);
3293  ProtectedObject p1(variable);
3294  /* and get a retriever for this variable */
3296 
3297  /* this must be a stem variable in order for the sorting to work. */
3298 
3299  if ((!isOfClass(StemVariableTerm, retriever)) && (!isOfClass(CompoundVariableTerm, retriever)))
3300  {
3301  return false;
3302  }
3303 
3304  RexxString *tail = OREF_NULLSTRING;
3305  ProtectedObject p2(tail); // JLF useless here !
3306 
3307  if (isOfClass(CompoundVariableTerm, retriever))
3308  {
3309  length = variable->getLength(); /* get the string length */
3310  position = 0; /* start scanning at first character */
3311  /* scan to the first period */
3312  while (variable->getChar(position) != '.')
3313  {
3314  position++; /* step to the next character */
3315  length--; /* reduce the length also */
3316  }
3317  position++; /* step past previous period */
3318  length--; /* adjust the length */
3319  tail = variable->extract(position, length);
3320  tail = tail->upper();
3321  p2 = tail; // JLF here, it's useful
3322  }
3323 
3324  return retriever->sort(activation, tail, order, type, start, end, firstcol, lastcol);
3325  }
3326 }
3327 
3328 
3329 /**
3330  * Implement the equivalent of a FORWARD CONTINUE instruction
3331  * as an API call. All null arguments are filled in with
3332  * the method context args.
3333  *
3334  * @param to The target object. Defaults to SELF
3335  * @param msg The target message name. Defaults to current message.
3336  * @param super Any superclass override. Defaults to none.
3337  * @param args The message positional arguments. Defaults to current argument set.
3338  *
3339  * @return The message send result.
3340  */
3342 {
3343  // process all of the non-overridden values
3344  if (to == OREF_NULL)
3345  {
3346  to = getSelf();
3347  }
3348 
3349  if (msg == OREF_NULL)
3350  {
3351  msg = getMessageName();
3352  }
3353 
3354  // By default, use the positional & named arguments of the native activation...
3355  size_t _argcount = this->argcount;
3356  size_t _named_argcount = this->named_argcount;
3357  RexxObject **_arglist = this->arglist;
3358 
3359  // ... unless overriden
3360  ProtectedObject p_arguments;
3361  if (positionalArgs != OREF_NULL || namedArgs != OREF_NULL)
3362  {
3363  if (positionalArgs == OREF_NULL)
3364  {
3365  positionalArgs = getPositionalArguments();
3366  }
3367 
3368  if (namedArgs == OREF_NULL)
3369  {
3370  namedArgs = getNamedArguments();
3371  }
3372 
3373  _argcount = positionalArgs->size(); // count of positional arguments
3374  RexxArray *arguments = (RexxArray *)positionalArgs->copy();
3375  p_arguments = arguments;
3376  _named_argcount = namedArgs->appendAllIndexesItemsTo(arguments, /*from*/ _argcount+1); // from is 1-based index
3377 
3378  _arglist = arguments->data();
3379  }
3380 
3381  // no super class override? Normal message send
3382  if (super == OREF_NULL)
3383  {
3384  to->messageSend(msg, _arglist, _argcount, _named_argcount, _result);
3385  }
3386  else
3387  {
3388  to->messageSend(msg, _arglist, _argcount, _named_argcount, super, _result);
3389  }
3390 }
3391 
3392 
3393 /**
3394  * Create a stack frame for exception tracebacks.
3395  *
3396  * @return A StackFrame instance for this activation.
3397  */
3399 {
3400  if (receiver == OREF_NULL)
3401  {
3402  RexxArray *info = new_array(getMessageName());
3403  ProtectedObject p(info);
3404 
3406  p = message;
3408  }
3409  else
3410  {
3411  RexxClass *scope = ((RexxMethod *)getExecutableObject())->getScope();
3412  RexxString *scopeName = (scope == TheNilObject ? scope->requestString() : scope->getId());
3413  ProtectedObject pscopeName(scopeName);
3414  RexxArray *info = new_array(getMessageName(), scopeName);
3415  ProtectedObject p(info);
3416 
3418  p = message;
3419  RexxArray *arguments = getPositionalArguments();
3420  ProtectedObject p_arguments(arguments); // getArguments() returns a new array, so must be protected
3422  }
3423 }
3424 
3425 
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
RexxBuffer * new_buffer(size_t s)
@ T_NativeActivation
RexxDirectory * new_directory()
RexxIdentityTable * new_identity_table()
RexxInteger * new_integer(wholenumber_t v)
uint16_t *(RexxEntry * PNATIVEMETHOD)(RexxMethodContext *, ValueDescriptor *)
uint16_t *(RexxEntry * PNATIVEROUTINE)(RexxCallContext *, ValueDescriptor *)
RexxPointer * new_pointer(void *p)
#define SCOPE_RESERVED
#define SCOPE_RELEASED
ActivityException
#define OREF_NULL
Definition: RexxCore.h:61
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:315
#define TheClassClass
Definition: RexxCore.h:156
bool isString(RexxObject *o)
Definition: RexxCore.h:281
#define TheTrueObject
Definition: RexxCore.h:196
#define isOfClass(t, r)
Definition: RexxCore.h:224
#define ThePointerClass
Definition: RexxCore.h:175
#define TheNilObject
Definition: RexxCore.h:191
#define TheFalseObject
Definition: RexxCore.h:195
#define isOfClassType(t, r)
Definition: RexxCore.h:225
RexxArray * arrayArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:395
#define IntegerZero
Definition: RexxCore.h:199
#define TheMutableBufferClass
Definition: RexxCore.h:170
#define Error_Invalid_argument_range
#define Error_Logical_value_method
#define Error_Incorrect_call_signature
#define Error_Incorrect_method_nostem
#define Error_Invalid_argument_noarg
#define Error_Invalid_argument_double
#define Error_Invalid_argument_maxarg
#define Error_Incorrect_method_signature
#define Error_Incorrect_call_nostem
#define Error_Invalid_argument_pointer
#define Error_Invalid_argument_noclass
#define Message_Translations_compiled_routine_invocation
#define Error_Incorrect_call_external
#define Message_Translations_compiled_method_invocation
#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
#define MAX_NATIVE_ARGUMENTS
#define FRAME_METHOD
#define FRAME_ROUTINE
RexxString * new_string(const char *s, stringsize_t l)
bool isStem(const char *cstring)
virtual void handleError(wholenumber_t, RexxDirectory *)
void setContext(RexxActivity *act, RexxNativeActivation *a)
static RexxActivity *volatile currentActivity
RexxClass * findClass(RexxString *className)
Definition: MethodClass.cpp:87
RexxSource * getSourceObject()
virtual void handleError(wholenumber_t, RexxDirectory *)
void setContext(RexxActivity *act, RexxNativeActivation *a)
static RexxString * getVersionNumber()
Definition: Version.cpp:52
static RexxClass * findClass(RexxString *className)
static RexxString * getCurrentQueue()
static const wholenumber_t MIN_WHOLENUMBER
Definition: Numerics.hpp:63
static bool objectToUintptr(RexxObject *source, uintptr_t &result)
Definition: Numerics.cpp:526
static NumericSettings * getDefaultSettings()
Definition: Numerics.hpp:114
static RexxObject * stringsizeToObject(stringsize_t v)
Definition: Numerics.cpp:203
static const wholenumber_t MAX_WHOLENUMBER
Definition: Numerics.hpp:62
static const bool DEFAULT_FORM
Definition: Numerics.hpp:81
static bool objectToUnsignedInt64(RexxObject *o, uint64_t &result)
Definition: Numerics.cpp:483
static const size_t MAX_STRINGSIZE
Definition: Numerics.hpp:72
static bool objectToUnsignedInteger(RexxObject *o, size_t &result, size_t max)
Definition: Numerics.cpp:361
static bool objectToWholeNumber(RexxObject *o, wholenumber_t &result, wholenumber_t max, wholenumber_t min)
Definition: Numerics.cpp:226
static RexxObject * int64ToObject(int64_t v)
Definition: Numerics.cpp:140
static const size_t DEFAULT_FUZZ
Definition: Numerics.hpp:79
static bool objectToIntptr(RexxObject *source, intptr_t &result)
Definition: Numerics.cpp:549
static RexxObject * wholenumberToObject(wholenumber_t v)
Definition: Numerics.cpp:182
static bool objectToStringSize(RexxObject *o, stringsize_t &result, stringsize_t max)
Definition: Numerics.cpp:312
static bool objectToSignedInteger(RexxObject *o, ssize_t &result, ssize_t max, ssize_t min)
Definition: Numerics.cpp:269
static RexxString * pointerToString(void *)
Definition: Numerics.cpp:888
static bool objectToInt64(RexxObject *o, int64_t &result)
Definition: Numerics.cpp:409
static RexxObject * uint64ToObject(uint64_t v)
Definition: Numerics.cpp:161
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
RexxRoutineHandler * getEntry()
RexxActivationBase * previous
virtual bool trap(RexxString *, RexxDirectory *)
RexxObject * getExecutableObject()
BaseExecutable * executable
RexxActivationBase * getPreviousStackFrame()
BaseExecutable * getExecutable()
virtual RexxActivation * findRexxContext()
RexxDirectory * getAllLocalVariables()
RexxString * sourceString()
void setDigits(size_t)
RexxClass * findClass(RexxString *name)
RexxVariableDictionary * getLocalVariables()
void setFuzz(size_t)
size_t getProgramArgumentCount()
RexxObject * getProgramArgument(size_t position)
RexxObject * getContextObject()
virtual NumericSettings * getNumericSettings()
size_t getActivationLevel()
void requestAccess()
void restoreActivationLevel(size_t l)
void createMethodContext(MethodContext &context, RexxNativeActivation *owner)
void popStackFrame(bool reply)
RexxString * buildMessage(wholenumber_t, RexxArray *)
void reraiseException(RexxDirectory *)
void releaseAccess()
void createCallContext(CallContext &context, RexxNativeActivation *owner)
SecurityManager * getInstanceSecurityManager()
bool raiseCondition(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
RexxActivation * getCurrentRexxFrame()
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxObject * copy()
Definition: ArrayClass.cpp:122
size_t size()
Definition: ArrayClass.hpp:202
RexxObject ** data()
Definition: ArrayClass.hpp:204
virtual char * getData()
RexxString * getId()
Definition: ClassClass.cpp:284
RexxString * createCompoundName(RexxString *stemName)
RexxObject * at(RexxString *)
size_t appendAllIndexesItemsTo(RexxArray *array, size_t from)
static RexxDirectory * fromIndexItemArray(RexxObject **arglist, size_t count)
virtual RexxObject * put(RexxObject *, RexxObject *)
virtual RexxObject * remove(RexxObject *key)
virtual RexxObject * getRealValue(RexxActivation *)
virtual RexxObject * getValue(RexxActivation *)
bool isGuarded()
RexxClass * getScope()
RexxCompoundElement * compoundelement
int64_t int64Value(RexxObject *o, size_t position)
void setNextVariable(size_t value)
RexxReturnCode copyValue(RexxObject *value, RXSTRING *rxstring, size_t *length)
RexxReturnCode variablePoolInterface(PSHVBLOCK requests)
void variablePoolSetVariable(PSHVBLOCK pshvblock)
void dropObjectVariable(const char *name)
RexxDirectory * getNamedArguments()
RexxVariableDictionary * nextCurrent()
BaseExecutable * getRexxContextExecutable()
bool trap(RexxString *, RexxDirectory *)
void callRegisteredRoutine(RoutineClass *routine, RegisteredRoutine *code, RexxString *functionName, RexxObject **list, size_t count, size_t named_count, ProtectedObject &resultObj)
bool isInteger(RexxObject *)
void variablePoolFetchVariable(PSHVBLOCK pshvblock)
bool objectToValue(RexxObject *o, ValueDescriptor *value)
void variablePoolDropVariable(PSHVBLOCK pshvblock)
RexxObject * getContextVariable(const char *name)
void variablePoolFetchPrivate(PSHVBLOCK pshvblock)
stringsize_t unsignedIntegerValue(RexxObject *o, size_t position, stringsize_t maxValue)
RexxDirectory * getAllContextVariables()
RexxVariableDictionary * methodVariables()
virtual SecurityManager * getSecurityManager()
void dropContextVariable(const char *name)
RexxClass * findClass(RexxString *className)
void processArguments(size_t argcount, RexxObject **arglist, uint16_t *argumentTypes, ValueDescriptor *descriptors, size_t maximumArgumentCount)
void setNextCurrent(RexxVariableDictionary *vdict)
wholenumber_t signedIntegerValue(RexxObject *o, size_t position, wholenumber_t maxValue, wholenumber_t minValue)
virtual NumericSettings * getNumericSettings()
RexxVariableBase * variablePoolGetVariable(PSHVBLOCK pshvblock, bool symbolic)
void createLocalReference(RexxObject *objr)
RexxIdentityTable * savelist
void callNativeRoutine(RoutineClass *routine, RexxNativeRoutine *code, RexxString *functionName, RexxObject **list, size_t count, size_t named_count, ProtectedObject &result)
double getDoubleValue(RexxObject *, size_t position)
RexxStem * resolveStemVariable(RexxObject *s)
uint64_t unsignedInt64Value(RexxObject *o, size_t position)
int stemSort(const char *stemname, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
void setCompoundElement(RexxCompoundElement *element)
void * pointerString(RexxObject *object, size_t position)
virtual RexxActivation * getRexxContext()
void setObjectVariable(const char *name, RexxObject *value)
RexxObject * getObjectVariable(const char *name)
SecurityManager * securityManager
RexxObject * valueToObject(ValueDescriptor *value)
void run(RexxMethod *_method, RexxNativeMethod *_code, RexxObject *_receiver, RexxString *_msgname, RexxObject **_arglist, size_t _argcount, size_t _named_argcount, ProtectedObject &resultObj)
void reportStemError(size_t position, RexxObject *object)
void * pointer(RexxObject *)
RexxVariableDictionary * nextcurrent
void removeLocalReference(RexxObject *objr)
virtual RexxObject * getReceiver()
void variablePoolNextVariable(PSHVBLOCK pshvblock)
virtual RexxActivation * findRexxContext()
void setContextVariable(const char *name, RexxObject *value)
RexxObject * getPositionalArgument(size_t index)
void raiseCondition(RexxString *condition, RexxString *description, RexxObject *additional, RexxObject *result)
RexxObject * getContextStem(RexxString *name)
void variablePoolRequest(PSHVBLOCK pshvblock)
const char * cstring(RexxObject *)
void setNextStem(RexxVariable *stemVar)
RexxVariableDictionary * objectVariables
StackFrameClass * createStackFrame()
void forwardMessage(RexxObject *to, RexxString *msg, RexxClass *super, RexxArray *positionalArgs, RexxDirectory *namedArgs, ProtectedObject &result)
void setConditionInfo(RexxDirectory *info)
bool fetchNext(RexxString **name, RexxObject **value)
RexxClass * findCallerClass(RexxString *className)
RexxArray * valuesToObject(ValueDescriptor *value, size_t count)
SecurityManager * getSecurityManager()
PNATIVEMETHOD getEntry()
PNATIVEROUTINE getEntry()
RexxVariableDictionary * getObjectVariables(RexxObject *)
RexxObject * superScope(RexxObject *)
virtual bool doubleValue(double &result)
void * getCSelf()
RexxString * stringValue()
bool messageSend(RexxString *, RexxObject **, size_t, size_t, ProtectedObject &, bool processUnknown=true, bool dynamicTarget=true)
RexxString * requestString()
bool truthValue(int)
bool isInstanceOf(RexxClass *)
virtual bool logicalValue(logical_t &)
SecurityManager * getSecurityManager()
Definition: SourceFile.hpp:380
RexxCompoundElement * nextVariable(RexxNativeActivation *activation)
Definition: StemClass.cpp:652
bool sort(RexxActivation *context, RexxString *prefix, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
bool numberValue(wholenumber_t &result, size_t precision)
void toRxstring(CONSTRXSTRING &r)
size_t getLength()
const char * getStringData()
RexxString * extract(size_t offset, size_t sublength)
RexxString * concatWithCstring(const char *)
bool isEqual(RexxObject *)
bool strCompare(const char *s)
RexxString * upper()
char getChar(size_t p)
virtual void set(RexxActivation *, RexxObject *)
virtual void drop(RexxActivation *)
static RexxVariableBase * getVariableRetriever(RexxString *variable)
static RexxVariableBase * getDirectVariableRetriever(RexxString *variable)
RexxVariable * nextVariable(RexxNativeActivation *)
RexxString * getName()
RexxObject * getVariableValue()
static void * allocateResultMemory(size_t)
static void releaseResultMemory(void *)
virtual void handleError(wholenumber_t, RexxDirectory *)
void setContext(RexxActivity *act, RexxNativeActivation *a)
int type
Definition: cmdparse.cpp:1888
#define REXX_VALUE_double
Definition: oorexxapi.h:67
#define REXX_VALUE_OSELF
Definition: oorexxapi.h:59
#define REXX_VALUE_size_t
Definition: oorexxapi.h:89
#define REXX_VALUE_uint8_t
Definition: oorexxapi.h:78
#define REXX_VALUE_POINTER
Definition: oorexxapi.h:69
#define REXX_VALUE_wholenumber_t
Definition: oorexxapi.h:66
#define REXX_VALUE_SCOPE
Definition: oorexxapi.h:57
#define IS_OPTIONAL_ARGUMENT(t)
Definition: oorexxapi.h:3774
#define REXX_VALUE_stringsize_t
Definition: oorexxapi.h:71
#define ARGUMENT_EXISTS
Definition: oorexxapi.h:257
#define REXX_VALUE_int32_t
Definition: oorexxapi.h:75
#define REXX_VALUE_uintptr_t
Definition: oorexxapi.h:84
#define REXX_VALUE_uint32_t
Definition: oorexxapi.h:80
#define REXX_VALUE_NAME
Definition: oorexxapi.h:56
#define REXX_VALUE_CSELF
Definition: oorexxapi.h:58
#define REXX_VALUE_int
Definition: oorexxapi.h:65
#define REXX_VALUE_float
Definition: oorexxapi.h:72
#define REXX_ARGUMENT_TERMINATOR
Definition: oorexxapi.h:54
#define REXX_VALUE_uint64_t
Definition: oorexxapi.h:81
#define ARGUMENT_TYPE(t)
Definition: oorexxapi.h:3773
#define REXX_VALUE_RexxMutableBufferObject
Definition: oorexxapi.h:93
#define REXX_VALUE_RexxClassObject
Definition: oorexxapi.h:92
#define SPECIAL_ARGUMENT
Definition: oorexxapi.h:259
#define REXX_VALUE_ssize_t
Definition: oorexxapi.h:90
#define REXX_VALUE_RexxStemObject
Definition: oorexxapi.h:88
#define REXX_VALUE_uint16_t
Definition: oorexxapi.h:79
#define REXX_VALUE_ARGLIST
Definition: oorexxapi.h:55
#define REXX_VALUE_int8_t
Definition: oorexxapi.h:73
#define REXX_VALUE_SUPER
Definition: oorexxapi.h:60
#define REXX_VALUE_RexxArrayObject
Definition: oorexxapi.h:87
#define REXX_VALUE_intptr_t
Definition: oorexxapi.h:83
#define REXX_VALUE_RexxObjectPtr
Definition: oorexxapi.h:64
#define REXX_VALUE_RexxStringObject
Definition: oorexxapi.h:70
#define REXX_VALUE_int64_t
Definition: oorexxapi.h:76
#define REXX_VALUE_int16_t
Definition: oorexxapi.h:74
#define REXX_VALUE_logical_t
Definition: oorexxapi.h:86
#define REXX_VALUE_CSTRING
Definition: oorexxapi.h:68
#define REXX_VALUE_POINTERSTRING
Definition: oorexxapi.h:91
struct _RexxClassObject * RexxClassObject
Definition: rexx.h:136
size_t REXXENTRY RexxRoutineHandler(CONSTANT_STRING, size_t, PCONSTRXSTRING, CONSTANT_STRING, PRXSTRING)
Definition: rexx.h:408
const char * CSTRING
Definition: rexx.h:78
struct _RexxMutableBufferObject * RexxMutableBufferObject
Definition: rexx.h:140
struct _RexxStringObject * RexxStringObject
Definition: rexx.h:128
struct _RexxArrayObject * RexxArrayObject
Definition: rexx.h:130
struct _RexxObjectPtr * RexxObjectPtr
Definition: rexx.h:127
ssize_t wholenumber_t
Definition: rexx.h:230
#define MAKERXSTRING(r, p, l)
Definition: rexx.h:182
int RexxReturnCode
Definition: rexx.h:73
size_t stringsize_t
Definition: rexx.h:228
struct _RexxStemObject * RexxStemObject
Definition: rexx.h:139
#define RXSHV_NEWV
Definition: rexxapidefs.h:113
#define RXSHV_DROPV
Definition: rexxapidefs.h:99
#define RXSHV_NEXTV
Definition: rexxapidefs.h:103
#define RXSHV_SYFET
Definition: rexxapidefs.h:101
#define RXSHV_FETCH
Definition: rexxapidefs.h:98
#define RXSHV_NOAVL
Definition: rexxapidefs.h:108
#define RXSHV_BADN
Definition: rexxapidefs.h:116
#define RXSHV_SET
Definition: rexxapidefs.h:97
#define RXSHV_PRIV
Definition: rexxapidefs.h:104
#define RXSHV_SYSET
Definition: rexxapidefs.h:100
#define RXSHV_BADF
Definition: rexxapidefs.h:118
#define RXSHV_SYDRO
Definition: rexxapidefs.h:102
#define RXSHV_LVAR
Definition: rexxapidefs.h:114
#define RXSHV_MEMFL
Definition: rexxapidefs.h:117
#define RXSHV_TRUNC
Definition: rexxapidefs.h:115
const char * strptr
Definition: rexx.h:163
size_t strlength
Definition: rexx.h:162
size_t strlength
Definition: rexx.h:157
char * strptr
Definition: rexx.h:158
size_t shvvaluelen
Definition: rexx.h:209
CONSTANT_RXSTRING shvname
Definition: rexx.h:206
unsigned char shvret
Definition: rexx.h:211
unsigned char shvcode
Definition: rexx.h:210
RXSTRING shvvalue
Definition: rexx.h:207
size_t shvnamelen
Definition: rexx.h:208
struct _SHVBLOCK * shvnext
Definition: rexx.h:205
int32_t value_int32_t
Definition: oorexxapi.h:288
int64_t value_int64_t
Definition: oorexxapi.h:289
uint32_t value_uint32_t
Definition: oorexxapi.h:293
RexxMutableBufferObject value_RexxMutableBufferObject
Definition: oorexxapi.h:304
uint16_t value_uint16_t
Definition: oorexxapi.h:292
uint16_t flags
Definition: oorexxapi.h:339
RexxStringObject value_RexxStringObject
Definition: oorexxapi.h:284
uintptr_t value_uintptr_t
Definition: oorexxapi.h:297
int8_t value_int8_t
Definition: oorexxapi.h:286
uint8_t value_uint8_t
Definition: oorexxapi.h:291
size_t value_size_t
Definition: oorexxapi.h:299
uint16_t type
Definition: oorexxapi.h:338
double value_double
Definition: oorexxapi.h:281
intptr_t value_intptr_t
Definition: oorexxapi.h:296
logical_t value_logical_t
Definition: oorexxapi.h:280
POINTER value_POINTERSTRING
Definition: oorexxapi.h:303
wholenumber_t value_wholenumber_t
Definition: oorexxapi.h:278
RexxClassObject value_RexxClassObject
Definition: oorexxapi.h:276
RexxStemObject value_RexxStemObject
Definition: oorexxapi.h:302
uint64_t value_uint64_t
Definition: oorexxapi.h:294
union _ValueDescriptor::@26 value
int16_t value_int16_t
Definition: oorexxapi.h:287
CSTRING value_CSTRING
Definition: oorexxapi.h:282
stringsize_t value_stringsize_t
Definition: oorexxapi.h:279
RexxArrayObject value_RexxArrayObject
Definition: oorexxapi.h:301
POINTER value_POINTER
Definition: oorexxapi.h:283
ssize_t value_ssize_t
Definition: oorexxapi.h:300
RexxObjectPtr value_RexxObjectPtr
Definition: oorexxapi.h:275
RexxCallContext threadContext
RexxMethodContext threadContext
ValueDescriptor * arguments
Definition: oorexxapi.h:2202
ValueDescriptor * arguments
Definition: oorexxapi.h:1432
#define DEFRXSTRING
#define INT32_MAX
unsigned short uint16_t
#define INTPTR_MIN
#define SSIZE_MAX
UINT_PTR uintptr_t
int int32_t
#define SIZE_MAX
#define UINT16_MAX
signed __int64 int64_t
unsigned int uint32_t
#define INT32_MIN
SSIZE_T ssize_t
#define INTPTR_MAX
short int16_t
#define INT8_MIN
#define INT8_MAX
#define INT64_MIN
#define UINTPTR_MAX
INT_PTR intptr_t
#define UINT32_MAX
unsigned char uint8_t
#define INT16_MAX
#define INT64_MAX
#define INT16_MIN
char int8_t
#define UINT8_MAX
unsigned __int64 uint64_t