SelectInstruction.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 Select Parse Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "RexxActivity.hpp"
47 #include "RexxActivation.hpp"
48 #include "QueueClass.hpp"
49 #include "IntegerClass.hpp"
50 #include "SelectInstruction.hpp"
51 #include "EndInstruction.hpp"
52 #include "IfInstruction.hpp"
53 #include "OtherwiseInstruction.hpp"
54 #include "DoBlock.hpp"
55 
56 
58 /******************************************************************************/
59 /* Function: Initialize a SELECT instruction object */
60 /******************************************************************************/
61 {
62  /* create a list of WHEN targets */
63  OrefSet(this, this->when_list, new_queue());
64  // set the label name
65  OrefSet(this, this->label, name);
66 }
67 
68 
69 void RexxInstructionSelect::live(size_t liveMark)
70 /******************************************************************************/
71 /* Function: Normal garbage collection live marking */
72 /******************************************************************************/
73 {
74  memory_mark(this->nextInstruction); /* must be first one marked */
75  memory_mark(this->when_list);
76  memory_mark(this->end);
77  memory_mark(this->otherwise);
78  memory_mark(this->label);
79 }
80 
82 /******************************************************************************/
83 /* Function: Generalized object marking */
84 /******************************************************************************/
85 {
86  /* must be first one marked */
89  memory_mark_general(this->end);
92 }
93 
95 /******************************************************************************/
96 /* Function: Flatten an object */
97 /******************************************************************************/
98 {
100 
101  flatten_reference(newThis->nextInstruction, envelope);
102  flatten_reference(newThis->when_list, envelope);
103  flatten_reference(newThis->end, envelope);
104  flatten_reference(newThis->otherwise, envelope);
105  flatten_reference(newThis->label, envelope);
106 
108 }
109 
110 
111 
112 /**
113  * Return the associated label.
114  *
115  * @return The select label (which might be OREF_NULL)
116  */
118 {
119  return label;
120 }
121 
122 
123 /**
124  * Tests to see if this is a loop instruction.
125  *
126  * @return True if this is a repetitive loop, false otherwise.
127  */
129 {
130  return false;
131 }
132 
133 
134 /**
135  * Check for a label match on a block instruction.
136  *
137  * @param name The target block name.
138  *
139  * @return True if this is a name match, false otherwise.
140  */
142 {
143  return label == name;
144 }
145 
146 
148  RexxActivation *context, /* current execution context */
149  RexxDoBlock *doblock ) /* active do block */
150 /******************************************************************************/
151 /* Function: Terminate an active do loop */
152 /******************************************************************************/
153 {
154  /* perform cleanup */
155  context->terminateBlock(doblock->getIndent());
156  /* jump to the loop end */
157  context->setNext(this->end->nextInstruction);
158 }
159 
160 
162  RexxActivation *context, /* current activation context */
163  RexxExpressionStack *stack ) /* evaluation stack */
164 /****************************************************************************/
165 /* Function: Execute a REXX SELECT instruction */
166 /****************************************************************************/
167 {
168  RexxDoBlock *doblock = OREF_NULL;
169 
170  context->traceInstruction(this); /* trace if necessary */
171  /* create an active DO block */
172  doblock = new RexxDoBlock (this, context->getIndent());
173  context->newDo(doblock); /* set the new block */
174  /* do debug pause if necessary */
175 
176  /* have to re-execute? */
177  if (context->conditionalPauseInstruction())
178  {
179  this->terminate(context, doblock); /* cause termination cleanup */
180  }
181 }
182 
183 
185  RexxInstructionEnd *partner, /* end to match up */
186  RexxSource *source ) /* parsed source file (for errors) */
187 /******************************************************************************/
188 /* Function: Match an END instruction up with a SELECT */
189 /******************************************************************************/
190 {
191  RexxInstructionIf *when; /* target WHEN clause */
192  SourceLocation location; /* location of the end */
193  size_t lineNum; /* Instruction line number */
194 
195  location = partner->getLocation(); /* get location of END instruction */
196  lineNum = this->getLineNumber(); /* get the instruction line number */
197 
198  RexxString *name = partner->name; /* get then END name */
199  if (name != OREF_NULL) /* was a name given? */
200  {
201  RexxString *myLabel = getLabel();
202  if (myLabel == OREF_NULL) /* name given on non-control form? */
203  {
204  source->error(Error_Unexpected_end_select_nolabel, location, new_array(partner->name, new_integer(lineNum)));
205  }
206  else if (name != myLabel) /* not the same name? */
207  {
208  source->error(Error_Unexpected_end_select, location, new_array(name, myLabel, new_integer(lineNum)));
209  }
210  }
211  /* misplaced END instruction */
212  OrefSet(this, this->end, partner); /* match up with the END instruction */
213  /* get first item off of WHEN list */
214  when = (RexxInstructionIf *)(this->when_list->pullRexx());
215  /* nothing there? */
216  if (when == (RexxInstructionIf *)TheNilObject)
217  {
218  location = this->getLocation(); /* get the location info */
219  /* need at least one WHEN here */
220  source->error(Error_When_expected_when, location, new_array(new_integer(lineNum)));
221  }
222  /* link up each WHEN with the END */
223  while (when != (RexxInstructionIf *)TheNilObject)
224  {
225  /* hook up with the partner END */
226  when->fixWhen((RexxInstructionEndIf *)partner);
227  /* get the next list item */
228  when = (RexxInstructionIf *)(this->when_list->pullRexx());
229  }
230  /* get rid of the lists */
231  OrefSet(this, this->when_list, OREF_NULL);
232  if (this->otherwise != OREF_NULL) /* an other wise block? */
233  {
234  // for the END terminator on an OTHERWISE, we need to see if this
235  // select has a label. If it does, this needs special handling.
236  if (getLabel() == OREF_NULL)
237  {
238  partner->setStyle(OTHERWISE_BLOCK);
239  }
240  else
241  {
243  }
244  }
245  else
246  {
247  // the SELECT style will raise an error if hit, since it means
248  // there is not OTHERWISE clause. This doesn't matter if there
249  // is a label or not.
250  partner->setStyle(SELECT_BLOCK);
251  }
252 }
253 
254 
256  RexxInstructionIf *when) /* associated WHEN instruction */
257 /******************************************************************************/
258 /* Function: Associate a WHEN instruction with its surrounding SELECT */
259 /******************************************************************************/
260 {
261  /* add to the WHEN list queue */
262  this->when_list->pushRexx((RexxObject *)when);
263 }
264 
266  RexxInstructionOtherwise *_otherwise) /* partner OTHERWISE for SELECT */
267 /******************************************************************************/
268 /* Function: Associate an OTHERSISE instruction with its surrounding SELECT */
269 /******************************************************************************/
270 {
271  /* save the otherwise partner */
272  OrefSet(this, this->otherwise, _otherwise);
273 }
274 
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
#define SELECT_BLOCK
#define OTHERWISE_BLOCK
#define LABELED_OTHERWISE_BLOCK
RexxInteger * new_integer(wholenumber_t v)
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
#define OREF_NULL
Definition: RexxCore.h:60
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheNilObject
Definition: RexxCore.h:181
#define Error_When_expected_when
#define Error_Unexpected_end_select
#define Error_Unexpected_end_select_nolabel
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:493
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
#define cleanUpFlatten
Definition: RexxMemory.hpp:479
#define setUpFlatten(type)
Definition: RexxMemory.hpp:473
int conditionalPauseInstruction()
void newDo(RexxDoBlock *block)
void traceInstruction(RexxInstruction *v)
void terminateBlock(size_t _indent)
void setNext(RexxInstruction *v)
size_t getIndent()
Definition: DoBlock.hpp:73
void setStyle(size_t type)
const SourceLocation & getLocation()
RexxInstruction * nextInstruction
void fixWhen(RexxInstructionEndIf *partner)
RexxInstructionOtherwise * otherwise
bool isLabel(RexxString *name)
void terminate(RexxActivation *, RexxDoBlock *)
void flatten(RexxEnvelope *)
void liveGeneral(int reason)
RexxInstructionEnd * end
RexxInstructionSelect(RexxString *)
void execute(RexxActivation *, RexxExpressionStack *)
void setOtherwise(RexxInstructionOtherwise *)
void matchEnd(RexxInstructionEnd *, RexxSource *)
void addWhen(RexxInstructionIf *)
RexxObject * pushRexx(RexxObject *)
Definition: QueueClass.cpp:78
RexxObject * pullRexx()
Definition: QueueClass.cpp:64
void error(int)