Version 6.3
Copyright © 2005 - 2012 Lowell D. Thomas
APG
  … ABNF Parser Generator
All Data Structures Files Functions Variables Typedefs Macros Pages
UdtLib.c
Go to the documentation of this file.
1 /*******************************************************************************
2  APG Version 6.3
3  Copyright (C) 2005 - 2012 Lowell D. Thomas, all rights reserved
4 
5  author: Lowell D. Thomas
6  email: lowell@coasttocoastresearch.com
7  website: http://www.coasttocoastresearch.com
8 
9  This program is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see
21  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
22  or write to the Free Software Foundation, Inc.,
23  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 *******************************************************************************/
39 #include "Apg.h"
40 
42 #define UDTLIB_TAB (apg_achar)9
43 #define UDTLIB_LF (apg_achar)10
44 #define UDTLIB_CR (apg_achar)13
45 #define UDTLIB_SP (apg_achar)32
46 #define UDTLIB_DOUBLE_QUOTE (apg_achar)34
47 #define UDTLIB_SINGLE_QUOTE (apg_achar)39
48 #define UDTLIB_STAR (apg_achar)42
49 #define UDTLIB_SLASH (apg_achar)47
50 #define UDTLIB_SEMI (apg_achar)59
51 #define UDTLIB_HYPHEN (apg_achar)45
52 #define UDTLIB_0 (apg_achar)48
53 #define UDTLIB_9 (apg_achar)57
54 #define UDTLIB_UPPER_A (apg_achar)65
55 #define UDTLIB_UPPER_F (apg_achar)70
56 #define UDTLIB_UPPER_Z (apg_achar)90
57 #define UDTLIB_UNDERSCORE (apg_achar)95
58 #define UDTLIB_LOWER_A (apg_achar)97
59 #define UDTLIB_LOWER_F (apg_achar)102
60 #define UDTLIB_LOWER_X (apg_achar)120
61 #define UDTLIB_LOWER_Z (apg_achar)122
62 #define UDTLIB_PRINT_MIN (apg_achar)32
63 #define UDTLIB_PRINT_MAX (apg_achar)127
64 
65 // UDT STATIC HELPERS
68 static apg_uint uiIsAlpha(apg_achar acChar){
69  return ((acChar >= UDTLIB_UPPER_A && acChar <= UDTLIB_UPPER_Z) ||
70  (acChar >= UDTLIB_LOWER_A && acChar <= UDTLIB_LOWER_Z));
71 }
72 static apg_uint uiIsDigit(apg_achar acChar){
73  return ((acChar >= UDTLIB_0 && acChar <= UDTLIB_9));
74 }
75 static apg_uint uiIsHexDigit(apg_achar acChar){
76  return ((acChar >= UDTLIB_0 && acChar <= UDTLIB_9) ||
77  (acChar >= UDTLIB_UPPER_A && acChar <= UDTLIB_UPPER_F) ||
78  (acChar >= UDTLIB_LOWER_A && acChar <= UDTLIB_LOWER_F));
79 }
80 static apg_uint uiLineEnd(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
81  apg_uint uiRet = 0;
82  if(uiMaxPhraseLength > 0){
83  if(acpPhrase[0] == UDTLIB_LF){uiRet = 1;}
84  else if(acpPhrase[0] == UDTLIB_CR){
85  if(uiMaxPhraseLength > 1 && acpPhrase[1] == UDTLIB_LF){uiRet = 2;}
86  else{uiRet = 1;}
87  }
88  }
89  return uiRet;
90 }
91 //static apg_uint uiLineContinue(apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
92 // apg_uint uiRet = 0;
93 // apg_uint uiTest;
94 // if((0 < uiMaxPhraseLength) && (uiTest = uiLineEnd(&acpPhrase[0], uiMaxPhraseLength))){
95 // if((uiTest < uiMaxPhraseLength) && acpPhrase[uiTest] == UDTLIB_SP){
96 // uiRet = uiTest + 1;
97 // }
98 // }
99 // return uiRet;
100 //}
101 static apg_uint uiAny(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
102  apg_uint uiPhraseCount = 0;
103  apg_achar cAChar;
104  while(uiPhraseCount < uiMaxPhraseLength){
105  cAChar = acpPhrase[uiPhraseCount];
106  if(cAChar == UDTLIB_TAB || (cAChar >= UDTLIB_PRINT_MIN && cAChar <= UDTLIB_PRINT_MAX)){
107  uiPhraseCount++;
108  } else{break;}
109  }
110  return uiPhraseCount;
111 }
112 static apg_uint uiAlphaNum(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
113  apg_uint uiPhraseCount = 0;
114  if(uiPhraseCount < uiMaxPhraseLength && uiIsAlpha(acpPhrase[0])){
115  uiPhraseCount++;
116  while(uiPhraseCount < uiMaxPhraseLength){
117  if(uiIsAlpha(acpPhrase[uiPhraseCount]) ||
118  uiIsDigit(acpPhrase[uiPhraseCount])){
119  uiPhraseCount++;
120  } else{break;}
121  }
122  }
123  return uiPhraseCount;
124 }
125 static apg_uint uiAlphaNumPlus(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength, apg_achar acExtraChar){
126  apg_uint uiPhraseCount = 0;
127  if(uiPhraseCount < uiMaxPhraseLength && uiIsAlpha(acpPhrase[0])){
128  uiPhraseCount++;
129  while(uiPhraseCount < uiMaxPhraseLength){
130  if((acpPhrase[uiPhraseCount] == acExtraChar) ||
131  uiIsAlpha(acpPhrase[uiPhraseCount]) ||
132  uiIsDigit(acpPhrase[uiPhraseCount])){
133  uiPhraseCount++;
134  } else{break;}
135  }
136  }
137  return uiPhraseCount;
138 }
139 static apg_uint uiSingleQuotedString(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
140  apg_uint uiPhraseCount = 0;
141  apg_achar cAChar;
142  if(uiPhraseCount < uiMaxPhraseLength && (acpPhrase[0] == UDTLIB_SINGLE_QUOTE)){
143  uiPhraseCount++;
144  while(uiPhraseCount < uiMaxPhraseLength){
145  cAChar = acpPhrase[uiPhraseCount];
146  if(cAChar == UDTLIB_TAB ||
147  (cAChar >= UDTLIB_PRINT_MIN && cAChar < UDTLIB_SINGLE_QUOTE) ||
148  (cAChar >UDTLIB_SINGLE_QUOTE && cAChar < UDTLIB_PRINT_MAX)){uiPhraseCount++;}
149  else{break;}
150  }
151  if(uiPhraseCount < uiMaxPhraseLength && (acpPhrase[uiPhraseCount] == UDTLIB_SINGLE_QUOTE)){uiPhraseCount++;}
152  else{uiPhraseCount = 0;}
153  }
154  return uiPhraseCount;
155 }
156 static apg_uint uiDoubleQuotedString(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
157  apg_uint uiPhraseCount = 0;
158  apg_achar cAChar;
159  if(uiPhraseCount < uiMaxPhraseLength && (acpPhrase[0] == UDTLIB_DOUBLE_QUOTE)){
160  uiPhraseCount++;
161  while(uiPhraseCount < uiMaxPhraseLength){
162  cAChar = acpPhrase[uiPhraseCount];
163  if(cAChar == UDTLIB_TAB ||
164  (cAChar >= UDTLIB_PRINT_MIN && cAChar < UDTLIB_DOUBLE_QUOTE) ||
165  (cAChar >UDTLIB_DOUBLE_QUOTE && cAChar < UDTLIB_PRINT_MAX)){uiPhraseCount++;}
166  else{break;}
167  }
168  if(uiPhraseCount < uiMaxPhraseLength && (acpPhrase[uiPhraseCount] == UDTLIB_DOUBLE_QUOTE)){uiPhraseCount++;}
169  else{uiPhraseCount = 0;}
170  }
171  return uiPhraseCount;
172 }
173 static apg_uint uiSemiComment(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
174  apg_uint uiPhraseCount = 0;
175  apg_uint uiLeft = uiMaxPhraseLength;
176  apg_uint uiTest;
177  if(uiLeft > 0 && acpPhrase[0] == UDTLIB_SEMI){
178  uiPhraseCount++;
179  uiLeft--;
180  while(uiPhraseCount < uiMaxPhraseLength){
181  if((uiTest = uiAny(&acpPhrase[uiPhraseCount], uiLeft))){
182  uiLeft -= uiTest;
183  uiPhraseCount += uiTest;
184  } else{break;}
185  }
186  }
187  return uiPhraseCount;
188 }
189 static apg_uint uiCppComment(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
190  apg_uint uiPhraseCount = 0;
191  apg_uint uiLeft = uiMaxPhraseLength;
192  apg_uint uiTest;
193  if(uiLeft > 1 && acpPhrase[0] == UDTLIB_SLASH && acpPhrase[1] == UDTLIB_SLASH){
194  uiPhraseCount += 2;
195  uiLeft -= 2;
196  while(uiPhraseCount < uiMaxPhraseLength){
197  if((uiTest = uiAny(&acpPhrase[uiPhraseCount], uiLeft))){
198  uiLeft -= uiTest;
199  uiPhraseCount += uiTest;
200  } else{break;}
201  }
202  }
203  return uiPhraseCount;
204 }
205 static apg_uint uiAnyButStarSlash(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
206  apg_uint uiPhraseCount = 0;
207  apg_achar cAChar;
208  while(uiPhraseCount < uiMaxPhraseLength){
209  cAChar = acpPhrase[uiPhraseCount];
210  if(uiPhraseCount+1<uiMaxPhraseLength && cAChar == UDTLIB_STAR && acpPhrase[uiPhraseCount+1] == UDTLIB_SLASH){break;}
211  if(cAChar == UDTLIB_TAB || (cAChar >= UDTLIB_PRINT_MIN && cAChar <= UDTLIB_PRINT_MAX)){
212  uiPhraseCount++;
213  } else{break;}
214  }
215  return uiPhraseCount;
216 }
217 static apg_uint uiCComment(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
218  apg_uint uiPhraseCount = 0;
219  apg_uint uiLeft = uiMaxPhraseLength;
220  apg_uint uiTest;
221  if(uiLeft > 1 && acpPhrase[0] == UDTLIB_SLASH && acpPhrase[1] == UDTLIB_STAR){
222  uiPhraseCount += 2;
223  uiLeft -= 2;
224  while(uiPhraseCount < uiMaxPhraseLength){
225  if(uiLeft > 1 && acpPhrase[uiPhraseCount] == UDTLIB_STAR && acpPhrase[uiPhraseCount + 1] == UDTLIB_SLASH){
226  uiPhraseCount += 2;
227  break;
228  }
229  if((uiTest = uiAnyButStarSlash(&acpPhrase[uiPhraseCount], uiLeft))){
230  uiLeft -= uiTest;
231  uiPhraseCount += uiTest;
232  } else if(uiLeft > 0 && (acpPhrase[uiPhraseCount] == UDTLIB_CR || acpPhrase[uiPhraseCount] == UDTLIB_LF)){
233  uiLeft--;
234  uiPhraseCount++;
235  } else{break;}
236 
237  }
238  }
239  return uiPhraseCount;
240 }
241 static apg_uint uiWsp(const apg_achar* acpPhrase, apg_uint uiMaxPhraseLength){
242  apg_uint uiPhraseCount = 0;
243  apg_uint uiLeft = uiMaxPhraseLength;
244 // apg_uint uiTest;
245  while(uiLeft > 0){
246  if(acpPhrase[uiPhraseCount] == UDTLIB_SP){uiLeft--;}
247  else if(acpPhrase[uiPhraseCount] == UDTLIB_TAB){uiLeft--;}
248 
249  // uncomment to include line continuations as white space
250 // else if((uiTest = uiLineContinue(&acpPhrase[uiPhraseCount], uiLeft))){uiLeft -= uiTest;}
251 
252  // uncomment any or all of the following to include comments as white space
253 // else if((uiTest = uiSemiComment(&acpPhrase[uiPhraseCount], uiLeft))){uiLeft -= uiTest;}
254 // else if((uiTest = uiCppComment(&acpPhrase[uiPhraseCount], uiLeft))){uiLeft -= uiTest;}
255 // else if((uiTest = uiCComment(&acpPhrase[uiPhraseCount], uiLeft))){uiLeft -= uiTest;}
256  else{break;}
257  uiPhraseCount = uiMaxPhraseLength - uiLeft;
258  }
259 
260  return uiPhraseCount;
261 }
262 
264 // UDT CALLBACK LIBRARY
266 
281  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
282  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
283  spData->uiPhraseLength = uiWsp(acpPhrase, uiMaxPhraseLength);
284  return 0;
285 }
286 
302  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
303  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
304  spData->uiPhraseLength = uiWsp(acpPhrase, uiMaxPhraseLength);
305  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
306  return 0;
307 }
308 
321  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
322  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
323  spData->uiPhraseLength = uiLineEnd(acpPhrase, uiMaxPhraseLength);
324  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
325  return 0;
326 }
327 
338  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
339  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
340  spData->uiPhraseLength = uiAny(acpPhrase, uiMaxPhraseLength);
341  return 0;
342 }
343 
355  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
356  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
357  spData->uiPhraseLength = uiSemiComment(acpPhrase, uiMaxPhraseLength);
358  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
359  return 0;
360 }
361 
373  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
374  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
375  spData->uiPhraseLength = uiCppComment(acpPhrase, uiMaxPhraseLength);
376  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
377  return 0;
378 }
379 
396  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
397  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
398  spData->uiPhraseLength = uiCComment(acpPhrase, uiMaxPhraseLength);
399  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
400  return 0;
401 }
402 
415  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
416  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
417  spData->uiPhraseLength = uiAlphaNum(acpPhrase, uiMaxPhraseLength);
418  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
419  return 0;
420 }
421 
435  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
436  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
437  spData->uiPhraseLength = uiAlphaNumPlus(acpPhrase, uiMaxPhraseLength, UDTLIB_HYPHEN);
438  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
439  return 0;
440 }
441 
455  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
456  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
457  spData->uiPhraseLength = uiAlphaNumPlus(acpPhrase, uiMaxPhraseLength, UDTLIB_UNDERSCORE);
458  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
459  return 0;
460 }
461 
473  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
474  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
475  apg_uint uiPhraseCount = 0;
476  while(uiPhraseCount < uiMaxPhraseLength){
477  if(uiIsDigit(acpPhrase[uiPhraseCount])){uiPhraseCount++;}
478  else{break;}
479  }
480  if(uiPhraseCount){spData->uiPhraseLength = uiPhraseCount;}
481  else{spData->uiPhraseLength = APG_UNDEFINED;};
482  return 0;
483 }
484 
496  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
497  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
498  apg_uint uiPhraseCount = 0;
499  if((uiPhraseCount + 1) < uiMaxPhraseLength){
500  if((acpPhrase[uiPhraseCount] == UDTLIB_0) &&
501  (acpPhrase[uiPhraseCount + 1] == UDTLIB_LOWER_X)){
502  uiPhraseCount += 2;
503  while(uiPhraseCount < uiMaxPhraseLength){
504  if(uiIsHexDigit(acpPhrase[uiPhraseCount])){uiPhraseCount++;}
505  else{break;}
506  }
507  }
508  }
509  if(uiPhraseCount){spData->uiPhraseLength = uiPhraseCount;}
510  else{spData->uiPhraseLength = APG_UNDEFINED;};
511  return 0;
512 }
513 
526  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
527  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
528  apg_uint uiTest;
529  if((uiTest = uiSingleQuotedString(acpPhrase, uiMaxPhraseLength))){spData->uiPhraseLength = uiTest;}
530  else if((uiTest = uiDoubleQuotedString(acpPhrase, uiMaxPhraseLength))){spData->uiPhraseLength = uiTest;}
531  else{spData->uiPhraseLength = APG_UNDEFINED;}
532  return 0;
533 }
534 
545  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
546  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
547  spData->uiPhraseLength = uiSingleQuotedString(acpPhrase, uiMaxPhraseLength);
548  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
549  return 0;
550 }
551 
562  const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;
563  apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;
564  spData->uiPhraseLength = uiDoubleQuotedString(acpPhrase, uiMaxPhraseLength);
565  if(!spData->uiPhraseLength){spData->uiPhraseLength = APG_UNDEFINED;}
566  return 0;
567 }
uiUdtLib_u_alphanum_under
apg_uint uiUdtLib_u_alphanum_under(APG_CBDATA *spData)
Definition: UdtLib.c:454
APG_CBDATA::acpSrc
const apg_achar * acpSrc
Definition: Apg.h:455
uiCppComment
apg_uint uiCppComment(APG_CBDATA *spData)
Definition: Callbacks.c:182
uiUdtLib_u_doublequotedstring
apg_uint uiUdtLib_u_doublequotedstring(APG_CBDATA *spData)
Definition: UdtLib.c:561
apg_uint
unsigned int apg_uint
Definition: Apg.h:169
uiLineEnd
apg_uint uiLineEnd(APG_CBDATA *spData)
Definition: Callbacks.c:282
uiUdtLib_u_decnum
apg_uint uiUdtLib_u_decnum(APG_CBDATA *spData)
Definition: UdtLib.c:472
APG_CBDATA::uiPhraseOffset
apg_uint uiPhraseOffset
Definition: Apg.h:457
uiUdtLib_e_any
apg_uint uiUdtLib_e_any(APG_CBDATA *spData)
Definition: UdtLib.c:337
Apg.h
Required header file for all APG-generated parsers. Contains important configuration macros and decla...
uiCComment
apg_uint uiCComment(APG_CBDATA *spData)
Definition: Callbacks.c:198
APG_CBDATA::uiPhraseLength
apg_uint uiPhraseLength
Definition: Apg.h:459
uiUdtLib_u_alphanum_hyphen
apg_uint uiUdtLib_u_alphanum_hyphen(APG_CBDATA *spData)
Definition: UdtLib.c:434
uiSemiComment
apg_uint uiSemiComment(APG_CBDATA *spData)
Definition: Callbacks.c:163
apg_achar
unsigned char apg_achar
Definition: Apg.h:183
uiUdtLib_u_cpp_comment
apg_uint uiUdtLib_u_cpp_comment(APG_CBDATA *spData)
Definition: UdtLib.c:372
uiUdtLib_u_singlequotedstring
apg_uint uiUdtLib_u_singlequotedstring(APG_CBDATA *spData)
Definition: UdtLib.c:544
APG_CBDATA
The data structure passed to all syntax and AST callback functions, both rule and UDT.
Definition: Apg.h:453
APG_CBDATA::uiSrcLen
apg_uint uiSrcLen
Definition: Apg.h:456
uiUdtLib_e_owsp
apg_uint uiUdtLib_e_owsp(APG_CBDATA *spData)
Definition: UdtLib.c:280
APG_UNDEFINED
#define APG_UNDEFINED
Definition: Apg.h:194
uiUdtLib_u_lineend
apg_uint uiUdtLib_u_lineend(APG_CBDATA *spData)
Definition: UdtLib.c:320
uiUdtLib_u_alphanum
apg_uint uiUdtLib_u_alphanum(APG_CBDATA *spData)
Definition: UdtLib.c:414
uiUdtLib_u_c_comment
apg_uint uiUdtLib_u_c_comment(APG_CBDATA *spData)
Definition: UdtLib.c:395
uiUdtLib_u_quotedstring
apg_uint uiUdtLib_u_quotedstring(APG_CBDATA *spData)
Definition: UdtLib.c:525
uiUdtLib_u_semi_comment
apg_uint uiUdtLib_u_semi_comment(APG_CBDATA *spData)
Definition: UdtLib.c:354
uiUdtLib_u_hexnum
apg_uint uiUdtLib_u_hexnum(APG_CBDATA *spData)
Definition: UdtLib.c:495
uiUdtLib_u_wsp
apg_uint uiUdtLib_u_wsp(APG_CBDATA *spData)
Definition: UdtLib.c:301
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/licenses.html or write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.