PackageClass.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 PackageClass.cpp */
40 /* */
41 /* Primitive Package class */
42 /* */
43 /******************************************************************************/
44 #include "RexxCore.h"
45 #include "ArrayClass.hpp"
46 #include "SourceFile.hpp"
47 #include "DirectoryClass.hpp"
48 #include "ProtectedObject.hpp"
49 #include "PackageClass.hpp"
50 #include "RoutineClass.hpp"
51 #include "InterpreterInstance.hpp"
52 #include "PackageManager.hpp"
53 
54 
55 // singleton class instance
57 
58 
59 /**
60  * Create initial class object at bootstrap time.
61  */
63 {
64  CLASS_CREATE(Package, "Package", RexxClass);
65 }
66 
67 
68 void *PackageClass::operator new (size_t size)
69 /******************************************************************************/
70 /* Function: create a new method instance */
71 /******************************************************************************/
72 {
73  /* get a new method object */
74  return new_object(size, T_Package);
75 }
76 
77 
79 /******************************************************************************/
80 /* Function: Initialize a method object */
81 /******************************************************************************/
82 {
83  OrefSet(this, this->source, s); /* store the code */
84 }
85 
86 
87 void PackageClass::live(size_t liveMark)
88 /******************************************************************************/
89 /* Function: Normal garbage collection live marking */
90 /******************************************************************************/
91 {
92  memory_mark(this->source);
93  memory_mark(this->objectVariables);
94 }
95 
96 void PackageClass::liveGeneral(int reason)
97 /******************************************************************************/
98 /* Function: Generalized object marking */
99 /******************************************************************************/
100 {
102  memory_mark_general(this->objectVariables);
103 }
104 
106 /******************************************************************************/
107 /* Function: Flatten an object */
108 /******************************************************************************/
109 {
111 
112  flatten_reference(newThis->source, envelope);
113  flatten_reference(newThis->objectVariables, envelope);
114 
116 }
117 
118 
119 /**
120  * Get the program name of the package
121  *
122  * @return The name of the original source package.
123  */
125 {
126  return source->getProgramName();
127 }
128 
129 
130 /**
131  * Return all of the source lines for the package, as an array.
132  *
133  * @return The entire array of source lines.
134  */
136 {
137  return source->extractSource();
138 }
139 
140 
141 /**
142  * Extract a specific line from the program source.
143  *
144  * @param n The line position.
145  *
146  * @return The extracted line.
147  */
149 {
150  return source->get(n);
151 }
152 
153 
154 /**
155  * Extract a specific line from the program source.
156  *
157  * @param n The line position.
158  *
159  * @return The extracted line.
160  */
162 {
163  // the starting position isn't optional
164  size_t n = positionArgument(position, ARG_ONE);
165  return source->get(n);
166 }
167 
168 
169 /**
170  * Get the number of source lines in the package
171  *
172  * @return the count of lines
173  */
175 {
176  return new_integer(source->sourceSize());
177 }
178 
179 
180 /**
181  * Retrieve all classes defined by this package.
182  *
183  * @return A directory of all of the classes defined by this package.
184  */
186 {
187  // we need to return a copy. The source might necessarily have any of these,
188  // so we return an empty directory if it's not there.
190  if (classes != OREF_NULL)
191  {
192  return (RexxDirectory *)classes->copy();
193  }
194  else
195  {
196  return new_directory();
197  }
198 }
199 
200 
201 /**
202  * Retrieve all public classes defined by this package.
203  *
204  * @return A directory of the public classes.
205  */
207 {
208  // we need to return a copy. The source might necessarily have any of these,
209  // so we return an empty directory if it's not there.
211  if (classes != OREF_NULL)
212  {
213  return (RexxDirectory *)classes->copy();
214  }
215  else
216  {
217  return new_directory();
218  }
219 }
220 
221 
222 /**
223  * Retrieve all of the classes imported into this package from
224  * other packages.
225  *
226  * @return A directory of the imported classes.
227  */
229 {
230  // we need to return a copy. The source might necessarily have any of these,
231  // so we return an empty directory if it's not there.
233  if (classes != OREF_NULL)
234  {
235  return (RexxDirectory *)classes->copy();
236  }
237  else
238  {
239  return new_directory();
240  }
241 }
242 
243 
244 /**
245  * Get a list of all routines defined by this package.
246  *
247  * @return A directory of the routines.
248  */
250 {
251  // we need to return a copy. The source might necessarily have any of these,
252  // so we return an empty directory if it's not there.
254  if (routines != OREF_NULL)
255  {
256  return (RexxDirectory *)routines->copy();
257  }
258  else
259  {
260  return new_directory();
261  }
262 }
263 
264 
265 /**
266  * Return a directory of the Public routines defined by this
267  * package.
268  *
269  * @return A directory holding the public routines.
270  */
272 {
273  // we need to return a copy. The source might necessarily have any of these,
274  // so we return an empty directory if it's not there.
276  if (routines != OREF_NULL)
277  {
278  return (RexxDirectory *)routines->copy();
279  }
280  else
281  {
282  return new_directory();
283  }
284 }
285 
286 
287 /**
288  * Get the directory of routines that have been imported into
289  * to this package form other packages.
290  *
291  * @return A directory of the imported routines.
292  */
294 {
295  // we need to return a copy. The source might necessarily have any of these,
296  // so we return an empty directory if it's not there.
298  if (routines != OREF_NULL)
299  {
300  return (RexxDirectory *)routines->copy();
301  }
302  else
303  {
304  return new_directory();
305  }
306 }
307 
308 
309 /**
310  * Get all of the unattached methods defined in this package.
311  *
312  * @return A directory of the unattached methods.
313  */
315 {
316  // we need to return a copy. The source might necessarily have any of these,
317  // so we return an empty directory if it's not there.
318  RexxDirectory *methods = source->getMethods();
319  if (methods != OREF_NULL)
320  {
321  return (RexxDirectory *)methods->copy();
322  }
323  else
324  {
325  return new_directory();
326  }
327 }
328 
329 
330 /**
331  * Get all of the packages that have been added to this package
332  * context.
333  *
334  * @return An array of the added packages.
335  */
337 {
338  RexxList *packages = source->getPackages();
339  if (packages != OREF_NULL)
340  {
341  return packages->makeArray();
342  }
343  else
344  {
345  return new_array((size_t)0);
346  }
347 
348 }
349 
350 
351 /**
352  * Load a package in a source context.
353  *
354  * @param name The target package name.
355  * @param s The optional source lines for the package, as an array.
356  *
357  * @return The loaded package object.
358  */
360 {
361  // make sure we have a valid name and delegate to the source object
362  name = stringArgument(name, OREF_positional, 1);
363  ProtectedObject p(name);
364  // if no source provided, this comes from a file
365  if (s == OREF_NULL)
366  {
368  }
369  else
370  {
371  s = arrayArgument(s, OREF_positional, OREF_SOURCE);
372  ProtectedObject p(s);
374  }
375 }
376 
377 
378 /**
379  * Load a package in a source context.
380  *
381  * @param name The target package name.
382  *
383  * @return The loaded package object.
384  */
386 {
387  classArgument(package, ThePackageClass, OREF_positional, OREF_PACKAGE);
388  source->addPackage(package);
389  return this;
390 }
391 
392 
393 /**
394  * Add a routine to this package's private routine list.
395  *
396  * @param routine The routine to add.
397  *
398  * @return The target package object.
399  */
401 {
402  name = stringArgument(name, OREF_positional, "name");
403  ProtectedObject p(name);
404  classArgument(routine, TheRoutineClass, OREF_positional, OREF_ROUTINE);
405  source->addInstalledRoutine(name, routine, false);
406  return this;
407 }
408 
409 
410 /**
411  * Add a routine to this package's public routine list.
412  *
413  * @param routine The routine to add.
414  *
415  * @return The target package object.
416  */
418 {
419  name = stringArgument(name, OREF_positional, "name");
420  ProtectedObject p(name);
421  classArgument(routine, TheRoutineClass, OREF_positional, OREF_ROUTINE);
422  source->addInstalledRoutine(name, routine, true);
423  return this;
424 }
425 
426 
427 /**
428  * Add a class to this package's class list.
429  *
430  * @param clazz The class to add.
431  *
432  * @return The target package object.
433  */
435 {
436  name = stringArgument(name, OREF_positional, "name");
437  ProtectedObject p(name);
438  classArgument(clazz, TheClassClass, OREF_positional, OREF_CLASS);
439  source->addInstalledClass(name, clazz, false);
440  return this;
441 }
442 
443 
444 /**
445  * Add a class to this package's public class list.
446  *
447  * @param clazz The class to add.
448  *
449  * @return The target package object.
450  */
452 {
453  name = stringArgument(name, OREF_positional, "name");
454  ProtectedObject p(name);
455  classArgument(clazz, TheClassClass, OREF_positional, OREF_CLASS);
456  source->addInstalledClass(name, clazz, true);
457  return this;
458 }
459 
460 
461 /**
462  * Resolve a class in the context of a package.
463  *
464  * @param name The required class name.
465  *
466  * @return The resolved class object.
467  */
469 {
470  RexxClass *classObj = source->findClass(name);
471  // we need to filter this to always return a class object
472  if (classObj != OREF_NULL && classObj->isInstanceOf(TheClassClass))
473  {
474  return classObj;
475  }
476  return OREF_NULL;
477 }
478 
479 
480 /**
481  * Resolve a class in the context of a package.
482  *
483  * @param name The required class name.
484  *
485  * @return The resolved class object.
486  */
488 {
489  name = stringArgument(name, OREF_positional, "name");
490  RexxClass *cls = source->findClass(name);
491  if (cls == OREF_NULL)
492  {
493  return (RexxClass *)TheNilObject;
494  }
495  return cls;
496 }
497 
498 
499 /**
500  * Resolve a routine in the context of a package.
501  *
502  * @param name The required routine name.
503  *
504  * @return The resolved routine object.
505  */
507 {
508  return source->findRoutine(name);
509 }
510 
511 
512 /**
513  * Resolve a routine in the context of a package.
514  *
515  * @param name The required routine name.
516  *
517  * @return The resolved routine object.
518  */
520 {
521  name = stringArgument(name, OREF_positional, "name");
522  RoutineClass *routine = findRoutine(name);
523  if (routine == OREF_NULL)
524  {
525  return (RoutineClass *)TheNilObject;
526  }
527  return routine;
528 }
529 
530 
531 /**
532  * Locate a program using the target package context.
533  *
534  * @param name The target name.
535  *
536  * @return The fully resolved filename, or .nil if no file was found.
537  */
539 {
540  RexxString *target = stringArgument(name, OREF_positional, "name");
541  ProtectedObject p(target);
542 
544  RexxString *program = activity->resolveProgramName(target, OREF_NULL, OREF_NULL);
545  if (program == OREF_NULL) return TheNilObject; //not found
546  return program;
547 }
548 
549 
550 /**
551  * Set a security manager on a package.
552  *
553  * @param manager The security manager object.
554  *
555  * @return The security manager object.
556  */
558 {
559  source->setSecurityManager(manager);
560  return TheTrueObject;
561 }
562 
563 
565  RexxObject **init_args, /* subclass init arguments */
566  size_t argCount, /* number of arguments passed */
567  size_t named_argCount)
568 /******************************************************************************/
569 /* Function: Create a new packag from REXX code contained in a file or an */
570 /* array */
571 /******************************************************************************/
572 {
573  // this method is defined on the object class, but this is actually attached
574  // to a class object instance. Therefore, any use of the this pointer
575  // will be touching the wrong data. Use the classThis pointer for calling
576  // any methods on this object from this method.
577  RexxClass *classThis = (RexxClass *)this;
578  classThis->checkAbstract(); // ooRexx
579 
580  RexxObject *pgmname; /* method name */
581  RexxObject *_source; /* Array or string object */
582  size_t initCount = 0; /* count of arguments we pass along */
584  InterpreterInstance *instance = activity->getInstance();
585 
586  /* break up the arguments */
587 
588  RexxClass::processNewArgs(init_args, argCount, &init_args, &initCount, 2, (RexxObject **)&pgmname, (RexxObject **)&_source);
589 
590  PackageClass *package = OREF_NULL;
591 
592  /* get the package name as a string */
593  RexxString *nameString = stringArgument(pgmname, OREF_positional, "name");
594  ProtectedObject p_nameString(nameString);
595  if (_source == OREF_NULL)
596  {
597  // if no directly provided source, resolve the name in the global context and have the instance
598  // load the file.
599  RexxString *resolvedName = instance->resolveProgramName(nameString, OREF_NULL, OREF_NULL);
600  ProtectedObject n(resolvedName);
601  package = instance->loadRequires(activity, nameString, resolvedName);
602  }
603  else
604  {
605  // add this to the instance context
606  RexxArray *sourceArray = arrayArgument(_source, OREF_positional, OREF_SOURCE);
607  ProtectedObject p(sourceArray);
608  package = instance->loadRequires(activity, nameString, sourceArray);
609  }
610 
611  ProtectedObject p_package(package);
612 
613  /* Give new object its behaviour */
614  package->setBehaviour(classThis->getInstanceBehaviour());
615  if (classThis->hasUninitDefined())
616  {
617  package->hasUninit(); /* Make sure everyone is notified. */
618  }
619  /* now send an INIT message */
620  package->sendMessage(OREF_INIT, init_args, initCount, named_argCount);
621  return package; /* return the new method */
622 }
623 
624 
625 /**
626  * Dynamically load a library package
627  *
628  * @param name The required package name.
629  *
630  * @return True if the package was loaded and resolved, false if
631  * the package could not be loaded.
632  */
634 {
635  name = stringArgument(name, OREF_positional, "name");
636  ProtectedObject p(name);
637  // have we already loaded this package?
638  // may need to bootstrap it up first.
639  LibraryPackage *package = PackageManager::loadLibrary(name);
640  return package == NULL ? TheFalseObject : TheTrueObject;
641 }
642 
643 
644 /**
645  * Return the package-defined digits setting
646  *
647  * @return The digits setting defined for this package.
648  */
650 {
651  return new_integer(source->getDigits());
652 }
653 
654 
655 /**
656  * Return the package-defined default fuzz setting.
657  *
658  * @return The package defined fuzz setting.
659  */
661 {
662  return new_integer(source->getFuzz());
663 }
664 
665 
666 /**
667  * Return the package-defined default form setting.
668  *
669  * @return The default form setting.
670  */
672 {
673  return source->getForm() == Numerics::FORM_SCIENTIFIC ? OREF_SCIENTIFIC : OREF_ENGINEERING;
674 }
675 
676 
677 /**
678  * Return the package-defined default trace setting.
679  *
680  * @return The string-formatted trace setting.
681  */
683 {
684  return source->getTrace();
685 }
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
@ T_Package
RexxDirectory * new_directory()
RexxInteger * new_integer(wholenumber_t v)
#define ThePackageClass
Definition: RexxCore.h:163
#define OREF_NULL
Definition: RexxCore.h:61
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:315
#define TheClassClass
Definition: RexxCore.h:156
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
#define TheNilObject
Definition: RexxCore.h:191
void classArgument(RexxObject *object, RexxClass *clazz, RexxString *kind, RexxString *name)
Definition: RexxCore.h:440
#define TheRoutineClass
Definition: RexxCore.h:162
const int ARG_ONE
Definition: RexxCore.h:83
RexxArray * arrayArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:395
#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
stringsize_t positionArgument(RexxObject *argument, size_t position)
static RexxActivity *volatile currentActivity
RexxString * resolveProgramName(RexxString *name, RexxString *dir, RexxString *ext)
static const bool FORM_SCIENTIFIC
Definition: Numerics.hpp:76
RexxString * getSourceLineRexx(RexxObject *)
RexxString * getSourceLine(size_t)
RexxObject * loadLibrary(RexxString *name)
RexxObject * addClass(RexxString *name, RexxClass *clazz)
RexxObject * findProgramRexx(RexxObject *name)
RexxArray * getImportedPackages()
RexxObject * form()
RexxObject * addPublicClass(RexxString *name, RexxClass *clazz)
RexxObject * trace()
void flatten(RexxEnvelope *)
RexxObject * digits()
RoutineClass * findRoutine(RexxString *name)
RexxDirectory * getImportedRoutines()
RexxClass * findClassRexx(RexxString *name)
RexxDirectory * getRoutines()
RexxDirectory * getMethods()
PackageClass(RexxSource *source)
PackageClass * loadPackage(RexxString *name, RexxArray *source)
RexxObject * addPackage(PackageClass *package)
RoutineClass * findRoutineRexx(RexxString *name)
RexxSource * source
RexxObject * fuzz()
RexxDirectory * getClasses()
RexxObject * addRoutine(RexxString *name, RoutineClass *routine)
RexxDirectory * getPublicClasses()
RexxString * getName()
static RexxClass * classInstance
PackageClass * newRexx(RexxObject **init_args, size_t argCount, size_t named_argCount)
RexxClass * findClass(RexxString *name)
RexxArray * getSource()
RexxInteger * getSourceSize()
RexxObject * setSecurityManager(RexxObject *)
RexxObject * addPublicRoutine(RexxString *name, RoutineClass *routine)
RexxDirectory * getImportedClasses()
static void createInstance()
void liveGeneral(int reason)
RexxDirectory * getPublicRoutines()
void live(size_t)
InterpreterInstance * getInstance()
RexxString * resolveProgramName(RexxString *, RexxString *, RexxString *)
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
RexxObject * copy()
RexxArray * makeArray()
Definition: ListClass.cpp:873
bool isInstanceOf(RexxClass *)
RexxDirectory * getImportedClasses()
Definition: SourceFile.hpp:406
PackageClass * loadRequires(RexxActivity *activity, RexxString *target)
RexxDirectory * getInstalledPublicRoutines()
Definition: SourceFile.hpp:408
RexxArray * extractSource(SourceLocation &)
RexxString * getProgramName()
Definition: SourceFile.hpp:301
void setSecurityManager(RexxObject *manager)
Definition: SourceFile.hpp:379
bool getForm()
Definition: SourceFile.hpp:413
RexxDirectory * getInstalledPublicClasses()
Definition: SourceFile.hpp:405
size_t getDigits()
Definition: SourceFile.hpp:412
RexxDirectory * getMethods()
Definition: SourceFile.hpp:305
void addInstalledRoutine(RexxString *name, RoutineClass *routineObject, bool publicRoutine)
size_t getFuzz()
Definition: SourceFile.hpp:414
RoutineClass * findRoutine(RexxString *)
void addInstalledClass(RexxString *name, RexxClass *classObject, bool publicClass)
size_t sourceSize()
Definition: SourceFile.cpp:783
RexxDirectory * getInstalledRoutines()
Definition: SourceFile.hpp:407
RexxDirectory * getImportedRoutines()
Definition: SourceFile.hpp:409
RexxString * getTrace()
Definition: SourceFile.hpp:417
RexxDirectory * getInstalledClasses()
Definition: SourceFile.hpp:404
RexxList * getPackages()
Definition: SourceFile.hpp:411
RexxString * get(size_t)
Definition: SourceFile.cpp:815
RexxClass * findClass(RexxString *)
void addPackage(PackageClass *package)