ExpressionCompoundVariable.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 Translator */
40 /* */
41 /* Primitive Translator Expression Parsing Compound Variable Reference Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "QueueClass.hpp"
48 #include "StemClass.hpp"
50 #include "RexxActivation.hpp"
51 #include "RexxActivity.hpp"
53 #include "ExpressionVariable.hpp"
54 #include "RexxVariable.hpp"
55 #include "ProtectedObject.hpp"
56 #include "RexxCompoundTail.hpp"
57 
59  RexxString * _compoundName,
60  RexxString * _stemName, /* stem retriever */
61  size_t stemIndex, /* stem lookaside index */
62  RexxQueue * tailList, /* list of tails */
63  size_t TailCount) /* count of tails */
64 /******************************************************************************/
65 /* Function: Complete compound variable initialization */
66 /******************************************************************************/
67 {
68  this->tailCount= TailCount; /* set the count (and hash value) */
69  OrefSet(this, this->compoundName, _compoundName);
70  OrefSet(this, this->stemName, _stemName); /* save the associate value */
71  this->index = stemIndex; /* set the stem index */
72 
73  while (TailCount > 0) /* loop through the variable list */
74  {
75  /* copying each variable */
76  OrefSet(this, this->tails[--TailCount], tailList->pop());
77  }
78 }
79 
81  RexxString * variable_name, /* full variable name of compound */
82  bool direct ) /* this is direct access */
83 /******************************************************************************/
84 /* Function: Build a dynamically created compound variable */
85 /******************************************************************************/
86 {
87  RexxString * stem; /* stem part of compound variable */
88  RexxString * tail; /* tail section string value */
89  RexxQueue * tails; /* tail elements */
90  RexxObject * tailPart; /* tail element retriever */
91  size_t position; /* scan position within compound name*/
92  size_t start; /* starting scan position */
93  size_t length; /* length of tail section */
94 
95  length = variable_name->getLength(); /* get the string length */
96  position = 0; /* start scanning at first character */
97  /* scan to the first period */
98  while (variable_name->getChar(position) != '.')
99  {
100  position++; /* step to the next character */
101  length--; /* reduce the length also */
102  }
103  /* extract the stem part */
104  stem = variable_name->extract(0, position + 1);
105  ProtectedObject p1(stem);
106  /* processing to decompose the name */
107  /* into its component parts */
108 
109  tails = new_queue(); /* get a new list for the tails */
110  ProtectedObject p2(tails);
111  position++; /* step past previous period */
112  length--; /* adjust the length */
113  if (direct == true) /* direct access? */
114  {
115  /* extract the tail part */
116  tail = variable_name->extract(position, length);
117  tails->push(tail); /* add to the tail piece list */
118  }
119  else
120  {
121  while (length > 0) /* process rest of the variable */
122  {
123  start = position; /* save the start position */
124  /* scan for the next period */
125  while (length > 0 && variable_name->getChar(position) != '.')
126  {
127  position++; /* step to the next character */
128  length--; /* reduce the length also */
129  }
130  /* extract the tail part */
131  tail = variable_name->extract(start, position - start);
132  /* have a null tail piece or */
133  /* section begin with a digit? */
134  /* CHM - defect 87: change index start to 0 and compare for range */
135  /* ASCII '0' to '9' to recognize a digit */
136  if (tail->getLength() == 0 || (tail->getChar(0) >= '0' && tail->getChar(0) <= '9'))
137  {
138  tailPart = (RexxObject *)tail; /* this is a literal piece */
139  }
140  else
141  {
142  /* create a new variable retriever */
143  tailPart = (RexxObject *)new RexxParseVariable(tail, 0);
144  }
145  tails->push(tailPart); /* add to the tail piece list */
146  position++; /* step past previous period */
147  length--; /* adjust the length */
148  }
149  /* have a trailing period? */
150  if (variable_name->getChar(position - 1) == '.')
151  {
152  tails->push(OREF_NULLSTRING); /* add to the tail piece list */
153  }
154  }
155  /* create and return a new compound */
156  return(RexxObject *)new (tails->getSize()) RexxCompoundVariable(variable_name, stem, 0, tails, tails->getSize());
157 }
158 
159 void RexxCompoundVariable::live(size_t liveMark)
160 /******************************************************************************/
161 /* Function: Normal garbage collection live marking */
162 /******************************************************************************/
163 {
164  size_t i; /* loop counter */
165  size_t count; /* argument count */
166 
167  for (i = 0, count = this->tailCount; i < count; i++)
168  {
169  memory_mark(this->tails[i]);
170  }
171  memory_mark(this->compoundName);
172  memory_mark(this->stemName);
173 }
174 
176 /******************************************************************************/
177 /* Function: Generalized object marking */
178 /******************************************************************************/
179 {
180  size_t i; /* loop counter */
181  size_t count; /* argument count */
182 
183  for (i = 0, count = this->tailCount; i < count; i++)
184  {
185  memory_mark_general(this->tails[i]);
186  }
189 }
190 
192 /******************************************************************************/
193 /* Function: Flatten an object */
194 /******************************************************************************/
195 {
196  size_t i; /* loop counter */
197  size_t count; /* argument count */
198 
200 
201  flatten_reference(newThis->compoundName, envelope);
202  flatten_reference(newThis->stemName, envelope);
203  for (i = 0, count = this->tailCount; i < count; i++)
204  {
205  flatten_reference(newThis->tails[i], envelope);
206  }
207 
209 }
210 
212  RexxActivation *context, /* current activation context */
213  RexxExpressionStack *stack ) /* evaluation stack */
214 /******************************************************************************/
215 /* Function: Evaluate a REXX compound variable */
216 /******************************************************************************/
217 {
218  /* and ask it for the value */
220 
221  stack->push(value); /* place on the evaluation stack */
222  return value; /* return the located variable */
223 }
224 
226  RexxVariableDictionary *dictionary) /* current activation dictionary */
227 /******************************************************************************/
228 /* Function: Direct value retrieve of a compound variable */
229 /******************************************************************************/
230 {
231  /* resolve the tail element */
232  return dictionary->getCompoundVariableValue(stemName, &tails[0], tailCount);
233 }
234 
236  RexxActivation *context) /* current activation dictionary */
237 /******************************************************************************/
238 /* Function: Direct value retrieve of a compound variable */
239 /******************************************************************************/
240 {
241  /* resolve the tail element */
243 }
244 
245 /**
246  * Retrieve an object variable value, returning OREF_NULL if
247  * the variable does not have a value.
248  *
249  * @param dictionary The source variable dictionary.
250  *
251  * @return The variable value, or OREF_NULL if the variable is not
252  * assigned.
253  */
255 {
256  /* resolve the tail element */
257  return dictionary->getCompoundVariableRealValue(stemName, &tails[0], tailCount);
258 }
259 
260 
261 /**
262  * Get the value of a variable without applying a default value
263  * to it. Used in the apis so the caller can more easily
264  * detect an uninitialized variable.
265  *
266  * @param context The current context.
267  *
268  * @return The value of the variable. Returns OREF_NULL if the variable
269  * has not been assigned a value.
270  */
272 {
273  /* resolve the tail element */
275 }
276 
277 
279  RexxActivation *context, /* current activation context */
280  RexxObject *value ) /* new value to assign */
281 /******************************************************************************/
282 /* Function: Assign a new value to a compound variable */
283 /******************************************************************************/
284 {
285  /* the dictionary manages all of these details */
286  context->setLocalCompoundVariable(stemName, index, &tails[0], tailCount, value);
287 }
288 
289 
291  RexxVariableDictionary *dictionary, /* an object variable dictionary */
292  RexxObject *value ) /* new value to assign */
293 /******************************************************************************/
294 /* Function: Assign a new value to a compound variable */
295 /******************************************************************************/
296 {
297  /* the dictionary manages all of these details */
298  dictionary->setCompoundVariable(stemName, &tails[0], tailCount, value);
299 }
300 
301 
303  RexxActivation *context) /* current execution context */
304 /******************************************************************************/
305 /* Function: Check to see if a compound variable exists in a directory */
306 /******************************************************************************/
307 {
308  /* retrieve the variable value, and */
309  /* see it really exists */
310  return context->localCompoundVariableExists(stemName, index, &tails[0], tailCount);
311 }
312 
314  RexxActivation *context, /* current activation context */
315  RexxExpressionStack *stack, /* current evaluation stack */
316  RexxObject *value ) /* new value to assign */
317 /******************************************************************************/
318 /* Function: Assign a value to a compound variable */
319 /******************************************************************************/
320 {
321  /* the context manages the assignment details */
323 }
324 
326  RexxActivation *context) /* current activation context */
327 /******************************************************************************/
328 /* Function: Drop a compound variable */
329 /******************************************************************************/
330 {
331  /* set the compound value */
333 }
334 
335 /**
336  * Drop a variable that's directly in a variable dictionary.
337  *
338  * @param dictionary The target dictionary
339  */
341 {
342  /* the dictionary manages all of these details */
343  dictionary->dropCompoundVariable(stemName, &tails[0], tailCount);
344 }
345 
346 
348  RexxActivation *context, /* current activation context */
349  RexxActivation *parent, /* the parent activation context */
350  RexxExpressionStack *stack) /* current evaluation stack */
351 /******************************************************************************/
352 /* Function: Expose a compound variable */
353 /******************************************************************************/
354 {
355  /* first get (and possible create) the compound variable in the */
356  /* parent context. */
358  /* get the stem index from the current level. This may end up */
359  /* creating the stem that holds the exposed value. */
360  RexxStem *stem_table = context->getLocalStem(stemName, index);
361  /* have the stem expose this */
362  stem_table->expose(variable);
363  /* trace resolved compound name */
364  context->traceCompoundName(stemName, (RexxObject **)&tails[0], tailCount, variable->getName());
365 }
366 
367 
369  RexxActivation *context, /* current activation context */
370  RexxExpressionStack *stack, /* current evaluation stack */
371  /* variable scope we're exposing from*/
372  RexxVariableDictionary *object_dictionary)
373 /******************************************************************************/
374 /* Function: Expose a compound variable */
375 /******************************************************************************/
376 {
377  /* get the stem in the source dictionary */
378  RexxStem *source_stem = object_dictionary->getStem(stemName);
379  /* new tail for compound */
380  RexxCompoundTail resolved_tail(context, &tails[0], tailCount);
381  /* first get (and possible create) the compound variable in the */
382  /* object context. */
383  RexxCompoundElement *variable = source_stem->exposeCompoundVariable(&resolved_tail);
384  /* get the stem index from the current level. This may end up */
385  /* creating the stem that holds the exposed value. */
386  RexxStem *stem_table = context->getLocalStem(stemName, index);
387  /* have the stem expose this */
388  stem_table->expose(variable);
389  /* tracing intermediate values? */
390  if (context->tracingIntermediates()) {
391  /* trace resolved compound name */
392  context->traceCompoundName(stemName, (RexxObject **)&tails[0], tailCount, variable->getName());
393  }
394 }
395 
396 
398  RexxActivation *context ) /* current activation context */
399 /******************************************************************************/
400 /* Function: Set a guard wait in a compound variable */
401 /******************************************************************************/
402 {
403  /* get the variable item */
405  variable->inform(ActivityManager::currentActivity); /* mark the variable entry */
406 }
407 
409  RexxActivation *context ) /* current activation context */
410 /******************************************************************************/
411 /* Function: Clear a guard wait on a compound variable */
412 /******************************************************************************/
413 {
414  /* get the variable item */
416  variable->uninform(ActivityManager::currentActivity); /* mark the variable entry */
417 }
418 
419 void * RexxCompoundVariable::operator new(size_t size,
420  size_t tailCount) /* count of tails */
421 /******************************************************************************/
422 /* Function: Create a new compound variable object */
423 /******************************************************************************/
424 {
425  if (tailCount == 0)
426  {
427  // this object is normal sized, minus the dummy tail element
428  return new_object(size - sizeof(RexxObject *), T_CompoundVariableTerm);
429  }
430  else
431  {
432  /* Get new object */
433  return new_object(size + ((tailCount - 1) * sizeof(RexxObject *)), T_CompoundVariableTerm);
434  }
435 }
436 
438  RexxActivation *context) /* current activation context */
439 /******************************************************************************/
440 /* Function: Translate to upper case the contents of a variable object */
441 /******************************************************************************/
442 {
443  RexxObject *value = this->getValue(context);
444  RexxString *string = REQUEST_STRING(value);
445  ProtectedObject p(string);
446  this->set(context, string->upper());
447 }
@ T_CompoundVariableTerm
RexxObject * build(RexxString *variable_name, bool direct)
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:295
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
static RexxActivity *volatile currentActivity
RexxObject * getLocalCompoundVariableRealValue(RexxString *localstem, size_t index, RexxObject **tail, size_t tailCount)
RexxCompoundElement * getLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
void traceCompoundName(RexxString *stemVar, RexxObject **tails, size_t tailCount, RexxCompoundTail *tail)
RexxStem * getLocalStem(RexxString *name, size_t index)
void assignLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
void dropLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
RexxObject * evaluateLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
RexxCompoundElement * exposeLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
bool localCompoundVariableExists(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
RexxObject * getLocalCompoundVariableValue(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount)
void setLocalCompoundVariable(RexxString *stemName, size_t index, RexxObject **tail, size_t tailCount, RexxObject *value)
bool tracingIntermediates()
void procedureExpose(RexxActivation *, RexxActivation *, RexxExpressionStack *)
void expose(RexxActivation *, RexxExpressionStack *, RexxVariableDictionary *)
RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
RexxCompoundVariable(RexxString *, RexxString *, size_t, RexxQueue *, size_t)
void clearGuard(RexxActivation *)
void setGuard(RexxActivation *)
void set(RexxActivation *, RexxObject *)
RexxObject * getRealValue(RexxVariableDictionary *)
RexxObject * getValue(RexxActivation *context)
void assign(RexxActivation *, RexxExpressionStack *, RexxObject *)
void push(RexxObject *value)
size_t getSize()
Definition: ListClass.hpp:126
void push(RexxObject *obj)
Definition: QueueClass.hpp:81
RexxObject * pop()
Definition: QueueClass.hpp:80
RexxCompoundElement * exposeCompoundVariable(RexxCompoundTail *name)
Definition: StemClass.cpp:593
void expose(RexxCompoundElement *variable)
Definition: StemClass.cpp:895
size_t getLength()
RexxString * extract(size_t offset, size_t sublength)
RexxString * upper()
char getChar(size_t p)
RexxStem * getStem(RexxString *stemName)
void setCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount, RexxObject *value)
RexxObject * getCompoundVariableValue(RexxString *stemName, RexxObject **tail, size_t tailCount)
RexxObject * getCompoundVariableRealValue(RexxString *stem, RexxObject **tail, size_t tailCount)
void dropCompoundVariable(RexxString *stemName, RexxObject **tail, size_t tailCount)
void uninform(RexxActivity *)
RexxString * getName()
void inform(RexxActivity *)