CallInstruction.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 Call Parse Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "DirectoryClass.hpp"
48 #include "ArrayClass.hpp"
50 #include "RexxActivation.hpp"
51 #include "RexxActivity.hpp"
52 #include "CallInstruction.hpp"
53 #include "SourceFile.hpp"
54 #include "ProtectedObject.hpp"
55 
57  RexxObject *_name, /* CALL name */
58  RexxString *_condition, /* CALL ON/OFF condition */
59  size_t argCount, /* count of positional arguments */
60  RexxQueue *argList, /* call positional arguments */
61  size_t namedArgCount, /* count of named arguments */
62  RexxQueue *namedArgList, /* call named arguments */
63  size_t flags, /* CALL flags */
64  size_t builtin_index) /* builtin routine index */
65 /******************************************************************************/
66 /* Function: Complete CALL instruction object */
67 /******************************************************************************/
68 {
69  /* set the name */
70  OrefSet(this, this->name, (RexxString *)_name);
71  /* and the condition */
72  OrefSet(this, this->condition, _condition);
73  instructionFlags = (uint16_t)flags; /* copy the flags */
74  builtinIndex = (uint16_t)builtin_index; /* and the builtin function index */
75  /* no arguments */
76  argumentCount = (uint16_t)argCount;
77  while (argCount > 0) { /* now copy the argument pointers */
78  /* in reverse order */
79  OrefSet(this, this->arguments[--argCount], argList->pop());
80  }
81 
82  // The named arguments are stored after the positional arguments
83  // Each named argument has 2 entries : name, expression
84  // namedArgumentCount = the number of named arguments
85  namedArgumentCount = (uint16_t)namedArgCount;
86  while (namedArgCount > 0) {
87  --namedArgCount;
88  OrefSet(this, this->arguments[argumentCount + (2 * namedArgCount) + 1], namedArgList->pop()); // expression
89  OrefSet(this, this->arguments[argumentCount + (2 * namedArgCount) + 0], namedArgList->pop()); // name
90  }
91 }
92 
93 void RexxInstructionCall::live(size_t liveMark)
94 /******************************************************************************/
95 /* Function: Normal garbage collection live marking */
96 /******************************************************************************/
97 {
98  size_t i; /* loop counter */
99  size_t count; /* argument count */
100 
101  memory_mark(this->nextInstruction); /* must be first one marked */
102  memory_mark(this->name);
103  memory_mark(this->target);
104  memory_mark(this->condition);
105  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
106  {
107  memory_mark(this->arguments[i]);
108  }
109 }
110 
112 /******************************************************************************/
113 /* Function: Generalized object marking */
114 /******************************************************************************/
115 {
116  size_t i; /* loop counter */
117  size_t count; /* argument count */
118 
119  /* must be first one marked */
121  memory_mark_general(this->name);
124  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
125  {
126  memory_mark_general(this->arguments[i]);
127  }
128 }
129 
131 /******************************************************************************/
132 /* Function: Flatten an object */
133 /******************************************************************************/
134 {
135  size_t i; /* loop counter */
136  size_t count; /* argument count */
137 
139 
140  flatten_reference(newThis->nextInstruction, envelope);
141  flatten_reference(newThis->name, envelope);
142  flatten_reference(newThis->target, envelope);
143  flatten_reference(newThis->condition, envelope);
144  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
145  flatten_reference(newThis->arguments[i], envelope);
146 
148 }
149 
151  RexxDirectory *labels) /* table of program labels */
152 /******************************************************************************/
153 /* Function: Resolve a CALL instruction target */
154 /******************************************************************************/
155 {
156  if (this->name == OREF_NULL) /* not a name target form? */
157  return; /* just return */
158  if (instructionFlags&call_dynamic) { // can't resolve now
159  return; //
160  }
161  if (!(instructionFlags&call_nointernal)) { /* internal routines allowed? */
162  if (labels != OREF_NULL) /* have a labels table? */
163  /* check the label table */
164  OrefSet(this, this->target, (RexxInstruction *)labels->at((RexxString *)this->name));
165  instructionFlags |= call_internal; /* this is an internal call */
166  }
167  if (this->target == OREF_NULL) { /* not found yet? */
168  /* have a builtin function? */
169  if (builtinIndex != NO_BUILTIN) {
170  instructionFlags |= call_builtin; /* this is a builtin function */
171  /* cast off the routine name */
172  // OrefSet(this, this->name, OREF_NULL); // jlf: I need this name when searching an overriding routine
173  }
174  else
175  instructionFlags |= call_external; /* have an external routine */
176  }
177 }
178 
180  RexxActivation *context, /* current activation context */
181  RexxExpressionStack *stack) /* evaluation stack */
182 /******************************************************************************/
183 /* Function: Execute a REXX CALL instruction */
184 /******************************************************************************/
185 {
186  int type; /* type of call */
187  size_t builtin_index; /* builtin function index */
188  ProtectedObject result; /* returned result */
189  RexxInstruction *_target; /* resolved call target */
190  RexxString *_name; /* resolved function name */
191  RexxDirectory *labels; /* labels table */
192 
193  ProtectedObject p_name;
194 
195  ActivityManager::currentActivity->checkStackSpace(); /* have enough stack space? */
196  context->traceInstruction(this); /* trace if necessary */
197  if (this->condition != OREF_NULL) /* is this the ON/OFF form? */
198  {
199  if (instructionFlags&call_on_off) /* ON form? */
200  {
201  /* turn on the trap */
202  context->trapOn(this->condition, (RexxInstructionCallBase *)this);
203  }
204  else
205  {
206  /* turn off the trap */
207  context->trapOff(this->condition);
208  }
209  }
210  else /* normal form of CALL */
211  {
212  if (instructionFlags&call_dynamic) /* dynamic form of call? */
213  {
214  /* evaluate the variable */
215  result = this->name->evaluate(context, stack);
216  stack->toss(); /* toss the top item */
217  _name = REQUEST_STRING(result); /* force to string form */
218  p_name = _name;
219  context->traceResult(_name); /* trace if necessary */
220  /* resolve potential builtins */
221  builtin_index = RexxSource::resolveBuiltin(_name);
222  _target = OREF_NULL; /* clear out the target */
223  labels = context->getLabels(); /* get the labels table */
224  if (labels != OREF_NULL) /* have labels in the program? */
225  {
226  /* look up label and go to normal */
227  /* signal processing */
228  _target = (RexxInstruction *)(labels->at(_name));
229  }
230  if (_target != OREF_NULL) /* found one? */
231  {
232  type = call_internal; /* have an internal call */
233  }
234  /* have a builtin by this name? */
235  else if (builtin_index != NO_BUILTIN)
236  {
237  type = call_builtin; /* set for a builtin */
238  }
239  else /* must be external */
240  {
241  type = call_external; /* set as so */
242  }
243  }
244  else /* set up for a normal call */
245  {
246  _target = this->target; /* copy the target */
247  _name = (RexxString *)this->name; /* the name value */
248  /* and the builtin index */
249  builtin_index = builtinIndex;
250  type = instructionFlags&call_type_mask; /* just copy the type info */
251  }
252 
253  // Positional arguments
254  for (size_t i = 0; i < argumentCount; i++) /* loop through the argument list */
255  {
256  /* real argument? */
257  if (this->arguments[i] != OREF_NULL)
258  {
259  /* evaluate the expression */
260  RexxObject *argResult = this->arguments[i]->evaluate(context, stack);
261 
262  /* trace if necessary */
263  context->traceIntermediate(argResult, TRACE_PREFIX_ARGUMENT);
264  }
265  else
266  {
267  stack->push(OREF_NULL); /* push an non-existent argument */
268  /* trace if necessary */
269  context->traceIntermediate(OREF_NULLSTRING, TRACE_PREFIX_ARGUMENT);
270  }
271  }
272 
273  // Named arguments
274  for (size_t i = argumentCount; i < argumentCount + (2 * namedArgumentCount); i+=2)
275  {
276  // Argument name: string literal
277  RexxObject *name = this->arguments[i];
278  stack->push(name); // a string
280 
281  // Argument expression
282  RexxObject *argResult = this->arguments[i+1]->evaluate(context, stack);
283  context->traceIntermediate(argResult, TRACE_PREFIX_ARGUMENT);
284  }
285 
286  // More easy to work with an array of arguments (address of the first argument) than a stack of arguments (address of the last argument).
287  RexxObject **_arguments = stack->arguments(argumentCount + (2 * namedArgumentCount));
288 
289  switch (type) /* process various call types */
290  {
291 
292  case call_internal: /* need to process internal routine */
293  /* go process the internal call */
294  context->internalCall(_name, _target, _arguments, argumentCount, namedArgumentCount, result);
295  break;
296 
297  case call_builtin: /* builtin function call */
298  {
299  // Check the global functions directory
300  // this is actually considered part of the built-in functions, but these are
301  // written in ooRexx. The names are also case sensitive
302  RoutineClass *routine = OREF_NULL;
303  // Ignore the overridings if the flag call_nointernal is set
304  // _name should not be OREF_NULL, but just in case...
305  if (!(instructionFlags&call_nointernal) && _name != OREF_NULL) routine = (RoutineClass *)TheFunctionsDirectory->get(_name);
306  if (routine != OREF_NULL)
307  {
308  // call the user-defined routine
309  routine->call(ActivityManager::currentActivity, _name, _arguments, argumentCount, namedArgumentCount, OREF_SUBROUTINE, OREF_NULL, EXTERNALCALL, result);
310  }
311  else
312  {
313  /* call the function */
314  result = (*(RexxSource::builtinTable[builtin_index]))(context, _arguments, argumentCount, namedArgumentCount, stack);
315  }
316  }
317  break;
318 
319  case call_external: /* need to call externally */
320  /* go process the external call */
321  context->externalCall(_name, _arguments, argumentCount, namedArgumentCount, OREF_ROUTINENAME, result);
322  break;
323  }
324  if ((RexxObject *)result != OREF_NULL) /* result returned? */
325  {
326  /* set the RESULT variable to the */
327  /* message return value */
328  context->setLocalVariable(OREF_RESULT, VARIABLE_RESULT, (RexxObject *)result);
329  context->traceResult((RexxObject *)result); /* trace if necessary */
330  }
331  else /* drop the variable RESULT */
332  {
333  context->dropLocalVariable(OREF_RESULT, VARIABLE_RESULT);
334  }
335  }
336  context->pauseInstruction(); /* do debug pause if necessary */
337 }
338 
340  RexxActivation *context, /* current execution context */
341  RexxDirectory *conditionObj) /* associated condition object */
342 /******************************************************************************/
343 /* Function: Process a CALL ON trap */
344 /******************************************************************************/
345 {
346  ProtectedObject result;
347  context->trapDelay(this->condition); /* put trap into delay state */
348 
349  switch (instructionFlags&call_type_mask) /* process various call types */
350  {
351 
352  case call_internal: /* need to process internal routine */
353  /* go process the internal call */
354  context->internalCallTrap((RexxString *)this->name, this->target, conditionObj, result);
355  break;
356 
357  case call_builtin: /* builtin function call */
358  {
359  // Check the global functions directory
360  // this is actually considered part of the built-in functions, but these are
361  // written in ooRexx. The names are also case sensitive
362  RoutineClass *routine = OREF_NULL;
363  // Ignore the overridings if the flag call_nointernal is set
364  // _name should not be OREF_NULL, but just in case...
365  if (!(instructionFlags&call_nointernal) && this->name != OREF_NULL) RoutineClass *routine = (RoutineClass *)TheFunctionsDirectory->get((RexxString *)this->name);
366  if (routine != OREF_NULL)
367  {
368  // call the user-defined routine
369  routine->call(ActivityManager::currentActivity, (RexxString *)this->name, NULL, 0, 0, OREF_SUBROUTINE, OREF_NULL, EXTERNALCALL, result);
370  }
371  else
372  {
373  /* call the function */
374  (*(RexxSource::builtinTable[builtinIndex]))(context, NULL, 0, 0, context->getStack());
375  }
376  }
377  break;
378 
379  case call_external: /* need to call externally */
380  /* go process the externnl call */
381  context->externalCall((RexxString *)this->name, NULL, 0, 0, OREF_ROUTINENAME, result);
382  break;
383  }
384  /* restore the trap state */
385  context->trapUndelay(this->condition);
386 }
387 
#define EXTERNALCALL
@ TRACE_PREFIX_NAMED_ARGUMENT
@ TRACE_PREFIX_ARGUMENT
#define OREF_NULL
Definition: RexxCore.h:61
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:295
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheFunctionsDirectory
Definition: RexxCore.h:185
#define VARIABLE_RESULT
#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
#define NO_BUILTIN
Definition: Token.hpp:319
static RexxActivity *volatile currentActivity
RexxObject * externalCall(RexxString *, RexxObject **, size_t, size_t, RexxString *, ProtectedObject &)
RexxObject * internalCall(RexxString *, RexxInstruction *, RexxObject **, size_t, size_t, ProtectedObject &)
void trapOn(RexxString *, RexxInstructionCallBase *)
void setLocalVariable(RexxString *name, size_t index, RexxObject *value)
void traceResult(RexxObject *v)
void trapDelay(RexxString *)
RexxExpressionStack * getStack()
RexxObject * internalCallTrap(RexxString *, RexxInstruction *, RexxDirectory *, ProtectedObject &)
void traceInstruction(RexxInstruction *v)
void trapOff(RexxString *)
RexxDirectory * getLabels()
void trapUndelay(RexxString *)
void dropLocalVariable(RexxString *name, size_t index)
void traceIntermediate(RexxObject *v, int p)
void checkStackSpace()
RexxObject * at(RexxString *)
void push(RexxObject *value)
RexxObject ** arguments(size_t count)
RexxInstruction * target
RexxInstructionCall(RexxObject *, RexxString *, size_t, RexxQueue *, size_t, RexxQueue *, size_t, size_t)
void trap(RexxActivation *, RexxDirectory *)
void resolve(RexxDirectory *)
void execute(RexxActivation *, RexxExpressionStack *)
void flatten(RexxEnvelope *)
void liveGeneral(int reason)
RexxObject * arguments[1]
uint16_t instructionFlags
RexxInstruction * nextInstruction
virtual RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
RexxObject * pop()
Definition: QueueClass.hpp:80
static size_t resolveBuiltin(RexxString *)
static pbuiltin builtinTable[]
Definition: SourceFile.hpp:421
void call(RexxActivity *, RexxString *, RexxObject **, size_t, size_t, RexxString *, RexxString *, int, ProtectedObject &)
int type
Definition: cmdparse.cpp:1888
unsigned short uint16_t