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  RexxObject * newObj; /* newly created queue object */
547  RexxObject * name; /* name of the stem item */
548 
549  /* break up the arguments */
550  RexxClass::processNewArgs(init_args, argCount, &init_args, &argCount, 1, (RexxObject **)&name, NULL);
551  newObj = new RexxStem ((RexxString *)name); /* get a new stem */
552  ProtectedObject p(newObj);
553  newObj->setBehaviour(((RexxClass *)this)->getInstanceBehaviour());
554  /* does object have an UNINT method */
555  if (((RexxClass *)this)->hasUninitDefined())
556  {
557  newObj->hasUninit(); /* Make sure everyone is notified. */
558  }
559  /* Initialize the new instance */
560  newObj->sendMessage(OREF_INIT, init_args, argCount, named_argCount);
561  return newObj; /* return the new object */
562 }
563 
564 void *RexxStem::operator new(size_t size)
565 /******************************************************************************/
566 /* Function: Create a new stem object */
567 /******************************************************************************/
568 {
569  /* Get new object */
570  return new_object(size, T_Stem);
571 }
572 
573 
575  RexxCompoundTail *name) /* tail name */
576 /******************************************************************************/
577 /* Function: Get an item from the variable dictionary, adding a new empty */
578 /* variable entry if it wasn't found. */
579 /******************************************************************************/
580 {
581  /* get/create an entry in the table */
582  return tails.findEntry(name, true)->realVariable();
583 }
584 
585 
587  RexxCompoundTail *name) /* tail name */
588 /******************************************************************************/
589 /* Function: Get an item from the variable dictionary, adding a new empty */
590 /* variable entry if it wasn't found. */
591 /******************************************************************************/
592 {
593  // first see if the compound variable already exists. If it does, then
594  // it might represent an explicitly dropped varaible. We leave this along
595  // in that case.
596  RexxCompoundElement *variable = tails.findEntry(name, false);
597  // ok, it's already there, return the real variable value.
598  if (variable != OREF_NULL)
599  {
600  return variable->realVariable();
601  }
602 
603  // we're creating a real variable. If the stem has an explicit value,
604  // then we need to set that now.
605  variable = tails.findEntry(name, true)->realVariable();
606  /* if this variable does not have a value, we need to check the */
607  /* stem for a default value and assign it. */
608  if (variable->getVariableValue() == OREF_NULL) {
609  if (!dropped) { /* stem have a default value? */
610  variable->set(value); /* get the stem's value explicitly */
611  }
612  }
613  return variable;
614 }
615 
616 
618  RexxCompoundTail *name) /* tail name */
619 /******************************************************************************/
620 /* Function: Get an item from the variable dictionary, without creating a */
621 /* new variable if it doesn't exist. */
622 /******************************************************************************/
623 {
624  /* get, but don't create an entry in the table */
625  RexxCompoundElement *variable = tails.findEntry(name);
626  if (variable != OREF_NULL)
627  {
628  return variable->realVariable();/* return the real target */
629  }
630  return OREF_NULL;
631 }
632 
633 
635  RexxCompoundTail *name) /* tail name */
636 /******************************************************************************/
637 /* Function: Mark a variable as dropped. */
638 /******************************************************************************/
639 {
640  RexxVariable *variable = getCompoundVariable(name);/* look up this tail element */
641  variable->drop(); /* drop the variable entry */
642 }
643 
644 
646  RexxNativeActivation *activation) /* Hosting Native Act. */
647 /******************************************************************************/
648 /* Function: Return the "next" variable of a variable traversal */
649 /******************************************************************************/
650 {
651  RexxObject *_value; /* variable value */
652 
653  /* get the last saved stem */
654  RexxCompoundElement *variable = activation->compoundElement();
655 
656  while (variable != OREF_NULL)
657  { /* while we have more to process */
658  /* get the value */
659  _value = variable->getVariableValue();
660  if (_value != OREF_NULL)
661  { /* not a dropped variable? */
662  activation->setCompoundElement(tails.next(variable));
663  return variable; /* give this one back */
664  }
665  variable = tails.next(variable); /* step to the next table item */
666  }
667  /* clear out the saved element */
668  activation->setCompoundElement(OREF_NULL);
669  activation->setNextStem(OREF_NULL);
670 
671  return OREF_NULL; /* return end of table indicator */
672 }
673 
675  RexxCompoundTail *name, /* tail name */
676  RexxObject *_value) /* value to assign to variable name */
677 /******************************************************************************/
678 /* Function: Set a new variable value */
679 /******************************************************************************/
680 {
681  /* see if we have an entry for this */
682  RexxCompoundElement *variable = getCompoundVariable(name);
683  variable->set(_value); /* and perform the set */
684 }
685 
687 /******************************************************************************/
688 /* Function: Return all indices as an array */
689 /******************************************************************************/
690 {
691  RexxCompoundElement *variable; /* table variable entry */
692  RexxArray *array; /* returned array */
693  size_t count; /* count of variables */
694 
695  array = new_array(items()); /* get the array */
696  count = 1; /* start at the beginning again */
697 
698  variable = tails.first(); /* get the first variable */
699  while (variable != OREF_NULL)
700  { /* while more values to process */
701  /* this a real variable? */
702  if (variable->getVariableValue() != OREF_NULL)
703  {
704  /* add to our array */
705  array->put(variable->getName(), count++);
706  }
707  variable = tails.next(variable); /* go get the next one */
708  }
709  return array; /* return the array item */
710 }
711 
713  RexxActivation *context, /* the evaluation context (can be NULL) */
714  RexxString *stemVariableName, // the stem variable name this was evaluated from (used for noValue)
715  RexxCompoundTail *resolved_tail) /* the search tail */
716 /******************************************************************************/
717 /* Function: Retrieve a compound variable, returning the default value if the*/
718 /* variable does not exist. This includes NOVALUE handling. */
719 /******************************************************************************/
720 {
721  RexxCompoundElement *variable; /* the real variable */
722  RexxObject *_value; /* final variable value */
723  RexxString *tail_name; /* formatted tail name */
724 
725  /* get the compound variable */
726  variable = findCompoundVariable(resolved_tail);
727  if (variable == OREF_NULL)
728  { /* variable does not exist? */
729  if (!dropped) /* stem have a default value? */
730  {
731  _value = this->value; /* get the stems value */
732  }
733  else
734  { /* need to use name */
735  /* create a string version of the name */
736  tail_name = resolved_tail->createCompoundName(stemVariableName);
737  // the tail_name is the fully resolved variable, used for NOVALUE reporting.
738  // the defaultValue is the value that's returned as the expression result,
739  // which is derived from the stem object.
740  RexxObject *defaultValue = resolved_tail->createCompoundName(stemName);
741  /* take care of any novalue situations */
742  _value = handleNovalue(context, tail_name, defaultValue, variable);
743  }
744  }
745  else
746  {
747  /* get the variable value */
748  _value = variable->getVariableValue();
749  if (_value == OREF_NULL)
750  { /* explicitly dropped variable? */
751  /* create a string version of the name */
752  tail_name = resolved_tail->createCompoundName(stemName);
753  // the tail_name is the fully resolved variable, used for NOVALUE reporting.
754  // the defaultValue is the value that's returned as the expression result,
755  // which is derived from the stem object.
756  RexxObject *defaultValue = resolved_tail->createCompoundName(stemName);
757  /* take care of any novalue situations */
758  _value = handleNovalue(context, tail_name, defaultValue, variable);
759  }
760  }
761  return _value; /* and finally return the value */
762 }
763 
765  RexxCompoundTail *resolved_tail) /* the search tail */
766 /******************************************************************************/
767 /* Function: Retrieve a compound variable, returning the default value if the*/
768 /* variable does not exist. This does NOT raise NOVALUE conditions*/
769 /******************************************************************************/
770 {
771  RexxCompoundElement *variable; /* the real variable */
772  RexxObject *_value; /* final variable value */
773 
774  /* get the compound variable */
775  variable = findCompoundVariable(resolved_tail);
776  if (variable == OREF_NULL)
777  { /* variable does not exist? */
778  if (!dropped) /* stem have a default value? */
779  {
780  return this->value; /* get the stems value */
781  }
782  else
783  { /* need to use name */
784  /* create a string version of the name */
785  return(RexxObject *)resolved_tail->createCompoundName(stemName);
786  }
787  }
788  else
789  {
790  /* get the variable value */
791  _value = variable->getVariableValue();
792  if (_value == OREF_NULL)
793  { /* explicitly dropped variable? */
794  /* create a string version of the name */
795  _value = (RexxObject *)resolved_tail->createCompoundName(stemName);
796  }
797  }
798  return _value; /* and finally return the value */
799 }
800 
801 
802 /**
803  * Evaluate the real value of a compound variable. The real
804  * value is either its explicitly assigned value or a stem
805  * assigned value. This returns OREF_NULL if neither is
806  * available. This does not raise NOVALUE conditions.
807  *
808  * @param resolved_tail
809  * The target tail value.
810  *
811  * @return The variable value, or OREF_NULL if the variable does not
812  * have an explicit value.
813  */
815 {
816  // first resolve the compound variable.
817  RexxVariable *variable = findCompoundVariable(resolved_tail);
818  // if the variable is not found, return the stem's default value if it has one.
819  // If there is no default value, return OREF_NULL.
820  if (variable == OREF_NULL) /* variable does not exist? */
821  {
822  if (!dropped)
823  {
824  return value;
825  }
826  return OREF_NULL;
827  }
828  else
829  {
830  // just return the variable value (which may be OREF_NULL if explicitly dropped)
831  return variable->getVariableValue();
832  }
833 }
834 
835 
836 
838  RexxCompoundTail *resolved_tail) /* the search tail */
839 /******************************************************************************/
840 /* Function: Retrieve a compound variable, returning the default value if the*/
841 /* variable does not exist. This does not handle NOVALUEs. */
842 /******************************************************************************/
843 {
844  RexxCompoundElement *variable; /* the real variable */
845 
846  /* get the compound variable */
847  variable = findCompoundVariable(resolved_tail);
848  if (variable == OREF_NULL)
849  { /* variable does not exist? */
850  if (!dropped) /* stem have a default value? */
851  {
852  return this->value; /* get the stems value */
853  }
854  else
855  { /* need to use name */
856  return OREF_NULL; /* nothing to return */
857  }
858  }
859  /* get the variable value */
860  return variable->getVariableValue();
861 }
862 
863 
865  RexxActivation *context, /* the execution context for the request */
866  RexxString *name, // the fully resolved compound name
867  RexxObject *defaultValue, // the default value to use
868  RexxCompoundElement *variable) // the resolved variable element
869 /******************************************************************************/
870 /* Function: Process a nonvalue condition for a stem variable retrieval. */
871 /* If a context is provided, the novalue is handled in its */
872 /* context. */
873 /******************************************************************************/
874 {
875  /* are we doing this directly for method execution? */
876  if (context != OREF_NULL)
877  {
878  /* the context may need to do additional work */
879  return context->handleNovalueEvent(name, defaultValue, variable);
880  }
881  else
882  {
883  return name; /* just use the name */
884  }
885 }
886 
887 
889  RexxCompoundElement *old_variable) /* the parent compound variable */
890 /******************************************************************************/
891 /* Function: Retrieve a compound variable, returning the default value if the*/
892 /* variable does not exist. This includes NOVALUE handling. */
893 /******************************************************************************/
894 {
895  /* create the equivalent in this stem */
896  RexxCompoundElement *new_variable = tails.findEntry(old_variable->getName(), true);
897  new_variable->expose(old_variable); /* make the association between the two */
898 }
899 
900 
901 /**
902  * Return all items in the stem.
903  *
904  * @return An array of all items in the stem.
905  */
907 {
908  // now we know how big the return result will be, get an array and
909  // populate it, using the same traversal logic as before
910  RexxArray *array = new_array(items());
911  // we index the array with a origin-one index, so we start with one this time
912  size_t count = 1;
913 
914  RexxCompoundElement *variable = tails.first();
915  while (variable != OREF_NULL)
916  {
917  // only add the real values
918  if (variable->getVariableValue() != OREF_NULL)
919  {
920  array->put(variable->getVariableValue(), count++);
921  }
922  variable = tails.next(variable);
923  }
924  return array; // tada, finished
925 }
926 
927 
928 /**
929  * Locate a stem item by value.
930  *
931  * @return The compound item for the located element.
932  */
934 {
935  RexxCompoundElement *variable = tails.first();
936  while (variable != OREF_NULL)
937  {
938  RexxObject *_value = variable->getVariableValue();
939  // if this has a value, and we have a match, then return it
940  if (_value != OREF_NULL && target->equalValue(_value))
941  {
942  return variable;
943  }
944  variable = tails.next(variable);
945  }
946  return OREF_NULL; // not here, oh dear
947 }
948 
949 
950 /**
951  * Get the count of non-dropped items in the stem.
952  *
953  * @return The number of non-dropped items.
954  */
956 {
957  size_t count = 0;
958 
959  RexxCompoundElement *variable = tails.first();
960  while (variable != OREF_NULL)
961  {
962  // we only want to include the non-dropped compounds, so we only count
963  // elements with real values.
964  if (variable->getVariableValue() != OREF_NULL)
965  {
966  count++;
967  }
968  // and keep iterating
969  variable = tails.next(variable);
970  }
971  return count;
972 }
973 
974 
975 /**
976  * Empty the stem. This also clears dropped and exposed tails,
977  *
978  * @return Nothing.
979  */
981 {
982  tails.clear(); // just clear the tails.
983  return OREF_NULL;
984 }
985 
986 
987 /**
988  * Test if the stem is empty.
989  *
990  * @return True if the stem is empty, false otherwise.
991  */
993 {
994  return (items() == 0) ? TheTrueObject : TheFalseObject;
995 }
996 
997 
998 
999 /**
1000  * Create an array of all indexes of the stem.
1001  *
1002  * @return An array of all tail names used in the stem.
1003  */
1005 {
1006  return this->tailArray(); /* extract the array item */
1007 }
1008 
1009 
1010 /**
1011  * Create a supplier for the stem, returning the tail names as
1012  * the indexes and the values as the items.
1013  *
1014  * @return A supplier instance.
1015  */
1017 {
1018  // essentially the same logic as allItems(), but both the item and the
1019  // tail value are accumulated.
1020  size_t count = 0;
1021  RexxCompoundElement *variable = tails.first();
1022  while (variable != OREF_NULL)
1023  {
1024  // again, get the variable count
1025  if (variable->getVariableValue() != OREF_NULL)
1026  {
1027  count++; /* count this variable */
1028  }
1029  variable = tails.next(variable);
1030  }
1031 
1032  // to create the supplier, we need 2 arrays
1033  RexxArray *tailValues = new_array(count);
1034  RexxArray *values = new_array(count);
1035  count = 1; // we fill in using 1-based indexes
1036 
1037  variable = tails.first();
1038  while (variable != OREF_NULL)
1039  {
1040  // now grab both the tail and value and put them in the respective arrays
1041  if (variable->getVariableValue() != OREF_NULL)
1042  {
1043  tailValues->put(variable->getName(), count);
1044  values->put(variable->getVariableValue(), count++);
1045  }
1046  variable = tails.next(variable);
1047  }
1048  // two arrays become one supplier
1049  return new_supplier(values, tailValues);
1050 }
1051 
1052 
1053 /**
1054  * Create a directory from the stem. Each tail with an
1055  * assigned value will be an entry within the directory.
1056  *
1057  * @return A directory instance.
1058  */
1060 {
1061  RexxDirectory *result = new_directory();
1062  ProtectedObject p1(result);
1063  RexxCompoundElement *variable = tails.first();
1064  while (variable != OREF_NULL)
1065  {
1066  // again, get the variable count
1067  if (variable->getVariableValue() != OREF_NULL)
1068  {
1069  result->put(variable->getVariableValue(), variable->getName());
1070  }
1071  variable = tails.next(variable);
1072  }
1073 
1074  return result;
1075 }
1076 
1077 
1078 /**
1079  * Set a single stem variable object using a simple string
1080  * value tail as a result of an api call.
1081  *
1082  * @param tail The index of the target value.
1083  * @param value The new value to assign.
1084  */
1085 void RexxStem::setElement(const char *_tail, RexxObject *_value)
1086 {
1087  RexxCompoundTail resolved_tail(_tail);
1088  RexxVariable *variable = getCompoundVariable(&resolved_tail);
1089  variable->set(_value); /* set the new value */
1090 }
1091 
1092 
1093 /**
1094  * Set a single stem variable object using a simple string
1095  * value tail as a result of an api call.
1096  *
1097  * @param tail The index of the target value.
1098  * @param value The new value to assign.
1099  */
1100 void RexxStem::setElement(size_t _tail, RexxObject *_value)
1101 {
1102  RexxCompoundTail resolved_tail(_tail);
1103  RexxVariable *variable = getCompoundVariable(&resolved_tail);
1104  variable->set(_value); /* set the new value */
1105 }
1106 
1107 
1108 /**
1109  * Evaluate an array element for an API class.
1110  *
1111  * @param tail The direct tail value.
1112  *
1113  * @return The object value. If the stem element does not exist or
1114  * has been dropped, this returns OREF_NULL.
1115  */
1117 {
1118 
1119  RexxCompoundTail resolved_tail(_tail);
1120 
1121  return getElement(&resolved_tail);
1122 }
1123 
1124 /**
1125  * Evaluate an array element for an API class.
1126  *
1127  * @param tail The direct tail value.
1128  *
1129  * @return The object value. If the stem element does not exist or
1130  * has been dropped, this returns OREF_NULL.
1131  */
1133 {
1134 
1135  RexxCompoundTail resolved_tail(_tail);
1136 
1137  return getElement(&resolved_tail);
1138 }
1139 
1140 /**
1141  * Resolve a compound variable as a result of an api call.
1142  *
1143  * @param resolved_tail
1144  * The resolved tail value.
1145  *
1146  * @return The variable value. Returns OREF_NULL if not assigned or
1147  * dropped.
1148  */
1150 {
1151  // see if we have a variable...if we do, return its value (a dropped variable
1152  // has a value of OREF_NULL). If not found, return OREF_NULL;
1153  RexxCompoundElement *variable = findCompoundVariable(resolved_tail);
1154  if (variable != OREF_NULL)
1155  {
1156  return variable->getVariableValue();
1157  }
1158  return OREF_NULL;
1159 }
1160 
1161 
1162 /**
1163  * Drop an array element for an API class.
1164  *
1165  * @param tail The direct tail value.
1166  */
1167 void RexxStem::dropElement(size_t _tail)
1168 {
1169 
1170  RexxCompoundTail resolved_tail(_tail);
1171 
1172  dropElement(&resolved_tail);
1173 }
1174 
1175 /**
1176  * Drop an array element for an API class.
1177  *
1178  * @param tail The direct tail value.
1179  */
1180 void RexxStem::dropElement(const char *_tail)
1181 {
1182 
1183  RexxCompoundTail resolved_tail(_tail);
1184 
1185  dropElement(&resolved_tail);
1186 }
1187 
1188 
1189 /**
1190  * Drop an element using a resolved tail value.
1191  *
1192  * @param resolved_tail
1193  * The target tail element.
1194  */
1196 {
1197  RexxCompoundElement *variable = findCompoundVariable(resolved_tail);
1198  if (variable != OREF_NULL)
1199  {
1200  variable->drop();
1201  }
1202 }
1203 
1204 
1205 /**
1206  * Create a full compound name from a constructed compound taile.
1207  *
1208  * @param tailPart The constructed tail element.
1209  *
1210  * @return The fully resolved string name of the element.
1211  */
1213 {
1214  return tailPart->createCompoundName(stemName);
1215 }
1216 
1217 
1218 /******************************************************************************/
1219 /* Function: Below are a series of comparison routines used by the qsort() */
1220 /* library function when sorting stems. */
1221 /******************************************************************************/
1223 {
1224  return arg1->sortCaselessCompare(arg2);
1225 }
1226 
1228 {
1229  return arg1->sortCaselessCompare(arg2, sd->startColumn, sd->columnLength);
1230 }
1231 
1233 {
1234  return arg1->sortCompare(arg2);
1235 }
1236 
1238 {
1239  return arg1->sortCompare(arg2, sd->startColumn, sd->columnLength);
1240 }
1241 
1243 {
1244  return -arg1->sortCompare(arg2);
1245 }
1246 
1248 {
1249  return -arg1->sortCompare(arg2, sd->startColumn, sd->columnLength);
1250 }
1251 
1253 {
1254  return -arg1->sortCaselessCompare(arg2);
1255 }
1256 
1258 {
1259  return -arg1->sortCaselessCompare(arg2, sd->startColumn, sd->columnLength);
1260 }
1261 
1262 
1263 /**
1264  * The merge sort routine. This will partition the data in to
1265  * two sections, mergesort each partition, then merge the two
1266  * partitions together.
1267  *
1268  * @param sd The sort information.
1269  * @param comparator The comparator object used for the compares.
1270  * @param strings The input set of strings.
1271  * @param working The working array (same size as the sorted array).
1272  * @param left The left bound of the partition.
1273  * @param right The right bounds of the parition.
1274  */
1275 void RexxStem::mergeSort(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t right)
1276 {
1277  size_t len = right - left + 1;
1278  // use insertion sort for small arrays
1279  if (len <= 7) {
1280  for (size_t i = left + 1; i <= right; i++) {
1281  RexxString *current = strings[i];
1282  RexxString *prev = strings[i - 1];
1283  if (comparator(sd, current, prev) < 0) {
1284  size_t j = i;
1285  do {
1286  strings[j--] = prev;
1287  } while (j > left && comparator(sd, current, prev = strings[j - 1]) < 0);
1288  strings[j] = current;
1289  }
1290  }
1291  return;
1292  }
1293 
1294  size_t mid = (right + left) / 2;
1295  mergeSort(sd, comparator, strings, working, left, mid);
1296  mergeSort(sd, comparator, strings, working, mid + 1, right);
1297  merge(sd, comparator, strings, working, left, mid + 1, right);
1298 }
1299 
1300 
1301 /**
1302  * Perform a merge of two sort partitions.
1303  *
1304  * @param sd The sort descriptor.
1305  * @param comparator The comparator used to compare elements.
1306  * @param strings The input strings.
1307  * @param working A working array used for the merge operations.
1308  * @param left The left bound for the merge.
1309  * @param mid The midpoint for the merge.
1310  * @param right The right bound of merge (inclusive).
1311  */
1312 void RexxStem::merge(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString **working, size_t left, size_t mid, size_t right)
1313 {
1314  size_t leftEnd = mid - 1;
1315  // merging
1316 
1317  // if arrays are already sorted - no merge
1318  if (comparator(sd, strings[leftEnd], strings[mid]) <= 0) {
1319  return;
1320  }
1321 
1322  size_t leftCursor = left;
1323  size_t rightCursor = mid;
1324  size_t workingPosition = left;
1325 
1326  // use merging with exponential search
1327  do
1328  {
1329  RexxString *fromVal = strings[leftCursor];
1330  RexxString *rightVal = strings[rightCursor];
1331  if (comparator(sd, fromVal, rightVal) <= 0)
1332  {
1333  size_t leftInsertion = find(sd, comparator, strings, rightVal, -1, leftCursor + 1, leftEnd);
1334  size_t toCopy = leftInsertion - leftCursor + 1;
1335  arraycopy(strings, leftCursor, working, workingPosition, toCopy);
1336  workingPosition += toCopy;
1337  working[workingPosition++] = rightVal;
1338  // now we've added this
1339  rightCursor++;
1340  // step over the section we just copied...which might be
1341  // all of the remaining section
1342  leftCursor = leftInsertion + 1;
1343  }
1344  else
1345  {
1346  size_t rightInsertion = find(sd, comparator, strings, fromVal, 0, rightCursor + 1, right);
1347  size_t toCopy = rightInsertion - rightCursor + 1;
1348  arraycopy(strings, rightCursor, working, workingPosition, toCopy);
1349  workingPosition += toCopy;
1350  // insert the right-hand value
1351  working[workingPosition++] = fromVal;
1352  leftCursor++;
1353  rightCursor = rightInsertion + 1;
1354  }
1355  } while (right >= rightCursor && mid > leftCursor);
1356 
1357  // copy rest of array. If we've not used up the left hand side,
1358  // we copy that. Otherwise, there are items on the right side
1359  if (leftCursor < mid)
1360  {
1361  arraycopy(strings, leftCursor, working, workingPosition, mid - leftCursor);
1362  }
1363  else
1364  {
1365  arraycopy(strings, rightCursor, working, workingPosition, right - rightCursor + 1);
1366  }
1367 
1368  arraycopy(working, left, strings, left, right - left + 1);
1369 }
1370 
1371 /**
1372  * copy segments of one array into another.
1373  *
1374  * @param source The source array
1375  * @param start The starting index of the source copy
1376  * @param target The target array
1377  * @param index The target copy index
1378  * @param count The number of items to count.
1379  */
1380 void RexxStem::arraycopy(RexxString **source, size_t start, RexxString **target, size_t index, size_t count)
1381 {
1382  for (size_t i = start; i < start + count; i++)
1383  {
1384  target[index++] = source[i];
1385  }
1386 }
1387 
1388 /**
1389  * Finds the place in the given range of specified sorted array, where the
1390  * element should be inserted for getting sorted array. Uses exponential
1391  * search algorithm.
1392  *
1393  * @param sd The sort descriptor
1394  * @param comparator The comparator used to compare pairs of elements.
1395  * @param strings The input set of strings.
1396  * @param val object to be inserted
1397  * @param bnd possible values 0,-1. "-1" - val is located at index more then
1398  * elements equals to val. "0" - val is located at index less
1399  * then elements equals to val.
1400  * @param left The left bound of the insert operation.
1401  * @param right The right bound for the insert.
1402  *
1403  * @return The insertion point.
1404  */
1405 size_t RexxStem::find(SortData *sd, int (*comparator)(SortData *, RexxString *, RexxString *), RexxString **strings, RexxString *val, int limit, size_t left, size_t right)
1406 {
1407  size_t checkPoint = left;
1408  size_t delta = 1;
1409  while (checkPoint <= right)
1410  {
1411  // if this is too big, then we're moving to the right
1412  if (comparator(sd, val, strings[checkPoint]) > limit)
1413  {
1414  // the left bound is at least this
1415  left = checkPoint + 1;
1416  }
1417  else
1418  {
1419  // we've found a right limit. We can stop scanning here
1420  right = checkPoint - 1;
1421  break;
1422  }
1423  // step the delta amount
1424  checkPoint += delta;
1425  // and double the movement amount
1426  delta = delta * 2;
1427  }
1428  // we should have now limited the bounds for the insertion point
1429  // now start in the middle and shrink the range with each comparison
1430  while (left <= right)
1431  {
1432  // start in the middle of the current range
1433  checkPoint = (left + right) / 2;
1434  if (comparator(sd, val, strings[checkPoint]) > limit)
1435  {
1436  // pull in the left end of the range
1437  left = checkPoint + 1;
1438  }
1439  else
1440  {
1441  // chop the right range
1442  right = checkPoint - 1;
1443  }
1444  }
1445  // the left bound is the insertion point
1446  return left - 1;
1447 }
1448 
1449 
1450 bool RexxStem::sort(RexxString *prefix, int order, int type, size_t _first, size_t last, size_t firstcol, size_t lastcol)
1451 /******************************************************************************/
1452 /* Function: Sort elements of a stem variable as if it was an array. This */
1453 /* routine assumes that element ".0" of the stem contains a size */
1454 /* value for the array portion of the elements, and that tail */
1455 /* indices ".start" to ".end", inclusive all exist in the tail. */
1456 /* Sorting will be performed on the string values of all elements, */
1457 /* and in the final result, all values will be replaced by the */
1458 /* string values. */
1459 /******************************************************************************/
1460 {
1461  SortData sd;
1462 
1463  sd.startColumn = 0;
1464  sd.columnLength = 0;
1465 
1466  RexxCompoundTail stem_size(prefix, (size_t)0);
1467  RexxCompoundElement *size_element = findCompoundVariable(&stem_size);
1468  if (size_element == OREF_NULL) {
1469  return false;
1470  }
1471  RexxObject *size_value = size_element->getVariableValue();
1472  if (size_value == OREF_NULL) {
1473  return false;
1474  }
1475 
1476  stringsize_t count;
1477  /* get the integer value of this. It must be a valid numeric */
1478  /* value. */
1479  if (!size_value->unsignedNumberValue(count, Numerics::DEFAULT_DIGITS))
1480  {
1481  return false;
1482  }
1483  if (count == 0) // if the count is zero, sorting is easy!
1484  {
1485  return true;
1486  }
1487 
1488  /* if this is not specified, sort to the end */
1489  if (last == SIZE_MAX)
1490  {
1491  last = count;
1492  }
1493 
1494  /* verify we're fully within the bounds */
1495  if (_first > count || last > count) {
1496  return false;
1497  }
1498  size_t bounds = last - _first + 1;
1499 
1500  // get an array item and protect it. We need to have space for
1501  // the the variable anchors, the variable values, and a working buffer for the merge. */
1502  RexxArray *array = new_array(bounds * 3);
1503  ProtectedObject p1(array);
1504 
1505  size_t i;
1506  size_t j;
1507  for (j = 1, i = _first; i <= last; i++, j++)
1508  {
1509  RexxCompoundTail nextStem(prefix, (size_t)i);
1510  RexxCompoundElement *next_element = findCompoundVariable(&nextStem);
1511 
1512  if (next_element == OREF_NULL) {
1513  return false;
1514  }
1515 
1516  RexxObject *nextValue = next_element->getVariableValue();
1517  if (nextValue == OREF_NULL) {
1518  return false;
1519  }
1520  /* force this to a string value. */
1521  nextValue = REQUEST_STRING(nextValue);
1522  /* now anchor both in the sorting array */
1523  array->put((RexxObject *)next_element, j);
1524  array->put(nextValue, j + bounds);
1525  }
1526 
1527  // the data to be sorted
1528  RexxString **aData = (RexxString **)array->data(bounds + 1);
1529  // the merge sort work area
1530  RexxString **working = (RexxString **)array->data((bounds * 2) + 1);
1531 
1532  {
1533  // we're releasing kernel access during the process. The sort is being
1534  // done on a locally allocated array, so this will not be accessed by another thread.
1535  // All the rest of the operations are thread safe.
1536  UnsafeBlock block;
1537 
1538  if ((firstcol == 0) && (lastcol == SIZE_MAX)) {
1539  /* no special columns to check */
1540  switch (type) {
1541 
1542  case SORT_CASESENSITIVE:
1544  aData, working, 0, bounds - 1);
1545  break;
1546  case SORT_CASEIGNORE:
1548  aData, working, 0, bounds - 1);
1549  break;
1550  }
1551  }
1552  else
1553  {
1554  /* set columns to sort */
1555  sd.startColumn = firstcol;
1556  sd.columnLength = lastcol - firstcol + 1;
1557 
1558  switch (type)
1559  {
1560  case SORT_CASESENSITIVE:
1562  aData, working, 0, bounds - 1);
1563  break;
1564  case SORT_CASEIGNORE:
1566  aData, working, 0, bounds - 1);
1567  break;
1568  }
1569  }
1570  }
1571 
1572 
1573  /* The values have now been sorted. We now need to set each */
1574  /* each variable back to its new value. */
1575  for (i = 1; i <= bounds; i++) {
1576  RexxCompoundElement *element = (RexxCompoundElement *)array->get(i);
1577  RexxObject *_value = array->get(i + bounds);
1578  element->set(_value);
1579  }
1580  return true;
1581 }
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:60
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:469
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:283
#define IntegerOne
Definition: RexxCore.h:190
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheTrueObject
Definition: RexxCore.h:186
const int ARG_TWO
Definition: RexxCore.h:81
#define IntegerTwo
Definition: RexxCore.h:191
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
const int ARG_ONE
Definition: RexxCore.h:80
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:291
#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:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:493
#define CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
#define cleanUpFlatten
Definition: RexxMemory.hpp:479
#define setUpFlatten(type)
Definition: RexxMemory.hpp:473
RexxVariable * new_variable(RexxString *n)
int compare_desc_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1247
int compare_asc(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1232
int compare_desc(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1242
int compare_desc_i(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1252
int compare_asc_i_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1227
int compare_asc_i(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1222
int compare_desc_i_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1257
int compare_asc_cols(SortData *sd, RexxString *arg1, RexxString *arg2)
Definition: StemClass.cpp:1237
#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 **)
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:1212
RexxObject * itemsRexx()
Definition: StemClass.cpp:384
RexxCompoundElement * getCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:574
RexxObject * getCompoundVariableValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:764
size_t items()
Definition: StemClass.cpp:955
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:1275
RexxCompoundElement * exposeCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:586
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:814
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:1085
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:1450
RexxNumberString * numberString()
Definition: StemClass.cpp:491
void dropCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:634
RexxObject * copy()
Definition: StemClass.cpp:91
void setCompoundVariable(RexxCompoundTail *name, RexxObject *value)
Definition: StemClass.cpp:674
void live(size_t)
Definition: StemClass.cpp:116
RexxObject * getStemValue()
Definition: StemClass.cpp:179
RexxObject * isEmpty()
Definition: StemClass.cpp:992
static void createInstance()
Definition: StemClass.cpp:63
RexxObject * index(RexxObject *)
Definition: StemClass.cpp:368
RexxArray * allItems()
Definition: StemClass.cpp:906
RexxString * stringValue()
Definition: StemClass.cpp:442
bool unsignedNumberValue(stringsize_t &result, size_t precision)
Definition: StemClass.cpp:467
RexxSupplier * supplier()
Definition: StemClass.cpp:1016
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:1312
RexxCompoundElement * nextVariable(RexxNativeActivation *activation)
Definition: StemClass.cpp:645
RexxStem(RexxString *)
Definition: StemClass.cpp:69
RexxObject * handleNovalue(RexxActivation *context, RexxString *name, RexxObject *defaultValue, RexxCompoundElement *variable)
Definition: StemClass.cpp:864
RexxArray * tailArray()
Definition: StemClass.cpp:686
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:1405
RexxCompoundElement * findCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:617
RexxObject * empty()
Definition: StemClass.cpp:980
void expose(RexxCompoundElement *variable)
Definition: StemClass.cpp:888
RexxObject * evaluateCompoundVariableValue(RexxActivation *context, RexxString *stemVariableName, RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:712
void dropElement(const char *tail)
Definition: StemClass.cpp:1180
RexxString * stemName
Definition: StemClass.hpp:158
RexxCompoundElement * findByValue(RexxObject *target)
Definition: StemClass.cpp:933
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:1116
RexxDirectory * toDirectory()
Definition: StemClass.cpp:1059
RexxObject * realCompoundVariableValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:837
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:1004
RexxString * getName()
Definition: StemClass.hpp:139
void arraycopy(RexxString **source, size_t start, RexxString **target, size_t index, size_t count)
Definition: StemClass.cpp:1380
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:383
ssize_t wholenumber_t
Definition: rexx.h:230
size_t stringsize_t
Definition: rexx.h:228
#define SIZE_MAX