InterpreterAPI.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 /* Startup */
42 /* */
43 /******************************************************************************/
44 #include <string.h>
45 #include <signal.h>
46 #include <stdlib.h>
47 
48 #include "RexxCore.h"
49 #include "RexxMemory.hpp"
50 #include "StringClass.hpp"
51 #include "DirectoryClass.hpp"
52 #include "RexxActivity.hpp"
53 #include "ActivityManager.hpp"
54 #include "MethodClass.hpp"
55 #include "StackClass.hpp"
56 #include "Interpreter.hpp"
57 #include "TranslateDispatcher.hpp"
58 #include "RexxStartDispatcher.hpp"
59 #include "InterpreterInstance.hpp"
60 #include "RexxNativeActivation.hpp"
61 #include "RexxInternalApis.h"
62 #include "SystemInterpreter.hpp"
63 
64 
66 /******************************************************************************/
67 /* Function: Terminate the REXX interpreter...will only terminate if the */
68 /* call nesting level has reached zero. */
69 /******************************************************************************/
70 {
71  // terminate and clean up the interpreter runtime. This only works
72  // if there are no active instances
73  return Interpreter::terminateInterpreter() ? 0 : 1;
74 }
75 
77 /******************************************************************************/
78 /* Function: Perform main kernel initializations */
79 /******************************************************************************/
80 {
81  // start this up for normal execution
83  // this always returns true
84  return true;
85 }
86 
87 
88 /**
89  * Create the Rexx saved image during build processing.
90  *
91  * @return Nothing
92  */
93 void REXXENTRY RexxCreateInterpreterImage(const char *target)
94 {
95  // start this up and save the image. This never returns to here
97 }
98 
99 
100 
101 /******************************************************************************/
102 /* Name: RexxMain */
103 /* */
104 /* Arguments: argcount - Number of args in arglist */
105 /* arglist - Array of args (array of RXSTRINGs) */
106 /* programname - REXX program to run */
107 /* instore - Instore array (array of 2 RXSTRINGs) */
108 /* envname - Initial cmd environment */
109 /* calltype - How the program is called */
110 /* exits - Array of system exit names (array of RXSTRINGs) */
111 /* */
112 /* Returned: result - Result returned from program */
113 /* rc - Return code from program */
114 /* */
115 /* Notes: Primary path into Object REXX. Makes sure Object REXX is up */
116 /* and runs the requested program. */
117 /* */
118 /******************************************************************************/
120  size_t argcount, /* Number of args in arglist */
121  PCONSTRXSTRING arglist, /* Array of args */
122  const char *programname, /* REXX program to run */
123  PRXSTRING instore, /* Instore array */
124  const char *envname, /* Initial cmd environment */
125  int calltype, /* How the program is called */
126  PRXSYSEXIT exits, /* Array of system exit names */
127  short * retcode, /* Integer form of result */
128  PRXSTRING result) /* Result returned from program */
129 {
130  if (calltype == RXCOMMAND && argcount == 1 && arglist[0].strptr != NULL && arglist[0].strlength > 0 &&
131  StringUtil::caselessCompare(arglist[0].strptr, "//T", arglist[0].strlength) == 0)
132  {
133  TranslateDispatcher arguments;
134  arguments.programName = programname;
135  arguments.instore = instore;
136  // this just translates and gives the error, potentially returning
137  // the instore image
138  arguments.outputName = NULL;
139  // go run this program
140  arguments.invoke(exits, envname);
141 
142  return (int)arguments.rc; /* return the error code (negated) */
143  }
144 
145 
146  // this is the dispatcher that handles the actual
147  // interpreter call. This gets all of the RexxStart arguments, then
148  // gets dispatched on the other side of the interpreter boundary
149  RexxStartDispatcher arguments;
150  /* copy all of the arguments into */
151  /* the info control block, which is */
152  /* passed across the kernel boundary */
153  /* into the real RexxStart method */
154  /* this is a real execution */
155  arguments.argcount = argcount;
156  arguments.arglist = arglist;
157  arguments.programName = programname;
158  arguments.instore = instore;
159  arguments.calltype = calltype;
160  arguments.retcode = 0;
161  arguments.result = result;
162 
163  // go run this program
164  arguments.invoke(exits, envname);
165  *retcode = arguments.retcode;
166 
167  // terminate and clean up the interpreter runtime. This only works
168  // if there are no active instances
170 
171  return (int)arguments.rc; /* return the error code (negated) */
172 }
173 
174 
175 /**
176  * Translate a program and store the translated results in an
177  * external file.
178  *
179  * @param inFile The input source file.
180  * @param outFile The output source.
181  * @param exits The exits to use during the translation process.
182  *
183  * @return The error return code (if any).
184  */
185 RexxReturnCode REXXENTRY RexxTranslateProgram(const char *inFile, const char *outFile, PRXSYSEXIT exits)
186 {
187  TranslateDispatcher arguments;
188  // this gets processed from disk, always.
189  arguments.programName = inFile;
190  arguments.instore = NULL;
191  // this just translates and gives the error, potentially returning
192  // the instore image
193  arguments.outputName = outFile;
194  // go run this program
195  arguments.invoke(exits, NULL);
196 
197  // terminate and clean up the interpreter runtime. This only works
198  // if there are no active instances
200 
201  return (RexxReturnCode)arguments.rc; /* return the error code (negated) */
202 }
203 
204 
205 /**
206  * Translate a program and store the translated results in an
207  * external file.
208  *
209  * @param inFile The input name.
210  * @param source The source RXSTRING
211  * @param image The returned image RXSTRING
212  *
213  * @return The error return code (if any).
214  */
216 {
217  TranslateInstoreDispatcher arguments;
218  // this gets processed from disk, always.
219  arguments.programName = inFile;
220  arguments.source = source;
221  arguments.image = image;
222  // go run this program
223  arguments.invoke(NULL, NULL);
224  return (RexxReturnCode)arguments.rc; /* return the error code (negated) */
225 }
226 
227 
228 /**
229  * Retrieve the interpreter version information.
230  *
231  * @return
232  */
234 {
235  char ver[100];
236  snprintf( ver, sizeof ver, " %d.%d.%d", ORX_VER, ORX_REL, ORX_MOD );
237  char header[] = "Open Object Rexx Version";
238  #ifdef _DEBUG
239  char build[] = " - Internal Test Version\nBuild date: ";
240  #else
241  char build[] = "\nBuild date: ";
242  #endif
243  #ifdef __REXX64__
244  char mode[] = "\nAddressing Mode: 64";
245  #else
246  char mode[] = "\nAddressing Mode: 32";
247  #endif
248  char copy1[] = "\n\nCopyright (c) IBM Corporation 1995, 2004.\nCopyright (c) RexxLA " OOREXX_COPY_YEAR ".\nAll Rights Reserved.";
249  char copy2[] = "\nThis program and the accompanying materials are made available under";
250  char copy3[] = "\nthe terms of the Common Public License v1.0 which accompanies this";
251  char copy4[] = "\ndistribution or at";
252  char copy5[] = "\nhttp://www.oorexx.org/license.html";
253  size_t size = strlen(header) + strlen(ver) + strlen(build) + strlen(__DATE__) +
254  strlen(mode) + strlen(copy1) + strlen(copy2) + strlen(copy3) + strlen(copy4) + strlen(copy5) + 1;
255  char *ptr = (char *)SystemInterpreter::allocateResultMemory(size);
256  if (ptr != NULL)
257  {
258  snprintf(ptr, size, "%s%s%s%s%s%s%s%s%s%s", header, ver, build, __DATE__, mode, copy1, copy2, copy3, copy4, copy5);
259  }
260  return ptr;
261 }
262 
263 
264 /**
265  * Raise a halt condition for a target thread.
266  *
267  * @param threadid The target threadid.
268  *
269  * @return RXARI_OK if this worked, RXARI_NOT_FOUND if the thread isn't
270  * active.
271  */
273 {
274  if (Interpreter::isActive())
275  { /* Are we up? */
277  {
278  return (RXARI_NOT_FOUND); /* Couldn't find threadid */
279  }
280  return (RXARI_OK);
281  }
282  return RXARI_NOT_FOUND; /* REXX not running, error... */
283 }
284 
285 
286 /**
287  * Compatibility function for doing a RexxHaltThread().
288  *
289  * @param procid The process id (ignored).
290  * @param threadid The target threadid
291  *
292  * @return the success/failure return code.
293  */
295 {
296  return RexxHaltThread(threadid);
297 }
298 
299 
300 /**
301  * Turn on tracing for a given interpreter thread.
302  *
303  * @param threadid The target thread identifier.
304  *
305  * @return the success/failure return code.
306  */
308 {
309  if (Interpreter::isActive())
310  {
311  if (!ActivityManager::setActivityTrace(threadid, true))
312  {
313  return (RXARI_NOT_FOUND); /* Couldn't find threadid */
314  }
315  return (RXARI_OK);
316  }
317  return RXARI_NOT_FOUND; /* REXX not running, error... */
318 }
319 
320 
321 /**
322  * Reset the external trace for a target thread.
323  *
324  * @param threadid The target thread id.
325  *
326  * @return The success/failure indicator.
327  */
329 {
330  if (Interpreter::isActive())
331  {
332  if (!ActivityManager::setActivityTrace(threadid, false))
333  {
334  return (RXARI_NOT_FOUND); /* Couldn't find threadid */
335  }
336  return (RXARI_OK);
337  }
338  return RXARI_NOT_FOUND; /* REXX not running, error... */
339 }
340 
341 
342 /**
343  * Compatibility stub for the old signature of RexxSetTrace.
344  *
345  * @param procid The process id (ignored).
346  * @param threadid The target thread identifier.
347  *
348  * @return the success/failure return code.
349  */
351 {
352  return RexxSetThreadTrace(threadid);
353 }
354 
355 
356 /**
357  * The compatibility stub for the reset trace API.
358  *
359  * @param procid The target process id (ignored).
360  * @param threadid The thread id of the target thread.
361  *
362  * @return The success/failure indicator.
363  */
365 {
366  return RexxResetThreadTrace(threadid);
367 }
368 
369 
370 /**
371  * Create an interpreter instance at the API level.
372  *
373  * @param instance The returned instance pointer.
374  * @param context The initial thread context for this instance.
375  * @param exits A list of user exits to be used for this context.
376  * @param userData A pointer to a user defined data area.
377  *
378  * @return RXAPI_OK if the instance was created, RXAPI_MEMFAIL for any
379  * creation errors.
380  */
382 {
383  return Interpreter::createInstance(*instance, *context, options) ? RXAPI_OK : RXAPI_MEMFAIL;
384 }
385 
386 /**
387  * Main entry point for processing variable pool requests
388  *
389  * @param pshvblock The shaved variable block chain for the request.
390  *
391  * @return The composite request return code.
392  */
394 {
395  NativeContextBlock context;
396  // the variable pool interface handles its own try/catches.
397  return context.self->variablePoolInterface(pshvblock);
398 }
399 
400 /**
401  * Process a stemsort call for the rexxutil SysStemSort function.
402  *
403  * @param stemname The name of the stem.
404  * @param order The sort order.
405  * @param type The type of sort (case sensitivity).
406  * @param start The starting element number.
407  * @param end The end element number.
408  * @param firstcol The first sort column.
409  * @param lastcol The last sort column.
410  *
411  * @return The sort return code result.
412  */
413 RexxReturnCode RexxEntry RexxStemSort(const char *stemname, int order, int type,
414  size_t start, size_t end, size_t firstcol, size_t lastcol)
415 {
416  NativeContextBlock context;
417  // the variable pool interface handles its own try/catches.
418  return context.self->stemSort(stemname, order, type, start, end, firstcol, lastcol);
419 }
420 
421 /**
422  * Wait for Rexx termination. This is a nop in 4.0 since
423  * the APIs do the proper thing with respect to threading
424  * termination. This is maintained solely for binary
425  * compatibility.
426  *
427  * @return
428  */
430 {
431 }
432 
433 
434 /**
435  * Test if the interpreter environment has terminated. This is
436  * a nop in 4.0 since the APIs do the proper thing with respect
437  * to threading termination. This is maintained solely for
438  * binary compatibility.
439  *
440  * @return always returns true
441  */
443 {
444  return true;
445 }
RexxObject * build(RexxString *variable_name, bool direct)
char *REXXENTRY RexxGetVersionInformation()
RexxReturnCode RexxEntry RexxVariablePool(PSHVBLOCK pshvblock)
RexxReturnCode RexxEntry RexxStemSort(const char *stemname, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
RexxReturnCode REXXENTRY RexxTranslateProgram(const char *inFile, const char *outFile, PRXSYSEXIT exits)
void REXXENTRY RexxCreateInterpreterImage(const char *target)
RexxReturnCode REXXENTRY RexxTranslateInstoreProgram(const char *inFile, CONSTRXSTRING *source, RXSTRING *image)
int REXXENTRY RexxStart(size_t argcount, PCONSTRXSTRING arglist, const char *programname, PRXSTRING instore, const char *envname, int calltype, PRXSYSEXIT exits, short *retcode, PRXSTRING result)
int REXXENTRY RexxInitialize()
RexxReturnCode REXXENTRY RexxResetTrace(process_id_t procid, thread_id_t threadid)
RexxReturnCode REXXENTRY RexxResetThreadTrace(thread_id_t threadid)
RexxReturnCode REXXENTRY RexxSetThreadTrace(thread_id_t threadid)
void RexxEntry RexxWaitForTermination()
RexxReturnCode REXXENTRY RexxSetTrace(process_id_t procid, thread_id_t threadid)
RexxReturnCode REXXENTRY RexxHaltThread(thread_id_t threadid)
RexxReturnCode REXXENTRY RexxSetHalt(process_id_t procid, thread_id_t threadid)
RexxReturnCode RexxEntry RexxCreateInterpreter(RexxInstance **instance, RexxThreadContext **context, RexxOption *options)
RexxReturnCode RexxEntry RexxDidRexxTerminate()
int REXXENTRY RexxTerminate()
#define OREF_NULL
Definition: RexxCore.h:61
static bool setActivityTrace(thread_id_t thread_id, bool on_or_off)
static bool haltActivity(thread_id_t thread_id, RexxString *description)
static void startInterpreter(InterpreterStartupMode mode, const char *imageTarget)
static bool terminateInterpreter()
static bool isActive()
Definition: Interpreter.hpp:92
static int createInstance(RexxInstance *&instance, RexxThreadContext *&threadContext, RexxOption *options)
RexxNativeActivation * self
RexxReturnCode variablePoolInterface(PSHVBLOCK requests)
int stemSort(const char *stemname, int order, int type, size_t start, size_t end, size_t firstcol, size_t lastcol)
static int caselessCompare(const char *, const char *, size_t)
Definition: StringUtil.cpp:580
static void * allocateResultMemory(size_t)
int type
Definition: cmdparse.cpp:1888
CONSTANT_RXSTRING * PCONSTRXSTRING
Definition: rexx.h:186
int RexxReturnCode
Definition: rexx.h:73
#define RexxEntry
Definition: rexx.h:235
#define RXCOMMAND
Definition: rexxapidefs.h:64
#define RXARI_OK
Definition: rexxapidefs.h:212
#define RXAPI_MEMFAIL
Definition: rexxapidefs.h:61
#define RXARI_NOT_FOUND
Definition: rexxapidefs.h:213
#define RXAPI_OK
Definition: rexxapidefs.h:60
pid_t process_id_t
#define REXXENTRY
pthread_t thread_id_t