InterpreterInstance.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 /* Implementation of the InterpreterInstance class */
40 /* */
41 /******************************************************************************/
42 
43 #include "InterpreterInstance.hpp"
44 #include "Interpreter.hpp"
45 #include "SystemInterpreter.hpp"
46 #include "ActivityManager.hpp"
47 #include "RexxActivation.hpp"
48 #include "PackageManager.hpp"
49 #include "DirectoryClass.hpp"
50 #include "CommandHandler.hpp"
51 #include "PackageClass.hpp"
52 #include "WeakReferenceClass.hpp"
53 
54 /**
55  * Create a new Package object instance.
56  *
57  * @param size Size of the object.
58  *
59  * @return Pointer to new object storage.
60  */
61 void *InterpreterInstance::operator new(size_t size)
62 {
63  return new_object(size, T_InterpreterInstance);
64 }
65 
67 : terminationSem("InterpreterInstance::terminationSem")
68 {
69  // this needs to be created and set
72 
73  // fill in the interface vectore
75  // this back-link allows us to recover the instance pointer on the
76  // API callbacks.
77  context.instance = this;
78 }
79 
80 
81 void InterpreterInstance::live(size_t liveMark)
82 /******************************************************************************/
83 /* Function: Normal garbage collection live marking */
84 /******************************************************************************/
85 {
96 }
97 
98 
100 /******************************************************************************/
101 /* Function: Generalized object marking */
102 /******************************************************************************/
103 {
114 }
115 
116 
117 /**
118  * Initialize an interpreter instance.
119  *
120  * @param activity The root activity for the interpreter instance.
121  * @param handlers The exit handlers used by all threads running under this instance.
122  * @param defaultEnvironment
123  * The default address environment for this interpreter instance. Each
124  * active interpreter instance can define its own default environment.
125  */
127 {
128  rootActivity = activity;
130  searchExtensions = new_list(); // this will be filled in during options processing
131  requiresFiles = new_directory(); // our list of loaded requires packages
132  // this gets added to the entire active list.
133  allActivities->append((RexxObject *)activity);
135  // create a default wrapper for this security manager
137  // set the default system address environment (can be overridden by options)
139  // our list of command handlers (must be done before options are processed)
141 
142  // associate the thread with this instance
143  activity->setupAttachedActivity(this);
144  // create a local environment
146  processOptions(options);
147  // when handled originally, we didn't have the exits setup
148  // do this now.
149  activity->setupExits();
150  // do system specific initialization
151  sysInstance.initialize(this, options);
152  // register the system command handlers for this platform.
154  // now do the local initialization;
156 }
157 
158 
159 /**
160  * Set a new security manager object for this instance.
161  *
162  * @param m The security manager to set.
163  */
165 {
167 }
168 
169 
170 /**
171  * Attach a thread to an interpreter instance, returning the
172  * activity thread context.
173  *
174  * @param attachedContext
175  * The pointer for returning the thread context.
176  *
177  * @return 0 indicates success.
178  */
180 {
181  RexxActivity *activity = attachThread();
182  attachedContext = activity->getThreadContext();
183  // When we attach, we get the current lock. We need to ensure we
184  // release this before returning control to the outside world.
185  activity->releaseAccess();
186  return 0;
187 }
188 
189 
190 /**
191  * Attach a thread to an interpreter instance.
192  *
193  * @return The attached activity.
194  */
196 {
197  // first check for an existing activity
198  RexxActivity *activity = findActivity();
199  // do we have this? we can just return it
200  if (activity != OREF_NULL)
201  {
202  // make sure we mark this as attached...we might be nested and don't want to
203  // clean this up until we complete
204  activity->nestAttach();
205  return activity;
206  }
207 
208  // we need to get a new activity set up for this particular thread
209  activity = ActivityManager::attachThread();
210 
211  // resource lock must come AFTER we attach the thread, otherwise
212  // we can create a deadlock situation when we attempt to get the kernel
213  // lock
214  ResourceSection lock("InterpreterInstance::attachThread", 0);
215  // add this to the activity lists
216  allActivities->append((RexxObject *)activity);
217  // associate the thread with this instance
218  activity->setupAttachedActivity(this);
219  return activity;
220 }
221 
222 
223 /**
224  * Detach a thread from this interpreter instance.
225  *
226  * @param activity The activity to detach
227  *
228  * @return true if this worked ok.
229  */
231 {
232  // if the thread in question is not found, is not an attached thread, or
233  // the thread is currently busy, this fails
234  if (activity == OREF_NULL || !activity->isAttached() || activity->isActive())
235  {
236  return false;
237  }
238 
239  if (activity->isNestedAttach())
240  {
241  // if we reused the activity because of a nested callback attach, then
242  // we just decrement the nesting count and return without cleaning up
243  // any resources.
244  activity->returnAttach();
245  return true;
246  }
247 
248 
249  // this activity owned the kernel semaphore before entering here...release it
250  // now.
251  activity->releaseAccess();
252  ResourceSection lock("InterpreterInstance::detachThread", 0);
253 
254  allActivities->removeItem((RexxObject *)activity);
255  // have the activity manager remove this from the global tables
256  // and perform resource cleanup
258 
259  // Was this the last detach of an thread? Signal the shutdown event
260  if (allActivities->items() <= 1 && terminating)
261  {
263  }
264  return true;
265 }
266 
267 
268 /**
269  * Detach a thread from this interpreter instance.
270  *
271  * @return true if this worked ok.
272  */
274 {
275  // first check for an existing activity
276  return detachThread(findActivity());
277 }
278 
279 
280 
281 /**
282  * Spawn off a new thread from an existing thread.
283  *
284  * @param parent The parent thread.
285  *
286  * @return The attached activity.
287  */
289 {
290  // create a new activity
292  // associate the thread with this instance
293  activity->addToInstance(this);
294  // add this to the activities list
295  ResourceSection lock("InterpreterInstance::spawnActivity", 0);
296 
297  allActivities->append((RexxObject *)activity);
298  return activity;
299 }
300 
301 
302 /**
303  * Return a spawned activity back to the activity pool. This
304  * will disassociate the activity from the interpreter instance
305  * and place the thread back into the global thread pool.
306  *
307  * @param activity The activity to return.
308  *
309  * @return true if the activity was added to the pool, false if the
310  * activity should continue with termination.
311  */
313 {
314  ResourceSection lock("InterpreterInstance::poolActivity", 0);
315  // detach from this instance
316  activity->detachInstance();
317  // remove from the activities lists for the instance
318  allActivities->removeItem((RexxObject*)activity);
319  if (terminating)
320  {
321  // is this the last one to finish up? Generally, the main thread
322  // will be waiting for this to terminate. That is thread 1, we're thread
323  // 2. In reality, this is the test for the last "spawned" thread.
324  if (allActivities->items() <= 1)
325  {
327  }
328  // don't allow this to be pooled
329  return false;
330  }
331  // and move this to the global activity pool
332  return ActivityManager::poolActivity(activity);
333 }
334 
335 
336 /**
337  * Locate an activity for a specific thread ID that's attached
338  * to this instance.
339  *
340  * @param threadId The target thread id.
341  *
342  * @return The associated activity, or OREF_NULL if the current thread
343  * is not attached.
344  */
346 {
347  // this is a critical section
348  ResourceSection lock("InterpreterInstance::findActivity", 0);
349  // NB: New activities are pushed on to the end, so it's prudent to search
350  // from the list end toward the front of the list. Also, this ensures we
351  // will find the toplevel activity nested on a given thread first.
352  for (size_t listIndex = allActivities->lastIndex();
353  listIndex != LIST_END;
354  listIndex = allActivities->previousIndex(listIndex) )
355  {
356  RexxActivity *activity = (RexxActivity *)allActivities->getValue(listIndex);
357  // this should never happen, but we never return suspended threads
358  if (activity->isThread(threadId) && !activity->isSuspended())
359  {
360  return activity;
361  }
362  }
363  return OREF_NULL;
364 }
365 
366 
367 /**
368  * Find an activity for the current thread that's associated
369  * with this activity.
370  *
371  * @return The target activity.
372  */
374 {
376 }
377 
378 
379 /**
380  * Enter on the current thread context, making sure the interpreter
381  * lock is obtained.
382  *
383  * @return The activity object associated with this thread/instance
384  * combination.
385  */
387 {
388  RexxActivity *activity;
389  {
390  ResourceSection lock("InterpreterInstance::enterOnCurrentThread", 0); // lock the outer control block access
391  // attach this thread to the current activity
392  activity = attachThread();
393  // this will also get us the kernel lock, and take care of nesting
394  activity->activate();
395  }
396  // we need to ensure the resource lock is released before we attempt to
397  // acquire the kernel lock
398  activity->requestAccess();
399  // return the activity in case the caller needs it.
400  return activity;
401 }
402 
403 
404 /**
405  * We're leaving the current thread. So we need to deactivate
406  * this.
407  */
409 {
410  // find the current activity and deactivate it, and
411  // release the kernel lock.
412  RexxActivity *activity = findActivity();
413  activity->exitCurrentThread();
414 }
415 
416 
418 {
419  size_t count = allActivities->items();
420 
421  // This is a bit complicated. Each activity will be removed from the
422  // head of the list, and any activity not ready for termination is
423  // put back on the end. Since we're using the initial count of the
424  // items for handling this, we'll look at each activity at most once.
425  // If there are any items left, those are activities we can't release yet.
426  for (size_t i = 0; i < count; i++)
427  {
429  if (activity->isActive())
430  {
431  allActivities->append((RexxObject *)activity);
432  }
433  else
434  {
435  // have the inactive thread wake up and terminate
436  activity->terminatePoolActivity();
437  }
438  }
439 }
440 
441 
442 /**
443  * Attempt to shutdown the interpreter instance. This can only be done
444  * from the root activity.
445  *
446  * @return true if shutdown has been initiated, false otherwise.
447  */
449 {
450  // if our current activity is not the root one, we can't do that
451  RexxActivity *current = findActivity();
452  // we also can't be doing active work on the root thread
453  if (current != rootActivity || rootActivity->isActive())
454  {
455  return false;
456  }
457 
458  terminated = false;
459  // turn on the global termination in process flag
460  terminating = true;
461 
462  {
463 
464  ResourceSection lock("InterpreterInstance::terminate", 0);
465  // remove the current activity from the list so we don't clean everything
466  // up. We need to
467  allActivities->removeItem((RexxObject *)current);
468  // go remove all of the activities that are not doing work for this instance
470  // no activities left? We can leave now
471  terminated = allActivities->items() == 0;
472  // we need to restore the rootActivity to the list for potentially running uninits
473  allActivities->append((RexxObject *)current);
474  }
475 
476  // if there are active threads still running, we need to wait until
477  // they all finish
478  if (!terminated)
479  {
480  terminationSem.wait("InterpreterInstance::terminate", 0);
481  }
482 
483  // if everything has terminated, then make sure we run the uninits before shutting down.
484  // This activity is currently the current activity. We're going to run the
485  // uninits on this one, so reactivate it until we're done running
487  // release any global references we've been holding.
489  // before we update of the data structures, make sure we process any
490  // pending uninit activity.
491  memoryObject.verboseMessage("Calling runUninits through collectAndUninit from InterpreterInstance::terminate\n");
493 
494  // do system specific termination of an instance
496 
497  // ok, deactivate this again...this will return the activity because the terminating
498  // flag is on.
501 
502  // make sure the root activity is removed by the ActivityManager;
504 
505  // tell the main interpreter controller we're gone.
507  return true;
508 }
509 
510 
511 /**
512  * Add an object to the global references table.
513  *
514  * @param o The added object.
515  */
517 {
518  if (o != OREF_NULL)
519  {
520  globalReferences->put(o, o);
521  }
522 }
523 
524 /**
525  * Remove the global reference protection from an object.
526  *
527  * @param o The protected object.
528  */
530 {
531  if (o != OREF_NULL)
532  {
534  }
535 }
536 
537 
538 /**
539  * Raise a halt condition on all running activities.
540  */
542 {
543  // make sure we lock this, since it is possible the table can get updated
544  // as a result of setting these flags
545  ResourceSection lock("InterpreterInstance::haltAllActivities", 0);
546  bool result = true;
547  for (size_t listIndex = allActivities->firstIndex() ;
548  listIndex != LIST_END;
549  listIndex = allActivities->nextIndex(listIndex) )
550  {
551  /* Get the next message object to */
552  /*process */
553  RexxActivity *activity = (RexxActivity *)allActivities->getValue(listIndex);
554  // only halt the active ones
555  if (activity->isActive())
556  {
557  result = result && activity->halt(OREF_NULL);
558  }
559  }
560  return result;
561 }
562 
563 
564 /**
565  * Raise a trace condition on all running activities.
566  */
568 {
569  // make sure we lock this, since it is possible the table can get updated
570  // as a result of setting these flags
571  ResourceSection lock("InterpreterInstance::traceAllActivities", 0);
572  for (size_t listIndex = allActivities->firstIndex() ;
573  listIndex != LIST_END;
574  listIndex = allActivities->nextIndex(listIndex) )
575  {
576  /* Get the next message object to */
577  /*process */
578  RexxActivity *activity = (RexxActivity *)allActivities->getValue(listIndex);
579  // only activate the active ones
580  if (activity->isActive())
581  {
582  activity->setTrace(on);
583  }
584  }
585 }
586 
587 
588 /**
589  * Process interpreter instance options.
590  *
591  * @param options The list of defined options.
592  *
593  * @return True if the options were processed correctly, false otherwise.
594  */
596 {
597  // options are, well, optional...if nothing specified, we're done.
598  if (options == NULL)
599  {
600  return true;
601  }
602  // loop until we get to the last option item
603  while (options->optionName != NULL)
604  {
605  // an initial address environment
606  if (strcmp(options->optionName, INITIAL_ADDRESS_ENVIRONMENT) == 0)
607  {
609  }
610  // application data
611  else if (strcmp(options->optionName, APPLICATION_DATA) == 0)
612  {
613  // this is filled in to the instance context vector
615  }
616  // an additional search path
617  else if (strcmp(options->optionName, EXTERNAL_CALL_PATH) == 0)
618  {
620  }
621  // additional extensions for processing
622  else if (strcmp(options->optionName, EXTERNAL_CALL_EXTENSIONS) == 0)
623  {
624  const char *extStart = options->option.value.value_CSTRING;
625  const char *extEnd = extStart + strlen(extStart);
626 
627  while (extStart < extEnd)
628  {
629  const char *delim = strchr(extStart, ',');
630  if (delim == NULL)
631  {
632  delim = extEnd;
633  }
634  // make this into a string value and append
635  RexxString *ext = new_string(extStart, sizeB_v(delim - extStart));
636  searchExtensions->append(ext);
637 
638  // step past the delimiter and loop
639  extStart = delim + 1;
640  }
641  }
642  // old-style registered exit
643  else if (strcmp(options->optionName, REGISTERED_EXITS) == 0)
644  {
645  RXSYSEXIT *handlers = (RXSYSEXIT *)options->option.value.value_POINTER;
646  // if we have handlers, initialize the array
647  if (handlers != NULL)
648  {
649  /* while not the list ender */
650  for (int i= 0; handlers[i].sysexit_code != RXENDLST; i++)
651  {
652  /* enable this exit */
653  setExitHandler(handlers[i]);
654  }
655  }
656  }
657  // new-style context exit
658  else if (strcmp(options->optionName, DIRECT_EXITS) == 0)
659  {
660  RexxContextExit *handlers = (RexxContextExit *)options->option.value.value_POINTER;
661  // if we have handlers, initialize the array
662  if (handlers != NULL)
663  {
664  /* while not the list ender */
665  for (int i= 0; handlers[i].sysexit_code != RXENDLST; i++)
666  {
667  /* enable this exit */
668  setExitHandler(handlers[i]);
669  }
670  }
671  }
672  // old-style registered command handler
673  else if (strcmp(options->optionName, REGISTERED_ENVIRONMENTS) == 0)
674  {
676  // if we have handlers, initialize the array
677  if (handlers != NULL)
678  {
679  /* while not the list ender */
680  for (int i= 0; handlers[i].registeredName != NULL; i++)
681  {
682  // add the handler to this setup
683  addCommandHandler(handlers[i].name, handlers[i].registeredName);
684  }
685  }
686  }
687  // a direct call command handler
688  else if (strcmp(options->optionName, DIRECT_ENVIRONMENTS) == 0)
689  {
691  // if we have handlers, initialize the array
692  if (handlers != NULL)
693  {
694  /* while not the list ender */
695  for (int i= 0; handlers[i].handler != NULL; i++)
696  {
697  // add the handler to this setup
698  addCommandHandler(handlers[i].name, (REXXPFN)handlers[i].handler);
699  }
700  }
701  }
702  // a package to load at startup
703  else if (strcmp(options->optionName, LOAD_REQUIRED_LIBRARY) == 0)
704  {
705  RexxString *libraryName = new_string(options->option.value.value_CSTRING);
706 
707  // this must load ok in order for this to work
708  PackageManager::getLibrary(libraryName);
709  }
710  // a package to load at startup
711  else if (strcmp(options->optionName, REGISTER_LIBRARY) == 0)
712  {
713  RexxLibraryPackage *package = (RexxLibraryPackage *)options->option.value.value_POINTER;
714  RexxString *libraryName = new_string(package->registeredName);
715 
716  // this must load ok in order for this to work
717  PackageManager::registerPackage(libraryName, package->table);
718  }
719  else
720  {
721  // unknown option
722  return false;
723  }
724  // step to the next option value
725  options++;
726  }
727  return true;
728 }
729 
730 
731 /**
732  * Get the thread context vector for the root activity of the
733  * instance.
734  *
735  * @return The root RexxThreadContext environment;
736  */
738 {
739  return rootActivity->getThreadContext();
740 }
741 
742 
743 /**
744  * Retrieve a value from the instance local environment.
745  *
746  * @param name The name of the .local object.
747  *
748  * @return The object stored at the given name.
749  */
751 {
753  {
754  return TheNilObject;
755  }
756  return localEnvironment->at(name);
757 }
758 
759 /**
760  * Add a handler to the environment list.
761  *
762  * @param name The name of the address environment this services.
763  * @param entryPoint The entry point address of the handler.
764  */
765 void InterpreterInstance::addCommandHandler(const char *name, REXXPFN entryPoint)
766 {
767  RexxString *handlerName = new_upper_string(name);
768  commandHandlers->put((RexxObject *)new CommandHandler(entryPoint), handlerName);
769 }
770 
771 /**
772  * Add a handler for a registered subcom handler to the
773  * address handler list.
774  *
775  * @param name The environment name of the handler.
776  * @param registeredName
777  * The name of the registered subcom handler.
778  */
779 void InterpreterInstance::addCommandHandler(const char *name, const char *registeredName)
780 {
781  RexxString *handlerName = new_upper_string(name);
782  CommandHandler *handler = new CommandHandler(registeredName);
783  // it's possible we were give a bogus name, so validate this first
784  if (handler->isResolved())
785  {
786  commandHandlers->put((RexxObject *)handler, handlerName);
787  }
788 }
789 
790 
791 /**
792  * Resolve a command handler for invoking a command.
793  *
794  * @param name The name of the target address environment.
795  *
796  * @return The resolved handler, or OREF_NULL if this is not known.
797  */
799 {
800  // all names in the cache are in upper case
801  RexxString *upperName = name->upper();
802  ProtectedObject p(upperName);
803  CommandHandler *handler = (CommandHandler *)commandHandlers->at(upperName);
804  if (handler == OREF_NULL)
805  {
806  handler = new CommandHandler(name->getStringData());
807  if (!handler->isResolved())
808  {
809  return OREF_NULL; // can't find this
810  }
811  commandHandlers->put((RexxObject *)handler, upperName);
812  }
813  return handler;
814 }
815 
816 
817 /**
818  * Retrieve a requires file that might be loaded for this
819  * instance.
820  *
821  * @param name The name used for the requires file.
822  *
823  * @return The loaded requires file, or OREF_NULL if this instance
824  * has not used the file yet.
825  */
827 {
828  WeakReference *ref = (WeakReference *)requiresFiles->get(name);
829  if (ref != OREF_NULL)
830  {
831  PackageClass *resolved = (PackageClass *)ref->get();
832  if (resolved != OREF_NULL)
833  {
834  // get the guard lock on this...this will ensure that
835  // the initializer is run before we grab this from the cache
836  GuardLock lock(activity, resolved, ThePackageClass);
837  return resolved;
838  }
839  // this was garbage collected, remove it from the table
840  requiresFiles->remove(name);
841  }
842  return OREF_NULL;
843 }
844 
845 
846 /**
847  * Add a package to our cache, using weak references.
848  *
849  * @param shortName The shortName (always provided).
850  * @param fullName A second, fully resolved alias name.
851  * @param package The package to add
852  */
854 {
855  WeakReference *ref = new WeakReference(package);
856  requiresFiles->put(ref, shortName);
857  if (fullName != OREF_NULL)
858  {
859  requiresFiles->put(ref, fullName);
860  }
861 }
862 
863 
864 /**
865  * Do the initial run of a ::REQUIRES file.
866  *
867  * @param activity The current activity.
868  * @param name The name of the requires file.
869  * @param code The routine instance to run.
870  */
872 {
873  ProtectedObject dummy;
874 
875  // make sure we reference the circular reference stack
876  activity->addRunningRequires(name);
877  code->call(activity, name, NULL, 0, 0, dummy);
878  /* No longer installing routine. */
879  activity->removeRunningRequires(name);
880 }
881 
882 
883 /**
884  * Load a ::requires file into this interpreter instance.
885  *
886  * @param activity The current activity we're loading on.,
887  * @param shortName The original short name of this package.
888  * @param fullName An expanded fully resolved file name.
889  *
890  * @return The loaded package class, if located.
891  */
893 {
894 
895  // if we've already loaded this in this instance, just return it.
896  PackageClass *package = getRequiresFile(activity, shortName);
897  if (package != OREF_NULL)
898  {
899  return package;
900  }
901 
902  // if there is a fully resolved full name, check this next
903  if (fullName != OREF_NULL)
904  {
905  // if we've already loaded this in this instance, just return it.
906  package = getRequiresFile(activity, fullName);
907  if (package != OREF_NULL)
908  {
909  // add this to the cache using the short name, since they resolve to the same
910  addRequiresFile(shortName, OREF_NULL, package);
911  return package;
912  }
913  }
914 
915  // add the package manager to load this
916  ProtectedObject p;
917  RoutineClass *requiresFile = PackageManager::loadRequires(activity, shortName, fullName, p);
918 
919  if (requiresFile == OREF_NULL) /* couldn't create this? */
920  {
921  /* report an error */
923  }
924 
925  // The current name is the full path of the file.
926  // In the trace output, it's doubling the package name which is also displayed.
927  // So give a better name.
928  requiresFile->setName(new_string("<prolog>"));
929 
930  package = requiresFile->getPackage();
931  // make sure we lock this package until we finish running the requires.
932  GuardLock lock(activity, package, ThePackageClass);
933  // add this to the instance cache too, under both the long
934  // name and the fullName (if it was resolved)
935  addRequiresFile(shortName, fullName, package);
936  // for any requires file loaded to this instance, we run the prolog within the instance.
937  runRequires(activity, fullName != OREF_NULL ? fullName : shortName, requiresFile);
938 
939  return package;
940 }
941 
942 
943 /**
944  * Load a ::requires file into this interpreter instance.
945  *
946  * @param activity The current activity we're loading on.,
947  * @param shortName The original short name of this package.
948  * @param fullName An expanded fully resolved file name.
949  *
950  * @return The loaded package class, if located.
951  */
953 {
954  // if we've already loaded this in this instance, just return it.
955  PackageClass *package = getRequiresFile(activity, shortName);
956  if (package != OREF_NULL)
957  {
958  return package;
959  }
960 
961  // add the package manager to load this
962  ProtectedObject p;
963  RoutineClass *requiresFile = PackageManager::loadRequires(activity, shortName, source, p);
964 
965  if (requiresFile == OREF_NULL) /* couldn't create this? */
966  {
967  /* report an error */
969  }
970 
971  package = requiresFile->getPackage();
972  // make sure we lock this package until we finish running the requires.
973  GuardLock lock(activity, package, ThePackageClass);
974  // add this to the instance cache too, under both the long
975  // name and the fullName (if it was resolved)
976  addRequiresFile(shortName, OREF_NULL, package);
977 
978  // for any requires file loaded to this instance, we run the prolog within the instance.
979  runRequires(activity, shortName, requiresFile);
980 
981  return package;
982 }
983 
984 
985 /**
986  * Load a ::requires file into this interpreter instance.
987  *
988  * @param activity The current activity we're loading on.,
989  * @param shortName The original short name of this package.
990  * @param data The source file data.
991  * @param length The length of the source data.
992  *
993  * @return The loaded package class, if located.
994  */
995 PackageClass *InterpreterInstance::loadRequires(RexxActivity *activity, RexxString *shortName, const char *data, size_t length)
996 {
997  // if we've already loaded this in this instance, just return it.
998  PackageClass *package = getRequiresFile(activity, shortName);
999  if (package != OREF_NULL)
1000  {
1001  return package;
1002  }
1003 
1004  // add the package manager to load this
1005  ProtectedObject p;
1006  RoutineClass *requiresFile = PackageManager::loadRequires(activity, shortName, data, length, p);
1007 
1008  if (requiresFile == OREF_NULL) /* couldn't create this? */
1009  {
1010  /* report an error */
1012  }
1013 
1014  package = requiresFile->getPackage();
1015  // make sure we lock this package until we finish running the requires.
1016  GuardLock lock(activity, package, ThePackageClass);
1017  // add this to the instance cache too, under both the long
1018  // name and the fullName (if it was resolved)
1019  addRequiresFile(shortName, OREF_NULL, package);
1020 
1021  // for any requires file loaded to this instance, we run the prolog within the instance.
1022  runRequires(activity, shortName, requiresFile);
1023 
1024  return package;
1025 }
1026 
1027 
void reportException(wholenumber_t error)
@ T_InterpreterInstance
RexxDirectory * new_directory()
RexxIdentityTable * new_identity_table()
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
#define ThePackageClass
Definition: RexxCore.h:155
#define OREF_NULL
Definition: RexxCore.h:60
#define TheNilObject
Definition: RexxCore.h:181
#define Error_Routine_not_found_requires
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
@ REGISTER_LIBRARY
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
RexxString * new_upper_string(const char *s, stringsizeB_t bl, stringsizeC_t cl=-1)
static RexxActivity * createNewActivity()
static bool poolActivity(RexxActivity *activity)
static void returnActivity(RexxActivity *)
static RexxActivity * attachThread()
static void returnRootActivity(RexxActivity *activity)
void setName(RexxString *name)
Definition: MethodClass.hpp:94
static bool lastInstance()
static void initLocal()
static bool terminateInterpreterInstance(InterpreterInstance *instance)
SecurityManager * securityManager
bool poolActivity(RexxActivity *activity)
RexxObject * getLocalEnvironment(RexxString *)
void setSecurityManager(RexxObject *m)
void addGlobalReference(RexxObject *o)
RexxActivity * enterOnCurrentThread()
RexxActivity * findActivity()
SysInterpreterInstance sysInstance
RexxActivity * attachThread()
RexxDirectory * localEnvironment
RexxIdentityTable * globalReferences
void addRequiresFile(RexxString *shortName, RexxString *fullName, PackageClass *package)
bool haltAllActivities(RexxString *)
static RexxInstanceInterface interfaceVector
void removeGlobalReference(RexxObject *o)
PackageClass * getRequiresFile(RexxActivity *activity, RexxString *name)
PackageClass * loadRequires(RexxActivity *activity, RexxString *shortName, const char *data, size_t length)
void addCommandHandler(const char *name, const char *registeredName)
void traceAllActivities(bool on)
void setExitHandler(int exitNum, REXXPFN e)
void runRequires(RexxActivity *activity, RexxString *name, RoutineClass *code)
void initialize(RexxActivity *activity, RexxOption *options)
RexxActivity * spawnActivity(RexxActivity *parent)
RexxThreadContext * getRootThreadContext()
RexxDirectory * requiresFiles
bool processOptions(RexxOption *options)
CommandHandler * resolveCommandHandler(RexxString *name)
RexxDirectory * commandHandlers
static RoutineClass * loadRequires(RexxActivity *activity, RexxString *shortName, RexxString *resolvedName, ProtectedObject &result)
static bool registerPackage(RexxString *name, RexxPackageEntry *p)
static LibraryPackage * getLibrary(RexxString *name)
void addRunningRequires(RexxString *program)
void requestAccess()
void setupAttachedActivity(InterpreterInstance *interpreter)
bool halt(RexxString *)
bool isNestedAttach()
bool isThread(thread_id_t id)
void returnAttach()
void terminatePoolActivity()
bool isSuspended()
void removeRunningRequires(RexxObject *program)
void addToInstance(InterpreterInstance *interpreter)
void releaseAccess()
void detachInstance()
void exitCurrentThread()
RexxThreadContext * getThreadContext()
bool setTrace(bool)
RexxObject * at(RexxString *)
RexxObject * put(RexxObject *, RexxString *)
RexxObject * remove(RexxString *)
virtual RexxObject * get(RexxObject *key)
virtual RexxObject * put(RexxObject *, RexxObject *)
virtual RexxObject * remove(RexxObject *key)
size_t previousIndex(size_t i)
Definition: ListClass.cpp:830
RexxObject * append(RexxObject *)
Definition: ListClass.cpp:538
size_t firstIndex()
Definition: ListClass.hpp:84
size_t lastIndex()
Definition: ListClass.hpp:85
size_t nextIndex(size_t i)
Definition: ListClass.cpp:804
size_t items()
Definition: ListClass.hpp:97
RexxObject * removeItem(RexxObject *)
Definition: ListClass.cpp:1023
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
RexxObject * removeFirstItem()
Definition: ListClass.hpp:111
void collectAndUninit(bool clearStack)
Definition: RexxMemory.cpp:491
void verboseMessage(const char *message)
Definition: RexxMemory.hpp:240
const char * getStringData()
RexxString * upper()
void call(RexxActivity *, RexxString *, RexxObject **, size_t, size_t, RexxString *, RexxString *, int, ProtectedObject &)
static thread_id_t queryThreadID()
void registerCommandHandlers(InterpreterInstance *i)
void initialize(InterpreterInstance *i, RexxOption *options)
void wait(const char *ds, int di)
static RexxString * getDefaultAddressName()
RexxObject * get()
#define LOAD_REQUIRED_LIBRARY
Definition: oorexxapi.h:379
#define DIRECT_EXITS
Definition: oorexxapi.h:384
#define INITIAL_ADDRESS_ENVIRONMENT
Definition: oorexxapi.h:370
#define APPLICATION_DATA
Definition: oorexxapi.h:372
#define REGISTERED_EXITS
Definition: oorexxapi.h:381
#define REGISTERED_ENVIRONMENTS
Definition: oorexxapi.h:386
#define EXTERNAL_CALL_EXTENSIONS
Definition: oorexxapi.h:376
#define DIRECT_ENVIRONMENTS
Definition: oorexxapi.h:389
#define EXTERNAL_CALL_PATH
Definition: oorexxapi.h:374
#define sizeB_v(X)
Definition: rexx.h:250
#define RXENDLST
Definition: rexxapidefs.h:170
int sysexit_code
Definition: rexx.h:192
InterpreterInstance * instance
RexxInstance instanceContext
RexxContextCommandHandler * handler
Definition: oorexxapi.h:400
void * applicationData
Definition: oorexxapi.h:684
RexxInstanceInterface * functions
Definition: oorexxapi.h:683
ValueDescriptor option
Definition: oorexxapi.h:419
const char * optionName
Definition: oorexxapi.h:418
const char * registeredName
Definition: oorexxapi.h:406
CSTRING value_CSTRING
Definition: oorexxapi.h:282
POINTER value_POINTER
Definition: oorexxapi.h:283
union ValueDescriptor::@26 value
void * REXXPFN
pthread_t thread_id_t