Version 6.3
Copyright © 2005 - 2012 Lowell D. Thomas
APG
  … ABNF Parser Generator
All Data Structures Files Functions Variables Typedefs Macros Pages
main.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 *******************************************************************************/
25 #include "Generator.h"
26 #include "SABNFGrammar.h"
27 #include "Grammar.h"
31 // awful globals: used here so that they can be set dynamically but not necessary in vMainAlertHandler() call list
32 void* g_vpErrCtx = NULL;
33 void* g_vpWarnCtx = NULL;
35 static G_UINT uiValidateGrammar(void* vpCatCtx, void* vpErrCtx, void* vpWarnCtx);
36 
37 // Linux OS exception handler
38 //#include <signal.h>
39 //static void vSignalHandler (int sig, siginfo_t *siginfo, void *context){
40 // printf("\n");
41 // printf("Signal Handler: signo: %d\n", siginfo->si_signo);
42 // printf("Signal Handler: errno: %d\n", siginfo->si_errno);
43 // printf("Signal Handler: code: %d\n", siginfo->si_code);
44 // exit(EXIT_FAILURE);
45 //}
46 //typedef void (*PFN_OSEXCEPTION)(void);
47 //static void vOSExceptionHandler(){
48 // int iTest;
49 // struct sigaction act;
50 // memset (&act, '\0', sizeof(act));
51 // act.sa_sigaction = &vSignalHandler;
52 // act.sa_flags = SA_SIGINFO;
53 // for(iTest = 1; iTest < _NSIG; iTest++){
54 // sigaction(iTest, &act, NULL);
55 // }
56 //}
57 
115 int main(int argc, char** argv){
116  int iReturn = EXIT_FAILURE;
117  void* vpMemCtx = NULL;
118  void* vpParserCtx = NULL;
119  void* vpCatCtx = NULL;
120  void* vpErrCtx = NULL;
121  void* vpWarnCtx = NULL;
122  char* cpInputString = NULL;
123  G_UINT uiTest;
124  G_UINT uiTrace = APG_FALSE;
125  G_UINT uiStats = APG_FALSE;
126  G_UINT uiInputStringLen = 0;
127  G_UINT uiInputStringBufLen = 0;
128  apg_achar* acpInputString = NULL;
129  CALLBACK_CTX sCallbackCtx;
130  GRAMMAR_METRICS sMetrics;
131  APG_CALLBACK saSemantic[RULE_COUNT_SABNFGRAMMAR];
132  CM_CONFIG sConfig;
133 
134  while(APG_TRUE){
136  // SET UP
138  // memory and error reporting
139  vpMemCtx = vpMemCtor();
140  MSGASSERT(vpMemCtx, "memory component constructor failed");
141  vpErrCtx = vpErrorsCtor(vpMemCtx, vMainAlertHandler);
142  MSGASSERT(vpErrCtx, "error reporting constructor failed");
143  g_vpErrCtx = vpErrCtx;
144  vpWarnCtx = vpErrorsCtor(vpMemCtx, vMainAlertHandler);
145  MSGASSERT(vpWarnCtx, "warning reporting component constructor failed");
146  g_vpWarnCtx = vpWarnCtx;
147 
149  // READ THE COMMAND LINE
151  // get the command line options
152  uiTest = uiCommandLine(&sConfig, argc, argv);
153  if(!uiTest){break;}
154  if(sConfig.uiLog){
155  // redirect of output to a log file requested on command line
156  FILE* spRedirectOut;
157  vLicenseNotice(stdout);
158  printf("%s - output redirect file\n", sConfig.caLog);
159  spRedirectOut = freopen(sConfig.caLog, "w", stdout);
160  MSGASSERT(spRedirectOut, "failed to open output redirect file");
161  }
162  if(sConfig.uiVersion){
163  vLicenseNotice(stdout);
164  break;
165  }
166  if(sConfig.uiHelp){
167  vDisplayHelp(argc, argv);
168  break;
169  }
170  if(!sConfig.uiInput){
171  printf("\n*** ");
172  printf("input file name is required\n");
173  vDisplayHelp(argc, argv);
174  break;
175  }
176  vLicenseNotice(stdout);
177  if(sConfig.uiDisplayConfig){
178  printf("\n*** ");
179  printf("configuration parameters\n");
180  vDisplayConfig(&sConfig);
181  }
182  if(sConfig.uiDisplayTypes){
183  printf("\n*** ");
184  printf("integer type sizes\n");
185  vDisplayTypeSizes(NULL);
186  }
187 
189  // PREPARE THE GRAMMAR FOR PARSING
191  // read the grammar
192  uiInputStringLen = uiGetFileSize(&sConfig.caInput[0]);
193  MSGASSERT(uiInputStringLen, "failed to get input file size - file probably does not exist");
194  uiInputStringBufLen = (sizeof(apg_achar) * 2) * (uiInputStringLen + 10);
195  cpInputString = (char*)vpMemAlloc(vpMemCtx, uiInputStringBufLen);
196  MSGASSERT(cpInputString, "failed to allocate memory for input string");
197  uiTest = uiGetFile(&sConfig.caInput[0], (void*)cpInputString);
198  MSGASSERT(uiTest, "failed to read input string");
199  if(!((cpInputString[uiInputStringLen - 1] == (char)10) || (cpInputString[uiInputStringLen - 1] == (char)13))){
200  vErrorsReport(vpWarnCtx, "Grammar: Last line has no line ending. Line end CRLF added.");
201  cpInputString[uiInputStringLen] = (char)13;
202  uiInputStringLen++;
203  cpInputString[uiInputStringLen] = (char)10;
204  uiInputStringLen++;
205  }
206  cpInputString[uiInputStringLen] = 0;
207  // catalog the lines for error reporting of line numbers
208  vpCatCtx = vpCatalogCtor(vpMemCtx, vMainAlertHandler);
209  MSGASSERT(vpCatCtx, "line number catalog constructor failed");
210  uiTest = uiCatalogLines(vpCatCtx, cpInputString, uiInputStringLen);
211  if(cpInputString && uiInputStringLen && sConfig.uiDisplayGrammar){
212  printf("\n*** ");
213  printf("annotated input string\n");
214  vCatalogDisplay(vpCatCtx, stdout);
215  }
216  MSGASSERT(uiTest, "line number cataloging failed");
217  // validate the grammar
218  uiTest = uiValidateGrammar(vpCatCtx, vpErrCtx, vpWarnCtx);
219  MSGASSERT(uiTest, "grammar validation failed");
220  // convert input string to alphabet characters for the parser
221  acpInputString = (apg_achar*)vpMemAlloc(vpMemCtx, uiInputStringLen + 10);
222  MSGASSERT(acpInputString, "failed to allocate memory for alphabet character translation of input string");
223  vCharToAChar(acpInputString, cpInputString, uiInputStringLen);
224 
226  // PARSE THE GRAMMAR
228  // get the parser context
229  vpParserCtx = vpParserCtor(vpParserInit_SABNFGrammar, vMainAlertHandler);
230  MSGASSERT(vpParserCtx, "parser constructor failed");
231  vSemanticInit(saSemantic);
232  vParserAstInitCallbacks(vpParserCtx, saSemantic, NULL); // define the AST for translation
233  if(uiStats){uiParserStatsEnable(vpParserCtx, APG_TRUE);} // enable statistics gathering
234  if(uiTrace){uiParserTraceEnable(vpParserCtx, APG_TRUE);} // enable tracing
235  vCallbackInit(vpMemCtx, &sCallbackCtx); // provisions for the callback functions
236  sCallbackCtx.pfnAlertHandler = vMainAlertHandler;
237  sCallbackCtx.vpErrCtx = vpErrCtx;
238  sCallbackCtx.vpWarnCtx = vpWarnCtx;
239  sCallbackCtx.vpLineCatalogCtx = vpCatCtx;
240  uiTest = uiParserSyntaxAnalysis(vpParserCtx, RULE_SABNFGRAMMAR_FILE, acpInputString, uiInputStringLen, &sCallbackCtx);
241  MSGASSERT(uiTest, "parser syntax analysis failed");
242  if(sConfig.uiDisplayState){
243  printf("\n*** ");
244  printf("generator state\n");
245  vDisplayParserState(NULL, vpParserCtx);
246  }
247  if(sConfig.uiDisplayAst){
248  printf("\n*** ");
249  printf("AST\n");
250  vDisplayAstRecords(NULL, vpParserCtx);
251  }
252  if(uiErrorsCount(vpErrCtx)){
253  break;
254  }
255 
257  // APG, THE PARSER GENERATOR: GENERATE A PARSER FROM THE INPUT GRAMMAR
259  uiParserAstTranslate(vpParserCtx, NULL, NULL, &sCallbackCtx);
260  if(uiErrorsCount(vpErrCtx)){break;}
261  if(sConfig.uiDisplayGrammarMetrics){
262  // display of grammar metrics requested on command line
263  printf("\n*** ");
264  printf("grammar metrics\n");
265  vGrammarMetrics(&sCallbackCtx, &sMetrics);
266  vDisplayGrammarMetrics(&sMetrics);
267  }
268  if(sConfig.uiDisplayRules){
269  // display of opcodes in human-readable format requested (may generate lots of output)
270  printf("\n*** ");
271  printf("rules\n");
272  vGeneratorDisplayRules(&sCallbackCtx);
273  }
274  if(sConfig.uiDisplayOpcodes){
275  // display of opcodes in human-readable format requested (may generate lots of output)
276  printf("\n*** ");
277  printf("opcodes (in human-readable format)n");
278  vGeneratorDisplayOpcodes(&sCallbackCtx);
279  }
280 
282  // GRAMMAR ATTRIBUTES
284  // attributes
285  ATTRS_CTX* vpAttrsCtx = (ATTRS_CTX*)vpAttrsCtor(&sCallbackCtx);
286  MSGASSERT(vpAttrsCtx, "attributes component constructor failed");
287  uiTest = uiAttributes(vpAttrsCtx);
288  if(uiTest){
289  if(sConfig.uiDisplayAttributes){
290  printf("\n*** ");
291  printf("rule reference types\n");
292  vDisplayRuleDependencyTypes(vpAttrsCtx);
293  printf("\n*** ");
294  printf("grammar attributes\n");
295  vDisplayAttrs(vpAttrsCtx);
296  }
297  } else{
298  vErrorsReport(vpErrCtx, "Attributes error: unparsable attributes found - displaying attributes");
299  printf("\n*** ");
300  printf("rule reference types\n");
301  vDisplayRuleDependencyTypes(vpAttrsCtx);
302  printf("\n*** ");
303  printf("grammar attributes\n");
304  vDisplayAttrs(vpAttrsCtx);
305  break;
306  }
307 
309  // OUTPUT THE GENERATED PARSER IN THE REQUESTED LANGUAGES
311  uiTrace = APG_FALSE;
312  if(sConfig.uiC){
313  char caFileName[1024];
314  char* cpPath = NULL;
315  if(sConfig.uiOutput){cpPath = &sConfig.caOutput[0];}
316  printf("\n*** ");
317  printf("C parser generated\n");
318  vGenerateCHeader(&sCallbackCtx, cpPath, &sConfig.caC[0], cpInputString, caFileName, 1024);
319  printf(" %s\n", caFileName);
320  vGenerateCSource(&sCallbackCtx, cpPath, &sConfig.caC[0], caFileName, 1024);
321  printf(" %s\n", caFileName);
322  uiTrace = APG_TRUE;
323  }
324  if(sConfig.uiCpp){
325  char caFileName[1024];
326  char* cpPath = NULL;
327  if(sConfig.uiOutput){cpPath = &sConfig.caOutput[0];}
328  printf("\n*** ");
329  printf("C++ parser generated\n");
330  vGenerateCppHeader(&sCallbackCtx, cpPath, &sConfig.caCpp[0], cpInputString, caFileName, 1024);
331  printf(" %s\n", caFileName);
332  vGenerateCppSource(&sCallbackCtx, cpPath, &sConfig.caCpp[0], caFileName, 1024);
333  printf(" %s\n", caFileName);
334  uiTrace = APG_TRUE;
335  }
336  if(!uiTrace){printf("<no parser output requested>\n");}
337 
338  // success
339  iReturn = EXIT_SUCCESS;
340  break;
341  }
343  // DIPSLAY ERRORS AND WARNINGS
345  if(sConfig.uiDisplayWarnings && vpWarnCtx && (G_UINT)uiErrorsCount(vpWarnCtx)){
346  printf("\n*** ");
347  printf("%lu warning(s) detected\n", (printf_uint)uiErrorsCount(vpWarnCtx));
348  char* cpMsg = cpErrorsIterInit(vpWarnCtx);
349  G_UINT uiError = 0;
350  while(cpMsg){
351  printf("%lu: %s\n", (G_UINT)uiError, cpMsg);
352  uiError++;
353  cpMsg = cpErrorsIterNext(vpWarnCtx);
354  }
355  }
356  if(vpErrCtx && uiErrorsCount(vpErrCtx)){
357  printf("\n*** ");
358  printf("%lu error(s) detected\n", (printf_uint)uiErrorsCount(vpErrCtx));
359  char* cpMsg = cpErrorsIterInit(vpErrCtx);
360  G_UINT uiError = 0;
361  while(cpMsg){
362  printf("%lu: %s\n", (G_UINT)uiError, cpMsg);
363  uiError++;
364  cpMsg = cpErrorsIterNext(vpErrCtx);
365  }
366  }
367 
368  // success
369  vMemDtor(vpMemCtx);
370  return iReturn;
371 }
372 
373 static G_UINT uiValidateGrammar(void* vpCatCtx, void* vpErrCtx, void* vpWarnCtx){
374  G_UINT uiRet = APG_TRUE;
375  CATALOG_CTX* spCtx = (CATALOG_CTX*)vpCatCtx;
376  CATALOG_LINE* spLine = NULL;
377  unsigned char* ucpChar;
378  G_UINT uiChar;
379  G_UINT uiHasNonABNFLineEnd = APG_FALSE;
380  char caBuffer[2 * MAX_DISPLAY_LINE_LEN + 10];
381  if(spCtx){
382  spLine = spCatalogIterInit(vpCatCtx);
383  while(spLine){
384  if(spLine->uiLineEndLen == 1){uiHasNonABNFLineEnd = APG_TRUE;}
385  uiChar = 0;
386  for(ucpChar = (unsigned char*)spLine->cpBeg; ucpChar < (unsigned char*)spLine->cpEnd; ucpChar++, uiChar++){
387  G_UINT uiError = APG_FALSE;
388  if(*ucpChar < (unsigned char)9){uiError = APG_TRUE;}
389  else if(*ucpChar > (unsigned char)10 && *ucpChar < (unsigned char)13){uiError = APG_TRUE;}
390  else if(*ucpChar > (unsigned char)13 && *ucpChar < (unsigned char)32){uiError = APG_TRUE;}
391  else if(*ucpChar > (unsigned char)127){uiError = APG_TRUE;}
392  if(uiError){
393  // report error
394  G_UINT n = 0;
395  uiRet = APG_FALSE;
396  n += sprintf(&caBuffer[n],
397  "Grammar: invalid character: line no: %lu: character no: %lu: character: %lu\n ",
398  (G_UINT)spLine->uiLineNo, (G_UINT)(spLine->uiBegChar + uiChar), (G_UINT)*ucpChar);
399  vCatalogDisplayLine(spLine, &caBuffer[n], MAX_DISPLAY_LINE_LEN);
400  vErrorsReport(vpErrCtx, &caBuffer[0]);
401  }
402  }
403  spLine = spCatalogIterNext(vpCatCtx);
404  }
405  }
406  if(uiHasNonABNFLineEnd){
407  vErrorsReport(vpWarnCtx, "Grammar: has non-ABNF(non-CRLF) line endings");
408  }
409  return uiRet;
410 }
411 
413 void vMainAlertHandler(unsigned int uiLine, const char* cpFile){
414  printf("\n");
415  printf("ERROR: an unrecoverable error was encountered at the following file and line number:\n");
416  printf(" line: %lu\n", (G_UINT)uiLine);
417  printf(" file: %s\n", cpFile);
418  printf("\n");
419  if(g_vpErrCtx && uiErrorsCount(g_vpErrCtx)){
420  char* cpMsg = cpErrorsIterInit(g_vpErrCtx);
421  G_UINT uiError = 0;
422  if(cpMsg){
423  printf("\n*** %lu error(s) reported to the error log ***\n", (G_UINT)uiErrorsCount(g_vpErrCtx));
424  while(cpMsg){
425  printf("%lu: %s\n", (G_UINT)uiError, cpMsg);
426  uiError++;
427  cpMsg = cpErrorsIterNext(g_vpErrCtx);
428  }
429  }
430  }
431  if(g_vpWarnCtx && uiErrorsCount(g_vpWarnCtx)){
432  char* cpMsg = cpErrorsIterInit(g_vpWarnCtx);
433  G_UINT uiError = 0;
434  if(cpMsg){
435  printf("\n*** %lu warning(s) reported to the warning log ***\n", (G_UINT)uiErrorsCount(g_vpWarnCtx));
436  while(cpMsg){
437  printf("%lu: %s\n", (G_UINT)uiError, cpMsg);
438  uiError++;
439  cpMsg = cpErrorsIterNext(g_vpWarnCtx);
440  }
441  }
442  }
443  printf("\n");
444  printf("*** exit(EXIT_FAILURE) called ***\n");
445  exit(EXIT_FAILURE);
446 }
447 
448 void vMsgAssert(char* cpMsg, unsigned int uiLine, char* cpFile){
449  char caAssertBuffer[4096];
450  char* cpAssertBuffer = &caAssertBuffer[0];
451  G_UINT uiLen;
452  char* cpNoMsg = "<no message>";
453  if(!cpMsg){cpMsg = cpNoMsg;}
454  uiLen = strlen(cpMsg);
455  if(!uiLen){cpMsg = cpNoMsg;}
456  sprintf(cpAssertBuffer, "line: %lu: file: %s: msg: %s", (G_UINT)uiLine, cpFile, cpMsg);
457  vErrorsReport(g_vpErrCtx, cpAssertBuffer);
458  vMainAlertHandler(uiLine, cpFile);
459 }
vDisplayParserState
void vDisplayParserState(FILE *spOut, void *vpParserCtx)
Definition: Utilities.c:373
uiParserAstTranslate
apg_uint uiParserAstTranslate(void *vpCtx, APG_CALLBACK *pfnRuleCallbacks, APG_CALLBACK *pfnUdtCallbacks, void *vpData)
Definition: Parser.c:361
vParserAstInitCallbacks
void vParserAstInitCallbacks(void *vpCtx, APG_CALLBACK *spRuleCallbacks, APG_CALLBACK *spUdtCallbacks)
Definition: Parser.c:316
vMemDtor
void vMemDtor(void *vpCtx)
Definition: Memory.c:97
uiParserStatsEnable
apg_uint uiParserStatsEnable(void *vpCtx, apg_uint uiEnable)
Definition: Parser.c:403
APG_CALLBACK
apg_uint(* APG_CALLBACK)(APG_CBDATA *spData)
Definition: Apg.h:515
vpMemCtor
void * vpMemCtor()
Definition: Memory.c:77
vpMemAlloc
void * vpMemAlloc(void *vpCtx, apg_uint uiBytes)
Definition: Memory.c:130
uiGetFileSize
apg_uint uiGetFileSize(const char *cpFileName)
Definition: Files.c:40
vDisplayAstRecords
void vDisplayAstRecords(FILE *spOut, void *vpParserCtx)
Definition: Utilities.c:183
APG_TRUE
#define APG_TRUE
Definition: Apg.h:187
vLicenseNotice
void vLicenseNotice(FILE *spFile)
Definition: Utilities.c:442
apg_achar
unsigned char apg_achar
Definition: Apg.h:183
printf_uint
unsigned long int printf_uint
Definition: ApgUtilities.h:52
main
int main(int argc, char **argv)
Definition: main.c:115
vpParserCtor
void * vpParserCtor(void *vpParserInit, PFN_ALERT pfnAlertHandler)
Definition: Parser.c:58
APG_FALSE
#define APG_FALSE
Definition: Apg.h:190
uiGetFile
apg_uint uiGetFile(const char *cpFileName, void *vpBuffer)
Definition: Files.c:71
uiParserTraceEnable
apg_uint uiParserTraceEnable(void *vpCtx, apg_uint uiEnable)
Definition: Parser.c:452
vCharToAChar
void vCharToAChar(apg_achar *acpAChars, const char *cpChars, apg_uint uiLen)
Definition: Tools.c:79
vDisplayTypeSizes
void vDisplayTypeSizes(FILE *spOut)
Definition: Utilities.c:279
uiParserSyntaxAnalysis
apg_uint uiParserSyntaxAnalysis(void *vpCtx, apg_uint uiStartRule, const apg_achar *acpSrc, apg_uint uiSrcLen, void *vpData)
Definition: Parser.c:228
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.