SourceFile.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 Source File Class */
42 /* */
43 /******************************************************************************/
44 #include <ctype.h>
45 #include <string.h>
46 #include "RexxCore.h"
47 #include "StringClass.hpp"
48 #include "ArrayClass.hpp"
49 #include "DirectoryClass.hpp"
50 #include "BufferClass.hpp"
51 #include "RexxActivity.hpp"
52 #include "RexxActivation.hpp"
53 #include "MethodClass.hpp"
54 #include "RexxNativeCode.hpp"
55 #include "RexxCode.hpp"
57 #include "RexxSmartBuffer.hpp"
58 #include "SourceFile.hpp"
59 
60 #include "ExpressionFunction.hpp" /* expression terms */
61 #include "ExpressionMessage.hpp"
62 #include "ExpressionOperator.hpp"
63 #include "ExpressionLogical.hpp"
64 #include "ExpressionList.hpp"
65 
66 #include "ExpressionBaseVariable.hpp" /* base variable management class */
69 #include "ExpressionVariable.hpp"
71 #include "ExpressionStem.hpp"
72 
73 #include "RexxInstruction.hpp" /* base instruction definition */
74 #include "SelectInstruction.hpp"
75 #include "ElseInstruction.hpp"
76 #include "EndIf.hpp"
77 #include "DoInstruction.hpp"
78 #include "CallInstruction.hpp"
79 #include "ProtectedObject.hpp"
80 #include "CPPCode.hpp"
81 #include "SystemInterpreter.hpp"
82 #include "PackageClass.hpp"
83 #include "InterpreterInstance.hpp"
84 #include "ClassDirective.hpp"
85 #include "ExtensionDirective.hpp"
86 #include "LibraryDirective.hpp"
87 #include "RequiresDirective.hpp"
88 #include "PackageManager.hpp"
89 #include "SysFileSystem.hpp"
90 #include "RoutineClass.hpp"
91 #include "ActivationFrame.hpp"
92 #include "StackFrameClass.hpp"
93 #include "BlockClass.hpp"
94 
95 #define HOLDSIZE 60 /* room for 60 temporaries */
96 
97 typedef struct _LINE_DESCRIPTOR {
98  size_t position; /* position within the buffer */
99  size_t length; /* length of the line */
100 } LINE_DESCRIPTOR; /* line within a source buffer */
101 
102 #define line_delimiters "\r\n" /* stream file line end characters */
103 #define ctrl_z 0x1a // the end of file marker
104 
105 /**
106  * Create a source object with source provided from an array.
107  *
108  * @param programname
109  * The name of the program.
110  * @param source_array
111  * The array of the source lines.
112  */
113 RexxSource::RexxSource(RexxString *programname, RexxArray *source_array)
114 {
115  /* fill in the name */
116  setProgramName(programname);
117  /* fill in the source array */
118  OrefSet(this, this->sourceArray, source_array);
119  /* fill in the source size */
120  this->line_count = sourceArray->size();
121  this->position(1, 0); /* set position at the first line */
122 }
123 
124 
125 /**
126  * Create a source object with source provided from a buffer.
127  *
128  * @param programname
129  * The name of the program.
130  * @param source_buffer
131  * The source buffer holding the source data.
132  */
133 RexxSource::RexxSource(RexxString *programname, RexxBuffer *source_buffer)
134 {
135  /* fill in the name */
136  setProgramName(programname);
137  // we require a bit of protection while doing this
138  ProtectedObject p(this);
139  // initialize from the buffer data
140  initBuffered(source_buffer);
141 }
142 
143 
144 /**
145  * Create a source object with source provided from a a data buffer
146  * (not a buffer object).
147  *
148  * @param programname
149  * The name of the program.
150  * @param data The data buffer pointer.
151  * @param length the size of the source buffer.
152  */
153 RexxSource::RexxSource(RexxString *programname, const char *data, size_t length)
154 {
155  /* fill in the name */
156  setProgramName(programname);
157  // we require a bit of protection while doing this
158  ProtectedObject p(this);
159  // initialize from the buffer data
160  initBuffered(new_buffer(data, length));
161 }
162 
163 
164 /**
165  * Create a source object with source provided from a filo.
166  *
167  * @param programname
168  * The name of the program (also the file name)
169  */
171 {
172  /* fill in the name */
173  setProgramName(programname);
174  // we require a bit of protection while doing this
175  ProtectedObject p(this);
176  // read the file data and initialize.
177  initFile();
178 }
179 
180 
182  RexxBuffer *source_buffer) /* containing source buffer */
183 /******************************************************************************/
184 /* Function: Initialize a source object using the entire source as a */
185 /* stream buffer */
186 /******************************************************************************/
187 {
188  LINE_DESCRIPTOR descriptor; /* line description */
189  const char *scan; /* line scanning pointer */
190  const char *_current; /* current scan location */
191  char *start; /* start of the buffer */
192  size_t length; /* length of the buffer */
193 
194  extractNameInformation(); // make sure we have name information to work with
195  /* set the source buffer */
196  OrefSet(this, this->sourceBuffer, source_buffer);
197  RexxSmartBuffer *indices = new RexxSmartBuffer(1024);
198  ProtectedObject p(indices);
199  /* point to the data part */
200  start = this->sourceBuffer->getData();
201  /* get the buffer length */
202  length = this->sourceBuffer->getDataLength();
203 
204  // neutralize shell '#!...'
205  if (start[0] == '#' && start[1] == '!')
206  {
207  memcpy(start, "--", 2);
208  }
209 
210  descriptor.position = 0; /* fill in the "zeroth" position */
211  descriptor.length = 0; /* and the length */
212  /* add to the line list */
213  indices->copyData(&descriptor, sizeof(descriptor));
214  this->line_count = 0; /* start with zero lines */
215  /* look for an EOF mark */
216  scan = (const char *)memchr(start, ctrl_z, length);
217  if (scan != NULL) /* found one? */
218  {
219  length = scan - start; /* reduce the length */
220  }
221  _current = start; /* start at the beginning */
222  while (length != 0)
223  { /* loop until all done */
224  this->line_count++; /* add in another line */
225  /* set the start position */
226  descriptor.position = _current - start;
227  /* scan for a important character */
228  scan = Utilities::locateCharacter(_current, line_delimiters, length);
229  /* need to skip over null chars */
230  while (scan != OREF_NULL && *scan == '\0') // JLF : never enter the loop ? if scan is not null then *scan is necessarily \r or \n, but never \0
231  {
232  /* scan for a linend */
233  scan = Utilities::locateCharacter(scan + 1, line_delimiters, length - (scan - _current - 1));
234  }
235  if (scan == NULL)
236  { /* not found, go to the end */
237  _current = _current + length; /* step to the end */
238  descriptor.length = length; /* use the entire line */
239  length = 0; /* nothing left to process */
240  }
241  else
242  {
243  /* calculate this line length */
244  descriptor.length = scan - _current;
245  /* adjust scan at line end */
246  if (*scan == line_delimiters[0])
247  {/* CR encountered */
248  scan++; /* step the scan position */
249  /* now check for LF */
250  if (length > (size_t)(scan - _current))
251  {
252  if (*scan != '\0' && *scan == line_delimiters[1]) /* */
253  {
254  scan++; /* step again, if required */
255  }
256  }
257  }
258  else /* just a LF */
259  {
260  scan++; /* step the scan position */
261  }
262 
263  length -= scan - _current; /* reduce the length */
264  _current = scan; /* copy the scan pointer */
265  }
266  /* add to the line list */
267  indices->copyData(&descriptor, sizeof(descriptor));
268  }
269  /* throw away the buffer "wrapper" */
270  OrefSet(this, this->sourceIndices, indices->getBuffer());
271  this->position(1, 0); /* set position at the first line */
272 }
273 
274 
276 /******************************************************************************/
277 /* Function: Initialize a source object, reading the source from a file */
278 /******************************************************************************/
279 {
280  /* load the program file */
282  if (program_source == OREF_NULL) /* Program not found or read error? */
283  {
284  /* report this */
286  }
287 
288 #ifdef SCRIPTING
289  if (program_source->getDataLength() > 9)
290  {
291  char begin[10];
292  char end[4];
293  // check, if XML comments have to be removed from the script... (engine situation)
294  memcpy(begin,program_source->getData(), 9);
295  // hashvalue is the length of the buffer
296  memcpy(end, program_source->getData()+ (program_source->getDataLength()-3), 3);
297  begin[9]=end[3]=0x00;
298  if (!Utilities::strCaselessCompare("<![CDATA[",begin) && !Utilities::strCaselessCompare("]]>",end))
299  {
300  memcpy(program_source->getData(), " ", 9);
301  memcpy(program_source->getData() + (program_source->getDataLength() - 3), " ", 3);
302  }
303  }
304 #endif
305 
306  /* save the returned buffer */
307  OrefSet(this, this->sourceBuffer, program_source);
308  /* go process the buffer now */
309  this->initBuffered(this->sourceBuffer);
310 }
311 
312 
313 /**
314  * Extract various bits of the source name to give us directory,
315  * extension and file portions to be used for searches for additional
316  * files.
317  */
319 {
320  if (programName == OREF_NULL)
321  {
322  return;
323  }
324 
328 }
329 
330 
331 /**
332  * Set a program name for this source object. Usually used after
333  * a program restore to update the restored routine object. This
334  * will also update the extension and directory information.
335  *
336  * @param name The new program name.
337  */
339 {
340  OrefSet(this, this->programName, name);
342 }
343 
345 /******************************************************************************/
346 /* Function: Attempt to reconnect to the original source code file */
347 /******************************************************************************/
348 {
349  if (!(this->flags&reclaim_possible)) /* no chance of getting this? */
350  {
351  return false; /* just get out of here */
352  }
353  this->initFile(); /* go reinit this */
354  return true; /* give back the success return */
355 }
356 
358 /******************************************************************************/
359 /* Function: Allow a source reconnect to occur */
360 /******************************************************************************/
361 {
362  this->flags |= reclaim_possible; /* we have a shot at this! */
363 }
364 
365 void RexxSource::adjustLine(size_t start_line_number, size_t end_line_number)
366 /******************************************************************************/
367 /* Arguments: interpret/sourceLiteral line location */
368 /* */
369 /* Function: Adjust the source object so that it thinks it is scanning a */
370 /* set of lines with a line number other than 1 so that errors */
371 /* and trace of an interpreted instruction/ source literal will */
372 /* display the good line numbers. */
373 /******************************************************************************/
374 {
375  /* fill in the source size */
376  this->line_count = end_line_number; /* size is now the end line number */
377  this->line_number = start_line_number;/* we are now on line "nn of mm" */
378  /* remember for positioning */
379  this->line_adjust = start_line_number - 1;
380 }
381 
383  RexxToken *token) /* current token */
384 /******************************************************************************/
385 /* Function: validate that the current token is a variable token */
386 /******************************************************************************/
387 {
388  /* not a variable token? */
389  if (!token->isVariable())
390  {
391  /* begin with a dot? */
392  if (token->value->getChar(0) == '.')
393  {
395  }
396  else
397  {
399  }
400  }
401 }
402 
404  RexxToken *token) /* current token */
405 /******************************************************************************/
406 /* Function: validate that the current token is a variable token */
407 /******************************************************************************/
408 {
409  /* not a variable token or dot symbol*/
410  if (!token->isVariable() && (token->subclass != SYMBOL_DOTSYMBOL)) {
412  }
413 }
414 
416  int terminators, /* set of possible terminators */
417  RexxToken *token) /* token being processed */
418 /******************************************************************************/
419 /* Function: test for a terminator token in the given context */
420 /******************************************************************************/
421 {
422  bool endtoken; /* found the end flag */
423 
424  endtoken = false; /* not found the end yet */
425 
426  /* process based on terminator class */
427  switch (token->classId)
428  {
429 
430  case TOKEN_EOC: /* found the end-of-clause */
431  endtoken = true; /* this is always an end marker */
432  break;
433 
434  case TOKEN_RIGHT: /* found a right paren */
435  if (terminators&TERM_RIGHT) /* terminate on this? */
436  endtoken = true; /* set the flag */
437  break;
438 
439  case TOKEN_SQRIGHT: /* found a right square bracket */
440  if (terminators&TERM_SQRIGHT) /* terminate on this? */
441  endtoken = true; /* set the flag */
442  break;
443 
444  case TOKEN_COMMA: /* found a comma */
445  if (terminators&TERM_COMMA) /* terminate on this? */
446  endtoken = true; /* set the flag */
447  break;
448 
449  case TOKEN_SYMBOL: /* have a symbol, need to resolve */
450  if (terminators&TERM_KEYWORD)
451  { /* need to do keyword checks? */
452  /* process based on the keyword */
453  // JLF todo ? token->subclass ?
454  switch (this->subKeyword(token))
455  {
456 
457  case SUBKEY_TO: /* TO subkeyword */
458  if (terminators&TERM_TO) /* terminate on this? */
459  endtoken = true; /* set the flag */
460  break;
461 
462  case SUBKEY_BY: /* BY subkeyword */
463  if (terminators&TERM_BY) /* terminate on this? */
464  endtoken = true; /* set the flag */
465  break;
466 
467  case SUBKEY_FOR: /* FOR subkeyword */
468  if (terminators&TERM_FOR) /* terminate on this? */
469  {
470  endtoken = true; /* set the flag */
471  }
472  break;
473 
474  case SUBKEY_WHILE: /* WHILE subkeyword */
475  case SUBKEY_UNTIL: /* UNTIL subkeyword */
476  if (terminators&TERM_WHILE)/* terminate on this? */
477  endtoken = true; /* set the flag */
478  break;
479 
480  case SUBKEY_WITH: /* WITH subkeyword */
481  if (terminators&TERM_WITH) /* terminate on this? */
482  endtoken = true; /* set the flag */
483  break;
484 
485  case SUBKEY_THEN: /* THEN subkeyword */
486  if (terminators&TERM_THEN) /* terminate on this? */
487  endtoken = true; /* set the flag */
488  break;
489 
490  default: /* not a terminator for others */
491  break;
492  }
493  }
494  default: /* not a terminator for others */
495  break;
496  }
497  if (endtoken) /* found the end one? */
498  {
499  previousToken(); /* push it back on the clause */
500  }
501  return endtoken; /* return the true/false flag */
502 }
503 
505 /******************************************************************************/
506 /* Function: Advance the current position to the next source line */
507 /******************************************************************************/
508 {
509  if (this->clause) /* have a clause object? */
510  {
511  /* record current position in clause */
512  this->clause->setEnd(this->line_number, this->line_offset);
513  }
514  /* move to the start of the next line*/
515  this->position(this->line_number + 1, 0);
516 }
517 
519  size_t line, /* target line number */
520  size_t offset) /* target line offset */
521 /******************************************************************************/
522 /* Function: Move the current scan position to a new spot */
523 /******************************************************************************/
524 {
525  LINE_DESCRIPTOR *descriptors; /* line descriptors */
526  const char *buffer_start; /* start of source buffer */
527  RexxString *new_line; /* new line to scan */
528 
529  this->line_number = line; /* set the line number */
530  this->line_offset = offset; /* and the offset */
531  /* past the end? */
532  if (line > this->line_count)
533  {
534  this->current = OREF_NULL; /* null out the current line */
535  this->current_length = 0; /* tag this as a null line */
536  }
537  else
538  {
539  /* working from an array? */
540  if (this->sourceArray != OREF_NULL)
541  {
542  /* get the next line */
543  new_line = (RexxString *)(this->sourceArray->get(line - this->line_adjust));
544  if (new_line == OREF_NULL) /* missing line? */
545  {
546  /* this is an error */
548  }
549  /* not working with a string? */
550  if (!isOfClass(String, new_line))
551  {
552  /* get this as a string */
553  new_line = (RexxString *)new_line->stringValue();
554  if (new_line == TheNilObject) /* got back .nil? */
555  {
556  /* this is an error */
558  }
559  }
560  /* set the program pointer */
561  this->current = new_line->getStringData();
562  /* get the string length */
563  this->current_length = new_line->getLength();
564  }
565  /* single buffer source */
566  else
567  {
568  /* get the descriptors pointer */
569  descriptors = (LINE_DESCRIPTOR *)(this->sourceIndices->getData());
570  /* source buffered in a string? */
571  if (isOfClass(String, this->sourceBuffer))
572  {
573  /* point to the data part */
574  buffer_start = ((RexxString *)(this->sourceBuffer))->getStringData();
575  }
576  else
577  {
578  /* point to the data part */
579  buffer_start = this->sourceBuffer->getData();
580  }
581  /* calculate the line start */
582  this->current = buffer_start + descriptors[line - this->line_adjust].position;
583  /* and get the length */
584  this->current_length = descriptors[line - this->line_adjust].length;
585  }
586  }
587 }
588 
589 void RexxSource::live(size_t liveMark)
590 /******************************************************************************/
591 /* Perform garbage collection marking of a source object */
592 /******************************************************************************/
593 {
594  memory_mark(this->parentSource);
595  memory_mark(this->sourceArray);
596  memory_mark(this->programName);
599  memory_mark(this->programFile);
600  memory_mark(this->clause);
602  memory_mark(this->sourceBuffer);
603  memory_mark(this->sourceIndices);
604  memory_mark(this->first);
605  memory_mark(this->last);
607  memory_mark(this->savelist);
608  memory_mark(this->holdstack);
609  memory_mark(this->variables);
610  memory_mark(this->literals);
612  memory_mark(this->labels);
613  memory_mark(this->strings);
616  memory_mark(this->control);
617  memory_mark(this->terms);
618  memory_mark(this->subTerms);
619  memory_mark(this->namedSubTerms);
620  memory_mark(this->operators);
621  memory_mark(this->calls);
622  memory_mark(this->routines);
625  memory_mark(this->requires);
626  memory_mark(this->libraries);
628  memory_mark(this->package);
629  memory_mark(this->classes);
630  memory_mark(this->extensions);
635  memory_mark(this->methods);
636  memory_mark(this->active_class);
638  memory_mark(this->initCode);
640 }
641 
642 void RexxSource::liveGeneral(int reason)
643 /******************************************************************************/
644 /* Function: Perform generalized marking of a source object */
645 /******************************************************************************/
646 {
647 #ifndef KEEPSOURCE
648  if (memoryObject.savingImage()) { /* save image time? */
649  /* don't save the source image */
650  OrefSet(this, this->sourceArray, OREF_NULL);
651  OrefSet(this, this->sourceBuffer, OREF_NULL);
652  OrefSet(this, this->sourceIndices, OREF_NULL);
653  OrefSet(this, this->clause, OREF_NULL);
654  /* don't save the install information*/
655  OrefSet(this, this->methods, OREF_NULL);
656  OrefSet(this, this->requires, OREF_NULL);
657  OrefSet(this, this->classes, OREF_NULL);
658  OrefSet(this, this->extensions, OREF_NULL);
659  OrefSet(this, this->routines, OREF_NULL);
660  OrefSet(this, this->libraries, OREF_NULL);
661  OrefSet(this, this->installed_classes, OREF_NULL);
665  this->flags &= ~reclaim_possible; /* can't recover source immediately */
666  }
667 #endif
678  memory_mark_general(this->first);
680  memory_mark_general(this->last);
691  memory_mark_general(this->terms);
695  memory_mark_general(this->calls);
714 }
715 
717 /******************************************************************************/
718 /* Function: Flatten a source object */
719 /******************************************************************************/
720 {
721 
723  /* if we are flattening for EA's, we */
724  /* don't need to to keep source info */
725  /* so ask the envelope if this is a */
726  /* flatten to save the method image */
727  this->sourceArray = OREF_NULL;
728  this->sourceBuffer = OREF_NULL;
729  this->sourceIndices = OREF_NULL;
730  this->securityManager = OREF_NULL;
732  flatten_reference(newThis->sourceArray, envelope);
733  flatten_reference(newThis->parentSource, envelope);
734  flatten_reference(newThis->programName, envelope);
735  flatten_reference(newThis->programDirectory, envelope);
736  flatten_reference(newThis->programExtension, envelope);
737  flatten_reference(newThis->programFile, envelope);
738  flatten_reference(newThis->clause, envelope);
739  flatten_reference(newThis->securityManager, envelope);
740  flatten_reference(newThis->sourceBuffer, envelope);
741  flatten_reference(newThis->sourceIndices, envelope);
742  flatten_reference(newThis->first, envelope);
743  flatten_reference(newThis->last, envelope);
744  flatten_reference(newThis->currentInstruction, envelope);
745  flatten_reference(newThis->savelist, envelope);
746  flatten_reference(newThis->holdstack, envelope);
747  flatten_reference(newThis->variables, envelope);
748  flatten_reference(newThis->literals, envelope);
749  flatten_reference(newThis->sourceLiterals, envelope);
750  flatten_reference(newThis->labels, envelope);
751  flatten_reference(newThis->strings, envelope);
752  flatten_reference(newThis->guard_variables, envelope);
753  flatten_reference(newThis->exposed_variables, envelope);
754  flatten_reference(newThis->control, envelope);
755  flatten_reference(newThis->terms, envelope);
756  flatten_reference(newThis->subTerms, envelope);
757  flatten_reference(newThis->namedSubTerms, envelope);
758  flatten_reference(newThis->operators, envelope);
759  flatten_reference(newThis->calls, envelope);
760  flatten_reference(newThis->routines, envelope);
761  flatten_reference(newThis->public_routines, envelope);
762  flatten_reference(newThis->class_dependencies, envelope);
763  flatten_reference(newThis->requires, envelope);
764  flatten_reference(newThis->libraries, envelope);
765  flatten_reference(newThis->loadedPackages, envelope);
766  flatten_reference(newThis->package, envelope);
767  flatten_reference(newThis->classes, envelope);
768  flatten_reference(newThis->extensions, envelope);
769  flatten_reference(newThis->installed_public_classes, envelope);
770  flatten_reference(newThis->installed_classes, envelope);
771  flatten_reference(newThis->merged_public_classes, envelope);
772  flatten_reference(newThis->merged_public_routines, envelope);
773  flatten_reference(newThis->methods, envelope);
774  flatten_reference(newThis->active_class, envelope);
775  flatten_reference(newThis->active_extension, envelope);
776  flatten_reference(newThis->initCode, envelope);
777  flatten_reference(newThis->interpret_activation, envelope);
778 
780 }
781 
782 
784 /******************************************************************************/
785 /* Function: Return count of lines in the source. If the source is not */
786 /* available, return 0 */
787 /******************************************************************************/
788 {
789  /* currently no source? */
790  if ((this->sourceArray == OREF_NULL && this->sourceBuffer == OREF_NULL))
791  {
792  if (!this->reconnect()) /* unable to recover the source? */
793  {
794  return 0; /* we have no source lines */
795  }
796  }
797  return this->line_count; /* return the line count */
798 }
799 
800 
802 /******************************************************************************/
803 /* Function: Determine if a program is traceable (i.e., the program source */
804 /* is available) */
805 /******************************************************************************/
806 {
807  /* currently no source? */
808  if ((this->sourceArray == OREF_NULL && this->sourceBuffer == OREF_NULL))
809  {
810  return this->reconnect(); /* unable to recover the source? */
811  }
812  return true; /* return the line count */
813 }
814 
816  size_t _position) /* requested source line */
817 /******************************************************************************/
818 /* Function: Extract a give source line from the source program */
819 /******************************************************************************/
820 {
821  LINE_DESCRIPTOR *descriptors; /* line descriptors */
822  const char *buffer_start; /* start of source buffer */
823 
824  if (_position > this->line_count) /* beyond last line? */
825  {
826  return OREF_NULLSTRING; /* just return a null string */
827  }
828  /* working from an array? */
829  if (this->sourceArray != OREF_NULL)
830  {
831  /* return the array line */
832  return(RexxString *)(this->sourceArray->get(_position));
833  }
834  /* buffered version? */
835  else if (this->sourceBuffer != OREF_NULL)
836  {
837  /* get the descriptors pointer */
838  descriptors = (LINE_DESCRIPTOR *)(this->sourceIndices->getData());
839  /* source buffered in a string? */
840  if (isOfClass(String, this->sourceBuffer))
841  {
842  /* point to the data part */
843  buffer_start = ((RexxString *)(this->sourceBuffer))->getStringData();
844  }
845  else
846  {
847  /* point to the data part */
848  buffer_start = this->sourceBuffer->getData();
849  }
850  /* create a new string version */
851  return new_string(buffer_start + descriptors[_position].position, descriptors[_position].length);
852  }
853  else
854  {
855  return OREF_NULLSTRING; /* we have no line */
856  }
857 }
858 
859 #ifdef _DEBUG
860 #define dumpClause(from, source, clause) dumpClauseImpl(from, source, clause)
861 #else
862 #define dumpClause(from, source, clause)
863 #endif
864 
865 void dumpClauseImpl(const char *from, RexxSource *source, RexxClause *clause)
866 {
867  if (!Utilities::traceParsing()) return;
868 
869  RexxString *value = source->extract(clause->clauseLocation, true);
870  ProtectedObject p(value);
872  {
873  // To avoid mixing output from different threads , better to have each line displayed by one dbgprintf instead of two.
874  struct ConcurrencyInfos concurrencyInfos;
875  Utilities::GetConcurrencyInfos(concurrencyInfos);
876  dbgprintf(CONCURRENCY_TRACE "...... ... (Parsing)-------------------------------------------------\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock);
877  dbgprintf(CONCURRENCY_TRACE "...... ... (Parsing)From %s\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, from);
878  dbgprintf(CONCURRENCY_TRACE "...... ... (Parsing)%s\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, value->getStringData());
879  dbgprintf(CONCURRENCY_TRACE "...... ... (Parsing)\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock);
880  }
881  else
882  {
883  // Here, we don't display concurrency trace, we have one dbgprintf per line, good.
884  dbgprintf("(Parsing)-------------------------------------------------\n");
885  dbgprintf("(Parsing)From %s\n", from);
886  dbgprintf("(Parsing)%s\n", value->getStringData());
887  dbgprintf("(Parsing)\n");
888  }
889 }
890 
891 #ifdef _DEBUG
892 #define dumpTokens(from, source, clause) dumpTokensImpl(from, source, clause)
893 #else
894 #define dumpTokens(from, source, clause)
895 #endif
896 
897 void dumpTokensImpl(const char *from, RexxSource *source, RexxClause *clause)
898 {
899  if (!Utilities::traceParsing()) return;
900 
901  // I think it's better to always start from 1, because this method is called
902  // after the creation of instructions, and the 'first' attribute will be the
903  // first token of the last instruction extracted from the clause.
904  // Here, I want to see ALL the tokens of the clause (after semantic annotation).
905  for (size_t i=1/*clause->first*/; i < clause->free; i++)
906  {
907  RexxToken *token = (RexxToken *)clause->tokens->get(i);
909  {
910  // To avoid mixing output from different threads , better to have one dbgprintf instead of several.
911  struct ConcurrencyInfos concurrencyInfos;
912  Utilities::GetConcurrencyInfos(concurrencyInfos);
913  dbgprintf( CONCURRENCY_TRACE "...... ... "
914  "(Parsing)startLine=%i startCol=%i endLine=%i endCol=%i "
915  "classId=%s subclass=%s numeric=%i "
916  "token=\"%s\"\n",
917  concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock,
920  token->value == NULL ? "NULL" : token->value->getStringData());
921  }
922  else
923  {
924  // Here, we don't display concurrency trace, we have only one dbgprintf, good.
925  dbgprintf( "(Parsing)startLine=%i startCol=%i endLine=%i endCol=%i "
926  "classId=%s subclass=%s numeric=%i "
927  "token=\"%s\"\n",
930  token->value == NULL ? "NULL" : token->value->getStringData());
931  }
932  if (token->classId == TOKEN_EOC) break;
933  }
934 }
935 
937 /*********************************************************************/
938 /* Extract a clause from the source and return as a clause object. */
939 /* The clause object contains a list of all of the tokens contained */
940 /* within the clause and is used by the parser to determine the */
941 /* type of instruction and create the instruction parse tree. */
942 /*********************************************************************/
943 {
944  RexxToken *token; /* current token being processed */
945  SourceLocation location; /* location of the clause */
946  SourceLocation token_location; /* location of each token */
947 
948  /* need to scan off a clause? */
949  if (!(this->flags&reclaimed))
950  {
951  this->clause->newClause(); /* reset the clause object */
952  /* loop until we get an non-null */
953  for (;;)
954  {
955  /* record the start position */
956  this->clause->setStart(this->line_number, this->line_offset);
957  /* get the next source token */
958  /* (blanks are not significant here) */
959  token = this->sourceNextToken(OREF_NULL);
960  /* hit the end of the file? */
961  if (token == OREF_NULL)
962  {
963  this->flags |= no_clause; /* flag this as a no clause */
964  return; /* we're finished */
965  }
966  /* is this the end of the clause? */
967  if (!token->isEndOfClause())
968  {
969  break; /* we've got what we need */
970  }
971  this->clause->newClause(); /* reset the clause object */
972  }
973  /* get the start position */
974  token_location = token->getLocation();
975  location = token_location; /* copy the location info */
976  /* record in clause for errors */
977  this->clause->setLocation(location);
978  /* loop until physical end of clause */
979  for (;;)
980  {
981  /* get the next token of real clause */
982  /* (blanks can be significant) */
983  token = this->sourceNextToken(token);
984  /* get this tokens location */
985  token_location = token->getLocation();
986  if (token->isEndOfClause()) /* end of the clause now? */
987  {
988  break; /* hit the physical end of clause */
989  }
990  }
991  location.setEnd(token_location);
992  /* record the clause position */
993  this->clause->setLocation(location);
994  }
995  this->flags &= ~reclaimed; /* no reclaimed clause */
996  // always set the error information
998 }
999  /* extra space required to format a */
1000  /* result line. This overhead is */
1001  /* 8 leading spaces for the line */
1002  /* number, + 1 space + length of the */
1003  /* message prefix (3) + 1 space + */
1004  /* 2 for an indent + 2 for the */
1005  /* quotes surrounding the value */
1006 #define TRACE_OVERHEAD 16
1007  /* overhead for a traced instruction */
1008  /* (8 digit line number, blank, */
1009  /* 3 character prefix, and a blank */
1010 #define INSTRUCTION_OVERHEAD 11
1011 #define LINENUMBER 6 /* size of a line number */
1012 #define PREFIX_OFFSET (LINENUMBER + 1) /* location of the prefix field */
1013 #define PREFIX_LENGTH 3 /* length of the prefix flag */
1014 #define INDENT_SPACING 2 /* spaces per indentation amount */
1015 
1016 
1017 /**
1018  * Create a stack frame for this parsing context.
1019  *
1020  * @return a stack frame instance for error reporting
1021  */
1023 {
1024  // construct the traceback line before we allocate the stack frame object.
1025  // calling this in the constructor argument list can cause the stack frame instance
1026  // to be inadvertently reclaimed if a GC is triggered while evaluating the constructor
1027  // arguments.
1028  RexxString *traceback = traceBack(OREF_NULL, clauseLocation, 0, true);
1029  ProtectedObject p_traceback(traceback);
1031 }
1032 
1033 
1034 /**
1035  * Format a source line for tracing
1036  *
1037  * @param activation The activation of the current running code. This can be
1038  * null if this is a translation time error.
1039  * @param location The source line location.
1040  * @param indent The indentation amount to apply to the trace line
1041  * @param trace This is a traced line vs. an error line
1042  *
1043  * @return A formatted trace line, including headers and indentations.
1044  */
1046  size_t indent, bool trace)
1047 {
1048  RexxString *buffer; /* buffer for building result */
1049  RexxString *line; /* actual line data */
1050  size_t outlength; /* output length */
1051  char *linepointer; /* pointer to the line number */
1052  char linenumber[11]; /* formatted line number */
1053 
1054  /* format the value */
1055  snprintf(linenumber, sizeof linenumber, "%zu", location.getLineNumber());
1056 
1057  line = this->extract(location); /* extract the source string */
1058  /* doesn't exist and this isn't a */
1059  /* trace instruction format? */
1060  if (line == OREF_NULLSTRING)
1061  {
1062  // old space code means this is part of the interpreter image. Don't include
1063  // the package name in the message
1064  if (this->isOldSpace())
1065  {
1067  }
1068  // if we have an activation (and we should, since the only time we won't would be for a
1069  // translation time error...and we have source then), ask it to provide a line describing
1070  // the invocation situation
1071  if (activation != OREF_NULL)
1072  {
1074  }
1075  // this could be part of the internal code...give a generic message that doesn't identify
1076  // the actual package.
1077  else if (this->isInternalCode())
1078  {
1080  }
1081  else
1082  {
1083  // generic package message.
1084  RexxArray *args = new_array(this->programName);
1085  ProtectedObject p(args);
1087  }
1088  }
1089  /* get an output string */
1090  buffer = raw_string(line->getLength() + INSTRUCTION_OVERHEAD + indent * INDENT_SPACING);
1091  /* blank out the first part */
1092  buffer->set(0, ' ', INSTRUCTION_OVERHEAD + indent * INDENT_SPACING);
1093  /* copy in the line */
1094  buffer->put(INSTRUCTION_OVERHEAD + indent * INDENT_SPACING, line->getStringData(), line->getLength());
1095  outlength = strlen(linenumber); /* get the line number length */
1096  linepointer = linenumber; /* point to number start */
1097  /* too long for defined field? */
1098  if (outlength > LINENUMBER)
1099  {
1100  /* step over extra numbers */
1101  linepointer += outlength - LINENUMBER;
1102  *linepointer = '?'; /* overlay a question mark */
1103  outlength = LINENUMBER; /* shorten the length */
1104  }
1105  /* copy in the line number */
1106  buffer->put(LINENUMBER - outlength, linepointer, outlength);
1107  buffer->put(PREFIX_OFFSET, "*-*", PREFIX_LENGTH);
1108  return buffer; /* return formatted buffer */
1109 }
1110 
1112  SourceLocation &location, /* target retrieval structure */
1113  bool newline /* if true then inserts a newline at then end of each line */
1114  )
1115 /******************************************************************************/
1116 /* Extrace a line from the source using the given location information */
1117 /******************************************************************************/
1118 {
1119  /* RexxString * */ ProtectedObject line(OREF_NULLSTRING); /* returned source line */
1120  RexxString *source_line; /* current extracting line */
1121  size_t counter; /* line counter */
1122 
1123  /* currently no source? */
1124  if ((this->sourceArray == OREF_NULL && this->sourceBuffer == OREF_NULL))
1125  {
1126  if (!this->reconnect()) /* unable to recover the source? */
1127  return OREF_NULLSTRING; /* return a null array */
1128  }
1129  /* is the location out of bounds? */
1130  if (location.getLineNumber() == 0 || location.getLineNumber() > this->line_count)
1131  line = OREF_NULLSTRING; /* just give back a null string */
1132  /* all on one line? */
1133  else if (location.getLineNumber() >= location.getEndLine())
1134  /* just extract the string */
1135  line = this->get(location.getLineNumber() - this->line_adjust)->extract(location.getOffset(),
1136  location.getEndOffset() - location.getOffset());
1137  /* multiple line clause */
1138  else
1139  {
1140  /* get the source line */
1141  source_line = this->get(location.getLineNumber() - this->line_adjust);
1142  /* extract the first part */
1143  line = source_line->extract(location.getOffset(), source_line->getLength() - location.getOffset());
1144  if (location.isLimitedTrace()) return line;
1145  /* loop down to end line */
1146  for (counter = location.getLineNumber() + 1 - this->line_adjust; counter < location.getEndLine(); counter++)
1147  {
1148  /* concatenate the next line on */
1149  if (newline) line = ((RexxString*)line)->concatWith(this->get(counter), '\n');
1150  else line = ((RexxString*)line)->concat(this->get(counter));
1151  }
1152  /* now add on the last part */
1153  if (newline) line = ((RexxString*)line)->concatWith(this->get(counter)->extract(0, location.getEndOffset()), '\n');
1154  else line = ((RexxString*)line)->concat(this->get(counter)->extract(0, location.getEndOffset()));
1155  }
1156  return line; /* return the extracted line */
1157 }
1158 
1159 
1160 /**
1161  * Extract all of the source from the package.
1162  *
1163  * @return An array of the source lines.
1164  */
1166 {
1167  SourceLocation location;
1168 
1169  location.setLineNumber(1);
1170  location.setEndLine(0);
1171  location.setOffset(0);
1172 
1173  return extractSource(location);
1174 }
1175 
1176 
1177 
1179  SourceLocation &location ) /* target retrieval structure */
1180 /******************************************************************************/
1181 /* Function: Extract a section of source from a method source object, using */
1182 /* the created bounds for the method. */
1183 /******************************************************************************/
1184 {
1185  /* currently no source? */
1186  if ((this->sourceArray == OREF_NULL && this->sourceBuffer == OREF_NULL))
1187  {
1188  if (!this->reconnect()) /* unable to recover the source? */
1189  {
1190  /* return a null array */
1191  return(RexxArray *)TheNullArray->copy();
1192  }
1193  }
1194  /* is the location out of bounds? */
1195  if (location.getLineNumber() == 0 || location.getLineNumber() /*- this->line_adjust*/ > this->line_count)
1196  {
1197  /* just give back a null array */
1198  return (RexxArray *)TheNullArray->copy();
1199  }
1200  else
1201  {
1202  if (location.getEndLine() == 0)
1203  { /* no ending line? */
1204  /* use the last line */
1205  location.setEnd(this->line_count, this->get(line_count)->getLength());
1206  }
1207  /* end at the line start? */
1208  else if (location.getEndOffset() == 0)
1209  {
1210  // step back a line
1211  location.setEndLine(location.getEndLine() - 1); /* step back a line */
1212  /* end at the line end */
1213  location.setEndOffset(this->get(location.getEndLine())->getLength());
1214  }
1215  /* get the result array */
1216  RexxArray *source = new_array(location.getEndLine() - location.getLineNumber() + 1);
1217  ProtectedObject p(source);
1218  /* all on one line? */
1219  if (location.getLineNumber() == location.getEndLine())
1220  {
1221  /* get the line */
1222  RexxString *source_line = this->get(location.getLineNumber() - this->line_adjust);
1223  /* extract the line segment */
1224  source_line = source_line->extract(location.getOffset(), location.getEndOffset() - location.getOffset());
1225  source->put(source_line, 1); /* insert the trailing piece */
1226  return source; /* all done */
1227  }
1228  if (location.getOffset() == 0) /* start on the first location? */
1229  {
1230  /* copy over the entire line */
1231  source->put(this->get(location.getLineNumber()), 1);
1232  }
1233  else
1234  {
1235  /* get the line */
1236  RexxString *source_line = this->get(location.getLineNumber() - this->line_adjust);
1237  /* extract the end portion */
1238  source_line = source_line->extract(location.getOffset(), source_line->getLength() - location.getOffset());
1239  source->put(source_line, 1); /* insert the trailing piece */
1240  }
1241 
1242  size_t i = 2;
1243  /* loop until the last line */
1244  for (size_t counter = location.getLineNumber() + 1; counter < location.getEndLine(); counter++, i++)
1245  {
1246  /* copy over the entire line */
1247  source->put(this->get(counter - this->line_adjust), i);
1248  }
1249  /* get the last line */
1250  RexxString *source_line = this->get(location.getEndLine() - this->line_adjust);
1251  /* more than one line? */
1252  if (location.getEndLine() > location.getLineNumber())
1253  {
1254  /* need the entire line? */
1255  if (location.getEndOffset() >= source_line->getLength())
1256  {
1257  source->put(source_line, i); /* just use it */
1258  }
1259  else
1260  {
1261  /* extract the tail part */
1262  source->put(source_line->extract(0, location.getEndOffset() - 1), i);
1263  }
1264  }
1265  return source;
1266  }
1267 }
1268 
1270 /******************************************************************************/
1271 /* Function: Perform global parsing initialization */
1272 /******************************************************************************/
1273 {
1274  /* holding pen for temporaries */
1275  OrefSet(this, this->holdstack, new (HOLDSIZE, false) RexxStack(HOLDSIZE));
1276  /* create a save table */
1277  OrefSet(this, this->savelist, new_identity_table());
1278  /* allocate global control tables */
1279  OrefSet(this, this->control, new_queue());
1280  OrefSet(this, this->terms, new_queue());
1281  OrefSet(this, this->subTerms, new_queue());
1282  OrefSet(this, this->namedSubTerms, new_queue());
1283  OrefSet(this, this->operators, new_queue());
1284  OrefSet(this, this->literals, new_directory());
1285  OrefSet(this, this->sourceLiterals, new_list());
1286 
1287  // during an image build, we have a global string table. If this is
1288  // available now, use it.
1289 
1290  // for experimentation, dont use the global string table.
1291  // I try to manage the encoding of string literals per package.
1292  // So a string table per source is what I need.
1293  // OrefSet(this, this->strings, memoryObject.getGlobalStrings());
1294 
1295  if (this->strings == OREF_NULL)
1296  {
1297  // no global string table, use a local copy
1298  OrefSet(this, this->strings, new_directory());
1299  }
1300  /* get the clause object */
1301  OrefSet(this, this->clause, new RexxClause());
1302 }
1303 
1304 
1306 /******************************************************************************/
1307 /* Function: Convert a source object into an executable method */
1308 /******************************************************************************/
1309 {
1310  this->globalSetup(); /* do the global setup part */
1311  /* translate the source program */
1312  RexxCode *newCode = this->translate(OREF_NULL);
1313  ProtectedObject p(newCode);
1314  this->cleanup(); /* release temporary tables */
1315  // if generating a method object, then process the directive installation now
1316  if (isMethod)
1317  {
1318  // force this to install now
1319  install();
1320  }
1321  return newCode; /* return the method */
1322 }
1323 
1325  RexxDirectory *_labels, /* parent label set */
1326  RexxActivation *_activation) /* INTERPRET's activation */
1327 /******************************************************************************/
1328 /* Function: Convert a source object into an executable interpret method */
1329 /******************************************************************************/
1330 {
1331  this->globalSetup(); /* do the global setup part */
1332  this->flags |= _interpret; /* this is an interpret */
1333  OrefSet(this, this->interpret_activation, _activation);
1334  RexxCode *newCode = this->translate(_labels); /* translate the source program */
1335  ProtectedObject p(newCode);
1336  this->cleanup(); /* release temporary tables */
1337  return newCode; /* return the method */
1338 }
1339 
1341  RexxString *string, /* interpret string value */
1342  RexxDirectory *_labels, /* parent labels */
1343  size_t _line_number, /* line number of interpret */
1345 /******************************************************************************/
1346 /* Function: Interpret a string in the current activation context */
1347 /******************************************************************************/
1348 {
1349  /* create a source object */
1350  RexxSource *source = new RexxSource (this->programName, new_array(string));
1351  ProtectedObject p(source);
1352  source->adjustLine(_line_number, _line_number);/* fudge the line numbering*/
1353  /* convert to executable form */
1354  return source->interpretMethod(_labels, activation);
1355 }
1356 
1357 void RexxSource::checkDirective(int errorCode)
1358 /******************************************************************************/
1359 /* Function: Verify that no code follows a directive except for more */
1360 /* directive instructions. */
1361 /******************************************************************************/
1362 {
1363  // save the clause location so we can reset for errors
1364  SourceLocation location = clauseLocation;
1365 
1366  this->nextClause(); /* get the next clause */
1367  dumpClause("RexxSource::checkDirective", this, this->clause);
1368  /* have a next clause? */
1369  if (!(this->flags&no_clause))
1370  {
1371  RexxToken *token = nextReal(); /* get the first token */
1372  /* not a directive start? */
1373  if (token->classId != TOKEN_DCOLON)
1374  {
1375  /* this is an error */
1376  syntaxError(errorCode);
1377  }
1378  firstToken(); /* reset to the first token */
1379  this->reclaimClause(); /* give back to the source object */
1380  }
1381  // this resets the current clause location so that any errors on the current
1382  // clause detected after the clause check reports this on the correct line
1383  // number
1384  clauseLocation = location;
1385 }
1386 
1387 
1388 /**
1389  * Test if a directive is followed by a body of Rexx code
1390  * instead of another directive or the end of the source.
1391  *
1392  * @return True if there is a non-directive clause following the current
1393  * clause.
1394  */
1396 {
1397  // assume there's no body here
1398  bool result = false;
1399 
1400  // if we have anything to look at, see if it is a directive or not.
1401  this->nextClause();
1402  dumpClause("RexxSource::hasBody", this, this->clause);
1403  if (!(this->flags&no_clause))
1404  {
1405  // we have a clause, now check if this is a directive or not
1406  RexxToken *token = nextReal();
1407  // not a "::", not a directive, which means we have real code to deal with
1408  result = token->classId != TOKEN_DCOLON;
1409  // reset this clause entirely so we can start parsing for real.
1410  firstToken();
1411  this->reclaimClause();
1412  }
1413  return result;
1414 }
1415 
1416 
1418  RexxObject *object) /* object to "release" */
1419 /******************************************************************************/
1420 /* Function: Remove an object from the save list */
1421 /******************************************************************************/
1422 {
1423  /* have a real object */
1424  if (object != OREF_NULL)
1425  {
1426  this->savelist->remove(object); /* remove from the save table */
1427  this->holdObject(object); /* return this object as held */
1428  }
1429  return object; /* return the object */
1430 }
1431 
1433 /******************************************************************************/
1434 /* Function: Final cleanup after parsing */
1435 /******************************************************************************/
1436 {
1437  /* global area cleanup */
1438  /* release the holding pen */
1439  OrefSet(this, this->holdstack, OREF_NULL);
1440  /* release any saved objects */
1441  OrefSet(this, this->savelist, OREF_NULL);
1442  OrefSet(this, this->literals, OREF_NULL);
1443  OrefSet(this, this->sourceLiterals, OREF_NULL);
1444  OrefSet(this, this->strings, OREF_NULL);
1445  OrefSet(this, this->clause, OREF_NULL);
1446  OrefSet(this, this->control, OREF_NULL);
1447  OrefSet(this, this->terms, OREF_NULL);
1448  OrefSet(this, this->subTerms, OREF_NULL);
1449  OrefSet(this, this->namedSubTerms, OREF_NULL);
1450  OrefSet(this, this->operators, OREF_NULL);
1451  OrefSet(this, this->class_dependencies, OREF_NULL);
1452  OrefSet(this, this->active_class, OREF_NULL);
1453  OrefSet(this, this->active_extension, OREF_NULL);
1454  /* now method parsing areas */
1455  OrefSet(this, this->calls, OREF_NULL);
1456  OrefSet(this, this->variables, OREF_NULL);
1457  OrefSet(this, this->guard_variables, OREF_NULL);
1458  OrefSet(this, this->exposed_variables, OREF_NULL);
1459  OrefSet(this, this->labels, OREF_NULL);
1460  OrefSet(this, this->first, OREF_NULL);
1461  OrefSet(this, this->last, OREF_NULL);
1462  OrefSet(this, this->currentInstruction, OREF_NULL);
1463 }
1464 
1465 
1466 /**
1467  * Merge a parent source context into our context so all of the
1468  * bits that are visible in the parent are also resolvable in our
1469  * context. This is mostly used for dynamically created methods.
1470  *
1471  * @param parent The parent source context.
1472  */
1474 {
1475  // set this as a parent
1476  OrefSet(this, this->parentSource, source);
1477 
1478  // Remember : too early to set up the package global defaults, from the parent.
1479  // At this point, the ::options directives have not been parsed.
1480 }
1481 
1482 
1484 /******************************************************************************/
1485 /* Function: Merge all public class and routine information from a called */
1486 /* program into the full public information of this program. */
1487 /******************************************************************************/
1488 {
1489  // has the source already merged in some public routines? pull those in first,
1490  // so that the direct set will override
1491  if (source->merged_public_routines != OREF_NULL)
1492  {
1493  /* first merged attempt? */
1494  if (this->merged_public_routines == OREF_NULL)
1495  {
1496  /* get the directory */
1498  }
1499  /* loop through the list of routines */
1500  for (HashLink i = source->merged_public_routines->first(); source->merged_public_routines->available(i); i = source->merged_public_routines->next(i))
1501  {
1502  /* copy the routine over */
1504  }
1505 
1506  }
1507 
1508  // now process the direct set
1509  if (source->public_routines != OREF_NULL)
1510  {
1511  /* first merged attempt? */
1512  if (this->merged_public_routines == OREF_NULL)
1513  {
1514  /* get the directory */
1516  }
1517  /* loop through the list of routines */
1518  for (HashLink i = source->public_routines->first(); source->public_routines->available(i); i = source->public_routines->next(i))
1519  {
1520  /* copy the routine over */
1522  }
1523  }
1524 
1525 
1526  // now do the same process for any of the class contexts
1527  if (source->merged_public_classes != OREF_NULL)
1528  {
1529  if (this->merged_public_classes == OREF_NULL)
1530  {
1531  /* get the directory */
1533  }
1534  /* loop through the list of classes, */
1535  for (HashLink i = source->merged_public_classes->first(); source->merged_public_classes->available(i); i = source->merged_public_classes->next(i))
1536  {
1537  /* copy the routine over */
1539  }
1540  }
1541 
1542  // the installed ones are processed second as they will overwrite the imported one, which
1543  // is the behaviour we want
1544  if (source->installed_public_classes != OREF_NULL)
1545  {
1546  if (this->merged_public_classes == OREF_NULL)
1547  {
1548  /* get the directory */
1550  }
1551  /* loop through the list of classes, */
1553  {
1554  /* copy the routine over */
1556  }
1557  }
1558 }
1559 
1560 
1561 /**
1562  * Resolve a directly defined class object in this or a parent
1563  * context.
1564  *
1565  * @param name The name we're searching for (all uppercase).
1566  *
1567  * @return A resolved class object, if found.
1568  */
1570 {
1571  // if we have one locally, then return it.
1572  if (this->routines != OREF_NULL)
1573  {
1574  /* try for a local one first */
1575  RoutineClass *result = (RoutineClass *)(this->routines->fastAt(name));
1576  if (result != OREF_NULL)
1577  {
1578  return result;
1579  }
1580  }
1581 
1582  // we might have a chained context, so check it also
1583  if (parentSource != OREF_NULL)
1584  {
1585  return parentSource->findLocalRoutine(name);
1586  }
1587  // nope, no got one
1588  return OREF_NULL;
1589 }
1590 
1591 
1592 /**
1593  * Resolve a public routine in this source context
1594  *
1595  * @param name The target name.
1596  *
1597  * @return A resolved Routine object, if found.
1598  */
1600 {
1601  // if we have one locally, then return it.
1602  if (this->merged_public_routines != OREF_NULL)
1603  {
1604  /* try for a local one first */
1605  RoutineClass *result = (RoutineClass *)(this->merged_public_routines->fastAt(name));
1606  if (result != OREF_NULL)
1607  {
1608  return result;
1609  }
1610  }
1611 
1612  // we might have a chained context, so check it also
1613  if (parentSource != OREF_NULL)
1614  {
1615  return parentSource->findPublicRoutine(name);
1616  }
1617  // nope, no got one
1618  return OREF_NULL;
1619 }
1620 
1621 
1622 /**
1623  * Resolve a routine from this source files base context.
1624  *
1625  * @param routineName
1626  * The routine name of interest.
1627  *
1628  * @return A RoutineClass instance if located. Returns OREF_NULL if this
1629  * is not known at this level.
1630  */
1632 {
1633  // These lookups are case insensive, so the table are all created using the upper
1634  // case names. Use it once and reuse it.
1635  RexxString *upperName = routineName->upper();
1636  ProtectedObject p1(upperName);
1637  RoutineClass *routineObject = findLocalRoutine(upperName);
1638  if (routineObject != OREF_NULL)
1639  {
1640  return routineObject;
1641  }
1642 
1643  // now try for one pulled in from ::REQUIRES objects
1644  return findPublicRoutine(upperName);
1645 }
1646 
1647 
1648 /**
1649  * Resolve an external call in the context of the program making the
1650  * call. This will use the directory and extension of the context
1651  * program to modify the search order.
1652  *
1653  * @param activity The current activity
1654  * @param name The target name
1655  *
1656  * @return The fully resolved string name of the target program, if one is
1657  * located.
1658  */
1660 {
1662 }
1663 
1664 
1665 /**
1666  * Resolve a directly defined class object in this or a parent
1667  * context.
1668  *
1669  * @param name The name we're searching for (all uppercase).
1670  *
1671  * @return A resolved class object, if found.
1672  */
1674 {
1675  // if we have one locally, then return it.
1676  if (this->installed_classes != OREF_NULL)
1677  {
1678  /* try for a local one first */
1679  RexxClass *result = (RexxClass *)(this->installed_classes->fastAt(name));
1680  if (result != OREF_NULL)
1681  {
1682  return result;
1683  }
1684  }
1685 
1686  // we might have a chained context, so check it also
1687  if (parentSource != OREF_NULL)
1688  {
1689  return parentSource->findInstalledClass(name);
1690  }
1691  // nope, no got one
1692  return OREF_NULL;
1693 }
1694 
1695 
1697 {
1698  // if we have one locally, then return it.
1699  if (this->merged_public_classes != OREF_NULL)
1700  {
1701  /* try for a local one first */
1702  RexxClass *result = (RexxClass *)(this->merged_public_classes->fastAt(name));
1703  if (result != OREF_NULL)
1704  {
1705  return result;
1706  }
1707  }
1708 
1709  // we might have a chained context, so check it also
1710  if (parentSource != OREF_NULL)
1711  {
1712  return parentSource->findPublicClass(name);
1713  }
1714  // nope, no got one
1715  return OREF_NULL;
1716 }
1717 
1718 
1719 /**
1720  * Resolve a class from this source file context (including any
1721  * chained parent contexts).
1722  *
1723  * @param className The target name of the class.
1724  *
1725  * @return The resolved class object, if any.
1726  */
1728 {
1729  RexxString *internalName = className->upper(); /* upper case it */
1730  ProtectedObject p(internalName);
1731  // check for a directly defined one in the source context chain
1732  RexxClass *classObject = findInstalledClass(internalName);
1733  // return if we got one
1734  if (classObject != OREF_NULL)
1735  {
1736  return classObject;
1737  }
1738  // now try for public classes we pulled in from other contexts
1739  classObject = findPublicClass(internalName);
1740  // return if we got one
1741  if (classObject != OREF_NULL)
1742  {
1743  return classObject;
1744  }
1745 
1746  // give the security manager a go
1747  if (this->securityManager != OREF_NULL)
1748  {
1749  classObject = (RexxClass *)securityManager->checkLocalAccess(internalName);
1750  if (classObject != OREF_NULL)
1751  {
1752  return classObject;
1753  }
1754  }
1755 
1756  /* send message to .local */
1757  classObject = (RexxClass *)(ActivityManager::getLocalEnvironment(internalName));
1758  if (classObject != OREF_NULL)
1759  {
1760  return classObject;
1761  }
1762 
1763  /* normal execution? */
1764  if (this->securityManager != OREF_NULL)
1765  {
1766  classObject = (RexxClass *)securityManager->checkEnvironmentAccess(internalName);
1767  if (classObject != OREF_NULL)
1768  {
1769  return classObject;
1770  }
1771  }
1772 
1773  /* last chance, try the environment */
1774  return(RexxClass *)(TheEnvironment->at(internalName));
1775 }
1776 
1777 
1778 /**
1779  * Perform a non-contextual install of a package.
1780  */
1782 {
1783  if (needsInstallation())
1784  {
1785  // In order to install, we need to call something. We manage this by
1786  // creating a dummy stub routine that we can call to force things to install
1787  RexxCode *stub = new RexxCode(this, OREF_NULL, OREF_NULL, 10, FIRST_VARIABLE_INDEX);
1788  ProtectedObject p2(stub);
1789  RoutineClass *code = new RoutineClass(programName, stub);
1790  p2 = code;
1791  ProtectedObject dummy;
1792  code->call(ActivityManager::currentActivity, programName, NULL, 0, 0, dummy);
1793  }
1794 }
1795 
1796 
1798  RexxActivation *activation) /* invoking activation */
1799 /******************************************************************************/
1800 /* Function: Process directive information contained within a method, calling*/
1801 /* all ::requires routines, creating all ::class methods, and */
1802 /* processing all ::routines. */
1803 /******************************************************************************/
1804 {
1805  /* turn the install flag off */
1806  /* immediately, otherwise we may */
1807  /* run into a recursion problem */
1808  /* when class init methods are */
1809  /* processed */
1810  this->flags &= ~_install; /* we are now installed */
1811 
1812  // native packages are processed first. The requires might actually need
1813  // functons loaded by the packages
1814  if (this->libraries != OREF_NULL)
1815  {
1816  /* classes and routines */
1817  // now loop through the requires items
1818  for (size_t i = libraries->firstIndex(); i != LIST_END; i = libraries->nextIndex(i))
1819  {
1820  // and have it do the installs processing
1821  LibraryDirective *library = (LibraryDirective *)this->libraries->getValue(i);
1822  library->install(activation);
1823  }
1824  }
1825 
1826  // native methods and routines are lazy resolved on first use, so we don't
1827  // need to process them here.
1828 
1829  if (this->requires != OREF_NULL) /* need to process ::requires? */
1830  {
1831  /* classes and routines */
1832  // now loop through the requires items
1833  for (size_t i = requires->firstIndex(); i != LIST_END; i = requires->nextIndex(i))
1834  {
1835  // and have it do the installs processing. This is a little roundabout, but
1836  // we end up back in our own context while processing this, and the merge
1837  // of the information happens then.
1838  RequiresDirective *_requires = (RequiresDirective *)this->requires->getValue(i);
1839  _requires->install(activation);
1840  }
1841  }
1842 
1843  // and finally process classes
1844  if (this->classes != OREF_NULL)
1845  {
1846  /* get an installed classes directory*/
1847  OrefSet(this, this->installed_classes, new_directory());
1848  /* and the public classes */
1850  RexxArray *createdClasses = new_array(classes->items());
1851 
1852  ProtectedObject p(createdClasses);
1853  size_t index = 1; // used for keeping track of install order
1854  for (size_t i = classes->firstIndex(); i != LIST_END; i = classes->nextIndex(i))
1855  {
1856  /* get the class info */
1857  ClassDirective *current_class = (ClassDirective *)this->classes->getValue(i);
1858  // save the newly created class in our array so we can send the activate
1859  // message at the end
1860  RexxClass *newClass = current_class->install(this, activation);
1861  createdClasses->put(newClass, index++);
1862  }
1863  // now send an activate message to each of these classes
1864  for (size_t j = 1; j < index; j++)
1865  {
1866  RexxClass *clz = (RexxClass *)createdClasses->get(j);
1867  clz->sendMessage(OREF_ACTIVATE);
1868  }
1869  }
1870 
1871  // process extensions
1872  if (this->extensions != OREF_NULL)
1873  {
1874  for (size_t i = extensions->firstIndex(); i != LIST_END; i = extensions->nextIndex(i))
1875  {
1876  /* get the extension info */
1877  ExtensionDirective *current_extension = (ExtensionDirective *)this->extensions->getValue(i);
1878  current_extension->install(this, activation);
1879  }
1880  }
1881 }
1882 
1884  RexxDirectory *_labels) /* interpret labels */
1885 /******************************************************************************/
1886 /* Function: Translate a source object into a method object */
1887 /******************************************************************************/
1888 {
1890 
1891  // set up the package global defaults
1899 
1900  /* go translate the lead block */
1901  RexxCode *newMethod = this->translateBlock(_labels);
1902  // we save this in case we need to explicitly run this at install time
1903  OrefSet(this, this->initCode, newMethod);
1904  if (!this->atEnd()) /* have directives to process? */
1905  {
1906  /* create the routines directory */
1907  OrefSet(this, this->routines, new_directory());
1908  /* create the routines directory */
1909  OrefSet(this, this->public_routines, new_directory());
1910  /* and a directory of dependencies */
1911  OrefSet(this, this->class_dependencies, new_directory());
1912  /* create the requires directory */
1913  OrefSet(this, this->requires, new_list());
1914  // and a list of load libraries requiring loading.
1915  OrefSet(this, this->libraries, new_list());
1916  /* create the classes list */
1917  OrefSet(this, this->classes, new_list());
1918  OrefSet(this, this->extensions, new_list());
1919  /* no active class definition */
1920  OrefSet(this, this->active_class, OREF_NULL);
1921  OrefSet(this, this->active_extension, OREF_NULL);
1922  /* translation stopped by a directive*/
1923  if (this->flags&_interpret) /* is this an interpret? */
1924  {
1925  dumpTokens("RexxSource::translate (interpret)", this, this->clause);
1926  this->nextClause(); /* get the directive clause */
1927  dumpClause("RexxSource::translate (interpret)", this, this->clause);
1928  /* raise an error */
1930  }
1931  /* create a directory for ..methods */
1932  OrefSet(this, this->methods, new_directory());
1933 
1934  while (!this->atEnd()) /* loop until end of source */
1935  {
1936  this->directive(); /* process the directive */
1937  }
1938  this->resolveDependencies(); /* go resolve class dependencies */
1939  }
1940  return newMethod; /* return the method */
1941 }
1942 
1943 
1945 /*********************************************************************/
1946 /* Function: Resolve dependencies between ::CLASS directives, */
1947 /* rearranging the order of the directives to preserve */
1948 /* relative ordering wherever possible. Classes with no */
1949 /* dependencies in this source file will be done first, */
1950 /* followed by those with dependencies in the appropriate */
1951 /* order */
1952 /*********************************************************************/
1953 {
1954  // get our class list
1955  if (classes->items() == 0) /* nothing to process? */
1956  {
1957  /* clear out the classes list */
1958  OrefSet(this, this->classes, OREF_NULL);
1959  }
1960  else /* have classes to process */
1961  {
1962  size_t i;
1963  // run through the class list having each directive set up its
1964  // dependencies
1965  for (i = classes->firstIndex(); i != LIST_END; i = classes->nextIndex(i))
1966  {
1967  /* get the next class */
1968  ClassDirective *current_class = (ClassDirective *)(classes->getValue(i));
1969  // have the class figure out it's in-package dependencies
1970  current_class->addDependencies(class_dependencies);
1971  }
1972 
1973  RexxList *class_order = new_list(); // get a list for doing the order
1974  ProtectedObject p(class_order);
1975 
1976 /* now we repeatedly scan the pending directory looking for a class */
1977 /* with no in-program dependencies - it's an error if there isn't one */
1978 /* as we build the classes we have to remove them (their names) from */
1979 /* pending list and from the remaining dependencies */
1980  while (classes->items() > 0)
1981  {
1982  // this is the next one we process
1983  ClassDirective *next_install = OREF_NULL;
1984  for (i = classes->firstIndex(); i != LIST_END; i = classes->nextIndex(i))
1985  {
1986  /* get the next class */
1987  ClassDirective *current_class = (ClassDirective *)(classes->getValue(i));
1988  // if this class doesn't have any additional dependencies, pick it next.
1989  if (current_class->dependenciesResolved())
1990  {
1991  next_install = current_class;
1992  // add this to the class ordering
1993  class_order->append((RexxObject *)next_install);
1994  // remove this from the processing list
1995  classes->removeIndex(i);
1996  }
1997  }
1998  if (next_install == OREF_NULL) /* nothing located? */
1999  {
2000  // directive line where we can give as the source of the error
2002  clauseLocation = error_class->getLocation();
2003  /* raise an error */
2005  }
2006  RexxString *class_name = next_install->getName();
2007 
2008  // now go through the pending list telling each of the remaining classes that
2009  // they can remove this dependency from their list
2010  for (i = classes->firstIndex(); i != LIST_END; i = classes->nextIndex(i))
2011  { /* go remove the dependencies */
2012  /* get a class */
2013  ClassDirective *current_class = (ClassDirective *)classes->getValue(i);
2014  current_class->removeDependency(class_name);
2015  }
2016  }
2017 
2018  /* replace the original class list */
2019  OrefSet(this, this->classes, class_order);
2020  /* don't need the dependencies now */
2021  OrefSet(this, this->class_dependencies, OREF_NULL);
2022  }
2023 
2024  if (this->requires->items() == 0) /* nothing there? */
2025  {
2026  /* just clear it out */
2027  OrefSet(this, this->requires, OREF_NULL);
2028  }
2029  if (this->libraries->items() == 0) /* nothing there? */
2030  {
2031  /* just clear it out */
2032  OrefSet(this, this->libraries, OREF_NULL);
2033  }
2034  if (this->routines->items() == 0) /* no routines to process? */
2035  {
2036  /* just clear it out also */
2037  OrefSet(this, this->routines, OREF_NULL);
2038  }
2039  /* now finally the public routines */
2040  if (this->public_routines->items() == 0)
2041  {
2042  /* just clear it out also */
2043  OrefSet(this, this->public_routines, OREF_NULL);
2044  }
2045  if (this->methods->items() == 0) /* and also the methods directory */
2046  {
2047  /* just clear it out also */
2048  OrefSet(this, this->methods, OREF_NULL);
2049  }
2050 }
2051 
2052 
2053 /**
2054  * Process a ::CLASS directive for a source file.
2055  */
2057 {
2058  RexxToken *token = nextReal(); /* get the next token */
2059  /* not a symbol or a string */
2060  if (!token->isSymbolOrLiteral())
2061  {
2062  /* report an error */
2064  }
2065  RexxString *name = token->value; /* get the routine name */
2066  /* get the exposed name version */
2067  RexxString *public_name = this->commonString(name->upper());
2068  ProtectedObject p(public_name);
2069  /* does this already exist? */
2070  if (this->class_dependencies->entry(public_name) != OREF_NULL)
2071  {
2072  /* have an error here */
2074  }
2075  /* create a dependencies list */
2076  this->flags |= _install; /* have information to install */
2077 
2078  OrefSet(this, this->active_extension, OREF_NULL);
2079  // create a class directive and add this to the dependency list
2080  OrefSet(this, this->active_class, new ClassDirective(name, public_name, this->clause));
2081  this->class_dependencies->put((RexxObject *)active_class, public_name);
2082  // and also add to the classes list
2083  this->classes->append((RexxObject *)this->active_class);
2084 
2085  AccessFlag Access = DEFAULT_ACCESS_SCOPE; /* haven't seen the keyword yet */
2086  for (;;)
2087  { /* now loop on the option keywords */
2088  token = nextReal(); /* get the next token */
2089  /* reached the end? */
2090  if (token->isEndOfClause())
2091  {
2092  break; /* get out of here */
2093  }
2094  /* not a symbol token? */
2095  else if (!token->isSymbol())
2096  {
2097  /* report an error */
2099  }
2100  else
2101  { /* have some sort of option keyword */
2102  /* get the keyword type */
2103  int type = this->subDirective(token);
2104  if (type != 0) refineSubclass(token, IS_SUBDIRECTIVE);
2105  switch (type)
2106  { /* process each sub keyword */
2107  /* ::CLASS name METACLASS metaclass */
2109  /* already had a METACLASS? */
2111  {
2113  }
2114  token = nextReal(); /* get the next token */
2115  /* not a symbol or a string */
2116  if (!token->isSymbolOrLiteral())
2117  {
2118  /* report an error */
2120  }
2121  /* tag the active class */
2122  this->active_class->setMetaClass(token->value);
2123  break;
2124 
2125 
2126  case SUBDIRECTIVE_PUBLIC: /* ::CLASS name PUBLIC */
2127  if (Access != DEFAULT_ACCESS_SCOPE) /* already had one of these? */
2128  {
2129  /* duplicates are invalid */
2131  }
2132  Access = PUBLIC_SCOPE; /* turn on the seen flag */
2133  /* just set this as a public object */
2134  this->active_class->setPublic();
2135  break;
2136 
2137  case SUBDIRECTIVE_PRIVATE: /* ::CLASS name PUBLIC */
2138  if (Access != DEFAULT_ACCESS_SCOPE) /* already had one of these? */
2139  {
2140  /* duplicates are invalid */
2142  }
2143  Access = PRIVATE_SCOPE; /* turn on the seen flag */
2144  break;
2145  /* ::CLASS name SUBCLASS sclass */
2146  case SUBDIRECTIVE_SUBCLASS:
2147  // If we have a subclass set already, this is an error
2149  {
2150  /* duplicates are invalid */
2152  }
2153  token = nextReal(); /* get the next token */
2154  /* not a symbol or a string */
2155  if (!token->isSymbolOrLiteral())
2156  {
2157  /* report an error */
2159  }
2160  /* set the subclass information */
2161  this->active_class->setSubClass(token->value);
2162  break;
2163  /* ::CLASS name MIXINCLASS mclass */
2165  // If we have a subclass set already, this is an error
2167  {
2168  /* duplicates are invalid */
2170  }
2171  token = nextReal(); /* get the next token */
2172  /* not a symbol or a string */
2173  if (!token->isSymbolOrLiteral())
2174  {
2175  /* report an error */
2177  }
2178  /* set the subclass information */
2179  this->active_class->setMixinClass(token->value);
2180  break;
2181  /* ::CLASS name INHERIT iclasses */
2182  case SUBDIRECTIVE_INHERIT:
2183  token = nextReal(); /* get the next token */
2184  /* nothing after the keyword? */
2185  if (token->isEndOfClause())
2186  {
2187  /* report an error */
2189  }
2190  while (!token->isEndOfClause())
2191  {
2192  /* not a symbol or a string */
2193  if (!token->isSymbolOrLiteral())
2194  {
2195  /* report an error */
2197  }
2198  /* add to the inherit list */
2199  this->active_class->addInherits(token->value);
2200  token = nextReal(); /* step to the next token */
2201  }
2202  previousToken(); /* step back a token */
2203  break;
2204 
2205  // ooRexx5
2206  // ::CLASS name ABSTRACT
2207  case SUBDIRECTIVE_ABSTRACT:
2208  // already been specified? this is an error
2209  if (this->active_class->isAbstract())
2210  {
2212  }
2213 
2214  // mark this as abstract
2215  this->active_class->setAbstract();
2216  break;
2217 
2218  default: /* invalid keyword */
2219  /* this is an error */
2221  break;
2222  }
2223  }
2224  }
2225 }
2226 
2227 
2228 /**
2229  * Process a ::EXTENSION directive for a source file.
2230  */
2232 {
2233  RexxToken *token = nextReal(); /* get the next token */
2234  /* not a symbol or a string */
2235  if (!token->isSymbolOrLiteral())
2236  {
2237  /* report an error */
2239  }
2240  RexxString *name = token->value; /* get the class name */
2241  /* get the exposed name version */
2242  RexxString *public_name = this->commonString(name->upper());
2243  ProtectedObject p(public_name);
2244  /* create a dependencies list */
2245  this->flags |= _install; /* have information to install */
2246 
2247  OrefSet(this, this->active_class, OREF_NULL);
2248  // create an extension directive
2249  OrefSet(this, this->active_extension, new ExtensionDirective(name, public_name, this->clause));
2250  // add to the extensions list
2251  this->extensions->append((RexxObject *)this->active_extension);
2252 
2253  for (;;)
2254  { /* now loop on the option keywords */
2255  token = nextReal(); /* get the next token */
2256  /* reached the end? */
2257  if (token->isEndOfClause())
2258  {
2259  break; /* get out of here */
2260  }
2261  /* not a symbol token? */
2262  else if (!token->isSymbol())
2263  {
2264  /* report an error */
2266  }
2267  else
2268  { /* have some sort of option keyword */
2269  /* get the keyword type */
2270  int type = this->subDirective(token);
2271  if (type != 0) refineSubclass(token, IS_SUBDIRECTIVE);
2272  switch (type)
2273  { /* process each sub keyword */
2274  case SUBDIRECTIVE_INHERIT:
2275  token = nextReal(); /* get the next token */
2276  /* nothing after the keyword? */
2277  if (token->isEndOfClause())
2278  {
2279  /* report an error */
2281  }
2282  while (!token->isEndOfClause())
2283  {
2284  /* not a symbol or a string */
2285  if (!token->isSymbolOrLiteral())
2286  {
2287  /* report an error */
2289  }
2290  /* add to the inherit list */
2291  this->active_extension->addInherits(token->value);
2292  token = nextReal(); /* step to the next token */
2293  }
2294  previousToken(); /* step back a token */
2295  break;
2296 
2297  default: /* invalid keyword */
2298  /* this is an error */
2300  break;
2301  }
2302  }
2303  }
2304 }
2305 
2306 
2307 /**
2308  * check for a duplicate method.
2309  *
2310  * @param name The name to check.
2311  * @param classMethod
2312  * Indicates whether this is a check for a CLASS or INSTANCE method.
2313  * @param errorMsg
2314  * The error code to use if there is a duplicate.
2315  */
2316 void RexxSource::checkDuplicateMethod(RexxString *name, bool classMethod, int errorMsg)
2317 {
2318  /* no previous ::CLASS or ::EXTENSION directive? */
2319  if (this->active_class == OREF_NULL && this->active_extension == OREF_NULL)
2320  {
2321  if (classMethod) /* supposed to be a class method? */
2322  {
2323  /* this is an error */
2325  }
2326  /* duplicate method name? */
2327  if (this->methods->entry(name) != OREF_NULL)
2328  {
2329  /* this is an error */
2330  syntaxError(errorMsg);
2331  }
2332  }
2333  else if (this->active_extension != OREF_NULL)
2334  {
2335  if (active_extension->checkDuplicateMethod(name, classMethod))
2336  {
2337  /* this is an error */
2338  syntaxError(errorMsg);
2339  }
2340  }
2341  else
2342  { /* add the method to the active class*/
2343  if (active_class->checkDuplicateMethod(name, classMethod))
2344  {
2345  /* this is an error */
2346  syntaxError(errorMsg);
2347  }
2348  }
2349 }
2350 
2351 
2352 /**
2353  * Add a new method to this compilation.
2354  *
2355  * @param name The directory name of the method.
2356  * @param method The method object.
2357  * @param classMethod
2358  * The class/instance method indicator.
2359  */
2360 void RexxSource::addMethod(RexxString *name, RexxMethod *method, bool classMethod)
2361 {
2362  // ooRexx5
2363  // make sure this is attached to the source object for context information
2364  //method->setPackageObject(package);
2365  method->setSourceObject(this);
2366 
2367  if (this->active_extension != OREF_NULL)
2368  {
2369  active_extension->addMethod(name, method, classMethod);
2370  }
2371  else if (this->active_class == OREF_NULL)
2372  {
2373  this->methods->setEntry(name, method);
2374  }
2375  else
2376  {
2377  active_class->addMethod(name, method, classMethod);
2378  }
2379 }
2380 
2381 
2382 
2383 /**
2384  * Process a ::METHOD directive in a source file.
2385  */
2387 {
2388  AccessFlag Access = DEFAULT_ACCESS_SCOPE; /* this is a public method */
2389  ProtectedFlag Protected = DEFAULT_PROTECTION; /* and is not protected yet */
2390  GuardFlag guard = DEFAULT_GUARD; /* default is guarding */
2391  bool Class = false; /* default is an instance method */
2392  bool Attribute = false; /* init Attribute flag */
2393  bool abstractMethod = false; // this is an abstract method
2394  RexxToken *token = nextReal(); /* get the next token */
2395  RexxString *externalname = OREF_NULL; /* not an external method yet */
2396 
2397  /* not a symbol or a string */
2398  if (!token->isSymbolOrLiteral())
2399  {
2400  /* report an error */
2402  }
2403  RexxString *name = token->value; /* get the string name */
2404  /* and the name form also */
2405  RexxString *internalname = this->commonString(name->upper());
2406  ProtectedObject p(internalname);
2407  for (;;)
2408  { /* now loop on the option keywords */
2409  token = nextReal(); /* get the next token */
2410  /* reached the end? */
2411  if (token->isEndOfClause())
2412  {
2413  break; /* get out of here */
2414  }
2415  /* not a symbol token? */
2416  else if (!token->isSymbol())
2417  {
2418  /* report an error */
2420  }
2421  else
2422  { /* have some sort of option keyword */
2423  /* process each sub keyword */
2424  switch (this->subDirective(token))
2425  {
2426  /* ::METHOD name CLASS */
2427  case SUBDIRECTIVE_CLASS:
2429  if (Class) /* had one of these already? */
2430  {
2431  /* duplicates are invalid */
2433  }
2434  Class = true; /* flag this for later processing */
2435  break;
2436  /* ::METHOD name EXTERNAL extname */
2437  case SUBDIRECTIVE_EXTERNAL:
2439  /* already had an external? */
2440  if (externalname != OREF_NULL || abstractMethod)
2441  {
2442  /* duplicates are invalid */
2444  }
2445  token = nextReal(); /* get the next token */
2446  /* not a string? */
2447  if (!token->isLiteral())
2448  {
2449  /* report an error */
2451  }
2452  externalname = token->value;
2453  break;
2454  /* ::METHOD name PRIVATE */
2455  case SUBDIRECTIVE_PRIVATE:
2457  if (Access != DEFAULT_ACCESS_SCOPE) /* already seen one of these? */
2458  {
2459  /* duplicates are invalid */
2461  }
2462  Access = PRIVATE_SCOPE; /* flag for later processing */
2463  break;
2464  // ::METHOD name PACKAGE
2465  case SUBDIRECTIVE_PACKAGE:
2467  // has an access flag already been specified?
2468  if (Access != DEFAULT_ACCESS_SCOPE)
2469  {
2471  }
2472  Access = PACKAGE_SCOPE;
2473  break;
2474 
2475  /* ::METHOD name PUBLIC */
2476  case SUBDIRECTIVE_PUBLIC:
2478  if (Access != DEFAULT_ACCESS_SCOPE) /* already seen one of these? */
2479  {
2480  /* duplicates are invalid */
2482  }
2483  Access = PUBLIC_SCOPE; /* flag for later processing */
2484  break;
2485  /* ::METHOD name PROTECTED */
2488  if (Protected != DEFAULT_PROTECTION) /* already seen one of these? */
2489  {
2490  /* duplicates are invalid */
2492  }
2493  Protected = PROTECTED_METHOD; /* flag for later processing */
2494  break;
2495  /* ::METHOD name UNPROTECTED */
2498  if (Protected != DEFAULT_PROTECTION) /* already seen one of these? */
2499  {
2500  /* duplicates are invalid */
2502  }
2503  Protected = UNPROTECTED_METHOD; /* flag for later processing */
2504  break;
2505  /* ::METHOD name UNGUARDED */
2508  /* already seen one of these? */
2509  if (guard != DEFAULT_GUARD)
2510  {
2511  /* duplicates are invalid */
2513  }
2514  guard = UNGUARDED_METHOD;/* flag for later processing */
2515  break;
2516  /* ::METHOD name GUARDED */
2517  case SUBDIRECTIVE_GUARDED:
2519  /* already seen one of these? */
2520  if (guard != DEFAULT_GUARD)
2521  {
2522  /* duplicates are invalid */
2524  }
2525  guard = GUARDED_METHOD; /* flag for later processing */
2526  break;
2527  /* ::METHOD name ATTRIBUTE */
2529 
2531  if (Attribute) /* already seen one of these? */
2532  {
2533  /* duplicates are invalid */
2535  }
2536  // cannot have an abstract attribute
2537  if (abstractMethod)
2538  {
2539  /* EXTERNAL and ATTRIBUTE are */
2540  /* mutually exclusive */
2542  }
2543  Attribute = true; /* flag for later processing */
2544  break;
2545 
2546  /* ::METHOD name ABSTRACT */
2547  case SUBDIRECTIVE_ABSTRACT:
2548 
2550  if (abstractMethod || externalname != OREF_NULL)
2551  {
2553  }
2554  // not compatible with ATTRIBUTE or EXTERNAL
2555  if (externalname != OREF_NULL || Attribute)
2556  {
2558  }
2559  abstractMethod = true; /* flag for later processing */
2560  break;
2561 
2562 
2563  default: /* invalid keyword */
2564  /* this is an error */
2566  break;
2567  }
2568  }
2569  }
2570 
2571  // go check for a duplicate and validate the use of the CLASS modifier
2573 
2574 
2575  RexxMethod *_method = OREF_NULL;
2576  // is this an attribute method?
2577  if (Attribute)
2578  {
2579  // now get this as the setter method.
2580  RexxString *setterName = commonString(internalname->concatWithCstring("="));
2581  // need to check for duplicates on that too
2583 
2584  /* Go check the next clause to make */
2585  this->checkDirective(Error_Translation_attribute_method); /* sure that no code follows */
2586  // this might be externally defined setters and getters.
2587  if (externalname != OREF_NULL)
2588  {
2589  RexxString *library = OREF_NULL;
2590  RexxString *procedure = OREF_NULL;
2591  decodeExternalMethod(internalname, externalname, library, procedure);
2592  ProtectedObject p_library(library);
2593  ProtectedObject p_procedure(procedure);
2594  // now create both getter and setting methods from the information.
2595  _method = createNativeMethod(internalname, library, procedure->concatToCstring("GET"));
2596  _method->setAttributes(Access, Protected, guard);
2597  // mark this as an attribute method
2598  _method->setAttribute();
2599  // add to the compilation
2600  addMethod(internalname, _method, Class);
2601 
2602  _method = createNativeMethod(setterName, library, procedure->concatToCstring("SET"));
2603  _method->setAttributes(Access, Protected, guard);
2604  // add to the compilation
2605  addMethod(setterName, _method, Class);
2606  }
2607  else
2608  {
2609  // now get a variable retriever to get the property
2610  RexxVariableBase *retriever = this->getRetriever(name);
2611 
2612  // create the method pair and quit.
2613  createAttributeGetterMethod(internalname, retriever, Class, Access, Protected, guard);
2614  createAttributeSetterMethod(setterName, retriever, Class, Access, Protected, guard);
2615  }
2616  return;
2617  }
2618  // abstract method?
2619  else if (abstractMethod)
2620  {
2621  /* Go check the next clause to make */
2622  this->checkDirective(Error_Translation_abstract_method); /* sure that no code follows */
2623  // this uses a special code block
2624  BaseCode *code = new AbstractCode();
2625  _method = new RexxMethod(name, code);
2626  _method->setSourceObject(this);
2627  // make sure the method is marked abstract
2628  _method->setAbstract();
2629  }
2630  /* not an external method? */
2631  else if (externalname == OREF_NULL)
2632  {
2633  // NOTE: It is necessary to translate the block and protect the code
2634  // before allocating the RexxMethod object. The new operator allocates the
2635  // the object first, then evaluates the constructor arguments after the allocation.
2636  // Since the translateBlock() call will allocate a lot of new objects before returning,
2637  // there's a high probability that the method object can get garbage collected before
2638  // there is any opportunity to protect the object.
2639  RexxCode *code = this->translateBlock(OREF_NULL);
2640  this->saveObject((RexxObject *)code);
2641 
2642  /* go do the next block of code */
2643  _method = new RexxMethod(name, code);
2644  }
2645  else
2646  {
2647  RexxString *library = OREF_NULL;
2648  RexxString *procedure = OREF_NULL;
2649  decodeExternalMethod(internalname, externalname, library, procedure);
2650  ProtectedObject p_library(library);
2651  ProtectedObject p_procedure(procedure);
2652 
2653  /* go check the next clause to make */
2655  // and make this into a method object.
2656  _method = createNativeMethod(name, library, procedure);
2657  }
2658  _method->setAttributes(Access, Protected, guard);
2659  // add to the compilation
2660  addMethod(internalname, _method, Class);
2661 }
2662 
2663 
2664 
2665 /**
2666  * Process a ::OPTIONS directive in a source file.
2667  */
2669 {
2670  // all options are of a keyword/value pattern
2671  for (;;)
2672  {
2673  RexxToken *token = nextReal(); /* get the next token */
2674  /* reached the end? */
2675  if (token->isEndOfClause())
2676  {
2677  break; /* get out of here */
2678  }
2679  /* not a symbol token? */
2680  else if (!token->isSymbol())
2681  {
2682  /* report an error */
2684  }
2685  else
2686  { /* have some sort of option keyword */
2687  /* process each sub keyword */
2688  switch (this->subDirective(token))
2689  {
2690  // ::OPTIONS DIGITS nnnn
2691  case SUBDIRECTIVE_DIGITS:
2692  {
2694  token = nextReal(); /* get the next token */
2695  /* not a string? */
2696  if (!token->isSymbolOrLiteral())
2697  {
2698  /* report an error */
2700  }
2701  RexxString *value = token->value; /* get the string value */
2702 
2703  if (!value->requestUnsignedNumber(digits, number_digits()) || digits < 1)
2704  {
2705  /* report an exception */
2707  }
2708  /* problem with the fuzz setting? */
2709  if (digits <= fuzz)
2710  {
2711  /* this is an error */
2713  }
2714  break;
2715  }
2716  // ::OPTIONS FORM ENGINEERING/SCIENTIFIC
2717  case SUBDIRECTIVE_FORM:
2719  token = nextReal(); /* get the next token */
2720  /* not a string? */
2721  if (!token->isSymbol())
2722  {
2723  /* report an error */
2725  }
2726  /* resolve the subkeyword */
2727  /* and process */
2728  switch (this->subKeyword(token))
2729  {
2730 
2731  case SUBKEY_SCIENTIFIC: /* NUMERIC FORM SCIENTIFIC */
2732  refineSubclass(token, IS_SUBKEY);
2734  break;
2735 
2736  case SUBKEY_ENGINEERING: /* NUMERIC FORM ENGINEERING */
2737  refineSubclass(token, IS_SUBKEY);
2739  break;
2740 
2741  default: /* invalid subkeyword */
2742  /* raise an error */
2744  break;
2745 
2746  }
2747  break;
2748  // ::OPTIONS FUZZ nnnn
2749  case SUBDIRECTIVE_FUZZ:
2750  {
2752  token = nextReal(); /* get the next token */
2753  /* not a string? */
2754  if (!token->isSymbolOrLiteral())
2755  {
2756  /* report an error */
2758  }
2759  RexxString *value = token->value; /* get the string value */
2760 
2761  if (!value->requestUnsignedNumber(fuzz, number_digits()))
2762  {
2763  /* report an exception */
2765  }
2766  /* problem with the digits setting? */
2767  if (fuzz >= digits)
2768  {
2769  /* and issue the error */
2771  }
2772  break;
2773  }
2774  // ::OPTIONS TRACE setting
2775  case SUBDIRECTIVE_TRACE:
2776  {
2778  token = nextReal(); /* get the next token */
2779  /* not a string? */
2780  if (!token->isSymbolOrLiteral())
2781  {
2782  /* report an error */
2784  }
2785  RexxString *value = token->value; /* get the string value */
2786  char badOption = 0;
2787  /* process the setting */
2788  if (!parseTraceSetting(value, traceSetting, traceFlags, badOption))
2789  {
2791  }
2792  break;
2793  }
2794  // ::OPTIONS COMMANDS
2795  case SUBDIRECTIVE_COMMANDS:
2796  {
2798  enableCommands = true;
2799  break;
2800  }
2801  // ::OPTIONS NOCOMMANDS
2803  {
2805  enableCommands = false;
2806  break;
2807  }
2808  // ::OPTIONS MACROSPACE
2810  {
2812  enableMacrospace = true;
2813  break;
2814  }
2815  // ::OPTIONS NOMACROSPACE
2817  {
2819  enableMacrospace = false;
2820  break;
2821  }
2822 
2823  default: /* invalid keyword */
2824  /* this is an error */
2826  break;
2827  }
2828  }
2829  }
2830 }
2831 
2832 /**
2833  * Create a native method from a specification.
2834  *
2835  * @param name The method name.
2836  * @param library The library containing the method.
2837  * @param procedure The name of the procedure within the package.
2838  *
2839  * @return A method object representing this method.
2840  */
2842 {
2843  /* create a new native method */
2844  RexxNativeCode *nmethod = PackageManager::resolveMethod(library, procedure);
2845  // raise an exception if this entry point is not found.
2846  if (nmethod == OREF_NULL)
2847  {
2849  }
2850  // this might return a different object if this has been used already
2851  nmethod = (RexxNativeCode *)nmethod->setSourceObject(this);
2852  /* turn into a real method object */
2853  return new RexxMethod(name, nmethod);
2854 }
2855 
2856 /**
2857  * Decode an external library method specification.
2858  *
2859  * @param methodName The internal name of the method (uppercased).
2860  * @param externalSpec
2861  * The external specification string.
2862  * @param library The returned library name.
2863  * @param procedure The returned package name.
2864  */
2865 void RexxSource::decodeExternalMethod(RexxString *methodName, RexxString *externalSpec, RexxString *&library, RexxString *&procedure)
2866 {
2867  // this is the default
2868  procedure = methodName;
2869  library = OREF_NULL;
2870 
2871  /* convert external into words */
2872  RexxArray *_words = this->words(externalSpec);
2873  /* not 'LIBRARY library [entry]' form? */
2874  if (((RexxString *)(_words->get(1)))->strCompare(CHAR_LIBRARY))
2875  {
2876  // full library with entry name version?
2877  if (_words->size() == 3)
2878  {
2879  library = (RexxString *)_words->get(2);
2880  procedure = (RexxString *)_words->get(3);
2881  }
2882  else if (_words->size() == 2)
2883  {
2884  library = (RexxString *)_words->get(2);
2885  }
2886  else // wrong number of tokens
2887  {
2888  /* this is an error */
2890  }
2891  }
2892  else
2893  {
2894  /* unknown external type */
2896  }
2897 }
2898 
2899 #define ATTRIBUTE_BOTH 0
2900 #define ATTRIBUTE_GET 1
2901 #define ATTRIBUTE_SET 2
2902 
2903 
2904 /**
2905  * Process a ::ATTRIBUTE directive in a source file.
2906  */
2908 {
2909  AccessFlag Access = DEFAULT_ACCESS_SCOPE; /* this is a public method */
2910  ProtectedFlag Protected = DEFAULT_PROTECTION; /* and is not protected yet */
2911  GuardFlag guard = DEFAULT_GUARD; /* default is guarding */
2912  int style = ATTRIBUTE_BOTH; // by default, we create both methods for the attribute.
2913  bool Class = false; /* default is an instance method */
2914  bool abstractMethod = false; // by default, creating a concrete method
2915  RexxToken *token = nextReal(); /* get the next token */
2916 
2917  /* not a symbol or a string */
2918  if (!token->isSymbolOrLiteral())
2919  {
2920  /* report an error */
2922  }
2923  RexxString *name = token->value; /* get the string name */
2924  /* and the name form also */
2925  RexxString *internalname = this->commonString(name->upper());
2926  ProtectedObject p(internalname);
2927  RexxString *externalname = OREF_NULL;
2928 
2929  for (;;)
2930  { /* now loop on the option keywords */
2931  token = nextReal(); /* get the next token */
2932  /* reached the end? */
2933  if (token->isEndOfClause())
2934  {
2935  break; /* get out of here */
2936  }
2937  /* not a symbol token? */
2938  else if (!token->isSymbol())
2939  {
2940  /* report an error */
2942  }
2943  else
2944  { /* have some sort of option keyword */
2945  /* process each sub keyword */
2946  switch (this->subDirective(token))
2947  {
2948  case SUBDIRECTIVE_GET:
2950  // only one of GET/SET allowed
2951  if (style != ATTRIBUTE_BOTH)
2952  {
2954  }
2955  style = ATTRIBUTE_GET;
2956  break;
2957 
2958  case SUBDIRECTIVE_SET:
2960  // only one of GET/SET allowed
2961  if (style != ATTRIBUTE_BOTH)
2962  {
2964  }
2965  style = ATTRIBUTE_SET;
2966  break;
2967 
2968 
2969  /* ::ATTRIBUTE name CLASS */
2970  case SUBDIRECTIVE_CLASS:
2972  if (Class) /* had one of these already? */
2973  {
2974  /* duplicates are invalid */
2976  }
2977  Class = true; /* flag this for later processing */
2978  break;
2979  case SUBDIRECTIVE_PRIVATE:
2981  if (Access != DEFAULT_ACCESS_SCOPE) /* already seen one of these? */
2982  {
2983  /* duplicates are invalid */
2985  }
2986  Access = PRIVATE_SCOPE; /* flag for later processing */
2987  break;
2988  // define with package access
2989  case SUBDIRECTIVE_PACKAGE:
2991  // must be first access specifier
2992  if (Access != DEFAULT_ACCESS_SCOPE)
2993  {
2995  }
2996  Access = PACKAGE_SCOPE;
2997  break;
2998  /* ::METHOD name PUBLIC */
2999  case SUBDIRECTIVE_PUBLIC:
3001  if (Access != DEFAULT_ACCESS_SCOPE) /* already seen one of these? */
3002  {
3003  /* duplicates are invalid */
3005  }
3006  Access = PUBLIC_SCOPE; /* flag for later processing */
3007  break;
3008  /* ::METHOD name PROTECTED */
3011  if (Protected != DEFAULT_PROTECTION) /* already seen one of these? */
3012  {
3013  /* duplicates are invalid */
3015  }
3016  Protected = PROTECTED_METHOD; /* flag for later processing */
3017  break;
3020  if (Protected != DEFAULT_PROTECTION) /* already seen one of these? */
3021  {
3022  /* duplicates are invalid */
3024  }
3025  Protected = UNPROTECTED_METHOD; /* flag for later processing */
3026  break;
3027  /* ::METHOD name UNGUARDED */
3030  /* already seen one of these? */
3031  if (guard != DEFAULT_GUARD)
3032  {
3033  /* duplicates are invalid */
3035  }
3036  guard = UNGUARDED_METHOD;/* flag for later processing */
3037  break;
3038  /* ::METHOD name GUARDED */
3039  case SUBDIRECTIVE_GUARDED:
3041  /* already seen one of these? */
3042  if (guard != DEFAULT_GUARD)
3043  {
3044  /* duplicates are invalid */
3046  }
3047  guard = GUARDED_METHOD; /* flag for later processing */
3048  break;
3049  /* ::METHOD name ATTRIBUTE */
3050  case SUBDIRECTIVE_EXTERNAL:
3052  /* already had an external? */
3053  if (externalname != OREF_NULL || abstractMethod)
3054  {
3055  /* duplicates are invalid */
3057  }
3058  token = nextReal(); /* get the next token */
3059  /* not a string? */
3060  if (!token->isLiteral())
3061  {
3062  /* report an error */
3064  }
3065  externalname = token->value;
3066  break;
3067  /* ::METHOD name ABSTRACT */
3068  case SUBDIRECTIVE_ABSTRACT:
3069 
3070  if (abstractMethod || externalname != OREF_NULL)
3071  {
3073  }
3074  abstractMethod = true; /* flag for later processing */
3075  break;
3076 
3077 
3078  default: /* invalid keyword */
3079  /* this is an error */
3081  break;
3082  }
3083  }
3084  }
3085 
3086  // both attributes same default properties?
3087 
3088  // now get a variable retriever to get the property (do this before checking the body
3089  // so errors get diagnosed on the correct line),
3090  RexxVariableBase *retriever = this->getRetriever(name);
3091 
3092  switch (style)
3093  {
3094  case ATTRIBUTE_BOTH:
3095  {
3097  // now get this as the setter method.
3098  RexxString *setterName = commonString(internalname->concatWithCstring("="));
3100 
3101  // no code can follow the automatically generated methods
3103  if (externalname != OREF_NULL)
3104  {
3105  RexxString *library = OREF_NULL;
3106  RexxString *procedure = OREF_NULL;
3107  decodeExternalMethod(internalname, externalname, library, procedure);
3108  ProtectedObject p_library(library);
3109  ProtectedObject p_procedure(procedure);
3110  // now create both getter and setting methods from the information.
3111  RexxMethod *_method = createNativeMethod(internalname, library, procedure->concatToCstring("GET"));
3112  _method->setAttributes(Access, Protected, guard);
3113  // mark this as an attribute method
3114  _method->setAttribute();
3115  // add to the compilation
3116  addMethod(internalname, _method, Class);
3117 
3118  _method = createNativeMethod(setterName, library, procedure->concatToCstring("SET"));
3119  _method->setAttributes(Access, Protected, guard);
3120  // mark this as an attribute method
3121  _method->setAttribute();
3122  // add to the compilation
3123  addMethod(setterName, _method, Class);
3124  }
3125  // abstract method?
3126  else if (abstractMethod)
3127  {
3128  // create the method pair and quit.
3129  createAbstractMethod(internalname, Class, Access, Protected, guard, true);
3130  createAbstractMethod(setterName, Class, Access, Protected, guard, true);
3131  }
3132  else
3133  {
3134  // create the method pair and quit.
3135  createAttributeGetterMethod(internalname, retriever, Class, Access, Protected, guard);
3136  createAttributeSetterMethod(setterName, retriever, Class, Access, Protected, guard);
3137  }
3138  break;
3139 
3140  }
3141 
3142  case ATTRIBUTE_GET: // just the getter method
3143  {
3145  // external? resolve the method
3146  if (externalname != OREF_NULL)
3147  {
3148  // no code can follow external methods
3150  RexxString *library = OREF_NULL;
3151  RexxString *procedure = OREF_NULL;
3152  decodeExternalMethod(internalname, externalname, library, procedure);
3153  ProtectedObject p_library(library);
3154  ProtectedObject p_procedure(procedure);
3155  // if there was no procedure explicitly given, create one using the GET/SET convention
3156  if (internalname == procedure)
3157  {
3158  procedure = procedure->concatToCstring("GET");
3159  p_procedure = procedure;
3160  }
3161  // now create both getter and setting methods from the information.
3162  RexxMethod *_method = createNativeMethod(internalname, library, procedure);
3163  _method->setAttributes(Access, Protected, guard);
3164  // mark this as an attribute method
3165  _method->setAttribute();
3166  // add to the compilation
3167  addMethod(internalname, _method, Class);
3168  }
3169  // abstract method?
3170  else if (abstractMethod)
3171  {
3172  // no code can follow abstract methods
3174  // create the method pair and quit.
3175  createAbstractMethod(internalname, Class, Access, Protected, guard, true);
3176  }
3177  // either written in ooRexx or is automatically generated.
3178  else {
3179  if (hasBody())
3180  {
3181  createMethod(internalname, Class, Access, Protected, guard, true);
3182  }
3183  else
3184  {
3185  createAttributeGetterMethod(internalname, retriever, Class, Access, Protected, guard);
3186  }
3187  }
3188  break;
3189  }
3190 
3191  case ATTRIBUTE_SET:
3192  {
3193  // now get this as the setter method.
3194  RexxString *setterName = commonString(internalname->concatWithCstring("="));
3196  // external? resolve the method
3197  if (externalname != OREF_NULL)
3198  {
3199  // no code can follow external methods
3201  RexxString *library = OREF_NULL;
3202  RexxString *procedure = OREF_NULL;
3203  decodeExternalMethod(internalname, externalname, library, procedure);
3204  ProtectedObject p_library(library);
3205  ProtectedObject p_procedure(procedure);
3206  // if there was no procedure explicitly given, create one using the GET/SET convention
3207  if (internalname == procedure)
3208  {
3209  procedure = procedure->concatToCstring("SET");
3210  p_procedure = procedure;
3211  }
3212  // now create both getter and setting methods from the information.
3213  RexxMethod *_method = createNativeMethod(setterName, library, procedure);
3214  _method->setAttributes(Access, Protected, guard);
3215  // mark this as an attribute method
3216  _method->setAttribute();
3217  // add to the compilation
3218  addMethod(setterName, _method, Class);
3219  }
3220  // abstract method?
3221  else if (abstractMethod)
3222  {
3223  // no code can follow abstract methods
3225  // create the method pair and quit.
3226  createAbstractMethod(setterName, Class, Access, Protected, guard, true);
3227  }
3228  else
3229  {
3230  if (hasBody()) // just the getter method
3231  {
3232  createMethod(setterName, Class, Access, Protected, guard, true);
3233  }
3234  else
3235  {
3236  createAttributeSetterMethod(setterName, retriever, Class, Access, Protected, guard);
3237  }
3238  }
3239  break;
3240  }
3241  }
3242 }
3243 
3244 
3245 /**
3246  * Process a ::CONSTANT directive in a source file.
3247  */
3249 {
3250  RexxToken *token = nextReal(); /* get the next token */
3251  /* not a symbol or a string */
3252  if (!token->isSymbolOrLiteral())
3253  {
3254  /* report an error */
3256  }
3257  RexxString *name = token->value; /* get the string name */
3258  /* and the name form also */
3259  RexxString *internalname = this->commonString(name->upper());
3260  ProtectedObject p(internalname);
3261 
3262  // we only expect just a single value token here
3263  token = nextReal(); /* get the next token */
3264  RexxObject *value;
3265  /* not a symbol or a string */
3266  if (!token->isSymbolOrLiteral())
3267  {
3268  // if not a "+" or "-" operator, this is an error
3269  if (!token->isOperator() || (token->subclass != OPERATOR_SUBTRACT && token->subclass != OPERATOR_PLUS))
3270  {
3271  /* report an error */
3273  }
3274  RexxToken *second = nextReal();
3275  // this needs to be a constant symbol...we check for
3276  // numeric below
3277  if (!second->isSymbol() || second->subclass != SYMBOL_CONSTANT)
3278  {
3279  /* report an error */
3281  }
3282  // concat with the sign operator
3283  value = token->value->concat(second->value);
3284  // and validate that this a valid number
3285  if (value->numberString() == OREF_NULL)
3286  {
3287  /* report an error */
3289  }
3290  }
3291  else
3292  {
3293  // this will be some sort of literal value
3294  value = this->commonString(token->value);
3295  }
3296 
3297  token = nextReal(); /* get the next token */
3298  // No other options on this instruction
3299  if (!token->isEndOfClause())
3300  {
3301  /* report an error */
3303  }
3304  // this directive does not allow a body
3306 
3307  // check for duplicates. We only do the class duplicate check if there
3308  // is an active class, otherwise we'll get a syntax error
3310  if (this->active_class != OREF_NULL)
3311  {
3313  }
3314 
3315  // create the method pair and quit.
3316  createConstantGetterMethod(internalname, value);
3317 }
3318 
3319 
3320 /**
3321  * Create a Rexx method body.
3322  *
3323  * @param name The name of the attribute.
3324  * @param classMethod
3325  * Indicates whether we are creating a class or instance method.
3326  * @param privateMethod
3327  * The method's private attribute.
3328  * @param protectedMethod
3329  * The method's protected attribute.
3330  * @param guardedMethod
3331  * The method's guarded attribute.
3332  */
3333 void RexxSource::createMethod(RexxString *name, bool classMethod,
3334  AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod, bool isAttribute)
3335 {
3336  // NOTE: It is necessary to translate the block and protect the code
3337  // before allocating the RexxMethod object. The new operator allocates the
3338  // the object first, then evaluates the constructor arguments after the allocation.
3339  // Since the translateBlock() call will allocate a lot of new objects before returning,
3340  // there's a high probability that the method object can get garbage collected before
3341  // there is any opportunity to protect the object.
3342  RexxCode *code = this->translateBlock(OREF_NULL);
3343  this->saveObject((RexxObject *)code);
3344 
3345  /* go do the next block of code */
3346  RexxMethod *_method = new RexxMethod(name, code);
3347  _method->setAttributes(privateMethod, protectedMethod, guardedMethod);
3348  // mark with the attribute state
3349  _method->setAttribute(isAttribute);
3350  // go add the method to the accumulator
3351  addMethod(name, _method, classMethod);
3352 }
3353 
3354 
3355 /**
3356  * Create an ATTRIBUTE "get" method.
3357  *
3358  * @param name The name of the attribute.
3359  * @param retriever
3360  * @param classMethod
3361  * Indicates we're adding a class or instance method.
3362  * @param privateMethod
3363  * The method's private attribute.
3364  * @param protectedMethod
3365  * The method's protected attribute.
3366  * @param guardedMethod
3367  * The method's guarded attribute.
3368  */
3370  bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod)
3371 {
3372  // create the kernel method for the accessor
3373  BaseCode *code = new AttributeGetterCode(retriever);
3374  RexxMethod *_method = new RexxMethod(name, code);
3375  _method->setSourceObject(this);
3376  _method->setAttributes(privateMethod, protectedMethod, guardedMethod);
3377  // mark as an attribute method
3378  _method->setAttribute();
3379  // add this to the target
3380  addMethod(name, _method, classMethod);
3381 }
3382 
3383 
3384 /**
3385  * Create an ATTRIBUTE "set" method.
3386  *
3387  * @param name The name of the attribute.
3388  * @param classMethod
3389  * Indicates we're adding a class or instance method.
3390  * @param privateMethod
3391  * The method's private attribute.
3392  * @param protectedMethod
3393  * The method's protected attribute.
3394  * @param guardedMethod
3395  * The method's guarded attribute.
3396  */
3398  bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod)
3399 {
3400  // create the kernel method for the accessor
3401  BaseCode *code = new AttributeSetterCode(retriever);
3402  RexxMethod *_method = new RexxMethod(name, code);
3403  _method->setSourceObject(this);
3404  _method->setAttributes(privateMethod, protectedMethod, guardedMethod);
3405  // mark as an attribute method
3406  _method->setAttribute();
3407  // add this to the target
3408  addMethod(name, _method, classMethod);
3409 }
3410 
3411 
3412 /**
3413  * Create an abstract method.
3414  *
3415  * @param name The name of the method.
3416  * @param classMethod
3417  * Indicates we're adding a class or instance method.
3418  * @param privateMethod
3419  * The method's private attribute.
3420  * @param protectedMethod
3421  * The method's protected attribute.
3422  * @param guardedMethod
3423  * The method's guarded attribute.
3424  */
3426  bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod, bool isAttribute)
3427 {
3428  // create the kernel method for the accessor
3429  // this uses a special code block
3430  BaseCode *code = new AbstractCode();
3431  RexxMethod * _method = new RexxMethod(name, code);
3432  _method->setSourceObject(this);
3433  _method->setAttributes(privateMethod, protectedMethod, guardedMethod);
3434  // mark with the attribute state
3435  _method->setAttribute(isAttribute);
3436  // and also mark as abstract
3437  _method->setAbstract();
3438  // add this to the target
3439  addMethod(name, _method, classMethod);
3440 }
3441 
3442 
3443 /**
3444  * Create a CONSTANT "get" method.
3445  *
3446  * @param target The target method directory.
3447  * @param name The name of the attribute.
3448  */
3450 {
3451  ConstantGetterCode *code = new ConstantGetterCode(value);
3452  // add this as an unguarded method
3453  RexxMethod *method = new RexxMethod(name, code);
3454  method->setSourceObject(this);
3455  method->setUnguarded();
3456  // mark as a constant method
3457  method->setConstant();
3458 
3460  {
3461  addMethod(name, method, false);
3462  }
3463  else if (active_extension != OREF_NULL)
3464  {
3465  active_extension->addConstantMethod(name, method);
3466  }
3467  else
3468  {
3469  active_class->addConstantMethod(name, method);
3470  }
3471 }
3472 
3473 
3474 /**
3475  * Process a ::routine directive in a source file.
3476  */
3478 {
3479  RexxToken *token = nextReal(); /* get the next token */
3480  /* not a symbol or a string */
3481  if (!token->isSymbolOrLiteral())
3482  {
3483  /* report an error */
3485  }
3486  RexxString *name = token->value; /* get the routine name */
3487  /* does this already exist? */
3488  if (this->routines->entry(name) != OREF_NULL)
3489  {
3490  /* have an error here */
3492  }
3493  this->flags |= _install; /* have information to install */
3494  RexxString *externalname = OREF_NULL; /* no external name yet */
3495  AccessFlag Access = DEFAULT_ACCESS_SCOPE; /* not a public routine yet */
3496  for (;;) /* now loop on the option keywords */
3497  {
3498  token = nextReal(); /* get the next token */
3499  /* reached the end? */
3500  if (token->isEndOfClause())
3501  {
3502  break; /* get out of here */
3503  }
3504  /* not a symbol token? */
3505  else if (!token->isSymbol())
3506  {
3507  /* report an error */
3509  }
3510  /* process each sub keyword */
3511  switch (this->subDirective(token))
3512  {
3513  /* ::ROUTINE name EXTERNAL []*/
3514  case SUBDIRECTIVE_EXTERNAL:
3516  /* already had an external? */
3517  if (externalname != OREF_NULL)
3518  {
3519  /* duplicates are invalid */
3521  }
3522  token = nextReal(); /* get the next token */
3523  /* not a string? */
3524  if (!token->isLiteral())
3525  {
3526  /* report an error */
3528  }
3529  /* external name is token value */
3530  externalname = token->value;
3531  break;
3532  /* ::ROUTINE name PUBLIC */
3533  case SUBDIRECTIVE_PUBLIC:
3535  if (Access != DEFAULT_ACCESS_SCOPE) /* already had one of these? */
3536  {
3537  /* duplicates are invalid */
3539 
3540  }
3541  Access = PUBLIC_SCOPE; /* turn on the seen flag */
3542  break;
3543  /* ::ROUTINE name PUBLIC */
3544  case SUBDIRECTIVE_PRIVATE:
3546  if (Access != DEFAULT_ACCESS_SCOPE) /* already had one of these? */
3547  {
3548  /* duplicates are invalid */
3550 
3551  }
3552  Access = PRIVATE_SCOPE; /* turn on the seen flag */
3553  break;
3554 
3555  default: /* invalid keyword */
3556  /* this is an error */
3558  break;
3559  }
3560  }
3561  {
3562  this->saveObject(name); /* protect the name */
3563 
3564  if (externalname != OREF_NULL) /* have an external routine? */
3565  {
3566  /* convert external into words */
3567  RexxArray *_words = this->words(externalname);
3568  // ::ROUTINE foo EXTERNAL "LIBRARY libbar [foo]"
3569  if (((RexxString *)(_words->get(1)))->strCompare(CHAR_LIBRARY))
3570  {
3571  RexxString *library = OREF_NULL;
3572  // the default entry point name is the internal name
3573  RexxString *entry = name;
3574 
3575  // full library with entry name version?
3576  if (_words->size() == 3)
3577  {
3578  library = (RexxString *)_words->get(2);
3579  entry = (RexxString *)_words->get(3);
3580  }
3581  else if (_words->size() == 2)
3582  {
3583  library = (RexxString *)_words->get(2);
3584  }
3585  else // wrong number of tokens
3586  {
3587  /* this is an error */
3589  }
3590 
3591  /* go check the next clause to make */
3592  this->checkDirective(Error_Translation_external_routine); /* sure no code follows */
3593  /* create a new native method */
3594  RoutineClass *routine = PackageManager::resolveRoutine(library, entry);
3595  // raise an exception if this entry point is not found.
3596  if (routine == OREF_NULL)
3597  {
3599  }
3600  // make sure this is attached to the source object for context information
3601  routine->setSourceObject(this);
3602  /* add to the routine directory */
3603  this->routines->setEntry(name, routine);
3604  if (Access == PUBLIC_SCOPE) /* a public routine? */
3605  {
3606  /* add to the public directory too */
3607  this->public_routines->setEntry(name, routine);
3608  }
3609  }
3610 
3611  // ::ROUTINE foo EXTERNAL "REGISTERED libbar [foo]"
3612  else if (((RexxString *)(_words->get(1)))->strCompare(CHAR_REGISTERED))
3613  {
3614  RexxString *library = OREF_NULL;
3615  // the default entry point name is the internal name
3616  RexxString *entry = name;
3617 
3618  // full library with entry name version?
3619  if (_words->size() == 3)
3620  {
3621  library = (RexxString *)_words->get(2);
3622  entry = (RexxString *)_words->get(3);
3623  }
3624  else if (_words->size() == 2)
3625  {
3626  library = (RexxString *)_words->get(2);
3627  }
3628  else // wrong number of tokens
3629  {
3630  /* this is an error */
3632  }
3633 
3634  /* go check the next clause to make */
3635  this->checkDirective(Error_Translation_external_routine); /* sure no code follows */
3636  /* create a new native method */
3637  RoutineClass *routine = PackageManager::resolveRoutine(name, library, entry);
3638  // raise an exception if this entry point is not found.
3639  if (routine == OREF_NULL)
3640  {
3642  }
3643  // make sure this is attached to the source object for context information
3644  routine->setSourceObject(this);
3645  /* add to the routine directory */
3646  this->routines->setEntry(name, routine);
3647  if (Access == PUBLIC_SCOPE) /* a public routine? */
3648  {
3649  /* add to the public directory too */
3650  this->public_routines->setEntry(name, routine);
3651  }
3652  }
3653  else
3654  {
3655  /* unknown external type */
3657  }
3658  }
3659  else
3660  {
3661  // NOTE: It is necessary to translate the block and protect the code
3662  // before allocating the RexxMethod object. The new operator allocates the
3663  // the object first, then evaluates the constructor arguments after the allocation.
3664  // Since the translateBlock() call will allocate a lot of new objects before returning,
3665  // there's a high probability that the method object can get garbage collected before
3666  // there is any opportunity to protect the object.
3667  RexxCode *code = this->translateBlock(OREF_NULL);
3668  this->saveObject((RexxObject *)code);
3669  RoutineClass *routine = new RoutineClass(name, code);
3670  /* add to the routine directory */
3671  this->routines->setEntry(name, routine);
3672  if (Access == PUBLIC_SCOPE) /* a public routine? */
3673  {
3674  /* add to the public directory too */
3675  this->public_routines->setEntry(name, routine);
3676 
3677  }
3678  }
3679  this->toss(name); /* release the "Gary Cole" (GC) lock */
3680  }
3681 }
3682 
3683 /**
3684  * Process a ::REQUIRES directive.
3685  */
3687 {
3688  RexxToken *token = nextReal(); /* get the next token */
3689  /* not a symbol or a string */
3690  if (!token->isSymbolOrLiteral())
3691  {
3692  /* report an error */
3694  }
3695  RexxString *name = token->value; /* get the requires name */
3696  token = nextReal(); /* get the next token */
3697  if (!token->isEndOfClause()) /* something appear after this? */
3698  {
3699  // this is potentially a library directive
3700  libraryDirective(name, token);
3701  return;
3702  }
3703  this->flags |= _install; /* have information to install */
3704  /* save the ::requires location */
3705  this->requires->append((RexxObject *)new RequiresDirective(name, this->clause));
3706 }
3707 
3708 
3709 /**
3710  * Process a ::REQUIRES name LIBRARY directive.
3711  */
3713 {
3714  // we have an extra token on a ::REQUIRES directive. The only thing accepted here
3715  // is the token LIBRARY.
3716  if (!token->isSymbol())
3717  {
3719  }
3720  /* process each sub keyword */
3721  if (subDirective(token) != SUBDIRECTIVE_LIBRARY)
3722  {
3724  }
3726  token = nextReal(); /* get the next token */
3727  if (!token->isEndOfClause()) /* something appear after this? */
3728  {
3729  // nothing else allowed after this
3731  }
3732  this->flags |= _install; /* have information to install */
3733  // add this to the library list
3734  this->libraries->append((RexxObject *)new LibraryDirective(name, this->clause));
3735 }
3736 
3737 
3739 /********************************************************************/
3740 /* Function: parse a directive statement */
3741 /********************************************************************/
3742 {
3743  RexxToken *token; /* current token under processing */
3744 
3745  dumpClause("RexxSource::directive", this, this->clause);
3746  this->nextClause(); /* get the directive clause */
3747  dumpClause("RexxSource::directive", this, this->clause);
3748  if (this->flags&no_clause) /* reached the end? */
3749  return; /* all finished */
3750  token = nextReal(); /* skip the leading :: */
3751  if (token->classId != TOKEN_DCOLON) /* reached the end of a block? */
3752  /* have an error here */
3754  token = nextReal(); /* get the keyword token */
3755  if (!token->isSymbol()) /* not a symbol? */
3756  /* have an error here */
3758 
3759  int directiveType = this->keyDirective(token);
3760  if (directiveType != 0 ) refineSubclass(token, IS_DIRECTIVE);
3761  switch (this->keyDirective(token))
3762  { /* match against the directive list */
3763 
3764  case DIRECTIVE_CLASS: /* ::CLASS directive */
3765  classDirective();
3766  break;
3767 
3768  case DIRECTIVE_EXTENSION: /* ::EXTENSION directive */
3770  break;
3771 
3772  case DIRECTIVE_METHOD: /* ::METHOD directive */
3773  methodDirective();
3774  break;
3775 
3776  case DIRECTIVE_ROUTINE: /* ::ROUTINE directive */
3777  routineDirective();
3778  break;
3779 
3780  case DIRECTIVE_REQUIRES: /* ::REQUIRES directive */
3782  break;
3783 
3784  case DIRECTIVE_ATTRIBUTE: /* ::ATTRIBUTE directive */
3786  break;
3787 
3788  case DIRECTIVE_CONSTANT: /* ::CONSTANT directive */
3790  break;
3791 
3792  case DIRECTIVE_OPTIONS: /* ::OPTIONS directive */
3793  optionsDirective();
3794  break;
3795 
3796  default: /* unknown directive */
3798  break;
3799  }
3800 }
3801 
3802 
3804  RexxInstruction *_instruction) /* next instruction */
3805 /******************************************************************************/
3806 /* Function: Flush any pending compound instructions from the control stack */
3807 /* for new added instructions */
3808 /******************************************************************************/
3809 {
3810  size_t type; /* instruction type */
3811  RexxInstruction *second; /* additional created instructions */
3812 
3813  /* loop through the control stack */
3814  for (;;)
3815  {
3816  type = this->topDo()->getType(); /* get the instruction type */
3817  /* pending ELSE close? */
3818  if (type == KEYWORD_ELSE)
3819  {
3820  second = this->popDo(); /* pop the item off of the control */
3821  /* create a new end marker */
3822  second = this->endIfNew((RexxInstructionIf *)second);
3823  /* have an instruction? */
3824  if (_instruction != OREF_NULL)
3825  {
3826  this->addClause(_instruction); /* add this here */
3827  _instruction = OREF_NULL; /* don't process more instructions */
3828  }
3829  this->addClause(second); /* add the clause to the list */
3830  }
3831  /* nested IF-THEN situation? */
3832  else if (type == KEYWORD_IFTHEN || type == KEYWORD_WHENTHEN)
3833  {
3834  second = this->popDo(); /* pop the item off of the control */
3835  /* have an instruction? */
3836  if (_instruction != OREF_NULL)
3837  {
3838  this->addClause(_instruction); /* add this here */
3839  _instruction = OREF_NULL; /* don't process more instructions */
3840  /* create a new end marker */
3841  second = this->endIfNew((RexxInstructionIf *)second);
3842  this->addClause(second); /* add the clause to the list */
3843  this->pushDo(second); /* add to the control stack too */
3844  }
3845  else
3846  {
3847  /* create a new end marker */
3848  second = this->endIfNew((RexxInstructionIf *)second);
3849  this->addClause(second); /* add the clause to the list */
3850  this->pushDo(second); /* add to the control stack too */
3851  }
3852  break; /* finish up here */
3853  }
3854  /* some other type of construct */
3855  else
3856  {
3857  if (_instruction != OREF_NULL) /* have an instruction? */
3858  {
3859  this->addClause(_instruction); /* add this here */
3860  }
3861  break; /* finished flushing */
3862  }
3863  }
3864 }
3865 
3867  RexxDirectory *_labels ) /* labels (for interpret) */
3868 /******************************************************************************/
3869 /* Function: Translate a block of REXX code (delimited by possible */
3870 /* directive instructions */
3871 /******************************************************************************/
3872 {
3873  RexxInstruction *_instruction; /* created instruction item */
3874  RexxInstruction *second; /* secondary clause for IF/WHEN */
3875  RexxToken *token; /* current working token */
3876  size_t type; /* instruction type information */
3877  size_t controltype; /* type on the control stack */
3878 
3879  /* no instructions yet */
3880  OrefSet(this, this->first, OREF_NULL);
3881  OrefSet(this, this->last, OREF_NULL);
3882  /* allocate the call list */
3883  OrefSet(this, this->calls, new_list());
3884  /* create variables and lit tables */
3885  OrefSet(this, this->variables, (RexxDirectory *)TheCommonRetrievers->copy());
3886  /* restart the variable index */
3888  OrefSet(this, this->exposed_variables, new_directory());
3889  if (this->flags&_interpret) /* this an interpret? */
3890  {
3891  /* just use the existing label set */
3892  OrefSet(this, this->labels, _labels);
3893  }
3894  else
3895  {
3896  /* create a new labels directory */
3897  OrefSet(this, this->labels, new_directory());
3898  }
3899  /* not collecting guard variables yet*/
3900  OrefSet(this, this->guard_variables, OREF_NULL);
3901  this->maxstack = 0; /* clear all of the stack accounting */
3902  this->currentstack = 0; /* fields */
3903  this->flags &= ~no_clause; /* not reached the end yet */
3904 
3905  /* add the first dummy instruction */
3906  _instruction = new RexxInstruction(OREF_NULL, KEYWORD_FIRST);
3907  this->pushDo(_instruction); /* set bottom of control stack */
3908  this->addClause(_instruction); /* add to the instruction list */
3909  dumpTokens("RexxSource::translateBlock#1", this, this->clause);
3910  this->nextClause(); /* get the next physical clause */
3911  dumpClause("RexxSource::translateBlock#1", this, this->clause);
3912  for (;;) /* process all clauses */
3913  {
3914  _instruction = OREF_NULL; /* zero the instruction pointer */
3915  while (!(this->flags&no_clause)) /* scan through all labels */
3916  {
3917  /* resolve the instruction type */
3918  _instruction = this->instruction();
3919  if (_instruction == OREF_NULL) /* found a directive clause? */
3920  {
3921  break; /* return to higher level */
3922  }
3923  /* is this a label? */
3924  if (_instruction->getType() != KEYWORD_LABEL)
3925  {
3926  break; /* have a non-label clause */
3927  }
3928  this->addClause(_instruction); /* add this to clause list */
3929  dumpTokens("RexxSource::translateBlock#2", this, this->clause);
3930  this->nextClause(); /* get the next physical clause */
3931  dumpClause("RexxSource::translateBlock#2", this, this->clause);
3932  _instruction = OREF_NULL; /* no instruction any more */
3933  }
3934  /* get an end-of-clause? */
3935  if (this->flags&no_clause || _instruction == OREF_NULL)
3936  {
3937  /* get the control stack type */
3938  controltype = this->topDo()->getType();
3939  /* while end of an IF or WHEN */
3940  while (controltype == KEYWORD_ENDTHEN || controltype == KEYWORD_ENDWHEN)
3941  {
3942  this->popDo(); /* pop pending closing IFs */
3943  this->flushControl(OREF_NULL); /* flush any IFs or ELSEs */
3944  /* get the control stack type */
3945  controltype = this->topDo()->getType();
3946  }
3947  /* any unclosed composite clauses? */
3948  if (this->topDo()->getType() != KEYWORD_FIRST)
3949  {
3950  /* report the block error */
3951  blockSyntaxError(this->topDo());
3952  }
3953  this->popDo(); /* remove the top one */
3954  break; /* done parsing this section */
3955  }
3956  type = _instruction->getType(); /* get the top instruction type */
3957  if (type != KEYWORD_ELSE) /* have a pending THEN to finish */
3958  {
3959  /* get the control stack type */
3960  controltype = this->topDo()->getType();
3961  /* while end of an IF or WHEN */
3962  while (controltype == KEYWORD_ENDTHEN || controltype == KEYWORD_ENDWHEN)
3963  {
3964  this->popDo(); /* pop pending closing IFs */
3965  this->flushControl(OREF_NULL); /* flush any IFs or ELSEs */
3966  /* get the control stack type */
3967  controltype = this->topDo()->getType();
3968  }
3969  }
3970  if (type == KEYWORD_IF || type == KEYWORD_SELECT || type == KEYWORD_DO || type == KEYWORD_LOOP)
3971  {
3972  this->addClause(_instruction); /* add to instruction heap */
3973  }
3974  else if (type != KEYWORD_ELSE) /* not a new control level */
3975  {
3976  this->flushControl(_instruction); /* flush any IFs or ELSEs */
3977  }
3978  /* have a bad instruction within a */
3979  /* SELECT instruction? */
3980  if (this->topDo()->getType() == KEYWORD_SELECT &&
3982  {
3984  }
3985 
3986  switch (type) /* post process the instructions */
3987  {
3988  case KEYWORD_WHEN: /* WHEN clause of SELECT */
3989  second = this->topDo(); /* get the top of the queue */
3990  /* not working on a SELECT? */
3991  if (second->getType() != KEYWORD_SELECT)
3992  {
3994  }
3995  /* add this to the select list */
3996  ((RexxInstructionSelect *)second)->addWhen((RexxInstructionIf *)_instruction);
3997  /* just fall into IF logic */
3998 
3999  case KEYWORD_IF: /* start of an IF instruction */
4000  token = nextReal(); /* get the terminator token */
4001  /* have a terminator before the THEN?*/
4002  if (token->isEndOfClause())
4003  {
4004  dumpTokens("RexxSource::translateBlock#3", this, this->clause);
4005  this->nextClause(); /* get the next physical clause */
4006  dumpClause("RexxSource::translateBlock#3", this, this->clause);
4007  if (this->flags&no_clause) /* get an end-of-file? */
4008  {
4009  /* raise an error */
4010  syntaxError(Error_Then_expected_if, _instruction);
4011  }
4012  token = nextReal(); /* get the first token */
4013  /* not a THEN keyword? */
4014  if (!token->isSymbol() || this->keyword(token) != KEYWORD_THEN)
4015  {
4016  /* have an error */
4017  syntaxError(Error_Then_expected_if, _instruction);
4018  }
4019  /* create a new then clause */
4020  second = this->thenNew(token, (RexxInstructionIf *)_instruction);
4021  token = nextReal(); /* get token after THEN keyword */
4022  /* terminator here? */
4023  if (token->isEndOfClause())
4024  {
4025  dumpTokens("RexxSource::translateBlock#4", this, this->clause);
4026  this->nextClause(); /* get the next physical clause */
4027  dumpClause("RexxSource::translateBlock#4", this, this->clause);
4028  if (this->flags&no_clause) /* get an end-of-file? */
4029  {
4030  /* raise an error */
4031  syntaxError(Error_Incomplete_do_then, _instruction);
4032  }
4033  }
4034  else
4035  {
4036  previousToken(); /* step back a token */
4037  trimClause(); /* make this start of the clause */
4038  }
4039  }
4040  else /* if expr THEN form */
4041  {
4042  /* create a new then clause */
4043  second = this->thenNew(token, (RexxInstructionIf *)_instruction);
4044  token = nextReal(); /* get token after THEN keyword */
4045  /* terminator here? */
4046  if (token->isEndOfClause())
4047  {
4048  dumpTokens("RexxSource::translateBlock#5", this, this->clause);
4049  this->nextClause(); /* get the next physical clause */
4050  dumpClause("RexxSource::translateBlock#5", this, this->clause);
4051  if (this->flags&no_clause) /* get an end-of-file? */
4052  {
4053  /* raise an error */
4054  syntaxError(Error_Incomplete_do_then, _instruction);
4055  }
4056  }
4057  else
4058  {
4059  previousToken(); /* step back a token */
4060  trimClause(); /* make this start of the clause */
4061  }
4062  }
4063  this->addClause(second); /* add this to the instruction list */
4064  this->pushDo(second); /* add to top of control queue */
4065  continue; /* straight around to process clause */
4066  /* remainder */
4067  case KEYWORD_ELSE: /* have an ELSE instruction */
4068  second = this->topDo(); /* get the top block */
4069  if (this->topDo()->getType() != KEYWORD_ENDTHEN)
4070  {
4071  /* have an error */
4073  }
4074  this->addClause(_instruction); /* add to instruction heap */
4075  second = this->popDo(); /* pop the ENDTHEN item */
4076  this->pushDo(_instruction); /* add to the control list */
4077  /* join the THEN and ELSE together */
4078  ((RexxInstructionElse *)_instruction)->setParent((RexxInstructionEndIf *)second);
4079  ((RexxInstructionEndIf *)second)->setEndInstruction((RexxInstructionEndIf *)_instruction);
4080  token = nextReal(); /* get the next token */
4081  /* have an ELSE keyword alone? */
4082  if (token->isEndOfClause())
4083  {
4084  dumpTokens("RexxSource::translateBlock#6", this, this->clause);
4085  this->nextClause(); /* get the next physical clause */
4086  dumpClause("RexxSource::translateBlock#6", this, this->clause);
4087  if (this->flags&no_clause) /* get an end-of-file? */
4088  {
4089  /* raise an error */
4090  syntaxError(Error_Incomplete_do_else, _instruction);
4091  }
4092  }
4093  else /* ELSE instruction form */
4094  {
4095  previousToken(); /* step back a token */
4096  trimClause(); /* make this start of the clause */
4097  }
4098  continue; /* straight around to process clause */
4099  /* remainder */
4100 
4101  case KEYWORD_OTHERWISE: /* start of an OTHERWISE group */
4102  second = this->topDo(); /* get the top of the queue */
4103  /* not working on a SELECT? */
4104  if (second->getType() != KEYWORD_SELECT)
4105  {
4107  }
4108  /* hook up the OTHERWISE instruction */
4109  ((RexxInstructionSelect *)second)->setOtherwise((RexxInstructionOtherwise *)_instruction);
4110  this->pushDo(_instruction); /* add this to the control queue */
4111  token = nextReal(); /* get the next token */
4112  /* OTHERWISE instr form? */
4113  if (!token->isEndOfClause())
4114  {
4115  previousToken(); /* step back a token */
4116  trimClause(); /* make this start of the clause */
4117  continue; /* straight around to process clause */
4118  /* remainder */
4119  }
4120  break; /* normal OTHERWISE processing */
4121 
4122 
4123  case KEYWORD_END: /* END instruction for DO or SELECT */
4124  second = this->popDo(); /* get the top of the queue */
4125  type = second->getType(); /* get the instruction type */
4126  /* not working on a block? */
4128  {
4129  if (type == KEYWORD_ELSE) /* on an else? */
4130  {
4131  /* give the specific error */
4133  }
4134  else if (type == KEYWORD_IFTHEN || type == KEYWORD_WHENTHEN)
4135  {
4136  /* this is a different error */
4138  }
4139  else
4140  {
4141  /* have a misplaced END */
4143  }
4144  }
4145  if (type == KEYWORD_OTHERWISE) /* OTHERWISE part of a SELECT? */
4146  {
4147  second = this->popDo(); /* need to pop one more item off */
4148  }
4149  /* matching a select? */
4150  if (second->getType() == KEYWORD_SELECT)
4151  {
4152  /* match up the instruction */
4153  ((RexxInstructionSelect *)second)->matchEnd((RexxInstructionEnd *)_instruction, this);
4154  }
4155  else /* must be a DO block */
4156  {
4157  /* match up the instruction */
4158  ((RexxInstructionDo *)second)->matchEnd((RexxInstructionEnd *)_instruction, this);
4159  }
4160  this->flushControl(OREF_NULL); /* finish pending IFs or ELSEs */
4161  break;
4162 
4163  case KEYWORD_DO: // start of new DO group (also picks up LOOP instruction)
4164  case KEYWORD_LOOP:
4165  this->pushDo(_instruction); /* add this to the control queue */
4166  break;
4167 
4168  case KEYWORD_SELECT: /* start of new SELECT group */
4169  this->pushDo(_instruction); /* and also to the control queue */
4170  break;
4171 
4172  default: /* other types of instruction */
4173  break;
4174  }
4175  dumpTokens("RexxSource::translateBlock#7", this, this->clause);
4176  this->nextClause(); /* get the next physical clause */
4177  dumpClause("RexxSource::translateBlock#7", this, this->clause);
4178  }
4179  /* now go resolve any label targets */
4180  _instruction = (RexxInstruction *)(this->calls->removeFirst());
4181  /* while still more references */
4182  while (_instruction != (RexxInstruction *)TheNilObject)
4183  {
4184  /* actually a function call? */
4185  if (isOfClass(FunctionCallTerm, _instruction))
4186  {
4187  /* resolve the function call */
4188  ((RexxExpressionFunction *)_instruction)->resolve(this->labels);
4189  }
4190  else
4191  {
4192  /* resolve the CALL/SIGNAL/FUNCTION */
4193  /* label targets */
4194  ((RexxInstructionCallBase *)_instruction)->resolve(this->labels);
4195  }
4196  /* now get the next instruction */
4197  _instruction = (RexxInstruction *)(this->calls->removeFirst());
4198  }
4199  /* remove the first instruction */
4200  OrefSet(this, this->first, this->first->nextInstruction);
4201  /* no labels needed? */
4202  if (this->labels != OREF_NULL && this->labels->items() == 0)
4203  {
4204  /* release that directory also */
4205  OrefSet(this, this->labels, OREF_NULL);
4206  }
4207  /* create a rexx code object */
4208  return new RexxCode(this, this->first, this->labels, (this->maxstack+ 10), this->variableindex);
4209 }
4210 
4212 /******************************************************************************/
4213 /* Function: Process an individual REXX clause */
4214 /******************************************************************************/
4215 {
4216  RexxToken *_first; /* first token of clause */
4217  RexxToken *second; /* second token of clause */
4218  RexxInstruction *_instruction; /* current working instruction */
4219  RexxObject *term; /* term for a message send */
4220  RexxObject *subexpression; /* subexpression of a clause */
4221  int _keyword; /* resolved instruction keyword */
4222 
4223  _instruction = OREF_NULL; /* default to no instruction found */
4224  _first = nextReal(); /* get the first token */
4225 
4226  if (_first->classId == TOKEN_DCOLON)
4227  {/* reached the end of a block? */
4228  firstToken(); /* reset the location */
4229  this->reclaimClause(); /* give back the clause */
4230  }
4231  else
4232  { /* have a real instruction to process*/
4233  second = nextToken(); /* now get the second token */
4234  /* is this a label? (can be either */
4235  /* a symbol or a literal) */
4236  if ((_first->classId == TOKEN_SYMBOL || _first->classId == TOKEN_LITERAL) && second->classId == TOKEN_COLON)
4237  {
4238  if (this->flags&_interpret) /* is this an interpret? */
4239  {
4240  /* this is an error */
4242  }
4243  firstToken(); /* reset to the beginning */
4244  _instruction = this->labelNew(); /* create a label instruction */
4245  second = nextToken(); /* get the next token */
4246  /* not the end of the clause? */
4247  if (!second->isEndOfClause())
4248  {
4249  previousToken(); /* give this token back */
4250  trimClause(); /* make this start of the clause */
4251  this->reclaimClause(); /* give the remaining clause back */
4252  }
4253  return _instruction;
4254  }
4255 
4256  // this is potentially an assignment of the form "symbol = expr"
4257  if (_first->isSymbol())
4258  {
4259  // "symbol == expr" is considered an error
4260  if (second->subclass == OPERATOR_STRICT_EQUAL)
4261  {
4262  // With implicit return, an expression like value==1 is quite common, and not an error.
4263  // So, next line deactivated...
4264  // syntaxError(Error_Invalid_expression_general, second);
4265  }
4266  // true assignment instruction?
4267  if (second->subclass == OPERATOR_EQUAL)
4268  {
4269  return this->assignmentNew(_first);
4270  }
4271  // this could be a special assignment operator such as "symbol += expr"
4272  else if (second->classId == TOKEN_ASSIGNMENT)
4273  {
4274  return this->assignmentOpNew(_first, second);
4275  }
4276  // other
4277 
4278  }
4279 
4280  /* some other type of instruction */
4281  /* we need to skip over the first */
4282  /* term of the instruction to */
4283  /* determine the type of clause, */
4284  /* including recognition of keyword */
4285  /* instructions */
4286  firstToken(); /* reset to the first token */
4287  term = this->messageTerm(); /* get the first term of instruction */
4288  second = nextToken(); /* get the next token */
4289 
4290 
4291  // some sort of recognizable message term? Need to check for the
4292  // special cases.
4293  if (term != OREF_NULL)
4294  {
4295  // if parsing the message term consumed everything, this is a message instruction
4296  if (second->isEndOfClause())
4297  {
4298  return this->messageNew((RexxExpressionMessage *)term);
4299  }
4300 #if 0 // JLF : I want to support ~select{index~left(1) == "S"}
4301  else if (second->subclass == OPERATOR_STRICT_EQUAL)
4302  {
4303  // messageterm == something is an invalid assignment
4305  }
4306 #endif
4307  // messageterm = something is a pseudo assignment
4308  else if (second->subclass == OPERATOR_EQUAL)
4309  {
4310  this->saveObject(term); /* protect this */
4311  // we need an expression following the op token
4312  subexpression = this->subExpression(TERM_EOC);
4313  if (subexpression == OREF_NULL)
4314  {
4316  }
4317  // this is a message assignment
4318  _instruction = this->messageAssignmentNew((RexxExpressionMessage *)term, subexpression);
4319  this->toss(term); /* release the term */
4320  return _instruction;
4321  }
4322  // one of the special operator forms?
4323  else if (second->classId == TOKEN_ASSIGNMENT)
4324  {
4325  this->saveObject(term); /* protect this */
4326  // we need an expression following the op token
4327  subexpression = this->subExpression(TERM_EOC);
4328  if (subexpression == OREF_NULL)
4329  {
4331  }
4332  // this is a message assignment
4333  _instruction = this->messageAssignmentOpNew((RexxExpressionMessage *)term, second, subexpression);
4334  this->toss(term); /* release the term */
4335  return _instruction;
4336  }
4337  }
4338 
4339  // ok, none of the special cases passed....not start the keyword processing
4340 
4341  firstToken(); /* reset to the first token */
4342  _first = nextToken(); /* get the first token again */
4343  {
4344  size_t mark = markPosition();
4345  second = nextToken();
4346  resetPosition(mark);
4347  }
4348  /* is first a symbol that matches a */
4349  /* defined REXX keyword? */
4350  /* Not a keyword if the symbol is followed by a left paren (it's a function call) */
4351  /* [jlf] Not a keyword if the symbol is followed by a source literal (abbreviated syntax of a block passed as last argument) */
4352  if (_first->isSymbol() && (second->classId != TOKEN_LEFT) && (second->classId != TOKEN_SOURCE_LITERAL) && (_keyword = this->keyword(_first)))
4353  {
4354 
4355  switch (_keyword)
4356  { /* process each instruction type */
4357 
4358  case KEYWORD_NOP: /* NOP instruction */
4359  refineSubclass(_first, IS_KEYWORD);
4360  /* add the instruction to the parse */
4361  _instruction = this->nopNew();
4362  break;
4363 
4364  case KEYWORD_DROP: /* DROP instruction */
4365  refineSubclass(_first, IS_KEYWORD);
4366  /* add the instruction to the parse */
4367  _instruction = this->dropNew();
4368  break;
4369 
4370  case KEYWORD_SIGNAL: /* various forms of SIGNAL */
4371  refineSubclass(_first, IS_KEYWORD);
4372  /* add the instruction to the parse */
4373  _instruction = this->signalNew();
4374  break;
4375 
4376  case KEYWORD_CALL: /* various forms of CALL */
4377  refineSubclass(_first, IS_KEYWORD);
4378  /* add the instruction to the parse */
4379  _instruction = this->callNew();
4380  break;
4381 
4382  case KEYWORD_RAISE: /* RAISE instruction */
4383  refineSubclass(_first, IS_KEYWORD);
4384  /* add the instruction to the parse */
4385  _instruction = this->raiseNew();
4386  break;
4387 
4388  case KEYWORD_ADDRESS: /* ADDRESS instruction */
4389  refineSubclass(_first, IS_KEYWORD);
4390  /* add the instruction to the parse */
4391  _instruction = this->addressNew();
4392  break;
4393 
4394  case KEYWORD_NUMERIC: /* NUMERIC instruction */
4395  refineSubclass(_first, IS_KEYWORD);
4396  /* add the instruction to the parse */
4397  _instruction = this->numericNew();
4398  break;
4399 
4400  case KEYWORD_TRACE: /* TRACE instruction */
4401  refineSubclass(_first, IS_KEYWORD);
4402  /* add the instruction to the parse */
4403  _instruction = this->traceNew();
4404  break;
4405 
4406  case KEYWORD_DO: /* all variations of DO instruction */
4407  refineSubclass(_first, IS_KEYWORD);
4408  /* add the instruction to the parse */
4409  _instruction = this->doNew();
4410  break;
4411 
4412  case KEYWORD_LOOP: /* all variations of LOOP instruction */
4413  refineSubclass(_first, IS_KEYWORD);
4414  /* add the instruction to the parse */
4415  _instruction = this->loopNew();
4416  break;
4417 
4418  case KEYWORD_EXIT: /* EXIT instruction */
4419  refineSubclass(_first, IS_KEYWORD);
4420  /* add the instruction to the parse */
4421  _instruction = this->exitNew();
4422  break;
4423 
4424  case KEYWORD_INTERPRET: /* INTERPRET instruction */
4425  refineSubclass(_first, IS_KEYWORD);
4426  /* add the instruction to the parse */
4427  _instruction = this->interpretNew();
4428  break;
4429 
4430  case KEYWORD_PUSH: /* PUSH instruction */
4431  refineSubclass(_first, IS_KEYWORD);
4432  /* add the instruction to the parse */
4433  _instruction = this->queueNew(QUEUE_LIFO);
4434  break;
4435 
4436  case KEYWORD_QUEUE: /* QUEUE instruction */
4437  refineSubclass(_first, IS_KEYWORD);
4438  /* add the instruction to the parse */
4439  _instruction = this->queueNew(QUEUE_FIFO);
4440  break;
4441 
4442  case KEYWORD_REPLY: /* REPLY instruction */
4443  refineSubclass(_first, IS_KEYWORD);
4444  /* interpreted? */
4445  if (this->flags&_interpret)
4447  /* add the instruction to the parse */
4448  _instruction = this->replyNew();
4449  break;
4450 
4451  case KEYWORD_RETURN: /* RETURN instruction */
4452  refineSubclass(_first, IS_KEYWORD);
4453  /* add the instruction to the parse */
4454  _instruction = this->returnNew();
4455  break;
4456 
4457  case KEYWORD_IF: /* IF instruction */
4458  refineSubclass(_first, IS_KEYWORD);
4459  /* add the instruction to the parse */
4460  _instruction = this->ifNew(KEYWORD_IF);
4461  break;
4462 
4463  case KEYWORD_ITERATE: /* ITERATE instruction */
4464  refineSubclass(_first, IS_KEYWORD);
4465  /* add the instruction to the parse */
4466  _instruction = this->leaveNew(KEYWORD_ITERATE);
4467  break;
4468 
4469  case KEYWORD_LEAVE: /* LEAVE instruction */
4470  refineSubclass(_first, IS_KEYWORD);
4471  /* add the instruction to the parse */
4472  _instruction = this->leaveNew(KEYWORD_LEAVE);
4473  break;
4474 
4475  case KEYWORD_EXPOSE: /* EXPOSE instruction */
4476  refineSubclass(_first, IS_KEYWORD);
4477  /* interpreted? */
4478  if (this->flags&_interpret)
4480  /* add the instruction to the parse */
4481  _instruction = this->exposeNew();
4482  break;
4483 
4484  case KEYWORD_FORWARD: /* FORWARD instruction */
4485  refineSubclass(_first, IS_KEYWORD);
4486  /* interpreted? */
4487  if (this->flags&_interpret)
4489  /* add the instruction to the parse */
4490  _instruction = this->forwardNew();
4491  break;
4492 
4493  case KEYWORD_PROCEDURE: /* PROCEDURE instruction */
4494  refineSubclass(_first, IS_KEYWORD);
4495  /* add the instruction to the parse */
4496  _instruction = this->procedureNew();
4497  break;
4498 
4499  case KEYWORD_GUARD: /* GUARD instruction */
4500  refineSubclass(_first, IS_KEYWORD);
4501  /* interpreted? */
4502  if (this->flags&_interpret)
4504  /* add the instruction to the parse */
4505  _instruction = this->guardNew();
4506  break;
4507 
4508  case KEYWORD_USE: /* USE instruction */
4509  refineSubclass(_first, IS_KEYWORD);
4510  /* interpreted? */
4511  if (this->flags&_interpret)
4513  /* add the instruction to the parse */
4514  _instruction = this->useNew();
4515  break;
4516 
4517  case KEYWORD_ARG: /* ARG instruction */
4518  refineSubclass(_first, IS_KEYWORD);
4519  /* add the instruction to the parse */
4520  _instruction = this->parseNew(SUBKEY_ARG);
4521  break;
4522 
4523  case KEYWORD_PULL: /* PULL instruction */
4524  refineSubclass(_first, IS_KEYWORD);
4525  /* add the instruction to the parse */
4526  _instruction = this->parseNew(SUBKEY_PULL);
4527  break;
4528 
4529  case KEYWORD_PARSE: /* PARSE instruction */
4530  refineSubclass(_first, IS_KEYWORD);
4531  /* add the instruction to the parse */
4532  _instruction = this->parseNew(KEYWORD_PARSE);
4533  break;
4534 
4535  case KEYWORD_SAY: /* SAY instruction */
4536  refineSubclass(_first, IS_KEYWORD);
4537  /* add the instruction to the parse */
4538  _instruction = this->sayNew();
4539  break;
4540 
4541  case KEYWORD_OPTIONS: /* OPTIONS instruction */
4542  refineSubclass(_first, IS_KEYWORD);
4543  /* add the instruction to the parse */
4544  _instruction = this->optionsNew();
4545  break;
4546 
4547  case KEYWORD_SELECT: /* SELECT instruction */
4548  refineSubclass(_first, IS_KEYWORD);
4549  /* add the instruction to the parse */
4550  _instruction = this->selectNew();
4551  break;
4552 
4553  case KEYWORD_WHEN: /* WHEN in an SELECT instruction */
4554  refineSubclass(_first, IS_KEYWORD);
4555  /* add the instruction to the parse */
4556  _instruction = this->ifNew(KEYWORD_WHEN);
4557  break;
4558 
4559  case KEYWORD_OTHERWISE: /* OTHERWISE in a SELECT */
4560  refineSubclass(_first, IS_KEYWORD);
4561  /* add the instruction to the parse */
4562  _instruction = this->otherwiseNew(_first);
4563  break;
4564 
4565  case KEYWORD_ELSE: /* unexpected ELSE */
4566  refineSubclass(_first, IS_KEYWORD);
4567  /* add the instruction to the parse */
4568  _instruction = this->elseNew(_first);
4569  break;
4570 
4571  case KEYWORD_END: /* END for a block construct */
4572  refineSubclass(_first, IS_KEYWORD);
4573  /* add the instruction to the parse */
4574  _instruction = this->endNew();
4575  break;
4576 
4577  case KEYWORD_THEN: /* unexpected THEN */
4578  /* raise an error */
4580  break;
4581 
4582  case KEYWORD_UPPER: /* UPPER instruction */
4583  refineSubclass(_first, IS_KEYWORD);
4584  /* add the instruction to the parse */
4585  _instruction = this->upperNew();
4586  break;
4587  }
4588  }
4589  else
4590  { /* this is a "command" instruction */
4591  firstToken(); /* reset to the first token */
4592  /* process this instruction */
4593  _instruction = this->commandNew();
4594  }
4595  }
4596  return _instruction; /* return the created instruction */
4597 }
4598 
4600  RexxString *varname) /* variable to add */
4601 /******************************************************************************/
4602 /* Function: Resolve a variable name to a single common retriever object */
4603 /* per method */
4604 /******************************************************************************/
4605 {
4606  /* check the directory for an entry */
4607  RexxVariableBase *retriever = (RexxVariableBase *)this->variables->fastAt(varname);
4608  if (retriever == OREF_NULL) /* not in the table yet? */
4609  {
4610  if (!(this->flags&_interpret)) /* not in an interpret? */
4611  {
4612  this->variableindex++; /* step the counter */
4613  /* create a new variable retriever */
4614  retriever = new RexxParseVariable(varname, this->variableindex);
4615  }
4616  else /* force dynamic lookup each time */
4617  {
4618  retriever = new RexxParseVariable(varname, 0);
4619  }
4620  /* add to the variable table */
4621  this->variables->put((RexxObject *)retriever, varname);
4622  }
4623  /* collecting guard variables? */
4624  if (this->guard_variables != OREF_NULL)
4625  {
4626  /* in the list of exposed variables? */
4627  if (this->exposed_variables != OREF_NULL && this->exposed_variables->fastAt(varname) != OREF_NULL)
4628  {
4629  /* add this to the guard list */
4630  this->guard_variables->put((RexxObject *)retriever, (RexxObject *)retriever);
4631  }
4632  }
4633  return retriever; /* return variable accesser */
4634 }
4635 
4637  RexxString *stemName) /* stem to add */
4638 /******************************************************************************/
4639 /* Function: Process creation of stem variables */
4640 /******************************************************************************/
4641 {
4642  /* check the table for an entry */
4643  RexxStemVariable *retriever = (RexxStemVariable *)(this->variables->fastAt(stemName));
4644  if (retriever == OREF_NULL) /* not in the table yet? */
4645  {
4646  if (!(this->flags&_interpret)) /* not in an interpret? */
4647  {
4648  this->variableindex++; /* step the counter */
4649  /* create a new variable retriever */
4650  retriever = new RexxStemVariable(stemName, this->variableindex);
4651  }
4652  else /* force dynamic lookup each time */
4653  {
4654  retriever = new RexxStemVariable(stemName, 0);
4655  }
4656  /* add to the variable table */
4657  this->variables->put((RexxObject *)retriever, stemName);
4658  }
4659  /* collecting guard variables? */
4660  if (this->guard_variables != OREF_NULL)
4661  {
4662  /* in the list of exposed variables? */
4663  if (this->exposed_variables != OREF_NULL && this->exposed_variables->fastAt(stemName) != OREF_NULL)
4664  {
4665  /* add this to the guard list */
4666  this->guard_variables->put((RexxObject *)retriever, (RexxObject *)retriever);
4667  }
4668  }
4669  return retriever; /* return variable accesser */
4670 }
4671 
4672 
4674  RexxString *name) /* name of the compound variable */
4675 /******************************************************************************/
4676 /* Function: Parse to completion a compound variable */
4677 /******************************************************************************/
4678 {
4679  RexxStemVariable *stemRetriever; /* retriever for the stem value */
4680  RexxString *stemName; /* stem part of compound variable */
4681  RexxString *tail; /* tail section string value */
4682  const char * start; /* starting scan position */
4683  size_t length; /* length of tail section */
4684  const char * _position; /* current position */
4685  const char * end; // the end scanning position
4686  size_t tailCount; /* count of tails in compound */
4687 
4688  length = name->getLength(); /* get the string length */
4689  _position = name->getStringData(); /* start scanning at first character */
4690  start = _position; /* save the starting point */
4691  end = _position + length; // save our end marker
4692 
4693  // we know this is a compound, so there must be at least one period.
4694  /* scan to the first period */
4695  while (*_position != '.')
4696  {
4697  _position++; /* step to the next character */
4698  }
4699  /* get the stem string */
4700  stemName = new_string(start, _position - start + 1);
4701  stemRetriever = this->addStem(stemName); /* get a retriever item for this */
4702 
4703  tailCount = 0; /* no tails yet */
4704  do /* process rest of the variable */
4705  {
4706  // we're here because we just saw a previous period. that's either the
4707  // stem variable period or the last tail element we processed.
4708  // either way, we step past it. If this period is a trailing one,
4709  // we'll add a null tail element, which is exactly what we want.
4710  _position++; /* step past previous period */
4711  start = _position; /* save the start position */
4712  /* scan for the next period */
4713  while (_position < end)
4714  {
4715  if (*_position == '.') // found the next one?
4716  {
4717  break; // stop scanning now
4718  }
4719  _position++; // continue looking
4720  }
4721  /* extract the tail piece */
4722  tail = new_string(start, _position - start);
4723  /* have a null tail piece or */
4724  /* section begin with a digit? */
4725  if (!(tail->getLength() == 0 || (*start >= '0' && *start <= '9')))
4726  {
4727  /* push onto the term stack */
4728  this->subTerms->push((RexxObject *)(this->addVariable(tail)));
4729  }
4730  else
4731  {
4732  /* just use the string value directly*/
4733  this->subTerms->push(this->commonString(tail));
4734  }
4735  tailCount++; /* up the tail count */
4736  } while (_position < end);
4737  /* finally, create the compound var */
4738  return new (tailCount) RexxCompoundVariable(name, stemName, stemRetriever->index, this->subTerms, tailCount);
4739 }
4740 
4741 
4743  RexxString *name ) /* variable name to add to list */
4744 /******************************************************************************/
4745 /* Function: Add a variable name to the list of exposed variables for the */
4746 /* method. */
4747 /******************************************************************************/
4748 {
4749  /* add to the exposed variables list */
4750  this->exposed_variables->put(name, name);
4751 }
4752 
4753 
4755  RexxString *string ) /* string token to "collapse" */
4756 /******************************************************************************/
4757 /* Function: Compress all string tokens needed by a group of programs into */
4758 /* a single, common set of strings. */
4759 /******************************************************************************/
4760 {
4761  /* check the global table first */
4762  RexxString *result = (RexxString *)this->strings->fastAt(string);
4763  /* not in the table */
4764  if (result == OREF_NULL)
4765  {
4766  ProtectedObject p(string); // often string is a non-protected object on the caller side, better to protect it now
4767  this->strings->put(string, string);/* add this to the table */
4768  result = string; /* also the final value */
4769  }
4770 #if debug_encoding // debug encoding
4771  if ((string->getText() != OREF_NULL && string->getText() != string) || (string->getEncoding() != OREF_NULL && string->getEncoding() != string)) printf("RexxSource::commonString string (in) PANIC string=%p text=%p encoding=%p %s\n", string, string->getText(), string->getEncoding(), string->getStringData());
4772  if ((result->getText() != OREF_NULL && result->getText() != result) || (result->getEncoding() != OREF_NULL && result->getEncoding() != result)) printf("RexxSource::commonString result (out) PANIC result=%p text=%p encoding=%p %s\n", result, result->getText(), result->getEncoding(), result->getStringData());
4773 #endif // debug encoding
4774  return result; /* return the string */
4775 }
4776 
4777 
4779 {
4780  needVariable(token);
4781  return addText(token);
4782 }
4783 
4784 
4786  RexxToken *token) /* token to process */
4787 /******************************************************************************/
4788 /* Function: Generalized text token addition */
4789 /******************************************************************************/
4790 {
4791  RexxObject *retriever; /* created retriever */
4792  RexxObject *value; /* evaluated literal value */
4793 
4794  RexxString *name = token->value; /* get the string value for this */
4795  switch (token->classId)
4796  {
4797 
4798  case TOKEN_SYMBOL: /* various types of symbols */
4799  /* each symbol subtype requires a */
4800  /* different retrieval method */
4801  switch (token->subclass)
4802  {
4803 
4804  case SYMBOL_DUMMY: /* just a dot symbol */
4805  case SYMBOL_CONSTANT: /* a literal symbol */
4806 
4807  /* see if we've had this before */
4808  retriever = this->literals->fastAt(name);
4809  /* first time literal? */
4810  if (retriever == OREF_NULL)
4811  {
4812  /* can we create an integer object? */
4813  if (token->numeric == INTEGER_CONSTANT)
4814  {
4815  /* create this as an integer */
4817  /* conversion error? */
4818  if (value == TheNilObject)
4819  {
4820  value = name; /* just go with the string value */
4821  }
4822  else
4823  /* snip off the string number string */
4824  /* value that was created when the */
4825  /* integer value was created. This */
4826  /* is rarely used, but contributes */
4827  /* to the saved program size */
4828  name->setNumberString(OREF_NULL);
4829  }
4830  else
4831  {
4832  value = name; /* just use the string value */
4833  /* give it a number string value */
4834  name->setNumberString((RexxObject *)value->numberString());
4835  }
4836  /* the constant is the retriever */
4837  this->literals->put(value, name);
4838  retriever = value; /* the retriever is the value itthis */
4839  }
4840  break;
4841 
4842  case SYMBOL_VARIABLE: /* simple variable symbol */
4843  /* add variable to proper dictionary */
4844  retriever = (RexxObject *)this->addVariable(name);
4845  break;
4846 
4847  case SYMBOL_STEM: /* stem variable */
4848  /* add variable to proper dictionary */
4849  retriever = (RexxObject *)this->addStem(name);
4850  break;
4851 
4852  case SYMBOL_COMPOUND: /* compound variable, need more */
4853  /* add variable to proper dictionary */
4854  retriever = (RexxObject *)this->addCompound(name);
4855  break;
4856 
4857  case SYMBOL_DOTSYMBOL: /* variable with a leading dot */
4858  /* get a lookup object */
4859  /* see if we've had this before */
4860  retriever = this->variables->fastAt(name);
4861  /* first time dot variable? */
4862  if (retriever == OREF_NULL)
4863  {
4864  /* create the shorter name */
4865  value = name->extract(1, name->getLength() - 1);
4866  /* add this to the common pile */
4867  value = this->commonString((RexxString *)value);
4868  /* create a retriever for this */
4869  retriever = (RexxObject *)new RexxDotVariable((RexxString *)value);
4870  /* add this to the common table */
4871  this->variables->put(retriever, name);
4872  }
4873  break;
4874 
4875  default: /* all other types (shouldn't happen)*/
4876  retriever = OREF_NULL; /* return nothing */
4877  break;
4878  }
4879  break;
4880 
4881  case TOKEN_LITERAL: /* literal strings */
4882  /* get a lookup object */
4883  /* see if we've had this before */
4884  retriever = this->literals->fastAt(name);
4885  /* first time literal? */
4886  if (retriever == OREF_NULL)
4887  {
4888  /* the constant is the retriever */
4889  this->literals->put(name, name);
4890  retriever = name; /* use the name directly */
4891  }
4892  break;
4893 
4894  case TOKEN_SOURCE_LITERAL: /* source literal strings */
4895  {
4896  // can't optimize like TOKEN_LITERAL because need a distinct source object for each source literal
4897  RexxString *source = new_string(name->getStringData()+1, name->getLength()-2); // Remove surrounding {}
4898  ProtectedObject p(source); // an array of lines will be derived from it, which could trigger GC
4899  PackageClass *package = this->isInterpret() ? this->interpret_activation->getPackage() : this->getPackage();
4900  // Remember : I pass only the startLine instead of the complete tokenLocation because the source array built
4901  // from the string MAY be one line smaller than tokenLocation.endLine (that happens when the final '}' is
4902  // the first character of the last line. The "real" endLine will be calculated using the source array size.
4903  retriever = (RexxObject *) new RexxSourceLiteral(source, package, token->tokenLocation.getLineNumber());
4904  p = retriever; // Now protect the source literal
4905  this->sourceLiterals->append(retriever); // Hooked, to not GC it.
4906  }
4907  break;
4908 
4909  default: /* all other tokens */
4910  retriever = OREF_NULL; /* don't return anything */
4911  break;
4912  }
4913  return retriever; /* return created retriever */
4914 }
4915 
4917  RexxString *name) /* name of the variable to process */
4918 /******************************************************************************/
4919 /* Function: Generalized method attribute retriever */
4920 /******************************************************************************/
4921 {
4922  RexxVariableBase *retriever = OREF_NULL; /* created retriever */
4923 
4924  /* go validate the symbol */
4925  switch (name->isSymbol())
4926  {
4927 
4928  case STRING_NAME: /* valid simple name */
4929  /* get a simple dynamic retriever */
4930  retriever = (RexxVariableBase *)new RexxParseVariable(name, 0);
4931  break;
4932 
4933  case STRING_STEM: /* this is a stem name */
4934  /* force dynamic lookup each time */
4935  retriever = (RexxVariableBase *)new RexxStemVariable(name, 0);
4936  break;
4937 
4938  case STRING_COMPOUND_NAME: /* compound variable name */
4939  /* get a direct retriever for this */
4941  break;
4942 
4943  default: /* all other invalid cases */
4944  /* have an invalid attribute */
4946  }
4947  return retriever; /* return created retriever */
4948 }
4949 
4950 
4952  RexxInstruction *_instruction) /* new label to add */
4953 /******************************************************************************/
4954 /* Add an instruction to the tree code execution stream */
4955 /******************************************************************************/
4956 {
4957 #ifdef _DEBUG
4959  {
4960  RexxString *instructionSource = this->extract(_instruction->instructionLocation, true);
4961  ProtectedObject p(instructionSource);
4963  {
4964  // To avoid mixing output from different threads , better to have one dbgprintf instead of several.
4965  struct ConcurrencyInfos concurrencyInfos;
4966  Utilities::GetConcurrencyInfos(concurrencyInfos);
4967  dbgprintf( CONCURRENCY_TRACE "...... ... "
4968  "(Parsing)Add RexxInstruction : instructionType=\"%s\" instructionFlags=%i "
4969  "startLine=%i startCol=%i endLine=%i endCol=%i "
4970  "instruction={%s}\n",
4971  concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock,
4972  RexxToken::keywordText(_instruction->instructionType), _instruction->instructionFlags,
4973  _instruction->instructionLocation.getLineNumber(), _instruction->instructionLocation.getOffset(), _instruction->instructionLocation.getEndLine(), _instruction->instructionLocation.getEndOffset(),
4974  instructionSource->getStringData());
4975  }
4976  else
4977  {
4978  // Here, we don't display concurrency trace, we have only one dbgprintf, good.
4979  dbgprintf( "(Parsing)Add RexxInstruction : instructionType=\"%s\" instructionFlags=%i "
4980  "startLine=%i startCol=%i endLine=%i endCol=%i "
4981  "instruction={%s}\n",
4982  RexxToken::keywordText(_instruction->instructionType), _instruction->instructionFlags,
4983  _instruction->instructionLocation.getLineNumber(), _instruction->instructionLocation.getOffset(), _instruction->instructionLocation.getEndLine(), _instruction->instructionLocation.getEndOffset(),
4984  instructionSource->getStringData());
4985  }
4986  }
4987 #endif
4988 
4989  /* is this the first one? */
4990  if (this->first == OREF_NULL)
4991  {
4992  /* make this the first one */
4993  OrefSet(this, this->first, _instruction);
4994  /* and the last one */
4995  OrefSet(this, this->last, _instruction);
4996  }
4997  /* non-root instruction */
4998  else
4999  {
5000  this->last->setNext(_instruction); /* add on to the last instruction */
5001  /* this is the new last instruction */
5002  OrefSet(this, this->last, _instruction);
5003  }
5004  /* now safe from garbage collection */
5005  this->toss((RexxObject *)_instruction);
5006 }
5007 
5008 
5010  RexxInstruction *label, /* new label to add */
5011  RexxString *labelname ) /* the label name */
5012 /******************************************************************************/
5013 /* Function: add a label to the global label table. */
5014 /******************************************************************************/
5015 {
5016  /* not already in the table? */
5017  if (this->labels->fastAt(labelname) == OREF_NULL)
5018  {
5019  /* add this item */
5020  this->labels->put((RexxObject *)label, labelname);
5021  }
5022 }
5023 
5024 
5026  RexxString *labelname) /* target label */
5027 /******************************************************************************/
5028 /* Search the label table for a label name match */
5029 /******************************************************************************/
5030 {
5031  if (this->labels != OREF_NULL) /* have labels? */
5032  {
5033  /* just return entry from the table */
5034  return(RexxInstruction *)this->labels->fastAt(labelname);
5035  }
5036  else
5037  {
5038  return OREF_NULL; /* don't return anything */
5039  }
5040 }
5041 
5043 /******************************************************************************/
5044 /* Function: Set on guard expression variable "gathering" */
5045 /******************************************************************************/
5046 {
5047  /* just starting to trap? */
5048  if (this->guard_variables == OREF_NULL)
5049  {
5050  /* create the guard table */
5051  OrefSet(this, this->guard_variables, new_identity_table());
5052  }
5053 }
5054 
5056 /******************************************************************************/
5057 /* Function: Complete guard expression variable collection and return the */
5058 /* table of variables. */
5059 /******************************************************************************/
5060 {
5061  /* convert into an array */
5062  RexxArray *guards = this->guard_variables->makeArray();
5063  /* discard the table */
5064  OrefSet(this, this->guard_variables, OREF_NULL);
5065  /* just starting to trap? */
5066  return guards; /* return the guards array */
5067 }
5068 
5070 /******************************************************************************/
5071 /* Function: Evaluate a "constant" expression for REXX instruction keyword */
5072 /* values. A constant expression is a literal string, constant */
5073 /* symbol, or an expression enclosed in parentheses. */
5074 /******************************************************************************/
5075 {
5076  RexxToken *token; /* current token */
5077  RexxToken *second; /* second token */
5078  RexxObject *_expression = OREF_NULL; /* parse expression */
5079 
5080  token = nextReal(); /* get the first token */
5081  if (token->isLiteral()) /* literal string expression? */
5082  {
5083  _expression = this->addText(token); /* get the literal retriever */
5084  }
5085  else if (token->isSourceLiteral()) /* source literal expression? */
5086  {
5087  _expression = this->addText(token); /* get the literal retriever */
5088  }
5089  else if (token->isConstant()) /* how about a constant symbol? */
5090  {
5091  _expression = this->addText(token); /* get the literal retriever */
5092  }
5093  /* got an end of expression? */
5094  else if (token->isEndOfClause())
5095  {
5096  previousToken(); /* push the token back */
5097  return OREF_NULL; /* nothing here (may be optional) */
5098  }
5099  /* not a left paren here? */
5100  else if (token->classId != TOKEN_LEFT)
5101  {
5102  /* this is an invalid expression */
5104  }
5105  else
5106  {
5107  /* get the subexpression */
5108  _expression = this->subExpression(TERM_EOC | TERM_RIGHT);
5109  second = nextToken(); /* get the terminator token */
5110  /* not terminated by a right paren? */
5111  if (second->classId != TOKEN_RIGHT)
5112  {
5113  /* this is an error */
5115  }
5116  }
5117  this->holdObject(_expression); /* protect the expression */
5118  return _expression; /* and return it */
5119 }
5120 
5122 /******************************************************************************/
5123 /* Function: Evaluate a "constant" expression for REXX instruction keyword */
5124 /* values. A constant expression is a literal string, constant */
5125 /* symbol, or an expression enclosed in parentheses. The */
5126 /* expression inside parens can be a complex logical expression. */
5127 /******************************************************************************/
5128 {
5129  RexxToken *token; /* current token */
5130  RexxToken *second; /* second token */
5131  RexxObject *_expression = OREF_NULL; /* parse expression */
5132 
5133  token = nextReal(); /* get the first token */
5134  if (token->isLiteral()) /* literal string expression? */
5135  {
5136 
5137  _expression = this->addText(token); /* get the literal retriever */
5138  }
5139  else if (token->isSourceLiteral()) /* source literal expression? */
5140  {
5141  _expression = this->addText(token); /* get the literal retriever */
5142  }
5143  else if (token->isConstant()) /* how about a constant symbol? */
5144  {
5145  _expression = this->addText(token); /* get the literal retriever */
5146  }
5147  /* got an end of expression? */
5148  else if (token->isEndOfClause())
5149  {
5150  previousToken(); /* push the token back */
5151  return OREF_NULL; /* nothing here (may be optional) */
5152  }
5153  /* not a left paren here? */
5154  else if (token->classId != TOKEN_LEFT)
5155  {
5156  /* this is an invalid expression */
5158  }
5159  else
5160  {
5161  /* get the subexpression */
5162  _expression = this->parseLogical(token, TERM_EOC | TERM_RIGHT);
5163  second = nextToken(); /* get the terminator token */
5164  /* not terminated by a right paren? */
5165  if (second->classId != TOKEN_RIGHT)
5166  {
5167  /* this is an error */
5169  }
5170  }
5171  this->holdObject(_expression); /* protect the expression */
5172  return _expression; /* and return it */
5173 }
5174 
5176 /******************************************************************************/
5177 /* Function: Evaluate a "parenthetical" expression for REXX instruction */
5178 /* values. A parenthetical expression is an expression enclosed */
5179 /* in parentheses. */
5180 /******************************************************************************/
5181 {
5182  // NB, the opening paren has already been parsed off
5183 
5184  RexxObject *_expression = this->subExpression(TERM_EOC | TERM_RIGHT);
5185  RexxToken *second = nextToken(); /* get the terminator token */
5186  /* not terminated by a right paren? */
5187  if (second->classId != TOKEN_RIGHT)
5188  {
5190  }
5191  /* this is an error */
5192  this->holdObject(_expression); /* protect the expression */
5193  return _expression; /* and return it */
5194 }
5195 
5197  int terminators ) /* expression termination context */
5198 /******************************************************************************/
5199 /* Function: Parse off an expression, stopping when one of the possible set */
5200 /* of terminator tokens is reached. The terminator token is */
5201 /* placed back on the token queue. */
5202 /******************************************************************************/
5203 {
5204  nextReal(); /* get the first real token */
5205  previousToken(); /* now put it back */
5206  /* parse off the subexpression */
5207  // return this->subExpression(terminators);
5208  return this->fullSubExpression(terminators);
5209 }
5210 
5211 /**
5212  * Perform the parsing of an expression where the expression
5213  * can be treated as a comma-separated list of subexpressions.
5214  * If we have just a simple single subexpression, the
5215  * return value is the parsed subexpression. If a comma
5216  * is found as a terminator, then we turn this expression
5217  * into an operator that will create an array object from the
5218  * list of expressions. Omitted expressions are allowed and
5219  * no effort is made to remove trailing null expressions.
5220  *
5221  * @param terminators
5222  * The list of terminators for this expression type.
5223  *
5224  * @return Either a simple expression, or an expression object for
5225  * creating an array item.
5226  */
5228 {
5229  size_t total = 0; // total is the full count of arguments we attempt to parse.
5230  RexxToken *terminatorToken; // the terminator token that ended a sub expression
5231 
5232  // now loop until we get a terminator. Note that COMMAs are always a terminator
5233  // token now that list expressions are possible.
5234  for (;;)
5235  {
5236  // parse off an argument expression
5237  RexxObject *subExpr = subExpression(terminators | TERM_COMMA); // jlf: here I differ from ooRexx5 which FORCES "comma is separator" in the method terminator.
5238  // We have two term stacks. The main term stack is used for expression evaluation.
5239  // the subTerm stack is used for processing expression lists like this.
5240  // NOTE that we need to use pushSubTerm here so that the required expression stack
5241  // calculation comes out right.
5242  pushSubTerm(subExpr);
5243 
5244  // now check the total. Real count will be the last
5245  // expression that requires evaluation.
5246  total++;
5247 
5248  // the next token will be our terminator. If this is not
5249  // a comma, we have more expressions to parse.
5250  terminatorToken = nextToken();
5251  if (!terminatorToken->isType(TOKEN_COMMA))
5252  {
5253  // push this token back and stop parsing
5254  previousToken();
5255  break;
5256  }
5257  }
5258 
5259  // if we only saw the single expression, then return that expression
5260  // as the result
5261  if (total == 1)
5262  {
5263  return popSubTerm();
5264  }
5265 
5266  // we have an array creation list, so create the operator type for
5267  // building the array.
5268  return (RexxObject*) new (total) RexxExpressionList(total, subTerms);
5269 }
5270 
5271 
5273  int terminators ) /* expression termination context */
5274 /******************************************************************************/
5275 /* Function: Parse off a sub- expression, stopping when one of the possible */
5276 /* set of terminator tokens is reached. The terminator token is */
5277 /* placed back on the token queue. */
5278 /******************************************************************************/
5279 {
5280  RexxObject *left; /* left term of operation */
5281  RexxObject *right; /* right term of operation */
5282  RexxToken *token; /* current working token */
5283  RexxToken *second; /* look ahead token */
5284  RexxObject *subexpression; /* final subexpression */
5285  SourceLocation location; /* token location info */
5286 
5287  /* get the left term */
5288  left = this->messageSubterm(terminators);
5289  if (left == OREF_NULL) /* end of the expression? */
5290  {
5291  return OREF_NULL; /* done processing here */
5292  }
5293  this->pushTerm(left); /* add the term to the term stack */
5294  /* add a fence item to operator stack*/
5296  token = nextToken(); /* get the next token */
5297  /* loop until end of expression */
5298  while (!this->terminator(terminators, token))
5299  {
5300  switch (token->classId)
5301  {
5302 
5303  case TOKEN_TILDE: /* have a message send operation */
5304  case TOKEN_DTILDE: /* have a double twiddle operation */
5305  left = this->popTerm(); /* get the left term from the stack */
5306  if (left == OREF_NULL) /* not there? */
5307  {
5308  /* this is an invalid expression */
5310  }
5311  /* process a message term */
5312  subexpression = this->message(left, token->classId == TOKEN_DTILDE, terminators);
5313  this->pushTerm(subexpression); /* push this back on the term stack */
5314  break;
5315 
5316  case TOKEN_SQLEFT: /* collection syntax message */
5317  left = this->popTerm(); /* get the left term from the stack */
5318  if (left == OREF_NULL) /* not there? */
5319  {
5320  /* this is an invalid expression */
5322  }
5323  /* process a message term */
5324  subexpression = this->collectionMessage(token, left, terminators);
5325  this->pushTerm(subexpression); /* push this back on the term stack */
5326  break;
5327 
5328  case TOKEN_SYMBOL: /* Symbol in the expression */
5329  case TOKEN_LITERAL: /* Literal in the expression */
5330  //case TOKEN_SOURCE_LITERAL: /* Source literal in the expression */
5331  case TOKEN_LEFT: /* start of subexpression */
5332 
5333  location = token->getLocation(); /* get the token start position */
5334  /* abuttal ends on the same line */
5335  location.setEnd(location.getLineNumber(), location.getOffset());
5336  /* This is actually an abuttal */
5337  token = new RexxToken (TOKEN_OPERATOR, OPERATOR_ABUTTAL, OREF_NULLSTRING, location);
5338  previousToken(); /* step back on the token list */
5339 
5340  case TOKEN_BLANK: /* possible blank concatenate */
5341  second = nextReal(); /* get the next token */
5342  /* blank prior to a terminator? */
5343  if (this->terminator(terminators, second))
5344  {
5345  break; /* not a real operator */
5346  }
5347  else /* have a blank operator */
5348  {
5349  previousToken(); /* push this back */
5350  }
5351  /* fall through to operator logic */
5352 
5353  case TOKEN_OPERATOR: /* have a dyadic operator */
5354  /* actually a prefix only one? */
5355  if (token->subclass == OPERATOR_BACKSLASH)
5356  {
5357  /* this is an invalid expression */
5359  }
5360  /* handle operator precedence */
5361  for (;;)
5362  {
5363  second = this->topOperator();/* get the top term */
5364  /* hit the fence term? */
5365  if (second == (RexxToken *)TheNilObject)
5366  {
5367  break; /* out of here */
5368  }
5369  /* current have higher precedence? */
5370  if (this->precedence(token) > this->precedence(second))
5371  {
5372  break; /* finished also */
5373  }
5374  right = this->popTerm(); /* get the right term */
5375  left = this->popTerm(); /* and the left term */
5376  /* not enough terms? */
5377  if (right == OREF_NULL || left == OREF_NULL)
5378  {
5379  /* this is an invalid expression */
5381  }
5382  /* create a new operation */
5383  RexxToken *op = popOperator();
5384  subexpression = (RexxObject *)new RexxBinaryOperator(op->subclass, left, right);
5385  /* push this back on the term stack */
5386  this->pushTerm(subexpression);
5387  }
5388  this->pushOperator(token); /* push this operator onto stack */
5389  right = this->messageSubterm(terminators);
5390  /* end of the expression? */
5391  if (right == OREF_NULL && token->subclass != OPERATOR_BLANK)
5392  {
5393  /* have a bad expression */
5395  }
5396  this->pushTerm(right); /* add the term to the term stack */
5397  break;
5398 
5399  case TOKEN_ASSIGNMENT:
5400  // special assignment token in a bad context. We report this as an error.
5401  /* this is an invalid expression */
5403  break;
5404 
5405  case TOKEN_COMMA: /* found a comma in the expression */
5406  /* should have been trapped as an */
5407  /* expression terminator, so this is */
5408  /* not a valid expression */
5410  break;
5411 
5412  case TOKEN_RIGHT: /* found a paren in the expression */
5414  break;
5415 
5416  case TOKEN_SQRIGHT: /* found a bracket in the expression */
5418  break;
5419 
5420  default: /* something unexpected */
5421  /* not a valid expression */
5423  break;
5424  }
5425  token = nextToken(); /* get the next token */
5426  }
5427  token= this->popOperator(); /* get top operator token */
5428  /* process pending operations */
5429  while (token != (RexxToken *)TheNilObject)
5430  {
5431  right = this->popTerm(); /* get the right term */
5432  left = this->popTerm(); /* now get the left term */
5433  /* missing any terms? */
5434  if (left == OREF_NULL || right == OREF_NULL)
5435  {
5436  /* this is an invalid expression */
5438  }
5439  /* create a new operation */
5440  subexpression = (RexxObject *)new RexxBinaryOperator(token->subclass, left, right);
5441  this->pushTerm(subexpression); /* push this back on the term stack */
5442  token = this->popOperator(); /* get top operator token */
5443  }
5444  return this->popTerm(); /* expression is top of term stack */
5445 }
5446 
5447 /*RexxArray* */ void RexxSource::argArray(
5448  RexxToken *_first, /* token starting arglist */
5449  int terminators, /* expression termination context */
5450  bool namedArgumentAllowed,
5451  RexxArray* &_argArray, // output argument: either OREF_NULL or an array
5452  RexxArray* &_namedArgArray) // output argument: either OREF_NULL or an array
5453 /******************************************************************************/
5454 /* Function: Parse off an array of argument expressions */
5455 /******************************************************************************/
5456 {
5457  size_t argCount=0; /* count of positional arguments */
5458  size_t namedArgCount=0; /* count of named arguments */
5459  //RexxArray *_argArray; /* returned array */
5460 
5461  /* scan off the argument list */
5462  /*argCount =*/ this->argList(_first, terminators, namedArgumentAllowed, /*byref*/argCount, /*byref*/namedArgCount);
5463 
5464  _argArray = new_array(argCount); /* get a new argument list */
5465  this->holdObject(_argArray); // protect
5466  /* now copy the argument pointers */
5467  while (argCount > 0)
5468  {
5469  /* in reverse order */
5470  _argArray->put(this->subTerms->pop(), argCount--);
5471  }
5472 
5473  _namedArgArray = new_array(2 * namedArgCount); /* get a new named argument list */
5474  this->holdObject(_namedArgArray); // protect
5475  /* now copy the arguments name,expression */
5476  while (namedArgCount > 0)
5477  {
5478  /* in reverse order */
5479  _namedArgArray->put(this->namedSubTerms->pop(), (2 * namedArgCount)); // expression
5480  _namedArgArray->put(this->namedSubTerms->pop(), (2 * namedArgCount) - 1); // name
5481  namedArgCount--;
5482  }
5483 
5484  //return _argArray; /* return the argument array */
5485 }
5486 
5488  RexxToken *_first, /* token starting arglist */
5489  int terminators, /* expression termination context */
5490  bool namedArgumentAllowed,
5491  size_t &positionalArgumentCount,
5492  size_t &namedArgumentCount)
5493 /******************************************************************************/
5494 /* Function: Parse off a list of argument expressions */
5495 /******************************************************************************/
5496 // jlf : keep the trailing omitted arguments !
5497 // .array~of(10,20,30,)~dimensions= --> [3] (not ok, should be [4])
5498 
5499 {
5500  RexxQueue *arglist; /* positional argument list */
5501  RexxQueue *namedArglist; /* named argument list */
5502  RexxObject *subexpr; /* current subexpression */
5503  RexxToken *token; /* current working token */
5504  //size_t realcount; /* count of real arguments */
5505  size_t total; /* total positional arguments */
5506  size_t namedTotal;
5507 
5508  arglist = this->subTerms; /* use the subterms list for the positional parameters */
5509  namedArglist = this->namedSubTerms; /* use the namedsubterms list for the named parameters */
5510 
5511  /*
5512  JLF
5513  I don't really understand how is working subTerms and namedSubTerms...
5514  I added namedSubTerms by replicating the code I saw for subTerms.
5515  And one day, I stumbled on this bug:
5516  r = myroutine(1, 2, a1:1, a2:2, a3:myroutine(10, 20, a1:10, a2:20))
5517  Error 35.900: Named argument: The name "A1" is passed more than once
5518  It's because this->namedSubTerms contains : ("A1", 1, "A2", 2) when parsing the inner call of myroutine...
5519  Seems correct because it's the same for this->subTerms which contains (1, 2) when parsing the inner call.
5520  I bypassed this bug by using a queue local to this method, but I should investigate more !
5521  */
5522  RexxQueue *localNamedArglist = new_queue();
5523  ProtectedObject p(localNamedArglist);
5524 
5525 
5526  //realcount = 0; /* no arguments yet */
5527  total = 0; // count positional arguments
5528  namedTotal = 0; // count named arguments
5529  bool namedArgument = false; // will become true when the first named argument is met
5530 
5531  /* Shortcut syntax : f{...} is equivalent to f({...}) */
5532  if (_first && _first->isSourceLiteral())
5533  {
5534  RexxObject *expr = this->addText(_first);
5535  arglist->push(expr); /* add next argument to list */
5536  positionalArgumentCount = 1;
5537  namedArgumentCount = 0;
5538  return;
5539  }
5540 
5541  /* get the first real token, which */
5542  nextReal(); /* skips any leading blanks on CALL */
5543  previousToken(); /* now put it back */
5544  /* loop until get a full terminator */
5545  for (;;)
5546  {
5547  if (!namedArgument)
5548  {
5549  // The first named argument indicates the end of the positional arguments
5550  // A named argument is a variable symbol followed by ":"
5551  size_t position = markPosition();
5552  token = nextReal();
5553  if (token->classId == TOKEN_SYMBOL) // don't test token->isVariable() here, to have a better error message
5554  {
5555  token = nextReal();
5556  if (token->classId == TOKEN_COLON) namedArgument = true;
5557  }
5558  // or ":" followed by a variable symbol
5559  if (token->classId == TOKEN_COLON)
5560  {
5561  token = nextReal();
5562  if (token->classId == TOKEN_SYMBOL) namedArgument = true; // don't test token->isVariable() here, to have a better error message
5563  }
5565 
5566  if (namedArgument && !namedArgumentAllowed) syntaxError(Error_Translation_user_defined,
5567  new_string("Named argument not supported"));
5568  }
5569 
5570  // JLF remember: for retrofit array literal, I can keep this part unchanged.
5571  // In particular, I don't try to simplify and use pushSubTerm.
5572  if (!namedArgument)
5573  {
5574  /* parse off next positional argument expression*/
5575  subexpr = this->subExpression(terminators | TERM_COMMA);
5576  arglist->push(subexpr); /* add next argument to list */
5577  this->pushTerm(subexpr); /* add the term to the term stack */
5578  total++; /* increment the total */
5579  //if (subexpr != OREF_NULL) /* real expression? */
5580  //{
5581  // realcount = total; /* update the real count */
5582  //}
5583  }
5584  else
5585  {
5586  // A named argument is a symbol followed by ":"
5587  // or ":" followed by a variable symbol
5588  token = nextReal();
5589  if (token->classId == TOKEN_COLON)
5590  {
5591  token = nextReal();
5593  new_string("Named argument: expected symbol followed by colon, or colon followed by symbol"));
5594  this->needVariable(token);
5595  if (localNamedArglist->hasItem(token->value) == TheTrueObject) syntaxError(Error_Translation_user_defined,
5596  token->value->concatToCstring("Named argument: '")->concatWithCstring(":' is passed more than once"));
5597  localNamedArglist->push(token->value); // Bypass the bug described above by using a queue local to this method.
5598  namedArglist->push(token->value); /* add argument name to list */
5599  this->pushTerm(token->value); // For a proper stack size, must count also the named parameters
5600 
5601  // The named argument expression is the variable
5602  subexpr = this->addText(token); // variable
5603  namedArglist->push(subexpr); /* add next argument to list */
5604  this->pushTerm(subexpr); // For a proper stack size, must count also the named parameters
5605  if (!this->terminator(terminators | TERM_COMMA, nextToken()))
5606  {
5607  syntaxError(Error_Translation_user_defined, new_string("Named argument: the expression after colon must be a variable only"));
5608  }
5609  }
5610  else
5611  {
5613  new_string("Named argument: expected symbol followed by colon, or colon followed by symbol"));
5614  this->needVariable(token);
5615  if (localNamedArglist->hasItem(token->value) == TheTrueObject) syntaxError(Error_Translation_user_defined,
5616  token->value->concatToCstring("Named argument: '")->concatWithCstring(":' is passed more than once"));
5617  localNamedArglist->push(token->value); // Bypass the bug described above by using a queue local to this method.
5618  namedArglist->push(token->value); /* add argument name to list */
5619  this->pushTerm(token->value); // For a proper stack size, must count also the named parameters
5620 
5621  token = nextReal();
5623  new_string("Named argument: expected symbol followed by colon, or colon followed by symbol"));
5624 
5625  /* parse off named argument expression*/
5626  RexxObject *subexpr = this->subExpression(terminators | TERM_COMMA);
5627  if (subexpr == OREF_NULL) subexpr = IntegerOne;
5628  namedArglist->push(subexpr); /* add next argument to list */
5629  this->pushTerm(subexpr); // For a proper stack size, must count also the named parameters
5630  }
5631  namedTotal++;
5632  }
5633 
5634  token = nextToken(); /* get the next token */
5635  if (token->classId != TOKEN_COMMA) /* start of next argument? */
5636  {
5637  break; /* no, all finished */
5638  }
5639  }
5640 
5641  /* not closed with expected ')'? */
5642  if (terminators & TERM_RIGHT && token->classId != TOKEN_RIGHT)
5643  {
5644  /* raise an error */
5646  }
5647 
5648  /* not closed with expected ']'? */
5649  if (terminators&TERM_SQRIGHT && token->classId != TOKEN_SQRIGHT)
5650  {
5651  /* have an unmatched bracket */
5653  }
5654 
5655  this->popNTerms(total + ((2 * namedTotal))); /* pop all items off the term stack */
5656  /* pop off any trailing omitteds */
5657  //while (total > realcount)
5658  //{
5659  // arglist->pop(); /* just pop off the dummy */
5660  // total--; /* reduce the total */
5661  //}
5662  if (total == 1 && subexpr == OREF_NULL)
5663  {
5664  // case f() : no arg, must pop this OREF_NULL
5665  // case f(,) : 2 omitted args, we don't enter here
5666  arglist->pop();
5667  total--;
5668  }
5669 
5670  if (!token->isEndOfClause())
5671  {
5672  /* Shortcut syntax : f(a1,a2,...){...} is equivalent to f(a1,a2,...,{...}) */
5673  token = nextToken();
5674  if (token && token->isSourceLiteral())
5675  {
5676  RexxObject *expr = this->addText(token);
5677  arglist->push(expr); /* add next argument to list */
5678  //realcount++; /* increment the total */
5679  total++;
5680  }
5681  else previousToken(); /* put it back */
5682  }
5683 
5684  positionalArgumentCount = total;
5685  namedArgumentCount = namedTotal;
5686 
5687  //return realcount; /* return the argument count */
5688  //return total;
5689 }
5690 
5692  RexxToken *token, /* arglist start (for error reports) */
5693  RexxToken *name, /* function name */
5694  int terminators ) /* expression termination context */
5695 /******************************************************************************/
5696 /* Function: Parse off a REXX function call */
5697 /******************************************************************************/
5698 {
5699  size_t argCount=0; /* count of function arguments */
5700  size_t namedArgCount=0;
5701  RexxExpressionFunction *_function; /* newly created function argument */
5702 
5703  saveObject((RexxObject *)name); // protect while parsing the argument list
5704 
5705  /* process the argument list */
5706  /*argCount =*/ this->argList(token, ((terminators | TERM_RIGHT) & ~TERM_SQRIGHT), true, /*byref*/argCount, /*byref*/namedArgCount);
5707 
5708  /* create a new function item */
5709  _function = new (argCount + (2 * namedArgCount)) RexxExpressionFunction(name->value, argCount, this->subTerms, namedArgCount, this->namedSubTerms, this->resolveBuiltin(name->value), name->isLiteral());
5710  /* add to table of references */
5711  this->addReference((RexxObject *)_function);
5712  removeObj((RexxObject *)name); // end of protected windoww.
5713  return (RexxObject *)_function; /* and return this to the caller */
5714 }
5715 
5716 #if 0
5717 // It works, but not activated... Since there is also the tilde-call message
5718 // I prefer to keep things simple : only one way to do function calls.
5720  RexxToken *token, /* arglist start (for error reports) */
5721  RexxObject *target, /* target term */
5722  int terminators ) /* expression termination context */
5723 /******************************************************************************/
5724 /* Function: Process an expression term of the form "target(arg,arg)" */
5725 /******************************************************************************/
5726 {
5727  size_t argCount=0; /* count of function arguments */
5728  size_t namedArgCount=0;
5729  RexxObject *_message; /* new message term */
5730 
5731  this->saveObject((RexxObject *)target); /* save target until it gets connected to message */
5732  /* process the argument list */
5733  /*argCount =*/ this->argList(token, ((terminators | TERM_RIGHT) & ~TERM_SQRIGHT), true, /*byref*/argCount, /*byref*/namedArgCount);
5734  /* create a new message item */
5735  _message = (RexxObject *)new (argCount + (2 * namedArgCount)) RexxExpressionMessage(target, (RexxString *)OREF_ROUND_BRACKETS, (RexxObject *)OREF_NULL, argCount, this->subTerms, namedArgCount, this->namedSubTerms, false);
5736  this->holdObject(_message); /* hold this here for a while */
5737  this->removeObj((RexxObject *)target); /* target is now connected to message, remove from savelist without hold */
5738  return _message; /* return the message item */
5739 }
5740 #endif
5741 
5743  RexxToken *token, /* arglist start (for error reports) */
5744  RexxObject *target, /* target term */
5745  int terminators ) /* expression termination context */
5746 /******************************************************************************/
5747 /* Function: Process an expression term of the form "target[arg,arg]" */
5748 /******************************************************************************/
5749 {
5750  size_t argCount=0; /* count of function arguments */
5751  size_t namedArgCount=0;
5752  RexxObject *_message; /* new message term */
5753 
5754  this->saveObject((RexxObject *)target); /* save target until it gets connected to message */
5755  /* process the argument list */
5756  /*argCount =*/ this->argList(token, ((terminators | TERM_SQRIGHT) & ~TERM_RIGHT), true, /*byref*/argCount, /*byref*/namedArgCount);
5757  /* create a new message item */
5758  _message = (RexxObject *)new (argCount + (2 * namedArgCount)) RexxExpressionMessage(target, (RexxString *)OREF_BRACKETS, (RexxObject *)OREF_NULL, argCount, this->subTerms, namedArgCount, this->namedSubTerms, false);
5759  this->holdObject(_message); /* hold this here for a while */
5760  this->removeObj((RexxObject *)target); /* target is now connected to message, remove from savelist without hold */
5761  return _message; /* return the message item */
5762 }
5763 
5765  int terminators, /* expression termination context */
5766  int errorcode) /* expected error code */
5767 /******************************************************************************/
5768 /* Function: Get a token, checking to see if this is a terminatore token */
5769 /******************************************************************************/
5770 {
5771  RexxToken *token = nextToken(); /* get the next token */
5772  /* this a terminator token? */
5773  if (this->terminator(terminators, token))
5774  {
5775  if (errorcode != 0) /* want an error raised? */
5776  {
5777  syntaxError(errorcode); /* report this */
5778  }
5779  return OREF_NULL; /* just return a null */
5780  }
5781  return token; /* return the token */
5782 }
5783 
5785  RexxObject *target, /* message send target */
5786  bool doubleTilde, /* class of message send */
5787  int terminators ) /* expression termination context */
5788 /******************************************************************************/
5789 /* Function: Parse a full message send expression term */
5790 /******************************************************************************/
5791 {
5792  size_t argCount; /* list of function arguments */
5793  size_t namedArgCount;
5794  RexxString *messagename = OREF_NULL; /* message name */
5795  bool messagenameProvided = true;
5796  RexxObject *super; /* super class target */
5797  RexxToken *token; /* current working token */
5798  RexxExpressionMessage *_message; /* new message term */
5799 
5800  super = OREF_NULL; /* default no super class */
5801  argCount = 0; /* and no arguments */
5802  namedArgCount = 0;
5803  this->saveObject(target); /* save target until it gets connected to message */
5804 
5805  /* add the term to the term stack so that the calculations */
5806  /* include this in the processing. */
5807  this->pushTerm(target);
5808  /* get the next token */
5809  token = this->getToken(terminators, 0 /*Error_Symbol_or_string_tilde*/);
5810  /* unexpected type? */
5811  if (token == OREF_NULL || token->classId == TOKEN_COLON || token->classId == TOKEN_LEFT || token->isSourceLiteral())
5812  {
5813  // no explicit message name, this is the implicit tilde-call
5814  messagename = (RexxString *)OREF_TILDE_ROUND_BRACKETS;
5815  messagenameProvided = false;
5816  if (token != OREF_NULL) previousToken();
5817  }
5818  else if (token->isSymbolOrLiteral())
5819  {
5820  messagename = token->value; /* get the message name */
5821  }
5822  else
5823  {
5824  /* error! */
5826  }
5827  /* get the next token */
5828  token = this->getToken(terminators, 0);
5829  if (token != OREF_NULL)
5830  { /* not reached the clause end? */
5831  /* have a super class? */
5832  if (token->classId == TOKEN_COLON)
5833  {
5834  /* get the next token */
5835  token = this->getToken(terminators, Error_Symbol_expected_colon);
5836  /* not a variable symbol? */
5837  if (!token->isVariable() && token->subclass != SYMBOL_DOTSYMBOL)
5838  {
5839  /* have an error */
5841  }
5842  super = this->addText(token); /* get the variable retriever */
5843  /* get the next token */
5844  token = this->getToken(terminators, 0);
5845  }
5846  }
5847  if (!messagenameProvided)
5848  {
5849  // Message name or argument list is mandatory
5850  if (token == OREF_NULL || (token->classId != TOKEN_LEFT && !token->isSourceLiteral()))
5851  {
5853  }
5854  }
5855  if (token != OREF_NULL)
5856  { /* not reached the clause end? */
5857  if (token->classId == TOKEN_LEFT || token->isSourceLiteral()) /* have an argument list? */
5858  {
5859  /* process the argument list */
5860  /*argCount =*/ this->argList(token, ((terminators | TERM_RIGHT) & ~TERM_SQRIGHT), true, /*byref*/argCount, /*byref*/namedArgCount);
5861  }
5862  else
5863  {
5864  previousToken(); /* something else, step back */
5865  }
5866  }
5867 
5868  this->popTerm(); /* it is now safe to pop the message target */
5869  /* create a message send node */
5870  _message = new (argCount + (2 * namedArgCount)) RexxExpressionMessage(target, messagename, super, argCount, this->subTerms, namedArgCount, this->namedSubTerms, doubleTilde);
5871  /* protect for a bit */
5872  this->holdObject((RexxObject *)_message);
5873  this->removeObj(target); /* target is now connected to message, remove from savelist without hold */
5874  return(RexxObject *)_message; /* return the message item */
5875 }
5876 
5877 
5878 /**
5879  * Parse off a single variable symbol or a message term that
5880  * can be used for an assignment.
5881  *
5882  * NOTE: If this is a message term, then the message term
5883  * will be configured as an assignment term.
5884  *
5885  * @return The object for an assignment target, or OREF_NULL if something
5886  * other than a variable or a message term was found. On return,
5887  * the clause position pointer will either be unchanged or
5888  * positioned at the next token of the clause.
5889  */
5891 {
5892  // try for a message term first. If not successful, see if the
5893  // next token is a variable symbol.
5894  RexxObject *result = messageTerm();
5895  if (result == OREF_NULL)
5896  {
5897  RexxToken *_first = nextReal();
5898  if (_first->isSymbol())
5899  {
5900  // ok, add the variable to the processing list
5901  this->needVariable(_first);
5902  result = this->addText(_first);
5903  }
5904  else
5905  {
5906  previousToken(); // just push back on for the caller to sort out
5907  }
5908  }
5909  else
5910  {
5911  // we need to convert this into an assignment message.
5912  ((RexxExpressionMessage *)result)->makeAssignment(this);
5913  }
5914  return result;
5915 }
5916 
5917 
5918 
5920 /******************************************************************************/
5921 /* Function: Parse off an instruction leading message term element */
5922 /******************************************************************************/
5923 {
5924  RexxToken *token; /* current working token */
5925  RexxObject *term; /* working term */
5926  RexxObject *start; /* starting term */
5927  int classId; /* token class */
5928 
5929  size_t mark = markPosition(); // save the current position so we can reset cleanly
5930 
5931  // jlf: add TERM_COMMA to support ",;" which is evaluated as an array of 2 elements
5932  start = this->subTerm(TERM_EOC | TERM_COMMA); /* get the first term of instruction */
5933  this->holdObject(start); /* save the starting term */
5934  term = OREF_NULL; /* default to no term */
5935  token = nextToken(); /* get the next token */
5936  classId = token->classId; /* get the token class */
5937  /* while cascading message sends */
5938  while (classId == TOKEN_TILDE || classId == TOKEN_DTILDE || classId == TOKEN_SQLEFT )
5939  {
5940  if (classId == TOKEN_SQLEFT) /* left bracket form? */
5941  {
5942  term = this->collectionMessage(token, start, TERM_EOC);
5943  }
5944  else
5945  {
5946  /* process a message term */
5947  term = this->message(start, classId == TOKEN_DTILDE, TERM_EOC);
5948  }
5949  start = term; /* set for the next pass */
5950  token = nextToken(); /* get the next token */
5951  classId = token->classId; /* get the token class */
5952  }
5953  previousToken(); /* push this term back */
5954  // if this was not a valid message term, reset the position to the beginning
5955  if (term == OREF_NULL)
5956  {
5957  resetPosition(mark); // reset back to the entry conditions
5958  }
5959  /* return the message term (returns */
5960  return term; /* OREF_NULL if not a message term) */
5961 }
5962 
5964  int terminators ) /* expression termination context */
5965 /******************************************************************************/
5966 /* Function: Parse off a message subterm within an expression */
5967 /******************************************************************************/
5968 {
5969  RexxToken *token; /* current working token */
5970  RexxObject *term = OREF_NULL; /* working term */
5971  int classId; /* token class */
5972 
5973  token = nextToken(); /* get the next token */
5974  /* this the expression end? */
5975  if (this->terminator(terminators, token))
5976  {
5977  return OREF_NULL; /* nothing to do here */
5978  }
5979  /* have potential prefix operator? */
5980  if (token->classId == TOKEN_OPERATOR)
5981  {
5982 
5983  /* handle prefix operators as terms */
5984  switch (token->subclass)
5985  {
5986 
5987  case OPERATOR_PLUS: /* prefix plus */
5988  case OPERATOR_SUBTRACT: /* prefix minus */
5989  case OPERATOR_BACKSLASH: /* prefix backslash */
5990  /* handle following term */
5991  term = this->messageSubterm(terminators);
5992  if (term == OREF_NULL) /* nothing found? */
5993  {
5994  /* this is an error */
5996  }
5997  /* create the new operator term */
5998  term = (RexxObject *)new RexxUnaryOperator(token->subclass, term);
5999  break;
6000 
6001  default: /* other operators not allowed here */
6002  /* this is an error */
6004  }
6005  }
6006  /* non-prefix operator code */
6007  else
6008  {
6009  previousToken(); /* put back the first token */
6010  term = this->subTerm(TERM_EOC); /* get the first term of instruction */
6011  this->holdObject(term); /* save the starting term */
6012  token = nextToken(); /* get the next token */
6013  classId = token->classId; /* get the token class */
6014  /* while cascading message sends */
6015  while (classId == TOKEN_TILDE || classId == TOKEN_DTILDE || classId == TOKEN_SQLEFT )
6016  {
6017  if (classId == TOKEN_SQLEFT) /* left bracket form? */
6018  {
6019  term = this->collectionMessage(token, term, TERM_EOC);
6020  }
6021  else
6022  {
6023  /* process a message term */
6024  term = this->message(term, classId == TOKEN_DTILDE, TERM_EOC);
6025  }
6026  token = nextToken(); /* get the next token */
6027  classId = token->classId; /* get the token class */
6028  }
6029  previousToken(); /* push this term back */
6030  }
6031  /* return the message term (returns */
6032  return term; /* OREF_NULL if not a message term) */
6033 }
6034 
6036  int terminators ) /* expression termination context */
6037 /******************************************************************************/
6038 /* Function: Parse off a subterm of an expression, from simple ones like */
6039 /* variable names, to more complex such as message sends */
6040 /******************************************************************************/
6041 {
6042  RexxToken *token; /* current token being processed */
6043  RexxObject *term = OREF_NULL; /* parsed out term */
6044  RexxToken *second; /* second token of term */
6045 
6046  token = nextToken(); /* get the next token */
6047  /* this the expression end? */
6048  if (this->terminator(terminators, token))
6049  {
6050  return OREF_NULL; /* nothing to do here */
6051  }
6052 
6053  switch (token->classId)
6054  {
6055 
6056  case TOKEN_LEFT: /* have a left parentheses */
6057  /* get the subexpression */
6058  //term = this->subExpression(((terminators | TERM_RIGHT) & ~TERM_SQRIGHT));
6059 
6060  // parse off the parenthetical. This might not return anything if there
6061  // is nothing in the parens. This is an error. Also, in this context,
6062  // we are back in a mode where the array-creation syntax is allowed.
6063  term = fullSubExpression(TERM_RIGHT);
6064  if (term == OREF_NULL) /* nothing found? */
6065  {
6066  /* this is an error */
6068  }
6069  second = nextToken(); /* get the terminator token */
6070  /* not terminated by a right paren? */
6071  if (second->classId != TOKEN_RIGHT)
6072  {
6073  /* this is an error */
6075  }
6076  break;
6077 
6078  case TOKEN_SYMBOL: /* Symbol in the expression */
6079  case TOKEN_LITERAL: /* Literal in the expression */
6080  case TOKEN_SOURCE_LITERAL: /* Source literal in the expression */
6081  second = nextToken(); /* get the next token */
6082  /* have a function call? */
6083  if (second->classId == TOKEN_LEFT || second->isSourceLiteral())
6084  {
6085  /* process the function call */
6086  if (token->classId == TOKEN_SOURCE_LITERAL)
6087  {
6088 #if 0
6089  // It works but not activated... Tilde-call is more general.
6090  term = this->addText(token);
6091  term = this->functionCallMessage(second, term, terminators);
6092 #else
6093  // Function-call not activated. Just return the source literal.
6094  previousToken(); /* push the token back */
6095  term = this->addText(token); /* variable or literal access */
6096 #endif
6097  }
6098  else
6099  {
6100  term = this->function(second, token, terminators);
6101  }
6102  }
6103  else
6104  {
6105  previousToken(); /* push the token back */
6106  term = this->addText(token); /* variable or literal access */
6107  }
6108  break;
6109 
6110  case TOKEN_RIGHT: /* have a right parentheses */
6111  /* this is an error here */
6113  break;
6114 
6115  case TOKEN_COMMA: /* have a comma */
6116  /* this is an error here */
6118  break;
6119 
6120  case TOKEN_SQRIGHT: /* have a right square bracket */
6121  /* this is an error here */
6123  break;
6124 
6125  case TOKEN_OPERATOR: /* operator token */
6126  switch (token->subclass)
6127  { /* handle prefix operators as terms */
6128 
6129  case OPERATOR_PLUS: /* prefix plus */
6130  case OPERATOR_SUBTRACT: /* prefix minus */
6131  case OPERATOR_BACKSLASH: /* prefix backslash */
6132  previousToken(); /* put the token back */
6133  return OREF_NULL; /* just return null (processed later)*/
6134 
6135  default: /* other operators not allowed here */
6136  /* this is an error */
6138  }
6139  break;
6140 
6141  default: /* unknown thing in expression */
6142  /* this is an error */
6144  }
6145  return term; /* return this term */
6146 }
6147 
6149  RexxObject *term ) /* term to push */
6150 /******************************************************************************/
6151 /* Function: Push a term onto the expression term stack */
6152 /******************************************************************************/
6153 {
6154  this->terms->push(term); /* push the term on the stack */
6155  this->currentstack++; /* step the stack depth */
6156  /* new "high water" mark? */
6157  if (this->currentstack > this->maxstack)
6158  {
6159  /* make it the highest point */
6160  this->maxstack = this->currentstack;
6161  }
6162 }
6163 
6165 /******************************************************************************/
6166 /* Function: Pop a term off of the expression term stack */
6167 /******************************************************************************/
6168 {
6169  RexxObject *term; /* returned term */
6170 
6171  this->currentstack--; /* reduce the size count */
6172  term = this->terms->pop(); /* pop the term */
6173  this->holdObject(term); /* give it a little protection */
6174  return term; /* and return it */
6175 }
6176 
6177 /**
6178  * Push a term on to the expression sub term stack. The
6179  * subterms normally contribute to the total required stack
6180  * size, so make sure we account for these when calculating the
6181  * total required stack size. Only use this method of pushing
6182  * the term when the max stack size is affected.
6183  *
6184  * @param term The term object.
6185  */
6187 {
6188  // push the term on to the stack.
6189  subTerms->push(term);
6190 
6191  // we keep track of how large the term stack gets during parsing. This
6192  // tells us how much stack space we need to allocate at run time.
6193  currentstack++;
6194  // maxStack = Numerics::maxVal(currentStack, maxStack);
6196 }
6197 
6198 
6199 /**
6200  * Pop a term off of the expression sub term stack.
6201  *
6202  * @return The popped object.
6203  */
6205 {
6206  // reduce the stack count
6207  currentstack--;
6208  // pop the object off of the stack and give it some short-term
6209  // GC protection.
6210  RexxObject *term = subTerms->pop();
6211  holdObject(term);
6212  return term;
6213 }
6214 
6215 
6217  size_t count ) /* number of terms to pop */
6218 /******************************************************************************/
6219 /* Function: Pop multiple terms off of the operator stack */
6220 /******************************************************************************/
6221 {
6222  RexxObject *result = OREF_NULL; /* final popped element */
6223 
6224  this->currentstack -= count; /* reduce the size count */
6225  while (count--) /* while more to remove */
6226  {
6227  result = this->terms->pop(); /* pop the next item */
6228  }
6229  this->holdObject(result); /* protect this a little */
6230  return result; /* and return it */
6231 }
6232 
6234 /******************************************************************************/
6235 /* Function: Validate placement of an EXPOSE instruction. The EXPOSE must */
6236 /* be the first instruction and this must not be an interpret */
6237 /* invocation. NOTE: labels are not allowed preceeding, as that */
6238 /* will give a target for SIGNAL or CALL that will result in an */
6239 /* invalid EXPOSE execution. */
6240 /******************************************************************************/
6241 {
6242  if (this->flags&_interpret) /* is this an interpret? */
6243  {
6244  /* give the interpret error */
6246  }
6247  /* not the first instruction? */
6248  if (this->last->getType() != KEYWORD_FIRST)
6249  {
6250  /* general placement error */
6252  }
6253 }
6254 
6256  RexxString *string) /* target string */
6257 /******************************************************************************/
6258 /* Function: Break up a string into an array of words for parsing and */
6259 /* interpretation. */
6260 /******************************************************************************/
6261 {
6262  RexxQueue *wordlist; /* created list of words */
6263  RexxArray *wordarray; /* array version of the list */
6264  RexxString *word; /* current word */
6265  size_t count; /* count of words */
6266  size_t i; /* loop counter */
6267 
6268  wordlist = this->subTerms; /* use the subterms list */
6269  /* get the first word */
6270  word = ((RexxString *)(string->word(IntegerOne)))->upper();
6271  word = this->commonString(word); /* get the common version of this */
6272  wordlist->push(word); /* add to the word list */
6273  count = 1; /* one word so far */
6274  /* while still more words */
6275  for (i = 3, word = (RexxString *)(string->word(IntegerTwo)); word->getLength() != 0; i++)
6276  {
6277  count++; /* have another word */
6278  word = this->commonString(word); /* get the common version of this */
6279  wordlist->push(word); /* add this word to the list */
6280  /* get the next word */
6281  word = (RexxString *)string->word(new_integer(i));
6282  }
6283  wordarray = new_array(count); /* get an array return value */
6284  while (count > 0) /* while more words */
6285  {
6286  /* copy into the array */
6287  wordarray->put(wordlist->pop(), count--);
6288  }
6289  return wordarray; /* return as an array */
6290 }
6291 
6293 /******************************************************************************/
6294 /* Function: Free up all of the parsing elements because of an error */
6295 /******************************************************************************/
6296 {
6297  this->cleanup(); /* do needed cleanup */
6298 }
6299 
6300 void RexxSource::error(int errorcode)
6301 /******************************************************************************/
6302 /* Function: Raise an error caused by source translation problems. */
6303 /******************************************************************************/
6304 {
6305  this->errorCleanup(); /* release any saved objects */
6306  /* pass on the exception info */
6308 }
6309 
6310 void RexxSource::error(int errorcode, SourceLocation &location, RexxArray *subs)
6311 /******************************************************************************/
6312 /* Function: Raise an error caused by source translation problems. */
6313 /******************************************************************************/
6314 {
6315  this->errorCleanup(); /* release any saved objects */
6316  clauseLocation = location; // set the error location
6317  /* pass on the exception info */
6319 }
6320 
6322  int errorcode, /* error to raise */
6323  RexxInstruction *_instruction) /* instruction for the line number */
6324 /******************************************************************************/
6325 /* Function: Raise an error where one of the error message substitutions is */
6326 /* the line number of another instruction object */
6327 /******************************************************************************/
6328 {
6329  this->errorCleanup(); /* release any saved objects */
6330  /* pass on the exception info */
6332 }
6333 
6335  int errorcode, /* error to raise */
6336  SourceLocation token_location ) /* token location for description */
6337 /******************************************************************************/
6338 /* Function: Raise an error, displaying the location of a token associated */
6339 /* with the error. */
6340 /******************************************************************************/
6341 {
6342  this->errorCleanup(); /* release any saved objects */
6343  /* pass on the exception info */
6345 }
6346 
6348  int errorcode, /* error to raise */
6349  RexxToken *token ) /* token value for description */
6350 /******************************************************************************/
6351 /* Function: Raise an error, displaying the value of a token in the error */
6352 /* message. */
6353 /******************************************************************************/
6354 {
6355  RexxString *value = token->value; /* get the token value */
6356  if (value == OREF_NULL)
6357  {
6358  switch (token->classId)
6359  {
6360 
6361  case TOKEN_BLANK: /* blank operator */
6362  value = new_string(" ", 1); /* use a blank */
6363  break;
6364 
6365  case TOKEN_EOC: /* source terminator */
6366  value = new_string(";", 1); /* use a semicolon */
6367  break;
6368 
6369  case TOKEN_COMMA: /* comma */
6370  value = new_string(",", 1); /* display a comma */
6371  break;
6372 
6373  case TOKEN_LEFT: /* left parentheses */
6374  value = new_string("(", 1); /* display that */
6375  break;
6376 
6377  case TOKEN_RIGHT: /* right parentheses */
6378  value = new_string(")", 1); /* display that */
6379  break;
6380 
6381  case TOKEN_SQLEFT: /* left square bracket */
6382  value = new_string("[", 1); /* display that */
6383  break;
6384 
6385  case TOKEN_SQRIGHT: /* right square bracket */
6386  value = new_string("]", 1); /* display that */
6387  break;
6388 
6389  case TOKEN_COLON: /* colon */
6390  value = new_string(":", 1); /* display that */
6391  break;
6392 
6393  case TOKEN_TILDE: /* twiddle operator */
6394  value = new_string("~", 1); /* display that */
6395  break;
6396 
6397  case TOKEN_DTILDE: /* double twiddle operator */
6398  value = new_string("~~", 2); /* display that */
6399  break;
6400 
6401  case TOKEN_DCOLON: /* double colon operator */
6402  value = new_string("::", 2); /* display that */
6403  break;
6404 
6405  default: /* ????? token */
6406  /* just use a null string */
6407  value = (RexxString *)OREF_NULLSTRING;
6408  break;
6409  }
6410  }
6411  else if (token->getLocation().isLimitedTrace())
6412  { /* multi-line value, display only the first line*/
6413  const char *string = value->getStringData();
6414  const char *newline = strchr(string, '\n');
6415  if (newline) value = new_string(string, newline - string);
6416  this->clauseLocation.setLimitedTrace(true);
6417  }
6418  this->errorCleanup(); /* release any saved objects */
6419  /* pass on the exception info */
6421 }
6422 
6424  int errorcode, /* error to raise */
6425  RexxObject *value ) /* value for description */
6426 /******************************************************************************/
6427 /* Function: Issue an error message with a single substitution parameter. */
6428 /******************************************************************************/
6429 {
6430  this->errorCleanup(); /* release any saved objects */
6431  /* pass on the exception info */
6433 }
6434 
6436  int errorcode, /* error to raise */
6437  RexxObject *value1, /* first value for description */
6438  RexxObject *value2 ) /* second value for description */
6439 /******************************************************************************/
6440 /* Function: Issue an error message with two substitution parameters. */
6441 /******************************************************************************/
6442 {
6443  this->errorCleanup(); /* release any saved objects */
6444  /* pass on the exception info */
6446 }
6447 
6449  int errorcode, /* error to raise */
6450  RexxObject *value1, /* first value for description */
6451  RexxObject *value2, /* second value for description */
6452  RexxObject *value3 ) /* third value for description */
6453 /****************************************************************************/
6454 /* Function: Issue an error message with three substitution parameters. */
6455 /****************************************************************************/
6456 {
6457  this->errorCleanup(); /* release any saved objects */
6458  /* pass on the exception info */
6459  ActivityManager::currentActivity->raiseException(errorcode, OREF_NULL, new_array(value1, value2, value3), OREF_NULL);
6460 }
6461 
6463  RexxInstruction *_instruction ) /* unclosed control instruction */
6464 /******************************************************************************/
6465 /* Function: Raise an error for an unclosed block instruction. */
6466 /******************************************************************************/
6467 {
6468  // get the instruction location and set as the current error location
6469  clauseLocation = this->last->getLocation();
6470 
6471  switch (_instruction->getType())
6472  { /* issue proper message type */
6473  case KEYWORD_DO: /* incomplete DO */
6474  /* raise an error */
6475  syntaxError(Error_Incomplete_do_do, _instruction);
6476  break;
6477  case KEYWORD_LOOP: /* incomplete LOOP */
6478  /* raise an error */
6479  syntaxError(Error_Incomplete_do_loop, _instruction);
6480  break;
6481 
6482  case KEYWORD_SELECT: /* incomplete SELECT */
6483  syntaxError(Error_Incomplete_do_select, _instruction);
6484  break;
6485 
6486  case KEYWORD_OTHERWISE: /* incomplete SELECT */
6488  break;
6489 
6490  case KEYWORD_IF: /* incomplete IF */
6491  case KEYWORD_IFTHEN: /* incomplete IF */
6492  case KEYWORD_WHENTHEN: /* incomplete IF */
6493  syntaxError(Error_Incomplete_do_then, _instruction);
6494  break;
6495 
6496  case KEYWORD_ELSE: /* incomplete ELSE */
6497  syntaxError(Error_Incomplete_do_else, _instruction);
6498  break;
6499  }
6500 }
6501 
6502 void *RexxSource::operator new (size_t size)
6503 /******************************************************************************/
6504 /* Function: Create a new translator object from an array */
6505 /******************************************************************************/
6506 {
6507  /* Get new object */
6508  return new_object(sizeof(RexxSource), T_RexxSource);
6509 }
6510 
6511 
6513  size_t size, /* Object size */
6514  RexxBehaviour *_behaviour, /* Object's behaviour */
6515  int type ) /* Type of instruction */
6516 /******************************************************************************/
6517 /* Function: Create a "raw" translator instruction object */
6518 /******************************************************************************/
6519 {
6520  RexxObject *newObject = new_object(size); /* Get new object */
6521  newObject->setBehaviour(_behaviour); /* Give new object its behaviour */
6522  /* do common initialization */
6523  new ((void *)newObject) RexxInstruction (this->clause, type);
6524  /* now protect this */
6525  OrefSet(this, this->currentInstruction, (RexxInstruction *)newObject);
6526  return (RexxInstruction *)newObject; /* return the new object */
6527 }
6528 
6529 /**
6530  * Parse a trace setting value into a decoded setting
6531  * and the RexxActivation debug flag set to allow
6532  * new trace settings to be processed more quickly.
6533  *
6534  * @param value The string source of the trace setting.
6535  * @param newSetting The returned setting in binary form.
6536  * @param debugFlags The debug flag representation of the trace setting.
6537  */
6538 bool RexxSource::parseTraceSetting(RexxString *value, size_t &newSetting, size_t &debugFlags, char &badOption)
6539 {
6540  size_t setting = TRACE_IGNORE; /* don't change trace setting yet */
6541  size_t debug = DEBUG_IGNORE; /* and the default debug change */
6542 
6543  size_t length = value->getLength(); /* get the string length */
6544  /* null string? */
6545  if (length == 0)
6546  {
6547  setting = TRACE_NORMAL; /* use default trace setting */
6548  debug = DEBUG_OFF; /* turn off debug mode */
6549  }
6550  else
6551  {
6552  /* start at the beginning */
6553  /* while more length to process */
6554  /* step one each character */
6555  for (size_t _position = 0; _position < length; _position++)
6556  {
6557 
6558  /* process the next character */
6559  switch (value->getChar(_position))
6560  {
6561 
6562  case '?': /* debug toggle character */
6563  /* already toggling? */
6564  if (debug == DEBUG_TOGGLE)
6565  {
6566  debug = DEBUG_IGNORE; /* this is back to no change at all */
6567  }
6568  else
6569  {
6570  debug = DEBUG_TOGGLE; /* need to toggle the debug mode */
6571  }
6572  continue; /* go loop again */
6573 
6574  case 'a': /* TRACE ALL */
6575  case 'A':
6576  setting = TRACE_ALL;
6577  break;
6578 
6579  case 'c': /* TRACE COMMANDS */
6580  case 'C':
6581  setting = TRACE_COMMANDS;
6582  break;
6583 
6584  case 'l': /* TRACE LABELS */
6585  case 'L':
6586  setting = TRACE_LABELS;
6587  break;
6588 
6589  case 'e': /* TRACE ERRORS */
6590  case 'E':
6591  setting = TRACE_ERRORS;
6592  break;
6593 
6594  case 'f': /* TRACE FAILURES */
6595  case 'F':
6596  setting = TRACE_FAILURES;
6597  break;
6598 
6599  case 'n': /* TRACE NORMAL */
6600  case 'N':
6601  setting = TRACE_NORMAL;
6602  break;
6603 
6604  case 'o': /* TRACE OFF */
6605  case 'O':
6606  setting = TRACE_OFF;
6607  break;
6608 
6609  case 'r': /* TRACE RESULTS */
6610  case 'R':
6611  setting = TRACE_RESULTS;
6612  break;
6613 
6614  case 'i': /* TRACE INTERMEDIATES */
6615  case 'I':
6616  setting = TRACE_INTERMEDIATES;
6617  break;
6618 
6619  default: /* unknown trace setting */
6620  // each context handles it's own error reporting, so give back the
6621  // information needed for the message.
6622  badOption = value->getChar(_position);
6623  return false;
6624  break;
6625  }
6626  break; /* non-prefix char found */
6627  }
6628  }
6629  // return the merged setting
6630  newSetting = setting | debug;
6631  // create the activation-specific flags
6632  debugFlags = RexxActivation::processTraceSetting(newSetting);
6633  return true;
6634 }
6635 
6636 
6637 /**
6638  * Format an encoded trace setting back into human readable form.
6639  *
6640  * @param setting The source setting.
6641  *
6642  * @return The string representation of the trace setting.
6643  */
6645 {
6646  char setting[3]; /* returned trace setting */
6647  setting[0] = '\0'; /* start with a null string */
6648  /* debug mode? */
6649  if (source & DEBUG_ON)
6650  {
6651  setting[0] = '?'; /* add the question mark */
6652  /* add current trace option */
6653  setting[1] = (char)source&TRACE_SETTING_MASK;
6654  /* create a string form */
6655  return new_string(setting, 2);
6656  }
6657  else /* no debug prefix */
6658  {
6659  /* add current trace option */
6660  setting[0] = (char)source&TRACE_SETTING_MASK;
6661  /* create a string form */
6662  return new_string(setting, 1);
6663  }
6664 }
6665 
6667  int type ) /* type of instruction */
6668 /****************************************************************************/
6669 /* Function: Process a variable list for PROCEDURE, DROP, UPPER and USE */
6670 /****************************************************************************/
6671 {
6672  RexxToken *token; /* current working token */
6673  int list_count; /* count of variables in list */
6674  RexxObject *retriever; /* variable retriever object */
6675 
6676  list_count = 0; /* no variables yet */
6677  token = nextReal(); /* get the first variable */
6678 
6679  /* while not at the end of the clause*/
6680  while (!token->isEndOfClause())
6681  {
6682  /* have a variable name? */
6683  if (token->isSymbol())
6684  {
6685  /* non-variable symbol? */
6686  if (token->subclass == SYMBOL_CONSTANT)
6687  {
6688  /* report the error */
6690  }
6691  else if (token->subclass == SYMBOL_DUMMY)
6692  {
6693  /* report the error */
6695  }
6696  retriever = this->addText(token);/* get a retriever for this */
6697  this->subTerms->push(retriever); /* add to the variable list */
6698  if (type == KEYWORD_EXPOSE) /* this an expose operation? */
6699  {
6700  this->expose(token->value); /* add to the expose list too */
6701  }
6702  list_count++; /* record the variable */
6703  }
6704  /* have a variable reference */
6705  else if (token->classId == TOKEN_LEFT)
6706  {
6707  list_count++; /* record the variable */
6708  token = nextReal(); /* get the next token */
6709  /* not a symbol? */
6710  if (!token->isSymbol())
6711  {
6712  /* must be a symbol here */
6714  }
6715  /* non-variable symbol? */
6716  if (token->subclass == SYMBOL_CONSTANT)
6717  {
6718  /* report the error */
6720  }
6721  else if (token->subclass == SYMBOL_DUMMY)
6722  {
6723  /* report the error */
6725  }
6726 
6727  retriever = this->addText(token);/* get a retriever for this */
6728  /* make this an indirect reference */
6729  retriever = (RexxObject *)new RexxVariableReference((RexxVariableBase *)retriever);
6730  this->subTerms->queue(retriever);/* add to the variable list */
6731  this->currentstack++; /* account for the varlists */
6732 
6733  token = nextReal(); /* get the next token */
6734  if (token->isEndOfClause()) /* nothing following? */
6735  {
6736  /* report the missing paren */
6738  }
6739  /* must be a right paren here */
6740  else if (token->classId != TOKEN_RIGHT)
6741  {
6742  /* this is an error */
6744  }
6745  }
6746  /* something bad.... */
6747  else
6748  { /* this is invalid */
6749  if (type == KEYWORD_DROP) /* DROP form? */
6750  {
6751  /* give appropriate message */
6753  }
6754  else if (type == KEYWORD_UPPER) /* UPPER form? */
6755  {
6756  /* give appropriate message */
6758  }
6759  else /* else give message for EXPOSEs */
6760  {
6762  }
6763  }
6764  token = nextReal(); /* get the next variable */
6765  }
6766  if (list_count == 0)
6767  { /* no variables? */
6768  if (type == KEYWORD_DROP) /* DROP form? */
6769  {
6770  /* give appropriate message */
6772  }
6773  else if (type == KEYWORD_UPPER) /* UPPER form? */
6774  {
6775  /* give appropriate message */
6777  }
6778  else /* else give message for EXPOSEs */
6779  {
6781  }
6782  }
6783  return list_count; /* return the count */
6784 }
6785 
6787  int *condition_type, /* type of condition */
6788  int error_message ) /* extra "stuff" error message */
6789 /******************************************************************************/
6790 /* Function: Allow for WHILE or UNTIL keywords following some other looping */
6791 /* construct. This returns SUBKEY_WHILE or SUBKEY_UNTIL to flag */
6792 /* the caller that a conditional has been used. */
6793 /******************************************************************************/
6794 {
6795  RexxToken *token; /* current working token */
6796  int _keyword; /* keyword of parsed conditional */
6797  RexxObject *_condition; /* parsed out condition */
6798 
6799  _condition = OREF_NULL; /* default to no condition */
6800  _keyword = 0; /* no conditional yet */
6801  token = nextReal(); /* get the terminator token */
6802 
6803  /* real end of instruction? */
6804  if (!token->isEndOfClause())
6805  {
6806  /* may have WHILE/UNTIL */
6807  if (token->isSymbol())
6808  {
6809  /* process the symbol */
6810  switch (this->subKeyword(token) )
6811  {
6812 
6813  case SUBKEY_WHILE: /* DO WHILE exprw */
6814  refineSubclass(token, IS_SUBKEY);
6815  /* get next subexpression */
6816  _condition = this->parseLogical(OREF_NULL, TERM_COND);
6817  if (_condition == OREF_NULL) /* nothing really there? */
6818  {
6819  /* another invalid DO */
6821  }
6822  token = nextToken(); /* get the terminator token */
6823  /* must be end of instruction */
6824  if (!token->isEndOfClause())
6825  {
6827  }
6828  _keyword = SUBKEY_WHILE; /* this is the WHILE form */
6829  break;
6830 
6831  case SUBKEY_UNTIL: /* DO UNTIL expru */
6832  refineSubclass(token, IS_SUBKEY);
6833  /* get next subexpression */
6834  /* get next subexpression */
6835  _condition = this->parseLogical(OREF_NULL, TERM_COND);
6836 
6837  if (_condition == OREF_NULL) /* nothing really there? */
6838  {
6839  /* another invalid DO */
6841  }
6842  token = nextToken(); /* get the terminator token */
6843  /* must be end of instruction */
6844  if (!token->isEndOfClause())
6845  {
6847  }
6848  _keyword = SUBKEY_UNTIL; /* this is the UNTIL form */
6849  break;
6850 
6851  default: /* nothing else is valid here! */
6852  /* raise an error */
6853  syntaxError(error_message, token);
6854  break;
6855  }
6856  }
6857  }
6858  if (condition_type != NULL) /* need the condition type? */
6859  {
6860  *condition_type = _keyword; /* set the keyword */
6861  }
6862  return _condition; /* return the condition expression */
6863 }
6864 
6865 
6866 /**
6867  * Parse off a "logical list expression", consisting of a
6868  * list of conditionals separated by commas.
6869  *
6870  * @param terminators
6871  * The set of terminators for this logical context.
6872  *
6873  * @return OREF_NULL if no expressions is found, a single expression
6874  * element if a single expression is located, and a complex
6875  * logical expression operator for a list of expressions.
6876  */
6878 {
6879  size_t count;
6880  size_t namedCount; // named arguments not allowed, will be always zero
6881  argList(_first, terminators, false, /*byref*/count, /*byref*/namedCount);
6882  // arglist has swallowed the terminator token, so we need to back up one.
6883  previousToken();
6884  // let the caller deal with completely missing expressions
6885  if (count == 0)
6886  {
6887  return OREF_NULL;
6888  }
6889 
6890  // just a single item (common)? Just pop the top item and return it.
6891  if (count == 1)
6892  {
6893  return subTerms->pop();
6894  }
6895 
6896  /* create a new function item */
6897  return (RexxObject *)new (count) RexxExpressionLogical(this, count, this->subTerms);
6898 }
6899 
6900 
6901 /**
6902  * Load a ::REQUIRES directive when the source file is first
6903  * invoked.
6904  *
6905  * @param target The name of the ::REQUIRES
6906  * @param instruction
6907  * The directive instruction being processed.
6908  */
6910 {
6911  // we need the instance this is associated with
6912  InterpreterInstance *instance = activity->getInstance();
6913 
6914  // get a fully resolved name for this....we might locate this under either name, but the
6915  // fully resolved name is generated from this source file context.
6916  RexxString *fullName = resolveProgramName(activity, target);
6917  ProtectedObject p(fullName);
6918 
6919  // if we've already loaded this in this instance, just return it.
6920  PackageClass *packageInstance = instance->loadRequires(activity, target, fullName);
6921 
6922  if (packageInstance == OREF_NULL) /* couldn't create this? */
6923  {
6924  /* report an error */
6926  }
6927  // add this to the source context
6928  addPackage(packageInstance);
6929  return packageInstance;
6930 }
6931 
6932 
6933 /**
6934  * Load a ::REQUIRES directive from an provided source target
6935  *
6936  * @param target The name of the ::REQUIRES
6937  */
6939 {
6940  // we need the instance this is associated with
6941  InterpreterInstance *instance = activity->getInstance();
6942 
6943  // if we've already loaded this in this instance, just return it.
6944  PackageClass *packageInstance = instance->loadRequires(activity, target, s);
6945 
6946  if (packageInstance == OREF_NULL) /* couldn't create this? */
6947  {
6948  /* report an error */
6950  }
6951  // add this to the source context
6952  addPackage(packageInstance);
6953  return packageInstance;
6954 }
6955 
6956 
6957 /**
6958  * Add a package to a source file context. This allows new
6959  * packages to be imported into a source.
6960  *
6961  * @param p
6962  */
6964 {
6965  // force the directives to be processed first
6966  install();
6967  // we only create this on the first use
6968  if (loadedPackages == OREF_NULL)
6969  {
6971  }
6972  else
6973  {
6974  // we only add a given package item once.
6976  {
6977  return;
6978  }
6979  }
6980 
6981  // add this to the list and merge the information
6982  loadedPackages->append(p);
6983  // not merge all of the info from the imported package
6985 }
6986 
6987 
6988 /**
6989  * Retrieve the package wrapper associated with this source.
6990  *
6991  * @return The package instance that fronts for this source in Rexx code.
6992  */
6994 {
6995  if (package == OREF_NULL)
6996  {
6997  OrefSet(this, this->package, new PackageClass(this));
6998  }
6999  return package;
7000 }
7001 
7002 
7003 /**
7004  * Add an installed class to this source package
7005  *
7006  * @param name The class name
7007  * @param classObject
7008  * The class object
7009  * @param publicClass
7010  * Indicates whether this needs to be added to the public list as well.
7011  */
7012 void RexxSource::addInstalledClass(RexxString *name, RexxClass *classObject, bool publicClass)
7013 {
7014  // force the directives to be processed first
7015  install();
7016  // make sure we have this created
7018  {
7020  }
7021  installed_classes->setEntry(name, classObject);
7022  if (publicClass)
7023  {
7024  // make sure we have this created also
7026  {
7028  }
7029  installed_public_classes->setEntry(name, classObject);
7030  }
7031 }
7032 
7033 
7034 /**
7035  * Add an installed routine to this source package
7036  *
7037  * @param name The routine name
7038  * @param classObject
7039  * The routine object
7040  * @param publicClass
7041  * Indicates whether this needs to be added to the public list as well.
7042  */
7043 void RexxSource::addInstalledRoutine(RexxString *name, RoutineClass *routineObject, bool publicRoutine)
7044 {
7045  // force the directives to be processed first
7046  install();
7047  // make sure we have this created
7048  if (routines == OREF_NULL)
7049  {
7050  OrefSet(this, routines, new_directory());
7051  }
7052  routines->setEntry(name, routineObject);
7053  if (publicRoutine)
7054  {
7055  // make sure we have this created
7056  if (public_routines == OREF_NULL)
7057  {
7059  }
7060  public_routines->setEntry(name, routineObject);
7061  }
7062 }
7063 
7064 
7065 
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
RexxBuffer * new_buffer(size_t s)
@ T_RexxSource
RexxDirectory * new_directory()
RexxIdentityTable * new_identity_table()
RexxInteger * new_integer(wholenumber_t v)
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
AccessFlag
Definition: MethodClass.hpp:73
@ PUBLIC_SCOPE
Definition: MethodClass.hpp:75
@ PRIVATE_SCOPE
Definition: MethodClass.hpp:76
@ PACKAGE_SCOPE
Definition: MethodClass.hpp:77
@ DEFAULT_ACCESS_SCOPE
Definition: MethodClass.hpp:74
GuardFlag
Definition: MethodClass.hpp:59
@ GUARDED_METHOD
Definition: MethodClass.hpp:61
@ UNGUARDED_METHOD
Definition: MethodClass.hpp:62
@ DEFAULT_GUARD
Definition: MethodClass.hpp:60
ProtectedFlag
Definition: MethodClass.hpp:66
@ UNPROTECTED_METHOD
Definition: MethodClass.hpp:69
@ PROTECTED_METHOD
Definition: MethodClass.hpp:68
@ DEFAULT_PROTECTION
Definition: MethodClass.hpp:67
size_t number_digits()
Definition: Numerics.hpp:147
RexxQueue * new_queue()
Definition: QueueClass.hpp:89
#define OREF_NULL
Definition: RexxCore.h:61
#define TheNullArray
Definition: RexxCore.h:193
#define IntegerOne
Definition: RexxCore.h:200
#define TheEnvironment
Definition: RexxCore.h:183
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheCommonRetrievers
Definition: RexxCore.h:186
#define TheTrueObject
Definition: RexxCore.h:196
bool isMethod(RexxObject *o)
Definition: RexxCore.h:288
#define IntegerTwo
Definition: RexxCore.h:201
#define isOfClass(t, r)
Definition: RexxCore.h:224
#define TheNilObject
Definition: RexxCore.h:191
#define Error_Translation_body_error
#define Error_Invalid_expression_until
#define Error_Translation_external_routine
#define Error_Translation_invalid_line
#define Error_Unexpected_then_else
#define Error_Symbol_or_string_fuzz_value
#define Error_Translation_bad_external
#define Error_Symbol_or_string_external
#define Error_Symbol_or_string_constant_value
#define Message_Translations_no_source_available
#define Error_Symbol_or_string_constant
#define Error_Unmatched_parenthesis_square
#define Error_Translation_constant_body
#define Error_Symbol_expected_colon
#define Error_Translation_attribute_method
#define Error_Translation_reply_interpret
#define Error_Invalid_subkeyword_method
#define Error_Symbol_or_string_trace_value
#define Error_Invalid_subkeyword_requires
#define Error_Invalid_expression_message_term
#define Error_Invalid_variable_period
#define Error_Execution_cyclic
#define Error_Unexpected_end_else
#define Error_Unexpected_comma_paren
#define Error_Unmatched_parenthesis_paren
#define Error_Translation_duplicate_constant
#define Error_Symbol_or_string_mixinclass
#define Error_Unexpected_comma_bracket
#define Error_Invalid_subkeyword_class
#define Error_Invalid_do_whileuntil
#define Error_External_name_not_found_routine
#define Error_Unexpected_end_then
#define Error_Translation_directive_interpret
#define Error_Program_unreadable_name
#define Error_Invalid_trace_trace
#define Error_Invalid_subkeyword_attribute
#define Error_Incomplete_do_otherwise
#define Error_Unexpected_comma_comma
#define Error_Routine_not_found_requires
#define Error_Symbol_or_string_attribute
#define Error_Symbol_or_string_inherit
#define Error_Invalid_expression_after_tilde
#define Error_Invalid_variable_number
#define Error_Symbol_or_string_digits_value
#define Error_Translation_bad_directive
#define Error_Symbol_or_string_routine
#define Error_Symbol_expected_varref
#define Error_Invalid_expression_general
#define Error_Symbol_expected_expose
#define Error_Translation_expose_interpret
#define Error_Translation_forward_interpret
#define Error_Symbol_or_string_subclass
#define Error_Symbol_expected_drop
#define Error_Invalid_subkeyword_options
#define Error_Translation_external_method
#define Error_Invalid_data_constant_dir
#define Error_Invalid_expression_prefix
#define Error_Symbol_expected_upper
#define Error_Translation_duplicate_attribute
#define Error_Translation_abstract_attribute
#define Error_Unexpected_when_when
#define Error_Symbol_or_string_method
#define Error_Symbol_or_string_requires
#define Error_Translation_external_attribute
#define Error_Then_expected_if
#define Error_Unexpected_then_then
#define Error_Variable_reference_missing
#define Error_Symbol_expected_directive
#define Error_Symbol_or_string_class
#define Error_Symbol_or_string_metaclass
#define Error_Expression_result_digits
#define Error_Translation_use_interpret
#define Error_Incomplete_do_then
#define Error_Incomplete_do_else
#define Error_Translation_missing_class
#define Error_When_expected_whenotherwise
#define Error_Invalid_subkeyword_routine
#define Error_Invalid_whole_number_fuzz
#define Error_Translation_invalid_attribute
#define Message_Translations_internal_code
#define Error_Unexpected_end_nodo
#define Error_Translation_user_defined
#define Error_Translation_guard_interpret
#define Error_External_name_not_found_method
#define Error_Unexpected_label_interpret
#define Error_Translation_abstract_method
#define Error_Incomplete_do_do
#define Error_Variable_reference_extra
#define Error_Unexpected_when_otherwise
#define Error_Translation_duplicate_method
#define Error_Invalid_expression_while
#define Error_Incomplete_do_loop
#define Error_Translation_duplicate_routine
#define Error_Invalid_whole_number_digits
#define Error_Translation_duplicate_class
#define Error_Translation_expose
#define Error_Invalid_subkeyword_form
#define Error_Incomplete_do_select
size_t HashLink
#define FIRST_VARIABLE_INDEX
RexxMemory memoryObject
Definition: RexxMemory.cpp:86
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
@ QUEUE_FIFO
@ QUEUE_LIFO
#define ATTRIBUTE_GET
#define PREFIX_LENGTH
#define line_delimiters
Definition: SourceFile.cpp:102
#define dumpClause(from, source, clause)
Definition: SourceFile.cpp:862
#define dumpTokens(from, source, clause)
Definition: SourceFile.cpp:894
#define HOLDSIZE
Definition: SourceFile.cpp:95
#define ctrl_z
Definition: SourceFile.cpp:103
#define INDENT_SPACING
void dumpTokensImpl(const char *from, RexxSource *source, RexxClause *clause)
Definition: SourceFile.cpp:897
#define ATTRIBUTE_SET
#define INSTRUCTION_OVERHEAD
#define PREFIX_OFFSET
#define ATTRIBUTE_BOTH
struct _LINE_DESCRIPTOR LINE_DESCRIPTOR
void dumpClauseImpl(const char *from, RexxSource *source, RexxClause *clause)
Definition: SourceFile.cpp:865
#define LINENUMBER
#define reclaimed
Definition: SourceFile.hpp:108
#define _install
Definition: SourceFile.hpp:107
#define _interpret
Definition: SourceFile.hpp:106
#define no_clause
Definition: SourceFile.hpp:110
#define reclaim_possible
Definition: SourceFile.hpp:109
#define FRAME_PARSE
RexxString * raw_string(stringsize_t l)
#define STRING_NAME
Definition: StringClass.hpp:60
RexxString * new_string(const char *s, stringsize_t l)
#define STRING_COMPOUND_NAME
Definition: StringClass.hpp:56
#define STRING_STEM
Definition: StringClass.hpp:55
#define IS_SUBDIRECTIVE
Definition: Token.hpp:275
#define TERM_SQRIGHT
Definition: Token.hpp:58
#define SUBKEY_UNTIL
Definition: Token.hpp:230
#define SUBKEY_WHILE
Definition: Token.hpp:236
#define SUBDIRECTIVE_NOCOMMANDS
Definition: Token.hpp:298
#define SUBDIRECTIVE_EXTERNAL
Definition: Token.hpp:282
#define KEYWORD_OTHERWISE
Definition: Token.hpp:180
#define KEYWORD_PULL
Definition: Token.hpp:162
#define KEYWORD_SELECT
Definition: Token.hpp:168
#define SUBDIRECTIVE_LIBRARY
Definition: Token.hpp:292
#define TOKEN_LITERAL
Definition: Token.hpp:79
#define SUBKEY_SCIENTIFIC
Definition: Token.hpp:226
#define KEYWORD_UPPER
Definition: Token.hpp:201
#define SUBDIRECTIVE_MIXINCLASS
Definition: Token.hpp:285
#define KEYWORD_PARSE
Definition: Token.hpp:160
#define DIRECTIVE_CLASS
Definition: Token.hpp:266
#define OPERATOR_SUBTRACT
Definition: Token.hpp:111
#define TOKEN_COLON
Definition: Token.hpp:87
#define TERM_COMMA
Definition: Token.hpp:63
#define TOKEN_OPERATOR
Definition: Token.hpp:80
#define SUBDIRECTIVE_PACKAGE
Definition: Token.hpp:301
#define SUBDIRECTIVE_FORM
Definition: Token.hpp:294
#define KEYWORD_NOP
Definition: Token.hpp:157
#define SUBKEY_BY
Definition: Token.hpp:206
#define KEYWORD_ENDTHEN
Definition: Token.hpp:193
#define OPERATOR_BACKSLASH
Definition: Token.hpp:141
#define OPERATOR_EQUAL
Definition: Token.hpp:120
#define KEYWORD_REPLY
Definition: Token.hpp:165
#define IS_DIRECTIVE
Definition: Token.hpp:264
#define TERM_COND
Definition: Token.hpp:70
#define KEYWORD_SIGNAL
Definition: Token.hpp:169
#define TOKEN_LEFT
Definition: Token.hpp:84
#define TERM_RIGHT
Definition: Token.hpp:57
#define DIRECTIVE_METHOD
Definition: Token.hpp:267
#define SUBDIRECTIVE_COMMANDS
Definition: Token.hpp:297
#define DIRECTIVE_EXTENSION
Definition: Token.hpp:272
#define SUBDIRECTIVE_MACROSPACE
Definition: Token.hpp:299
#define KEYWORD_RETURN
Definition: Token.hpp:166
#define SYMBOL_CONSTANT
Definition: Token.hpp:98
#define DIRECTIVE_REQUIRES
Definition: Token.hpp:265
#define KEYWORD_DO
Definition: Token.hpp:149
#define TERM_THEN
Definition: Token.hpp:65
#define KEYWORD_OPTIONS
Definition: Token.hpp:159
#define KEYWORD_CALL
Definition: Token.hpp:148
#define KEYWORD_PUSH
Definition: Token.hpp:163
#define TOKEN_BLANK
Definition: Token.hpp:77
#define KEYWORD_ITERATE
Definition: Token.hpp:154
#define SUBDIRECTIVE_SET
Definition: Token.hpp:291
#define IS_SUBKEY
Definition: Token.hpp:204
#define SUBKEY_THEN
Definition: Token.hpp:228
#define SUBDIRECTIVE_GUARDED
Definition: Token.hpp:280
#define DIRECTIVE_ROUTINE
Definition: Token.hpp:268
#define KEYWORD_IFTHEN
Definition: Token.hpp:181
#define KEYWORD_WHENTHEN
Definition: Token.hpp:182
#define KEYWORD_PROCEDURE
Definition: Token.hpp:161
#define SYMBOL_DOTSYMBOL
Definition: Token.hpp:104
#define KEYWORD_LEAVE
Definition: Token.hpp:155
#define SUBDIRECTIVE_UNGUARDED
Definition: Token.hpp:284
#define SUBDIRECTIVE_INHERIT
Definition: Token.hpp:278
#define OPERATOR_PLUS
Definition: Token.hpp:110
#define TOKEN_DCOLON
Definition: Token.hpp:92
#define SUBDIRECTIVE_SUBCLASS
Definition: Token.hpp:283
#define OPERATOR_ABUTTAL
Definition: Token.hpp:117
#define SUBDIRECTIVE_ATTRIBUTE
Definition: Token.hpp:286
#define refineSubclass(token, refinedSubclass)
Definition: Token.hpp:51
#define SUBKEY_ENGINEERING
Definition: Token.hpp:210
#define SUBDIRECTIVE_UNPROTECTED
Definition: Token.hpp:289
#define OPERATOR_STRICT_EQUAL
Definition: Token.hpp:128
#define IS_KEYWORD
Definition: Token.hpp:145
#define TERM_WITH
Definition: Token.hpp:64
#define KEYWORD_WHEN
Definition: Token.hpp:183
#define KEYWORD_NUMERIC
Definition: Token.hpp:158
#define TOKEN_COMMA
Definition: Token.hpp:82
#define KEYWORD_ADDRESS
Definition: Token.hpp:146
#define TERM_KEYWORD
Definition: Token.hpp:66
#define SUBDIRECTIVE_TRACE
Definition: Token.hpp:296
#define SUBKEY_FOR
Definition: Token.hpp:212
#define SYMBOL_COMPOUND
Definition: Token.hpp:101
#define SUBDIRECTIVE_FUZZ
Definition: Token.hpp:295
#define KEYWORD_QUEUE
Definition: Token.hpp:164
#define KEYWORD_ARG
Definition: Token.hpp:147
#define KEYWORD_ELSE
Definition: Token.hpp:177
#define KEYWORD_IF
Definition: Token.hpp:152
#define KEYWORD_USE
Definition: Token.hpp:173
#define SYMBOL_STEM
Definition: Token.hpp:102
#define TERM_EOC
Definition: Token.hpp:56
#define SUBDIRECTIVE_DIGITS
Definition: Token.hpp:293
#define SUBDIRECTIVE_NOMACROSPACE
Definition: Token.hpp:300
#define KEYWORD_LABEL
Definition: Token.hpp:187
#define TERM_BY
Definition: Token.hpp:60
#define KEYWORD_FORWARD
Definition: Token.hpp:198
#define DIRECTIVE_ATTRIBUTE
Definition: Token.hpp:269
#define SUBDIRECTIVE_GET
Definition: Token.hpp:290
#define SYMBOL_VARIABLE
Definition: Token.hpp:99
#define SUBDIRECTIVE_ABSTRACT
Definition: Token.hpp:288
#define DIRECTIVE_OPTIONS
Definition: Token.hpp:271
#define SUBDIRECTIVE_CLASS
Definition: Token.hpp:281
#define KEYWORD_GUARD
Definition: Token.hpp:172
#define TOKEN_SQRIGHT
Definition: Token.hpp:91
#define TERM_FOR
Definition: Token.hpp:61
#define TERM_WHILE
Definition: Token.hpp:62
#define SUBDIRECTIVE_PRIVATE
Definition: Token.hpp:279
#define KEYWORD_EXPOSE
Definition: Token.hpp:175
#define SUBKEY_TO
Definition: Token.hpp:229
#define KEYWORD_THEN
Definition: Token.hpp:178
#define KEYWORD_INTERPRET
Definition: Token.hpp:153
#define TOKEN_DTILDE
Definition: Token.hpp:89
#define KEYWORD_RAISE
Definition: Token.hpp:176
#define TOKEN_EOC
Definition: Token.hpp:81
#define KEYWORD_EXIT
Definition: Token.hpp:151
#define TERM_TO
Definition: Token.hpp:59
#define SUBKEY_ARG
Definition: Token.hpp:205
#define KEYWORD_DROP
Definition: Token.hpp:150
#define SUBKEY_WITH
Definition: Token.hpp:237
#define SUBDIRECTIVE_PUBLIC
Definition: Token.hpp:276
#define KEYWORD_FIRST
Definition: Token.hpp:190
#define SUBKEY_PULL
Definition: Token.hpp:225
#define TOKEN_RIGHT
Definition: Token.hpp:85
#define SUBDIRECTIVE_METACLASS
Definition: Token.hpp:277
#define TOKEN_SQLEFT
Definition: Token.hpp:90
#define KEYWORD_TRACE
Definition: Token.hpp:170
#define TOKEN_ASSIGNMENT
Definition: Token.hpp:94
#define KEYWORD_LOOP
Definition: Token.hpp:199
#define KEYWORD_SAY
Definition: Token.hpp:167
#define KEYWORD_ENDWHEN
Definition: Token.hpp:194
#define TOKEN_TILDE
Definition: Token.hpp:88
#define DIRECTIVE_CONSTANT
Definition: Token.hpp:270
#define INTEGER_CONSTANT
Definition: Token.hpp:105
#define TOKEN_SYMBOL
Definition: Token.hpp:78
#define OPERATOR_BLANK
Definition: Token.hpp:119
#define SUBDIRECTIVE_PROTECTED
Definition: Token.hpp:287
#define KEYWORD_END
Definition: Token.hpp:179
#define SYMBOL_DUMMY
Definition: Token.hpp:103
#define TOKEN_SOURCE_LITERAL
Definition: Token.hpp:95
#define CONCURRENCY_TRACE
Definition: Utilities.hpp:50
static RexxObject * getLocalEnvironment(RexxString *name)
static RexxActivity *volatile currentActivity
BaseExecutable * setSourceObject(RexxSource *s)
RexxString * getMetaClass()
void removeDependency(RexxString *name)
bool checkDuplicateMethod(RexxString *name, bool classMethod)
RexxClass * install(RexxSource *source, RexxActivation *activation)
RexxString * getSubClass()
void addConstantMethod(RexxString *name, RexxMethod *method)
RexxString * getName()
void addMethod(RexxString *name, RexxMethod *method, bool classMethod)
bool dependenciesResolved()
void addDependencies(RexxDirectory *class_directives)
void addMethod(RexxString *name, RexxMethod *method, bool classMethod)
bool checkDuplicateMethod(RexxString *name, bool classMethod)
void addConstantMethod(RexxString *name, RexxMethod *method)
void install(RexxSource *source, RexxActivation *activation)
PackageClass * loadRequires(RexxActivity *activity, RexxString *shortName, const char *data, size_t length)
RexxString * resolveProgramName(RexxString *name, RexxString *dir, RexxString *ext)
void install(RexxActivation *context)
static const bool DEFAULT_FORM
Definition: Numerics.hpp:81
static const bool FORM_SCIENTIFIC
Definition: Numerics.hpp:76
static const size_t DEFAULT_FUZZ
Definition: Numerics.hpp:79
static const bool FORM_ENGINEERING
Definition: Numerics.hpp:77
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
RexxSource * getSourceObject()
static RoutineClass * resolveRoutine(RexxString *function, RexxString *packageName, RexxString *procedure)
static RexxNativeMethod * resolveMethod(RexxString *packageName, RexxString *methodName)
void install(RexxActivation *context)
RexxString * formatSourcelessTraceLine(RexxString *packageName)
static const bool default_enable_macrospace
static size_t processTraceSetting(size_t traceSetting)
static const size_t default_trace_flags
static const bool default_enable_commands
void raiseException(wholenumber_t, RexxString *, RexxArray *, RexxObject *)
RexxString * buildMessage(wholenumber_t, RexxArray *)
InterpreterInstance * getInstance()
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
size_t getDataLength()
Definition: BufferClass.hpp:53
virtual char * getData()
void newClause()
Definition: Clause.cpp:130
void setStart(size_t, size_t)
Definition: Clause.cpp:96
void setEnd(size_t, size_t)
Definition: Clause.cpp:106
size_t free
Definition: Clause.hpp:84
SourceLocation clauseLocation
Definition: Clause.hpp:79
RexxArray * tokens
Definition: Clause.hpp:82
const SourceLocation & getLocation()
Definition: Clause.hpp:72
void setLocation(SourceLocation &l)
Definition: Clause.hpp:73
RexxObject * setEntry(RexxString *, RexxObject *)
RexxObject * put(RexxObject *, RexxString *)
RexxObject * fastAt(RexxString *name)
RexxObject * entry(RexxString *)
bool available(HashLink pos)
RexxObject * value(HashLink pos)
HashLink next(HashLink pos)
RexxObject * index(HashLink pos)
virtual RexxObject * put(RexxObject *, RexxObject *)
virtual RexxObject * remove(RexxObject *key)
SourceLocation instructionLocation
const SourceLocation & getLocation()
uint16_t instructionType
void setNext(RexxInstruction *next)
uint16_t instructionFlags
RexxInstruction * nextInstruction
void setBehaviour(RexxBehaviour *b)
RexxObject * removeIndex(size_t i)
Definition: ListClass.hpp:113
RexxObject * append(RexxObject *)
Definition: ListClass.cpp:538
size_t firstIndex()
Definition: ListClass.hpp:84
size_t nextIndex(size_t i)
Definition: ListClass.cpp:804
size_t items()
Definition: ListClass.hpp:97
RexxObject * hasItem(RexxObject *)
Definition: ListClass.cpp:994
RexxObject * removeFirst()
Definition: ListClass.hpp:109
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
bool savingImage()
Definition: RexxMemory.hpp:217
void setConstant()
void setAbstract()
void setAttribute()
void setAttributes(AccessFlag access, ProtectedFlag _protected, GuardFlag _guarded)
void setUnguarded()
virtual BaseCode * setSourceObject(RexxSource *s)
RexxNumberString * numberString()
bool requestUnsignedNumber(stringsize_t &, size_t)
RexxInteger * requestInteger(size_t)
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
void push(RexxObject *obj)
Definition: QueueClass.hpp:81
RexxObject * pop()
Definition: QueueClass.hpp:80
void queue(RexxObject *obj)
Definition: QueueClass.hpp:82
size_t copyData(void *, size_t)
RexxBuffer * getBuffer()
RexxInstruction * loopNew()
RexxQueue * subTerms
Definition: SourceFile.hpp:514
RexxStemVariable * addStem(RexxString *)
RexxDirectory * literals
Definition: SourceFile.hpp:509
RexxDirectory * class_dependencies
Definition: SourceFile.hpp:517
void resetPosition(size_t p)
Definition: SourceFile.hpp:319
RexxObject * subExpression(int)
static const size_t TRACE_COMMANDS
Definition: SourceFile.hpp:424
void pushDo(RexxInstruction *i)
Definition: SourceFile.hpp:297
void createConstantGetterMethod(RexxString *name, RexxObject *value)
void install()
PackageClass * loadRequires(RexxActivity *activity, RexxString *target)
static const size_t TRACE_ERRORS
Definition: SourceFile.hpp:428
RexxToken * sourceNextToken(RexxToken *)
Definition: Scanner.cpp:688
RexxList * sourceLiterals
Definition: SourceFile.hpp:510
RexxToken * popOperator()
Definition: SourceFile.hpp:308
static int subDirective(RexxToken *)
RexxInstruction * labelNew()
void decodeExternalMethod(RexxString *methodName, RexxString *externalSpec, RexxString *&library, RexxString *&procedure)
static int keyDirective(RexxToken *)
RexxDirectory * public_routines
Definition: SourceFile.hpp:480
RexxObject * parseLogical(RexxToken *first, int terminators)
RexxCode * translateBlock(RexxDirectory *)
RexxInstruction * forwardNew()
static const size_t TRACE_INTERMEDIATES
Definition: SourceFile.hpp:430
void createAttributeGetterMethod(RexxString *name, RexxVariableBase *retriever, bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod)
size_t line_adjust
Definition: SourceFile.hpp:470
RexxInstruction * traceNew()
static const size_t TRACE_SETTING_MASK
Definition: SourceFile.hpp:437
RexxObject * collectionMessage(RexxToken *, RexxObject *, int)
void extensionDirective()
RexxInstruction * ifNew(int)
void previousToken()
Definition: SourceFile.hpp:315
RexxString * programDirectory
Definition: SourceFile.hpp:457
void addClause(RexxInstruction *)
PackageClass * package
Definition: SourceFile.hpp:476
RexxQueue * terms
Definition: SourceFile.hpp:513
RexxClause * clause
Definition: SourceFile.hpp:462
static int precedence(RexxToken *)
Definition: Scanner.cpp:53
RexxString * programExtension
Definition: SourceFile.hpp:459
void argList(RexxToken *, int, bool, size_t &, size_t &)
RexxCode * interpret(RexxString *, RexxDirectory *, size_t, RexxActivation *)
RexxMethod * createNativeMethod(RexxString *name, RexxString *library, RexxString *procedure)
void resolveDependencies()
RexxToken * nextToken()
Definition: SourceFile.hpp:313
RexxObject * expression(int)
void setGuard()
bool reconnect()
Definition: SourceFile.cpp:344
RexxInstruction * messageAssignmentNew(RexxExpressionMessage *, RexxObject *)
void checkDuplicateMethod(RexxString *name, bool classMethod, int errorMsg)
void extractNameInformation()
Definition: SourceFile.cpp:318
RexxInstruction * exitNew()
void directive()
RexxString * traceBack(RexxActivation *, SourceLocation &, size_t, bool)
RexxInstruction * findLabel(RexxString *)
RexxInstruction * topDo()
Definition: SourceFile.hpp:299
RexxInstruction * exposeNew()
void flatten(RexxEnvelope *)
Definition: SourceFile.cpp:716
RexxSource * parentSource
Definition: SourceFile.hpp:477
RexxInstruction * instruction()
static int subKeyword(RexxToken *)
RexxObject * fullSubExpression(int)
RexxCode * initCode
Definition: SourceFile.hpp:473
void createAbstractMethod(RexxString *name, bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod, bool isAttribute)
void syntaxError(int errorcode, RexxInstruction *i)
Definition: SourceFile.hpp:320
RexxObject * popNTerms(size_t)
RexxString * resolveProgramName(RexxActivity *activity, RexxString *name)
RexxString * programName
Definition: SourceFile.hpp:456
RexxString * programFile
Definition: SourceFile.hpp:458
RoutineClass * findPublicRoutine(RexxString *)
RexxInstruction * elseNew(RexxToken *)
RexxInstruction * raiseNew()
size_t line_number
Definition: SourceFile.hpp:468
RexxObject * messageSubterm(int)
SourceLocation clauseLocation
Definition: SourceFile.hpp:463
void constantDirective()
RexxInstruction * assignmentNew(RexxToken *)
RexxArray * extractSource()
RexxList * classes
Definition: SourceFile.hpp:483
RexxToken * getToken(int, int)
RexxObject * messageTerm()
RexxObject * subTerm(int)
static const size_t TRACE_LABELS
Definition: SourceFile.hpp:425
RexxInstruction * messageAssignmentOpNew(RexxExpressionMessage *, RexxToken *, RexxObject *)
void addLabel(RexxInstruction *, RexxString *)
size_t flags
Definition: SourceFile.hpp:454
RexxVariableBase * getRetriever(RexxString *)
size_t variableindex
Definition: SourceFile.hpp:533
ExtensionDirective * active_extension
Definition: SourceFile.hpp:519
void pushOperator(RexxToken *operatorToken)
Definition: SourceFile.hpp:307
RexxObject * functionCallMessage(RexxToken *, RexxObject *, int)
void globalSetup()
void libraryDirective(RexxString *name, RexxToken *token)
ClassDirective * active_class
Definition: SourceFile.hpp:518
RexxObject * toss(RexxObject *)
void syntaxErrorAt(int errorcode, RexxToken *token)
Definition: SourceFile.hpp:322
void errorLine(int, RexxInstruction *)
RexxInstruction * signalNew()
RexxObject * parseConditional(int *, int)
RexxInstruction * leaveNew(int)
RexxActivation * interpret_activation
Definition: SourceFile.hpp:471
size_t line_count
Definition: SourceFile.hpp:467
RexxInstruction * addressNew()
RexxCompoundVariable * addCompound(RexxString *)
void firstToken()
Definition: SourceFile.hpp:316
RexxInstruction * numericNew()
void addReference(RexxObject *reference)
Definition: SourceFile.hpp:296
SecurityManager * securityManager
Definition: SourceFile.hpp:460
void createAttributeSetterMethod(RexxString *name, RexxVariableBase *retriever, bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod)
size_t traceFlags
Definition: SourceFile.hpp:497
RexxInstruction * upperNew()
StackFrameClass * createStackFrame()
bool hasBody()
size_t current_length
Definition: SourceFile.hpp:466
void pushSubTerm(RexxObject *)
RexxCode * translate(RexxDirectory *)
RexxInstruction * endNew()
RexxCode * generateCode(bool isMethod)
void addInstalledRoutine(RexxString *name, RoutineClass *routineObject, bool publicRoutine)
void routineDirective()
RexxObject * constantLogicalExpression()
void isExposeValid()
size_t line_offset
Definition: SourceFile.hpp:469
void cleanup()
static const size_t DEBUG_ON
Definition: SourceFile.hpp:444
void removeObj(RexxObject *object)
Definition: SourceFile.hpp:378
RexxList * loadedPackages
Definition: SourceFile.hpp:475
RexxDirectory * strings
Definition: SourceFile.hpp:511
RexxList * requires
Definition: SourceFile.hpp:482
RexxInstruction * parseNew(int)
void blockSyntaxError(RexxInstruction *i)
Definition: SourceFile.hpp:321
RexxObject * popTerm()
void errorToken(int, RexxToken *)
void argArray(RexxToken *, int, bool, RexxArray *&, RexxArray *&)
void methodDirective()
RexxArray * getGuard()
static RexxString * formatTraceSetting(size_t source)
RexxInstruction * useNew()
RexxInstruction * thenNew(RexxToken *, RexxInstructionIf *)
RexxCode * interpretMethod(RexxDirectory *, RexxActivation *)
RexxToken * topOperator()
Definition: SourceFile.hpp:309
void liveGeneral(int reason)
Definition: SourceFile.cpp:642
RexxInstruction * returnNew()
RexxArray * sourceArray
Definition: SourceFile.hpp:455
RoutineClass * findRoutine(RexxString *)
RexxInstruction * dropNew()
static const size_t TRACE_IGNORE
Definition: SourceFile.hpp:432
void position(size_t, size_t)
Definition: SourceFile.cpp:518
RexxQueue * operators
Definition: SourceFile.hpp:516
static const size_t DEBUG_OFF
Definition: SourceFile.hpp:445
void blockError(RexxInstruction *)
RexxInstruction * optionsNew()
void adjustLine(size_t, size_t)
Definition: SourceFile.cpp:365
void expose(RexxString *)
RexxInstruction * messageNew(RexxExpressionMessage *)
RexxInstruction * replyNew()
void createMethod(RexxString *name, bool classMethod, AccessFlag privateMethod, ProtectedFlag protectedMethod, GuardFlag guardedMethod, bool isAttribute)
RexxString * commonString(RexxString *)
RexxInstruction * popDo()
Definition: SourceFile.hpp:298
RexxSource(RexxString *, RexxArray *)
Definition: SourceFile.cpp:113
void addInstalledClass(RexxString *name, RexxClass *classObject, bool publicClass)
void errorCleanup()
RexxQueue * control
Definition: SourceFile.hpp:512
void classDirective()
RexxInstruction * interpretNew()
void initFile()
Definition: SourceFile.cpp:275
RexxInstruction * sourceNewObject(size_t, RexxBehaviour *, int)
RexxString * extract(SourceLocation &, bool=false)
size_t processVariableList(int)
RexxClass * findPublicClass(RexxString *name)
RexxObject * constantExpression()
RexxInstruction * doNew()
PackageClass * getPackage()
void errorPosition(int, SourceLocation)
RexxDirectory * variables
Definition: SourceFile.hpp:526
RexxInstruction * commandNew()
bool atEnd(void)
Definition: SourceFile.hpp:311
size_t sourceSize()
Definition: SourceFile.cpp:783
void error(int)
size_t maxstack
Definition: SourceFile.hpp:532
void pushTerm(RexxObject *)
bool needsInstallation()
Definition: SourceFile.hpp:294
static const size_t TRACE_NORMAL
Definition: SourceFile.hpp:426
RexxInstruction * nopNew()
void holdObject(RexxObject *object)
Definition: SourceFile.hpp:376
RexxList * libraries
Definition: SourceFile.hpp:481
void addMethod(RexxString *name, RexxMethod *method, bool classMethod)
void live(size_t)
Definition: SourceFile.cpp:589
const char * current
Definition: SourceFile.hpp:461
RexxObject * message(RexxObject *, bool, int)
RexxObject * variableOrMessageTerm()
void optionsDirective()
void mergeRequired(RexxSource *)
bool isInternalCode()
Definition: SourceFile.hpp:329
size_t traceSetting
Definition: SourceFile.hpp:496
RexxDirectory * installed_classes
Definition: SourceFile.hpp:487
void initBuffered(RexxBuffer *)
Definition: SourceFile.cpp:181
RexxInstruction * first
Definition: SourceFile.hpp:523
RexxInstruction * queueNew(int)
RexxInstruction * sayNew()
RexxToken * nextReal()
Definition: SourceFile.hpp:314
void setProgramName(RexxString *name)
Definition: SourceFile.cpp:338
RexxInstruction * assignmentOpNew(RexxToken *, RexxToken *)
RexxObject * popSubTerm()
void saveObject(RexxObject *object)
Definition: SourceFile.hpp:377
void setReconnect()
Definition: SourceFile.cpp:357
RexxVariableBase * addVariable(RexxString *)
static const size_t TRACE_RESULTS
Definition: SourceFile.hpp:429
RexxDirectory * methods
Definition: SourceFile.hpp:491
void needVariableOrDotSymbol(RexxToken *)
Definition: SourceFile.cpp:403
RexxIdentityTable * guard_variables
Definition: SourceFile.hpp:528
bool isTraceable()
Definition: SourceFile.cpp:801
RexxDirectory * installed_public_classes
Definition: SourceFile.hpp:486
void checkDirective(int errorCode)
void processInstall(RexxActivation *)
RexxIdentityTable * savelist
Definition: SourceFile.hpp:507
void inheritSourceContext(RexxSource *source)
RexxInstruction * last
Definition: SourceFile.hpp:524
size_t fuzz
Definition: SourceFile.hpp:494
RexxInstruction * otherwiseNew(RexxToken *)
RexxInstruction * currentInstruction
Definition: SourceFile.hpp:525
void trimClause()
Definition: SourceFile.hpp:317
RexxClass * findInstalledClass(RexxString *name)
size_t currentstack
Definition: SourceFile.hpp:531
void nextClause()
Definition: SourceFile.cpp:936
void flushControl(RexxInstruction *)
RexxObject * function(RexxToken *, RexxToken *, int)
RexxDirectory * merged_public_classes
Definition: SourceFile.hpp:488
static const size_t TRACE_OFF
Definition: SourceFile.hpp:431
RexxBuffer * sourceBuffer
Definition: SourceFile.hpp:464
RexxString * get(size_t)
Definition: SourceFile.cpp:815
RexxDirectory * merged_public_routines
Definition: SourceFile.hpp:490
RexxDirectory * exposed_variables
Definition: SourceFile.hpp:529
RexxInstruction * guardNew()
RexxInstruction * endIfNew(RexxInstructionIf *)
bool enableMacrospace
Definition: SourceFile.hpp:499
RexxObject * parenExpression(RexxToken *)
void attributeDirective()
RexxQueue * namedSubTerms
Definition: SourceFile.hpp:515
RexxArray * words(RexxString *)
RexxClass * findClass(RexxString *)
RexxStack * holdstack
Definition: SourceFile.hpp:508
static const size_t DEBUG_IGNORE
Definition: SourceFile.hpp:443
void needVariable(RexxToken *)
Definition: SourceFile.cpp:382
RexxObject * addText(RexxToken *)
bool terminator(int, RexxObject *)
static const size_t TRACE_ALL
Definition: SourceFile.hpp:423
RexxList * calls
Definition: SourceFile.hpp:530
static bool parseTraceSetting(RexxString *, size_t &, size_t &, char &)
size_t digits
Definition: SourceFile.hpp:493
void reclaimClause()
Definition: SourceFile.hpp:310
void nextLine()
Definition: SourceFile.cpp:504
void addPackage(PackageClass *package)
RexxList * extensions
Definition: SourceFile.hpp:484
static const size_t DEFAULT_TRACE_SETTING
Definition: SourceFile.hpp:434
static const size_t DEBUG_TOGGLE
Definition: SourceFile.hpp:446
RexxDirectory * labels
Definition: SourceFile.hpp:527
RoutineClass * findLocalRoutine(RexxString *)
bool enableCommands
Definition: SourceFile.hpp:498
void requiresDirective()
RexxInstruction * procedureNew()
size_t markPosition()
Definition: SourceFile.hpp:318
RexxDirectory * routines
Definition: SourceFile.hpp:479
static const size_t TRACE_FAILURES
Definition: SourceFile.hpp:427
RexxInstruction * selectNew()
RexxInstruction * callNew()
RexxBuffer * sourceIndices
Definition: SourceFile.hpp:465
RexxString * stringValue()
size_t getLength()
RexxObject * getEncoding()
RexxObject * getText()
const char * getStringData()
void setNumberString(RexxObject *)
void set(size_t s, int c, size_t l)
RexxString * extract(size_t offset, size_t sublength)
RexxString * word(RexxInteger *)
RexxString * concatWithCstring(const char *)
RexxString * concat(RexxString *)
RexxString * concatToCstring(const char *)
RexxString * upper()
void put(size_t s, const void *b, size_t l)
char getChar(size_t p)
int numeric
Definition: Token.hpp:451
RexxString * value
Definition: Token.hpp:448
SourceLocation tokenLocation
Definition: Token.hpp:447
static const char * keywordText(int code)
Definition: Token.cpp:236
static const char * codeText(int code)
Definition: Token.cpp:128
const SourceLocation & getLocation()
Definition: Token.hpp:443
bool isSymbol()
Definition: Token.hpp:439
bool isSymbolOrLiteral()
Definition: Token.hpp:437
bool isType(TokenClass t)
Definition: Token.hpp:430
bool isVariable()
Definition: Token.hpp:434
bool isOperator()
Definition: Token.hpp:440
bool isSourceLiteral()
Definition: Token.hpp:436
bool isLiteral()
Definition: Token.hpp:435
bool isConstant()
Definition: Token.hpp:438
bool isEndOfClause()
Definition: Token.hpp:441
int classId
Definition: Token.hpp:449
int subclass
Definition: Token.hpp:450
static RexxObject * buildCompoundVariable(RexxString *variable_name, bool direct)
void call(RexxActivity *, RexxString *, RexxObject **, size_t, size_t, RexxString *, RexxString *, int, ProtectedObject &)
RexxObject * checkEnvironmentAccess(RexxString *index)
RexxObject * checkLocalAccess(RexxString *index)
size_t getEndLine() const
size_t getLineNumber() const
void setEnd(SourceLocation &l)
size_t getEndOffset() const
void setEndLine(size_t l)
void setOffset(size_t l)
void setLineNumber(size_t l)
size_t getOffset() const
bool isLimitedTrace() const
void setLimitedTrace(bool b)
void setEndOffset(size_t l)
static RexxString * extractFile(RexxString *file)
static RexxString * extractDirectory(RexxString *file)
static RexxString * extractExtension(RexxString *file)
static RexxBuffer * readProgram(const char *file_name)
static const char * locateCharacter(const char *s, const char *set, size_t l)
Definition: Utilities.cpp:72
static void GetConcurrencyInfos(struct ConcurrencyInfos &concurrencyInfos)
Definition: Utilities.cpp:61
static bool traceConcurrency()
static bool traceParsing()
static int strCaselessCompare(const char *opt1, const char *opt2)
Definition: Utilities.cpp:102
int type
Definition: cmdparse.cpp:1888
RexxVariableDictionary * variableDictionary
Definition: Utilities.hpp:65
RexxActivation * activation
Definition: Utilities.hpp:64
unsigned short reserveCount
Definition: Utilities.hpp:66
RexxActivity * activity
Definition: Utilities.hpp:63
wholenumber_t threadId
Definition: Utilities.hpp:62
void dbgprintf(const char *format,...)
char line[LINEBUFSIZE]