InstructionParser.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 */
40 /* */
41 /* Primitive Translator Object Constructors */
42 /* */
43 /******************************************************************************/
44 
45 /******************************************************************************/
46 /* NOTE: Start of new methods for translator class objects. These new */
47 /* methods are segregated here to allow the actual translator to */
48 /* be easily decoupled from the rest of the interpreter. */
49 /* All of these methods are actually methods of the SOURCE */
50 /* class. They are in a seperate module for locational */
51 /* convenience. */
52 /******************************************************************************/
53 #include <ctype.h>
54 #include <string.h>
55 #include "RexxCore.h"
56 #include "StringClass.hpp"
57 #include "ArrayClass.hpp"
58 #include "RexxActivation.hpp"
59 #include "SourceFile.hpp" /* this is part of source */
60 
61 #include "ExpressionMessage.hpp"
62 #include "ExpressionOperator.hpp"
63 #include "RexxInstruction.hpp" /* base REXX instruction class */
64 
65 #include "AssignmentInstruction.hpp" /* keyword <expression> instructions */
66 #include "CommandInstruction.hpp"
67 #include "ExitInstruction.hpp"
68 #include "InterpretInstruction.hpp"
69 #include "OptionsInstruction.hpp"
70 #include "ReplyInstruction.hpp"
71 #include "ReturnInstruction.hpp"
72 #include "SayInstruction.hpp"
73 
74 #include "AddressInstruction.hpp" /* other instructions */
75 #include "DropInstruction.hpp"
76 #include "ExposeInstruction.hpp"
77 #include "ForwardInstruction.hpp"
78 #include "GuardInstruction.hpp"
79 #include "LabelInstruction.hpp"
80 #include "LeaveInstruction.hpp"
81 #include "MessageInstruction.hpp"
82 #include "NopInstruction.hpp"
83 #include "NumericInstruction.hpp"
84 #include "ProcedureInstruction.hpp"
85 #include "QueueInstruction.hpp"
86 #include "RaiseInstruction.hpp"
87 #include "TraceInstruction.hpp"
88 #include "UpperInstruction.hpp"
89 #include "UseStrictInstruction.hpp"
90 
91 #include "CallInstruction.hpp" /* call/signal instructions */
92 #include "SignalInstruction.hpp"
93 
94 #include "ParseInstruction.hpp" /* parse instruction and associates */
95 #include "ParseTarget.hpp"
96 #include "ParseTrigger.hpp"
97 
98 #include "ElseInstruction.hpp" /* control type instructions */
99 #include "EndIf.hpp"
100 #include "IfInstruction.hpp"
101 #include "ThenInstruction.hpp"
102 
103 #include "DoBlock.hpp" /* block type instructions */
104 #include "DoInstruction.hpp"
105 #include "EndInstruction.hpp"
106 #include "OtherwiseInstruction.hpp"
107 #include "SelectInstruction.hpp"
108 #include "ProtectedObject.hpp"
109 
110 
112 /****************************************************************************/
113 /* Function: Create a new ADDRESS translator object */
114 /****************************************************************************/
115 {
116  RexxObject *_expression = OREF_NULL; /* initialize import state variables */
117  RexxString *environment = OREF_NULL;
118  RexxObject *command = OREF_NULL;
119  RexxToken *token = nextReal(); /* get the next token */
120  if (!token->isEndOfClause())
121  { /* something other than a toggle? */
122  /* something other than a symbol or */
123  /* string?...implicit value form */
124  if (!token->isSymbolOrLiteral())
125  {
126  previousToken(); /* back up one token */
127  /* process the expression */
128  _expression = this->expression(TERM_EOC);
129  }
130  else
131  { /* have a constant address target */
132  /* may be value keyword, however... */
133  if (this->subKeyword(token) == SUBKEY_VALUE)
134  {
135  refineSubclass(token, IS_SUBKEY);
136  /* process the expression */
137  _expression = this->expression(TERM_EOC);
138  if (_expression == OREF_NULL) /* no expression? */
139  {
140  /* expression is required after value*/
142  }
143  }
144  else
145  { /* have a real constant target */
146  environment = token->value; /* get the actual name value */
147  token = nextReal(); /* get the next token */
148  /* have a command following name? */
149  if (!token->isEndOfClause())
150  {
151  previousToken(); /* step back a token */
152  /* process the expression */
153  command = this->expression(TERM_EOC);
154  }
155  }
156  } /* resolve the subkeyword */
157  }
158  /* create a new translator object */
159  RexxInstruction *newObject = new_instruction(ADDRESS, Address);
160  /* now complete this */
161  new ((void *)newObject) RexxInstructionAddress(_expression, environment, command);
162  return newObject; /* done, return this */
163 }
164 
165 
167  RexxToken *target ) /* target variable instruction */
168 /****************************************************************************/
169 /* Function: Create a new ASSIGNMENT translator object */
170 /****************************************************************************/
171 {
172  this->needVariable(target); /* must be a variable */
173  /* process the expression */
174  RexxObject *_expression = this->expression(TERM_EOC);
175 #if 0 // Compatibility: v= is a valid rexx instruction (assign "")
176  if (_expression == OREF_NULL) /* no expression here? */
177  {
178  /* this is invalid */
180  }
181 #endif
182  /* create a new translator object */
183  RexxInstruction *newObject = new_instruction(ASSIGNMENT, Assignment);
184  new ((void *)newObject) RexxInstructionAssignment((RexxVariableBase *)(this->addText(target)), _expression);
185  return newObject; /* done, return this */
186 }
187 
188 
189 /**
190  * Create a special assignment op of the form "variable (op)= expr".
191  *
192  * @param target The assignment target variable.
193  * @param operation The operator token. classId is TOKEN_ASSIGNMENT, the subclass
194  * is the type of the operation to perform.
195  *
196  * @return The constructed instruction object.
197  */
199 {
200  this->needVariable(target); // make sure this is a variable
201  // we require an expression for the additional part, which is required
202  RexxObject *_expression = this->expression(TERM_EOC);
203  if (_expression == OREF_NULL)
204  {
206  }
207 
208  // we need an evaluator for both the expression and the assignment
209  RexxObject *variable = addText(target);
210  // now add a binary operator to this expression tree
211  _expression = (RexxObject *)new RexxBinaryOperator(operation->subclass, variable, _expression);
212 
213  // now everything is the same as an assignment operator
214  RexxInstruction *newObject = new_instruction(ASSIGNMENT, Assignment);
215  new ((void *)newObject) RexxInstructionAssignment((RexxVariableBase *)variable, _expression);
216  return newObject; /* done, return this */
217 }
218 
220 /****************************************************************************/
221 /* Function: Create a new CALL translator object */
222 /****************************************************************************/
223 {
224  size_t _flags = 0; /* clear the flags */
225  size_t builtin_index = 0; /* clear the builtin index */
226  /* RexxString * */ ProtectedObject _condition((RexxObject*)OREF_NULL); /* clear the condition */
227  RexxObject *name = OREF_NULL; /* no name yet */
228  size_t argCount = 0; /* no arguments yet */
229  size_t namedArgCount = 0;
230 
231  RexxToken *token = nextReal(); /* get the next token */
232  if (token->isEndOfClause()) /* no target specified? */
233  {
234  /* this is an error */
236  }
237  /* may have to process ON/OFF forms */
238  else if (token->isSymbol())
239  {
240  int _keyword = this->subKeyword(token); /* check for the subkeywords */
241  if (_keyword == SUBKEY_ON)
242  { /* CALL ON instruction? */
243  refineSubclass(token, IS_SUBKEY);
244  _flags |= RexxInstructionCall::call_on_off; /* this is a CALL ON */
245  token = nextReal(); /* get the next token */
246  /* no condition specified or not a */
247  /* symbol? */
248  if (!token->isSymbol())
249  {
250  /* this is an error */
252  }
253  _keyword = this->condition(token);/* get the condition involved */
254  if (_keyword == 0 || /* invalid condition specified? */
255  _keyword == CONDITION_SYNTAX ||
256  _keyword == CONDITION_NOVALUE ||
257  _keyword == CONDITION_PROPAGATE ||
258  _keyword == CONDITION_LOSTDIGITS ||
259  _keyword == CONDITION_NOMETHOD ||
260  _keyword == CONDITION_NOSTRING)
261  {
262  /* got an error here */
264  }
265 
266  /* actually a USER condition request?*/
267  else if (_keyword == CONDITION_USER)
268  {
270  token = nextReal(); /* get the next token */
271  /* no condition specified or not a */
272  /* symbol? */
273  if (!token->isSymbol())
274  {
275  /* this is an error */
277  }
278  /* set the builtin index for later */
279  /* resolution step */
280  builtin_index = this->builtin(token);
281  if (builtin_index != 0) refineSubclass(token, IS_BUILTIN);
282  _condition = token->value; /* get the token string value */
283  name = _condition; /* set the default target */
284  /* condition name is "USER condition"*/
285  _condition = ((RexxString*)_condition)->concatToCstring(CHAR_USER_BLANK);
286  /* save the condition name */
287  _condition = this->commonString(_condition);
288  }
289  else
290  { /* language defined condition */
291  name = token->value; /* set the default target */
292  _condition = token->value; /* condition is the same as target */
293  /* set the builtin index for later */
294  /* resolution step */
295  builtin_index = this->builtin(token);
296  if (builtin_index != 0) refineSubclass(token, IS_BUILTIN);
297  }
298  token = nextReal(); /* get the next token */
299  /* anything real here? */
300  if (!token->isEndOfClause())
301  {
302  /* not a symbol? */
303  if (!token->isSymbol())
304  {
305  /* this is an error */
307  }
308  /* not the name token? */
309  if (this->subKeyword(token) != SUBKEY_NAME)
310  {
311  /* got an error here */
313  }
314  refineSubclass(token, IS_SUBKEY);
315  token = nextReal(); /* get the next token */
316  if (token->classId != TOKEN_SYMBOL && token->classId != TOKEN_LITERAL)
317  {
318  /* this is an error */
320  }
321  name = token->value; /* set the default target */
322  /* set the builtin index for later */
323  /* resolution step */
324  builtin_index = this->builtin(token);
325  if (builtin_index != 0) refineSubclass(token, IS_BUILTIN);
326  token = nextReal(); /* get the next token */
327  /* must have the clause end here */
328  if (!token->isEndOfClause())
329  {
330  /* this is an error */
332  }
333  }
334  }
335  else if (_keyword == SUBKEY_OFF)
336  { /* CALL OFF instruction? */
337  refineSubclass(token, IS_SUBKEY);
338  token = nextReal(); /* get the next token */
339  /* no condition specified or not a */
340  /* symbol? */
341  if (!token->isSymbol())
342  {
343  /* this is an error */
345  }
346  /* get the condition involved */
347  _keyword = this->condition(token);
348  if (_keyword == 0 || /* invalid condition specified? */
349  _keyword == CONDITION_SYNTAX ||
350  _keyword == CONDITION_NOVALUE ||
351  _keyword == CONDITION_PROPAGATE ||
352  _keyword == CONDITION_LOSTDIGITS ||
353  _keyword == CONDITION_NOMETHOD ||
354  _keyword == CONDITION_NOSTRING)
355  {
356  /* got an error here */
358  }
359  /* actually a USER condition request?*/
360  else if (_keyword == CONDITION_USER)
361  {
363  token = nextReal(); /* get the next token */
364  /* no condition specified or not a */
365  /* symbol? */
366  if (!token->isSymbol())
367  {
368  /* this is an error */
370  }
371  _condition = token->value; /* get the token string value */
372  /* condition name is "USER condition"*/
373  _condition = ((RexxString*)_condition)->concatToCstring(CHAR_USER_BLANK);
374  /* save the condition name */
375  _condition = this->commonString(_condition);
376  }
377  else /* language defined condition */
378  {
379  _condition = token->value; /* set the condition name */
380  }
381  token = nextReal(); /* get the next token */
382  if (!token->isEndOfClause()) /* must have the clause end here */
383  {
384  /* this is an error */
386  }
387  }
388  else
389  { /* normal CALL instruction */
390  /* set the default target */
391  name = (RexxString *)token->value;
392  /* set the builtin index for later */
393  /* resolution step */
394  builtin_index = this->builtin(token);
395  if (builtin_index != 0) refineSubclass(token, IS_BUILTIN);
396  /* get the argument list */
397  /*argCount =*/ this->argList(OREF_NULL, TERM_EOC, true, /*byref*/argCount, /*byref*/namedArgCount);
398  }
399  }
400  /* call with a string target */
401  else if (token->isLiteral())
402  {
403  name = token->value; /* set the default target */
404  /* set the builtin index for later */
405  /* resolution step */
406  builtin_index = this->builtin(token);
407  if (builtin_index != 0) refineSubclass(token, IS_BUILTIN);
408  /* process the argument list */
409  /*argCount =*/ this->argList(OREF_NULL, TERM_EOC, true, /*byref*/argCount, /*byref*/namedArgCount);
410  _flags |= RexxInstructionCall::call_nointernal; /* do not check for internal routines*/
411  }
412  /* indirect call case? */
413  else if (token->classId == TOKEN_LEFT)
414  {
415  _flags |= RexxInstructionCall::call_dynamic; /* going to be indirect */
416  name = this->parenExpression(token); // this is a full expression
417  // an expression is required
418  if (name == OREF_NULL)
419  {
421  }
422  /* process the argument list */
423  /*argCount =*/ this->argList(OREF_NULL, TERM_EOC, true, /*byref*/argCount, /*byref*/namedArgCount);
424  /* NOTE: this call is not added to */
425  /* the resolution list because it */
426  /* cannot be resolved until run time */
427  }
428  else
429  {
430  /* this is an error */
432  }
433  /* create a new translator object */
434  RexxInstruction *newObject = new_variable_instruction(CALL, Call, sizeof(RexxInstructionCallBase) + (argCount + (2 * namedArgCount)) * sizeof(RexxObject *));
435  ProtectedObject p(newObject); // jlf: probably not needed, already protected by this->currentInstruction
436  /* Initialize this new object */
437  new ((void *)newObject) RexxInstructionCall(name, _condition, argCount, this->subTerms, namedArgCount, this->namedSubTerms, _flags, builtin_index);
438 
439  if (!(flags&RexxInstructionCall::call_dynamic)) /* static name resolution? */
440  {
441  this->addReference((RexxObject *)newObject); /* add to table of references */
442  }
443  return newObject; /* done, return this */
444 }
445 
447 /****************************************************************************/
448 /* Function: Create a new COMMAND instruction object */
449 /****************************************************************************/
450 {
451  /* process the expression */
452  RexxObject *_expression = this->expression(TERM_EOC);
453  /* create a new translator object */
454  RexxInstruction *newObject = new_instruction(COMMAND, Command);
455  /* now complete this */
456  new ((void *)newObject) RexxInstructionCommand(_expression);
457  return newObject; /* done, return this */
458 }
459 
461 /****************************************************************************/
462 /* Function: Create a new DO translator object */
463 /****************************************************************************/
464 {
465  RexxInstruction *newObject = createDoLoop();
466  /* now complete the parsing */
467  return this->createDoLoop((RexxInstructionDo *)newObject, false);
468 }
469 
471 /****************************************************************************/
472 /* Function: Create a new LOOP translator object */
473 /****************************************************************************/
474 {
475  RexxInstruction *newObject = createLoop();
476  /* now complete the parsing */
477  return this->createDoLoop((RexxInstructionDo *)newObject, true);
478 }
479 
480 
481 /**
482  * Create a DO instruction instance.
483  *
484  * @return
485  */
487 {
488  // NOTE: we create a DO instruction for both DO and LOOP
489  RexxInstruction *newObject = new_instruction(DO, Do); /* create a new translator object */
490  new((void *)newObject) RexxInstructionDo;
491  return newObject;
492 }
493 
494 
495 /**
496  * Create a LOOP instruction instance.
497  *
498  * @return
499  */
501 {
502  // NOTE: we create a DO instruction for both DO and LOOP
503  RexxInstruction *newObject = new_instruction(LOOP, Do); /* create a new translator object */
504  new((void *)newObject) RexxInstructionDo;
505  return newObject;
506 }
507 
508 
510 /******************************************************************************/
511 /* Function: Create a new DO translator object */
512 /******************************************************************************/
513 {
514  size_t _position = markPosition(); // get a reset position before getting next token
515  // We've already figured out this is either a LOOP or a DO, now we need to
516  // decode what else is going on.
517  RexxToken *token = nextReal();
518  int conditional;
519 
520 
521  // before doing anything, we need to test for a "LABEL name" before other options. We
522  // need to make certain we check that the LABEL keyword is not being
523  // used as control variable.
524  if (token->isSymbol())
525  {
526  // potentially a label. Check the keyword value
527  if (this->subKeyword(token) == SUBKEY_LABEL)
528  {
529  // if the next token is a symbol, this is a label.
530  RexxToken *name = nextReal();
531  if (name->isSymbol())
532  {
533  refineSubclass(token, IS_SUBKEY);
534  OrefSet(newDo, newDo->label, name->value);
535  // update the reset position before stepping to the next position
536  _position = markPosition();
537  // step to the next token for processing the following parts
538  token = nextReal();
539  }
540  else if (name->subclass == OPERATOR_EQUAL)
541  {
542  // back up to the LABEL token and process as normal
543  previousToken();
544  }
545  else
546  {
547  // this is either an end-of-clause or something not a symbol. This is an error.
549  }
550  }
551  }
552 
553 
554  // Just the single token means this is either a simple DO block or
555  // a LOOP forever, depending on the type of instruction we're parsing.
556  if (token->isEndOfClause())
557  {
558  if (isLoop)
559  {
560  newDo->type = DO_FOREVER; // a LOOP with nothing else is a LOOP FOREVER
561  }
562  else
563  {
564  newDo->type = SIMPLE_DO; // this is a simple DO block
565  }
566  return newDo;
567  }
568 
569 
570  if (token->isSymbol())
571  {
572  // this can be a control variable or keyword. We need to look ahead
573  // to the next token.
574  RexxToken *second = nextReal();
575  // similar to assignment instructions, any equal sign triggers this to
576  // be a controlled form, even if the the "=" is part of a larger instruction
577  // such as "==". We give this as an expression error.
578  if (second->subclass == OPERATOR_STRICT_EQUAL)
579  {
581  }
582  // ok, now check for the control variable.
583  else if (second->subclass == OPERATOR_EQUAL)
584  {
585  newDo->type = CONTROLLED_DO; // this is a controlled DO loop
586  // the control expressions need to evaluated in the coded order,
587  // so we keep a little table of the order used.
588  int keyslot = 0;
589  // if this DO/LOOP didn't have a label clause, use the control
590  // variable name as the loop name.
591  if (newDo->label == OREF_NULL)
592  {
593  OrefSet(newDo, newDo->label, token->value);
594  }
595 
596  // get the variable retriever
597  OrefSet(newDo, newDo->control, (RexxVariableBase *)this->addVariable(token));
598  // go get the initial expression, using the control variable terminators
599  OrefSet(newDo, newDo->initial, this->expression(TERM_CONTROL));
600  // this is a required expression.
601  if (newDo->initial == OREF_NULL)
602  {
604  }
605  // ok, keep looping while we don't have a clause terminator
606  // because the parsing of the initial expression is terminated by either
607  // the end-of-clause or DO/LOOP keyword, we know the next token will by
608  // a symbol
609  token = nextReal();
610  while (!token->isEndOfClause())
611  {
612  // this must be a keyword, so resolve it.
613  switch (this->subKeyword(token) )
614  {
615 
616  case SUBKEY_BY:
617  refineSubclass(token, IS_SUBKEY);
618  // only one per customer
619  if (newDo->by != OREF_NULL)
620  {
622  }
623  // get the keyword expression, which is required also
624  OrefSet(newDo, newDo->by, this->expression(TERM_CONTROL));
625  if (newDo->by == OREF_NULL)
626  {
628 
629  }
630  // record the processing order
631  newDo->expressions[keyslot++] = EXP_BY;
632  break;
633 
634  case SUBKEY_TO:
635  refineSubclass(token, IS_SUBKEY);
636  // only one per customer
637  if (newDo->to != OREF_NULL)
638  {
640  }
641  // get the keyword expression, which is required also
642  OrefSet(newDo, newDo->to, this->expression(TERM_CONTROL));
643  if (newDo->to == OREF_NULL)
644  {
646 
647  }
648  // record the processing order
649  newDo->expressions[keyslot++] = EXP_TO;
650  break;
651 
652  case SUBKEY_FOR:
653  refineSubclass(token, IS_SUBKEY);
654  // only one per customer
655  if (newDo->forcount != OREF_NULL)
656  {
658  }
659  // get the keyword expression, which is required also
660  OrefSet(newDo, newDo->forcount, this->expression(TERM_CONTROL));
661  if (newDo->forcount == OREF_NULL)
662  {
664 
665  }
666  // record the processing order
667  newDo->expressions[keyslot++] = EXP_FOR;
668  break;
669 
670  case SUBKEY_WHILE:
671  refineSubclass(token, IS_SUBKEY);
672  // step back a token and process the conditional
673  previousToken();
674  OrefSet(newDo, newDo->conditional, this->parseConditional(NULL, 0));
675  previousToken(); // place the terminator back
676  // this changes the loop type
677  newDo->type = CONTROLLED_WHILE;
678  break;
679 
680  case SUBKEY_UNTIL:
681  refineSubclass(token, IS_SUBKEY);
682  // step back a token and process the conditional
683  previousToken();
684  OrefSet(newDo, newDo->conditional, this->parseConditional(NULL, 0));
685  previousToken(); // place the terminator back
686  // this changes the loop type
687  newDo->type = CONTROLLED_UNTIL;
688  break;
689  }
690  token = nextReal(); /* step to the next token */
691  }
692  }
693  // DO name OVER collection form?
694  else if (this->subKeyword(second) == SUBKEY_OVER)
695  {
696  refineSubclass(second, IS_SUBKEY);
697  // this is a DO OVER type
698  newDo->type = DO_OVER;
699  // if this DO/LOOP didn't have a label clause, use the control
700  // variable name as the loop name.
701  if (newDo->label == OREF_NULL)
702  {
703  OrefSet(newDo, newDo->label, token->value);
704  }
705  // save the control variable retriever
706  OrefSet(newDo, newDo->control, (RexxVariableBase *)this->addVariable(token));
707  // and get the OVER expression, which is required
708  OrefSet(newDo, newDo->initial, this->expression(TERM_COND));
709  /* no expression? */
710  if (newDo->initial == OREF_NULL)
711  {
713  }
714  // process an additional conditional
715  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, 0));
716  // if we have a conditional, we need to change type DO type.
717  if (conditional == SUBKEY_WHILE)
718  {
719  newDo->type = DO_OVER_WHILE; // this is the DO var OVER expr WHILE cond form
720  }
721  else if (conditional == SUBKEY_UNTIL)
722  {
723  newDo->type = DO_OVER_UNTIL; // this is the DO var OVER expr UNTIL cond form
724  }
725  }
726  else // not a controlled form, but this could be a conditional form.
727  {
728  // start the parsing process over from the beginning with the first of the
729  // loop-type tokens
730  resetPosition(_position);
731  token = nextReal();
732  // now check the other keyword varieties.
733  switch (this->subKeyword(token))
734  {
735  case SUBKEY_FOREVER: // DO FOREVER
736 
737  refineSubclass(token, IS_SUBKEY);
738  newDo->type = DO_FOREVER;
739  // this has a potential conditional
740  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, Error_Invalid_do_forever));
741  // if we have a conditional, then we need to adjust the loop type
742  if (conditional == SUBKEY_WHILE)
743  {
744  newDo->type = DO_WHILE; // DO FOREVER WHILE cond
745  }
746  else if (conditional == SUBKEY_UNTIL)
747  {
748  newDo->type = DO_UNTIL; // DO FOREVER UNTIL cond
749  }
750  break;
751 
752  case SUBKEY_WHILE: // DO WHILE cond */
753  refineSubclass(token, IS_SUBKEY);
754  // step back one token and process the conditional
755  previousToken();
756  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, 0));
757  newDo->type = DO_WHILE; // set the proper loop type */
758  break;
759 
760  case SUBKEY_UNTIL: // DO WHILE cond */
761  refineSubclass(token, IS_SUBKEY);
762  // step back one token and process the conditional
763  previousToken();
764  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, 0));
765  newDo->type = DO_UNTIL; // set the proper loop type */
766  break;
767 
768  default: /* not a real DO keyword...expression*/
769  previousToken(); /* step back one token */
770  newDo->type = DO_COUNT; /* just a DO count form */
771  /* get the repetitor expression */
772  OrefSet(newDo, newDo->forcount, this->expression(TERM_COND));
773  // this has a potential conditional
774  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, 0));
775  // if we have a conditional, then we need to adjust the loop type
776  if (conditional == SUBKEY_WHILE)
777  {
778  newDo->type = DO_COUNT_WHILE; // DO expr WHILE cond
779  }
780  else if (conditional == SUBKEY_UNTIL)
781  {
782  newDo->type = DO_COUNT_UNTIL; // DO expr UNTIL cond
783  }
784  break;
785  }
786  }
787  }
788  else // just a DO expr form
789  {
790  previousToken(); /* step back one token */
791  newDo->type = DO_COUNT; /* just a DO count form */
792  /* get the repetitor expression */
793  OrefSet(newDo, newDo->forcount, this->expression(TERM_COND));
794  // this has a potential conditional
795  OrefSet(newDo, newDo->conditional, this->parseConditional(&conditional, 0));
796  // if we have a conditional, then we need to adjust the loop type
797  if (conditional == SUBKEY_WHILE)
798  {
799  newDo->type = DO_COUNT_WHILE; // DO expr WHILE cond
800  }
801  else if (conditional == SUBKEY_UNTIL)
802  {
803  newDo->type = DO_COUNT_UNTIL; // DO expr UNTIL cond
804  }
805  }
806  return newDo;
807 }
808 
810 /****************************************************************************/
811 /* Function: Create a new DROP translator object */
812 /****************************************************************************/
813 {
814  /* go process the list */
815  size_t variableCount = this->processVariableList(KEYWORD_DROP);
816  /* create a new translator object */
817  RexxInstruction *newObject = new_variable_instruction(DROP, Drop, sizeof(RexxInstructionDrop) + (variableCount - 1) * sizeof(RexxObject *));
818  /* now complete this */
819  new ((void *)newObject) RexxInstructionDrop(variableCount, this->subTerms);
820  return newObject; /* done, return this */
821 }
822 
824  RexxToken *token) /* ELSE keyword token */
825 /****************************************************************************/
826 /* Function: Create a new ELSE translator object */
827 /****************************************************************************/
828 {
829  /* create a new translator object */
830  RexxInstruction *newObject = new_instruction(ELSE, Else);
831  /* now complete this */
832  new ((void *)newObject) RexxInstructionElse(token);
833  return newObject; /* done, return this */
834 }
835 
837 /****************************************************************************/
838 /* Function: Create a new END translator object */
839 /****************************************************************************/
840 {
841  RexxString *name = OREF_NULL; /* no name yet */
842  RexxToken *token = nextReal(); /* get the next token */
843  if (!token->isEndOfClause())
844  { /* have a name specified? */
845  if (!token->isSymbol())/* must have a symbol here */
846  {
847  /* this is an error */
849  }
850  name = token->value; /* get the name pointer */
851  token = nextReal(); /* get the next token */
852  if (!token->isEndOfClause()) /* end of the instruction? */
853  {
854  /* this is an error */
856  }
857  }
858  /* create a new translator object */
859  RexxInstruction *newObject = new_instruction(END, End);
860  /* now complete this */
861  new((void *)newObject) RexxInstructionEnd(name);
862  return newObject; /* done, return this */
863 }
864 
866  RexxInstructionIf *parent ) /* target parent IF or WHEN clause */
867 /****************************************************************************/
868 /* Function: Create a new DUMMY END IF translator object */
869 /****************************************************************************/
870 {
871  /* create a new translator object */
872  RexxInstruction *newObject = new_instruction(ENDIF, EndIf);
873  /* now complete this */
874  new ((void *)newObject) RexxInstructionEndIf(parent);
875  return newObject; /* done, return this */
876 }
877 
879 /****************************************************************************/
880 /* Function: Create a EXIT instruction object */
881 /****************************************************************************/
882 {
883  /* process the expression */
884  RexxObject *_expression = this->expression(TERM_EOC);
885  /* create a new translator object */
886  RexxInstruction *newObject = new_instruction(EXIT, Exit);
887  /* now complete this */
888  new((void *)newObject) RexxInstructionExit(_expression);
889  return newObject; /* done, return this */
890 }
891 
893 /****************************************************************************/
894 /* Function: Create a new EXPOSE translator object */
895 /****************************************************************************/
896 {
897  this->isExposeValid(); /* validate the placement */
898  /* go process the list */
899  size_t variableCount = this->processVariableList(KEYWORD_EXPOSE);
900  /* Get new object */
901  RexxInstruction *newObject = new_variable_instruction(EXPOSE, Expose, sizeof(RexxInstructionExpose) + (variableCount - 1) * sizeof(RexxObject *));
902  /* Initialize this new method */
903  new ((void *)newObject) RexxInstructionExpose(variableCount, this->subTerms);
904  return newObject; /* done, return this */
905 }
906 
908  RexxInstructionForward *newObject) /* target FORWARD instruction */
909 /****************************************************************************/
910 /* Function: Create a FORWARD instruction object */
911 /****************************************************************************/
912 {
913  bool returnContinue = false; /* no return or continue yet */
914  RexxToken *token = nextReal(); /* get the next token */
915 
916  while (!token->isEndOfClause())
917  {/* while still more to process */
918  if (!token->isSymbol())/* not a symbol token? */
919  {
920  /* this is an error */
922  }
923  switch (this->subKeyword(token))
924  { /* get the keyword value */
925 
926  case SUBKEY_TO: /* FORWARD TO expr */
927  refineSubclass(token, IS_SUBKEY);
928  /* have a description already? */
929  if (newObject->target != OREF_NULL)
930  {
931  /* this is invalid */
933  }
934  /* get the keyword value */
935  OrefSet(newObject, newObject->target, this->constantExpression());
936  /* no expression here? */
937  if (newObject->target == OREF_NULL)
938  {
939  /* this is invalid */
941  }
942  break;
943 
944  case SUBKEY_CLASS: /* FORWARD CLASS expr */
945  refineSubclass(token, IS_SUBKEY);
946  /* have a class over ride already? */
947  if (newObject->superClass != OREF_NULL)
948  {
949  /* this is invalid */
951  }
952  /* get the keyword value */
953  OrefSet(newObject, newObject->superClass, this->constantExpression());
954  /* no expression here? */
955  if (newObject->superClass == OREF_NULL)
956  {
957  /* this is invalid */
959  }
960  break;
961 
962  case SUBKEY_MESSAGE: /* FORWARD MESSAGE expr */
963  refineSubclass(token, IS_SUBKEY);
964  /* have a message over ride already? */
965  if (newObject->message != OREF_NULL)
966  {
967  /* this is invalid */
969  }
970  /* get the keyword value */
971  OrefSet(newObject, newObject->message, this->constantExpression());
972  /* no expression here? */
973  if (newObject->message == OREF_NULL)
974  {
975  /* this is invalid */
977  }
978  break;
979 
980  case SUBKEY_ARGUMENTS: /* FORWARD ARGUMENTS expr */
981  refineSubclass(token, IS_SUBKEY);
982  /* have a additional already? */
983  if (newObject->arguments != OREF_NULL || newObject->array != OREF_NULL)
984  {
985  /* this is invalid */
987  }
988  /* get the keyword value */
989  OrefSet(newObject, newObject->arguments, this->constantExpression());
990  /* no expression here? */
991  if (newObject->arguments == OREF_NULL)
992  {
993  /* this is invalid */
995  }
996  break;
997 
998  case SUBKEY_NAMEDARGUMENTS: /* FORWARD NAMEDARGUMENTS expr */
999  refineSubclass(token, IS_SUBKEY);
1000  /* have a additional already? */
1001  if (newObject->namedArgumentsExpression != OREF_NULL || newObject->namedArgumentsArray != OREF_NULL)
1002  {
1003  /* this is invalid */
1005  }
1006  /* get the keyword value */
1007  OrefSet(newObject, newObject->namedArgumentsExpression, this->constantExpression());
1008  /* no expression here? */
1009  if (newObject->namedArgumentsExpression == OREF_NULL)
1010  {
1011  /* this is invalid */
1013  new_string("Missing expression following NAMEDARGUMENTS keyword of a FORWARD instruction"));
1014  }
1015  break;
1016 
1017  case SUBKEY_ARRAY: /* FORWARD ARRAY (expr, expr) */
1018  refineSubclass(token, IS_SUBKEY);
1019  /* have arguments already? */
1020  if (newObject->arguments != OREF_NULL || newObject->namedArgumentsExpression != OREF_NULL ||
1021  newObject->array != OREF_NULL)
1022  {
1023  /* this is invalid */
1025  }
1026  token = nextReal(); /* get the next token */
1027  /* not an expression list starter? */
1028  if (token->classId != TOKEN_LEFT)
1029  {
1030  /* this is invalid */
1032  }
1033  /* process the array list */
1034  {
1036  RexxArray *namedArgArray = OREF_NULL;
1037  this->argArray(token, TERM_RIGHT, true, /*byref*/argArray, /*byref*/namedArgArray);
1038  OrefSet(newObject, newObject->array, argArray);
1039  OrefSet(newObject, newObject->namedArgumentsArray, namedArgArray);
1040  // Now both array and namedArgumentsArray are != OREF_NULL
1041  // They can have 0 item.
1042  }
1043  break;
1044 
1045  case SUBKEY_CONTINUE: /* FORWARD CONTINUE */
1046  refineSubclass(token, IS_SUBKEY);
1047  if (returnContinue) /* already had the return action? */
1048  {
1049  /* this is invalid */
1051  }
1052  returnContinue = true; /* not valid again */
1053  /* remember this */
1054  newObject->instructionFlags |= forward_continue;
1055  break;
1056 
1057  default: /* invalid subkeyword */
1058  /* this is a sub keyword error */
1060  break;
1061  }
1062  token = nextReal(); /* step to the next keyword */
1063  }
1064 }
1065 
1067 /****************************************************************************/
1068 /* Function: Create a new FORWARD translator object */
1069 /****************************************************************************/
1070 {
1071  /* create a new translator object */
1072  RexxInstruction *newObject = new_instruction(FORWARD, Forward);
1073  new((void *)newObject) RexxInstructionForward;
1075  return newObject; /* done, return this */
1076 }
1077 
1079 /******************************************************************************/
1080 /* Function: Create a new GUARD translator object */
1081 /******************************************************************************/
1082 {
1083  RexxObject *_expression = OREF_NULL; /* default no expression */
1084  RexxArray *variable_list = OREF_NULL; /* no variable either */
1085  size_t variable_count = 0; /* no variables yet */
1086  RexxToken *token = nextReal(); /* get the next token */
1087  if (!token->isSymbol()) /* must have a symbol here */
1088  {
1089  /* raise the error */
1091  }
1092 
1093  bool on_off = false;
1094 
1095  /* resolve the subkeyword and */
1096  /* process the subkeyword */
1097  switch (this->subKeyword(token))
1098  {
1099  case SUBKEY_OFF: /* GUARD OFF instruction */
1100  refineSubclass(token, IS_SUBKEY);
1101  on_off = false; /* this is the guard off form */
1102  break;
1103 
1104  case SUBKEY_ON: /* GUARD ON instruction */
1105  refineSubclass(token, IS_SUBKEY);
1106  on_off = true; /* remember it is the on form */
1107  break;
1108 
1109  default:
1110  /* raise an error */
1112  break;
1113  }
1114  token = nextReal(); /* get the next token */
1115  if (token->isSymbol())
1116  {/* have the keyword form? */
1117  /* resolve the subkeyword */
1118  switch (this->subKeyword(token))
1119  { /* and process */
1120 
1121  case SUBKEY_WHEN: /* GUARD ON WHEN expr */
1122  refineSubclass(token, IS_SUBKEY);
1123  this->setGuard(); /* turn on guard variable collection */
1124  /* process the expression */
1125  _expression = this->expression(TERM_EOC);
1126  if (_expression == OREF_NULL) /* no expression? */
1127  {
1128  /* expression is required after value*/
1130  }
1131  /* retrieve the guard variable list */
1132  variable_list = this->getGuard();
1133  /* get the size */
1134  variable_count = variable_list->size();
1135  break;
1136 
1137  default: /* invalid subkeyword */
1138  /* raise an error */
1140  break;
1141  }
1142  }
1143  else if (!token->isEndOfClause())/* not the end? */
1144  {
1145  /* raise an error */
1147  }
1148 
1149  /* Get new object */
1150  RexxInstruction *newObject = new_variable_instruction(GUARD, Guard, sizeof(RexxInstructionGuard)
1151  + (variable_count - 1) * sizeof(RexxObject *));
1152  /* Initialize this new method */
1153  new ((void *)newObject) RexxInstructionGuard(_expression, variable_list, on_off);
1154  return newObject; /* done, return this */
1155 }
1156 
1158  int type ) /* type of instruction (IF or WHEN) */
1159 /****************************************************************************/
1160 /* Function: Create a new INTERPRET instruction object */
1161 /****************************************************************************/
1162 {
1163  /* process the expression */
1164  RexxObject *_condition = this->parseLogical(OREF_NULL, TERM_IF);
1165  if (_condition == OREF_NULL)
1166  { /* no expression here? */
1167  if (type == KEYWORD_IF) /* IF form? */
1168  {
1169  /* issue the IF message */
1171  }
1172  else
1173  {
1174  /* issue the WHEN message */
1176  }
1177  }
1178  RexxToken *token = nextReal(); /* get terminator token */
1179  previousToken(); /* push the terminator back */
1180  /* create a new translator object */
1181  RexxInstruction *newObject = new_instruction(IF, If);
1182  /* now complete this */
1183  new ((void *)newObject) RexxInstructionIf(_condition, token);
1184  newObject->setType(type); /* set the IF/WHEN type */
1185  return newObject; /* done, return this */
1186 }
1187 
1188 
1190  int type ) /* instruction type */
1191 /****************************************************************************/
1192 /* Function: Create a new INSTRUCTION translator object */
1193 /****************************************************************************/
1194 {
1195  /* create a new translator object */
1197  newObject->setType(type); /* set the given type */
1198  return newObject; /* done, return this */
1199 }
1200 
1202 /****************************************************************************/
1203 /* Function: Create a new INTERPRET instruction object */
1204 /****************************************************************************/
1205 {
1206  /* process the expression */
1207  RexxObject *_expression = this->expression(TERM_EOC);
1208  if (_expression == OREF_NULL) /* no expression here? */
1209  {
1210  /* this is invalid */
1212  }
1213  /* create a new translator object */
1214  RexxInstruction *newObject = new_instruction(INTERPRET, Interpret);
1215  /* now complete this */
1216  new ((void *)newObject) RexxInstructionInterpret(_expression);
1217  return newObject; /* done, return this */
1218 }
1219 
1221 /******************************************************************************/
1222 /* Function: Create a new LABEL instruction translator object */
1223 /******************************************************************************/
1224 {
1225  RexxToken *token = nextToken(); /* get the next token */
1226  RexxString *name = token->value; /* get the label name */
1227  /* allocate a new object */
1228  RexxInstruction *newObject = new_instruction(LABEL, Label);
1229  /* add to the label list */
1230  this->addLabel( newObject, name);
1231  token = nextReal(); /* get the colon token */
1232 
1233  SourceLocation location = token->getLocation(); /* get the token location */
1234  /* the clause ends with the colon */
1235  newObject->setEnd(location.getEndLine(), location.getEndOffset());
1236  new ((void *)newObject) RexxInstructionLabel();
1237  return newObject; /* done, return this */
1238 }
1239 
1241  int type ) /* type of queueing operation */
1242 /****************************************************************************/
1243 /* Function: Create a new LEAVE/ITERATE instruction translator object */
1244 /****************************************************************************/
1245 {
1246  RexxString *name = OREF_NULL; /* no name yet */
1247  RexxToken *token = nextReal(); /* get the next token */
1248  if (!token->isEndOfClause())
1249  { /* have a name specified? */
1250  /* must have a symbol here */
1251  if (!token->isSymbol())
1252  {
1253  if (type == KEYWORD_LEAVE) /* is it a LEAVE? */
1254  {
1255  /* this is an error */
1257  }
1258  else
1259  {
1260  /* this is an iterate error */
1262  }
1263  }
1264  name = token->value; /* get the name pointer */
1265  token = nextReal(); /* get the next token */
1266  if (!token->isEndOfClause())
1267  { /* end of the instruction? */
1268  if (type == KEYWORD_LEAVE) /* is it a LEAVE? */
1269  {
1270  /* this is an error */
1272  }
1273  else
1274  {
1275  /* this is an iterate error */
1277  }
1278  }
1279  }
1280  /* allocate a new object */
1281  RexxInstruction *newObject = new_instruction(LEAVE, Leave);
1282  /* Initialize this new method */
1283  new ((void *)newObject) RexxInstructionLeave(type, name);
1284  return newObject; /* done, return this */
1285 }
1286 
1288  RexxExpressionMessage *_message) /* message to process */
1289 /****************************************************************************/
1290 /* Function: Create a new MESSAGE instruction translator object */
1291 /****************************************************************************/
1292 {
1293  ProtectedObject p(_message);
1294  /* allocate a new object */
1295  RexxInstruction *newObject = new_variable_instruction(MESSAGE, Message, sizeof(RexxInstructionMessage) + (_message->argumentCount - 1 + (2 * _message->namedArgumentCount)) * sizeof(RexxObject *));
1296  /* Initialize this new method */
1297  new ((void *)newObject) RexxInstructionMessage(_message);
1298  return newObject; /* done, return this */
1299 }
1300 
1302  RexxExpressionMessage *_message, /* message to process */
1303  RexxObject *_expression ) /* assignment value */
1304 /****************************************************************************/
1305 /* Function: Create a new MESSAGE assignment translator object */
1306 /****************************************************************************/
1307 {
1308  ProtectedObject p(_message); // protect this
1309  _message->makeAssignment(this); // convert into an assignment message
1310  // allocate a new object. NB: a message instruction gets an extra argument, so we don't subtract one.
1311  RexxInstruction *newObject = new_variable_instruction(MESSAGE, Message, sizeof(RexxInstructionMessage) + (_message->argumentCount + (2 * _message->namedArgumentCount)) * sizeof(RexxObject *));
1312  /* Initialize this new method */
1313  new ((void *)newObject) RexxInstructionMessage(_message, _expression);
1314  return newObject; /* done, return this */
1315 }
1316 
1317 
1318 /**
1319  * Create a message term pseudo assignment instruction for a
1320  * shortcut operator. The instruction is of the form
1321  * "messageTerm (op)= expr".
1322  *
1323  * @param message The target message term.
1324  * @param operation The operation to perform in the expansion.
1325  * @param expression The expression (which is the right-hand term of the eventual
1326  * expression).
1327  *
1328  * @return The constructed message operator.
1329  */
1331 {
1332  ProtectedObject p(_message); // protect this
1333  ProtectedObject p2(_expression); // also need to protect this portion
1334  // make a copy of the message term for use in the expression
1335  RexxObject *retriever = _message->copy();
1336 
1337  _message->makeAssignment(this); // convert into an assignment message (the original message term)
1338 
1339 
1340  // now add a binary operator to this expression tree
1341  _expression = (RexxObject *)new RexxBinaryOperator(operation->subclass, retriever, _expression);
1342  p2 = _expression;
1343 
1344  // allocate a new object. NB: a message instruction gets an extra argument, so we don't subtract one.
1345  RexxInstruction *newObject = new_variable_instruction(MESSAGE, Message, sizeof(RexxInstructionMessage) + (_message->argumentCount + (2 * _message->namedArgumentCount)) * sizeof(RexxObject *));
1346  /* Initialize this new method */
1347  new ((void *)newObject) RexxInstructionMessage(_message, _expression);
1348  return newObject; /* done, return this */
1349 }
1350 
1351 
1353 /****************************************************************************/
1354 /* Function: Create a NOP instruction object */
1355 /****************************************************************************/
1356 {
1357  RexxToken *token = nextReal(); /* get the next token */
1358  if (!token->isEndOfClause()) /* not at the end-of-clause? */
1359  {
1360  /* bad NOP instruction */
1362  }
1363  /* create a new translator object */
1364  RexxInstruction *newObject = new_instruction(NOP, Nop);
1365  /* dummy new to consruct VFT */
1366  new ((void *)newObject) RexxInstructionNop;
1367  return newObject; /* done, return this */
1368 }
1369 
1371 /****************************************************************************/
1372 /* Function: Create a NUMERIC instruction object */
1373 /****************************************************************************/
1374 {
1375  RexxObject *_expression = OREF_NULL; /* clear the expression */
1376  size_t _flags = 0; /* and the flags */
1377  RexxToken *token = nextReal(); /* get the next token */
1378  if (!token->isSymbol()) /* must have a symbol here */
1379  {
1380  /* raise the error */
1382  }
1383 
1384  unsigned short type = this->subKeyword(token); /* resolve the subkeyword */
1385  if (type != 0) refineSubclass(token, IS_SUBKEY);
1386  switch (type)
1387  { /* process the subkeyword */
1388  case SUBKEY_DIGITS: /* NUMERIC DIGITS instruction */
1389  token = nextReal(); /* get the next token */
1390  if (token->isEndOfClause()) /* just NUMERIC DIGITS? */
1391  {
1392  // reset to the default for this package
1393  _expression = OREF_NULL;
1394  break; /* we're all finished */
1395  }
1396  else if (token->isSymbol() && this->subKeyword(token) == SUBKEY_PROPAGATE)
1397  {
1398  // NUMERIC DIGITS PROPAGATE [expression]
1399  refineSubclass(token, IS_SUBKEY);
1400  _flags |= numeric_propagate;
1401  _expression = this->expression(TERM_EOC);
1402  }
1403  else
1404  {
1405  // NUMERIC DIGITS expression
1406  previousToken();
1407  _expression = this->expression(TERM_EOC);
1408  }
1409  break;
1410 
1411  case SUBKEY_FORM: /* NUMERIC FORM instruction */
1412  token = nextReal(); /* get the next token */
1413  if (token->isEndOfClause()) /* just NUMERIC FORM? */
1414  {
1415  // reset to the default for this package
1416  _flags |= numeric_form_default;
1417  break; /* we're all finished */
1418  }
1419  /* have the keyword form? */
1420  else if (token->isSymbol())
1421  {
1422  /* resolve the subkeyword */
1423  /* and process */
1424  switch (this->subKeyword(token))
1425  {
1426 
1427  case SUBKEY_SCIENTIFIC: /* NUMERIC FORM SCIENTIFIC */
1428  refineSubclass(token, IS_SUBKEY);
1429  token = nextReal(); /* get the next token */
1430  /* end of the instruction? */
1431  if (!token->isEndOfClause())
1432  {
1433  /* this is an error */
1435  }
1436  break;
1437 
1438  case SUBKEY_ENGINEERING: /* NUMERIC FORM ENGINEERING */
1439  refineSubclass(token, IS_SUBKEY);
1440  /* switch to engineering */
1441  _flags |= numeric_engineering;
1442  token = nextReal(); /* get the next token */
1443  /* end of the instruction? */
1444  if (!token->isEndOfClause())
1445  {
1446  /* this is an error */
1448  }
1449  break;
1450 
1451  case SUBKEY_VALUE: /* NUMERIC FORM VALUE expr */
1452  refineSubclass(token, IS_SUBKEY);
1453  /* process the expression */
1454  _expression = this->expression(TERM_EOC);
1455  /* no expression? */
1456  if (_expression == OREF_NULL)
1457  {
1458  /* expression is required after value*/
1460  }
1461  break;
1462 
1463  default: /* invalid subkeyword */
1464  /* raise an error */
1466  break;
1467 
1468  }
1469  }
1470  else
1471  { /* NUMERIC FORM expr */
1472  previousToken(); /* step back a token */
1473  /* process the expression */
1474  _expression = this->expression(TERM_EOC);
1475  }
1476  break;
1477 
1478  case SUBKEY_FUZZ: /* NUMERIC FUZZ instruction */
1479  /* process the expression */
1480  _expression = this->expression(TERM_EOC);
1481  break;
1482 
1483  default: /* invalid subkeyword */
1485  break;
1486  }
1487  /* create a new translator object */
1488  RexxInstruction *newObject = new_instruction(NUMERIC, Numeric);
1489  /* now complete this */
1490  new ((void *)newObject) RexxInstructionNumeric(_expression, type, _flags);
1491  return newObject; /* done, return this */
1492 }
1493 
1495 /****************************************************************************/
1496 /* Function: Create an OPTIONS instruction object */
1497 /****************************************************************************/
1498 {
1499  /* process the expression */
1500  RexxObject *_expression = this->expression(TERM_EOC);
1501  if (_expression == OREF_NULL) /* no expression here? */
1502  /* this is invalid */
1504  /* create a new translator object */
1505  RexxInstruction *newObject = new_instruction(OPTIONS, Options);
1506  /* now complete this */
1507  new((void *)newObject) RexxInstructionOptions(_expression);
1508  return newObject; /* done, return this */
1509 }
1510 
1512  RexxToken *token) /* OTHERWISE token */
1513 /****************************************************************************/
1514 /* Function: Create an OTHERWISE instruction object */
1515 /****************************************************************************/
1516 {
1517  /* create a new translator object */
1518  RexxInstruction *newObject = new_instruction(OTHERWISE, Otherwise);
1519  /* now complete this */
1520  new ((void *)newObject) RexxInstructionOtherwise(token);
1521  return newObject; /* done, return this */
1522 }
1523 
1525  int argpull) /* type of parsing operation */
1526 /****************************************************************************/
1527 /* Function: Create a PARSE instruction object */
1528 /****************************************************************************/
1529 {
1530 
1531  RexxToken *token; /* current working token */
1532  unsigned short string_source; /* source of string data */
1533 
1534  size_t _flags = 0; /* new flag values */
1535  RexxObject *_expression = OREF_NULL; /* zero out the expression */
1536  if (argpull != KEYWORD_PARSE)
1537  { /* have one of the short forms? */
1538  string_source = argpull; /* set the proper source location */
1539  _flags |= parse_upper; /* we're uppercasing */
1540  }
1541  else
1542  { /* need to parse source keywords */
1543  int _keyword;
1544  for (;;)
1545  { /* loop through for multiple keywords*/
1546  token = nextReal(); /* get a token */
1547  /* not a symbol here? */
1548  if (!token->isSymbol())
1549  {
1550  /* this is an error */
1552  }
1553  /* resolve the keyword */
1554  _keyword = this->parseOption(token);
1555 
1556  switch (_keyword)
1557  { /* process potential modifiers */
1558 
1559  case SUBKEY_UPPER: /* doing uppercasing? */
1560  refineSubclass(token, IS_SUBKEY);
1561  if (_flags&parse_translate) /* already had a translation option? */
1562  {
1563  break; /* this is an unrecognized keyword */
1564  }
1565  _flags |= parse_upper; /* set the translate option */
1566  continue; /* go around for another one */
1567 
1568  case SUBKEY_LOWER: /* doing lowercasing? */
1569  refineSubclass(token, IS_SUBKEY);
1570  if (_flags&parse_translate) /* already had a translation option? */
1571  {
1572  break; /* this is an unrecognized keyword */
1573  }
1574  /* set the translate option */
1575  _flags |= parse_lower; /* set the translate option */
1576  continue; /* go around for another one */
1577 
1578  case SUBKEY_CASELESS: /* caseless comparisons? */
1579  refineSubclass(token, IS_SUBKEY);
1580  if (_flags&parse_caseless) /* already had this options? */
1581  {
1582  break; /* this is an unrecognized keyword */
1583  }
1584  /* set the translate option */
1585  _flags |= parse_caseless; /* set the scan option */
1586  continue; /* go around for another one */
1587  }
1588  break; /* fall out into source processing */
1589  }
1590 
1591  string_source = _keyword; /* set the source */
1592  switch (_keyword)
1593  { /* now process the parse option */
1594 
1595  case SUBKEY_PULL: /* PARSE PULL instruction */
1596  case SUBKEY_LINEIN: /* PARSE LINEIN instruction */
1597  case SUBKEY_ARG: /* PARSE ARG instruction */
1598  case SUBKEY_SOURCE: /* PARSE SOURCE instruction */
1599  case SUBKEY_VERSION: /* PARSE VERSION instruction */
1600  refineSubclass(token, IS_SUBKEY);
1601  break; /* this is already done */
1602 
1603  case SUBKEY_VAR: /* PARSE VAR name instruction */
1604  refineSubclass(token, IS_SUBKEY);
1605  token = nextReal(); /* get the next token */
1606  /* not a symbol token */
1607  if (!token->isSymbol())
1608  {
1609  /* this is an error */
1611  }
1612  /* get the variable retriever */
1613  _expression = (RexxObject *)this->addVariable(token);
1614  this->saveObject(_expression); /* protect it in the saveTable (required for large PARSE statements) */
1615  break;
1616 
1617  case SUBKEY_VALUE: /* need to process an expression */
1618  refineSubclass(token, IS_SUBKEY);
1619  _expression = this->expression(TERM_WITH | TERM_KEYWORD);
1620  if (_expression == OREF_NULL ) /* If script not complete, report error RI0001 */
1621  {
1622  //syntaxError(Error_Invalid_template_with);
1623  _expression = OREF_NULLSTRING ; // Set to NULLSTRING if not coded in script
1624  }
1625  this->saveObject(_expression); /* protecting in the saveTable is better for large PARSE statements */
1626 
1627  token = nextToken(); /* get the terminator */
1628  if (!token->isSymbol() || this->subKeyword(token) != SUBKEY_WITH)
1629  {
1630  /* got another error */
1632  }
1633  refineSubclass(token, IS_SUBKEY);
1634  break;
1635 
1636  default: /* unknown (or duplicate) keyword */
1637  /* report an error */
1639  break;
1640  }
1641  }
1642 
1643  RexxQueue *parse_template = this->subTerms; /* use the sub terms list template */
1644  int templateCount = 0; /* no template items */
1645  RexxQueue *_variables = this->terms; /* and the terms list for variables */
1646  int variableCount = 0; /* no variable items */
1647  token = nextReal(); /* get the next token */
1648 
1649  RexxTrigger *trigger;
1650 
1651  for (;;)
1652  { /* while still in the template */
1653  /* found the end? */
1654  if (token->isEndOfClause())
1655  {
1656  /* string trigger, null target */
1657  trigger = new (variableCount) RexxTrigger(TRIGGER_END, (RexxObject *)OREF_NULL, variableCount, _variables);
1658  variableCount = 0; /* have a new set of variables */
1659  /* add this to the trigger list */
1660  parse_template->push((RexxObject *)trigger);
1661  templateCount++; /* and step the count */
1662  break; /* done processing */
1663  }
1664  /* comma in the template? */
1665  else if (token->classId == TOKEN_COMMA)
1666  {
1667  trigger = new (variableCount) RexxTrigger(TRIGGER_END, (RexxObject *)OREF_NULL, variableCount, _variables);
1668  variableCount = 0; /* have a new set of variables */
1669  /* add this to the trigger list */
1670  parse_template->push((RexxObject *)trigger);
1671  parse_template->push(OREF_NULL); /* add an empty entry in the list */
1672  templateCount += 2; /* count both of these */
1673  }
1674  /* some variety of special trigger? */
1675  else if (token->classId == TOKEN_OPERATOR)
1676  {
1677  int trigger_type = 0;
1678  switch (token->subclass)
1679  { /* process the operator character */
1680 
1681  case OPERATOR_PLUS: /* +num or +(var) form */
1682  trigger_type = TRIGGER_PLUS; /* positive relative trigger */
1683  break;
1684 
1685  case OPERATOR_SUBTRACT: /* -num or -(var) form */
1686  trigger_type = TRIGGER_MINUS;/* negative relative trigger */
1687  break;
1688 
1689  case OPERATOR_EQUAL: /* =num or =(var) form */
1690  /* absolute column trigger */
1691  trigger_type = TRIGGER_ABSOLUTE;
1692  break;
1693 
1694  case OPERATOR_LESSTHAN: // <num or <(var)
1695  trigger_type = TRIGGER_MINUS_LENGTH;
1696  break;
1697 
1698  case OPERATOR_GREATERTHAN: // >num or >(var)
1699  trigger_type = TRIGGER_PLUS_LENGTH;
1700  break;
1701 
1702  default: /* something unrecognized */
1703  /* this is invalid */
1705  break;
1706  }
1707  token = nextReal(); /* get the next token */
1708  /* have a variable trigger? */
1709  if (token->classId == TOKEN_LEFT)
1710  {
1711  // parse off an expression in the parens.
1712  RexxObject *subExpr = this->parenExpression(token);
1713  // an expression is required
1714  if (subExpr == OREF_NULL)
1715  {
1717  }
1718  /* create the appropriate trigger */
1719  trigger = new (variableCount) RexxTrigger(trigger_type, subExpr, variableCount, _variables);
1720  variableCount = 0; /* have a new set of variables */
1721  /* add this to the trigger list */
1722  parse_template->push((RexxObject *)trigger);
1723  templateCount++; /* add this one in */
1724  }
1725  /* have a symbol? */
1726  else if (token->isSymbol())
1727  {
1728  /* non-variable symbol? */
1729  if (token->subclass != SYMBOL_CONSTANT)
1730  {
1731  /* this is invalid */
1733  }
1734  /* set the trigger type */
1735  /* create the appropriate trigger */
1736  trigger = new (variableCount) RexxTrigger(trigger_type, this->addText(token), variableCount, _variables);
1737  variableCount = 0; /* have a new set of variables */
1738  /* add this to the trigger list */
1739  parse_template->push((RexxObject *)trigger);
1740  templateCount++; /* step the counter */
1741  }
1742  /* at the end? */
1743  else if (token->isEndOfClause())
1744  {
1745  /* report the missing piece */
1747  }
1748  else
1749  {
1750  /* general position error */
1752  }
1753  }
1754  /* variable string trigger? */
1755  else if (token->classId == TOKEN_LEFT)
1756  {
1757  // parse off an expression in the parens.
1758  RexxObject *subExpr = this->parenExpression(token);
1759  // an expression is required
1760  if (subExpr == OREF_NULL)
1761  {
1763  }
1764  /* create the appropriate trigger */
1765  trigger = new (variableCount) RexxTrigger(_flags&parse_caseless ? TRIGGER_MIXED : TRIGGER_STRING, subExpr, variableCount, _variables);
1766  variableCount = 0; /* have a new set of variables */
1767  /* add this to the trigger list */
1768  parse_template->push((RexxObject *)trigger);
1769  templateCount++; /* step the counter */
1770  }
1771  else if (token->isLiteral())
1772  { /* non-variable string trigger? */
1773  /* create the appropriate trigger */
1774  trigger = new (variableCount) RexxTrigger(_flags&parse_caseless ? TRIGGER_MIXED : TRIGGER_STRING,
1775  this->addText(token), variableCount, _variables);
1776  variableCount = 0; /* have a new set of variables */
1777  /* add this to the trigger list */
1778  parse_template->push((RexxObject *)trigger);
1779  templateCount++; /* step the counter */
1780  }
1781  else if (token->isSymbol())
1782  { /* symbol in the template? */
1783  /* non-variable symbol? */
1784  if (token->subclass == SYMBOL_CONSTANT)
1785  {
1786  /* create the appropriate trigger */
1787  trigger = new (variableCount) RexxTrigger(TRIGGER_ABSOLUTE, this->addText(token), variableCount, _variables);
1788  variableCount = 0; /* have a new set of variables */
1789  /* add this to the trigger list */
1790  parse_template->push((RexxObject *)trigger);
1791  templateCount++; /* step the counter */
1792  }
1793  /* place holder period? */
1794  else
1795  {
1796  if (token->subclass == SYMBOL_DUMMY)
1797  {
1798  _variables->push(OREF_NULL); /* just add an empty item */
1799  variableCount++; /* step the variable counter */
1800  }
1801  else /* have a variable, add to list */
1802  {
1803  // this is potentially a message term
1804  previousToken();
1806  if (term == OREF_NULL)
1807  {
1809  }
1810  _variables->push(term);
1811  variableCount++; /* step the variable counter */
1812  }
1813  }
1814  }
1815  else
1816  {
1817  /* this is invalid */
1819  }
1820  token = nextReal(); /* get the next token */
1821  }
1822  /* create a new translator object */
1823  RexxInstruction *newObject = new_variable_instruction(PARSE, Parse, sizeof(RexxInstructionParse) + (templateCount - 1) * sizeof(RexxObject *));
1824  /* now complete this */
1825  new ((void *)newObject) RexxInstructionParse(_expression, string_source, _flags, templateCount, parse_template);
1826  this->toss(_expression); /* release the expression, it is saved by newObject */
1827  return newObject; /* done, return this */
1828 }
1829 
1831 /****************************************************************************/
1832 /* Function: Create a new PROCEDURE translator object */
1833 /****************************************************************************/
1834 {
1835  RexxToken *token = nextReal(); /* get the next token */
1836  size_t variableCount = 0; /* no variables allocated yet */
1837  if (!token->isEndOfClause())
1838  { /* potentially PROCEDURE EXPOSE? */
1839  if (!token->isSymbol())/* not a symbol? */
1840  {
1841  /* must be a symbol here */
1843  }
1844  /* not the EXPOSE keyword? */
1845  if (this->subKeyword(token) != SUBKEY_EXPOSE)
1846  {
1848  }
1849  refineSubclass(token, IS_SUBKEY);
1850  /* go process the list */
1851  variableCount = this->processVariableList(KEYWORD_PROCEDURE);
1852  }
1853  /* create a new translator object */
1854  RexxInstruction *newObject = new_variable_instruction(PROCEDURE, Procedure, sizeof(RexxInstructionProcedure) + (variableCount - 1) * sizeof(RexxObject *));
1855  /* Initialize this new method */
1856  new ((void *)newObject) RexxInstructionProcedure(variableCount, this->subTerms);
1857  return newObject; /* done, return this */
1858 }
1859 
1861  int type) /* type of queueing operation */
1862 /****************************************************************************/
1863 /* Function: Create a QUEUE instruction object */
1864 /****************************************************************************/
1865 {
1866  /* process the expression */
1867  RexxObject *_expression = this->expression(TERM_EOC);
1868  /* create a new translator object */
1869  RexxInstruction *newObject = new_instruction(QUEUE, Queue);
1870  /* now complete this */
1871  new((void *)newObject) RexxInstructionQueue(_expression, type);
1872  return newObject; /* done, return this */
1873 }
1875 /****************************************************************************/
1876 /* Function: Create a new RAISE translator object */
1877 /****************************************************************************/
1878 {
1879  size_t arrayCount = SIZE_MAX; /* clear out the temporaries */
1880  RexxObject *_expression = OREF_NULL;
1881  RexxObject *description = OREF_NULL;
1882  RexxObject *additional = OREF_NULL;
1883  RexxObject *result = OREF_NULL;
1884  bool raiseReturn = false; /* default is exit form */
1885 
1886  RexxQueue *saveQueue = new_queue(); /* get a new queue item */
1887  this->saveObject(saveQueue); /* protect it */
1888  RexxToken *token = nextReal(); /* get the next token */
1889  /* no target specified or have a */
1890  if (!token->isSymbol()) /* bad token type? */
1891  {
1892  /* this is an error */
1894  }
1895  RexxString *_condition = token->value; /* use the condition string value */
1896  saveQueue->push(_condition); /* save the condition name */
1897  int _keyword = this->condition(token); /* check for the subkeywords */
1898  if (_keyword != 0) refineSubclass(token, IS_CONDITION);
1899  switch (_keyword)
1900  { /* process the different conditions */
1901 
1902  case CONDITION_FAILURE: /* RAISE FAILURE returncode */
1903  case CONDITION_ERROR: /* RAISE ERROR returncode */
1904  case CONDITION_SYNTAX: /* RAISE SYNTAX number */
1905  /* go get the keyword value expr. */
1906  _expression = this->constantExpression();
1907  if (_expression == OREF_NULL)
1908  { /* no expression given? */
1909  token = nextToken(); /* get the terminator token */
1910  /* this is an invalid expression */
1912  }
1913  saveQueue->queue(_expression); /* protect it */
1914  break;
1915 
1916  case CONDITION_USER: /* CONDITION USER usercondition */
1917  token = nextReal(); /* get the next token */
1918  /* bad token type? */
1919  if (!token->isSymbol())
1920  {
1921  /* this is an error */
1923  }
1924  _condition = token->value; /* get the token string value */
1925  /* condition name is "USER condition"*/
1926  _condition = _condition->concatToCstring(CHAR_USER_BLANK);
1927  /* get the common version */
1928  _condition = this->commonString(_condition);
1929  saveQueue->queue(_condition); /* save the condition */
1930  break;
1931 
1932  case CONDITION_HALT: /* CONDITION HALT */
1933  case CONDITION_NOMETHOD: /* CONDITION NOMETHOD */
1934  case CONDITION_NOSTRING: /* CONDITION NOSTRING */
1935  case CONDITION_NOTREADY: /* CONDITION NOTREADY */
1936  case CONDITION_NOVALUE: /* CONDITION NOVALUE */
1937  case CONDITION_LOSTDIGITS: /* CONDITION NUMERIC */
1938  case CONDITION_PROPAGATE: /* CONDITION PROPAGATE */
1939  break; /* this is already processed above */
1940 
1941  default: /* invalid condition specified */
1942  /* this is a sub keyword error */
1944  break;
1945  }
1946  token = nextReal(); /* get the next token */
1947  while (!token->isEndOfClause())
1948  {/* while still more to process */
1949  if (!token->isSymbol())/* not a symbol token? */
1950  {
1951  /* this is an error */
1953  }
1954  _keyword = this->subKeyword(token); /* get the keyword value */
1955  if (_keyword != 0) refineSubclass(token, IS_SUBKEY);
1956  switch (_keyword)
1957  { /* process the subkeywords */
1958 
1959  case SUBKEY_DESCRIPTION: /* RAISE ... DESCRIPTION expr */
1960  if (description != OREF_NULL) /* have a description already? */
1961  {
1962  /* this is invalid */
1964  }
1965  /* get the keyword value */
1966  description = this->constantExpression();
1967  if (description == OREF_NULL) /* no expression here? */
1968  {
1969  /* this is invalid */
1971  }
1972  saveQueue->queue(description); /* protect this */
1973  break;
1974 
1975  case SUBKEY_ADDITIONAL: /* RAISE ... ADDITIONAL expr */
1976  /* have a additional already? */
1977  if (additional != OREF_NULL || arrayCount != SIZE_MAX)
1978  {
1979  /* this is invalid */
1981  }
1982  /* get the keyword value */
1983  additional = this->constantExpression();
1984  /* no expression here? */
1985  if (additional == OREF_NULL)
1986  {
1987  /* this is invalid */
1989  }
1990  saveQueue->queue(additional); /* protect this */
1991  break;
1992 
1993  case SUBKEY_ARRAY: /* RAISE ... ARRAY expr */
1994  /* have a additional already? */
1995  if (additional != OREF_NULL || arrayCount != SIZE_MAX)
1996  {
1997  /* this is invalid */
1999  }
2000  token = nextReal(); /* get the next token */
2001  /* not an expression list starter? */
2002  if (token->classId != TOKEN_LEFT)
2003  {
2004  /* this is invalid */
2006  }
2007  /* process the array list */
2008  {
2009  size_t namedArgCount=0; // named arguments not allowed, will be always 0
2010  /*arrayCount =*/ this->argList(token, TERM_RIGHT, false, /*byref*/arrayCount, /*byref*/namedArgCount);
2011  }
2012  break;
2013 
2014  case SUBKEY_RETURN: /* RAISE ... RETURN expr */
2015  /* have a result already? */
2016  if (result != OREF_NULL)
2017  {
2018  /* this is invalid */
2020  }
2021  raiseReturn = true; /* remember this */
2022  /* get the keyword value */
2023  result = this->constantExpression();
2024  if (result != OREF_NULL) /* actually have one? */
2025  {
2026  saveQueue->queue(result); /* protect this */
2027  }
2028  break;
2029 
2030  case SUBKEY_EXIT: /* RAISE ... EXIT expr */
2031  if (result != OREF_NULL) /* have a result already? */
2032  {
2033  /* this is invalid */
2035  }
2036  /* get the keyword value */
2037  result = this->constantExpression();
2038  if (result != OREF_NULL) /* actually have one? */
2039  {
2040  saveQueue->queue(result); /* protect this */
2041  }
2042  break;
2043 
2044  default: /* invalid subkeyword */
2045  /* this is a sub keyword error */
2047  break;
2048  }
2049  token = nextReal(); /* step to the next keyword */
2050  }
2051 
2052  RexxInstruction *newObject;
2053 
2054  if (arrayCount != SIZE_MAX) /* have the array version? */
2055  {
2056  /* create a new translator object */
2057  newObject = new_variable_instruction(RAISE, Raise, sizeof(RexxInstructionRaise) + (arrayCount - 1) * sizeof(RexxObject *));
2058  }
2059  else /* static instruction size */
2060  {
2061  newObject = new_instruction(RAISE, Raise);
2062  }
2063  /* now complete this */
2064  new ((void *)newObject) RexxInstructionRaise(_condition, _expression, description, additional, result, arrayCount, this->subTerms, raiseReturn);
2065  this->toss(saveQueue); /* release the GC lock */
2066  return newObject; /* done, return this */
2067 }
2068 
2070 /****************************************************************************/
2071 /* Function: Create a REPLY instruction object */
2072 /****************************************************************************/
2073 {
2074  RexxObject *_expression = this->expression(TERM_EOC);
2075  /* create a new translator object */
2076  RexxInstruction *newObject = new_instruction(REPLY, Reply);
2077  /* now complete this */
2078  new ((void *)newObject) RexxInstructionReply(_expression);
2079  return newObject; /* done, return this */
2080 }
2081 
2083 /****************************************************************************/
2084 /* Function: Create a RETURN instruction object */
2085 /****************************************************************************/
2086 {
2087  /* process the expression */
2088  RexxObject *_expression = this->expression(TERM_EOC);
2089  /* create a new translator object */
2090  RexxInstruction *newObject = new_instruction(RETURN, Return);
2091  /* now complete this */
2092  new ((void *)newObject) RexxInstructionReturn(_expression);
2093  return newObject; /* done, return this */
2094 }
2095 
2097 /****************************************************************************/
2098 /* Function: Create a SAY instruction object */
2099 /****************************************************************************/
2100 {
2101  RexxObject *_expression = this->expression(TERM_EOC);
2102  /* create a new translator object */
2103  RexxInstruction *newObject = new_instruction(SAY, Say);
2104  /* now complete this */
2105  new ((void *)newObject) RexxInstructionSay(_expression);
2106  return newObject; /* done, return this */
2107 }
2108 
2110 /****************************************************************************/
2111 /* Function: Create a SELECT instruction object */
2112 /****************************************************************************/
2113 {
2114  // SELECT can be either SELECT; or SELECT LABEL name;
2115  // for saved image compatibility, we have different classes for this
2116  // depending on the form used.
2117  RexxToken *token = nextReal();
2118  // easy version, no LABEL.
2119  if (token->isEndOfClause())
2120  {
2121  // just a simple SELECT type
2122  RexxInstruction *newObject = new_instruction(SELECT, Select);
2123  new ((void *)newObject) RexxInstructionSelect(OREF_NULL);
2124  return newObject;
2125  }
2126  else if (!token->isSymbol())
2127  {
2128  // not a LABEL keyword, this is bad
2130  }
2131 
2132  // potentially a label. Check the keyword value
2133  if (this->subKeyword(token) != SUBKEY_LABEL)
2134  {
2135  /* raise an error */
2137  }
2138  refineSubclass(token, IS_SUBKEY);
2139  // ok, get the label now
2140  token = nextReal();
2141  // this is required, and must be a symbol
2142  if (!token->isSymbol())
2143  {
2145  }
2146 
2147  RexxString *label = token->value;
2148  token = nextReal();
2149  // this must be the end of the clause
2150  if (!token->isEndOfClause())
2151  {
2153  }
2154 
2155  // ok, finally allocate this and return
2156  RexxInstruction *newObject = new_instruction(SELECT, Select);
2157  new ((void *)newObject) RexxInstructionSelect(label);
2158  return newObject;
2159 }
2160 
2162 /****************************************************************************/
2163 /* Function: Create a SIGNAL instruction object */
2164 /****************************************************************************/
2165 {
2166  bool signalOff = false; /* not a SIGNAL OFF instruction */
2167  RexxObject *_expression = OREF_NULL; /* no expression yet */
2168  RexxString *name = OREF_NULL; /* no name */
2169  RexxString *_condition = OREF_NULL; /* and no condition */
2170  size_t _flags = 0; /* no flags */
2171  RexxToken *token = nextReal(); /* get the next token */
2172 
2173  if (token->isEndOfClause()) /* no target specified? */
2174  {
2175  /* this is an error */
2177  }
2178  /* implicit value form? */
2179  else if (!token->isSymbolOrLiteral())
2180  {
2181  previousToken(); /* step back a token */
2182  /* go process the expression */
2183  _expression = this->expression(TERM_EOC);
2184  }
2185  else
2186  { /* have a real target */
2187  /* may have to process ON/OFF forms */
2188  if (token->isSymbol())
2189  {
2190  /* check for the subkeywords */
2191  int _keyword = this->subKeyword(token);
2192  if (_keyword == SUBKEY_ON)
2193  { /* SIGNAL ON instruction? */
2194  refineSubclass(token, IS_SUBKEY);
2195  _flags |= signal_on; /* this is a SIGNAL ON */
2196  token = nextReal(); /* get the next token */
2197  /* no condition specified or not a */
2198  /* symbol? */
2199  if (!token->isSymbol())
2200  {
2201  /* this is an error */
2203  }
2204  /* get the condition involved */
2205  _keyword = this->condition(token);
2206  /* invalid condition specified? */
2207  if (_keyword == 0 || _keyword == CONDITION_PROPAGATE)
2208  {
2209  /* got an error here */
2211  }
2212  /* actually a USER condition request?*/
2213  else if (_keyword == CONDITION_USER)
2214  {
2215  refineSubclass(token, IS_CONDITION);
2216  token = nextReal(); /* get the next token */
2217  /* no condition specified or not a */
2218  /* symbol? */
2219  if (!token->isSymbol())
2220  {
2221  /* this is an error */
2223  }
2224  name = token->value; /* set the default target */
2225  /* condition name is "USER condition"*/
2226  _condition = name->concatToCstring(CHAR_USER_BLANK);
2227  /* save the condition name */
2228  _condition = this->commonString(_condition);
2229  }
2230  else
2231  { /* language defined condition */
2232  name = token->value; /* set the default target */
2233  _condition = name; /* condition is the same as target */
2234  }
2235  token = nextReal(); /* get the next token */
2236  /* anything real here? */
2237  if (!token->isEndOfClause())
2238  {
2239  /* not a symbol? */
2240  if (!token->isSymbol())
2241  {
2242  /* this is an error */
2244  }
2245  /* not the name token? */
2246  if (this->subKeyword(token) != SUBKEY_NAME)
2247  {
2248  /* got an error here */
2250  }
2251  refineSubclass(token, IS_SUBKEY);
2252  token = nextReal(); /* get the next token */
2253  /* not got a symbol here? */
2254  if (!token->isSymbolOrLiteral())
2255  {
2256  /* this is an error */
2258  }
2259  name = token->value; /* set the new target location */
2260  token = nextReal(); /* get the next token */
2261  /* must have the clause end here */
2262  if (!token->isEndOfClause())
2263  {
2264  /* this is an error */
2266  }
2267  }
2268  }
2269  else if (_keyword == SUBKEY_OFF)
2270  {/* SIGNAL OFF instruction? */
2271  refineSubclass(token, IS_SUBKEY);
2272  signalOff = true; /* doing a SIGNAL OFF */
2273  token = nextReal(); /* get the next token */
2274  /* no condition specified or not a */
2275  /* symbol? */
2276  if (!token->isSymbol())
2277  {
2278  /* this is an error */
2280  }
2281  /* get the condition involved */
2282  _keyword = this->condition(token);
2283  /* invalid condition specified? */
2284  if (_keyword == 0 || _keyword == CONDITION_PROPAGATE)
2285  {
2286  /* got an error here */
2288  }
2289  /* actually a USER condition request?*/
2290  else if (_keyword == CONDITION_USER)
2291  {
2292  refineSubclass(token, IS_CONDITION);
2293  token = nextReal(); /* get the next token */
2294  /* no condition specified or not a */
2295  /* symbol? */
2296  if (!token->isSymbol())
2297  {
2298  /* this is an error */
2300  }
2301  _condition = token->value; /* get the token string value */
2302  /* condition name is "USER condition"*/
2303  _condition = _condition->concatToCstring(CHAR_USER_BLANK);
2304  /* save the condition name */
2305  _condition = this->commonString(_condition);
2306  }
2307  else /* language defined condition */
2308  {
2309  _condition = token->value; /* set the condition name */
2310  }
2311  token = nextReal(); /* get the next token */
2312  /* must have the clause end here */
2313  if (!token->isEndOfClause())
2314  {
2315  /* this is an error */
2317  }
2318  }
2319  /* is this the value keyword form? */
2320  else if (_keyword == SUBKEY_VALUE)
2321  {
2322  refineSubclass(token, IS_SUBKEY);
2323  /* get the expression */
2324  _expression = this->expression(TERM_EOC);
2325  if (_expression == OREF_NULL) /* no expression here? */
2326  {
2327  /* this is invalid */
2329  }
2330  }
2331  else
2332  { /* normal SIGNAL instruction */
2333  name = token->value; /* set the signal target */
2334  token = nextReal(); /* step to the next token */
2335  /* not the end? */
2336  if (!token->isEndOfClause())
2337  {
2338  /* have an error */
2340  }
2341  }
2342  }
2343  else
2344  { /* signal with a string target */
2345  name = token->value; /* set the signal target */
2346  token = nextReal(); /* step to the next token */
2347  if (!token->isEndOfClause()) /* not the end? */
2348  {
2349  /* have an error */
2351  }
2352  }
2353  }
2354  /* create a new translator object */
2355  RexxInstruction *newObject = new_instruction(SIGNAL, Signal);
2356  ProtectedObject p(newObject); // jlf: probably not neded, already protected by this->currentInstruction
2357  /* now complete this */
2358  new ((void *)newObject) RexxInstructionSignal(_expression, _condition, name, _flags);
2359  if (!signalOff) /* need to resolve later? */
2360  {
2361  this->addReference((RexxObject *)newObject); /* add to table of references */
2362  }
2363  return newObject; /* done, return this */
2364 }
2365 
2367  RexxToken *token, /* THEN keyword token */
2368  RexxInstructionIf *parent ) /* target parent IF or WHEN clause */
2369 /****************************************************************************/
2370 /* Function: Create a THEN instruction object */
2371 /****************************************************************************/
2372 {
2373  /* create a new translator object */
2374  RexxInstruction *newObject = new_instruction(THEN, Then);
2375  /* now complete this */
2376  new ((void *)newObject) RexxInstructionThen(token, parent);
2377  return newObject; /* done, return this */
2378 }
2379 
2381 /****************************************************************************/
2382 /* Function: Create a TRACE instruction object */
2383 /****************************************************************************/
2384 {
2385  size_t setting = TRACE_NORMAL; /* set default trace mode */
2386  wholenumber_t debug_skip = 0; /* no skipping */
2387  size_t trcFlags = 0; /* no translated flags */
2388  RexxObject *_expression = OREF_NULL; /* not expression form */
2389  RexxToken *token = nextReal(); /* get the next token */
2390 
2391  if (!token->isEndOfClause())
2392  { /* more than just TRACE? */
2393  /* is this a symbol? */
2394  if (token->isSymbol())
2395  {
2396  /* TRACE VALUE expr? */
2397  if (this->subKeyword(token) == SUBKEY_VALUE)
2398  {
2399  refineSubclass(token, IS_SUBKEY);
2400  /* process the expression */
2401  _expression = this->expression(TERM_EOC);
2402  if (_expression == OREF_NULL) /* no expression? */
2403  {
2404  /* expression is required after value*/
2406  }
2407  }
2408  else
2409  { /* must have a symbol here */
2410  RexxString *value = token->value; /* get the string value */
2411  token = nextReal(); /* get the next token */
2412  /* end of the instruction? */
2413  if (!token->isEndOfClause())
2414  {
2415  /* this is an error */
2417  }
2418  if (!value->requestNumber(debug_skip, number_digits()))
2419  {
2420  debug_skip = 0; /* belt and braces */
2421  char badOption = 0;
2422  /* process the setting */
2423  if (!parseTraceSetting(value, setting, trcFlags, badOption))
2424  {
2426  }
2427  }
2428  else
2429  {
2430  setting = 0; /* not a normal setting situation */
2431  }
2432  }
2433  }
2434  else if (token->isLiteral())
2435  { /* is this a string? */
2436  RexxString *value = token->value; /* get the string value */
2437  token = nextReal(); /* get the next token */
2438  if (!token->isEndOfClause()) /* end of the instruction? */
2439  {
2440  /* this is an error */
2442  }
2443  if (!value->requestNumber(debug_skip, number_digits()))
2444  {
2445  debug_skip = 0; /* belt and braces */
2446  char badOption = 0;
2447  /* process the setting */
2448  if (!parseTraceSetting(value, setting, trcFlags, badOption))
2449  {
2451  }
2452  }
2453  else
2454  {
2455  setting = 0; /* not a normal setting situation */
2456  }
2457  }
2458  /* is this a minus sign? */
2459  else if (token->subclass == OPERATOR_SUBTRACT || token->subclass == OPERATOR_PLUS)
2460  {
2461  /* minus form? */
2462  if (token->subclass == OPERATOR_SUBTRACT)
2463  {
2464  setting |= DEBUG_NOTRACE; // turn on the no tracing flag
2465  }
2466  setting = 0; /* indicate a debug version */
2467  token = nextReal(); /* get the next token */
2468  if (token->isEndOfClause()) /* end of the instruction? */
2469  {
2470  /* this is an error */
2472  }
2473  RexxString *value = token->value; /* get the string value */
2474  token = nextReal(); /* get the next token */
2475 
2476  if (!token->isEndOfClause()) /* end of the instruction? */
2477  {
2478  /* this is an error */
2480  }
2481  if (!value->requestNumber(debug_skip, number_digits()))
2482  {
2483  /* have an error */
2485  }
2486  }
2487  else
2488  { /* implicit value form */
2489  previousToken(); /* step back a token */
2490  /* process the expression */
2491  _expression = this->expression(TERM_EOC);
2492  }
2493  }
2494  /* create a new translator object */
2495  RexxInstruction *newObject = new_instruction(TRACE, Trace);
2496  /* now complete this */
2497  new ((void *)newObject) RexxInstructionTrace(_expression, setting, trcFlags, debug_skip);
2498  return newObject; /* done, return this */
2499 }
2500 
2502 /****************************************************************************/
2503 /* Function: Create a new UPPER translator object */
2504 /****************************************************************************/
2505 {
2506  /* go process the list */
2507  size_t variableCount = this->processVariableList(KEYWORD_UPPER);
2508  /* create a new translator object */
2509  RexxInstruction *newObject = new_variable_instruction(UPPER, Upper, sizeof(RexxInstructionUpper) + (variableCount - 1) * sizeof(RexxObject *));
2510  /* now complete this */
2511  new ((void *)newObject) RexxInstructionUpper(variableCount, this->subTerms);
2512  return newObject; /* done, return this */
2513 }
2514 
2515 /**
2516  * Parse a USE STRICT ARG instruction.
2517  *
2518  * @return The executable instruction object.
2519  */
2521 {
2522  bool strictChecking = false; // no strict checking enabled yet
2523  bool autoCreation = false;
2524  bool namedArg = false;
2525 
2526  // The STRICT keyword turns this into a different instruction with different
2527  // syntax rules
2528  RexxToken *token = nextReal();
2529 
2530  if (subKeyword(token) == SUBKEY_STRICT)
2531  {
2532  refineSubclass(token, IS_SUBKEY);
2533  token = nextReal(); // skip over the token
2534  strictChecking = true; // apply the strict checks.
2535  }
2536 
2537  if (subKeyword(token) == SUBKEY_AUTO)
2538  {
2539  refineSubclass(token, IS_SUBKEY);
2540  token = nextReal(); // skip over the token
2541  autoCreation = true;
2542  }
2543 
2544  if (subKeyword(token) == SUBKEY_NAMED)
2545  {
2546  refineSubclass(token, IS_SUBKEY);
2547  token = nextReal(); // skip over the token
2548  namedArg = true;
2549  }
2550 
2551  // the only subkeyword supported is ARG
2552  if (subKeyword(token) != SUBKEY_ARG)
2553  {
2555  }
2556  refineSubclass(token, IS_SUBKEY);
2557 
2558  // we accumulate 2 sets of data here, so we need 2 queues to push them in
2559  // if this is the SIMPLE version, the second queue will be empty.
2560  size_t variableCount = 0;
2561  RexxQueue *variable_list = new_queue(); // we might be parsing message terms, so we can't use the subterms list.
2562  saveObject(variable_list);
2563  RexxQueue *defaults_list = new_queue();
2564  saveObject(defaults_list);
2565  RexxQueue *minimumLength_list = new_queue(); // Minimum length for abbreviation
2566  saveObject(minimumLength_list);
2567  token = nextReal(); /* get the next token */
2568 
2569  bool allowOptionals = false; // we don't allow trailing optionals unless the list ends with "..."
2570  // keep processing tokens to the end
2571  while (!token->isEndOfClause())
2572  {
2573  // this could be a token to skip a variable
2574  if (token->classId == TOKEN_COMMA)
2575  {
2577 
2578  // this goes on as a variable, but an empty entry to process.
2579  // we also need to push empty entries on the other queues to keep everything in sync.
2580  variable_list->push(OREF_NULL);
2581  defaults_list->push(OREF_NULL);
2582  minimumLength_list->push(OREF_NULL);
2583  variableCount++;
2584  // step to the next token, and go process more
2585  token = nextReal();
2586  continue;
2587  }
2588  else // something real. This could be a single symbol or a message term
2589  {
2590  // we might have an ellipsis (...) on the end of the list meaning stop argument checking at that point
2591  if (token->isSymbol())
2592  {
2593  // is this an ellipsis symbol?
2594  if (token->value->strCompare(CHAR_ELLIPSIS))
2595  {
2596  // ok, this is the end of everything. Tell the instructions to not enforce the max rules
2597  allowOptionals = true;
2598  // but we still need to make sure it's at the end
2599  token = nextReal();
2600  if (!token->isEndOfClause())
2601  {
2603  }
2604  break; // done parsing
2605  }
2606  }
2607 
2608 
2609  previousToken(); // push the current token back for term processing
2610  // see if we can get a variable or a message term from this
2611  RexxObject *retriever = variableOrMessageTerm();
2612  if (retriever == OREF_NULL)
2613  {
2615  }
2616  // A message term assignment is not allowed for USE NAMED
2617  if (namedArg && ((RexxVariableBase *)retriever)->isAllowedForUseNamed() == false)
2618  {
2620  }
2621  variable_list->push(retriever);
2622  variableCount++;
2623  token = nextReal();
2624 
2625  // For named argument only : optional minimum length specified after the name
2626  // USE NAMED ARG myname(4)
2627  if (namedArg && token->classId == TOKEN_LEFT)
2628  {
2629  RexxToken *tokenLeft = token; // will be used for error message
2630  token = nextReal();
2631 
2632  // if "+" then skip it
2633  if (token->isOperator() && token->subclass == OPERATOR_PLUS)
2634  {
2635  token = nextReal();
2636  }
2637  RexxString *token_strvalue = token->value;
2638  size_t token_intvalue = 0;
2639  if (token->subclass == SYMBOL_CONSTANT
2640  && token->numeric == INTEGER_CONSTANT
2641  && token_strvalue->requestUnsignedNumber(token_intvalue, number_digits())
2642  && token_intvalue > 0)
2643  {
2644  RexxInteger * minimumLength = new_integer(token_intvalue);
2645  ProtectedObject p(minimumLength);
2646  minimumLength_list->push(minimumLength);
2647  }
2648  else
2649  {
2650  RexxString *message = new_string("Named argument minimum length must be a positive whole number");
2653  }
2654  token = nextReal();
2655  if (token->classId != TOKEN_RIGHT)
2656  {
2658  }
2659  token = nextReal();
2660  }
2661  else
2662  {
2663  minimumLength_list->push(OREF_NULL);
2664  }
2665 
2666  // a terminator takes us out. We need to keep all 3 lists in sync with dummy entries.
2667  if (token->isEndOfClause())
2668  {
2669  defaults_list->push(OREF_NULL);
2670  break;
2671  }
2672  // if we've hit a comma here, step to the next token and continue with the next variable
2673  else if (token->classId == TOKEN_COMMA)
2674  {
2675  defaults_list->push(OREF_NULL);
2676  token = nextReal();
2677  continue;
2678  }
2679 
2680  // if this is NOT a comma, we potentially have a
2681  // default value
2682 
2683  if (token->subclass == OPERATOR_EQUAL)
2684  {
2685  // this is a constant expression value. Single token forms
2686  // are fine without parens, more complex forms require parens as
2687  // delimiters.
2688  RexxObject *defaultValue = constantExpression();
2689  // no expression is an error
2690  if (defaultValue == OREF_NULL)
2691  {
2693  }
2694 
2695  // add this to the defaults
2696  defaults_list->push(defaultValue);
2697  // step to the next token
2698  token = nextReal();
2699  // a terminator takes us out. We need to keep all 3 lists in sync with dummy entries.
2700  if (token->isEndOfClause())
2701  {
2702  break;
2703  }
2704  // if we've hit a comma here, step to the next token and continue with the next variable
2705  else if (token->classId == TOKEN_COMMA)
2706  {
2707  token = nextReal();
2708  continue;
2709  }
2710  }
2711  else
2712  {
2713  // if not an assignment, this needs to be a comma.
2715  }
2716  }
2717  }
2718 
2719  RexxInstruction *newObject = new_variable_instruction(USE, Use, sizeof(RexxInstructionUseStrict) + (variableCount == 0 ? 0 : (variableCount - 1)) * sizeof(UseVariable));
2720  new ((void *)newObject) RexxInstructionUseStrict(variableCount, strictChecking, allowOptionals, autoCreation, namedArg, variable_list, defaults_list, minimumLength_list);
2721 
2722  // release the object locks and return;
2723  removeObj(variable_list);
2724  removeObj(defaults_list);
2725  removeObj(minimumLength_list);
2726  return newObject;
2727 }
2728 
#define DO_COUNT
#define DO_OVER_WHILE
#define EXP_TO
#define CONTROLLED_UNTIL
#define SIMPLE_DO
#define DO_OVER_UNTIL
#define DO_COUNT_WHILE
#define DO_FOREVER
#define DO_WHILE
#define DO_UNTIL
#define EXP_BY
#define DO_OVER
#define DO_COUNT_UNTIL
#define EXP_FOR
#define CONTROLLED_WHILE
#define CONTROLLED_DO
#define forward_continue
RexxInteger * new_integer(wholenumber_t v)
#define numeric_engineering
#define numeric_propagate
#define numeric_form_default
size_t number_digits()
Definition: Numerics.hpp:155
#define parse_lower
#define parse_upper
#define parse_caseless
#define parse_translate
#define TRIGGER_MIXED
#define TRIGGER_END
#define TRIGGER_PLUS_LENGTH
#define TRIGGER_MINUS
#define TRIGGER_MINUS_LENGTH
#define TRIGGER_STRING
#define TRIGGER_ABSOLUTE
#define TRIGGER_PLUS
#define TheInstructionBehaviour
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
#define INTERPRET
#define OREF_NULL
Definition: RexxCore.h:60
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define Error_Variable_expected_PARSE
#define Error_Invalid_subkeyword_message
#define Error_Symbol_expected_user
#define Error_Invalid_subkeyword_select
#define Error_Invalid_subkeyword_forward_option
#define Error_Invalid_subkeyword_description
#define Error_Invalid_subkeyword_callon
#define Error_Invalid_subkeyword_guard_on
#define Error_Variable_reference_use
#define Error_Invalid_template_trigger
#define Error_Symbol_expected_raise
#define Error_Invalid_data_form
#define Error_Variable_symbol_expected_USE_NAMED
#define Error_Invalid_expression_forward_message
#define Error_Unmatched_parenthesis_paren
#define Error_Invalid_expression_raise_description
#define Error_Invalid_subkeyword_to
#define Error_Invalid_do_forever
#define Error_Invalid_subkeyword_calloff
#define Error_Variable_expected_USE
#define Error_Invalid_expression_control
#define Error_Invalid_subkeyword_additional
#define Error_Invalid_expression_trace
#define Error_Invalid_data_name
#define Error_Invalid_subkeyword_signaloff
#define Error_Symbol_or_string_signal
#define Error_Invalid_whole_number_trace
#define Error_Invalid_trace_trace
#define Error_Invalid_subkeyword_result
#define Error_Symbol_or_string_call
#define Error_Invalid_subkeyword_continue
#define Error_Invalid_subkeyword_signalon
#define Error_Invalid_expression_guard
#define Error_Invalid_expression_if
#define Error_Invalid_expression_general
#define Error_Symbol_or_string_name
#define Error_Invalid_subkeyword_forward_class
#define Error_Invalid_data_trace
#define Error_Symbol_expected_off
#define Error_Invalid_expression_options
#define Error_Invalid_expression_raise_list
#define Error_Symbol_expected_leave
#define Error_Invalid_expression_form
#define Error_Invalid_expression_forward_class
#define Error_Invalid_data_condition
#define Error_Invalid_expression_to
#define Error_Invalid_expression_call
#define Error_Invalid_expression_when
#define Error_Invalid_template_with
#define Error_Invalid_subkeyword_callonname
#define Error_Invalid_subkeyword_numeric
#define Error_Invalid_whole_number_user_defined
#define Error_Invalid_expression_forward_to
#define Error_Invalid_data_leave
#define Error_Skipped_variable_not_allowed_USE_NAMED
#define Error_Symbol_expected_end
#define Error_Invalid_expression_for
#define Error_Symbol_expected_numeric
#define Error_Symbol_expected_parse
#define Error_Invalid_expression_over
#define Error_Invalid_expression_assign
#define Error_Invalid_subkeyword_raise
#define Error_Invalid_subkeyword_use
#define Error_Invalid_subkeyword_signalonname
#define Error_Invalid_expression_use_strict_default
#define Error_Invalid_expression_parse
#define Error_Invalid_data_select
#define Error_Invalid_expression_raise_additional
#define Error_Symbol_expected_iterate
#define Error_Invalid_data_end
#define Error_Invalid_expression_signal
#define Error_Invalid_subkeyword_procedure
#define Error_Invalid_expression_interpret
#define Error_Symbol_expected_LABEL
#define Error_Invalid_data_nop
#define Error_Invalid_expression_forward_arguments
#define Error_Invalid_data_signal
#define Error_Invalid_subkeyword_guard
#define Error_Invalid_template_missing
#define Error_Invalid_expression_address
#define Error_Invalid_expression_user_defined
#define Error_Invalid_subkeyword_parse
#define Error_Symbol_expected_on
#define Error_Invalid_template_position
#define Error_Invalid_data_iterate
#define Error_Invalid_subkeyword_raiseoption
#define Error_Invalid_subkeyword_arguments
#define Error_Invalid_do_duplicate
#define Error_Invalid_subkeyword_form
#define Error_Symbol_expected_var
#define Error_Translation_use_strict_ellipsis
#define Error_Invalid_expression_by
#define signal_on
#define new_instruction(name, type)
Definition: SourceFile.hpp:102
#define new_variable_instruction(name, type, size)
Definition: SourceFile.hpp:103
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
#define SUBKEY_UNTIL
Definition: Token.hpp:230
#define SUBKEY_CLASS
Definition: Token.hpp:245
#define SUBKEY_WHILE
Definition: Token.hpp:236
#define SUBKEY_VAR
Definition: Token.hpp:233
#define SUBKEY_EXIT
Definition: Token.hpp:243
#define CONDITION_NOSTRING
Definition: Token.hpp:309
#define TOKEN_LITERAL
Definition: Token.hpp:79
#define SUBKEY_SCIENTIFIC
Definition: Token.hpp:226
#define KEYWORD_UPPER
Definition: Token.hpp:201
#define CONDITION_LOSTDIGITS
Definition: Token.hpp:315
#define KEYWORD_PARSE
Definition: Token.hpp:160
#define SUBKEY_MESSAGE
Definition: Token.hpp:246
#define CONDITION_SYNTAX
Definition: Token.hpp:313
#define OPERATOR_SUBTRACT
Definition: Token.hpp:111
#define SUBKEY_LOWER
Definition: Token.hpp:217
#define TOKEN_OPERATOR
Definition: Token.hpp:80
#define SUBKEY_LABEL
Definition: Token.hpp:248
#define SUBKEY_BY
Definition: Token.hpp:206
#define SUBKEY_EXPOSE
Definition: Token.hpp:211
#define OPERATOR_EQUAL
Definition: Token.hpp:120
#define KEYWORD_INSTRUCTION
Definition: Token.hpp:197
#define TERM_COND
Definition: Token.hpp:70
#define TOKEN_LEFT
Definition: Token.hpp:84
#define TERM_RIGHT
Definition: Token.hpp:57
#define SUBKEY_DESCRIPTION
Definition: Token.hpp:238
#define SUBKEY_RETURN
Definition: Token.hpp:242
#define SUBKEY_AUTO
Definition: Token.hpp:254
#define SYMBOL_CONSTANT
Definition: Token.hpp:98
#define TERM_CONTROL
Definition: Token.hpp:68
#define IS_BUILTIN
Definition: Token.hpp:320
#define SUBKEY_STRICT
Definition: Token.hpp:249
#define SUBKEY_ARGUMENTS
Definition: Token.hpp:247
#define IS_SUBKEY
Definition: Token.hpp:204
#define SUBKEY_WHEN
Definition: Token.hpp:235
#define SUBKEY_ADDITIONAL
Definition: Token.hpp:239
#define CONDITION_USER
Definition: Token.hpp:314
#define SUBKEY_ARRAY
Definition: Token.hpp:241
#define KEYWORD_PROCEDURE
Definition: Token.hpp:161
#define KEYWORD_LEAVE
Definition: Token.hpp:155
#define OPERATOR_PLUS
Definition: Token.hpp:110
#define CONDITION_PROPAGATE
Definition: Token.hpp:312
#define refineSubclass(token, refinedSubclass)
Definition: Token.hpp:51
#define SUBKEY_ENGINEERING
Definition: Token.hpp:210
#define OPERATOR_STRICT_EQUAL
Definition: Token.hpp:128
#define TERM_WITH
Definition: Token.hpp:64
#define SUBKEY_NAMED
Definition: Token.hpp:253
#define TOKEN_COMMA
Definition: Token.hpp:82
#define CONDITION_NOMETHOD
Definition: Token.hpp:308
#define TERM_KEYWORD
Definition: Token.hpp:66
#define CONDITION_NOVALUE
Definition: Token.hpp:311
#define SUBKEY_FOR
Definition: Token.hpp:212
#define CONDITION_ERROR
Definition: Token.hpp:305
#define KEYWORD_IF
Definition: Token.hpp:152
#define SUBKEY_FUZZ
Definition: Token.hpp:215
#define SUBKEY_FOREVER
Definition: Token.hpp:213
#define TERM_EOC
Definition: Token.hpp:56
#define CONDITION_FAILURE
Definition: Token.hpp:306
#define SUBKEY_OVER
Definition: Token.hpp:224
#define SUBKEY_VERSION
Definition: Token.hpp:234
#define OPERATOR_LESSTHAN
Definition: Token.hpp:124
#define OPERATOR_GREATERTHAN
Definition: Token.hpp:122
#define SUBKEY_NAMEDARGUMENTS
Definition: Token.hpp:252
#define KEYWORD_EXPOSE
Definition: Token.hpp:175
#define SUBKEY_TO
Definition: Token.hpp:229
#define SUBKEY_DIGITS
Definition: Token.hpp:207
#define SUBKEY_SOURCE
Definition: Token.hpp:227
#define SUBKEY_LINEIN
Definition: Token.hpp:216
#define TERM_IF
Definition: Token.hpp:72
#define SUBKEY_NAME
Definition: Token.hpp:219
#define SUBKEY_OFF
Definition: Token.hpp:221
#define CONDITION_NOTREADY
Definition: Token.hpp:310
#define SUBKEY_UPPER
Definition: Token.hpp:231
#define SUBKEY_ARG
Definition: Token.hpp:205
#define KEYWORD_DROP
Definition: Token.hpp:150
#define SUBKEY_WITH
Definition: Token.hpp:237
#define IS_CONDITION
Definition: Token.hpp:303
#define SUBKEY_PULL
Definition: Token.hpp:225
#define TOKEN_RIGHT
Definition: Token.hpp:85
#define SUBKEY_VALUE
Definition: Token.hpp:232
#define SUBKEY_PROPAGATE
Definition: Token.hpp:255
#define INTEGER_CONSTANT
Definition: Token.hpp:105
#define TOKEN_SYMBOL
Definition: Token.hpp:78
#define SUBKEY_ON
Definition: Token.hpp:222
#define SUBKEY_CASELESS
Definition: Token.hpp:218
#define SYMBOL_DUMMY
Definition: Token.hpp:103
#define CONDITION_HALT
Definition: Token.hpp:307
#define SUBKEY_FORM
Definition: Token.hpp:214
#define SUBKEY_CONTINUE
Definition: Token.hpp:244
size_t size()
Definition: ArrayClass.hpp:202
void makeAssignment(RexxSource *source)
RexxVariableBase * control
RexxString * label
RexxObject * forcount
RexxObject * initial
uint8_t expressions[3]
RexxObject * conditional
RexxObject * namedArgumentsExpression
uint16_t instructionFlags
void setType(size_t type)
void setEnd(size_t line, sizeB_t off)
virtual RexxObject * copy()
bool requestUnsignedNumber(stringsize_t &, size_t)
bool requestNumber(wholenumber_t &, size_t)
void push(RexxObject *obj)
Definition: QueueClass.hpp:81
void queue(RexxObject *obj)
Definition: QueueClass.hpp:82
RexxInstruction * loopNew()
RexxQueue * subTerms
Definition: SourceFile.hpp:513
void resetPosition(size_t p)
Definition: SourceFile.hpp:318
static int condition(RexxToken *)
RexxInstruction * labelNew()
RexxObject * parseLogical(RexxToken *first, int terminators)
RexxInstruction * forwardNew()
RexxInstruction * traceNew()
RexxInstruction * ifNew(int)
void previousToken()
Definition: SourceFile.hpp:314
RexxQueue * terms
Definition: SourceFile.hpp:512
void argList(RexxToken *, int, bool, size_t &, size_t &)
RexxToken * nextToken()
Definition: SourceFile.hpp:312
RexxObject * expression(int)
void setGuard()
RexxInstruction * messageAssignmentNew(RexxExpressionMessage *, RexxObject *)
RexxInstruction * exitNew()
RexxInstruction * exposeNew()
static int subKeyword(RexxToken *)
void syntaxError(int errorcode, RexxInstruction *i)
Definition: SourceFile.hpp:319
RexxInstruction * elseNew(RexxToken *)
RexxInstruction * raiseNew()
RexxInstruction * createLoop()
RexxInstruction * assignmentNew(RexxToken *)
RexxInstruction * messageAssignmentOpNew(RexxExpressionMessage *, RexxToken *, RexxObject *)
void addLabel(RexxInstruction *, RexxString *)
size_t flags
Definition: SourceFile.hpp:453
RexxObject * toss(RexxObject *)
void syntaxErrorAt(int errorcode, RexxToken *token)
Definition: SourceFile.hpp:321
RexxInstruction * signalNew()
RexxInstruction * leaveNew(int)
RexxInstruction * addressNew()
RexxInstruction * numericNew()
void addReference(RexxObject *reference)
Definition: SourceFile.hpp:295
RexxInstruction * upperNew()
RexxInstruction * endNew()
void isExposeValid()
void removeObj(RexxObject *object)
Definition: SourceFile.hpp:377
RexxInstruction * parseNew(int)
RexxInstruction * instructionNew(int)
void argArray(RexxToken *, int, bool, RexxArray *&, RexxArray *&)
RexxArray * getGuard()
RexxInstruction * useNew()
RexxInstruction * thenNew(RexxToken *, RexxInstructionIf *)
RexxInstruction * returnNew()
RexxInstruction * createDoLoop()
void RexxInstructionForwardCreate(RexxInstructionForward *)
RexxInstruction * dropNew()
RexxInstruction * optionsNew()
RexxInstruction * messageNew(RexxExpressionMessage *)
RexxInstruction * replyNew()
RexxString * commonString(RexxString *)
RexxInstruction * interpretNew()
RexxInstruction * sourceNewObject(size_t, RexxBehaviour *, int)
size_t processVariableList(int)
static int builtin(RexxToken *)
RexxObject * constantExpression()
RexxInstruction * doNew()
RexxInstruction * commandNew()
static const size_t TRACE_NORMAL
Definition: SourceFile.hpp:425
RexxInstruction * nopNew()
RexxObject * message(RexxObject *, bool, int)
RexxObject * variableOrMessageTerm()
RexxInstruction * queueNew(int)
RexxInstruction * sayNew()
RexxToken * nextReal()
Definition: SourceFile.hpp:313
RexxInstruction * assignmentOpNew(RexxToken *, RexxToken *)
void saveObject(RexxObject *object)
Definition: SourceFile.hpp:376
RexxVariableBase * addVariable(RexxString *)
RexxInstruction * otherwiseNew(RexxToken *)
RexxInstruction * guardNew()
RexxInstruction * endIfNew(RexxInstructionIf *)
static int parseOption(RexxToken *)
static const size_t DEBUG_NOTRACE
Definition: SourceFile.hpp:446
RexxObject * parenExpression(RexxToken *)
RexxQueue * namedSubTerms
Definition: SourceFile.hpp:514
void needVariable(RexxToken *)
Definition: SourceFile.cpp:382
RexxObject * addText(RexxToken *)
static bool parseTraceSetting(RexxString *, size_t &, size_t &, char &)
RexxInstruction * procedureNew()
size_t markPosition()
Definition: SourceFile.hpp:317
RexxInstruction * selectNew()
RexxInstruction * callNew()
RexxString * concatToCstring(const char *)
bool strCompare(const char *s)
int numeric
Definition: Token.hpp:450
RexxString * value
Definition: Token.hpp:447
const SourceLocation & getLocation()
Definition: Token.hpp:442
bool isSymbol()
Definition: Token.hpp:438
bool isSymbolOrLiteral()
Definition: Token.hpp:436
bool isOperator()
Definition: Token.hpp:439
bool isLiteral()
Definition: Token.hpp:434
bool isEndOfClause()
Definition: Token.hpp:440
int classId
Definition: Token.hpp:448
int subclass
Definition: Token.hpp:449
size_t getEndLine() const
sizeB_t getEndOffset() const
int type
Definition: cmdparse.cpp:383
ssize_t wholenumber_t
Definition: rexx.h:230
#define SIZE_MAX