StreamCommandParser.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 parse.c */
40 /* */
41 /* Stream option string parsing */
42 /* */
43 /******************************************************************************/
44 #include <stdio.h> /* for printf calls */
45 #include <stdlib.h> /* for malloc call */
46 #include <string.h> /* for string functions */
47 #include "RexxCore.h" /* global REXX definitions */
48 #include "StreamCommandParser.h" /* local structures */
49 
50 
51 /**
52  * Get the next token from the parsed string.
53  *
54  * @return True if a token is available, false if we've hit the end.
55  */
57 {
58  // move past the previous token...if the token was pushed back,
59  // the offset is 0, so we don't really move.
60  offset += length;
61  // go past any blanks
62  skipBlanks();
63  // if we got to the end of string, return the end-of-string return
64  /*return no_token */
65  if (sourceData[offset] == '\0')
66  {
67  string = NULL; /* nll string pointer */
68  offset = 0; /* offset is zero */
69  length = 0; /* and the length is zero */
70  return false; /* return no-token indicator */
71  }
72 
73  // now check for special characters
74  switch (sourceData[offset])
75  {
76  case '=': // equals token
77  case '+': // plus token
78  case '-': // minus token
79  case '<': // less than sign
80  // point to the token start
81  string = sourceData + offset;
82  length = 1; // single character token found
83  return true; // had success
84  }
85 
86  // set the token start position
87  string = (const char *)sourceData + offset;
88  // else count the number of
89  //characters in next token
90  for (length = 0 ; sourceData[offset + length] != '\0'; length++ )
91  {
92  // contain a special character or blank?
93  if (strchr("=+-< ", sourceData [offset + length]) != NULL)
94  {
95  break; /* finished */
96  }
97  }
98  return true; /* return success */
99 }
100 
101 
102 /**
103  * Push a token back on to the stream.
104  */
106 {
107  /* just set the length to zero so */
108  /* that the current offset is used */
109  length = 0; /* for the next token scan */
110 }
111 
112 /*********************************************************************/
113 /* parse */
114 /* Will go thru the input STRING processing each token that */
115 /* matches with the TokenTable passed in. It will return either */
116 /* a zero, if all the tokens get parsed, or the error code */
117 /* from the actions table, or if there is a call what is passed */
118 /* back from it. */
119 /*********************************************************************/
120 
121 int parser(TokenDefinition *ttsp, const char *tokenString, void *userparms)
122 {
123  int result = 0; /* parse result */
124  StreamToken tokenizer(tokenString); /* single token structure */
125 
126  /* Process each token in tokenstring */
127  while (tokenizer.nextToken())
128  {
129  TokenDefinition *def;
130  // check each of the table elements
131  for ( def = ttsp; def->isValid() && !tokenizer.equals(def->token); def++);
132 
133  if (!def->isValid()) /* no token found? */
134  {
135  tokenizer.previousToken(); // push the token back
136  /* call the caller specified function*/
137  /* when a parameter is not in the */
138  /*token table */
139  result = def->callUnknown(tokenizer, userparms);
140  if (result != 0) /* get an error? */
141  {
142  return result; /* return that result */
143  }
144  }
145  else
146  {
147  /* if token is less than the valid */
148  /*minimum */
149  if (def->minlength > tokenizer.getLength())
150  {
151  /* it is considered ambiguous since */
152  /*it can match more than one of the */
153  /*valid keywords */
154  return 1; /* return a failure */
155 
156  }
157  /* Check actions table for work item */
158  for (ParseAction *actionItem = def->actions; actionItem->isValid(); actionItem++)
159  {
160  // process the action
161  if (actionItem->applyAction(ttsp, tokenizer, userparms) != 0)
162  {
163  return 1;
164  }
165  }
166  }
167  }
168  return 0; /* just return zero */
169 }
170 
171 
172 /**
173  * Apply an a parse table action.
174  *
175  * @param def The token definition this belongs to.
176  * @param token The token parsing stream.
177  * @param userparms An opaque argument value.
178  *
179  * @return 0 if the action was processed ok, 1 if it is an error condition.
180  */
181 int ParseAction::applyAction(TokenDefinition *def, StreamToken &token, void *userparms)
182 {
183  switch (action) /* check out what to do */
184  {
185  case (BitOr): /* item or'ed with the output? */
186  // Bit operations only get applied to int items
187  *int_output |= int_value;
188  return 0;
189 
190  case (BitAnd): /* and the item with output */
191  // Bit operations only get applied to int items
192  *int_output &= int_value;
193  return 0;
194  /* for a mutual field */
195  /* check where the output */
196  /* is pointing for any value - for */
197  /* the length of int */
198  /* If there is a value - return the */
199  /* errorcode */
200  case (MF):
201  /* for mutual exclusion */
202  /* check the item mask against the */
203  /* output to see if the specified */
204  /* bits are on. If any of the bits */
205  /* are on - return the errorcode */
206  return (*int_output != 0) ? 1 : 0;
207  case (MEB):
208  /* for mutual exclusion */
209  /* check the item mask against the */
210  /* output to see if the specified */
211  /* bits are on. If any of the bits */
212  /* are on - return the errorcode */
213  return (*bool_output) ? 1 : 0;
214 
215  case (MIB):
216  /* for mutual inclusion */
217  /* check the item mask against the */
218  /* output to see if the specified */
219  /* bits are on. If any of the bits */
220  /* are on - return the errorcode */
221  return (*bool_output) ? 0 : 1;
222 
223  case (ME):
224  return (*int_output & int_value) ? 1 : 0;
225  /* for mutual inclusion */
226  /* check the item mask against the */
227  /* output to see if the specified */
228  /* bits are off. If any of the bits */
229  /* are off - return the errorcode */
230  case (MI):
231  return ((*int_output & int_value) != int_value) ? 1 : 0;
232  /* for copy of item into the output */
233  /* use the c-lib memcpy function */
234  case SetItem:
235  // just directly set the item
237  return 0;
238  case SetBool:
239  // just directly set the item
241  return 0;
242 
243  /* for call - use item as function */
244  /* pointer and pass all the information available */
245  case (CallItem) :
246  return (*afp)(def, token, actionParm);
247  /* table error if there is an */
248  /* unknown actions */
249  default :
250  break;
251  }
252  return 1;
253 }
int parser(TokenDefinition *ttsp, const char *tokenString, void *userparms)
@ BitAnd
@ CallItem
@ SetBool
@ SetItem
int(* afp)(TokenDefinition *, StreamToken &, void *)
int applyAction(TokenDefinition *def, StreamToken &token, void *userparms)
bool equals(const char *token)
const char * sourceData
ParseAction * actions
int callUnknown(StreamToken &tokenizer, void *parms)