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