windows/rexx.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2012 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 /* */
40 /* File Name: REXX.C */
41 /* */
42 /* Description: Call the REXX interpreter using the command */
43 /* line arguments. */
44 /* */
45 /* Entry Points: main - main entry point */
46 /* */
47 /*********************************************************************/
48 
49 
50 #include <windows.h>
51 #include <oorexxapi.h> /* needed for rexx stuff */
52 #include <malloc.h>
53 #include <stdio.h> /* needed for printf() */
54 #include <string.h> /* needed for strlen() */
55 
56 
57 //
58 // Prototypes
59 //
60 int __cdecl main(int argc, char *argv[]); /* main entry point */
61 LONG REXXENTRY MY_IOEXIT( LONG ExitNumber, LONG Subfunction, PEXIT ParmBlock);
62 
63 #include "ArgumentParser.h" /* defines getArguments and freeArguments */
64 
65 //
66 // MAIN program
67 //
68 int __cdecl main(int argc, char *argv[]) {
69  short rexxrc = 0; /* return code from rexx */
70  int i; /* loop counter */
71  int rc; /* actually running program RC */
72  const char *program_name; /* name to run */
73  char arg_buffer[8192]; /* starting argument buffer */
74  char *cp; /* option character pointer */
75  CONSTRXSTRING arguments; /* rexxstart argument */
76  size_t argcount;
77  RXSTRING rxretbuf; // program return buffer
78  BOOL from_string = FALSE; /* running from command line string? */
79  BOOL real_argument = TRUE; /* running from command line string? */
80  RXSTRING instore[2];
81 
82  RexxInstance *pgmInst;
83  RexxThreadContext *pgmThrdInst;
84  RexxArrayObject rxargs, rxcargs;
86  RexxObjectPtr result;
87 
88  rc = 0; /* set default return */
89 
90  /*
91  * Convert the input array into a single string for the Object REXX
92  * argument string. Initialize the RXSTRING variable to point to this
93  * string. Keep the string null terminated so we can print it for debug.
94  * First argument is name of the REXX program
95  * Next argument(s) are parameters to be passed
96  */
97 
98  arg_buffer[0] = '\0'; /* default to no argument string */
99  program_name = NULL; /* no program to run yet */
100 
101  for (i = 1; i < argc; i++) /* loop through the arguments */
102  {
103  /* is this an option switch? */
104  if ((*(cp=*(argv+i)) == '-' || *cp == '/')) {
105  switch (*++cp) {
106  case 'e':
107  case 'E': /* execute from string */
108  if (from_string == FALSE) { /* only treat 1st -e differently */
109  from_string = TRUE;
110  if ( argc == i+1 ) {
111  break;
112  }
113  program_name = "INSTORE";
114  instore[0].strptr = argv[i+1];
115  instore[0].strlength = strlen(instore[0].strptr);
116  instore[1].strptr = NULL;
117  instore[1].strlength = 0;
118  real_argument = FALSE;
119  }
120  break;
121  case 'v':
122  case 'V': { /* version display */
123  char *ptr = RexxGetVersionInformation();
124  if (ptr)
125  {
126  fprintf(stdout, ptr);
127  fprintf(stdout, "\n");
128  RexxFreeMemory(ptr);
129  }
130  return 0;
131  }
132  default: /* ignore other switches */
133  break;
134  }
135  }
136  else /* convert into an argument string */
137  {
138  if (program_name == NULL) { /* no name yet? */
139  program_name = argv[i]; /* program is first non-option */
140  break; /* end parsing after program_name has been resolved */
141  }
142  else if ( real_argument ) { /* part of the argument string */
143  if (arg_buffer[0] != '\0') { /* not the first one? */
144  strcat(arg_buffer, " "); /* add an blank */
145  }
146  strcat(arg_buffer, argv[i]); /* add this to the argument string */
147  }
148  real_argument = TRUE;
149  }
150  }
151 
152  if (program_name == NULL) {
153  /* give a simple error message */
154 #undef printf
155  printf("\n");
156  fprintf(stderr,"Syntax is \"rexx filename [arguments]\"\n");
157  fprintf(stderr,"or \"rexx -e program_string [arguments]\"\n");
158  fprintf(stderr,"or \"rexx -v\".\n");
159  return -1;
160  }
161  else { /* real program execution */
162  getArguments(NULL, GetCommandLine(), &argcount, &arguments);
163  rxretbuf.strlength = 0L; /* initialize return to empty */
164 
165 #ifdef REXXC_DEBUG
166  printf("program_name = %s\n", program_name);
167  printf("argv 0 = %s\n", argv[0]);
168  printf("argv 1 = %s\n", argv[1]);
169  printf("argv 2 = %s\n", argv[2]);
170  printf("argument.strptr = %s\n", argument.strptr);
171  printf("argument.strlenth = %lu\n", argument.strlength);
172 #endif
173 
174 
175  if (from_string) {
176  /* Here we call the interpreter. We don't really need to use */
177  /* all the casts in this call; they just help illustrate */
178  /* the data types used. */
179  rc=REXXSTART(argcount, /* number of arguments */
180  &arguments, /* array of arguments */
181  program_name, /* name of REXX file */
182  instore, /* rexx code from command line */
183  "CMD", /* Command env. name */
184  RXCOMMAND, /* Code for how invoked */
185  NULL,
186  &rexxrc, /* Rexx program output */
187  &rxretbuf ); /* Rexx program output */
188  /* rexx procedure executed*/
189  if ((rc==0) && rxretbuf.strptr) {
190  RexxFreeMemory(rxretbuf.strptr); /* Release storage only if */
191  }
192  freeArguments(NULL, &arguments);
193  }
194  else {
195  RexxCreateInterpreter(&pgmInst, &pgmThrdInst, NULL);
196  // configure the traditional single argument string
197 
198  if ( arguments.strptr != NULL )
199  {
200  rxargs = pgmThrdInst->NewArray(1);
201  pgmThrdInst->ArrayPut(rxargs, pgmThrdInst->String(arguments.strptr), 1);
202  }
203  else
204  {
205  rxargs = pgmThrdInst->NewArray(0);
206  }
207 
208  // set up the C args into the .local environment
209  dir = (RexxDirectoryObject)pgmThrdInst->GetLocalEnvironment();
210  if ( argc > 2 )
211  {
212  rxcargs = pgmThrdInst->NewArray(argc - 2);
213  }
214  else
215  {
216  rxcargs = pgmThrdInst->NewArray(0);
217  }
218  for (i = 2; i < argc; i++)
219  {
220  pgmThrdInst->ArrayPut(rxcargs,
221  pgmThrdInst->NewStringFromAsciiz(argv[i]),
222  i - 1);
223  }
224  pgmThrdInst->DirectoryPut(dir, rxcargs, "SYSCARGS");
225  // call the interpreter
226  result = pgmThrdInst->CallProgram(program_name, rxargs);
227  // display any error message if there is a condition.
228  // if there was an error, then that will be our return code.
229  // Although the return is a wholenumber_t we know there is no error
230  // code too big to fit in an int.
231  rc = (int)pgmThrdInst->DisplayCondition();
232  if (rc != 0)
233  {
234  pgmInst->Terminate();
235  return -rc; // well, the negation of the error number is the return code
236  }
237  // now handle any potential return value
238  if (result != NULL) {
239  pgmThrdInst->ObjectToInt32(result, &rc);
240  }
241 
242  pgmInst->Terminate();
243 
244  return rc;
245  }
246  }
247  return rc ? rc : rexxrc; // rexx program return cd
248 }
249 
PCONSTRXSTRING getArguments(const char **program, const char *argptr, size_t *count, PCONSTRXSTRING retarr)
void freeArguments(const char *program, PCONSTRXSTRING arguments)
char *REXXENTRY RexxGetVersionInformation()
RexxReturnCode RexxEntry RexxCreateInterpreter(RexxInstance **instance, RexxThreadContext **context, RexxOption *options)
RexxReturnCode REXXENTRY RexxFreeMemory(void *)
struct _RexxArrayObject * RexxArrayObject
Definition: rexx.h:130
#define REXXSTART
Definition: rexx.h:465
struct _RexxObjectPtr * RexxObjectPtr
Definition: rexx.h:127
char * PEXIT
Definition: rexx.h:215
struct _RexxDirectoryObject * RexxDirectoryObject
Definition: rexx.h:137
#define RXCOMMAND
Definition: rexxapidefs.h:64
const char * strptr
Definition: rexx.h:163
size_t strlength
Definition: rexx.h:157
char * strptr
Definition: rexx.h:158
#define REXXENTRY
int __cdecl main(int argc, char *argv[])
LONG REXXENTRY MY_IOEXIT(LONG ExitNumber, LONG Subfunction, PEXIT ParmBlock)