RexxVariableDictionary.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 RexxVariableDictionary.cpp */
40 /* */
41 /* Primitive Variable Dictionary Class */
42 /* */
43 /******************************************************************************/
44 #include "RexxCore.h"
45 #include "StringClass.hpp"
46 #include "DirectoryClass.hpp"
47 #include "RexxNativeActivation.hpp"
48 #include "RexxActivity.hpp"
49 #include "ArrayClass.hpp"
50 #include "ListClass.hpp"
52 #include "StemClass.hpp"
54 #include "ExpressionStem.hpp"
55 #include "ExpressionVariable.hpp"
58 #include "ProtectedObject.hpp"
59 #include "SupplierClass.hpp"
60 #include "RexxCompoundTail.hpp"
61 #include "SourceFile.hpp"
62 
63 
65 /******************************************************************************/
66 /* Function: Copy a variable dictionary */
67 /******************************************************************************/
68 {
69  /* create a new object */
71  /* copy the behaviour pointer */
72  OrefSet(copyObj, copyObj->behaviour, this->behaviour);
73  ProtectedObject p(copyObj);
74  /* copy the hash table */
75  OrefSet(copyObj, copyObj->contents, (RexxHashTable *)this->contents->copy());
76  /* make sure we copy the scope too */
77  OrefSet(copyObj, copyObj->scope, this->scope);
78  copyObj->copyValues(); /* copy all of the variables */
79  return(RexxObject *)copyObj; /* return the new vdict */
80 }
81 
83 /******************************************************************************/
84 /* Function: Copy all of the values in a vdict */
85 /******************************************************************************/
86 {
87  /* loop through the hash table */
88  for (size_t i = this->contents->first();
89  i < this->contents->totalSlotsSize();
90  i = this->contents->next(i))
91  {
92  RexxObject *value = this->contents->value(i); /* get the next value */
93  RexxObject *copyObj = value->copy(); /* copy the value */
94  this->contents->replace(copyObj, i); /* replace with the copied value */
95  }
96 }
97 
99  RexxString *name) /* name of variable to retrieve */
100 /******************************************************************************/
101 /* Function: Retrieve a variable's value WITHOUT returning the default */
102 /* variable name if it doesn't exist. */
103 /******************************************************************************/
104 {
105  RexxVariable *variable = resolveVariable(name); /* look up the name */
106  if (variable == OREF_NULL) /* not found? */
107  {
108  return OREF_NULL; /* say so */
109  }
110  return variable->getVariableValue(); /* use the variable value */
111 }
112 
113 
114 /**
115  * Drop the value of a named variable in the method dictionary.
116  *
117  * @param name The string name of the variable.
118  */
120 {
121  // if the variable exists, drop the value
122  RexxVariable *variable = resolveVariable(name);
123  if (variable != OREF_NULL)
124  {
125  variable->drop();
126  }
127 }
128 
129 
130 /**
131  * Drop the value of a named variable in the method dictionary.
132  *
133  * @param name The string name of the variable.
134  */
136 {
137  // if the variable exists, drop the value
138  RexxVariable *variable = resolveVariable(name);
139  if (variable != OREF_NULL)
140  {
141  variable->drop();
142  /* create a new stem element and set this */
143  variable->set(new RexxStem(name));
144  }
145 }
146 
147 
149  RexxString *stemName, /* name of stem for compound */
150  RexxObject **tail, /* tail of the compound element */
151  size_t tailCount) /* number of tail pieces */
152 /******************************************************************************/
153 /* Function: Retrieve a compound variable, returning OREF_NULL if the */
154 /* variable does not exist. */
155 /******************************************************************************/
156 {
157  /* new tail for compound */
158  RexxCompoundTail resolved_tail(this, tail, tailCount);
159 
160  RexxStem *stem_table = getStem(stemName); /* get the stem entry from this dictionary */
161  /* get the compound variable */
162  return stem_table->getCompoundVariable(&resolved_tail);
163 }
164 
165 
167  RexxString *stemName, /* name of stem for compound */
168  RexxObject **tail, /* tail of the compound element */
169  size_t tailCount) /* number of tail pieces */
170 /******************************************************************************/
171 /* Function: Retrieve a compound variable, returning default value if the */
172 /* variable does not exist. This does not raise NOVALUE. */
173 /******************************************************************************/
174 {
175  /* new tail for compound */
176  RexxCompoundTail resolved_tail(this, tail, tailCount);
177 
178  RexxStem *stem_table = getStem(stemName); /* get the stem entry from this dictionary */
179  /* get the value from the stem...we pass OREF_NULL */
180  /* for the dictionary to bypass NOVALUE handling */
181  return stem_table->evaluateCompoundVariableValue(OREF_NULL, stemName, &resolved_tail);
182 }
183 
184 
185 /**
186  * Retrieve the "real" value of a compound variable. This
187  * return OREF_NULL for any situation where the compound variable
188  * name would be returned.
189  *
190  * @param stem The name of the stem.
191  * @param tail The set of tails used for the lookup.
192  * @param tailCount The number of tail elements.
193  *
194  * @return Either the variable value, or OREF_NULL for unassigned
195  * variables.
196  */
198  RexxObject **tail, size_t tailCount)
199 {
200  /* new tail for compound */
201  RexxCompoundTail resolved_tail(this, tail, tailCount);
202 
203  RexxStem *stem_table = getStem(stem); /* get the stem entry from this dictionary */
204  /* get the value from the stem...we pass OREF_NULL */
205  /* for the dictionary to bypass NOVALUE handling */
206  return stem_table->getCompoundVariableRealValue(&resolved_tail);
207 }
208 
209 
211  RexxString *stemName) /* name of stem for compound */
212 /******************************************************************************/
213 /* Function: Retrieve the "real" value of a stem variable. OREF_NULL is */
214 /* returned if the stem does not exist. */
215 /******************************************************************************/
216 {
217  /* look up the name */
218  return this->getStem(stemName); /* find and return the stem directly */
219 }
220 
221 
223  RexxVariable *variable, /* new variable entry */
224  RexxString *name) /* variable name */
225 /******************************************************************************/
226 /* Function: Insert an item into the variable dictionary hash table, */
227 /* updating the lookaside array if the index is available. */
228 /******************************************************************************/
229 {
230  /* try to place in existing hashtab */
231  RexxHashTable *new_hash = this->contents->stringAdd((RexxObject *)variable, name);
232  if (new_hash != OREF_NULL) /* have a reallocation occur? */
233  {
234  /* hook on the new hash table */
235  OrefSet(this, this->contents, new_hash);
236  }
237 }
238 
240  RexxVariable *variable, /* new variable entry */
241  RexxString *name) /* variable name */
242 /******************************************************************************/
243 /* Function: Insert an item into the variable dictionary hash table, */
244 /* updating the lookaside array if the index is available. */
245 /******************************************************************************/
246 {
247  /* try to place in existing hashtab */
248  RexxHashTable *new_hash = this->contents->stringPut((RexxObject *)variable, name);
249  if (new_hash != OREF_NULL) /* have a reallocation occur? */
250  {
251  /* hook on the new hash table */
252  OrefSet(this, this->contents, new_hash);
253  }
254 }
255 
256 
258  RexxString *stemName) /* name of target stem */
259 /******************************************************************************/
260 /* Function: Lookup and retrieve a STEM variable item (not the stem table) */
261 /* level) */
262 /******************************************************************************/
263 {
264  RexxVariable *variable = new_variable(stemName); /* make a new variable entry */
265  RexxStem *stemtable = new RexxStem (stemName); /* create a stem object as value */
266  /* the stem object is the value of */
267  /* stem variable */
268  variable->set((RexxObject *)stemtable);
269  /* try to place in existing hashtab */
270  RexxHashTable *new_hash = this->contents->stringAdd((RexxObject *)variable, stemName);
271  if (new_hash != OREF_NULL) /* have a reallocation occur? */
272  {
273  /* hook on the new hash table */
274  OrefSet(this, this->contents, new_hash);
275  }
276  return variable; /* return the stem */
277 }
278 
279 
281  RexxString *name) /* name of target variable */
282 /******************************************************************************/
283 /* Function: Create a new variable item and add it to the dictionary. */
284 /******************************************************************************/
285 {
286  RexxVariable *variable = new_variable(name); /* make a new variable entry */
287  /* try to place in existing hashtab */
288  RexxHashTable *new_hash = this->contents->stringAdd((RexxObject *)variable, name);
289  if (new_hash != OREF_NULL) /* have a reallocation occur? */
290  {
291  /* hook on the new hash table */
292  OrefSet(this, this->contents, new_hash);
293  }
294  return variable; /* return the stem */
295 }
296 
298  RexxNativeActivation *activation) /* Hosting Native Act. */
299 /******************************************************************************/
300 /* Function: Return the "next" variable of a variable traversal */
301 /******************************************************************************/
302 {
303  if (activation->nextVariable() == SIZE_MAX)/* first time through? */
304  {
305  /* get the first item */
306  activation->setNextVariable(this->contents->first());
307  }
308  else /* step to the next index item */
309  {
310  activation->setNextVariable(this->contents->next(activation->nextVariable()));
311  }
312  /* while more directory entries */
313  while (this->contents->index(activation->nextVariable()) != OREF_NULL)
314  {
315  /* get the variable object */
316  RexxVariable *variable = (RexxVariable *)this->contents->value(activation->nextVariable());
317  /* get the value */
318  RexxObject *value = variable->getVariableValue();
319  if (value != OREF_NULL)
320  { /* not a dropped variable? */
321  return variable; /* got what we need */
322  }
323  /* step to the next index item */
324  activation->setNextVariable(this->contents->next(activation->nextVariable()));
325  }
326  activation->setNextVariable(-1); /* reset the index for the end */
327  return OREF_NULL;
328 }
329 
331  RexxString *name, /* name to set */
332  RexxObject *value) /* value to assign to variable name */
333 /******************************************************************************/
334 /* Function: Set a new variable value */
335 /******************************************************************************/
336 {
337  RexxVariable *variable; /* retrieved variable item */
338 
339  variable = getVariable(name); /* look up the name */
340  variable->set(value); /* and perform the set */
341 }
342 
344  RexxActivity *activity) /* reserving activity */
345 /******************************************************************************/
346 /* Function: Reserve a scope on an object, waiting for completion if this */
347 /* is already reserved by another activity */
348 /******************************************************************************/
349 {
350  /* currently unlocked? */
351  if (this->reservingActivity == OREF_NULL)
352  {
353  /* set the locker */
354  OrefSet(this, this->reservingActivity, activity);
355  this->reserveCount = 1; /* we're reserved once */
356  }
357  /* doing again on the same stack? */
358  else if (this->reservingActivity == activity)
359  {
360  this->reserveCount++; /* bump the nesting count */
361  }
362  else
363  { /* need to wait on this */
364  /* go perform dead lock checks */
365  this->reservingActivity->checkDeadLock(activity);
366  /* no list here? */
367  if (this->waitingActivities == OREF_NULL)
368  {
369  /* get a waiting queue */
370  OrefSet(this, this->waitingActivities, new_list());
371  }
372  /* add to the wait queue */
373  this->waitingActivities->addLast((RexxObject *)activity);
374  /* ok, now we wait */
375  activity->waitReserve((RexxObject *)this);
376  }
377 }
378 
380  RexxActivity *activity) /* reserving activity */
381 /******************************************************************************/
382 /* Function: Release the lock on an object's ovd */
383 /******************************************************************************/
384 {
385  this->reserveCount--; /* decrement the reserving count */
386  if (this->reserveCount == 0)
387  { /* last one for this activity? */
388  /* remove the current reserver */
389  OrefSet(this, this->reservingActivity, OREF_NULL);
390  /* have things waiting? */
391  if (this->waitingActivities != OREF_NULL)
392  {
393  /* get the next one */
394  RexxActivity *newActivity = (RexxActivity *)this->waitingActivities->removeFirst();
395  /* have a real one here? */
396  if (newActivity != (RexxActivity *)TheNilObject)
397  {
398  /* this is the new owner */
399  OrefSet(this, this->reservingActivity, newActivity);
400  this->reserveCount = 1; /* back to one lock again */
401  /* wake up the waiting activity */
402  newActivity->postDispatch();
403  }
404  }
405  }
406 }
407 
408 
410  RexxActivity *activity) /* new reserving activity */
411 /******************************************************************************/
412 /* Function: Transfer a vdict lock to another activity */
413 /******************************************************************************/
414 {
415  if (this->reserveCount == 1)
416  { /* only one level of nesting? */
417  /* easy, just switch the owner */
418  OrefSet(this, this->reservingActivity, activity);
419  return true; /* say this worked */
420  }
421  else
422  { /* multiple nesting levels */
423  this->release(activity); /* release this lock */
424  return false; /* can't do this */
425  }
426 }
427 
428 
430 /******************************************************************************/
431 /* Function: Chain up a dictionary associated with an object */
432 /******************************************************************************/
433 {
434  OrefSet(this, this->next, _next);
435 }
436 
437 void RexxVariableDictionary::live(size_t liveMark)
438 /******************************************************************************/
439 /* Function: Normal garbage collection live marking */
440 /******************************************************************************/
441 {
442  memory_mark(this->contents);
445  memory_mark(this->next);
446  memory_mark(this->scope);
447 }
448 
450 /******************************************************************************/
451 /* Function: Generalized object marking */
452 /******************************************************************************/
453 {
457  memory_mark_general(this->next);
458  memory_mark_general(this->scope);
459 }
460 
461 
462 /**
463  * Get all of the variables in the local context. This returns
464  * just the top-level variables (i.e., simple variables and stems).
465  *
466  * @return A supplier for iterating the variable sset.
467  */
469 {
470  HashLink i;
471  RexxDirectory *result = new_directory();
472  ProtectedObject p1(result);
473  /* loop through the hash table */
474  for (i = this->contents->first();
475  i < this->contents->totalSlotsSize();
476  i = this->contents->next(i))
477  {
478  // get the next variable from the dictionary
479  RexxVariable *variable = (RexxVariable *)this->contents->value(i);
480  // if this variable has a value, bump the count
481  if (variable->getVariableValue() != OREF_NULL)
482  {
483  result->put(variable->getVariableValue(), variable->getName());
484  }
485  }
486 
487  return result;
488 }
489 
490 
492 /******************************************************************************/
493 /* Function: Flatten an object */
494 /******************************************************************************/
495 {
497 
498  flatten_reference(newThis->contents, envelope);
499  flatten_reference(newThis->reservingActivity, envelope);
500  flatten_reference(newThis->waitingActivities, envelope);
501  flatten_reference(newThis->next, envelope);
502  flatten_reference(newThis->scope, envelope);
504 }
505 
506 
508  size_t looksize) /* expected size of the vdict */
509 /******************************************************************************/
510 /* Function: Create a new translator object */
511 /******************************************************************************/
512 {
513  /* Get new object */
514  /* NOTE: there is one extra */
515  /* lookaside element allocated, */
516  /* which is used for non-lookaside */
517  /* lookups. Using this extra element*/
518  /* (which is always NULL), allows */
519  /* some special optimization of the */
520  /* look ups */
521  /* get a new object and hash */
523 }
524 
525 
527  RexxObject *scope) /* expected size of the vdict */
528 /******************************************************************************/
529 /* Function: Create a new translator object */
530 /******************************************************************************/
531 {
532  /* create entries for twice size */
533  size_t hashTabSize = DEFAULT_OBJECT_DICTIONARY_SIZE * 2;
534  /* Get new object */
535  /* NOTE: there is one extra */
536  /* lookaside element allocated, */
537  /* which is used for non-lookaside */
538  /* lookups. Using this extra element*/
539  /* (which is always NULL), allows */
540  /* some special optimization of the */
541  /* look ups */
542  /* get a new object and hash */
544  newObj->scope = scope; /* fill in the scope */
545  return newObj; /* return the new vdict */
546 }
547 
548 
549 /**
550  * Set a compound variable in the dictionary.
551  *
552  * @param stemName The name of the stem.
553  * @param tail The tail elements.
554  * @param tailCount The count of tail elements.
555  * @param value The value to set.
556  */
557 void RexxVariableDictionary::setCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount, RexxObject *value)
558 {
559  /* new tail for compound */
560  RexxCompoundTail resolved_tail(this, tail, tailCount);
561 
562  RexxStem *stem_table = getStem(stemName); /* get the stem entry from this dictionary */
563  /* and set the value */
564  stem_table->setCompoundVariable(&resolved_tail, value);
565 }
566 
567 
568 /**
569  * Drop a compound variable in the dictionary.
570  *
571  * @param stemName The name of the stem.
572  * @param tail The tail elements.
573  * @param tailCount The count of tail elements.
574  * @param value The value to set.
575  */
576 void RexxVariableDictionary::dropCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount)
577 {
578  /* new tail for compound */
579  RexxCompoundTail resolved_tail(this, tail, tailCount);
580 
581  RexxStem *stem_table = getStem(stemName); /* get the stem entry from this dictionary */
582  /* and set the value */
583  stem_table->dropCompoundVariable(&resolved_tail);
584 }
585 
586 
588  RexxString *variable ) /* name of the variable */
589 /******************************************************************************/
590 /* Arguments: Name of variable to generate retriever */
591 /* */
592 /* Returned: Retriever for variable (returns OREF_NULL for invalids) */
593 /******************************************************************************/
594 {
595  variable = variable->upper(); /* upper case the variable */
596  ProtectedObject p(variable);
597  int type = variable->isSymbol(); /* validate the symbol */
598  /* create a retriever object */
599  switch (type)
600  {
601  case STRING_BAD_VARIABLE: /* if it didn't validate */
602  return OREF_NULL; /* don't return a retriever object */
603 
604  case STRING_LITERAL_DOT: /* if is is a literal */
605  case STRING_NUMERIC:
606  /* these are literals */
607  return(RexxVariableBase *)variable;
608 
609  // Dot variables retrieve from the environment
610  case STRING_LITERAL:
611  // this is only a dot variable if it begins with a period
612  if (variable->getChar(0) == '.')
613  {
614  return (RexxVariableBase *)new RexxDotVariable(variable->extract(1, variable->getLength() - 1));
615  }
616  // this is a literal symbol not beginning with a period
617  return (RexxVariableBase *)variable;
618 
619  /* if it is a stem */
620  case STRING_STEM:
621  /* create a new stem retriever */
622  return(RexxVariableBase *)new RexxStemVariable(variable, 0);
623  /* if it is a compound */
625  /* create a new compound retriever */
626  return(RexxVariableBase *)buildCompoundVariable(variable, false);
627  /* if it is a simple */
628  case STRING_NAME:
629  /* create a new variable retriever */
630  return(RexxVariableBase *)new RexxParseVariable(variable, 0);
631  /* if we don't know what it is */
632  default:
633  return OREF_NULL; /* don't return a retriever object */
634  }
635 }
636 
637 
639  RexxString *variable ) /* name of the variable */
640 /******************************************************************************/
641 /* Function: Return a retriever for a variable using direct access (i.e. */
642 /* no substitution in compound variable tails) */
643 /******************************************************************************/
644 {
645  size_t length = variable->getLength(); /* get the name length */
646  /* get the first character */
647  codepoint_t character = variable->getChar(0);
648  bool literal = false; /* literal indicator */
649  /* constant symbol? */
650  if (character == '.' || (character >= '0' && character <= '9'))
651  {
652  literal = true; /* this is a literal value */
653  }
654  /* have a valid length? */
655  if (length <= (size_t)MAX_SYMBOL_LENGTH && length > 0)
656  {
657  size_t compound = 0; /* no periods yet */
658  size_t scan = 0; /* start at string beginning */
659  size_t nonnumeric = 0; /* count of non-numeric characters */
660  codepoint_t last = 0; /* no last character */
661  while (scan < length)
662  {
663  /* get the next character */
664  character = variable->getChar(scan);
665  /* have a period? */
666  if (character == '.')
667  {
668  if (!literal) /* not a literal value? */
669  {
670  /* don't process past here */
671  return(RexxVariableBase *)buildCompoundVariable(variable, true);
672  }
673  else
674  {
675  compound++; /* count the character */
676  }
677  }
678  /* may have a special character */
679  else if (!RexxSource::isSymbolCharacter(character))
680  {
681  /* maybe exponential form? */
682  if (character == '+' || character == '-')
683  {
684  /* front part not valid? */
685  if (compound > 1 || nonnumeric > 1 || last != 'E')
686  {
687  return OREF_NULL; /* got a bad symbol */
688  }
689  scan++; /* step over the sign */
690  if (scan >= length) /* sign as last character? */
691  {
692  return OREF_NULL; /* this is bad also */
693  }
694  /* scan remainder */
695  while (scan < length)
696  {
697  /* get the next character */
698  character = variable->getChar(scan);
699  /* outside numeric range? */
700  if (character < '0' || character > '9')
701  {
702  return OREF_NULL; /* not valid either */
703  }
704  scan++; /* step scan position */
705  }
706  break; /* done with scanning */
707  }
708  else
709  {
710  // invalid character in a symbol
711  return OREF_NULL;
712  }
713  }
714  /* non-numeric character? */
715  else if (character < '0' || character > '9')
716  {
717  nonnumeric++; /* count the non-numeric */
718  }
719  /* lower case character? */
720  else if (RexxSource::translateChar(character) != character)
721  {
722  return OREF_NULL; /* this is bad, return */
723  }
724  last = character; /* remember last one */
725  scan++; /* step the pointer */
726  }
727  }
728  if (literal) /* was this a literal? */
729  {
730  /* these are both just literals */
731  return(RexxVariableBase *)variable;
732  }
733  else /* simple variable */
734  {
735  /* create a new variable retriever */
736  return(RexxVariableBase *)new RexxParseVariable(variable, 0);
737  }
738 }
739 
740 
742  RexxString *variable_name, /* full variable name of compound */
743  bool direct) /* this is direct access */
744 /******************************************************************************/
745 /* Function: Build a dynamically created compound variable */
746 /******************************************************************************/
747 {
748  size_t length = variable_name->getLength(); /* get the string length */
749  size_t position = 0; /* start scanning at first character */
750  /* scan to the first period */
751  while (variable_name->getChar(position) != '.')
752  {
753  position++; /* step to the next character */
754  length--; /* reduce the length also */
755  }
756  /* extract the stem part */
757  RexxString *stem = variable_name->extract(0, position + 1);
758  ProtectedObject p(stem);
759  /* processing to decompose the name */
760  /* into its component parts */
761 
762  RexxQueue *tails = new_queue(); /* get a new list for the tails */
763  ProtectedObject p1(tails);
764  position++; /* step past previous period */
765  length--; /* adjust the length */
766  /* direct access? */
767  if (direct == true)
768  {
769  /* extract the tail part */
770  RexxString *tail = variable_name->extract(position, length);
771  tails->push(tail); /* add to the tail piece list */
772  }
773  else
774  {
775  size_t endPosition = position + length;
776 
777  while (position < endPosition) /* process rest of the variable */
778  {
779  size_t start = position; /* save the start position */
780  /* scan for the next period */
781  while (position < endPosition && variable_name->getChar(position) != '.')
782  {
783  position++; /* step to the next character */
784  }
785  /* extract the tail part */
786  RexxString *tail = variable_name->extract(start, position - start);
787  /* have a null tail piece or */
788  /* section begin with a digit? */
789  /* ASCII '0' to '9' to recognize a digit */
790 
791  RexxObject *tailPart;
792  if (tail->getLength() == 0 || (tail->getChar(0) >= '0' && tail->getChar(0) <= '9'))
793  {
794  tailPart = (RexxObject *)tail; /* this is a literal piece */
795  }
796  else
797  {
798  /* create a new variable retriever */
799  tailPart = (RexxObject *)new RexxParseVariable(tail, 0);
800  }
801  tails->push(tailPart); /* add to the tail piece list */
802  position++; /* step past previous period */
803  }
804  /* have a trailing period? */
805  if (variable_name->getChar(position - 1) == '.')
806  {
807  tails->push(OREF_NULLSTRING); /* add to the tail piece list */
808  }
809  }
810  /* create and return a new compound */
811  return(RexxObject *)new (tails->getSize()) RexxCompoundVariable(variable_name, stem, 0, tails, tails->getSize());
812 }
@ T_VariableDictionary
RexxDirectory * new_directory()
RexxList * new_list()
Definition: ListClass.hpp:147
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
#define OREF_NULL
Definition: RexxCore.h:61
const int MAX_SYMBOL_LENGTH
Definition: RexxCore.h:77
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheNilObject
Definition: RexxCore.h:191
size_t HashLink
RexxTable * new_hashCollection(size_t s, size_t s2, size_t t)
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#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)
#define DEFAULT_OBJECT_DICTIONARY_SIZE
RexxVariableDictionary * new_variableDictionary(size_t s)
#define STRING_LITERAL
Definition: StringClass.hpp:57
#define STRING_NUMERIC
Definition: StringClass.hpp:59
#define STRING_NAME
Definition: StringClass.hpp:60
#define STRING_COMPOUND_NAME
Definition: StringClass.hpp:56
#define STRING_STEM
Definition: StringClass.hpp:55
#define STRING_LITERAL_DOT
Definition: StringClass.hpp:58
#define STRING_BAD_VARIABLE
Definition: StringClass.hpp:54
void checkDeadLock(RexxActivity *)
RexxObject * put(RexxObject *, RexxString *)
size_t mainSlotsSize()
RexxHashTable * stringPut(RexxObject *value, RexxString *key)
RexxObject * index(HashLink position)
size_t totalSlotsSize()
HashLink first()
RexxHashTable * stringAdd(RexxObject *value, RexxString *key)
RexxObject * value(HashLink position)
HashLink next(HashLink position)
RexxObject * replace(RexxObject *value, HashLink position)
virtual RexxObject * copy()
RexxBehaviour * behaviour
size_t getSize()
Definition: ListClass.hpp:126
RexxObject * removeFirst()
Definition: ListClass.hpp:109
void addLast(RexxObject *value)
Definition: ListClass.cpp:455
void setNextVariable(size_t value)
RexxObject * copy()
void push(RexxObject *obj)
Definition: QueueClass.hpp:81
static bool isSymbolCharacter(codepoint_t ch)
Definition: SourceFile.hpp:387
static int translateChar(codepoint_t ch)
Definition: SourceFile.hpp:394
RexxCompoundElement * getCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:581
RexxObject * getCompoundVariableRealValue(RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:821
void dropCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:641
void setCompoundVariable(RexxCompoundTail *name, RexxObject *value)
Definition: StemClass.cpp:681
RexxObject * evaluateCompoundVariableValue(RexxActivation *context, RexxString *stemVariableName, RexxCompoundTail *resolved_tail)
Definition: StemClass.cpp:719
size_t getLength()
RexxString * extract(size_t offset, size_t sublength)
RexxString * upper()
char getChar(size_t p)
void setNextDictionary(RexxVariableDictionary *next)
void add(RexxVariable *, RexxString *)
RexxObject * realValue(RexxString *name)
RexxVariable * resolveVariable(RexxString *name)
RexxStem * getStem(RexxString *stemName)
RexxVariable * createVariable(RexxString *stemName)
static RexxVariableBase * getVariableRetriever(RexxString *variable)
static RexxObject * buildCompoundVariable(RexxString *variable_name, bool direct)
void dropStemVariable(RexxString *)
RexxVariable * getVariable(RexxString *name)
void set(RexxString *, RexxObject *)
void setCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount, RexxObject *value)
RexxObject * getCompoundVariableValue(RexxString *stemName, RexxObject **tail, size_t tailCount)
RexxCompoundElement * getCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount)
void flatten(RexxEnvelope *envelope)
static RexxVariableBase * getDirectVariableRetriever(RexxString *variable)
RexxObject * getCompoundVariableRealValue(RexxString *stem, RexxObject **tail, size_t tailCount)
RexxVariableDictionary * next
static RexxVariableDictionary * newInstance(size_t)
RexxVariable * nextVariable(RexxNativeActivation *)
RexxVariable * createStemVariable(RexxString *stemName)
void dropCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount)
RexxObject * realStemValue(RexxString *stemName)
void put(RexxVariable *, RexxString *)
void set(RexxObject *value)
RexxString * getName()
RexxObject * getVariableValue()
int type
Definition: cmdparse.cpp:1888
ssize_t codepoint_t
Definition: rexx.h:232
#define SIZE_MAX