MethodClass.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 Method Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include "RexxCore.h"
48 #include "StringClass.hpp"
49 #include "ArrayClass.hpp"
50 #include "RexxCode.hpp"
51 #include "RexxNativeCode.hpp"
52 #include "RexxActivity.hpp"
53 #include "RexxActivation.hpp"
54 #include "RexxNativeActivation.hpp"
55 #include "MethodClass.hpp"
56 #include "SourceFile.hpp"
57 #include "DirectoryClass.hpp"
58 #include "ProtectedObject.hpp"
59 #include "BufferClass.hpp"
60 #include "RexxInternalApis.h"
61 #include "RoutineClass.hpp"
62 #include "PackageClass.hpp"
63 #include "Interpreter.hpp"
64 #include "RexxCode.hpp"
65 #include "PackageManager.hpp"
66 
67 // singleton class instance
69 
70 
71 /**
72  * Create initial class object at bootstrap time.
73  */
75 {
76  CLASS_CREATE(Method, "Method", RexxClass);
77 }
78 
79 
80 /**
81  * Resolve a class in the context of an executable.
82  *
83  * @param className The name of the required class.
84  *
85  * @return The resolve class, or OREF_NULL if not found.
86  */
88 {
89  return code->findClass(className);
90 }
91 
92 
93 // ooRexx5 uses setPackageObject
94 /**
95  * Set the source object into a routine or method executable.
96  * This is generally used to attach a source context to a
97  * native method or function defined on a source directive. Since
98  * native functions can be referenced in multiple packages, but are
99  * managed in the package manager context, this may end up
100  * returning a copy of the executable.
101  *
102  * @param s The new source.
103  *
104  * @return Either the same executable object, or a new copy with the
105  * context set.
106  */
108 {
109  // set this into a source object context. If we get a
110  // new object returned, we need to make a copy of the base
111  // executable object also
112  BaseCode *setCode = code->setSourceObject(s);
113  // we're cool if these are equal
114  if (setCode == code)
115  {
116  return this;
117  }
118  // make a copy of this executable, and set the new code into it.
119  BaseExecutable *newBase = (BaseExecutable *)this->copy();
120  OrefSet(newBase, newBase->code, setCode);
121  return newBase;
122 }
123 
124 
125 /**
126  * Retrieve the package from a base executable.
127  *
128  * @return The associated package object. If there is no available package
129  * object, this returns .nil.
130  */
132 {
133  // Keep this test here, to override a possible source's package
134  if (code->isInRexxPackage()) return TheRexxPackage; // indirectly ooRexx5
135 
136  PackageClass *package = code->getPackage();
137  if (package == OREF_NULL)
138  {
139  return (PackageClass *)TheNilObject;
140  }
141  return package;
142 }
143 
144 
145 /**
146  * Retrieve the source lines for a base executable
147  *
148  * @return An array of the source lines
149  */
151 {
152  return code->getSource();
153 }
154 
155 
156 
157 /**
158  * Generate a method directly from a source object.
159  *
160  * @param source The source object.
161  */
163 {
164  // we need to protect this object until the constructor completes.
165  // the code generation step will create lots of new objects, giving a
166  // pretty high probability that it will be collected.
167  ProtectedObject p(this);
168  ProtectedObject p2(_source);
169  OrefSet(this, this->executableName, name);
170  // generate our code object and make the file hook up.
171  RexxCode *codeObj = _source->generateCode(true);
172  OrefSet(this, this->code, codeObj);
173 }
174 
175 
176 /**
177  * Initialize a Routine object from a generated code object. Generally
178  * used for routines generated from ::METHOD directives.
179  *
180  * @param name The routine name.
181  * @param codeObj The associated code object.
182  */
184 {
185  OrefSet(this, this->executableName, name);
186  OrefSet(this, this->code, codeObj); /* store the code */
187 }
188 
189 
190 /**
191  * Initialize a RexxMethod object from a file source.
192  *
193  * @param name The routine name (and the resolved name of the file).
194  */
196 {
197  // we need to protect this object until the constructor completes.
198  // the code generation step will create lots of new objects, giving a
199  // pretty high probability that it will be collected.
200  ProtectedObject p(this);
201  OrefSet(this, this->executableName, name);
202  // get a source object to generat this from
203  RexxSource *_source = new RexxSource(name);
204  ProtectedObject p2(_source);
205  // generate our code object and make the file hook up.
206  RexxCode *codeObj = _source->generateCode(true);
207  OrefSet(this, this->code, codeObj);
208 }
209 
210 
211 /**
212  * Initialize a Routine object using a buffered source.
213  *
214  * @param name The name of the routine.
215  * @param source the source buffer.
216  */
218 {
219  // we need to protect this object until the constructor completes.
220  // the code generation step will create lots of new objects, giving a
221  // pretty high probability that it will be collected.
222  ProtectedObject p(this);
223  OrefSet(this, this->executableName, name);
224  // get a source object to generat this from
225  RexxSource *_source = new RexxSource(name, buf);
226  ProtectedObject p2(_source);
227  // generate our code object and make the file hook up.
228  RexxCode *codeObj = _source->generateCode(true);
229  OrefSet(this, this->code, codeObj);
230 }
231 
232 
233 /**
234  * Initialize a Routine object using directly provided source.
235  *
236  * @param name The name of the routine.
237  * @param data The source data buffer pointer.
238  * @param length the length of the source buffer.
239  */
240 RexxMethod::RexxMethod(RexxString *name, const char *data, size_t length)
241 {
242  // we need to protect this object until the constructor completes.
243  // the code generation step will create lots of new objects, giving a
244  // pretty high probability that it will be collected.
245  ProtectedObject p(this);
246  OrefSet(this, this->executableName, name);
247  // get a source object to generat this from
248  RexxSource *_source = new RexxSource(name, data, length);
249  ProtectedObject p2(_source);
250  // generate our code object and make the file hook up.
251  RexxCode *codeObj = _source->generateCode(true);
252  OrefSet(this, this->code, codeObj);
253 }
254 
255 
256 /**
257  * Initialize a Routine object using an array source.
258  *
259  * @param name The name of the routine.
260  * @param source the source buffer.
261  */
263 {
264  // we need to protect this object until the constructor completes.
265  // the code generation step will create lots of new objects, giving a
266  // pretty high probability that it will be collected.
267  ProtectedObject p(this);
268  OrefSet(this, this->executableName, name);
269  // get a source object to generat this from
270  RexxSource *_source = new RexxSource(name, s);
271  ProtectedObject p2(_source);
272  // generate our code object and make the file hook up.
273  RexxCode *codeObj = _source->generateCode(true);
274  OrefSet(this, this->code, codeObj);
275 }
276 
277 void RexxMethod::live(size_t liveMark)
278 /******************************************************************************/
279 /* Function: Normal garbage collection live marking */
280 /******************************************************************************/
281 {
282  memory_mark(this->scope);
283  memory_mark(this->code);
285  memory_mark(this->objectVariables);
286 }
287 
288 void RexxMethod::liveGeneral(int reason)
289 /******************************************************************************/
290 /* Function: Generalized object marking */
291 /******************************************************************************/
292 {
293  memory_mark_general(this->scope);
294  memory_mark_general(this->code);
296  memory_mark_general(this->objectVariables);
297 }
298 
300 /******************************************************************************/
301 /* Function: Flatten an object */
302 /******************************************************************************/
303 {
305 
306  flatten_reference(newThis->scope, envelope);
307  flatten_reference(newThis->code, envelope);
308  flatten_reference(newThis->executableName, envelope);
309  flatten_reference(newThis->objectVariables, envelope);
310 
312 }
313 
314 
316  RexxActivity *activity, /* activity running under */
317  RexxObject *receiver, /* object receiving the message */
318  RexxString *msgname, /* message to be run */
319  RexxObject **argPtr, /* arguments to the method */
320  size_t count, /* count of arguments */
321  size_t named_count,
322  ProtectedObject &result) // the returned result
323 /******************************************************************************/
324 /* Function: Run a method on an object */
325 /******************************************************************************/
326 {
327  ProtectedObject p(this); // belt-and-braces to make sure this is protected
328  // just forward this to the code object
329  code->run(activity, this, receiver, msgname, argPtr, count, named_count, result);
330 }
331 
332 
334  RexxClass *_scope) /* new method scope */
335 /******************************************************************************/
336 /* Function: Create a new method with a given scope */
337 /******************************************************************************/
338 {
339  // if this doesn't have a scope yet, we can just override what's here
340  if (this->scope == OREF_NULL)
341  {
342  OrefSet(this, this->scope, _scope); /* just set it directly */
343  return this; /* and pass back unchanged */
344  }
345  else
346  {
347  /* copy the method */
348  RexxMethod *newMethod= (RexxMethod *)this->copy();
349  /* give the method the new scope */
350  OrefSet(newMethod, newMethod->scope, _scope);
351  return newMethod; /* and return it */
352  }
353 }
354 
355 
357  RexxObject *manager) /* supplied security manager */
358 /******************************************************************************/
359 /* Function: Associate a security manager with a method's source */
360 /******************************************************************************/
361 {
362  return code->setSecurityManager(manager);
363 }
364 
366  RexxClass *_scope) /* scope for the method */
367 /******************************************************************************/
368 /* Function: Set a scope for a method without making a copy of the method */
369 /* object. */
370 /******************************************************************************/
371 {
372  OrefSet(this, this->scope, _scope); /* just set the scope */
373 }
374 
376 /******************************************************************************/
377 /* Function: Flag a method as being an unguarded method */
378 /******************************************************************************/
379 {
380  this->setUnguarded(); /* turn on the UNGUARDED state */
381  return OREF_NULL; /* return nothing */
382 }
383 
385 /******************************************************************************/
386 /* Function: Flag a method as being a guarded method (the default) */
387 /******************************************************************************/
388 {
389  this->setGuarded(); /* flip back to the GUARDED state */
390  return OREF_NULL; /* return nothing */
391 }
392 
394 /******************************************************************************/
395 /* Function: Flag a method as being a private method */
396 /******************************************************************************/
397 {
398  this->setPrivate(); /* turn on the PRIVATE flag */
399  return OREF_NULL; /* always return nothing */
400 }
401 
403 /******************************************************************************/
404 /* Function: Flag a method as being a private method */
405 /******************************************************************************/
406 {
407  this->setProtected(); /* turn on the PROTECTED flag */
408  return OREF_NULL; /* always return nothing */
409 }
410 
411 /**
412  * Return the Guarded setting for a method object.
413  *
414  * @return .true if the method is guarded. .false otherwise.
415  */
417 {
418  return isGuarded() ? TheTrueObject : TheFalseObject;
419 }
420 
421 /**
422  * Return the Private setting for a method object.
423  *
424  * @return .true if the method is private. .false otherwise.
425  */
427 {
428  return isPrivate() ? TheTrueObject : TheFalseObject;
429 }
430 
431 /**
432  * Return the Package setting for a method object.
433  *
434  * @return .true if the method is package scope. .false
435  * otherwise.
436  */
438 {
439  return booleanObject(isPackageScope());
440 }
441 
442 
443 /**
444  * Return the Protected setting for a method object.
445  *
446  * @return .true if the method is protected. .false otherwise.
447  */
449 {
450  return isProtected() ? TheTrueObject : TheFalseObject;
451 }
452 
453 
454 /**
455  * Indicate if this is an abstract method
456  *
457  * @return .true if the method is abstract. .false otherwise.
458  */
460 {
461  return booleanObject(isAbstract());
462 }
463 
464 
465 /**
466  * Indicate if this method was defined as an attribute method
467  * (using ::attribute or ::method attribute)
468  *
469  * @return .true if the method is defined as an attribute.
470  * .false otherwise.
471  */
473 {
474  return booleanObject(isAttribute());
475 }
476 
477 
478 /**
479  * Indicate if this method was defined as a constant method
480  * (using ::constant)
481  *
482  * @return .true if the method is defined as an attribute.
483  * .false otherwise.
484  */
486 {
487  return booleanObject(isConstant());
488 }
489 
490 
491 /**
492  * Returns the defining class scope for a method. Returns .nil
493  * for any method not defined by a class scope.
494  *
495  * @return The scope class or .nil.
496  */
498 {
499  return resultOrNil(getScope());
500 }
501 
502 
503 /**
504  * Retrieve a string name for the method scope. If the scope is .nil,
505  * then ".NIL" is returned, otherwise the class name is used.
506  *
507  * @return A string name for the scope.
508  */
510 {
511  return (RexxObject *)scope == TheNilObject ? OREF_DOTNIL : scope->getId();
512 }
513 
514 
515 /**
516  * Set the entire set of method attributes with one call. Used
517  * during source compilation.
518  *
519  * @param _access The access setting.
520  * @param _protected The protected setting.
521  * @param _guarded The guarded setting.
522  */
523 void RexxMethod::setAttributes(AccessFlag _access, ProtectedFlag _protected, GuardFlag _guarded)
524 {
525  switch (_access)
526  {
527  case PRIVATE_SCOPE:
528  setPrivate();
529  break;
530 
531  case PACKAGE_SCOPE:
532  setPackageScope();
533  break;
534 
535  // covers PUBLIC and DEFAULT
536  default:
537  break;
538  }
539 
540  if (_protected == PROTECTED_METHOD)
541  {
542  setProtected();
543  }
544 
545  // both GUARDED and DEFAULT are guarded, so check for the reverse.
546  if (_guarded == UNGUARDED_METHOD)
547  {
548  setUnguarded();
549  }
550 }
551 
552 
554 /******************************************************************************/
555 /* Function: Flatten translated method into a buffer for storage into EA's etc*/
556 /******************************************************************************/
557 {
558  RexxEnvelope *envelope; /* envelope for flattening */
559  /* Get new envelope object */
560  envelope = new RexxEnvelope;
561  ProtectedObject p(envelope);
562  /* now pack up the envelope for */
563  /* saving. */
564  envelope->pack(this);
565  return envelope->getBuffer(); /* return the buffer */
566 }
567 
568 void *RexxMethod::operator new (size_t size)
569 /******************************************************************************/
570 /* Function: create a new method instance */
571 /******************************************************************************/
572 {
573  /* get a new method object */
574  RexxObject *newObj = new_object(size, T_Method);
575  return newObj; /* Initialize this new method */
576 }
577 
578 
579 /**
580  * Static method used for constructing new method objects in
581  * various contexts (such as the define method on the Class class).
582  *
583  * @param pgmname The name of the method we're creating.
584  * @param source The method source (either a string or an array).
585  * @param position The position used for reporting errors. This is the position
586  * of the source argument for the calling method context.
587  * @param parentScope
588  * The parent code we inherit routine scope from. This overrides
589  * anything that might be defined in single method code.
590  *
591  * @return The constructed method object.
592  */
593 RexxMethod *RexxMethod::newMethodObject(RexxString *pgmname, RexxObject *source, RexxObject *position, RexxSource *parentSource, bool isBlock)
594 {
595  // request this as an array. If not convertable, then we'll use it as a string
596  RexxArray *newSourceArray = source->requestArray();
597  ProtectedObject p_newSourceArray(newSourceArray);
598  /* couldn't convert? */
599  if (newSourceArray == (RexxArray *)TheNilObject)
600  {
601  /* get the string representation */
602  RexxString *sourceString = source->makeString();
603  ProtectedObject p(sourceString);
604  /* got back .nil? */
605  if (sourceString == (RexxString *)TheNilObject)
606  {
607  /* raise an error */
608  reportException(Error_Incorrect_method_no_method, OREF_positional, position);
609  }
610  /* wrap an array around the value */
611  newSourceArray = new_array(sourceString);
612  }
613  else /* have an array, make sure all */
614  {
615  /* is it single dimensional? */
616  if (newSourceArray->getDimension() != 1)
617  {
618  /* raise an error */
619  reportException(Error_Incorrect_method_noarray, OREF_positional, position);
620  }
621  /* element are strings. */
622  /* Make sure all elements in array */
623  for (size_t counter = 1; counter <= newSourceArray->size(); counter++)
624  {
625  /* Get element as string object */
626  RexxObject *item = newSourceArray ->get(counter);
627  RexxString *sourceString = (item == OREF_NULL) ? OREF_NULLSTRING : item->makeString();
628  ProtectedObject p(sourceString);
629  /* Did it convert? */
630  if (sourceString == (RexxString *)TheNilObject)
631  {
632  /* and report the error. */
634  }
635  else
636  {
637  /* itsa string add to source array */
638  newSourceArray ->put(sourceString, counter);
639  }
640  }
641  }
642  p_newSourceArray = newSourceArray;
643 
644  RexxMethod *result = new RexxMethod(pgmname, newSourceArray);
645  ProtectedObject p(result);
646  result->getSourceObject()->setIsBlock(isBlock);
647 
648  // if we've been provided with a scope, use it
649  if (parentSource == OREF_NULL)
650  {
651  // see if we have an active context and use the current source as the basis for the lookup
653  if (currentContext != OREF_NULL)
654  {
655  parentSource = currentContext->getSourceObject();
656  }
657  }
658 
659  // if there is a parent source, then merge in the scope information
660  if (parentSource != OREF_NULL)
661  {
662  result->getSourceObject()->inheritSourceContext(parentSource);
663  }
664 
665  return result;
666 }
667 
668 
670  RexxObject **init_args, /* subclass init arguments */
671  size_t argCount, /* number of posit arguments passed */
672  size_t named_argCount) /* number of named arguments passed */
673 /******************************************************************************/
674 /* Function: Create a new method from REXX code contained in a string or an */
675 /* array */
676 /******************************************************************************/
677 {
678  // this method is defined as an instance method, but this is actually attached
679  // to a class object instance. Therefore, any use of the this pointer
680  // will be touching the wrong data. Use the classThis pointer for calling
681  // any methods on this object from this method.
682  RexxClass *classThis = (RexxClass *)this;
683  classThis->checkAbstract(); // ooRexx5
684 
685  RexxObject *pgmname; /* method name */
686  RexxObject *_source; /* Array or string object */
687  RexxMethod *newMethod; /* newly created method object */
688  RexxObject *option = OREF_NULL;
689  size_t initCount = 0; /* count of arguments we pass along */
690 
691  /* break up the arguments */
692 
693  RexxClass::processNewArgs(init_args, argCount, &init_args, &initCount, 2, (RexxObject **)&pgmname, (RexxObject **)&_source);
694  /* get the method name as a string */
695  RexxString *nameString = stringArgument(pgmname, OREF_positional, ARG_ONE);
696  ProtectedObject p_nameString(nameString);
697  requiredArgument(_source, OREF_positional, ARG_TWO); /* make sure we have the second too */
698 
699  RexxSource *sourceContext = OREF_NULL;
700  // retrieve extra parameter if exists
701  if (initCount != 0)
702  {
703  RexxClass::processNewArgs(init_args, initCount, &init_args, &initCount, 1, (RexxObject **)&option, NULL);
704  if (isOfClass(Method, option))
705  {
706  sourceContext = ((RexxMethod *)option)->getSourceObject();
707  }
708  else if (isOfClass(Routine, option))
709  {
710  sourceContext = ((RoutineClass *)option)->getSourceObject();
711  }
712  else if (isOfClass(Package, option))
713  {
714  sourceContext = ((PackageClass *)option)->getSourceObject();
715  }
716  else
717  {
718  // this must be a string (or convertable) and have a specific value
719  option = option->requestString();
720  ProtectedObject p(option);
721  if (option == TheNilObject)
722  {
723  RexxString *info = new_string("Method, Routine, Package, or String object");
724  ProtectedObject p(info);
726  }
727  // default given? set option to NULL (see code below)
728  if (!((RexxString *)option)->strCaselessCompare("PROGRAMSCOPE"))
729  {
730  RexxString *info = new_string("\"PROGRAMSCOPE\", Method, Routine, Package object");
731  ProtectedObject p(info);
732  reportException(Error_Incorrect_call_list, OREF_NEW, OREF_positional, IntegerThree, info, option);
733  }
734  }
735  }
736 
737  bool isBlock = false;
738  // retrieve extra parameter if exists
739  if (initCount != 0)
740  {
741  RexxClass::processNewArgs(init_args, initCount, &init_args, &initCount, 1, (RexxObject **)&option, NULL);
742  isBlock = option->truthValue(Error_Logical_value_method);
743  }
744 
745  /* go create a method */
746  newMethod = RexxMethod::newMethodObject(nameString, _source, IntegerTwo, sourceContext, isBlock);
747  ProtectedObject p(newMethod);
748  /* Give new object its behaviour */
749  newMethod->setBehaviour(classThis->getInstanceBehaviour());
750  if (classThis->hasUninitDefined()) /* does object have an UNINT method */
751  {
752  newMethod->hasUninit(); /* Make sure everyone is notified. */
753  }
754  /* now send an INIT message */
755  newMethod->sendMessage(OREF_INIT, init_args, initCount, named_argCount);
756  return newMethod; /* return the new method */
757 }
758 
759 
761 /******************************************************************************/
762 /* Function: Create a method from a fully resolved file name */
763 /******************************************************************************/
764 {
765  // this method is defined on the object class, but this is actually attached
766  // to a class object instance. Therefore, any use of the this pointer
767  // will be touching the wrong data. Use the classThis pointer for calling
768  // any methods on this object from this method.
769  RexxClass *classThis = (RexxClass *)this;
770  classThis->checkAbstract(); // ooRexx5
771 
772  /* get the method name as a string */
773  filename = stringArgument(filename, OREF_positional, ARG_ONE);
774  ProtectedObject p1(filename);
775  /* create a source object */
776  RexxMethod *newMethod = new RexxMethod(filename);
777  ProtectedObject p2(newMethod);
778  newMethod->setScope((RexxClass *)TheNilObject);
779  /* Give new object its behaviour */
780  newMethod->setBehaviour(classThis->getInstanceBehaviour());
781  if (classThis->hasUninitDefined()) /* does object have an UNINT method */
782  {
783  newMethod->hasUninit(); /* Make sure everyone is notified. */
784  }
785  /* now send an INIT message */
786  newMethod->sendMessage(OREF_INIT);
787  return newMethod;
788 }
789 
790 
792  RexxBuffer *buffer, /* buffer containing the method */
793  char *startPointer, /* first character of the method */
794  size_t length) // length of the data to restore
795 /******************************************************************************/
796 /* Function: Unflatten a translated method. Passed a buffer object containing*/
797 /* the method */
798 /******************************************************************************/
799 {
800  /* Get new envelope object */
801  RexxEnvelope *envelope = new RexxEnvelope;
802  ProtectedObject p(envelope);
803  /* now puff up the method object */
804  envelope->puff(buffer, startPointer, length);
805  /* The receiver object is an envelope*/
806  /* whose receiver is the actual */
807  /* method object we're restoring */
808  return (RexxMethod *)envelope->getReceiver();
809 }
810 
811 
812 /**
813  * Run this code as a method invocation.
814  *
815  * @param activity The current activity.
816  * @param method The method we're invoking.
817  * @param receiver The method target object.
818  * @param msgname The name the method was invoked under.
819  * @param argCount The count of positional arguments.
820  * @param named_argCount The count of named arguments.
821  * @param arguments The argument pointer.
822  * @param result The returned result.
823  */
824 void BaseCode::run(RexxActivity *activity, RexxMethod *method, RexxObject *receiver, RexxString *msgname, RexxObject **arguments, size_t argCount, size_t named_argCount, ProtectedObject &result)
825 {
826  // The subcasses decide which of run and call are allowed
828 }
829 
830 
831 /**
832  * Invoke a code element as a call target. This form is generally
833  * only used for calls from Rexx code to Rexx code or for top level
834  * program invocation.
835  *
836  * @param activity The activity we're running under.
837  * @param msgname The name of the program or name used to invoke the routine.
838  * @param arguments The arguments to the method.
839  * @param argcount The count of positional arguments.
840  * @param named_argcount The count of named arguments.
841  * @param ct The call context.
842  * @param env The current address environment.
843  * @param context The type of call being made (program call, internal call, interpret,
844  * etc.)
845  * @param result The returned result.
846  */
847 void BaseCode::call(RexxActivity *activity, RoutineClass *routine, RexxString *msgname, RexxObject **arguments, size_t argcount, size_t named_argcount, RexxString *ct, RexxString *env, int context, ProtectedObject &result)
848 {
849  // the default for this is the simplified call. This is used by Rexx code to make calls to
850  // both Rexx programs and native routines, so the polymorphism simplifies the processing.
851  call(activity, routine, msgname, arguments, argcount, named_argcount, result);
852 }
853 
854 
855 /**
856  * Simplified call form used for calling from Rexx code to native code.
857  *
858  * @param activity The current activity.
859  * @param msgname The name of the call.
860  * @param arguments the call arguments.
861  * @param argcount The count of positional arguments.
862  * @param named_argcount The count of named arguments.
863  * @param result The returned result.
864  */
865 void BaseCode::call(RexxActivity *activity, RoutineClass *routine, RexxString *msgname, RexxObject **arguments, size_t argcount, size_t named_argcount, ProtectedObject &result)
866 {
867  // The subcasses decide which of run and call are allowed
869 }
870 
871 
872 /**
873  * Return source informaton for a BaseCode object. If not
874  * representing an element in a source file, this returns
875  * an empty array.
876  *
877  * @return A null array.
878  */
880 {
881  /* this is always a null array */
882  return (RexxArray *)TheNullArray->copy();
883 }
884 
885 
886 /**
887  * Set the security manager in the code source context.
888  *
889  * @param manager The new security manager.
890  *
891  * @return Returns true if the manager could be set. Non-Rexx code objects
892  * just return false unconditionally.
893  */
895 /******************************************************************************/
896 /* Function: Associate a security manager with a method's source */
897 /******************************************************************************/
898 {
899  // the default is just to return a failure
900  return TheFalseObject;
901 }
902 
903 
904 /**
905  * Retrieve the source object associated with a code object.
906  *
907  * @return
908  */
910 {
911  return OREF_NULL;
912 }
913 
914 
915 /**
916  * Default class resolution...which only looks in the environment
917  * or .local.
918  *
919  * @param className The target class name.
920  *
921  * @return The resolved class object, or OREF_NULL if this is not known.
922  */
924 {
925  // the interpreter class handles the default lookups
926  return Interpreter::findClass(className);
927 }
928 
929 
930 // ooRexx5 uses setPackageObject
931 /**
932  * Set a source object into a code context. The default
933  * implementation is just to return the same object without
934  * setting a source. This is used mostly for attaching a source
935  * context to native code methods and routines defined on
936  * directives.
937  *
938  * @param s The new source object.
939  *
940  * @return Either the same object, or a new copy of the code object.
941  */
943 {
944  return this; // this is just a nop
945 }
946 
947 
948 /**
949  * Retrieve the package associated with a code object. Returns
950  * OREF_NULL if this code object doesn't have a source.
951  *
952  * @return The associated package, or OREF_NULL.
953  */
955 {
957  if (source != OREF_NULL)
958  {
959  return source->getPackage();
960  }
961 
962  return OREF_NULL;
963 }
964 
965 
966 /**
967  * Create a method from an external library source.
968  *
969  * @param name The method name.
970  *
971  * @return The resolved method object, or OREF_NULL if unable to
972  * load the routine.
973  */
975 {
976  name = stringArgument(name, OREF_positional, "name");
977  ProtectedObject p1(name);
978  descriptor = stringArgument(descriptor, OREF_positional, "descriptor");
979  ProtectedObject p2(descriptor);
980  /* convert external into words */
981  RexxArray *_words = StringUtil::words(descriptor->getStringData(), descriptor->getLength());
982  ProtectedObject p(_words);
983  // "LIBRARY libbar [foo]"
984  if (((RexxString *)(_words->get(1)))->strCompare(CHAR_LIBRARY))
985  {
986  RexxString *library = OREF_NULL;
987  // the default entry point name is the internal name
988  RexxString *entry = name;
989 
990  // full library with entry name version?
991  if (_words->size() == 3)
992  {
993  library = (RexxString *)_words->get(2);
994  entry = (RexxString *)_words->get(3);
995  }
996  else if (_words->size() == 2)
997  {
998  library = (RexxString *)_words->get(2);
999  }
1000  else // wrong number of tokens
1001  {
1002  /* this is an error */
1004  }
1005  /* create a new native method */
1006  RexxNativeCode *nmethod = PackageManager::loadMethod(library, entry);
1007  // raise an exception if this entry point is not found.
1008  if (nmethod == OREF_NULL)
1009  {
1010  return (RexxMethod *)TheNilObject;
1011  }
1012  /* turn into a real method object */
1013  return new RexxMethod(name, nmethod);
1014  }
1015  else
1016  {
1017  /* unknown external type */
1019  }
1020  return OREF_NULL;
1021 }
1022 
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Method
AccessFlag
Definition: MethodClass.hpp:73
@ PRIVATE_SCOPE
Definition: MethodClass.hpp:76
@ PACKAGE_SCOPE
Definition: MethodClass.hpp:77
GuardFlag
Definition: MethodClass.hpp:59
@ UNGUARDED_METHOD
Definition: MethodClass.hpp:62
ProtectedFlag
Definition: MethodClass.hpp:66
@ PROTECTED_METHOD
Definition: MethodClass.hpp:68
#define TheRexxPackage
Definition: RexxCore.h:189
RexxObject * resultOrNil(RexxInternalObject *o)
Definition: RexxCore.h:484
RexxObject * booleanObject(bool v)
Definition: RexxCore.h:496
#define OREF_NULL
Definition: RexxCore.h:61
#define IntegerThree
Definition: RexxCore.h:202
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:315
#define TheNullArray
Definition: RexxCore.h:193
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
const int ARG_TWO
Definition: RexxCore.h:84
#define IntegerTwo
Definition: RexxCore.h:201
#define isOfClass(t, r)
Definition: RexxCore.h:224
#define TheNilObject
Definition: RexxCore.h:191
#define TheFalseObject
Definition: RexxCore.h:195
const int ARG_ONE
Definition: RexxCore.h:83
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define Error_Logical_value_method
#define Error_Translation_bad_external
#define Error_Incorrect_method_no_method
#define Error_Interpretation
#define Error_Incorrect_method_nostring_inarray
#define Error_Incorrect_method_argType
#define Error_Incorrect_call_list
#define Error_Incorrect_method_noarray
#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 CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:503
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
RexxString * new_string(const char *s, stringsize_t l)
static RexxActivity *volatile currentActivity
virtual BaseCode * setSourceObject(RexxSource *s)
virtual RexxArray * getSource()
virtual void run(RexxActivity *, RexxMethod *, RexxObject *, RexxString *, RexxObject **, size_t, size_t, ProtectedObject &)
virtual RexxSource * getSourceObject()
virtual PackageClass * getPackage()
virtual RexxObject * setSecurityManager(RexxObject *manager)
virtual RexxClass * findClass(RexxString *className)
virtual void call(RexxActivity *, RoutineClass *, RexxString *, RexxObject **, size_t, size_t, RexxString *, RexxString *, int, ProtectedObject &)
PackageClass * getPackage()
RexxArray * source()
RexxString * executableName
RexxClass * findClass(RexxString *className)
Definition: MethodClass.cpp:87
BaseCode * code
RexxSource * getSourceObject()
BaseExecutable * setSourceObject(RexxSource *s)
static RexxClass * findClass(RexxString *className)
static RexxNativeMethod * loadMethod(RexxString *packageName, RexxString *methodName)
RexxSource * getSourceObject()
RexxActivation * getCurrentRexxFrame()
size_t getDimension()
Definition: ArrayClass.cpp:693
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxString * makeString(RexxString *, RexxString *)
size_t size()
Definition: ArrayClass.hpp:202
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
static void processNewArgs(RexxObject **, size_t, RexxObject ***, size_t *, size_t, RexxObject **, RexxObject **)
void checkAbstract()
RexxBehaviour * getInstanceBehaviour()
Definition: ClassClass.hpp:135
bool hasUninitDefined()
Definition: ClassClass.hpp:125
RexxBuffer * pack(RexxObject *)
void puff(RexxBuffer *, char *, size_t length)
RexxSmartBuffer * getBuffer()
RexxObject * getReceiver()
void setBehaviour(RexxBehaviour *b)
RexxMethod * newRexx(RexxObject **, size_t, size_t)
static void createInstance()
Definition: MethodClass.cpp:74
void liveGeneral(int reason)
RexxSmartBuffer * saveMethod()
RexxObject * isPrivateRexx()
RexxObject * setPrivateRexx()
RexxObject * isAttributeRexx()
static RexxMethod * restore(RexxBuffer *, char *, size_t length)
RexxObject * setUnguardedRexx()
RexxObject * setProtectedRexx()
RexxObject * setSecurityManager(RexxObject *)
RexxClass * scope
RexxObject * isProtectedRexx()
RexxObject * isAbstractRexx()
void run(RexxActivity *, RexxObject *, RexxString *, RexxObject **, size_t, size_t, ProtectedObject &)
RexxMethod * newFileRexx(RexxString *)
RexxObject * getScopeRexx()
void flatten(RexxEnvelope *)
RexxObject * isGuardedRexx()
RexxMethod * loadExternalMethod(RexxString *name, RexxString *descriptor)
static RexxClass * classInstance
void setScope(RexxClass *)
RexxObject * isPackageRexx()
static RexxMethod * newMethodObject(RexxString *, RexxObject *, RexxObject *, RexxSource *a, bool isBlock=false)
void setAttributes(AccessFlag access, ProtectedFlag _protected, GuardFlag _guarded)
RexxString * getScopeName()
RexxObject * isConstantRexx()
void live(size_t)
RexxObject * setGuardedRexx()
RexxMethod * newScope(RexxClass *)
RexxMethod(RexxString *name, BaseCode *_code)
RexxString * makeString()
RexxArray * requestArray()
RexxObject * copy()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
RexxString * requestString()
bool truthValue(int)
RexxCode * generateCode(bool isMethod)
void setIsBlock(bool b)
Definition: SourceFile.hpp:145
void inheritSourceContext(RexxSource *source)
size_t getLength()
const char * getStringData()
static RexxArray * words(const char *data, size_t length)