StemClass.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel StemClass.cpp */
40 /* */
41 /* Primitive Stem variable class */
42 /* */
43 /******************************************************************************/
44 #include "RexxCore.h"
45 #include "StringClass.hpp"
46 #include "ArrayClass.hpp"
47 #include "RexxActivation.hpp"
48 #include "RexxNativeActivation.hpp"
50 #include "RexxVariable.hpp"
51 #include "SupplierClass.hpp"
52 #include "DirectoryClass.hpp"
53 #include "StemClass.hpp"
54 #include "RexxCompoundTail.hpp"
55 
56 // singleton class instance
58 
59 
60 /**
61  * Create initial class object at bootstrap time.
62  */
64 {
65  CLASS_CREATE(Stem, "Stem", RexxClass);
66 }
67 
68 
70  RexxString *name) /* the variable name */
71 /******************************************************************************/
72 /* Function: Initialize a STEM class item */
73 /******************************************************************************/
74 {
75  if (name == OREF_NULL) /* no explicit default value? */
76  {
77  name = OREF_NULLSTRING; /* set a null string */
78  }
79  else
80  {
81  /* must get a string here */
82  name = stringArgument(name, OREF_positional, ARG_ONE);
83  }
84  OrefSet(this, this->stemName, name); /* fill in the name */
85  OrefSet(this, this->value, name); /* fill in the default value */
86  tails.init(this); /* initialize the tail table */
87  /* create a tails table */
88  this->dropped = true; /* no explicit value */
89 }
90 
92 /******************************************************************************/
93 /* Function: Copy a stem collection object */
94 /******************************************************************************/
95 {
96  /* make a copy of ourself (this also */
97  /* copies the object variables */
98  RexxStem *newObj = (RexxStem *)this->RexxObject::copy();
99  ProtectedObject p(newObj);
100  newObj->copyFrom(tails); /* have the tail table copy itself */
101  return newObj; /* return the new object */
102 }
103 
104 /**
105  * Copy the tails from another stem object into this stem.
106  *
107  * @param _tails The source tail collection.
108  */
110 {
111  tails.init(this);
112  tails.copyFrom(_tails);
113 }
114 
115 
116 void RexxStem::live(size_t liveMark)
117 /******************************************************************************/
118 /* Function: Normal garbage collection live marking */
119 /******************************************************************************/
120 {
121  memory_mark(this->value);
122  memory_mark(this->stemName);
123  memory_mark(this->objectVariables);
125 }
126 
127 void RexxStem::liveGeneral(int reason)
128 /******************************************************************************/
129 /* Function: Generalized object marking */
130 /******************************************************************************/
131 {
132  memory_mark_general(this->value);
134  memory_mark_general(this->objectVariables);
136 }
137 
139 /******************************************************************************/
140 /* Function: Flatten an object */
141 /******************************************************************************/
142 {
144 
145  flatten_reference(newThis->value, envelope);
146  flatten_reference(newThis->stemName, envelope);
147  flatten_reference(newThis->objectVariables, envelope);
149 
151 }
152 
154  RexxObject *_value) /* new variable value */
155 /******************************************************************************/
156 /* Function: Set a new stem default value */
157 /******************************************************************************/
158 {
159  OrefSet(this, this->value, _value); /* set the new value */
160  this->dropped = false; /* now have an explict value */
161 }
162 
164 /******************************************************************************/
165 /* Function: Drop a stem value -- this reinitializes it */
166 /******************************************************************************/
167 {
168  /* reset to the default value */
169  OrefSet(this, this->value, this->stemName);
170  this->dropped = true; /* no explict value any more */
171 }
172 
173 
174 /**
175  * Retrieve the assigned stem value.
176  *
177  * @return The default stem value.
178  */
180 {
181  return value;
182 }
183 
184 
186  RexxString *msgname, /* unknown message name */
187  RexxArray *arguments, /* message arguments */
188  RexxDirectory *named_arguments)
189 /******************************************************************************/
190 /* Function: Forward an unknown message to the value of the stem. */
191 /******************************************************************************/
192 {
193  /* validate the name */
194  msgname = stringArgument(msgname, OREF_positional, ARG_ONE);
195  ProtectedObject p(msgname);
196  requiredArgument(arguments, OREF_positional, ARG_TWO); /* need an argument array */
197  /* get this as an array */
198  arguments = (RexxArray *)REQUEST_ARRAY(arguments);
199  ProtectedObject p2(arguments);
200  if (arguments == TheNilObject) /* didn't convert? */
201  {
202  /* raise an error */
204  }
205 
206  ProtectedObject p_named_arguments;
207  if (named_arguments != OREF_NULL && named_arguments != TheNilObject)
208  {
209  /* get a directory version */
210  named_arguments = named_arguments->requestDirectory();
211  p_named_arguments = named_arguments; // GC protect
212 
213  /* not a directory item ? */
214  if (named_arguments == TheNilObject)
215  {
216  reportException(Error_Execution_user_defined , "UNKNOWN namedArguments must be a directory or NIL");
217  }
218  }
219 
220  size_t argumentsCount = arguments ? arguments->size() : 0;
221  size_t namedArgumentsCount = (named_arguments != OREF_NULL && named_arguments != TheNilObject) ? named_arguments->items() : 0;
222 
223  RexxArray *args = arguments;
224  ProtectedObject p_args;
225  if (namedArgumentsCount != 0)
226  {
227  // Optimization: create a copy of the positional arguments only if some named arguments must be added
228  args = (RexxArray *)arguments->copy();
229  p_args = args;
230  named_arguments->appendAllIndexesItemsTo(args, /*from*/ argumentsCount+1); // from is 1-based index
231  }
232 
233  return this->value->sendMessage(msgname, args->data(), argumentsCount, namedArgumentsCount);
234 }
235 
237  RexxObject **tailElements, /* tail elements */
238  size_t argCount, /* number of tail elements */
239  size_t named_argCount)
240 /******************************************************************************/
241 /* Function: Resolve the "stem.[a,b,c]" to the equivalent stem.a.b.c form, */
242 /* with all of the indices taken as constants */
243 /******************************************************************************/
244 {
245  if (argCount == 0) /* default value request? */
246  {
247  return this->value; /* just return the default value */
248  }
249  /* create a searchable tail from the array elements */
250  RexxCompoundTail resolved_tail(tailElements, argCount);
251  /* now look up this element */
252  return evaluateCompoundVariableValue(OREF_NULL, stemName, &resolved_tail);
253 }
254 
255 
256 /**
257  * Test if this compound variable has a given index.
258  *
259  * @param tails The set of tail expressions.
260  * @param argCount The argument count
261  *
262  * @return True if the fully resolved tail exists in the stem, false
263  * otherwise.
264  */
265 RexxObject *RexxStem::hasIndex(RexxObject **tailElements, size_t argCount, size_t named_argCount)
266 {
267  if (argCount == 0)
268  {
269  return TheTrueObject; // we always have something here
270  }
271  // compose the tail element
272  RexxCompoundTail resolved_tail(tailElements, argCount);
273  // see if we have a compound
274  RexxCompoundElement *compound = findCompoundVariable(&resolved_tail);
275  // if there's a variable there, and it has a real value, then
276  // this is true.
277  if (compound != OREF_NULL && compound->getVariableValue() != OREF_NULL)
278  {
279  return TheTrueObject;
280  }
281  // nope, we got nuttin'
282  return TheFalseObject;
283 }
284 
285 
286 /**
287  * Remove an item from the collection. This is essentially
288  * equivalent to a drop operation on the stem variable.
289  *
290  * @param tails The set of tail indexes.
291  * @param argCount The number of indexes.
292  *
293  * @return The removed object. If nothing was removed, this returns
294  * .nil.
295  */
296 RexxObject *RexxStem::remove(RexxObject **tailElements, size_t argCount, size_t named_argCount)
297 {
298  // if asked to remove the default value, reset this back to the name
299  if (argCount == 0)
300  {
301  // replace with the name and return the old value.
302  RexxObject *oldValue = this->value;
303  OrefSet(this, value, getName());
304  return oldValue;
305  }
306 
307  // compose the tail element
308  RexxCompoundTail resolved_tail(tailElements, argCount);
309  RexxCompoundElement *compound = findCompoundVariable(&resolved_tail);
310  // if there's a variable there, and it has a real value, then
311  // we have something to remove
312  if (compound != OREF_NULL && compound->getVariableValue() != OREF_NULL)
313  {
314  // get the value, which is the return value, and drop the variable.
315  RexxObject *oldValue = compound->getVariableValue();
316  compound->drop();
317  return oldValue;
318  }
319  return TheNilObject; // nothing dropped.
320 }
321 
322 
323 /**
324  * Search for any index that matches the target object.
325  *
326  * @param target The object of interest.
327  *
328  * @return .true if the object is in the collection, .false otherwise.
329  */
331 {
332  RexxCompoundElement *variable = findByValue(target);
333  return variable == OREF_NULL ? TheFalseObject : TheTrueObject;
334 }
335 
336 
337 
338 /**
339  * Remove an item from the collection.
340  *
341  * @param target The object of interest.
342  *
343  * @return .true if the object is in the collection, .false otherwise.
344  */
346 {
347  RexxCompoundElement *compound = findByValue(target);
348  // if there's a variable there, and it has a real value, then
349  // we have something to remove
350  if (compound != OREF_NULL && compound->getVariableValue() != OREF_NULL)
351  {
352  // get the value, which is the return value, and drop the variable.
353  RexxObject *oldValue = compound->getVariableValue();
354  compound->drop();
355  return oldValue;
356  }
357  return TheNilObject; // nothing dropped.
358 }
359 
360 
361 /**
362  * Return the index for a target item.
363  *
364  * @param target The target object.
365  *
366  * @return The tail name for the match, or .nil if it was not found.
367  */
369 {
370  RexxCompoundElement *variable = findByValue(target);
371  if (variable != OREF_NULL)
372  {
373  return variable->getName();
374  }
375  return TheNilObject;
376 }
377 
378 /**
379  * Return the number of items set in the collection.
380  *
381  * @return The count of items in the collection, not counting the
382  * default value.
383  */
385 {
386  return new_integer(items());
387 }
388 
389 
391  RexxObject **tailElements, /* tail elements */
392  size_t argCount, /* number of tail elements */
393  size_t named_argCount)
394 /******************************************************************************/
395 /* Function: Resolve the "stem.[a,b,c]=" to the equivalent stem.a.b.c= form, */
396 /* with all of the indices taken as constants */
397 /******************************************************************************/
398 {
399  RexxVariable * variable; /* resolved variable element */
400  RexxObject * new_value; /* newly assigned value */
401 
402  if (argCount == 0) /* have nothing at all? */
403  {
404  /* this is an error */
406  }
407  new_value = tailElements[0]; /* get the new value */
408  if (new_value == OREF_NULL) /* nothing given? */
409  {
410  /* this is an error also */
412  }
413 
414  if (argCount == 1)
415  { /* just setting the default value? */
416  if (isOfClass(Stem, new_value)) // stem value as default? don't allow this as it leads to recursion loops
417  {
419  }
420  /* set the new default value */
421  OrefSet(this, this->value, new_value);
422  this->tails.clear(); /* clear out the dictionary */
423  this->dropped = false; /* now have an explicit value */
424  return this->value; /* just return the default value */
425  }
426  /* create a searchable tail from the array elements */
427  RexxCompoundTail resolved_tail(tailElements + 1, argCount - 1);
428  variable = getCompoundVariable(&resolved_tail);
429  variable->set(new_value); /* set the new value */
430  return OREF_NULL; /* never returns anything */
431 }
432 
433 
435 /******************************************************************************/
436 /* Function: Extract as an array the tails of a stem. */
437 /******************************************************************************/
438 {
439  return this->tailArray(); /* extract the array item */
440 }
441 
443 /******************************************************************************/
444 /* Function: Forward string request on to the default value */
445 /******************************************************************************/
446 {
447  /* return the objects string value */
448  return (RexxString *)this->value->stringValue();
449 }
450 
452 /******************************************************************************/
453 /* Function: Convert a REXX object to a long value */
454 /******************************************************************************/
455 {
456  return value->numberValue(result, digits);
457 }
458 
460 /******************************************************************************/
461 /* Function: Convert a REXX object to a long value */
462 /******************************************************************************/
463 {
464  return value->numberValue(result);
465 }
466 
468 /******************************************************************************/
469 /* Function: Convert a REXX object to a long value */
470 /******************************************************************************/
471 {
472  return value->unsignedNumberValue(result, digits);
473 }
474 
476 /******************************************************************************/
477 /* Function: Convert a REXX object to a long value */
478 /******************************************************************************/
479 {
480  return value->unsignedNumberValue(result);
481 }
482 
483 bool RexxStem::doubleValue(double &result)
484 /******************************************************************************/
485 /* Function: Convert a primitive internal object to a double value */
486 /******************************************************************************/
487 {
488  return value->doubleValue(result);
489 }
490 
492 /******************************************************************************/
493 /* Function: Forward numberstring request on to the default value */
494 /******************************************************************************/
495 {
496  /* just forward to default value */
497  return this->value->numberString();
498 }
499 
501 /******************************************************************************/
502 /* Function: Forward integer request on to the default value */
503 /******************************************************************************/
504 {
505  /* just forward to default value */
506  return this->value->integerValue(precision);
507 }
508 
510  RexxString *makeclass) /* required class name */
511 /******************************************************************************/
512 /* Function: Forward all REQUEST messages on to the default value */
513 /******************************************************************************/
514 {
515  ProtectedObject result;
516  /* Verify we have a string parm */
517  makeclass = stringArgument(makeclass, OREF_positional, ARG_ONE)->upper();
518  ProtectedObject p(makeclass);
519  /* array request? */
520  if (makeclass->strCompare(CHAR_ARRAY))
521  {
522  if (isOfClass(Stem, this)) /* a real stem object? */
523  {
524  /* process here directly */
525  return(RexxObject *)this->makeArray();
526  }
527  else /* go to the real make array method */
528  {
529  this->sendMessage(OREF_MAKEARRAY, result);
530  return(RexxObject *)result;
531  }
532  }
533  /* just forward on */
534  this->value->sendMessage(OREF_REQUEST, makeclass, result);
535  return(RexxObject *)result;
536 }
537 
539  RexxObject **init_args, /* subclass init arguments */
540  size_t argCount, /* the number of arguments */
541  size_t named_argCount)
542 /******************************************************************************/
543 /* Function: Create an instance of a stem */
544 /******************************************************************************/
545 {
546  // this method is defined on the object class, but this is actually attached
547  // to a class object instance. Therefore, any use of the this pointer
548  // will be touching the wrong data. Use the classThis pointer for calling
549  // any methods on this object from this method.
550  RexxClass *classThis = (RexxClass *)this;
551  classThis->checkAbstract(); // ooRexx5
552 
553  RexxObject * newObj; /* newly created queue object */
554  RexxObject * name; /* name of the stem item */
555 
556  /* break up the arguments */
557  RexxClass::processNewArgs(init_args, argCount, &init_args, &argCount, 1, (RexxObject **)&name, NULL);
558  newObj = new RexxStem ((RexxString *)name); /* get a new stem */
559  ProtectedObject p(newObj);
560  newObj->setBehaviour(classThis->getInstanceBehaviour());
561  /* does object have an UNINT method */
562  if (classThis->hasUninitDefined())
563  {
564  newObj->hasUninit(); /* Make sure everyone is notified. */
565  }
566  /* Initialize the new instance */
567  newObj->sendMessage(OREF_INIT, init_args, argCount, named_argCount);
568  return newObj; /* return the new object */
569 }
570 
571 void *RexxStem::operator new(size_t size)
572 /******************************************************************************/
573 /* Function: Create a new stem object */
574 /******************************************************************************/
575 {
576  /* Get new object */
577  return new_object(size, T_Stem);
578 }
579 
580 
582  RexxCompoundTail *name) /* tail name */
583 /******************************************************************************/
584 /* Function: Get an item from the variable dictionary, adding a new empty */
585 /* variable entry if it wasn't found. */
586 /******************************************************************************/
587 {
588  /* get/create an entry in the table */
589  return tails.findEntry(name, true)->realVariable();
590 }
591 
592 
594  RexxCompoundTail *name) /* tail name */
595 /******************************************************************************/
596 /* Function: Get an item from the variable dictionary, adding a new empty */
597 /* variable entry if it wasn't found. */
598 /******************************************************************************/
599 {
600  // first see if the compound variable already exists. If it does, then
601  // it might represent an explicitly dropped varaible. We leave this along
602  // in that case.
603  RexxCompoundElement *variable = tails.findEntry(name, false);
604  // ok, it's already there, return the real variable value.
605  if (variable != OREF_NULL)
606  {
607  return variable->realVariable();
608  }
609 
610  // we're creating a real variable. If the stem has an explicit value,
611  // then we need to set that now.
612  variable = tails.findEntry(name, true)->realVariable();
613  /* if this variable does not have a value, we need to check the */
614  /* stem for a default value and assign it. */
615  if (variable->getVariableValue() == OREF_NULL) {
616  if (!dropped) { /* stem have a default value? */
617  variable->set(value); /* get the stem's value explicitly */
618  }
619  }
620  return variable;
621 }
622 
623 
625  RexxCompoundTail *name) /* tail name */
626 /******************************************************************************/
627 /* Function: Get an item from the variable dictionary, without creating a */
628 /* new variable if it doesn't exist. */
629 /******************************************************************************/
630 {
631  /* get, but don't create an entry in the table */
632  RexxCompoundElement *variable = tails.findEntry(name);
633  if (variable != OREF_NULL)
634  {
635  return variable->realVariable();/* return the real target */
636  }
637  return OREF_NULL;
638 }
639 
640 
642  RexxCompoundTail *name) /* tail name */
643 /******************************************************************************/
644 /* Function: Mark a variable as dropped. */
645 /******************************************************************************/
646 {
647  RexxVariable *variable = getCompoundVariable(name);/* look up this tail element */
648  variable->drop(); /* drop the variable entry */
649 }
650 
651 
653  RexxNativeActivation *activation) /* Hosting Native Act. */
654 /******************************************************************************/
655 /* Function: Return the "next" variable of a variable traversal */
656 /******************************************************************************/
657 {
658  RexxObject *_value; /* variable value */
659 
660  /* get the last saved stem */
661  RexxCompoundElement *variable = activation->compoundElement();
662 
663  while (variable != OREF_NULL)
664  { /* while we have more to process */
665  /* get the value */
666  _value = variable->getVariableValue();
667  if (_value != OREF_NULL)
668  { /* not a dropped variable? */
669  activation->setCompoundElement(tails.next(variable));
670  return variable; /* give this one back */
671  }
672  variable = tails.next(variable); /* step to the next table item */
673  }
674  /* clear out the saved element */
675  activation->setCompoundElement(OREF_NULL);
676  activation->setNextStem(OREF_NULL);
677 
678  return OREF_NULL; /* return end of table indicator */
679 }
680 
682  RexxCompoundTail *name, /* tail name */
683  RexxObject *_value) /* value to assign to variable name */
684 /******************************************************************************/
685 /* Function: Set a new variable value */
686 /******************************************************************************/
687 {
688  /* see if we have an entry for this */
689  RexxCompoundElement *variable = getCompoundVariable(name);
690  variable->set(_value); /* and perform the set */
691 }
692 
694 /******************************************************************************/
695 /* Function: Return all indices as an array */
696 /******************************************************************************/
697 {
698  RexxCompoundElement *variable; /* table variable entry */
699  RexxArray *array; /* returned array */
700  size_t count; /* count of variables */
701 
702  array = new_array(items()); /* get the array */
703  count = 1; /* start at the beginning again */
704 
705  variable = tails.first(); /* get the first variable */
706  while (variable != OREF_NULL)
707  { /* while more values to process */
708  /* this a real variable? */
709  if (variable->getVariableValue() != OREF_NULL)
710  {
711  /* add to our array */
712  array->put(variable->getName(), count++);
713  }
714  variable = tails.next(variable); /* go get the next one */
715  }
716  return array; /* return the array item */
717 }
718 
720  RexxActivation *context, /* the evaluation context (can be NULL) */
721  RexxString *stemVariableName, // the stem variable name this was evaluated from (used for noValue)
722  RexxCompoundTail *resolved_tail) /* the search tail */
723 /******************************************************************************/
724 /* Function: Retrieve a compound variable, returning the default value if the*/
725 /* variable does not exist. This includes NOVALUE handling. */
726 /******************************************************************************/
727 {
728  RexxCompoundElement *variable; /* the real variable */
729  RexxObject *_value; /* final variable value */
730  RexxString *tail_name; /* formatted tail name */
731 
732  /* get the compound variable */
733  variable = findCompoundVariable(resolved_tail);
734  if (variable == OREF_NULL)
735  { /* variable does not exist? */
736  if (!dropped) /* stem have a default value? */
737  {
738  _value = this->value; /* get the stems value */
739  }
740  else
741  { /* need to use name */
742  /* create a string version of the name */
743  tail_name = resolved_tail->createCompoundName(stemVariableName);
744  // the tail_name is the fully resolved variable, used for NOVALUE reporting.
745  // the defaultValue is the value that's returned as the expression result,
746  // which is derived from the stem object.
747  RexxObject *defaultValue = resolved_tail->createCompoundName(stemName);
748  /* take care of any novalue situations */
749  _value = handleNovalue(context, tail_name, defaultValue, variable);
750  }
751  }
752  else
753  {
754  /* get the variable value */
755  _value = variable->getVariableValue();
756  if (_value == OREF_NULL)
757  { /* explicitly dropped variable? */
758  /* create a string version of the name */
759  tail_name = resolved_tail->createCompoundName(stemName);
760  // the tail_name is the fully resolved variable, used for NOVALUE reporting.
761  // the defaultValue is the value that's returned as the expression result,
762  // which is derived from the stem object.
763  RexxObject *defaultValue = resolved_tail->createCompoundName(stemName);
764  /* take care of any novalue situations */
765  _value = handleNovalue(context, tail_name, defaultValue, variable);
766  }
767  }
768  return _value; /* and finally return the value */
769 }
770 
772  RexxCompoundTail *resolved_tail) /* the search tail */
773 /******************************************************************************/
774 /* Function: Retrieve a compound variable, returning the default value if the*/
775 /* variable does not exist. This does NOT raise NOVALUE conditions*/
776 /******************************************************************************/
777 {
778  RexxCompoundElement *variable; /* the real variable */
779  RexxObject *_value; /* final variable value */
780 
781  /* get the compound variable */
782  variable = findCompoundVariable(resolved_tail);
783  if (variable == OREF_NULL)
784  { /* variable does not exist? */
785  if (!dropped) /* stem have a default value? */
786  {
787  return this->value; /* get the stems value */
788  }
789  else
790  { /* need to use name */
791  /* create a string version of the name */
792  return(RexxObject *)resolved_tail->createCompoundName(stemName);
793  }
794  }
795  else
796  {
797  /* get the variable value */
798  _value = variable->getVariableValue();
799  if (_value == OREF_NULL)
800  { /* explicitly dropped variable? */
801  /* create a string version of the name */
802  _value = (RexxObject *)resolved_tail->createCompoundName(stemName);
803  }
804  }
805  return _value; /* and finally return the value */
806 }
807 
808 
809 /**
810  * Evaluate the real value of a compound variable. The real
811  * value is either its explicitly assigned value or a stem
812  * assigned value. This returns OREF_NULL if neither is
813  * available. This does not raise NOVALUE conditions.
814  *
815  * @param resolved_tail
816  * The target tail value.
817  *
818  * @return The variable value, or OREF_NULL if the variable does not
819  * have an explicit value.
820  */
822 {
823  // first resolve the compound variable.
824  RexxVariable *variable = findCompoundVariable(resolved_tail);
825  // if the variable is not found, return the stem's default value if it has one.
826  // If there is no default value, return OREF_NULL.
827  if (variable == OREF_NULL) /* variable does not exist? */
828  {
829  if (!dropped)
830  {
831  return value;
832  }
833  return OREF_NULL;
834  }
835  else
836  {
837  // just return the variable value (which may be OREF_NULL if explicitly dropped)
838  return variable->getVariableValue();
839  }
840 }
841 
842 
843 
845  RexxCompoundTail *resolved_tail) /* the search tail */
846 /******************************************************************************/
847 /* Function: Retrieve a compound variable, returning the default value if the*/
848 /* variable does not exist. This does not handle NOVALUEs. */
849 /******************************************************************************/
850 {
851  RexxCompoundElement *variable; /* the real variable */
852 
853  /* get the compound variable */
854  variable = findCompoundVariable(resolved_tail);
855  if (variable == OREF_NULL)
856  { /* variable does not exist? */
857  if (!dropped) /* stem have a default value? */
858  {
859  return this->value; /* get the stems value */
860  }
861  else
862  { /* need to use name */
863  return OREF_NULL; /* nothing to return */
864  }
865  }
866  /* get the variable value */
867  return variable->getVariableValue();
868 }
869 
870 
872  RexxActivation *context, /* the execution context for the request */
873  RexxString *name, // the fully resolved compound name
874  RexxObject *defaultValue, // the default value to use
875  RexxCompoundElement *variable) // the resolved variable element
876 /******************************************************************************/
877 /* Function: Process a nonvalue condition for a stem variable retrieval. */
878 /* If a context is provided, the novalue is handled in its */
879 /* context. */
880 /******************************************************************************/
881 {
882  /* are we doing this directly for method execution? */
883  if (context != OREF_NULL)
884  {
885  /* the context may need to do additional work */
886  return context->handleNovalueEvent(name, defaultValue, variable);
887  }
888  else
889  {
890  return name; /* just use the name */
891  }
892 }
893 
894 
896  RexxCompoundElement *old_variable) /* the parent compound variable */
897 /******************************************************************************/
898 /* Function: Retrieve a compound variable, returning the default value if the*/
899 /* variable does not exist. This includes NOVALUE handling. */
900 /******************************************************************************/
901 {
902  /* create the equivalent in this stem */
903  RexxCompoundElement *new_variable = tails.findEntry(old_variable->getName(), true);
904  new_variable->expose(old_variable); /* make the association between the two */
905 }
906 
907 
908 /**
909  * Return all items in the stem.
910  *
911  * @return An array of all items in the stem.
912  */
914 {
915  // now we know how big the return result will be, get an array and
916  // populate it, using the same traversal logic as before
917  RexxArray *array = new_array(items());
918  // we index the array with a origin-one index, so we start with one this time
919  size_t count = 1;
920 
921  RexxCompoundElement *variable = tails.first();
922  while (variable != OREF_NULL)
923  {
924  // only add the real values
925  if (variable->getVariableValue() != OREF_NULL)
926  {
927  array->put(variable->getVariableValue(), count++);
928  }
929  variable = tails.next(variable);
930  }
931  return array; // tada, finished
932 }
933 
934 
935 /**
936  * Locate a stem item by value.
937  *
938  * @return The compound item for the located element.
939  */
941 {
942  RexxCompoundElement *variable = tails.first();
943  while (variable != OREF_NULL)
944  {
945  RexxObject *_value = variable->getVariableValue();
946  // if this has a value, and we have a match, then return it
947  if (_value != OREF_NULL && target->equalValue(_value))
948  {
949  return variable;
950  }
951  variable = tails.next(variable);
952  }
953  return OREF_NULL; // not here, oh dear
954 }
955 
956 
957 /**
958  * Get the count of non-dropped items in the stem.
959  *
960  * @return The number of non-dropped items.
961  */
963 {
964  size_t count = 0;
965 
966  RexxCompoundElement *variable = tails.first();
967  while (variable != OREF_NULL)
968  {
969  // we only want to include the non-dropped compounds, so we only count
970  // elements with real values.
971  if (variable->getVariableValue() != OREF_NULL)
972  {
973  count++;
974  }
975  // and keep iterating
976  variable = tails.next(variable);
977  }
978  return count;
979 }
980 
981 
982 /**
983  * Empty the stem. This also clears dropped and exposed tails,
984  *
985  * @return Nothing.
986  */
988 {
989  tails.clear(); // just clear the tails.
990  return OREF_NULL;
991 }
992 
993 
994 /**
995  * Test if the stem is empty.
996  *
997  * @return True if the stem is empty, false otherwise.
998  */
1000 {
1001  return (items() == 0) ? TheTrueObject : TheFalseObject;
1002 }
1003 
1004 
1005 
1006 /**
1007  * Create an array of all indexes of the stem.
1008  *
1009  * @return An array of all tail names used in the stem.
1010  */
1012 {
1013  return this->tailArray(); /* extract the array item */
1014 }
1015 
1016 
1017 /**
1018  * Create a supplier for the stem, returning the tail names as
1019  * the indexes and the values as the items.
1020  *
1021  * @return A supplier instance.
1022  */
1024 {
1025  // essentially the same logic as allItems(), but both the item and the
1026  // tail value are accumulated.
1027  size_t count = 0;
1028  RexxCompoundElement *variable = tails.first();
1029  while (variable != OREF_NULL)
1030  {
1031  // again, get the variable count
1032  if (variable->getVariableValue() != OREF_NULL)
1033  {
1034  count++; /* count this variable */
1035  }
1036  variable = tails.next(variable);
1037  }
1038 
1039  // to create the supplier, we need 2 arrays
1040  RexxArray *tailValues = new_array(count);
1041  RexxArray *values = new_array(count);
1042  count = 1; // we fill in using 1-based indexes
1043 
1044  variable = tails.first();
1045  while (variable != OREF_NULL)
1046  {
1047  // now grab both the tail and value and put them in the respective arrays
1048  if (variable->getVariableValue() != OREF_NULL)
1049  {
1050  tailValues->put(variable->getName(), count);
1051  values->put(variable->getVariableValue(), count++);
1052  }
1053  variable = tails.next(variable);
1054  }
1055  // two arrays become one supplier
1056  return new_supplier(values, tailValues);
1057 }
1058 
1059 
1060 /**
1061  * Create a directory from the stem. Each tail with an
1062  * assigned value will be an entry within the directory.
1063  *
1064  * @return A directory instance.
1065  */
1067 {
1068  RexxDirectory *result = new_directory();
1069  ProtectedObject p1(result);
1070  RexxCompoundElement *variable = tails.first();
1071  while (variable != OREF_NULL)
1072  {
1073  // again, get the variable count
1074  if (variable->getVariableValue() != OREF_NULL)
1075  {
1076  result->put(variable->getVariableValue(), variable->getName());
1077  }
1078  variable = tails.next(variable);
1079  }
1080 
1081  return result;
1082 }
1083 
1084 
1085 /**
1086  * Set a single stem variable object using a simple string
1087  * value tail as a result of an api call.
1088  *
1089  * @param tail The index of the target value.
1090  * @param value The new value to assign.
1091  */
1092 void RexxStem::setElement(const char *_tail, RexxObject *_value)
1093 {
1094  RexxCompoundTail resolved_tail(_tail);
1095  RexxVariable *variable = getCompoundVariable(&resolved_tail);
1096  variable->set(_value); /* set the new value */
1097 }
1098 
1099 
1100 /**
1101  * Set a single stem variable object using a simple string
1102  * value tail as a result of an api call.
1103  *
1104  * @param tail The index of the target value.
1105  * @param value The new value to assign.
1106  */
1107 void RexxStem::setElement(size_t _tail, RexxObject *_value)
1108 {
1109  RexxCompoundTail resolved_tail(_tail);
1110  RexxVariable *variable = getCompoundVariable(&resolved_tail);
1111  variable->set(_value); /* set the new value */
1112 }
1113 
1114 
1115 /**
1116  * Evaluate an array element for an API class.
1117  *
1118  * @param tail The direct tail value.
1119  *
1120  * @return The object value. If the stem element does not exist or
1121  * has been dropped, this returns OREF_NULL.
1122  */
1124 {
1125 
1126  RexxCompoundTail resolved_tail(_tail);
1127 
1128  return getElement(&resolved_tail);
1129 }
1130 
1131 /**
1132  * Evaluate an array element for an API class.
1133  *
1134  * @param tail The direct tail value.
1135  *
1136  * @return The object value. If the stem element does not exist or
1137  * has been dropped, this returns OREF_NULL.
1138  */
1140 {
1141 
1142  RexxCompoundTail resolved_tail(_tail);
1143 
1144  return getElement(&resolved_tail);
1145 }
1146 
1147 /**
1148  * Resolve a compound variable as a result of an api call.
1149  *
1150  * @param resolved_tail
1151  * The resolved tail value.
1152  *
1153  * @return The variable value. Returns OREF_NULL if not assigned or
1154  * dropped.
1155  */
1157 {
1158  // see if we have a variable...if we do, return its value (a dropped variable
1159  // has a value of OREF_NULL). If not found, return OREF_NULL;
1160  RexxCompoundElement *variable = findCompoundVariable(resolved_tail);
1161  if (variable != OREF_NULL)
1162  {
1163  return variable->getVariableValue();
1164  }
1165  return OREF_NULL;
1166 }
1167 
1168 
1169 /**
1170  * Drop an array element for an API class.
1171  *
1172  * @param tail The direct tail value.
1173  */
1174 void RexxStem::dropElement(size_t _tail)
1175 {
1176 
1177  RexxCompoundTail resolved_tail(_tail);
1178 
1179  dropElement(&resolved_tail);
1180 }
1181 
1182 /**
1183  * Drop an array element for an API class.
1184  *
1185  * @param tail The direct tail value.
1186  */
1187 void RexxStem::dropElement(const char *_tail)
1188 {
1189 
1190  RexxCompoundTail resolved_tail(_tail);
1191 
1192  dropElement(&resolved_tail);
1193 }
1194 
1195 
1196 /**
1197  * Drop an element using a resolved tail value.
1198  *
1199  * @param resolved_tail
1200  * The target tail element.
1201  */
1203 {
1204  RexxCompoundElement *variable = findCompoundVariable(resolved_tail);
1205  if (variable != OREF_NULL)
1206  {
1207  variable->drop();
1208  }
1209 }
1210 
1211 
1212 /**
1213  * Create a full compound name from a constructed compound taile.
1214  *
1215  * @param tailPart The constructed tail element.
1216  *
1217  * @return The fully resolved string name of the element.
1218  */
1220 {
1221  return tailPart->createCompoundName(stemName);
1222 }
1223 
1224 
1225 /******************************************************************************/
1226 /* Function: Below are a series of comparison routines used by the qsort() */
1227 /* library function when sorting stems. */
1228 /******************************************************************************/
1230 {
1231  return arg1->sortCaselessCompare(arg2);
1232 }
1233 
1235 {
1236  return arg1->sortCaselessCompare(arg2, sd->startColumn, sd->columnLength);
1237 }
1238 
1240 {
1241  return arg1->sortCompare(arg2);
1242 }
1243 
1245 {
1246  return arg1->sortCompare(arg2, sd->startColumn, sd->columnLength);
1247 }
1248 
1250 {
1251  return -arg1->sortCompare(arg2);
1252 }
1253 
1255 {
1256  return -arg1->sortCompare(arg2, sd->startColumn, sd->columnLength);
1257 }
1258 
1260 {
1261  return -arg1->sortCaselessCompare(arg2);
1262 }
1263 
1265 {
1266  return -arg1->sortCaselessCompare(arg2, sd->startColumn, sd->columnLength);
1267 }
1268 
1269 
1270 /**
1271  * The merge sort routine. This will partition the data in to
1272  * two sections, mergesort each partition, then merge the two
1273  * partitions together.
1274  *
1275  * @param sd The sort information.
1276  * @param comparator The comparator object used for the compares.
1277  * @param strings The input set of strings.
1278  * @param working The working array (same size as the sorted array).
1279  * @param left The left bound of the partition.
1280  * @param right The right bounds of the parition.
1281  */
1282 void RexxStem::mergeSort(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t right)
1283 {
1284  size_t len = right - left + 1;
1285  // use insertion sort for small arrays
1286  if (len <= 7) {
1287  for (size_t i = left + 1; i <= right; i++) {
1288  RexxString *current = strings[i];
1289  RexxString *prev = strings[i - 1];
1290  if (comparator(sd, current, prev) < 0) {
1291  size_t j = i;
1292  do {
1293  strings[j--] = prev;
1294  } while (j > left && comparator(sd, current, prev = strings[j - 1]) < 0);
1295  strings[j] = current;
1296  }
1297  }
1298  return;
1299  }
1300 
1301  size_t mid = (right + left) / 2;
1302  mergeSort(sd, comparator, strings, working, left, mid);
1303  mergeSort(sd, comparator, strings, working, mid + 1, right);
1304  merge(sd, comparator, strings, working, left, mid + 1, right);
1305 }
1306 
1307 
1308 /**
1309  * Perform a merge of two sort partitions.
1310  *
1311  * @param sd The sort descriptor.
1312  * @param comparator The comparator used to compare elements.
1313  * @param strings The input strings.
1314  * @param working A working array used for the merge operations.
1315  * @param left The left bound for the merge.
1316  * @param mid The midpoint for the merge.
1317  * @param right The right bound of merge (inclusive).
1318  */
1319 void RexxStem::merge(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t mid, size_t right)
1320 {
1321  size_t leftEnd = mid - 1;
1322  // merging
1323 
1324  // if arrays are already sorted - no merge
1325  if (comparator(sd, strings[leftEnd], strings[mid]) <= 0) {
1326  return;
1327  }
1328 
1329  size_t leftCursor = left;
1330  size_t rightCursor = mid;
1331  size_t workingPosition = left;
1332 
1333  // use merging with exponential search
1334  do
1335  {
1336  RexxString *fromVal = strings[leftCursor];
1337  RexxString *rightVal = strings[rightCursor];
1338  if (comparator(sd, fromVal, rightVal) <= 0)
1339  {
1340  size_t leftInsertion = find(sd, comparator, strings, rightVal, -1, leftCursor + 1, leftEnd);
1341  size_t toCopy = leftInsertion - leftCursor + 1;
1342  arraycopy(strings, leftCursor, working, workingPosition, toCopy);
1343  workingPosition += toCopy;
1344  working[workingPosition++] = rightVal;
1345  // now we've added this
1346  rightCursor++;
1347  // step over the section we just copied...which might be
1348  // all of the remaining section
1349  leftCursor = leftInsertion + 1;
1350  }
1351  else
1352  {
1353  size_t rightInsertion = find(sd, comparator, strings, fromVal, 0, rightCursor + 1, right);
1354  size_t toCopy = rightInsertion - rightCursor + 1;
1355  arraycopy(strings, rightCursor, working, workingPosition, toCopy);
1356  workingPosition += toCopy;
1357  // insert the right-hand value
1358  working[workingPosition++] = fromVal;
1359  leftCursor++;
1360  rightCursor = rightInsertion + 1;
1361  }
1362  } while (right >= rightCursor && mid > leftCursor);
1363 
1364  // copy rest of array. If we've not used up the left hand side,
1365  // we copy that. Otherwise, there are items on the right side
1366  if (leftCursor < mid)
1367  {
1368  arraycopy(strings, leftCursor, working, workingPosition, mid - leftCursor);
1369  }
1370  else
1371  {
1372  arraycopy(strings, rightCursor, working, workingPosition, right - rightCursor + 1);
1373  }
1374 
1375  arraycopy(working, left, strings, left, right - left + 1);
1376 }
1377 
1378 /**
1379  * copy segments of one array into another.
1380  *
1381  * @param source The source array
1382  * @param start The starting index of the source copy
1383  * @param target The target array
1384  * @param index The target copy index
1385  * @param count The number of items to count.
1386  */
1387 void RexxStem::arraycopy(RexxString **source, size_t start, RexxString **target, size_t index, size_t count)
1388 {
1389  for (size_t i = start; i < start + count; i++)
1390  {
1391  target[index++] = source[i];
1392  }
1393 }
1394 
1395 /**
1396  * Finds the place in the given range of specified sorted array, where the
1397  * element should be inserted for getting sorted array. Uses exponential
1398  * search algorithm.
1399  *
1400  * @param sd The sort descriptor
1401  * @param comparator The comparator used to compare pairs of elements.
1402  * @param strings The input set of strings.
1403  * @param val object to be inserted
1404  * @param bnd possible values 0,-1. "-1" - val is located at index more then
1405  * elements equals to val. "0" - val is located at index less
1406  * then elements equals to val.
1407  * @param left The left bound of the insert operation.
1408  * @param right The right bound for the insert.
1409  *
1410  * @return The insertion point.
1411  */
1412 size_t RexxStem::find(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString *val, int limit, size_t left, size_t right)
1413 {
1414  size_t checkPoint = left;
1415  size_t delta = 1;
1416  while (checkPoint <= right)
1417  {
1418  // if this is too big, then we're moving to the right
1419  if (comparator(sd, val, strings[checkPoint]) > limit)
1420  {
1421  // the left bound is at least this
1422  left = checkPoint + 1;
1423  }
1424  else
1425  {
1426  // we've found a right limit. We can stop scanning here
1427  right = checkPoint - 1;
1428  break;
1429  }
1430  // step the delta amount
1431  checkPoint += delta;
1432  // and double the movement amount
1433  delta = delta * 2;
1434  }
1435  // we should have now limited the bounds for the insertion point
1436  // now start in the middle and shrink the range with each comparison
1437  while (left <= right)
1438  {
1439  // start in the middle of the current range
1440  checkPoint = (left + right) / 2;
1441  if (comparator(sd, val, strings[checkPoint]) > limit)
1442  {
1443  // pull in the left end of the range
1444  left = checkPoint + 1;
1445  }
1446  else
1447  {
1448  // chop the right range
1449  right = checkPoint - 1;
1450  }
1451  }
1452  // the left bound is the insertion point
1453  return left - 1;
1454 }
1455 
1456 
1457 bool RexxStem::sort(RexxString *prefix, int order, int type, size_t _first, size_t last, size_t firstcol, size_t lastcol)
1458 /******************************************************************************/
1459 /* Function: Sort elements of a stem variable as if it was an array. This */
1460 /* routine assumes that element ".0" of the stem contains a size */
1461 /* value for the array portion of the elements, and that tail */
1462 /* indices ".start" to ".end", inclusive all exist in the tail. */
1463 /* Sorting will be performed on the string values of all elements, */
1464 /* and in the final result, all values will be replaced by the */
1465 /* string values. */
1466 /******************************************************************************/
1467 {
1468  SortData sd;
1469 
1470  sd.startColumn = 0;
1471  sd.columnLength = 0;
1472 
1473  RexxCompoundTail stem_size(prefix, (size_t)0);
1474  RexxCompoundElement *size_element = findCompoundVariable(&stem_size);
1475  if (size_element == OREF_NULL) {
1476  return false;
1477  }
1478  RexxObject *size_value = size_element->getVariableValue();
1479  if (size_value == OREF_NULL) {
1480  return false;
1481  }
1482 
1483  stringsize_t count;
1484  /* get the integer value of this. It must be a valid numeric */
1485  /* value. */
1486  if (!size_value->unsignedNumberValue(count, Numerics::DEFAULT_DIGITS))
1487  {
1488  return false;
1489  }
1490  if (count == 0) // if the count is zero, sorting is easy!
1491  {
1492  return true;
1493  }
1494 
1495  /* if this is not specified, sort to the end */
1496  if (last == SIZE_MAX)
1497  {
1498  last = count;
1499  }
1500 
1501  /* verify we're fully within the bounds */
1502  if (_first > count || last > count) {
1503  return false;
1504  }
1505  size_t bounds = last - _first + 1;
1506 
1507  // get an array item and protect it. We need to have space for
1508  // the the variable anchors, the variable values, and a working buffer for the merge. */
1509  RexxArray *array = new_array(bounds * 3);
1510  ProtectedObject p1(array);
1511 
1512  size_t i;
1513  size_t j;
1514  for (j = 1, i = _first; i <= last; i++, j++)
1515  {
1516  RexxCompoundTail nextStem(prefix, (size_t)i);
1517  RexxCompoundElement *next_element = findCompoundVariable(&nextStem);
1518 
1519  if (next_element == OREF_NULL) {
1520  return false;
1521  }
1522 
1523  RexxObject *nextValue = next_element->getVariableValue();
1524  if (nextValue == OREF_NULL) {
1525  return false;
1526  }
1527  /* force this to a string value. */
1528  nextValue = REQUEST_STRING(nextValue);
1529  /* now anchor both in the sorting array */
1530  array->put((RexxObject *)next_element, j);
1531  array->put(nextValue, j + bounds);
1532  }
1533 
1534  // the data to be sorted
1535  RexxString **aData = (RexxString **)array->data(bounds + 1);
1536  // the merge sort work area
1537  RexxString **working = (RexxString **)array->data((bounds * 2) + 1);
1538 
1539  {
1540  // we're releasing kernel access during the process. The sort is being
1541  // done on a locally allocated array, so this will not be accessed by another thread.
1542  // All the rest of the operations are thread safe.
1543  UnsafeBlock block;
1544 
1545  if ((firstcol == 0) && (lastcol == SIZE_MAX)) {
1546  /* no special columns to check */
1547  switch (type) {
1548 
1549  case SORT_CASESENSITIVE:
1551  aData, working, 0, bounds - 1);
1552  break;
1553  case SORT_CASEIGNORE:
1555  aData, working, 0, bounds - 1);
1556  break;
1557  }
1558  }
1559  else
1560  {
1561  /* set columns to sort */
1562  sd.startColumn = firstcol;
1563  sd.columnLength = lastcol - firstcol + 1;
1564 
1565  switch (type)
1566  {
1567  case SORT_CASESENSITIVE:
1569  aData, working, 0, bounds - 1);
1570  break;
1571  case SORT_CASEIGNORE:
1573  aData, working, 0, bounds - 1);
1574  break;
1575  }
1576  }
1577  }
1578 
1579 
1580  /* The values have now been sorted. We now need to set each */
1581  /* each variable back to its new value. */
1582  for (i = 1; i <= bounds; i++) {
1583  RexxCompoundElement *element = (RexxCompoundElement *)array->get(i);
1584  RexxObject *_value = array->get(i + bounds);
1585  element->set(_value);
1586  }
1587  return true;
1588 }
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Stem
RexxDirectory * new_directory()
RexxInteger * new_integer(wholenumber_t v)
#define markGeneralCompoundTable()
#define markCompoundTable()
#define flattenCompoundTable()
#define OREF_NULL
Definition: RexxCore.h:61
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:315
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:457
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:295
#define IntegerOne
Definition: RexxCore.h:200
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
const int ARG_TWO
Definition: RexxCore.h:84
#define IntegerTwo
Definition: RexxCore.h:201
#define isOfClass(t, r)
Definition: RexxCore.h:224
#define TheNilObject
Definition: RexxCore.h:191
#define TheFalseObject
Definition: RexxCore.h:195
const int ARG_ONE
Definition: RexxCore.h:83
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define Error_Execution_user_defined
#define Error_Execution_nostem
#define Error_Incorrect_method_noarg
#define Error_Incorrect_method_noarray
#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
RexxVariable * new_variable(RexxString *n)
int compare_desc_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1254
int compare_asc(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1239
int compare_desc(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1249
int compare_desc_i(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1259
int compare_asc_i_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1234
int compare_asc_i(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1229
int compare_desc_i_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1264
int compare_asc_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1244
#define SORT_ASCENDING
Definition: StemClass.hpp:54
#define SORT_CASEIGNORE
Definition: StemClass.hpp:52
#define SORT_CASESENSITIVE
Definition: StemClass.hpp:51
RexxSupplier * new_supplier(RexxArray *c, RexxArray *f)
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
RexxObject * handleNovalueEvent(RexxString *name, RexxObject *defaultValue, RexxVariable *variable)
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
static void processNewArgs(RexxObject **, size_t, RexxObject ***, size_t *, size_t, RexxObject **, RexxObject **)
void checkAbstract()
RexxBehaviour * getInstanceBehaviour()
Definition: ClassClass.hpp:135
bool hasUninitDefined()
Definition: ClassClass.hpp:125
RexxCompoundElement * realVariable()
void copyFrom(RexxCompoundTable &other)
RexxCompoundElement * findEntry(RexxCompoundTail *tail)
void init(RexxStem *parent)
RexxCompoundElement * first()
RexxCompoundElement * next(RexxCompoundElement *node)
RexxString * createCompoundName(RexxString *)
RexxObject * put(RexxObject *, RexxString *)
size_t appendAllIndexesItemsTo(RexxArray *array, size_t from)
void setBehaviour(RexxBehaviour *b)
void setCompoundElement(RexxCompoundElement *element)
RexxCompoundElement * compoundElement()
void setNextStem(RexxVariable *stemVar)
RexxMessage * start(RexxObject **, size_t, size_t)
RexxNumberString * numberString()
RexxInteger * integerValue(size_t)
virtual bool doubleValue(double &result)
bool equalValue(RexxObject *other)
RexxObject * copy()
RexxString * stringValue()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxDirectory * requestDirectory()
virtual bool numberValue(wholenumber_t &result, size_t precision)
virtual bool unsignedNumberValue(stringsize_t &result, size_t precision)
bool numberValue(wholenumber_t &result, size_t precision)
Definition: StemClass.cpp:451
RexxString * createCompoundName(RexxCompoundTail *tailPart)
Definition: StemClass.cpp:1219
RexxObject * itemsRexx()
Definition: StemClass.cpp:384
RexxCompoundElement * getCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:581
RexxObject * getCompoundVariableValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:771
size_t items()
Definition: StemClass.cpp:962
RexxObject * remove(RexxObject **, size_t, size_t)
Definition: StemClass.cpp:296
void mergeSort(SortData *sd, int(*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t right)
Definition: StemClass.cpp:1282
RexxCompoundElement * exposeCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:593
void dropValue()
Definition: StemClass.cpp:163
RexxCompoundTable tails
Definition: StemClass.hpp:159
RexxObject * newRexx(RexxObject **, size_t, size_t)
Definition: StemClass.cpp:538
RexxObject * getCompoundVariableRealValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:821
static RexxClass * classInstance
Definition: StemClass.hpp:154
void flatten(RexxEnvelope *)
Definition: StemClass.cpp:138
RexxArray * makeArray()
Definition: StemClass.cpp:434
void setElement(const char *tail, RexxObject *value)
Definition: StemClass.cpp:1092
RexxInteger * integerValue(size_t)
Definition: StemClass.cpp:500
void copyFrom(RexxCompoundTable &_tails)
Definition: StemClass.cpp:109
bool sort(RexxString *prefix, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
Definition: StemClass.cpp:1457
RexxNumberString * numberString()
Definition: StemClass.cpp:491
void dropCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:641
RexxObject * copy()
Definition: StemClass.cpp:91
void setCompoundVariable(RexxCompoundTail *name, RexxObject *value)
Definition: StemClass.cpp:681
void live(size_t)
Definition: StemClass.cpp:116
RexxObject * getStemValue()
Definition: StemClass.cpp:179
RexxObject * isEmpty()
Definition: StemClass.cpp:999
static void createInstance()
Definition: StemClass.cpp:63
RexxObject * index(RexxObject *)
Definition: StemClass.cpp:368
RexxArray * allItems()
Definition: StemClass.cpp:913
RexxString * stringValue()
Definition: StemClass.cpp:442
bool unsignedNumberValue(stringsize_t &result, size_t precision)
Definition: StemClass.cpp:467
RexxSupplier * supplier()
Definition: StemClass.cpp:1023
void merge(SortData *sd, int(*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t mid, size_t right)
Definition: StemClass.cpp:1319
RexxCompoundElement * nextVariable(RexxNativeActivation *activation)
Definition: StemClass.cpp:652
RexxStem(RexxString *)
Definition: StemClass.cpp:69
RexxObject * handleNovalue(RexxActivation *context, RexxString *name, RexxObject *defaultValue, RexxCompoundElement *variable)
Definition: StemClass.cpp:871
RexxArray * tailArray()
Definition: StemClass.cpp:693
RexxObject * bracketEqual(RexxObject **, size_t, size_t)
Definition: StemClass.cpp:390
size_t find(SortData *sd, int(*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString *val, int bnd, size_t left, size_t right)
Definition: StemClass.cpp:1412
RexxCompoundElement * findCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:624
RexxObject * empty()
Definition: StemClass.cpp:987
void expose(RexxCompoundElement *variable)
Definition: StemClass.cpp:895
RexxObject * evaluateCompoundVariableValue(RexxActivation *context, RexxString *stemVariableName, RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:719
void dropElement(const char *tail)
Definition: StemClass.cpp:1187
RexxString * stemName
Definition: StemClass.hpp:158
RexxCompoundElement * findByValue(RexxObject *target)
Definition: StemClass.cpp:940
RexxObject * bracket(RexxObject **, size_t, size_t)
Definition: StemClass.cpp:236
bool dropped
Definition: StemClass.hpp:161
RexxObject * getElement(size_t tail)
Definition: StemClass.cpp:1123
RexxDirectory * toDirectory()
Definition: StemClass.cpp:1066
RexxObject * realCompoundVariableValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:844
RexxObject * removeItem(RexxObject *)
Definition: StemClass.cpp:345
RexxObject * request(RexxString *)
Definition: StemClass.cpp:509
void liveGeneral(int reason)
Definition: StemClass.cpp:127
RexxObject * hasIndex(RexxObject **, size_t, size_t)
Definition: StemClass.cpp:265
void setValue(RexxObject *value)
Definition: StemClass.cpp:153
RexxObject * hasItem(RexxObject *)
Definition: StemClass.cpp:330
RexxObject * value
Definition: StemClass.hpp:160
RexxArray * allIndexes()
Definition: StemClass.cpp:1011
RexxString * getName()
Definition: StemClass.hpp:139
void arraycopy(RexxString **source, size_t start, RexxString **target, size_t index, size_t count)
Definition: StemClass.cpp:1387
RexxObject * unknown(RexxString *, RexxArray *, RexxDirectory *)
Definition: StemClass.cpp:185
bool doubleValue(double &result)
Definition: StemClass.cpp:483
int sortCaselessCompare(RexxString *other)
bool strCompare(const char *s)
RexxString * upper()
int sortCompare(RexxString *other)
void set(RexxObject *value)
RexxString * getName()
RexxObject * getVariableValue()
stringsize_t startColumn
Definition: StemClass.hpp:65
stringsize_t columnLength
Definition: StemClass.hpp:66
int type
Definition: cmdparse.cpp:1888
ssize_t wholenumber_t
Definition: rexx.h:230
size_t stringsize_t
Definition: rexx.h:228
#define SIZE_MAX