LibraryPackage.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.ibm.com/developerworks/oss/CPLv1.0.htm */
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 LibraryPackage management */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "LibraryPackage.hpp"
47 #include "PackageManager.hpp"
48 #include "Interpreter.hpp"
49 #include "RexxNativeCode.hpp"
50 #include "DirectoryClass.hpp"
51 #include "RoutineClass.hpp"
52 #include "ProtectedObject.hpp"
53 
54 /**
55  * Create a new LibraryPackage object instance.
56  *
57  * @param size Size of the object.
58  *
59  * @return Pointer to new object storage.
60  */
61 void *LibraryPackage::operator new(size_t size)
62 {
63  return new_object(size, T_LibraryPackage);
64 }
65 
66 
67 /**
68  * Constructor for a loaded package.
69  *
70  * @param n Name of the library associated with this package. This is
71  * also the name used to load the library when requested.
72  */
74 {
75  OrefSet(this, libraryName, n);
76 }
77 
78 /**
79  * Constructor for a loaded package.
80  *
81  * @param n Name of the library associated with this package. This is
82  * also the name used to load the library when requested.
83  * @param m The package manager that orchestrates the loading operations.
84  * @param p The packag table attached to this package name.
85  */
87 {
88  OrefSet(this, libraryName, n);
89  ProtectedObject p2(this);
90  // store the registered package entry
91  package = p;
92  // this is an internal package.
93  internal = true;
94 }
95 
96 /**
97  * Normal live marking.
98  */
99 void LibraryPackage::live(size_t liveMark)
100 {
104 }
105 
106 /**
107  * Generalized live marking.
108  */
110 {
114 }
115 
116 
117 /**
118  * Perform the initial loading of a package. The loading
119  * process involves resolving the external library and
120  * attempting to resolve a Rexx package exporter routine
121  * in the library. If the library loads, but does not have
122  * the package exporter function, this is a classic library.
123  *
124  * If we do find a package exporter, then we can load all of
125  * the routines immediately. Method loads are deferred until
126  * the first request.
127  *
128  * @param manager The package manager we're attached to.
129  *
130  * @return True if we were able to load this as proper ooRexx package
131  * file, false if either step failed. We do not throw
132  * exceptions here, since these are usually loaded in the
133  * context of operations that return an error result instead
134  * of an exception.
135  */
137 {
138  // try to load the package table.
139  package = getPackageTable();
140  // if this is NULL, return false to the manager
141  if (package == NULL)
142  {
143  return false;
144  }
145  // call the loader to get the package tables and set them up.
146  loadPackage();
147  return true;
148 }
149 
150 
151 
152 /**
153  * Unload a package library.
154  */
156 {
157  // call an unloader, if we have one.
158  if (package->unloader != NULL)
159  {
160  // go run the dispatcher call
162 
164  }
165  // the internal packages don't get unloaded because
166  // we'll be reusing the definition
167  if (loaded && !internal)
168  {
169  lib.unload();
170  }
171 }
172 
173 
174 /**
175  * Load a library and see if it is possible to retrieve
176  * a package entry from the library.
177  *
178  * @return A package table entry, if possible. A load failure or
179  * no package loading routines returns NULL.
180  */
182 {
183  // first try to load the libary
185  // reset the library handle that was saved in the image.
186  lib.reset();
187 
189  {
190  // we don't report an exception here. This may have
191  // just been a probe attempt to see if we're real. We'll
192  // leave the exception decisions up to the package manager.
193  return NULL;
194  }
195 
196  // we're loaded now, vs. just a package fronting a name.
197  loaded = true;
198  // the try to resolve a package getting structure
199  // resolve the function address
200  void *entry = lib.getProcedure("RexxGetPackage");
201  if (entry == NULL)
202  {
203  // again, this is not an exception...this could just be
204  // a classic style function registration.
205  return NULL;
206  }
207  loader = (PACKAGE_LOADER)entry;
208  // call the loader to get the package tables and set them up.
209  return (*loader)();
210 }
211 
212 
213 /**
214  * Load a package with a provided package definition.
215  *
216  * @param p The package table entry.
217  */
219 {
220  // verify that this library is compatible
222  {
224  }
225  // load the function table
227 
228  // call a loader, if we have one.
229  if (package->loader != NULL)
230  {
231  // go run the dispatcher call
233 
235  }
236 }
237 
238 
239 /**
240  * Load all of the routines in a package, registering them with
241  * the package manager.
242  *
243  * @param table The package table describing this package.
244  */
246 {
247  // no routines exported by this package? Just return without
248  // doing anything.
249  if (table == NULL)
250  {
251  return;
252  }
253 
254  // create a directory of loaded routines
255  OrefSet(this, routines, new_directory());
256 
257  while (table->style != 0)
258  {
259  // table names tend to be specified in friendly form, we need to
260  // convert them to uppercase because "normal" Rexx function names
261  // tend to be uppercase.
262  RexxString *target = new_upper_string(table->name);
263  RexxString *routineName = new_string(table->name);
264 
265  RexxRoutine *func = OREF_NULL;
266  if (table->style == ROUTINE_CLASSIC_STYLE)
267  {
268  func = new RegisteredRoutine(libraryName, routineName, (RexxRoutineHandler *)table->entryPoint);
269  }
270  else
271  {
272  func = new RexxNativeRoutine(libraryName, routineName, (PNATIVEROUTINE)table->entryPoint);
273  }
274 
275  RoutineClass *routine = new RoutineClass(routineName, func);
276  // add this to our local table. Our local table needs to keep the original case,
277  // since those will be referenced by ::ROUTINE statements.
278  routines->put(routine, routineName);
279 
280  // add this to the global function pool
281  PackageManager::addPackageRoutine(target, routine);
282  // step to the next table entry
283  table++;
284  }
285 }
286 
287 
288 
289 /**
290  * Locate a named method entry from the package registration
291  * table.
292  *
293  * @param name The target name.
294  *
295  * @return The entry associated with the target entry, if it exists.
296  * NULL indicates a not found condition.
297  */
299 {
300  RexxMethodEntry *entry = package->methods;
301 
302  if (entry != NULL)
303  {
304  // scan the exported method table for the required method
305  while (entry->style != 0)
306  {
307  // is this one a name match? Make a method, add it to
308  // the table, and return.
309  if (name->strCaselessCompare(entry->name))
310  {
311  return entry;
312  }
313  entry++;
314  }
315  }
316  return NULL;
317 }
318 
319 
320 /**
321  * Locate a named function entry from the package registration
322  * table.
323  *
324  * @param name The target name.
325  *
326  * @return A pointer to the located function structure. Returns NULL
327  * if the package doesn't exist.
328  */
330 {
332 
333  if ( entry != NULL )
334  {
335  // scan the exported method table for the required method
336  while (entry->style != 0)
337  {
338  // is this one a name match? Make a method, add it to
339  // the table, and return.
340  if (name->strCaselessCompare(entry->name))
341  {
342  return entry;
343  }
344  entry++;
345  }
346  }
347  return NULL;
348 }
349 
350 
351 /**
352  * Get a NativeCode object for a method associated with a
353  * package.
354  *
355  * @param name Name of the target method.
356  *
357  * @return A RexxNativeCode object for this method, if located.
358  */
360 {
361  // create our methods table if not yet created.
362  if (methods == OREF_NULL)
363  {
364  OrefSet(this, methods, new_directory());
365  }
366 
367  // see if this is in the table yet.
368  RexxNativeMethod *code = (RexxNativeMethod *)methods->at(name);
369  if (code == OREF_NULL)
370  {
371  // find the package definition
372  RexxMethodEntry *entry = locateMethodEntry(name);
373  // if we found one with this name, create a native method out of it.
374  if (entry != NULL)
375  {
376  code = new RexxNativeMethod(libraryName, name, (PNATIVEMETHOD)entry->entryPoint);
377  methods->put((RexxObject *)code, name);
378  return code;
379  }
380  // This, we know from nothing....
381  return OREF_NULL;
382  }
383  // had this cached already.
384  return code;
385 }
386 
387 
388 /**
389  * Get a Routine object for a method associated with a package.
390  *
391  * @param name Name of the target method.
392  *
393  * @return A RexxNativeCode object for this method, if located.
394  */
396 {
397  // we resolve all of these at load time, so this is either in the table, or it's not.
398  return (RoutineClass *)routines->at(name);
399 }
400 
401 
402 /**
403  * Resolve an entry point for a package method entry (used on a
404  * restore or reflatten);
405  *
406  * @param name Name of the target method.
407  *
408  * @return The target entry point.
409  */
411 {
412  // find the package definition
413  RexxMethodEntry *entry = locateMethodEntry(name);
414  // if no entry, something bad has gone wrong
415  if (entry == NULL)
416  {
418  }
419  return (PNATIVEMETHOD)entry->entryPoint;
420 }
421 
422 
423 /**
424  * Resolve an entry point for a package function entry (used on
425  * a restore or reflatten);
426  *
427  * @param name Name of the target function.
428  *
429  * @return The target entry point.
430  */
432 {
433  // find the package definition
434  RexxRoutineEntry *entry = locateRoutineEntry(name);
435  // if no entry, something bad has gone wrong
436  if (entry == NULL)
437  {
439  }
440 
441  // style mismatch...this is incompatible
442  if (entry->style == ROUTINE_CLASSIC_STYLE)
443  {
445  }
446  return (PNATIVEROUTINE)entry->entryPoint;
447 }
448 
449 
450 /**
451  * Resolve an entry point for a package function entry (used on
452  * a restore or reflatten);
453  *
454  * @param name Name of the target function.
455  *
456  * @return The target entry point.
457  */
459 {
460  // find the package definition
461  RexxRoutineEntry *entry = locateRoutineEntry(name);
462  // if no entry, something bad has gone wrong
463  if (entry == NULL)
464  {
466  }
467 
468  // style mismatch...this is incompatible
469  if (entry->style != ROUTINE_CLASSIC_STYLE)
470  {
472  }
473  return (PREGISTEREDROUTINE)entry->entryPoint;
474 }
475 
476 
477 /**
478  * Refresh a non-internal package after an image restore.
479  */
481 {
482  package = getPackageTable();
483  if (package == OREF_NULL)
484  {
485  Interpreter::logicError("Failure loading required base library");
486  }
487 }
488 
489 
490 /**
491  * Refresh an internal package after an image restore.
492  *
493  * @param pack The internal package entry.
494  */
496 {
497  package = pack;
498 }
499 
500 
501 
502 /**
503  * Process a callout to package loader function
504  */
506 {
507  RexxThreadContext *context = activity->getThreadContext();
508 
509  loader(context);
510 }
511 
512 
513 
514 /**
515  * Process a callout to package loader function
516  */
518 {
519  RexxThreadContext *context = activity->getThreadContext();
520 
521  unloader(context);
522 }
void reportException(wholenumber_t error)
@ T_LibraryPackage
RexxDirectory * new_directory()
RexxPackageEntry *RexxEntry * PACKAGE_LOADER()
size_t(RexxEntry * PREGISTEREDROUTINE)(const char *, size_t, PCONSTRXSTRING, const char *, PRXSTRING)
uint16_t *(RexxEntry * PNATIVEMETHOD)(RexxMethodContext *, ValueDescriptor *)
uint16_t *(RexxEntry * PNATIVEROUTINE)(RexxCallContext *, ValueDescriptor *)
#define OREF_NULL
Definition: RexxCore.h:61
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define Error_Execution_library_method
#define Error_Execution_library_version
#define Error_Execution_library_routine
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
RexxString * new_string(const char *s, stringsize_t l)
RexxString * new_upper_string(const char *s, stringsize_t l)
static RexxActivity *volatile currentActivity
static void logicError(const char *desc, const char *info1=NULL, size_t info2=0)
RoutineClass * resolveRoutine(RexxString *name)
RexxRoutineEntry * locateRoutineEntry(RexxString *name)
RexxString * libraryName
RexxPackageEntry * getPackageTable()
void live(size_t liveMark)
PNATIVEMETHOD resolveMethodEntry(RexxString *name)
void liveGeneral(int reason)
RexxDirectory * methods
LibraryPackage(RexxString *n)
RexxNativeMethod * resolveMethod(RexxString *name)
PREGISTEREDROUTINE resolveRegisteredRoutineEntry(RexxString *name)
PNATIVEROUTINE resolveRoutineEntry(RexxString *name)
void loadRoutines(RexxRoutineEntry *table)
RexxMethodEntry * locateMethodEntry(RexxString *name)
RexxDirectory * routines
RexxPackageEntry * package
static void addPackageRoutine(RexxString *name, RoutineClass *func)
RexxObject * at(RexxString *)
RexxObject * put(RexxObject *, RexxString *)
bool strCaselessCompare(const char *s)
const char * getStringData()
void * getProcedure(const char *name)
bool load(const char *name)
#define ROUTINE_CLASSIC_STYLE
Definition: oorexxapi.h:187
#define REXX_CURRENT_INTERPRETER_VERSION
Definition: oorexxapi.h:223
size_t REXXENTRY RexxRoutineHandler(CONSTANT_STRING, size_t, PCONSTRXSTRING, CONSTANT_STRING, PRXSTRING)
Definition: rexx.h:408
void RexxEntry loader(RexxThreadContext *context)
Definition: rxsock.cpp:623
Definition: oorexxapi.h:198
int style
Definition: oorexxapi.h:199
void * entryPoint
Definition: oorexxapi.h:202
const char * name
Definition: oorexxapi.h:201
Definition: oorexxapi.h:242
RexxPackageUnloader unloader
Definition: oorexxapi.h:249
struct _RexxRoutineEntry * routines
Definition: oorexxapi.h:250
RexxPackageLoader loader
Definition: oorexxapi.h:248
int requiredVersion
Definition: oorexxapi.h:245
struct _RexxMethodEntry * methods
Definition: oorexxapi.h:251
Definition: oorexxapi.h:177
int style
Definition: oorexxapi.h:178
const char * name
Definition: oorexxapi.h:180
void * entryPoint
Definition: oorexxapi.h:181