ObjectClass.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 /* Object REXX Kernel */
40 /* */
41 /* The main REXX object definitions */
42 /* */
43 /******************************************************************************/
44 #include <ctype.h>
45 #include <string.h>
46 #include "RexxCore.h"
47 #include "ObjectClass.hpp"
48 #include "StringClass.hpp"
49 #include "BufferClass.hpp"
50 #include "RexxSmartBuffer.hpp"
51 #include "DirectoryClass.hpp"
53 #include "ArrayClass.hpp"
54 #include "RexxActivity.hpp"
55 #include "RexxActivation.hpp"
56 #include "MessageClass.hpp"
57 #include "MethodClass.hpp"
59 #include "SourceFile.hpp"
60 #include "ProtectedObject.hpp"
61 #include "PointerClass.hpp"
62 #include "TextClass.hpp"
63 #include "PackageClass.hpp"
64 
65 // singleton class instance
68 
69 
70 /**
71  * Create initial class object at bootstrap time.
72  */
74 {
75  CLASS_CREATE(Object, "Object", RexxClass);
76 }
77 
78 
79 void RexxObject::live(size_t liveMark)
80 /******************************************************************************/
81 /* Function: Normal garbage collection live marking */
82 /******************************************************************************/
83 {
84  memory_mark(this->objectVariables);
85 }
86 
87 void RexxObject::liveGeneral(int reason)
88 /******************************************************************************/
89 /* Function: Generalized object marking */
90 /******************************************************************************/
91 {
92  memory_mark_general(this->objectVariables);
93 }
94 
96 /******************************************************************************/
97 /* Function: Flatten an object */
98 /******************************************************************************/
99 {
101 
102  flatten_reference(newThis->objectVariables, envelope);
103 
105 }
106 
108 /******************************************************************************/
109 /* Function: Create a proxy object for a "special" REXX object */
110 /******************************************************************************/
111 {
112  if (this == TheNilObject)
113  {
114  return(RexxObject *)new_proxy("NIL");
115  }
116  else
117  {
118  return(RexxObject *)this;
119  }
120 }
121 
123  RexxObject *other) /* other object for comparison */
124 /******************************************************************************/
125 /* Function: primitive level equality method used by the hash collection */
126 /* classes for determining equality. */
127 /******************************************************************************/
128 {
129  return ((RexxObject *)this) == other;/* simple identity equality */
130 }
131 
133  RexxObject *other) /* other object for comparison */
134 /******************************************************************************/
135 /* Function: primitive level equality method used by the hash collection */
136 /* classes for determining equality. */
137 /******************************************************************************/
138 {
139  if (this->isBaseClass()) /* not a primitive? */
140  {
141  /* simple identity equality */
142  return ((RexxObject *)this) == other;
143  }
144  else /* return truth value of a compare */
145  {
146  ProtectedObject result;
147  this->sendMessage(OREF_STRICT_EQUAL, other, result);
148  if ((RexxObject *)result == OREF_NULL)
149  {
151  }
152  return ((RexxObject *)result)->truthValue(Error_Logical_value_method);
153  }
154 }
155 
156 
157 /**
158  * Test if an object instance is an enhanced version of a
159  * primitive class or a subclass of the primitive class.
160  *
161  * @return true if the object is a subclass instance or an enhanced one-off.
162  */
164 {
165  return behaviour->isNonPrimitive();
166 }
167 
168 
169 
170 
171 /**
172  * Test if an object instance is a true instance of a primitive
173  * class.
174  *
175  * @return true if the object is not a subclass instance or an enhanced one-off.
176  */
178 {
179  return behaviour->isPrimitive();
180 }
181 
182 
183 /**
184  * Wrapper around the compareTo() method that validates and
185  * extracts integer value.
186  *
187  * @param other The other comparison object
188  *
189  * @return -1, 0, 1 depending on the comparison result.
190  */
192 {
193  ProtectedObject result;
194 
195  sendMessage(OREF_COMPARETO, other, result);
196  if ((RexxObject *)result == OREF_NULL)
197  {
199  }
200  wholenumber_t comparison;
201 
202  if (!((RexxObject *)result)->numberValue(comparison))
203  {
205  }
206  return comparison;
207 }
208 
209 
210 /**
211  * Test if an internal object is an instance of another class.
212  *
213  * @param other The test class.
214  *
215  * @return Always returns false.
216  */
218 {
219  // internal classes always fail this
220  return false;
221 }
222 
223 
224 /**
225  * Test if a Rexx object is an instance of a given class.
226  *
227  * @param other The other test class.
228  *
229  * @return True if this object is an instance of the target class, false otherwise.
230  */
232 {
233  return classObject()->isCompatibleWith(other);
234 }
235 
236 
237 /**
238  * The Rexx external version of the instance of.
239  *
240  * @param other The other test class.
241  *
242  * @return .true if this class is an instance of the target class. .false
243  * otherwise.
244  */
246 {
247  requiredArgument(other, OREF_positional, ARG_ONE);
248  return isInstanceOf(other) ? TheTrueObject : TheFalseObject;
249 }
250 
251 
252 /**
253  * Retrieve the method instance for an object's defined method.
254  *
255  * @param method_name
256  * The method name.
257  *
258  * @return The method object that implements the object method.
259  */
261 {
262  return (RexxMethod *)TheNilObject;
263 }
264 
265 
266 /**
267  * Retrieve the method instance for an object's defined method.
268  *
269  * @param method_name
270  * The method name.
271  *
272  * @return The method object that implements the object method.
273  */
275 {
276  // the name must be a string...and we use it in upper case
277  method_name = stringArgument(method_name, OREF_positional, ARG_ONE)->upper();
278  ProtectedObject p(method_name);
279  // retrieve the method from the dictionary
280  RexxMethod *method_object = (RexxMethod *)this->behaviour->getMethodDictionary()->stringGet(method_name);
281  // We return .nil if the method doesn't exist.
282  if (method_object == OREF_NULL)
283  {
284  return (RexxMethod *)TheNilObject;
285  }
286  return method_object; // got a live one
287 }
288 
289 
290 /**
291  * Return a supplier containing the methods implemented by an
292  * object. Depending on the argument, this is either A) all of
293  * the methods, B) just the explicitly set instance methods, or
294  * C) the methods provided by a given class.
295  *
296  * @param class_object
297  * The target class object (optional).
298  *
299  * @return A supplier with the appropriate method set.
300  */
302 {
303  return OREF_NULL;
304 }
305 
306 
307 /**
308  * Return a supplier containing the methods implemented by an
309  * object. Depending on the argument, this is either A) all of
310  * the methods, B) just the explicitly set instance methods, or
311  * C) the methods provided by a given class.
312  *
313  * @param class_object
314  * The target class object (optional).
315  *
316  * @return A supplier with the appropriate method set.
317  */
319 {
320  // the behaviour handles all of this
321  return this->behaviour->getMethods(class_object);
322 }
323 
324 
325 /**
326  * Retrieve the method instance for an object's defined method.
327  *
328  * @param method_name
329  * The method name.
330  *
331  * @return The method object that implements the object method.
332  */
334 {
335  return instanceMethod(method_name);
336 }
337 
338 
339 /**
340  * Return a supplier containing the methods implemented by an
341  * object. Depending on the argument, this is either A) all of
342  * the methods, B) just the explicitly set instance methods, or
343  * C) the methods provided by a given class.
344  *
345  * @param class_object
346  * The target class object (optional).
347  *
348  * @return A supplier with the appropriate method set.
349  */
351 {
352  return instanceMethods(class_object);
353 }
354 
355 
356 /**
357  * Default implementation of the HASHCODE method.
358  *
359  * @return The object's hash code value.
360  */
362 {
363  // get the hash value directly, then turn it into a binary string value
364  HashCode h = getHashValue();
365  /* create a string value */
366  return (RexxObject *)new_string((char *)&h, sizeof(HashCode));
367 }
368 
369 
370 /**
371  * Hash an exported object. Of we're a non-primitive one, this
372  * will require us to send the HASHCODE message to request a
373  * hash value.
374  *
375  * @return A "hashed hash" that can be used by the map collections.
376  */
378 {
379  // if this is a primitive object, we can just return the primitive hash code.
380  if (this->isBaseClass())
381  {
382  return getHashValue();
383  }
384  else
385  {
386  ProtectedObject result;
387  // we have some other type of object, so we need to request a hash code
388  // by sending the HASHCODE() message.
389  this->sendMessage(OREF_HASHCODE, result);
390  return ((RexxObject *)result)->stringValue()->getObjectHashCode();
391  }
392 }
393 
394 
396  RexxObject * other) /* other object for comparison */
397 /******************************************************************************/
398 /* Function: Process the default "==" strict comparison operator */
399 /******************************************************************************/
400 {
401  requiredArgument(other, OREF_positional, ARG_ONE); /* must have the other argument */
402  /* this is direct object equality */
403  return (RexxObject *)((this == other) ? TheTrueObject : TheFalseObject);
404 }
405 
407 /******************************************************************************/
408 /* Function: Normal "=" type comparison. This only returns true if the */
409 /* two objects are the same object */
410 /******************************************************************************/
411 {
412  requiredArgument(other, OREF_positional, ARG_ONE); /* must have the other argument */
413  /* this is direct object equality */
414  return (RexxObject *)((this == other) ? TheTrueObject : TheFalseObject);
415 }
416 
418 /******************************************************************************/
419 /* Function: Return the strict inequality of two objects */
420 /******************************************************************************/
421 {
422  requiredArgument(other, OREF_positional, ARG_ONE); /* first argument is required */
423  return this != other ? TheTrueObject : TheFalseObject;
424 }
425 
427 /******************************************************************************/
428 /* Function: Return the inequality of two objects */
429 /******************************************************************************/
430 {
431  requiredArgument(other, OREF_positional, ARG_ONE); /* first argument is required */
432  return this != other ? TheTrueObject : TheFalseObject;
433 }
434 
435 /**
436  * Convert an object to a logical value without raising an
437  * error.
438  *
439  * @param result The converted value.
440  *
441  * @return true if this converted ok, false for an invalid logical.
442  */
444 {
445  return false;
446 }
447 
448 
449 /**
450  * Convert an object to a logical value without raising an
451  * error.
452  *
453  * @param result The converted value.
454  *
455  * @return true if this converted ok, false for an invalid logical.
456  */
458 {
459  return REQUEST_STRING(this)->logicalValue(result);
460 }
461 
462 
464  int errorCode) /* error to issue for bad conversion */
465 /******************************************************************************/
466 /* Function: test the truth value of a primitive object */
467 /******************************************************************************/
468 {
469  /* report the error */
470  reportException(errorCode, OREF_NULLSTRING);
471  return false; /* need a return value */
472 }
473 
475  int errorCode) /* error to issue for bad conversion */
476 /******************************************************************************/
477 /* Function: test the truth value of a primitive object */
478 /******************************************************************************/
479 {
480  /* just return string truth value */
481  return REQUEST_STRING(this)->truthValue(errorCode);
482 }
483 
485 /******************************************************************************/
486 /* Function: First level primitive copy of an object. This just copies */
487 /* the object storage, and nothing else. */
488 /******************************************************************************/
489 {
490  /* Instead of calling new_object and memcpy, ask the memory object to make */
491  /* a copy of ourself. This way, any header information can be correctly */
492  /* initialized by memory. */
493  return (RexxObject *)this->clone();
494 }
495 
496 void *RexxInternalObject::operator new(size_t size,
497  RexxClass *classObject) /* class of the object */
498 /******************************************************************************/
499 /* Function: Create a new primitive object */
500 /******************************************************************************/
501 {
502  /* get storage for a new object */
503  RexxObject *newObject = (RexxObject *)new_object(size);
504  /* use the class instance behaviour */
505  newObject->setBehaviour(classObject->getInstanceBehaviour());
506  return(void *)newObject; /* and return the new object */
507 }
508 
509 void *RexxInternalObject::operator new(size_t size,
510  RexxClass * classObject, /* class of the object */
511  RexxObject **arguments, /* arguments to the new method */
512  size_t argCount, /* the count of arguments */
513  size_t named_argCount)
514 /******************************************************************************/
515 /* Function: Create a new instance of object (with arguments) */
516 /******************************************************************************/
517 {
518  /* Get storage for a new object */
519  RexxObject *newObject = (RexxObject *)new_object(size);
520  /* use the classes instance behaviour*/
521  newObject->setBehaviour(classObject->getInstanceBehaviour());
522  return newObject; /* and return the object */
523 }
524 
526 /******************************************************************************/
527 /* Function: Copy an object that has an Object Variable Dictionary (OVD) */
528 /******************************************************************************/
529 {
530  /* Instead of calling new_object and memcpy, ask the memory object to make */
531  /* a copy of ourself. This way, any header information can be correctly */
532  /* initialized by memory. */
533  RexxObject *newObj = (RexxObject *)this->clone();
534  /* have object variables? */
535  if (this->objectVariables != OREF_NULL)
536  {
537  ProtectedObject p(newObj);
538  copyObjectVariables(newObj); /* copy the object variables into the new object */
539  }
540  /* have instance methods? */
542  {
543  /* need to copy the behaviour */
544  ProtectedObject p(newObj);
545  newObj->setBehaviour((RexxBehaviour *)newObj->behaviour->copy());
546  }
547  return newObj; /* return the copied version */
548 }
549 
551 /******************************************************************************/
552 /* Function: Copy an object's object variable dictionaries into another obj. */
553 /******************************************************************************/
554 {
555  RexxVariableDictionary *dictionary = objectVariables;
556  /* clear out the existing object variable pointer */
557  newObj->objectVariables = OREF_NULL;
558 
559  while (dictionary != OREF_NULL)
560  {
561  /* copy the dictionary */
562  RexxVariableDictionary *newDictionary = (RexxVariableDictionary *)dictionary->copy();
563  /* add this to the variable set */
564  newObj->addObjectVariables(newDictionary);
565  /* now that the dictionary is anchored in the new object, */
566  /* copy the variable objects inside. */
567  newDictionary->copyValues();
568  /* and repeat for each one */
569  dictionary = dictionary->getNextDictionary();
570  }
571 }
572 
574 /******************************************************************************/
575 /* Function: Check a private method for accessibility. */
576 /******************************************************************************/
577 {
578  /* get the top activation */
580  /* have an activation? */
581  if (activation != OREF_NULL)
582  {
583  RexxObject *sender = activation->getReceiver();/* get the receiving object */
584  if (sender == (RexxObject *)this) /* the same receiver? */
585  {
586  return method; /* just return the same method */
587  }
588  // no sender means this is a routine or program context. Definitely not allowed.
589  if (sender == OREF_NULL)
590  {
591  error = Error_No_method_private;
592  return OREF_NULL;
593  }
594  // ok, now we check the various scope possibilities
595  RexxClass *scope = method->getScope();
596  // 1) Another instance of the same class that defined the method?
597  if (sender->isInstanceOf(scope))
598  {
599  return method; // ok, we'll allow this
600  }
601  // if the sender is a class object, check the class for compatibility with the
602  // method scope
603  if (isOfClassType(Class, sender))
604  {
605  // if this class is part of the compatible hierarchy, this is also permitted
606  if (((RexxClass *)sender)->isCompatibleWith(scope))
607  {
608  return method;
609  }
610  }
611  }
612  // can't touch this...
613  error = Error_No_method_private;
614  return OREF_NULL; /* return a failure indicator */
615 }
616 
617 /**
618  * Check a package method for accessibility.
619  *
620  * @param method The method object to check
621  * @param error The error to be raised if this is not permitted.
622  *
623  * @return An executable method, or OREF_NULL if this cannot be called.
624  */
626 {
627  // get the calling activation context
629 
630  // likely a topLevel call via SendMessage() API which is contextless.
631  if (activation == OREF_NULL)
632  {
633  error = Error_No_method_package;
634  return OREF_NULL;
635  }
636  // get the package from that frame.
637  PackageClass *callerPackage = activation->getPackage();
638 
639  // it is possible this is a special native activation, which means there
640  // is no caller context. This is a no-go.
641  if (callerPackage == OREF_NULL)
642  {
643  return OREF_NULL;
644  }
645 
646  // defined in the same package, this is good.
647  if (method->isSamePackage(callerPackage))
648  {
649  return method;
650  }
651  // can't touch this...
652  error = Error_No_method_package;
653  return OREF_NULL;
654 }
655 
656 
657 // Should be named sendWith
659 {
660  ProtectedObject r;
661  this->sendMessage(message, args, named_args, r);
662  return (RexxObject *)r;
663 }
664 
665 RexxObject *RexxObject::sendMessage(RexxString *message, RexxObject **args, size_t argCount, size_t named_argCount)
666 {
667  ProtectedObject r;
668  this->sendMessage(message, args, argCount, named_argCount, r);
669  return (RexxObject *)r;
670 }
671 
673 {
674  ProtectedObject r;
675  this->sendMessage(message, r);
676  return (RexxObject *)r;
677 }
678 
680 {
681  ProtectedObject r;
682  this->sendMessage(message, argument1, r);
683  return (RexxObject *)r;
684 }
685 
686 
688 {
689  ProtectedObject r;
690  this->sendMessage(message, argument1, argument2, r);
691  return (RexxObject *)r;
692 }
693 
694 
695 RexxObject *RexxObject::sendMessage(RexxString *message, RexxObject *argument1, RexxObject *argument2, RexxObject *argument3)
696 {
697  ProtectedObject r;
698  this->sendMessage(message, argument1, argument2, argument3, r);
699  return (RexxObject *)r;
700 }
701 
702 
703 RexxObject *RexxObject::sendMessage(RexxString *message, RexxObject *argument1, RexxObject *argument2, RexxObject *argument3, RexxObject *argument4)
704 {
705  ProtectedObject r;
706  this->sendMessage(message, argument1, argument2, argument3, argument4, r);
707  return (RexxObject *)r;
708 }
709 
710 
711 RexxObject *RexxObject::sendMessage(RexxString *message, RexxObject *argument1, RexxObject *argument2, RexxObject *argument3, RexxObject *argument4, RexxObject *argument5)
712 {
713  ProtectedObject r;
714  this->sendMessage(message, argument1, argument2, argument3, argument4, argument5, r);
715  return (RexxObject *)r;
716 }
717 
718 
720  RexxString *message, /* name of the message to process */
721  RexxArray *arguments, /* array of arguments */
722  RexxDirectory * named_arguments,
723  ProtectedObject &result)
724 {
725  if (named_arguments == OREF_NULL || named_arguments == TheNilObject)
726  {
727  /******************************************************************************/
728  /* Function: Issue a message using a set of arguments already in an array item*/
729  /******************************************************************************/
730  this->messageSend(message, arguments->data(), arguments->size(), 0, result);
731  }
732  else
733  {
734  size_t argumentsCount = arguments ? arguments->size() : 0;
735  RexxArray *args = arguments ? (RexxArray *)arguments->copy() : new_array();
736  ProtectedObject p(args);
737  size_t namedArgumentsCount = named_arguments->appendAllIndexesItemsTo(args, /*from*/ argumentsCount+1); // from is 1-based index
738 
739  this->messageSend(message, args->data(), argumentsCount, namedArgumentsCount, result);
740  }
741 }
742 
744 {
745  RexxObject *arguments[1];
746  arguments[0] = argument1; // positional argument
747  this->messageSend(message, arguments, 1, 0, result);
748 }
749 
751  RexxString *message, /* name of the message to process */
752  RexxObject *argument1, /* first argument */
753  RexxObject *argument2, /* second argument */
754  ProtectedObject &result)
755  /******************************************************************************/
756  /* Function: Send a message with two arguments */
757  /******************************************************************************/
758 {
759  RexxObject *arguments[2]; /* argument array */
760 
761  arguments[0] = argument1; /* set each argument */
762  arguments[1] = argument2;
763  /* just pass on to message send */
764  this->messageSend(message, arguments, 2, 0, result);
765 }
766 
768  RexxString *message, /* name of the message to process */
769  RexxObject *argument1, /* first argument */
770  RexxObject *argument2, /* second argument */
771  RexxObject *argument3, /* third argument */
772  ProtectedObject &result)
773  /******************************************************************************/
774  /* Function: Send a message with three arguments */
775  /******************************************************************************/
776 {
777  RexxObject *arguments[3]; /* argument array */
778 
779  arguments[0] = argument1; /* set each argument */
780  arguments[1] = argument2;
781  arguments[2] = argument3;
782  /* just pass on to message send */
783  this->messageSend(message, arguments, 3, 0, result);
784 }
785 
787  RexxString *message, /* name of the message to process */
788  RexxObject *argument1, /* first argument */
789  RexxObject *argument2, /* second argument */
790  RexxObject *argument3, /* third argument */
791  RexxObject *argument4, /* fourth argument */
792  ProtectedObject &result)
793  /******************************************************************************/
794  /* Function: Send a message with four arguments */
795  /******************************************************************************/
796 {
797  RexxObject *arguments[4]; /* argument array */
798 
799  arguments[0] = argument1; /* set each argument */
800  arguments[1] = argument2;
801  arguments[2] = argument3;
802  arguments[3] = argument4;
803  /* just pass on to message send */
804  this->messageSend(message, arguments, 4, 0, result);
805 }
806 
808  RexxString *message, /* name of the message to process */
809  RexxObject *argument1, /* first argument */
810  RexxObject *argument2, /* second argument */
811  RexxObject *argument3, /* third argument */
812  RexxObject *argument4, /* fourth argument */
813  RexxObject *argument5, /* fifth argument */
814  ProtectedObject &result)
815  /******************************************************************************/
816  /* Function: Send a message with five arguments */
817  /******************************************************************************/
818 {
819  RexxObject *arguments[5]; /* argument array */
820 
821  arguments[0] = argument1; /* set each argument */
822  arguments[1] = argument2;
823  arguments[2] = argument3;
824  arguments[3] = argument4;
825  arguments[4] = argument5;
826  /* just pass on to message send */
827  this->messageSend(message, arguments, 5, 0, result);
828 }
829 
831  RexxString *msgname, /* name of the message to process */
832  RexxObject **arguments, /* array of arguments */
833  size_t count, /* count of arguments */
834  size_t named_count,
835  ProtectedObject &result, // returned result
836  bool processUnknown,
837  bool dynamicTarget)
838  /******************************************************************************/
839  /* Function: send a message (with message lookup) to an object. */
840  /* All types of methods are handled and dispatched */
841  /******************************************************************************/
842 {
843  ActivityManager::currentActivity->checkStackSpace(); /* have enough stack space? */
844 
845  RexxObject *target = this;
846  if (dynamicTarget) target = this->dynamicTarget(arguments, count, named_count);
847  ProtectedObject p_target(target);
848 
849  /* grab the method from this level */
850  RexxMethod *method_save = target->behaviour->methodLookup(msgname);
851 
853 
854  /* method exists...special processing*/
855  if (method_save != OREF_NULL && method_save->isSpecial())
856  {
857  if (method_save->isPrivate()) /* actually private method? */
858  {
859  /* go validate a private method */
860  method_save = target->checkPrivate(method_save, error);
861  }
862  else if (method_save->isPackageScope())
863  {
864  method_save = target->checkPackage(method_save, error);
865  }
866 
867  /* now process protected methods */
868  if (method_save != OREF_NULL && method_save->isProtected())
869  {
870  /* really a protected method */
871  target->processProtectedMethod(msgname, method_save, arguments, count, named_count, result);
872  return true;
873  }
874  }
875  /* have a method */
876  if (method_save != OREF_NULL)
877  {
878  method_save->run(ActivityManager::currentActivity, target, msgname, arguments, count, named_count, result);
879  return true;
880  }
881  else if (processUnknown)
882  {
883  /* go process an unknown method */
884  target->processUnknown(error, msgname, arguments, count, named_count, result);
885  }
886  return false;
887 }
888 
890  RexxString *msgname, /* name of the message to process */
891  RexxObject **arguments, /* array of arguments */
892  size_t count, /* count of arguments */
893  size_t named_count,
894  RexxObject *startscope, /* starting superclass scope */
895  ProtectedObject &result, // returned result
896  bool processUnknown,
897  bool dynamicTarget)
898  /******************************************************************************/
899  /* Function: send a message (with message lookup) to an object. */
900  /* All types of methods are handled and dispatched */
901  /******************************************************************************/
902 {
903  ActivityManager::currentActivity->checkStackSpace(); /* have enough stack space? */
904 
905  RexxObject *target = this;
906  if (dynamicTarget) target = this->dynamicTarget(arguments, count, named_count);
907  ProtectedObject p_target(target);
908 
909  // to double check: if the target is different from this, maybe startscope will not be applicable
910  /* go to the higher level */
911  RexxMethod *method_save = target->superMethod(msgname, startscope);
912 
914 
915  if (method_save != OREF_NULL && method_save->isSpecial())
916  {
917  if (method_save->isPrivate()) /* actually private method? */
918  {
919  method_save = target->checkPrivate(method_save, error);
920  }
921  else if (method_save->isPackageScope())
922  {
923  method_save = target->checkPackage(method_save, error);
924  }
925 
926  // a protected method...this gets special send handling
927  if (method_save != OREF_NULL && method_save->isProtected())
928  {
929  target->processProtectedMethod(msgname, method_save, arguments, count, named_count, result);
930  return true;
931  }
932  }
933  /* have a method */
934  if (method_save != OREF_NULL)
935  {
936  /* run the method */
937  method_save->run(ActivityManager::currentActivity, target, msgname, arguments, count, named_count, result);
938  return true;
939  }
940  else if (processUnknown)
941  {
942  /* go process an unknown method */
943  target->processUnknown(error, msgname, arguments, count, named_count, result);
944  }
945  return false;
946 }
947 
949  RexxString * messageName, /* message to issue */
950  RexxMethod * targetMethod, // the method to run
951  RexxObject ** arguments, /* actual message arguments */
952  size_t count, /* count of arguments */
953  size_t named_count,
954  ProtectedObject &result) // returned result
955 /******************************************************************************/
956 /* Function: Process an unknown message, uncluding looking for an UNKNOWN */
957 /* method and raising a NOMETHOD condition */
958 /******************************************************************************/
959 {
960  // get the current security manager
962  // the security manager can replace provide a new result
963  if (manager->checkProtectedMethod(this, messageName, count, named_count, arguments, result))
964  {
965  return;
966  }
967  /* run the method */
968  targetMethod->run(ActivityManager::currentActivity, this, messageName, arguments, count, named_count, result);
969 }
970 
972  RexxErrorCodes error,
973  RexxString * messageName, /* message to issue */
974  RexxObject ** arguments, /* actual message arguments */
975  size_t count, /* count of arguments */
976  size_t named_count,
977  ProtectedObject &result) // returned result
978 /******************************************************************************/
979 /* Function: Process an unknown message, uncluding looking for an UNKNOWN */
980 /* method and raising a NOMETHOD condition */
981 /******************************************************************************/
982 {
983  /* no method for this msgname */
984  /* find the unknown method */
985  RexxMethod *method_save = this->behaviour->methodLookup(OREF_UNKNOWN);
986  if (method_save == OREF_NULL) /* "unknown" method exists? */
987  /* no unknown method - try to raise */
988  /* a NOMETHOD condition, and if that */
989  {
990  reportNomethod(error, messageName, this); /* fails, it is an error message */
991  }
992 
993  RexxArray *argumentArray = new_array(count); /* get an array for the positional arguments */
994  ProtectedObject p(argumentArray);
995 
996  for (size_t i = 1; i <= count; i++) /* copy the positional arguments into an array */
997  {
998  argumentArray->put(arguments[i - 1], i);
999  }
1000 
1001  // The case no named argument is very common.
1002  // To avoid any performance loss, avoid to create a directory when named_count = 0.
1003  // This is managed by RexxDirectory::fromIndexItemArray which returns OREF_NULL when count = 0.
1004  RexxDirectory *namedArgumentDirectory = RexxDirectory::fromIndexItemArray(arguments + count, named_count);
1005  ProtectedObject p1(namedArgumentDirectory);
1006 
1007  RexxObject *unknown_arguments[2 + (1 * 2)];/* positional & named arguments to the unknown method */
1008  unknown_arguments[0] = messageName; /* method name is first argument */
1009  /* second argument is array of */
1010  unknown_arguments[1] = argumentArray;/* arguments for the original call */
1011  unknown_arguments[2] = OREF_NAMEDARGUMENTS;
1012  unknown_arguments[3] = namedArgumentDirectory ? namedArgumentDirectory : TheNilObject;
1013  /* run the unknown method */
1014  method_save->run(ActivityManager::currentActivity, this, OREF_UNKNOWN, unknown_arguments, 2, 1, result);
1015 }
1016 
1018  RexxString *msgname) /* name of the target message */
1019 /******************************************************************************/
1020 /* Function: Return the method object associated with a message name */
1021 /******************************************************************************/
1022 {
1023  return this->behaviour->methodLookup(msgname);
1024 }
1025 
1027 /******************************************************************************/
1028 /* Function: Convert a primitive internal object to a long value */
1029 /******************************************************************************/
1030 {
1031  return false; /* give a "safe" default here */
1032 }
1033 
1035 /******************************************************************************/
1036 /* Function: Convert a primitive internal object to a long value */
1037 /******************************************************************************/
1038 {
1039  return false; /* give a "safe" default here */
1040 }
1041 
1043 /******************************************************************************/
1044 /* Function: Convert a primitive internal object to a long value */
1045 /******************************************************************************/
1046 {
1047  return false; /* give a "safe" default here */
1048 }
1049 
1051 /******************************************************************************/
1052 /* Function: Convert a primitive internal object to a long value */
1053 /******************************************************************************/
1054 {
1055  return false; /* give a "safe" default here */
1056 }
1057 
1059 /******************************************************************************/
1060 /* Function: Convert a primitive internal object to a double value */
1061 /******************************************************************************/
1062 {
1063  return false; /* give a "safe" default here */
1064 }
1065 
1067  size_t precision) /* precision to use */
1068 /******************************************************************************/
1069 /* Function: Convert a primitive internal object to an integer value */
1070 /******************************************************************************/
1071 {
1072  return (RexxInteger *)TheNilObject; /* give a "safe" default here */
1073 }
1074 
1076 /******************************************************************************/
1077 /* Function: convert an internal object to a numberstring representation */
1078 /******************************************************************************/
1079 {
1080  return OREF_NULL; /* this never converts */
1081 }
1082 
1084 /******************************************************************************/
1085 /* Function: Convert a REXX object to a long value */
1086 /******************************************************************************/
1087 {
1088  /* get a string and convert */
1089  return REQUEST_STRING(this)->numberValue(result, digits);
1090 }
1091 
1093 /******************************************************************************/
1094 /* Function: Convert a REXX object to a long value */
1095 /******************************************************************************/
1096 {
1097  /* get a string and convert */
1098  return REQUEST_STRING(this)->numberValue(result);
1099 }
1100 
1102 /******************************************************************************/
1103 /* Function: Convert a REXX object to a long value */
1104 /******************************************************************************/
1105 {
1106  /* get a string and convert */
1107  return REQUEST_STRING(this)->unsignedNumberValue(result, digits);
1108 }
1109 
1111 /******************************************************************************/
1112 /* Function: Convert a REXX object to a long value */
1113 /******************************************************************************/
1114 {
1115  /* get a string and convert */
1116  return REQUEST_STRING(this)->unsignedNumberValue(result);
1117 }
1118 
1119 bool RexxObject::doubleValue(double &result)
1120 /******************************************************************************/
1121 /* Function: Convert a primitive internal object to a double value */
1122 /******************************************************************************/
1123 {
1124  /* get a string and convert */
1125  return this->requestString()->doubleValue(result);
1126 }
1127 
1129  size_t precision) /* precision to use */
1130 /******************************************************************************/
1131 /* Function: Convert a primitive internal object to an integer value */
1132 /******************************************************************************/
1133 {
1134  /* get a string and convert */
1135  return REQUEST_STRING(this)->integerValue(precision);
1136 }
1137 
1139 /******************************************************************************/
1140 /* Function: convert a standard object to a numberstring representation */
1141 /******************************************************************************/
1142 {
1143  /* get the string representation, */
1144  /* return the numberstring form */
1145  return this->requestString()->numberString();
1146 }
1147 
1149 /******************************************************************************/
1150 /* Function: Convert a primitive internal object to a string value */
1151 /******************************************************************************/
1152 {
1153  return OREF_NULLSTRING; /* give a "safe" default here */
1154 }
1155 
1157 /******************************************************************************/
1158 /* Function: Convert a primitive internal object to a text value */
1159 /******************************************************************************/
1160 {
1161  return TheNullText; /* give a "safe" default here */
1162 }
1163 
1165 /******************************************************************************/
1166 /* Function: Convert a primitive object to a string value */
1167 /******************************************************************************/
1168 {
1169  /* issue the object name message */
1170  return (RexxString *)this->sendMessage(OREF_OBJECTNAME);
1171 }
1172 
1174 /******************************************************************************/
1175 /* Function: Convert a primitive object to a text value */
1176 /******************************************************************************/
1177 {
1178  // printf("RexxObject::textValue this = %x, type = %s\n", this, this->behaviour->getOwningClass()->getId()->getStringData());
1179  /* issue the text message */
1180  RexxText *result = (RexxText *)this->sendMessage(OREF_TEXT);
1181  // printf("RexxObject::textValue result = %x, type = %s\n", result, result->behaviour->getOwningClass()->getId()->getStringData());
1182  return result;
1183 }
1184 
1186 /******************************************************************************/
1187 /* Function: Handle a string conversion REQUEST for an internal object */
1188 /******************************************************************************/
1189 {
1190  return (RexxString *)TheNilObject; /* should never occur */
1191 }
1192 
1193 
1195 /******************************************************************************/
1196 /* Function: Handle a text conversion REQUEST for an internal object */
1197 /******************************************************************************/
1198 {
1199  return (RexxText *)TheNilObject; /* should never occur */
1200 }
1201 
1202 
1204 /******************************************************************************/
1205 /* Function: Handle a tail construction request for an internal object */
1206 /******************************************************************************/
1207 {
1208  return; /* should never occur */
1209 }
1210 
1212 /******************************************************************************/
1213 /* Function: Handle a string conversion REQUEST for an internal object */
1214 /******************************************************************************/
1215 {
1216  return (RexxString *)TheNilObject; /* should never occur */
1217 }
1218 
1220 /******************************************************************************/
1221 /* Function: Handle a text conversion REQUEST for an internal object */
1222 /******************************************************************************/
1223 {
1224  return (RexxText *)TheNilObject; /* should never occur */
1225 }
1226 
1228 /******************************************************************************/
1229 /* Function: Handle a string conversion REQUEST for a REXX object */
1230 /******************************************************************************/
1231 {
1232  if (this->isBaseClass()) /* primitive object? */
1233  return (RexxString *)TheNilObject; /* this never converts */
1234  else /* process as a string request */
1235  {
1236  return (RexxString *)this->sendMessage(OREF_REQUEST, OREF_STRINGSYM);
1237  }
1238 }
1239 
1240 
1242 /******************************************************************************/
1243 /* Function: Handle a text conversion REQUEST for a REXX object */
1244 /******************************************************************************/
1245 {
1246  if (this->isBaseClass()) /* primitive object? */
1247  return (RexxText *)TheNilObject; /* this never converts */
1248  else /* process as a text request */
1249  {
1250  return (RexxText *)this->sendMessage(OREF_REQUEST, OREF_TEXT);
1251  }
1252 }
1253 
1254 
1256 /******************************************************************************/
1257 /* Function: Handle a tail construction request for an internal object */
1258 /******************************************************************************/
1259 {
1260  /* get our string value */
1261  RexxString *value = REQUEST_STRING(this);
1262  ProtectedObject p(value);
1263  value->copyIntoTail(tail); /* pass this on to the string value */
1264 }
1265 
1266 
1268 /******************************************************************************/
1269 /* Function: Handle an array conversion REQUEST for an internal object */
1270 /******************************************************************************/
1271 {
1272  return (RexxArray *)TheNilObject; /* should never occur */
1273 }
1274 
1276 /******************************************************************************/
1277 /* Function: Handle a string conversion REQUEST for a REXX object */
1278 /******************************************************************************/
1279 {
1280  if (this->isBaseClass()) /* primitive object? */
1281  return (RexxArray *)TheNilObject; /* this never converts */
1282  else /* process as a string request */
1283  {
1284  return (RexxArray *)this->sendMessage(OREF_REQUEST, OREF_ARRAYSYM);
1285  }
1286 }
1287 
1289 /******************************************************************************/
1290 /* Function: Handle a string request for a REXX object. This will go */
1291 /* through the whole search order to do the conversion. */
1292 /******************************************************************************/
1293 {
1294 
1295  /* primitive object? */
1296  if (this->isBaseClass())
1297  {
1298  RexxString *string_value; /* converted object */
1299  /* get the string representation */
1300  string_value = this->primitiveMakeString();
1301  if (string_value == TheNilObject)
1302  {/* didn't convert? */
1303  /* get the final string value */
1304  string_value = this->stringValue();
1305  /* raise a NOSTRING condition */
1306  ActivityManager::currentActivity->raiseCondition(OREF_NOSTRING, OREF_NULL, string_value, this, OREF_NULL);
1307  }
1308  return string_value; /* return the converted form */
1309  }
1310  else
1311  { /* do a real request for this */
1312  ProtectedObject string_value;
1313 
1314  this->sendMessage(OREF_REQUEST, OREF_STRINGSYM, string_value);
1315  // The returned value might be an Integer or NumberString value. We need to
1316  // force this to be a real string value.
1317  string_value = ((RexxObject *)string_value)->primitiveMakeString();
1318  if (string_value == TheNilObject)
1319  {/* didn't convert? */
1320  /* get the final string value */
1321  this->sendMessage(OREF_STRINGSYM, string_value);
1322  // we're really dependent upon the program respecting the protocol
1323  // here and returning a value. It is possible there is a
1324  // problem, so how to handle this. We could just raise an error, but this
1325  // isn't the most ideal message since the error is raised at the
1326  // line where the string value is required, but this is a rare
1327  // situation. As a fallback, use the default object STRING method,
1328  // then raise an error if we still don't get anything. This at least
1329  // keeps the interpreter from crashing, there's a good chance the
1330  // program will run. Frankly, there's something seriously wrong
1331  // if this error ever gets issued.
1332  if (((RexxObject *)string_value) == OREF_NULL)
1333  {
1334  string_value = RexxObject::stringValue();
1335  if (((RexxObject *)string_value) == OREF_NULL)
1336  {
1338  }
1339  }
1340  // The returned value might be an Integer or NumberString value. We need to
1341  // force this to be a real string value.
1342  string_value = ((RexxObject *)string_value)->primitiveMakeString();
1343  /* raise a NOSTRING condition */
1344  ActivityManager::currentActivity->raiseCondition(OREF_NOSTRING, OREF_NULL, (RexxString *)string_value, this, OREF_NULL);
1345  }
1346  return (RexxString *)string_value; /* return the converted form */
1347  }
1348 }
1349 
1351 /******************************************************************************/
1352 /* Function: Handle a string request for a REXX object. This will go */
1353 /* through the whole search order to do the conversion. */
1354 /******************************************************************************/
1355 {
1356 
1357  /* primitive object? */
1358  if (this->isBaseClass())
1359  {
1360  RexxString *string_value; /* converted object */
1361  /* get the string representation */
1362  string_value = this->primitiveMakeString();
1363  if (string_value == TheNilObject)
1364  {/* didn't convert? */
1365  /* get the final string value */
1366  string_value = this->stringValue();
1367  }
1368  return string_value;
1369  }
1370  else
1371  { /* do a real request for this */
1372  ProtectedObject string_value;
1373  this->sendMessage(OREF_REQUEST, OREF_STRINGSYM, string_value);
1374  if (string_value == TheNilObject)
1375  {/* didn't convert? */
1376  /* get the final string value */
1377  this->sendMessage(OREF_STRINGSYM, string_value);
1378  }
1379  return(RexxString *)string_value; /* return the converted form */
1380  }
1381 }
1382 
1383 
1385 /******************************************************************************/
1386 /* Function: Handle a text request for a REXX object. This will go */
1387 /* through the whole search order to do the conversion. */
1388 /******************************************************************************/
1389 {
1390 
1391  /* primitive object? */
1392  if (this->isBaseClass())
1393  {
1394  // printf("RexxObject::requestText: case base class\n");
1395  RexxText *text_value; /* converted object */
1396  /* get the text representation */
1397  text_value = this->primitiveMakeText();
1398  if (text_value == TheNilObject)
1399  {/* didn't convert? */
1400  /* get the final text value */
1401  text_value = this->textValue();
1402  }
1403  return text_value;
1404  }
1405  else
1406  { /* do a real request for this */
1407  // printf("RexxObject::requestText: not case base class\n");
1408  ProtectedObject text_value;
1409  this->sendMessage(OREF_REQUEST, OREF_TEXT, text_value);
1410  if (text_value == TheNilObject)
1411  {/* didn't convert? */
1412  /* get the final text value */
1413  this->sendMessage(OREF_TEXT, text_value);
1414  }
1415  return (RexxText *)text_value; /* return the converted form */
1416  }
1417 }
1418 
1419 
1421  RexxString *kind,
1422  size_t position) /* required argument position */
1423 /******************************************************************************/
1424 /* Function: Handle a string request for a REXX object in a context where */
1425 /* the object MUST have a string value. */
1426 /******************************************************************************/
1427 {
1428  RexxObject *string_value; /* converted object */
1429 
1430  if (this->isBaseClass()) /* primitive object? */
1431  {
1432  string_value = this->makeString(); /* get the string representation */
1433  }
1434  else /* do a full request for this */
1435  {
1436  string_value = this->sendMessage(OREF_REQUEST, OREF_STRINGSYM);
1437  }
1438  /* didn't convert? */
1439  if (string_value == TheNilObject)
1440  {
1441  /* this is an error */
1443  }
1444  return(RexxString *)string_value; /* return the converted form */
1445 }
1446 
1447 
1449  RexxString *kind,
1450  const char *name) /* required argument position */
1451 /******************************************************************************/
1452 /* Function: Handle a string request for a REXX object in a context where */
1453 /* the object MUST have a string value. */
1454 /******************************************************************************/
1455 {
1456  RexxObject *string_value; /* converted object */
1457 
1458  if (this->isBaseClass()) /* primitive object? */
1459  {
1460  string_value = this->makeString(); /* get the string representation */
1461  }
1462  else /* do a full request for this */
1463  {
1464  string_value = this->sendMessage(OREF_REQUEST, OREF_STRINGSYM);
1465  }
1466  /* didn't convert? */
1467  if (string_value == TheNilObject)
1468  {
1469  /* this is an error */
1471  }
1472  return(RexxString *)string_value; /* return the converted form */
1473 }
1474 
1475 /**
1476  * Handle a string request for a required string value where
1477  * the caller wishes to handle the error itself.
1478  *
1479  * @return The object's string value, or OREF_NULL if this is not a
1480  * string.
1481  */
1483 {
1484  // primitive object? We have a bypass for this
1485  if (this->isBaseClass())
1486  {
1487  return this->makeString();
1488  }
1489  else
1490  {
1491  // we have to use REQUEST to get this
1492  return (RexxString *)this->sendMessage(OREF_REQUEST, OREF_STRINGSYM);
1493  }
1494 }
1495 
1496 
1498  size_t precision) /* precision to use */
1499 /******************************************************************************/
1500 /* Function: Request an integer value from an object. If this is not a */
1501 /* primitive object, the object will be converted to a string, */
1502 /* and then the string integer value will be returned. */
1503 /******************************************************************************/
1504 {
1505  if (this->isBaseClass()) /* primitive object? */
1506  {
1507  /* return the integer value */
1508  return this->integerValue(precision);
1509  }
1510  else /* return integer value of string */
1511  {
1512  return this->requestString()->integerValue(precision);
1513  }
1514 }
1515 
1517  RexxString *kind,
1518  size_t position, /* precision to use */
1519  size_t precision) /* argument position for errors */
1520 /******************************************************************************/
1521 /* Function: Request an integer value from an object. If this is not a */
1522 /* primitive object, a REQUEST('STRING') will be performeding, */
1523 /* and then the string integer value will be returned. */
1524 /******************************************************************************/
1525 {
1526  RexxInteger *result; /* returned result */
1527 
1528  if (this->isBaseClass()) /* primitive object? */
1529  {
1530  /* return the integer value */
1531  result = this->integerValue(precision);
1532  }
1533  else /* return integer value of string */
1534  {
1535  result = this->requiredString(kind, position)->integerValue(precision);
1536  }
1537  /* didn't convert well? */
1538  if (result == (RexxInteger *)TheNilObject)
1539  {
1540  /* raise an error */
1541  reportException(Error_Incorrect_method_whole, kind, position, this);
1542  }
1543  return result; /* return the new integer */
1544 }
1545 
1546 
1547 /**
1548  * Request an object to convert itself into a number value.
1549  *
1550  * @param result The numeric result value.
1551  * @param precision The precision used for the conversion.
1552  *
1553  * @return true if the object converted ok, false for a conversion failure.
1554  */
1555 bool RexxObject::requestNumber(wholenumber_t &result, size_t precision)
1556 {
1557  if (isBaseClass())
1558  {
1559  // are we already a base class?
1560  // the base classes can handle this directly.
1561  return numberValue(result, precision);
1562  }
1563  else
1564  {
1565  // we need to perform the operation on the string value
1566  return numberValue(result, precision);
1567  }
1568 }
1569 
1570 
1571 /**
1572  * Request an object to convert itself into a number value.
1573  *
1574  * @param result The numeric result value.
1575  * @param precision The precision used for the conversion.
1576  *
1577  * @return true if the object converted ok, false for a conversion failure.
1578  */
1579 bool RexxObject::requestUnsignedNumber(stringsize_t &result, size_t precision)
1580 {
1581  if (isBaseClass())
1582  {
1583  // are we already a base class?
1584  // the base classes can handle this directly.
1585  return unsignedNumberValue(result, precision);
1586  }
1587  else
1588  {
1589  // we need to perform the operation on the string value
1590  return unsignedNumberValue(result, precision);
1591  }
1592 }
1593 
1594 
1596  RexxString *kind,
1597  size_t position, /* precision to use */
1598  size_t precision) /* argument position for errors */
1599 /******************************************************************************/
1600 /* Function: Request a long value from an object. If this is not a */
1601 /* primitive object, a REQUEST('STRING') will be performed */
1602 /* and then the string long value will be returned. */
1603 /******************************************************************************/
1604 {
1605  wholenumber_t result; /* returned result */
1606 
1607  /* primitive object? */
1608  if (this->isBaseClass() && !isOfClass(Object, this))
1609  {
1610  if (!numberValue(result, precision))
1611  {
1612  /* raise an error */
1613  reportException(Error_Incorrect_method_whole, kind, position, this);
1614  }
1615  }
1616  else /* return integer value of string */
1617  {
1618  if (!requiredString(kind, position)->numberValue(result, precision))
1619  {
1620  /* raise an error */
1621  reportException(Error_Incorrect_method_whole, kind, position, this);
1622  }
1623  }
1624  return result; /* return the result */
1625 }
1626 
1628  RexxString *kind,
1629  size_t position, /* precision to use */
1630  size_t precision) /* argument position for errors */
1631 /******************************************************************************/
1632 /* Function: Request a a positive long value from an object. If this is not */
1633 /* positive, it will raise an error. */
1634 /******************************************************************************/
1635 {
1636  stringsize_t result; /* returned result */
1637 
1638  if (!unsignedNumberValue(result, precision) || result == 0)
1639  {
1640  /* raise the error */
1641  reportException(Error_Incorrect_method_positive, kind, position, this);
1642  }
1643  return result;
1644 }
1645 
1646 
1648  RexxString *kind,
1649  size_t position, /* precision to use */
1650  size_t precision) /* argument position for errors */
1651 /******************************************************************************/
1652 /* Function: Request a non-negative long value from an object. If this is */
1653 /* less than zero, it will raise an error */
1654 /******************************************************************************/
1655 {
1656  stringsize_t result; /* returned result */
1657 
1658  if (!unsignedNumberValue(result, precision))
1659  {
1660  /* raise the error */
1661  reportException(Error_Incorrect_method_nonnegative, kind, position, this);
1662  }
1663  return result;
1664 }
1665 
1666 
1668 /******************************************************************************/
1669 /* Function: Request an array value from an object. */
1670 /******************************************************************************/
1671 {
1672  if (this->isBaseClass()) /* primitive object? */
1673  {
1674  if (isOfClass(Array, this)) /* already an array? */
1675  return (RexxArray *)this; /* return directly, don't makearray */
1676  else
1677  return this->makeArray(); /* return the array value */
1678  }
1679  else /* return integer value of string */
1680  {
1681  return (RexxArray *)this->sendMessage(OREF_REQUEST, OREF_ARRAYSYM);
1682  }
1683 }
1684 
1686 /******************************************************************************/
1687 /* Function: Request a directory value from an object. */
1688 /******************************************************************************/
1689 {
1690  if (this->isBaseClass() && isOfClass(Directory, this)) return (RexxDirectory *)this;
1691  return (RexxDirectory *)this->sendMessage(OREF_REQUEST, OREF_DIRECTORY);
1692 }
1693 
1695 /******************************************************************************/
1696 /* Function: Retrieve the object name for a primitive object */
1697 /******************************************************************************/
1698 {
1699  ProtectedObject string_value; /* returned string value */
1700 
1701  RexxObject *scope = lastMethod()->getScope(); /* get the method's scope */
1702  /* get the object name variable */
1703  string_value = (RexxString *)this->getObjectVariable(OREF_NAME, scope);
1704  if ((RexxObject *)string_value == OREF_NULL)
1705  { /* no name? */
1706  if (this->isBaseClass()) /* primitive object? */
1707  {
1708  /* use fast path to default name */
1709  string_value = this->defaultName();
1710  }
1711  else /* go through the full search */
1712  {
1713  this->sendMessage(OREF_DEFAULTNAME, string_value);
1714  }
1715  }
1716  return(RexxString *)string_value; /* return the string value */
1717 }
1718 
1720 /******************************************************************************/
1721 /* Function: retrieve an objects default name value */
1722 /******************************************************************************/
1723 {
1724  RexxObject *scope; /* scope of the object */
1725 
1726  requiredArgument(name, OREF_positional, ARG_ONE); /* must have a name */
1727  scope = lastMethod()->getScope(); /* get the method's scope */
1728  /* get this as a string */
1729  name = (RexxObject *)stringArgument(name, OREF_positional, ARG_ONE);
1730  /* set the name */
1731  this->setObjectVariable(OREF_NAME, name, scope);
1732  return OREF_NULL; /* no return value */
1733 }
1734 
1736 /******************************************************************************/
1737 /* Function: Handle "final" string coercion level */
1738 /******************************************************************************/
1739 {
1740  /* use the class id as the default */
1741  /* name */
1742  RexxString *defaultname = this->behaviour->getOwningClass()->getId();
1743  /* check if it is from an enhanced */
1744  if (this->behaviour->isEnhanced())
1745  { /* class */
1746  /* return the 'enhanced' id */
1747  return defaultname->concatToCstring("enhanced ");
1748  }
1749  switch (defaultname->getChar(0))
1750  { /* process based on first character*/
1751  case 'a': /* vowels */
1752  case 'A':
1753  case 'e':
1754  case 'E':
1755  case 'i':
1756  case 'I':
1757  case 'o':
1758  case 'O':
1759  case 'u':
1760  case 'U':
1761  /* prefix with "an" */
1762  defaultname = defaultname->concatToCstring("an ");
1763  break;
1764 
1765  default: /* consonants */
1766  /* prefix with "a" */
1767  defaultname = defaultname->concatToCstring("a ");
1768  break;
1769  }
1770  return defaultname; /* return that value */
1771 }
1772 
1774 /******************************************************************************/
1775 /* Function: Check for the presense of a method on the object */
1776 /******************************************************************************/
1777 {
1778  /* check the behaviour for the method*/
1779  return (this->behaviour->methodLookup(msgname) != OREF_NULL) ? TheTrueObject : TheFalseObject;
1780 }
1781 
1783 /******************************************************************************/
1784 /* Function: Return the class object associated with an object */
1785 /******************************************************************************/
1786 {
1787  /* just return class from behaviour */
1788  return this->behaviour->getOwningClass();
1789 }
1790 
1792  RexxString *msgname, /* name of the new method */
1793  RexxMethod *methobj, /* associated method object/code */
1794  RexxString *option)
1795  /******************************************************************************/
1796  /* Function: Add a new method to an object instance */
1797  /******************************************************************************/
1798 {
1799  /* get the message name as a string */
1800  msgname = stringArgument(msgname, OREF_positional, ARG_ONE)->upper();
1801  ProtectedObject p(msgname);
1802  if (option)
1803  {
1804  option = stringArgument(option, OREF_positional, ARG_THREE);
1805  if (!Utilities::strCaselessCompare("OBJECT", option->getStringData()))
1806  {
1807  // do nothing if OBJECT
1808  }
1809  else if (!Utilities::strCaselessCompare("FLOAT", option->getStringData()))
1810  {
1811  // "FLOAT" makes option a NULL pointer, causing the old default behaviour on setMethod...
1812  option = OREF_NULL;
1813  }
1814  else
1815  {
1816  RexxString *info = new_string("\"FLOAT\", \"OBJECT\"");
1817  ProtectedObject p(info);
1818  reportException(Error_Incorrect_call_list, OREF_SETMETHOD, OREF_positional, IntegerThree, info, option);
1819  }
1820  }
1821  ProtectedObject p2(option);
1822 
1823  if (methobj == OREF_NULL) /* we weren't passed a method, */
1824  {
1825  /* add a dummy method */
1826  methobj = (RexxMethod *)TheNilObject;
1827  }
1828  else if (!isOfClass(Method, methobj)) /* not a method type already? */
1829  {
1830  /* make one from a string or array */
1831  methobj = RexxMethod::newMethodObject(msgname, (RexxObject *)methobj, IntegerTwo, OREF_NULL);
1832  }
1833  this->defMethod(msgname, methobj, option); /* defMethod handles all the details */
1834  return OREF_NULL; /* no return value */
1835 }
1836 
1838  RexxString *msgname) /* target message name */
1839 /******************************************************************************/
1840 /* Function: Remove a method from an object instance */
1841 /******************************************************************************/
1842 {
1843  /* get the message name as a string */
1844  msgname = stringArgument(msgname, OREF_positional, ARG_ONE)->upper();
1845  ProtectedObject p(msgname);
1846  /* now just go remove this */
1847  this->behaviour->removeMethod(msgname);
1848  return OREF_NULL; /* no return value */
1849 }
1850 
1852  RexxString *className) /* target name of the class */
1853 /******************************************************************************/
1854 /* Function: Externalized version of the REQUEST method. This tries to */
1855 /* convert one class of object into another. */
1856 /******************************************************************************/
1857 {
1858  /* Verify we have a string parm */
1859  className = stringArgument(className, OREF_positional, ARG_ONE)->upper();
1860  ProtectedObject p1(className);
1861  RexxString *class_id = this->id()->upper(); /* get the class name in uppercase */
1862  ProtectedObject p2(class_id);
1863  /* of the same class? */
1864  if (className->strictEqual(class_id) == TheTrueObject)
1865  {
1866  return this; /* already converted */
1867  }
1868  /* Get "MAKE"||class methodname */
1869  RexxString *make_method = className->concatToCstring(CHAR_MAKE);
1870  /* find the MAKExxxx method */
1871  // RexxMethod *method = this->behaviour->methodLookup(make_method);
1872  RexxMethod *method = this->instanceMethod(make_method);
1873  /* have this method? */
1874  // if (method != OREF_NULL)
1875  if (method != TheNilObject)
1876  {
1877  /* Return its results */
1878  return this->sendMessage(make_method);
1879  }
1880  else /* No makeclass method */
1881  {
1882  return TheNilObject; /* Let user handle it */
1883  }
1884 }
1885 
1886 
1887 RexxObject *RexxObject::dynamicTargetRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
1888 {
1889  return this->dynamicTarget(arguments, argCount, named_argCount);
1890 }
1891 
1892 /**
1893  * Do a dynamic invocation of an object method.
1894  *
1895  * @param message The target message. This can be either a string message
1896  * name or a string/scope pair to do a qualified invocation.
1897  * @param arguments An array of arguments to used with the message invocation.
1898  *
1899  * @return The method result.
1900  */
1902  RexxObject **named_arglist, size_t named_argcount)
1903 {
1904  RexxString *messageName;
1905  RexxObject *startScope;
1906  // decode and validate the message input
1907  decodeMessageName(this, message, messageName, startScope);
1908  ProtectedObject m(messageName);
1909 
1910  arguments = arrayArgument(arguments, OREF_positional, ARG_TWO);
1911  ProtectedObject p(arguments);
1912  size_t count = arguments->size();
1913 
1914  // Named arguments
1915  // >>-sendWith(-messagename-,-arguments-+--------------------------+--)---><
1916  // +-,-namedArguments-:-exprd-+
1917 
1918  // use strict named arg namedArguments=.NIL
1919  NamedArguments expectedNamedArguments(1); // At most, one named argument
1920  expectedNamedArguments[0] = NamedArgument("NAMEDARGUMENTS", TheNilObject); // At least 1 characters, default value = .NIL
1921  expectedNamedArguments.match(named_arglist, named_argcount, /*strict*/ true, /*extraAllowed*/ false);
1922 
1923  RexxDirectory *named_arguments_value = (RexxDirectory*)expectedNamedArguments[0].value;
1924  ProtectedObject p_named_arguments_value;
1925  size_t named_count = 0;
1926  if (named_arguments_value != OREF_NULL && named_arguments_value != TheNilObject)
1927  {
1928  /* get a directory version */
1929  named_arguments_value = named_arguments_value->requestDirectory();
1930  p_named_arguments_value = named_arguments_value; // GC protect
1931 
1932  /* not a directory item ? */
1933  if (named_arguments_value == TheNilObject)
1934  {
1935  reportException(Error_Execution_user_defined, "SENDWITH namedArguments must be a directory or NIL");
1936  }
1937  named_count = named_arguments_value->items();
1938  }
1939 
1940  RexxArray *new_arguments = arguments;
1941  ProtectedObject p_new_arguments;
1942  if (named_count != 0)
1943  {
1944  // Optimization: do a copy of the positional arguments only is some named arguments must be added
1945  new_arguments = (RexxArray *)arguments->copy();
1946  p_new_arguments = new_arguments;
1947  named_arguments_value->appendAllIndexesItemsTo(new_arguments, /*from*/ count+1); // from is 1-based index
1948  }
1949 
1950  ProtectedObject r;
1951  if (startScope == OREF_NULL)
1952  {
1953  this->messageSend(messageName, new_arguments->data(), count, named_count, r);
1954  }
1955  else
1956  {
1957  this->messageSend(messageName, new_arguments->data(), count, named_count, startScope, r);
1958  }
1959  return (RexxObject *)r;
1960 }
1961 
1962 
1963 /**
1964  * Do a dynamic invocation of an object method.
1965  *
1966  * @param arguments The variable arguments passed to the method. The first
1967  * argument is a required message target, which can be either
1968  * a string method name or an array containing a name/scope
1969  * pair. The remainder of the arguments are the message
1970  * arguments.
1971  * @param argCount
1972  *
1973  * @return The method result.
1974  */
1975 RexxObject *RexxObject::send(RexxObject **arguments, size_t argCount, size_t named_argCount)
1976 {
1977  if (argCount < 1) /* no arguments? */
1978  {
1979  missingArgument(OREF_positional, ARG_ONE); /* Yes, this is an error. */
1980  }
1981 
1982  RexxString *messageName;
1983  RexxObject *startScope;
1984  // decode and validate the message input
1985  decodeMessageName(this, arguments[0], messageName, startScope);
1986  ProtectedObject m(messageName);
1987 
1988  ProtectedObject r;
1989  if (startScope == OREF_NULL)
1990  {
1991  this->messageSend(messageName, arguments + 1, argCount - 1, named_argCount, r);
1992  }
1993  else
1994  {
1995  this->messageSend(messageName, arguments + 1, argCount - 1, named_argCount, startScope, r);
1996  }
1997  return (RexxObject *)r;
1998 }
1999 
2000 
2001 /**
2002  * Perform a start() using arguments provided in an
2003  * array wrapper.
2004  *
2005  * @param message The target message. This can be either a string, or an
2006  * array containing a string/scope coupling.
2007  * @param arguments The message arguments.
2008  *
2009  * @return The message object.
2010  */
2012  RexxObject **named_arglist, size_t named_argcount)
2013 {
2014  // the message is required
2015  requiredArgument(message, OREF_positional, ARG_ONE);
2016  // this is required and must be an array
2017  arguments = arrayArgument(arguments, OREF_positional, ARG_TWO);
2018  ProtectedObject p(arguments);
2019  size_t count = arguments->size();
2020 
2021  // Named arguments
2022  // >> -startWith(-messagename - , -arguments - +-------------------------- + -)---> <
2023  // +-, -namedArguments-:-exprd-+
2024 
2025  // use strict named arg namedArguments=.NIL
2026  NamedArguments expectedNamedArguments(1); // At most, one named argument
2027  expectedNamedArguments[0] = NamedArgument("NAMEDARGUMENTS", TheNilObject); // At least 1 characters, default value = .NIL
2028  expectedNamedArguments.match(named_arglist, named_argcount, /*strict*/ true, /*extraAllowed*/ false);
2029  RexxDirectory *named_arguments_value = (RexxDirectory*)expectedNamedArguments[0].value;
2030 
2031  ProtectedObject p_named_arguments_value;
2032  size_t named_count = 0;
2033  if (named_arguments_value != OREF_NULL && named_arguments_value != TheNilObject)
2034  {
2035  /* get a directory version */
2036  named_arguments_value = named_arguments_value->requestDirectory();
2037  p_named_arguments_value = named_arguments_value; // GC protect
2038 
2039  /* not a directory item ? */
2040  if (named_arguments_value == TheNilObject)
2041  {
2042  reportException(Error_Execution_user_defined, "STARTWITH namedArguments must be a directory or NIL");
2043  }
2044  named_count = named_arguments_value->items();
2045  }
2046 
2047  RexxArray *new_arguments = arguments;
2048  ProtectedObject p_new_arguments;
2049  if (named_count != 0)
2050  {
2051  new_arguments = (RexxArray *)arguments->copy();
2052  p_new_arguments = new_arguments;
2053  named_arguments_value->appendAllIndexesItemsTo(new_arguments, /*from*/ count+1); // from is 1-based index
2054  }
2055 
2056  // the rest is handled by code common to startWith();
2057  return startCommon(message, new_arguments->data(), count, named_count);
2058 }
2059 
2060 
2061 /**
2062  * Run a message send in another thread.
2063  *
2064  * @param arguments The list of arguments. This is an open-ended argument
2065  * list. The first argument is the message, the remaining
2066  * arguments are the message arguments.
2067  * @param argCount The number of arguments we were invoked with.
2068  *
2069  * @return The count of arguments.
2070  */
2071 RexxMessage *RexxObject::start(RexxObject **arguments, size_t argCount, size_t named_argCount)
2072 {
2073  if (argCount < 1) /* no arguments? */
2074  {
2075  missingArgument(OREF_positional, ARG_ONE); /* Yes, this is an error. */
2076  }
2077  /* Get the message name. */
2078  RexxObject *message = arguments[0]; /* get the message . */
2079  /* Did we receive a message name */
2080  requiredArgument(message, OREF_positional, ARG_ONE);
2081  // the rest is handled by code common to startWith();
2082  return startCommon(message, arguments + 1, argCount - 1, named_argCount);
2083 }
2084 
2085 
2086 /**
2087  * A common method to process either a start() or a
2088  * startWith() method call.
2089  *
2090  * @param message The message name (which might be an array form)
2091  * @param arguments The array of arguments.
2092  * @param argCount The number of passed arguments.
2093  *
2094  * @return The message object spun off to process this message.
2095  */
2096 RexxMessage *RexxObject::startCommon(RexxObject *message, RexxObject **arguments, size_t argCount, size_t named_argCount)
2097 {
2098  RexxString *messageName;
2099  RexxObject *startScope;
2100  // decode and validate the message input
2101  decodeMessageName(this, message, messageName, startScope);
2102  ProtectedObject m(messageName);
2103 
2104  /* Create the new message object. */
2105  RexxArray *argPtr = new (argCount + 2 * named_argCount, arguments) RexxArray;
2106  ProtectedObject p_argPtr(argPtr);
2107  RexxMessage *newMessage = new RexxMessage(this, messageName, startScope, argPtr->data(), argCount, named_argCount);
2108  ProtectedObject p(newMessage);
2109  newMessage->start(OREF_NULL); /* Tell the message object to start */
2110  return newMessage; /* return the new message object */
2111 }
2112 
2113 
2114 /**
2115  * A static method that can be used to decode the
2116  * various message argument varieties used with start(),
2117  * startWith(), and the Message class new.
2118  *
2119  * @param message The input message. This can be a message name or an
2120  * array containing a message name/startscope pairing.
2121  * @param messageName
2122  * @param startScope
2123  */
2124 void RexxObject::decodeMessageName(RexxObject *target, RexxObject *message, RexxString *&messageName, RexxObject *&startScope)
2125 {
2126  // clear the starting scope
2127  startScope = OREF_NULL;
2128 
2129  /* if 1st arg is a string, we can do */
2130  /* this quickly */
2131  if (!isOfClass(String, message))
2132  {
2133  // this must be an array
2134  RexxArray *messageArray = arrayArgument(message, OREF_positional, ARG_ONE);
2135  ProtectedObject p(messageArray);
2136 
2137  // must be single dimension with two arguments
2138  if (messageArray->getDimension() != 1 || messageArray->size() != 2)
2139  {
2140  /* raise an error */
2142  }
2143  // get the message as a string in uppercase.
2144  messageName = stringArgument(messageArray->get(1), OREF_positional, ARG_ONE)->upper();
2145  startScope = messageArray->get(2);
2146  requiredArgument(startScope, OREF_positional, ARG_TWO);
2147 
2148  // validate the message creator now
2150  /* have an activation? */
2151  if (activation != OREF_NULL)
2152  {
2153  /* get the receiving object */
2154  RexxObject *sender = activation->getReceiver();
2155  if (sender != target) /* not the same receiver? */
2156  {
2157  /* this is an error */
2159  }
2160  }
2161  else
2162  {
2163  /* this is an error */
2165  }
2166  }
2167  else /* not an array as message. */
2168  {
2169  /* force to a string value */
2170  messageName = stringArgument(message, OREF_positional, ARG_ONE)->upper();
2171  }
2172 }
2173 
2174 
2176 /****************************************************************************/
2177 /* Function: Return the objects address as a HEX string (debugging only) */
2178 /****************************************************************************/
2179 {
2180  char buffer[20]; /* buffered address */
2181 
2182  snprintf(buffer, sizeof buffer, "%p", this); /* format this */
2183  /* and return a string */
2184  return(RexxString *)new_string(buffer, 8);
2185 }
2186 
2188 /****************************************************************************/
2189 /* Function: Tag an object as having an UNINIT method */
2190 /****************************************************************************/
2191 {
2192  /* tell the activity about this */
2194 }
2195 
2196 
2198  RexxObject **arguments, /* method arguments */
2199  size_t argumentsCount, /* the number of positional arguments*/
2200  size_t named_argumentsCount)
2201 /****************************************************************************/
2202 /* Function: Run a method on an object as if it was part of the object's */
2203 /* behaviour. */
2204 /****************************************************************************/
2205 {
2206  RexxArray *arglist = OREF_NULL; /* forwarded option string */
2207  RexxDirectory *argdirectory = OREF_NULL;
2208  RexxObject **argumentPtr = OREF_NULL; /* default to no arguments passed along */
2209  size_t argcount = 0; // the number of arguments in the array expra
2210  size_t named_argcount = 0; // the number of arguments in the directory exprd
2211 
2212  ProtectedObject p_arglist;
2213  ProtectedObject p_argdirectory;
2214 
2215  /*
2216  >>-run(-method-+-------------------------------------------------------+-)--><
2217  +-,-"Individual"---| Arguments |------------------------+
2218  +--+-------------------+--+--------------------------+--+
2219  +-,-"Array"-,-expra-+ +-,-namedArguments-:-exprd-+
2220  */
2221 
2222  // must have at least a first positional argument
2223  if (argumentsCount == 0)
2224  {
2225  missingArgument(OREF_positional, "method");
2226  }
2227 
2228  /* get the method object */
2229  RexxMethod *methobj = (RexxMethod *)arguments[0];
2230  requiredArgument(methobj, OREF_positional, ARG_ONE); /* make sure we have a method */
2231  if (!isOfClass(Method, methobj)) /* this a method object? */
2232  {
2233  /* create a method object */
2234  methobj = RexxMethod::newMethodObject(OREF_RUN, (RexxObject *)methobj, IntegerOne, OREF_NULL);
2235  /* set the correct scope */
2236  methobj->setScope((RexxClass *)TheNilObject);
2237  }
2238  else
2239  {
2240  /* ensure correct scope on method */
2241  methobj = methobj->newScope((RexxClass *)TheNilObject);
2242  }
2243  // we need to save this, since we might be working off of a newly created
2244  // one or a copy
2245  ProtectedObject p(methobj);
2246 
2247  char option = ' '; // No option by default
2248  if (argumentsCount > 1) /* if any positional arguments passed */
2249  {
2250  /* get the 1st one, its the option */
2251  RexxString *optionString = (RexxString *)arguments[1];
2252  /* this is now required */
2253  optionString = stringArgument(optionString, OREF_positional, ARG_TWO);
2254  option = toupper((int)optionString->getChar(0));
2255  /* process the different options */
2256  switch (option)
2257  {
2258  case 'A': /* args are an array */
2259  {
2260  /* so they say, make sure we have an */
2261  /* array and we were only passed 3 */
2262  /* args */
2263  if (argumentsCount < 3) /* not enough arguments? */
2264  {
2265  missingArgument(OREF_positional, ARG_THREE); /* this is an error*/
2266  }
2267  if (argumentsCount > 3) /* too many arguments? */
2268  {
2270  }
2271 
2272  /* now get the array */
2273  RexxArray *arglistUser = (RexxArray *)arguments[2];
2274  /* force to array form */
2275  arglist = REQUEST_ARRAY(arglistUser);
2276  p_arglist = arglist;
2277  /* not an array? */
2278  if (arglist == TheNilObject || arglist->getDimension() != 1)
2279  {
2280  /* raise an error */
2281  reportException(Error_Incorrect_method_noarray, OREF_positional, arguments[2]);
2282  }
2283 
2284  /* grab the argument information */
2285  argumentPtr = arglist->data();
2286  argcount = arglist->size();
2287 
2288  if (arglist == arglistUser)
2289  {
2290  // To not impact the array passed by the user, must create a copy because will need to append the named arguments
2291  arglist = (RexxArray *)arglist->copy();
2292  p_arglist = arglist;
2293  }
2294  break;
2295  }
2296 
2297  case 'I': /* args are "strung out" */
2298  /* point to the array data for the second value */
2299  argumentPtr = arguments + 2;
2300  argcount = argumentsCount - 2;
2301  break;
2302 
2303  default:
2304  /* invalid option */
2306  break;
2307  }
2308  }
2309 
2310  if (option == 'I')
2311  {
2312  // Nothing to do, the named arguments are supported directly
2313  named_argcount = named_argumentsCount;
2314  }
2315  else
2316  {
2317  // The directory of named arguments is passed with the named argument 'NAMEDARGUMENT' (optional)
2318 
2319  // use strict named arg namedArguments=.NIL
2320  NamedArguments expectedNamedArguments(1); // At most, one named argument
2321  expectedNamedArguments[0] = NamedArgument("NAMEDARGUMENTS", TheNilObject); // At least 1 character, default value = .NIL
2322  expectedNamedArguments.match(arguments + argumentsCount, named_argumentsCount, /*strict*/ true, /*extraAllowed*/ false);
2323 
2324  argdirectory = (RexxDirectory *)expectedNamedArguments[0].value;
2325  if (argdirectory != TheNilObject)
2326  {
2327  argdirectory = argdirectory->requestDirectory();
2328  p_argdirectory = argdirectory;
2329  if (argdirectory == TheNilObject)
2330  {
2331  reportException(Error_Execution_user_defined, "RUN namedArguments must be a directory or NIL");
2332  }
2333  named_argcount = argdirectory->items();
2334  }
2335 
2336  if (named_argcount != 0)
2337  {
2338  if (arglist == OREF_NULL)
2339  {
2340  // Here argcount == 0
2341  arglist = new_array(2 * named_argcount);
2342  p_arglist = arglist;
2343  }
2344  argdirectory->appendAllIndexesItemsTo(arglist, /*from*/ argcount+1); // argcount+1 because array.put use 1-based index
2345  argumentPtr = arglist->data();
2346  }
2347  }
2348 
2349  ProtectedObject result;
2350  /* now just run the method.... */
2351  methobj->run(ActivityManager::currentActivity, this, OREF_NONE, argumentPtr, argcount, named_argcount, result);
2352  return (RexxObject *)result;
2353 }
2354 
2356  RexxDirectory *methods) /* new table of methods */
2357 /****************************************************************************/
2358 /* Function: Add a table of methods to an object's behaviour */
2359 /****************************************************************************/
2360 {
2361  /* make a copy of the behaviour */
2362  OrefSet(this, this->behaviour, (RexxBehaviour *)this->behaviour->copy());
2363  /* loop through the list of methods */
2364  for (HashLink i = methods->first(); methods->available(i); i = methods->next(i))
2365  {
2366  /* Get the methjod Object */
2367  RexxMethod *method = (RexxMethod *)methods->value(i);
2368  if (method != TheNilObject) /* not a removal? */
2369  {
2370  /* set a new scope on this */
2371  method = method->newScope((RexxClass *)this);
2372  }
2373  else
2374  {
2375  method = OREF_NULL; // this is a method removal
2376  }
2377  /* Get the name for this method */
2378  RexxString *name = (RexxString *)methods->index(i);
2379  name = name->upper(); /* make sure the name is upperCase. */
2380  ProtectedObject p(name);
2381  /* add this method to the object's */
2382  /* behaviour */
2383  this->behaviour->define(name, method);
2384  }
2385  return OREF_NULL;
2386 }
2387 
2389  RexxString *msgname, /* new method name */
2390  RexxMethod *methobj, /* associated method object */
2391  RexxString *option)
2392  /****************************************************************************/
2393  /* Function: Add a method to an object's behaviour */
2394  /****************************************************************************/
2395 {
2396  RexxMethod *methcopy; /* copy of the original method */
2397  /* default scope "FLOAT" */
2398  RexxClass *targetClass = (RexxClass*)TheNilObject;
2399 
2400  msgname = msgname->upper(); /* add this as an uppercase name */
2401  ProtectedObject p(msgname);
2402  if (methobj != TheNilObject) /* not a removal? */
2403  {
2404  /* got an option? */
2405  if (option)
2406  {
2407  if (!Utilities::strCaselessCompare("OBJECT", option->getStringData()))
2408  {
2409  targetClass = this->behaviour->getOwningClass();
2410  }
2411  else
2412  {
2413  RexxString *info = new_string("\"FLOAT\", \"OBJECT\"");
2414  ProtectedObject p(info);
2415  reportException(Error_Incorrect_call_list, OREF_SETMETHOD, OREF_positional, IntegerThree, info, option);
2416  }
2417  }
2418  /* set a new scope on this */
2419  methcopy = methobj->newScope(targetClass);
2420  }
2421  else
2422  {
2423  /* no real method added */
2424  methcopy = (RexxMethod *)TheNilObject;
2425  }
2426  ProtectedObject p1(methcopy);
2427  /* is this the first added method? */
2429  {
2430 
2431  /* copy primitive behaviour object and define the method, a copy is made to */
2432  /* ensure that we don't update the behaviour of any other object, since they*/
2433  /* may have been sharing the mvd. */
2434  OrefSet(this, this->behaviour, (RexxBehaviour *)this->behaviour->copy());
2435  }
2436  /* now add this to the behaviour */
2437  this->behaviour->addMethod(msgname, methcopy);
2438  /* adding an UNINIT method to obj? */
2439  if (methobj != TheNilObject && msgname->strCompare(CHAR_UNINIT))
2440  {
2441  this->hasUninit(); /* yes, mark it as such */
2442  }
2443  return OREF_NULL;
2444 }
2445 
2447 /******************************************************************************/
2448 /* Function: Return the object's primitive type number */
2449 /******************************************************************************/
2450 {
2451  return this->behaviour->getClassType();
2452 }
2453 
2455 /******************************************************************************/
2456 /* Function: Remove an UNINIT method from an object */
2457 /******************************************************************************/
2458 {
2460 }
2461 
2462 /**
2463  * Search through all of the scopes looking for a variable
2464  * of the given name. This will return the first match.
2465  *
2466  * @param name The target name.
2467  *
2468  * @return The value associated with the variable or OREF_NULL if
2469  * no matching variable is found.
2470  */
2472 {
2473  RexxVariableDictionary *dictionary = objectVariables;
2474  while (dictionary != OREF_NULL)
2475  {
2476  // see if this dictionary has the variable
2477  RexxObject *val = dictionary->realValue(name);
2478  // return this if it exists
2479  if (val != OREF_NULL)
2480  {
2481  return val;
2482  }
2483  // step to the next dictionary in the chain
2484  dictionary = dictionary->getNextDictionary();
2485  }
2486  return OREF_NULL; // no variable found
2487 }
2488 
2489 
2491  RexxString * name, /* variable name (name object) */
2492  RexxObject * scope) /* target variable scope */
2493  /******************************************************************************/
2494  /* Function: retrieve the value of an object variable. This name */
2495  /* must be a name object, and only simple variables are supported.*/
2496  /* If the variable has not been assigned a value, then OREF_NULL */
2497  /* is returned. */
2498  /******************************************************************************/
2499 {
2500  if (OREF_NULL == scope) /* were we passed a scope for lookup */
2501  {
2502  scope = this; /* no, we use our own. */
2503  }
2504  /* get the ovd for our scope level */
2505  RexxVariableDictionary *ovd = this->getObjectVariables(scope);
2506  return ovd->realValue(name); /* get the real variable value */
2507 }
2508 
2510  RexxString *name, /* variable name (name object) */
2511  RexxObject *value, /* new variable value */
2512  RexxObject *scope) /* target variable scope */
2513  /******************************************************************************/
2514  /* Function: assign a new value to a object variable. This name */
2515  /* must be a name object, and only simple variables are supported.*/
2516  /******************************************************************************/
2517 {
2518  if (OREF_NULL == scope) /* were we passed a scope for lookup */
2519  {
2520  scope = this; /* no, we use our own. */
2521  }
2522  /* get the ovd for our scope level */
2523  RexxVariableDictionary *ovd = this->getObjectVariables(scope);
2524  ovd->set(name, value); /* do the variable assignment */
2525 }
2526 
2528  RexxVariableDictionary *dictionary)/* new variable set */
2529 /******************************************************************************/
2530 /* Function: Add a new variable dictionary to an object with a given scope */
2531 /******************************************************************************/
2532 {
2533  /* chain any existing dictionaries off of the new one */
2534  dictionary->setNextDictionary(objectVariables);
2535  /* make this the new head of the chain */
2536  OrefSet(this, objectVariables, dictionary);
2537 }
2538 
2540  RexxObject *startScope) /* target scope */
2541  /******************************************************************************/
2542  /* Function: Find the scope of a method's super class */
2543  /******************************************************************************/
2544 {
2545  return this->behaviour->superScope(startScope);
2546 }
2547 
2549  RexxString *msgName, /* target message name */
2550  RexxObject *startScope) /* starting lookup scope */
2551  /******************************************************************************/
2552  /* Function: Find a method using the given starting scope information */
2553  /******************************************************************************/
2554 {
2555  return this->behaviour->superMethod(msgName, startScope);
2556 }
2557 
2559  RexxObject *scope) /* required dictionary scope */
2560 /******************************************************************************/
2561 /* Function: Retrieve an object dictionary for a given scope */
2562 /******************************************************************************/
2563 {
2564  RexxVariableDictionary *dictionary = objectVariables; /* get the head of the chain */
2565  while (dictionary != OREF_NULL)
2566  { /* search for a scope match */
2567  /* if we've found a match, return it */
2568  if (dictionary->isScope(scope))
2569  {
2570  return dictionary;
2571  }
2572  dictionary = dictionary->getNextDictionary();
2573  }
2574 
2575  /* just create a new vdict */
2576  dictionary = new_objectVariableDictionary(scope);
2577  /* chain any existing dictionaries off of the new one */
2578  dictionary->setNextDictionary(objectVariables);
2579  /* make this the new head of the chain */
2580  OrefSet(this, objectVariables, dictionary);
2581  this->setHasReferences(); /* we now have references */
2582  return dictionary; /* return the correct ovd */
2583 }
2584 
2585 /**
2586  * Obtain a guard lock on the target object at the given scope.
2587  *
2588  * @param activity The activity we're running on.
2589  * @param scope The scope that needs to be locked.
2590  */
2592 {
2594  vdict->reserve(activity);
2595 }
2596 
2597 
2598 /**
2599  * Release a guard lock on the target object at the given scope.
2600  *
2601  * @param activity The activity we're running on.
2602  * @param scope The scope that needs to be released.
2603  */
2605 {
2607  vdict->release(activity);
2608 }
2609 
2610 
2611 
2612 const char *RexxObject::idString(void)
2613 /******************************************************************************/
2614 /* Function: Return a pointer to the object's string value */
2615 /******************************************************************************/
2616 {
2617  RexxString *classId = this->id(); /* get the id string */
2618  if (classId == OREF_NULL) /* internal class? */
2619  {
2620  return "unknown Class"; /* return an unknown identifier */
2621  }
2622  else
2623  {
2624  return classId->getStringData(); /* return the actual class ID */
2625  }
2626 }
2627 
2629 /******************************************************************************/
2630 /* Function: Get the class string name */
2631 /******************************************************************************/
2632 {
2633  /* get the class */
2634  RexxClass *createClass = this->behaviourObject()->getOwningClass();
2635  if (createClass == OREF_NULL) /* no class object? */
2636  {
2637  return OREF_NULL; /* return nothing */
2638  }
2639  else
2640  {
2641  return createClass->getId(); /* return the class id string */
2642  }
2643 }
2644 
2646 /******************************************************************************/
2647 /* Function: Exported Object INIT method */
2648 /******************************************************************************/
2649 {
2650  return OREF_NULL; /* this is basically a no-op */
2651 }
2652 
2653 
2654 /**
2655  * Return a unique identity hash value for this object. This
2656  * hash will be unique among the set of currently active Rexx
2657  * objects.
2658  *
2659  * @return The identity hash value as an integer object.
2660  */
2662 {
2663  return new_integer(this->identityHash());
2664 }
2665 
2666 
2667 /**
2668  * Check if this is the Nil object.
2669  *
2670  * @return true if Nil, false otherwise.
2671  */
2673 {
2674  return booleanObject(this == TheNilObject);
2675 }
2676 
2677 
2679 /******************************************************************************/
2680 /* Function: Exported Object INIT method */
2681 /******************************************************************************/
2682 {
2683  if (TheTrueObject == this->hasMethod(OREF_UNINIT))
2684  {
2685  this->sendMessage(OREF_UNINIT);
2686  }
2687 
2688 }
2689 
2691 /******************************************************************************/
2692 /* Function: Check to see if an object has an UNINIT method. */
2693 /******************************************************************************/
2694 {
2695  return TheTrueObject == this->hasMethod(OREF_UNINIT);
2696 }
2697 
2698 RexxObject *RexxObject::newRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
2699 /******************************************************************************/
2700 /* Function: Exposed REXX NEW method */
2701 /******************************************************************************/
2702 {
2703  // this method is defined on the object class, but this is actually attached
2704  // to a class object instance. Therefore, any use of the this pointer
2705  // will be touching the wrong data. Use the classThis pointer for calling
2706  // any methods on this object from this method.
2707  RexxClass *classThis = (RexxClass *)this;
2708  classThis->checkAbstract();
2709 
2710  return new (classThis, arguments, argCount, named_argCount) RexxObject;
2711 }
2712 
2713 
2715 /******************************************************************************/
2716 /* Arguments: Clone an object, and set up its header. This method should */
2717 /* be called by other _copy methods instead of using new_object */
2718 /* and memcpy, so that memory can properly initialize the new */
2719 /* object's header to avoid early gc. */
2720 /* */
2721 /* Returned: A new object copied from objr, but set to be live to avoid */
2722 /* being garbage collected on a pending sweep. */
2723 /******************************************************************************/
2724 {
2725  // we need an identically sized object
2726  size_t size = getObjectSize();
2727  RexxObject *cloneObj = new_object(size);
2728  // copy the object header. That's the only piece of this we're not going to keep from
2729  // the old object.
2730  ObjectHeader newHeader = cloneObj->header;
2731  // copy everything but the object header over from the source object.
2732  memcpy((char *)cloneObj, (char *)this, size);
2733  // restore the new header to the cloned object
2734  cloneObj->header = newHeader;
2735  return cloneObj;
2736 }
2737 
2738 #undef operatorMethod
2739 #define operatorMethod(name, message) RexxObject * RexxObject::name(RexxObject *operand) \
2740 {\
2741  ProtectedObject result; /* returned result */\
2742  /* do a real message send */\
2743  this->messageSend(OREF_##message, &operand, 1, 0, result); \
2744  if ((RexxObject *)result == OREF_NULL) /* in an expression and need a result*/ \
2745  { \
2746  RexxObject *self = this; \
2747  bool alternativeResult = operand->messageSend(OREF_##message##_RIGHT, &self, 1, 0, result, false); \
2748  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxObject *)result; \
2749  /* need to raise an exception */ \
2750  reportException(Error_No_result_object_message, OREF_##message); \
2751  } \
2752  return (RexxObject *)result; /* return the final result */ \
2753 }\
2754 
2755 
2756 #undef prefixOperatorMethod
2757 #define prefixOperatorMethod(name, message) RexxObject * RexxObject::name(RexxObject *operand) \
2758 {\
2759  ProtectedObject result; /* returned result */\
2760  /* do a real message send */\
2761  this->messageSend(OREF_##message, &operand, operand == OREF_NULL ? 0 : 1, 0, result); \
2762  if ((RexxObject *)result == OREF_NULL) /* in an expression and need a result*/ \
2763  { \
2764  if (operand != OREF_NULL) \
2765  { \
2766  RexxObject *self = this; \
2767  bool alternativeResult = operand->messageSend(OREF_##message##_RIGHT, &self, 1, 0, result, false); \
2768  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxObject *)result; \
2769  } \
2770  /* need to raise an exception */ \
2771  reportException(Error_No_result_object_message, OREF_##message); \
2772  } \
2773  return (RexxObject *)result; /* return the final result */ \
2774 }\
2775 
2776 
2777 prefixOperatorMethod(operator_plus, PLUS)
2778 prefixOperatorMethod(operator_minus, SUBTRACT)
2779 operatorMethod(operator_multiply, MULTIPLY)
2780 operatorMethod(operator_divide, DIVIDE)
2781 operatorMethod(operator_integerDivide, INTDIV)
2782 operatorMethod(operator_remainder, REMAINDER)
2783 operatorMethod(operator_power, POWER)
2784 operatorMethod(operator_abuttal, NULLSTRING)
2785 operatorMethod(operator_concat, CONCATENATE)
2786 operatorMethod(operator_concatBlank, BLANK)
2787 operatorMethod(operator_equal, EQUAL)
2788 operatorMethod(operator_notEqual, BACKSLASH_EQUAL)
2789 operatorMethod(operator_isGreaterThan, GREATERTHAN)
2790 operatorMethod(operator_isBackslashGreaterThan, BACKSLASH_GREATERTHAN)
2791 operatorMethod(operator_isLessThan, LESSTHAN)
2792 operatorMethod(operator_isBackslashLessThan, BACKSLASH_LESSTHAN)
2793 operatorMethod(operator_isGreaterOrEqual, GREATERTHAN_EQUAL)
2794 operatorMethod(operator_isLessOrEqual, LESSTHAN_EQUAL)
2795 operatorMethod(operator_strictEqual, STRICT_EQUAL)
2796 operatorMethod(operator_strictNotEqual, STRICT_BACKSLASH_EQUAL)
2797 operatorMethod(operator_strictGreaterThan, STRICT_GREATERTHAN)
2798 operatorMethod(operator_strictBackslashGreaterThan, STRICT_BACKSLASH_GREATERTHAN)
2799 operatorMethod(operator_strictLessThan, STRICT_LESSTHAN)
2800 operatorMethod(operator_strictBackslashLessThan, STRICT_BACKSLASH_LESSTHAN)
2801 operatorMethod(operator_strictGreaterOrEqual, STRICT_GREATERTHAN_EQUAL)
2802 operatorMethod(operator_strictLessOrEqual, STRICT_LESSTHAN_EQUAL)
2803 operatorMethod(operator_lessThanGreaterThan, LESSTHAN_GREATERTHAN)
2804 operatorMethod(operator_greaterThanLessThan, GREATERTHAN_LESSTHAN)
2805 operatorMethod(operator_and, AND)
2806 operatorMethod(operator_or, OR)
2807 operatorMethod(operator_xor, XOR)
2808 prefixOperatorMethod(operator_not, BACKSLASH)
2809 
2810 void *RexxObject::operator new(size_t size, RexxClass *classObject)
2811 /******************************************************************************/
2812 /* Function: Create a new translator object */
2813 /******************************************************************************/
2814 {
2815  /* get storage for new object */
2816  RexxObject *newObject = (RexxObject *)new_object(size);
2817  // the virtual function table is still object, but the behaviour is whatever
2818  // the class object defines.
2819  newObject->setBehaviour(classObject->getInstanceBehaviour());
2820  // the hash value and nulled object table was handled by new_object();
2821 
2822  if (classObject->hasUninitDefined() || classObject->parentHasUninitDefined())
2823  { /* or parent has one */
2824  newObject->hasUninit();
2825  }
2826 
2827  return(void *)newObject; /* Initialize the new object */
2828 }
2829 
2830 
2831 void *RexxObject::operator new(size_t size, RexxClass *classObject, RexxObject **args, size_t argCount, size_t named_argCount)
2832 /******************************************************************************/
2833 /* Function: Create a new instance of object */
2834 /******************************************************************************/
2835 {
2836  /* create a new object */
2837  ProtectedObject newObject(new (classObject) RexxObject);
2838  /* now drive the user INIT */
2839  ((RexxObject *)newObject)->sendMessage(OREF_INIT, args, argCount, named_argCount);
2840  return(RexxObject *)newObject; /* and returnthe new object */
2841 }
2842 
2843 
2844 /**
2845  * Concatentation operation supported by the Object class. This
2846  * converts the object into a string form, then asks the
2847  * converted object to perform the concatenaton.
2848  *
2849  * @param otherObj The object to concatenate.
2850  *
2851  * @return The concatenation result.
2852  */
2854 {
2855  RexxString *alias = (RexxString *)REQUEST_STRING(this);
2856  ProtectedObject p(alias);
2857  return alias->concatRexx(otherObj);
2858 }
2859 
2860 
2861 /**
2862  * Blank concatentation operation supported by the Object class.
2863  * This converts the object into a string form, then asks the
2864  * converted object to perform the concatenaton.
2865  *
2866  * @param otherObj The object to concatenate.
2867  *
2868  * @return The concatenation result.
2869  */
2871 {
2872  RexxString *alias = (RexxString *)REQUEST_STRING(this);
2873  ProtectedObject p(alias);
2874  return alias->concatBlank(otherObj);
2875 }
2876 
2877 
2879 /******************************************************************************/
2880 /* Function: Exported access to an object virtual function */
2881 /******************************************************************************/
2882 {
2883  return this->stringValue(); /* forward to the virtual function */
2884 }
2885 
2887 /******************************************************************************/
2888 /* Function: Exported access to an object virtual function */
2889 /******************************************************************************/
2890 {
2891  return this->makeString(); /* forward to the virtual function */
2892 }
2893 
2895 /******************************************************************************/
2896 /* Function: Exported access to an object virtual function */
2897 /******************************************************************************/
2898 {
2899  return this->makeArray(); /* forward to the virtual function */
2900 }
2901 
2903 /******************************************************************************/
2904 /* Function: Exported access to an object virtual function */
2905 /******************************************************************************/
2906 {
2907  return this->defaultName(); /* forward to the virtual function */
2908 }
2909 
2911 /******************************************************************************/
2912 /* Function: Exported access to an object virtual function */
2913 /******************************************************************************/
2914 {
2915  return this->copy(); /* forward to the virtual function */
2916 }
2917 
2919  RexxString *message, /* unknown message */
2920  RexxArray *arguments, /* message arguments */
2921  RexxObject **named_arglist,
2922  size_t named_argcount)
2923 /******************************************************************************/
2924 /* Function: Exported access to an object virtual function */
2925 /******************************************************************************/
2926 {
2927  // use strict named arg namedArguments=.NIL
2928  NamedArguments expectedNamedArguments(1); // At most, one named argument
2929  expectedNamedArguments[0] = NamedArgument("NAMEDARGUMENTS", TheNilObject); // At least 1 characters, default value = .NIL
2930  expectedNamedArguments.match(named_arglist, named_argcount, /*strict*/ true, /*extraAllowed*/ false);
2931  RexxDirectory *namedArguments = (RexxDirectory*)expectedNamedArguments[0].value;
2932 
2933  /* forward to the virtual function */
2934  return this->unknown(message, arguments, namedArguments);
2935 }
2936 
2938  RexxString *message) /* method name */
2939 /******************************************************************************/
2940 /* Function: Exported access to an object virtual function */
2941 /******************************************************************************/
2942 {
2943  message = stringArgument(message, OREF_positional, ARG_ONE)->upper();
2944  return this->hasMethod(message); /* forward to the virtual function */
2945 }
2946 
2948 /******************************************************************************/
2949 /* Function: give a formatted print of object information. */
2950 /******************************************************************************/
2951 {
2952  printf("Object at %p, of type %d\n", this, (int)this->getObjectTypeNumber());
2953 }
2954 
2955 /**
2956  * Create the NIL object instance.
2957  */
2959 {
2960  // use the initial identify hash and save this.
2961  hashValue = identityHash();
2962 }
2963 
2964 /**
2965  * Override of the default hash value method.
2966  */
2968 {
2969  return hashValue;
2970 }
2971 
2972 
2973 /**
2974  * Attempt to get a CSELF value from an object instance
2975  * for a native context.
2976  *
2977  * @return An unwrapperd CSELF value, if one can be found.
2978  */
2980 {
2981  // try for the variable value
2982  RexxObject *C_self = getObjectVariable(OREF_CSELF);
2983  // if we found one, validate for unwrappering
2984  if (C_self != OREF_NULL)
2985  {
2986  // if this is a pointer, then unwrapper the value
2987  if (C_self->isInstanceOf(ThePointerClass))
2988  {
2989  return ((RexxPointer *)C_self)->pointer();
2990  }
2991  // this could be a containing buffer instance as well
2992  else if (C_self->isInstanceOf(TheBufferClass))
2993  {
2994  // return a pointer to the buffer beginning
2995  return(void *)((RexxBuffer *)C_self)->getData();
2996  }
2997  }
2998  return NULL; /* no object available */
2999 }
3000 
3001 
3002 /**
3003  * Attempt to get a CSELF value from an object instance,
3004  * starting from a given scope value and checking each of the
3005  * super scopes for the class
3006  *
3007  * @param scope The starting scope for the search.
3008  *
3009  * @return An unwrappered CSELF value, if one can be found.
3010  */
3012 {
3013  while (scope != TheNilObject)
3014  {
3015  // try for the variable value
3016  RexxObject *C_self = getObjectVariable(OREF_CSELF, scope);
3017  // if we found one, validate for unwrappering
3018  if (C_self != OREF_NULL)
3019  {
3020  // if this is a pointer, then unwrapper the value
3021  if (C_self->isInstanceOf(ThePointerClass))
3022  {
3023  return ((RexxPointer *)C_self)->pointer();
3024  }
3025  // this could be a containing buffer instance as well
3026  else if (C_self->isInstanceOf(TheBufferClass))
3027  {
3028  // return a pointer to the buffer beginning
3029  return(void *)((RexxBuffer *)C_self)->getData();
3030  }
3031  }
3032  // step to the next scope
3033  scope = this->superScope(scope);
3034  }
3035  return NULL; /* no object available */
3036 }
3037 
3038 
3039 /**
3040  * new operator for creating a RexxNilObject
3041  */
3042 void *RexxNilObject::operator new(size_t size)
3043 {
3044  // At this point, this will be an instance of object. After we've removed
3045  // some of the methods during setup but before the image save, we'll update the
3046  // behaviour type information so that it will restore with the correct virtual
3047  // function table pointer.
3048  RexxObject *newObj = new_object(size, T_Object);
3049  // we need to switch the virtual method table pointer new.
3051  return newObj;
3052 }
3053 
3054 
3056 {
3057  NULL,
3058  (PCPPM)&RexxObject::operator_plus, // "+"
3059  (PCPPM)&RexxObject::operator_minus, // "-"
3060  (PCPPM)&RexxObject::operator_multiply, // "*"
3061  (PCPPM)&RexxObject::operator_divide, // "/"
3062  (PCPPM)&RexxObject::operator_integerDivide, // "%"
3063  (PCPPM)&RexxObject::operator_remainder, // "//"
3064  (PCPPM)&RexxObject::operator_power, // "**"
3065  (PCPPM)&RexxObject::operator_abuttal, // ""
3066  (PCPPM)&RexxObject::operator_concat, // "||"
3067  (PCPPM)&RexxObject::operator_concatBlank, // " "
3068  (PCPPM)&RexxObject::operator_equal, // "="
3069  (PCPPM)&RexxObject::operator_notEqual, // "\="
3070  (PCPPM)&RexxObject::operator_isGreaterThan, // ">"
3071  (PCPPM)&RexxObject::operator_isBackslashGreaterThan, // ">"
3072  (PCPPM)&RexxObject::operator_isLessThan, // "<"
3073  (PCPPM)&RexxObject::operator_isBackslashLessThan, // "<"
3074  (PCPPM)&RexxObject::operator_isGreaterOrEqual, // ">="
3075  (PCPPM)&RexxObject::operator_isLessOrEqual, // "<="
3076  (PCPPM)&RexxObject::operator_strictEqual, // "=="
3077  (PCPPM)&RexxObject::operator_strictNotEqual, // "\=="
3078  (PCPPM)&RexxObject::operator_strictGreaterThan, // ">>"
3079  (PCPPM)&RexxObject::operator_strictBackslashGreaterThan, // ">>"
3080  (PCPPM)&RexxObject::operator_strictLessThan, // "<<"
3081  (PCPPM)&RexxObject::operator_strictBackslashLessThan, // "<<"
3082  (PCPPM)&RexxObject::operator_strictGreaterOrEqual, // ">>="
3083  (PCPPM)&RexxObject::operator_strictLessOrEqual, // "<<="
3084  (PCPPM)&RexxObject::operator_lessThanGreaterThan, // "<>"
3085  (PCPPM)&RexxObject::operator_greaterThanLessThan, // "><"
3086  (PCPPM)&RexxObject::operator_and, // "&"
3087  (PCPPM)&RexxObject::operator_or, // "|"
3088  (PCPPM)&RexxObject::operator_xor, // "&&"
3089  (PCPPM)&RexxObject::operator_not, // "\"
3090 };
3091 
void reportException(wholenumber_t error)
void reportNomethod(RexxErrorCodes error, RexxString *message, RexxObject *receiver)
RexxMethod * lastMethod()
void missingArgument(RexxString *kind, size_t argumentPosition)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_NilObject
@ T_Object
RexxInteger * new_integer(wholenumber_t v)
#define operatorMethod(name, message)
#define prefixOperatorMethod(name, message)
RexxObject *(RexxObject::* PCPPM)()
size_t HashCode
Definition: ObjectClass.hpp:79
RexxObject * booleanObject(bool v)
Definition: RexxCore.h:496
#define OREF_NULL
Definition: RexxCore.h:61
#define IntegerThree
Definition: RexxCore.h:202
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:315
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:457
#define TheNullText
Definition: RexxCore.h:211
wholenumber_t RexxErrorCodes
Definition: RexxCore.h:65
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:295
#define IntegerOne
Definition: RexxCore.h:200
const int ARG_THREE
Definition: RexxCore.h:85
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
const int ARG_TWO
Definition: RexxCore.h:84
#define TheBufferClass
Definition: RexxCore.h:176
#define IntegerTwo
Definition: RexxCore.h:201
#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
const int ARG_ONE
Definition: RexxCore.h:83
RexxArray * arrayArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:395
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define Error_Execution_super
#define Error_Logical_value_method
#define Error_Incorrect_method_option
#define Error_Execution_user_defined
#define Error_Incorrect_method_positive
#define Error_No_result_object_message
#define Error_Incorrect_method_nostring
#define Error_Incorrect_method_nonnegative
#define Error_Incorrect_call_list
#define Error_Incorrect_method_message
#define Error_Incorrect_method_whole
#define Error_Incorrect_method_maxarg
#define Error_No_method_private
#define Error_Invalid_whole_number_compareto
#define Error_No_method_name
#define Error_Incorrect_method_noarray
#define Error_Invalid_argument_string
#define Error_No_method_package
size_t HashLink
RexxMemory memoryObject
Definition: RexxMemory.cpp:86
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:503
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
RexxVariableDictionary * new_objectVariableDictionary(RexxObject *s)
RexxString * new_string(const char *s, stringsize_t l)
RexxString * new_proxy(const char *name)
static RexxActivity *volatile currentActivity
void match(RexxObject **namedArglist, size_t namedArgCount, bool strict, bool extraAllowed, size_t minimumRequired=0)
virtual RexxObject * getReceiver()
virtual PackageClass * getPackage()
SecurityManager * getEffectiveSecurityManager()
void checkStackSpace()
RexxActivationBase * getTopStackFrame()
bool raiseCondition(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *)
size_t getDimension()
Definition: ArrayClass.cpp:693
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxObject * copy()
Definition: ArrayClass.cpp:122
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxObject ** data()
Definition: ArrayClass.hpp:204
RexxMethod * methodLookup(RexxString *)
RexxTable * getMethodDictionary()
RexxObject * define(RexxString *, RexxMethod *)
RexxObject * copy()
void removeMethod(RexxString *)
RexxClass * getOwningClass()
RexxSupplier * getMethods(RexxObject *scope)
RexxTable * getInstanceMethodDictionary()
RexxMethod * superMethod(RexxString *, RexxObject *)
RexxObject * superScope(RexxObject *)
void addMethod(RexxString *, RexxMethod *)
size_t getClassType()
void checkAbstract()
bool isCompatibleWith(RexxClass *other)
RexxString * getId()
Definition: ClassClass.cpp:284
size_t appendAllIndexesItemsTo(RexxArray *array, size_t from)
static RexxDirectory * fromIndexItemArray(RexxObject **arglist, size_t count)
bool available(HashLink pos)
RexxObject * value(HashLink pos)
HashLink next(HashLink pos)
RexxObject * index(HashLink pos)
virtual RexxInteger * integerValue(size_t)
virtual bool isInstanceOf(RexxClass *)
void setBehaviour(RexxBehaviour *b)
virtual RexxString * primitiveMakeString()
virtual bool unsignedNumberValue(stringsize_t &result, size_t precision)
virtual RexxText * makeText()
virtual bool isEqual(RexxObject *)
void setVirtualFunctions(void *t)
virtual RexxObject * makeProxy(RexxEnvelope *)
virtual bool doubleValue(double &result)
virtual RexxString * stringValue()
ObjectHeader header
virtual RexxSupplier * instanceMethods(RexxClass *)
RexxObject * clone()
virtual RexxString * makeString()
virtual bool numberValue(wholenumber_t &result, size_t precision)
virtual RexxArray * makeArray()
virtual RexxText * primitiveMakeText()
virtual RexxObject * dynamicTarget(RexxObject **arguments, size_t count, size_t named_count)
virtual RexxMethod * instanceMethod(RexxString *)
virtual void copyIntoTail(RexxCompoundTail *buffer)
virtual HashCode getHashValue()
virtual RexxObject * copy()
size_t getObjectTypeNumber()
RexxBehaviour * behaviour
virtual RexxText * textValue()
virtual RexxNumberString * numberString()
virtual bool truthValue(int)
HashCode identityHash()
virtual bool logicalValue(logical_t &)
void removeUninitObject(RexxObject *obj)
Definition: RexxMemory.cpp:605
static void * virtualFunctionTable[]
Definition: RexxMemory.hpp:301
void addUninitObject(RexxObject *obj)
Definition: RexxMemory.cpp:616
RexxObject * start(RexxObject *)
bool isProtected()
bool isPackageScope()
bool isPrivate()
void run(RexxActivity *, RexxObject *, RexxString *, RexxObject **, size_t, size_t, ProtectedObject &)
bool isSpecial()
bool isSamePackage(PackageClass *p)
static RexxMethod * newMethodObject(RexxString *, RexxObject *, RexxObject *, RexxSource *a, bool isBlock=false)
RexxClass * getScope()
RexxMethod * newScope(RexxClass *)
static RexxObject * nilObject
HashCode hashValue
virtual HashCode getHashValue()
RexxObject * isInstanceOfRexx(RexxClass *)
RexxInteger * requiredInteger(RexxString *kind, size_t, size_t)
bool hasUninitMethod()
RexxString * stringRexx()
RexxString * defaultNameRexx()
stringsize_t requiredPositive(RexxString *kind, size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
RexxMessage * start(RexxObject **, size_t, size_t)
virtual wholenumber_t compareTo(RexxObject *)
RexxString * objectName()
RexxNumberString * numberString()
RexxMessage * startCommon(RexxObject *message, RexxObject **arguments, size_t argCount, size_t named_argCount)
RexxInteger * integerValue(size_t)
RexxVariableDictionary * getObjectVariables(RexxObject *)
RexxObject * requestRexx(RexxString *)
static void decodeMessageName(RexxObject *target, RexxObject *message, RexxString *&messageName, RexxObject *&startScope)
RexxObject * dynamicTargetRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
RexxObject * sendWith(RexxObject *, RexxArray *, RexxObject **, size_t)
RexxString * concatRexx(RexxObject *)
RexxObject * unknownRexx(RexxString *, RexxArray *, RexxObject **, size_t)
bool requestUnsignedNumber(stringsize_t &, size_t)
static RexxClass * classInstance
stringsize_t requiredNonNegative(RexxString *kind, size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
RexxObject * hasMethodRexx(RexxString *)
RexxMethod * instanceMethodRexx(RexxString *)
void live(size_t)
Definition: ObjectClass.cpp:79
RexxText * textValue()
RexxObject * unsetMethod(RexxString *)
static void createInstance()
Definition: ObjectClass.cpp:73
RexxMethod * checkPrivate(RexxMethod *, RexxErrorCodes &)
RexxObject * superScope(RexxObject *)
virtual RexxInteger * hasMethod(RexxString *msg)
RexxObject * strictEqual(RexxObject *)
void guardOn(RexxActivity *activity, RexxObject *scope)
RexxMessage * startWith(RexxObject *, RexxArray *, RexxObject **, size_t)
virtual bool doubleValue(double &result)
RexxInteger * requestInteger(size_t)
RexxObject * setMethod(RexxString *, RexxMethod *, RexxString *a=OREF_NULL)
RexxMethod * methodLookup(RexxString *name)
virtual RexxObject * defMethod(RexxString *, RexxMethod *, RexxString *a=OREF_NULL)
RexxString * makeString()
RexxObject * send(RexxObject **, size_t, size_t)
RexxArray * makeArray()
RexxObject * objectNameEquals(RexxObject *)
void guardOff(RexxActivity *activity, RexxObject *scope)
void processUnknown(RexxErrorCodes, RexxString *, RexxObject **, size_t, size_t, ProtectedObject &)
RexxText * requestText()
RexxString * oref()
virtual RexxObject * unknown(RexxString *msg, RexxArray *args, RexxDirectory *named_args)
RexxArray * requestArray()
RexxString * requiredString()
void * getCSelf()
void processProtectedMethod(RexxString *, RexxMethod *, RexxObject **, size_t, size_t, ProtectedObject &)
RexxObject * copy()
RexxString * stringValue()
RexxSupplier * instanceMethods(RexxClass *)
void flatten(RexxEnvelope *)
Definition: ObjectClass.cpp:95
RexxObject * equal(RexxObject *)
RexxObject * isNilRexx()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxMethod * checkPackage(RexxMethod *, RexxErrorCodes &)
void liveGeneral(int reason)
Definition: ObjectClass.cpp:87
RexxObject * notEqual(RexxObject *other)
bool requestNumber(wholenumber_t &, size_t)
HashCode hash()
RexxInteger * identityHashRexx()
RexxDirectory * requestDirectory()
RexxMethod * instanceMethod(RexxString *)
bool messageSend(RexxString *, RexxObject **, size_t, size_t, ProtectedObject &, bool processUnknown=true, bool dynamicTarget=true)
void addObjectVariables(RexxVariableDictionary *)
RexxString * requestString()
void copyIntoTail(RexxCompoundTail *buffer)
RexxObject * makeStringRexx()
virtual bool numberValue(wholenumber_t &result, size_t precision)
RexxObject * newRexx(RexxObject **arguments, size_t argCount, size_t named_argCount)
RexxBehaviour * behaviourObject()
RexxObject * defMethods(RexxDirectory *)
RexxText * makeText()
bool isEqual(RexxObject *)
virtual RexxString * defaultName()
bool truthValue(int)
static PCPPM operatorMethods[]
RexxString * concatBlank(RexxObject *)
virtual bool unsignedNumberValue(stringsize_t &result, size_t precision)
RexxSupplier * instanceMethodsRexx(RexxClass *)
RexxString * requestStringNoNOSTRING()
RexxString * id()
RexxClass * classObject()
const char * idString()
RexxObject * copyRexx()
void setObjectVariable(RexxString *, RexxObject *, RexxObject *)
bool isInstanceOf(RexxClass *)
RexxObject * run(RexxObject **, size_t, size_t)
RexxObject * makeArrayRexx()
RexxMethod * superMethod(RexxString *, RexxObject *)
RexxObject * strictNotEqual(RexxObject *other)
RexxObject * getObjectVariable(RexxString *)
virtual bool logicalValue(logical_t &)
RexxObject * hashCode()
void copyObjectVariables(RexxObject *newObject)
RexxObject * init()
wholenumber_t requiredNumber(RexxString *kind, size_t position, size_t precision=Numerics::ARGUMENT_DIGITS)
bool numberValue(wholenumber_t &result, size_t precision)
bool truthValue(int)
RexxString * concatRexx(RexxObject *)
RexxInteger * strictEqual(RexxObject *)
bool doubleValue(double &result)
const char * getStringData()
RexxInteger * integerValue(size_t precision)
RexxString * concatBlank(RexxObject *)
RexxNumberString * numberString()
virtual bool logicalValue(logical_t &)
RexxString * concatToCstring(const char *)
bool strCompare(const char *s)
RexxString * upper()
char getChar(size_t p)
bool unsignedNumberValue(uwholenumber_t &result, size_t precision)
void copyIntoTail(RexxCompoundTail *buffer)
RexxObject * stringGet(RexxString *key)
Definition: TableClass.hpp:67
void setNextDictionary(RexxVariableDictionary *next)
RexxObject * realValue(RexxString *name)
bool isScope(RexxObject *otherScope)
void set(RexxString *, RexxObject *)
RexxVariableDictionary * getNextDictionary()
bool checkProtectedMethod(RexxObject *target, RexxString *messageName, size_t count, size_t named_count, RexxObject **arguments, ProtectedObject &result)
static int strCaselessCompare(const char *opt1, const char *opt2)
Definition: Utilities.cpp:102
size_t logical_t
Definition: rexx.h:231
ssize_t wholenumber_t
Definition: rexx.h:230
size_t stringsize_t
Definition: rexx.h:228