Version 6.3
Copyright © 2005 - 2012 Lowell D. Thomas
APG
  … ABNF Parser Generator
All Data Structures Files Functions Variables Typedefs Macros Pages
Utilities.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 "ApgUtilities.h"
29 typedef struct{
30  APG_STAT* spStat;
31  apg_uint uiIndex;
32  char* cpName;
33 } APG_STATS_SORT;
35 static apg_uint uiIndent(apg_uint uiIndent, char* cpBuffer, apg_uint uiBufferLen);
36 static void vPrintOperatorLine(FILE* spOut, char* cpOp, APG_STAT* spNode);
37 static void vPrintOperatorList(FILE* spOut, APG_NAME_STAT* spNameStats, apg_uint uiCount, apg_uint uiType);
38 static void vDisplayOp(APG_PARSER_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiOpIndex);
39 static void vIndentPrint(FILE* spOut, apg_uint uiIndent);
40 static void vRootOpen(FILE* spOut, apg_uint uiLines, apg_uint uiNodes);
41 static void vRootClose(FILE* spOut);
42 static void vNodeOpen(FILE* spOut, apg_uint uiId, char* cpName);
43 static void vNodeClose(FILE* spOut, apg_uint uiId, char* cpName);
44 static void vPhraseText(FILE* spOut, const apg_achar* acpPhrase, apg_uint uiLength);
45 static void vPhrase(FILE* spOut, apg_uint uiOffset, apg_uint uiLength, const apg_achar* acpPhrase);
46 static void vPrintHeader(FILE* spOut);
47 static void vPrintLine(FILE* spOut, char* cpLine, apg_uint uiLine, apg_uint uiOffset, apg_uint uiLineLen);
48 static apg_uint uiAddNonAscii(char* cpAdd, char cChar);
49 
50 
52 // DISPLAYS
54 
62 void vDisplayAscii(FILE* spOut, const char* cpSrc, apg_uint uiSrcLen){
63  apg_uint uiBufLen = 5*uiSrcLen;
64  char caBuffer[uiBufLen + 10];
65  char* cpLine = &caBuffer[0];
66  char* cpEllipsis = "...";
67  char* cpEof = "<EOF>";
68  apg_uint uiOffset = 0;
69  apg_uint uiSkipAddingCharacters;
70  apg_uint uiLineLen = 0;
71  apg_uint uiLineNo = 1;
72  apg_uint i;
73  char cChar;
74 
75  if(spOut == NULL){spOut = stdout;}
76  if(!(cpSrc && cpSrc[0])){
77  fprintf(spOut, "vDisplaySourceLines: spSrc may not be NULL or empty\n");
78  return;
79  }
80 
81  vPrintHeader(spOut);
82  uiSkipAddingCharacters = APG_FALSE;
83  uiOffset = 0;
84  uiLineLen = 0;
85  uiLineNo = 1;
86  cpLine = &caBuffer[0];
87  for(i = 0; i < uiSrcLen; i++){
88  cChar = cpSrc[i];
89  if(cChar == 13){
90  if(cpSrc[i+1] == 10){
91  // CRLF line end
92  uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
93  uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cpSrc[i+1]);
94  vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+2);
95  uiOffset = i + 2;
96  uiLineNo++;
97  uiLineLen = 0;
98  uiSkipAddingCharacters = APG_FALSE;
99  i++; // increment for the extra line end character
100  } else{
101  // CR line end
102  uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
103  vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+1);
104  uiOffset = i + 1;
105  uiLineNo++;
106  uiLineLen = 0;
107  uiSkipAddingCharacters = APG_FALSE;
108  }
109  } else if(cChar == 10){
110  // LF line end
111  uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
112  vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+1);
113  uiOffset = i + 1;
114  uiLineNo++;
115  uiLineLen = 0;
116  uiSkipAddingCharacters = APG_FALSE;
117  } else{
118  if(uiSkipAddingCharacters){
119  // just increment the character count
120  uiLineLen++;
121  } else{
122  if(cChar < 32 || cChar > 127){
123  // non-ASCII
124  uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
125  } else{
126  // non-special ASCII
127  cpLine[uiLineLen] = cChar;
128  uiLineLen++;
129  }
130  }
131  }
132  if(!uiSkipAddingCharacters && uiLineLen >= uiBufLen){
133  // add ellipsis & quit adding characters to the buffer
134  cpLine[uiLineLen] = 0;
135  strcat(cpLine, cpEllipsis);
136  uiLineLen += strlen(cpEllipsis);
137  uiSkipAddingCharacters = APG_TRUE;
138  }
139  }
140  if(uiLineLen > 0){
141  // last line has no line end
142  cpLine[uiLineLen] = 0;
143  strcat(cpLine, cpEof);
144  uiLineLen += strlen(cpEof);
145  vPrintLine(spOut, cpLine, uiLineNo, uiOffset, uiLineLen);
146  }
147 }
148 
153 void vDisplayOpcodes(void* vpCtx){
154  APG_PARSER_CTX* spCtx = (APG_PARSER_CTX*)vpCtx;
155  apg_uint i, j, uiOpIndex;
156  APG_RULE* spRule;
157  APG_OPCODE* spOp;
158 
159  printf("vDisplayOpcodes:\n");
160  uiOpIndex = 0;
161  for(i = 0; i < spCtx->uiRuleCount; i++){
162  spRule = &spCtx->spRules[i];
163  printf("RNM(%s) index: %lu: opcodes: %lu\n",
164  spRule->cpRuleName, (printf_uint)i, (printf_uint)spRule->uiOpcodeCount);
165  spOp = spRule->spOp;
166  for(j = 0; j < spCtx->spRules[i].uiOpcodeCount; j++, spOp++){
167  vDisplayOp(spCtx, spOp, uiOpIndex);
168  uiOpIndex++;
169  }
170  printf("\n");
171  }
172 }
173 
183 void vDisplayAstRecords(FILE* spOut, void* vpParserCtx){
184  APG_PARSER_CTX* spParserCtx = (APG_PARSER_CTX*)vpParserCtx;
185  if(spParserCtx->vpAstCtx){
186  apg_uint uiCharLen;
187  apg_uint uiBufLen = 128;
188  char cpBuffer[uiBufLen];
189 
190  char caPrtBuf[APG_DISPLAY_MAX_LINE + sizeof(PRINTBUF) + 1];
191  void* vpPrtBuf = NULL;
192  char caScratchBuf[3*APG_DISPLAY_MAX_LINE + 1];
193 
194  char* cpState;
195  APG_AST_CTX* spCtx = (APG_AST_CTX*)spParserCtx->vpAstCtx;
196  APG_AST_RECORD* spRecord = spCtx->spRecords;
197  APG_AST_RECORD* spRecordEnd = spCtx->spRecords + spCtx->uiRecordCount;
198  const apg_achar* acpPhrase;
199  apg_uint uiPhraseLen;
200  apg_uint uiTreeDepth = 0;
201 
202  if(spOut == NULL){spOut = stdout;}
203  fprintf(spOut, " a: this record number\n");
204  fprintf(spOut, " b: other record number\n");
205  fprintf(spOut, " c: tree depth\n");
206  fprintf(spOut, " d: state: ~=open, M=MATCH, E=EMPTY\n");
207  fprintf(spOut, " e: indented operator\n");
208  fprintf(spOut, " f: phrase offset\n");
209  fprintf(spOut, " g: phrase length\n");
210  fprintf(spOut, " h: phrase (... = truncated)\n");
211  fprintf(spOut, "%5s:%5s:%3s:%s:%2s:%s:%3s:%3s\n", "a", "b", "c", "d", "e", "f", "g", "h");
212  fprintf(spOut, "%5s:%5s:%3s:%s:%s:%s:%3s:%3s\n", "-----", "-----", "---", "-", "--", "-", "---", "---");
213  for(; spRecord < spRecordEnd; spRecord++){
214  vpPrtBuf = vpStrBufInit(&caPrtBuf[0], sizeof(caPrtBuf));
215  if(spRecord->uiState == PRE_AST){
216  cpState = "~";
217  sprintf(&caScratchBuf[0], "%5lu:%5lu:%3lu:%s:",
218  (printf_uint)spRecord->uiThisRecord, (printf_uint)spRecord->uiThatRecord, (printf_uint)uiTreeDepth, cpState);
219  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
220  acpPhrase = spParserCtx->acpInputString + spRecord->uiPhraseOffset;
221  uiPhraseLen = spRecord->uiPhraseLength;
222  uiIndent(uiTreeDepth, cpBuffer, uiBufLen);
223  if(spRecord->uiId >= spParserCtx->uiRuleCount){
224  APG_UDT* spUdt = spParserCtx->spUdts + spRecord->uiId - spParserCtx->uiRuleCount;
225  sprintf(&caScratchBuf[0], "%s%s:%lu:%lu:", cpBuffer, spUdt->cpUdtName,
226  (printf_uint)spRecord->uiPhraseOffset, (printf_uint)spRecord->uiPhraseLength);
227  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
228  uiCharLen = uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
229  uiStrBufCat(vpPrtBuf, cpBuffer);
230  } else{
231  APG_RULE* spRule= spParserCtx->spRules + spRecord->uiId;
232  sprintf(&caScratchBuf[0], "%s%s:%lu:%lu:", cpBuffer, spRule->cpRuleName,
233  (printf_uint)spRecord->uiPhraseOffset, (printf_uint)spRecord->uiPhraseLength);
234  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
235  uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
236  uiStrBufCat(vpPrtBuf, cpBuffer);
237  }
238  fprintf(spOut, "%s", cpStrBufString(vpPrtBuf));
239  if(uiStrBufIsTruncated(vpPrtBuf)){fprintf(spOut, "...");}
240  fprintf(spOut, "\n");
241  uiTreeDepth++;
242  } else if(spRecord->uiState == POST_AST){
243  cpState = (spRecord->uiPhraseLength) ? "M": "E";
244  sprintf(&caScratchBuf[0], "%5lu:%5lu:%3lu:%s:",
245  (printf_uint)spRecord->uiThisRecord, (printf_uint)spRecord->uiThatRecord, (printf_uint)uiTreeDepth, cpState);
246  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
247  acpPhrase = spParserCtx->acpInputString + spRecord->uiPhraseOffset;
248  uiPhraseLen = spRecord->uiPhraseLength;
249  uiTreeDepth--;
250  uiIndent(uiTreeDepth, cpBuffer, uiBufLen);
251  if(spRecord->uiId >= spParserCtx->uiRuleCount){
252  APG_UDT* spUdt = spParserCtx->spUdts + spRecord->uiId - spParserCtx->uiRuleCount;
253  sprintf(&caScratchBuf[0], "%s%s:%lu:%lu:", cpBuffer, spUdt->cpUdtName,
254  (printf_uint)spRecord->uiPhraseOffset, (printf_uint)spRecord->uiPhraseLength);
255  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
256  uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
257  uiStrBufCat(vpPrtBuf, cpBuffer);
258  } else{
259  APG_RULE* spRule= spParserCtx->spRules + spRecord->uiId;
260  sprintf(&caScratchBuf[0], "%s%s:%lu:%lu:", cpBuffer, spRule->cpRuleName,
261  (printf_uint)spRecord->uiPhraseOffset, (printf_uint)spRecord->uiPhraseLength);
262  uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
263  uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
264  uiStrBufCat(vpPrtBuf, cpBuffer);
265  }
266  fprintf(spOut, "%s", cpStrBufString(vpPrtBuf));
267  if(uiStrBufIsTruncated(vpPrtBuf)){fprintf(spOut, "...");}
268  fprintf(spOut, "\n");
269  }
270  }
271  }
272 }
273 
279 void vDisplayTypeSizes(FILE* spOut){
280  if(spOut == NULL){spOut = stdout;}
281  fprintf(spOut, " unsigned char: %lu\n", (printf_uint)sizeof(unsigned char));
282  fprintf(spOut, "unsigned short int: %lu\n", (printf_uint)sizeof(unsigned short));
283  fprintf(spOut, " unsigned int: %lu\n", (printf_uint)sizeof(unsigned int));
284  fprintf(spOut, " unsigned long int: %lu\n", (printf_uint)sizeof(unsigned long int));
285  fprintf(spOut, " apg_achar: %lu\n", (printf_uint)sizeof(apg_achar));
286  fprintf(spOut, " apg_uint: %lu\n", (printf_uint)sizeof(apg_uint));
287 }
288 
289 static char* g_cpDisplayStatsHdrFmt = "%5s %9s %9s %9s %9s";
296 void vDisplayOperatorStats(FILE* spOut, APG_PARSER_STATS* spStats){
297  if(spOut == NULL){spOut = stdout;}
298  if(!spStats){fprintf(spOut, "<no statistics>\n");}
299  else{
300  fprintf(spOut, g_cpDisplayStatsHdrFmt, "", "NOMATCH", "EMPTY", "MATCH", "TOTAL");
301  fprintf(spOut, "%s", " : OPERATOR STATISTICS");
302  fprintf(spOut, "\n");
303  vPrintOperatorLine(spOut, "RNM", &spStats->sRnm);
304  fprintf(spOut, "\n");
305  vPrintOperatorLine(spOut, "UDT", &spStats->sUdt);
306  fprintf(spOut, "\n");
307  vPrintOperatorLine(spOut, "ALT", &spStats->sAlt);
308  fprintf(spOut, "\n");
309  vPrintOperatorLine(spOut, "CAT", &spStats->sCat);
310  fprintf(spOut, "\n");
311  vPrintOperatorLine(spOut, "REP", &spStats->sRep);
312  fprintf(spOut, "\n");
313  vPrintOperatorLine(spOut, "AND", &spStats->sAnd);
314  fprintf(spOut, "\n");
315  vPrintOperatorLine(spOut, "NOT", &spStats->sNot);
316  fprintf(spOut, "\n");
317  vPrintOperatorLine(spOut, "TRG", &spStats->sTrg);
318  fprintf(spOut, "\n");
319  vPrintOperatorLine(spOut, "TBS", &spStats->sTbs);
320  fprintf(spOut, "\n");
321  vPrintOperatorLine(spOut, "TLS", &spStats->sTls);
322  fprintf(spOut, "\n");
323  vPrintOperatorLine(spOut, "TOTAL", &spStats->sTotal);
324  fprintf(spOut, "\n");
325  }
326 }
338 void vDisplayRuleStats(FILE* spOut, APG_PARSER_STATS* spStats, const char* cpType){
339  apg_uint uiType = 0; // 0=default, 1=alpha, 2=count
340  if(spOut == NULL){spOut = stdout;}
341  if(!spStats){fprintf(spOut, "<no statistics>\n");}
342  else{
343  if(cpType && (*cpType == 'a' || *cpType == 'A')){uiType = 1;}
344  if(cpType && (*cpType == 'c' || *cpType == 'C')){uiType = 2;}
345  fprintf(spOut, "\n");
346  fprintf(spOut, g_cpDisplayStatsHdrFmt, "", "NOMATCH", "EMPTY", "MATCH", "TOTAL");
347  fprintf(spOut, "%s", " : RULE/UDT STATISTICS");
348  switch(uiType){
349  case 1: // cpType = "alpha", list rules/UDTs alphabetically
350  fprintf(spOut, "%s", " (alphabetically sorted on rule/UDT names)");
351  fprintf(spOut, "\n");
352  vPrintOperatorList(spOut, spStats->spNameStatsAlpha, spStats->uiNameCount, 1);
353  break;
354  case 2: // cpType = "alpha", list rules/UDTs descending on count
355  fprintf(spOut, "%s", " (numerically sorted on total node visits)");
356  fprintf(spOut, "\n");
357  vPrintOperatorList(spOut, spStats->spNameStatsCount, spStats->uiNameCount, 2);
358  break;
359  default: // default = list by grammar index
360  fprintf(spOut, "%s", " (not sorted, listed by grammar index, rules followed by UDTs)");
361  fprintf(spOut, "\n");
362  vPrintOperatorList(spOut, spStats->spNameStats, spStats->uiNameCount, 0);
363  break;
364  }
365  }
366 }
367 
373 void vDisplayParserState(FILE* spOut, void* vpParserCtx){
374  APG_PARSER_CTX* spParserCtx = (APG_PARSER_CTX*)vpParserCtx;
375  if(spOut == NULL){spOut = stdout;}
376  if(spParserCtx && (void*)spParserCtx == spParserCtx->vpValidate){
377  fprintf(spOut, "%5s = success\n", cpBoolean2String(spParserCtx->sState.uiSuccess));
378  fprintf(spOut, "%5s = state\n", cpState2String(spParserCtx->sState.uiState));
379  fprintf(spOut, "%5lu = phrase length\n", (printf_uint)spParserCtx->sState.uiPhraseLength);
380  fprintf(spOut, "%5lu = string length\n", (printf_uint)spParserCtx->sState.uiStringLength);
381  } else{
382  fprintf(spOut, "vDisplayParserState: invalid input\n");
383  }
384 }
385 
391 void vDisplayState(FILE* spOut, APG_PARSER_STATE* spState){
392  if(spState){
393  fprintf(spOut, "%5s = success\n", cpBoolean2String(spState->uiSuccess));
394  fprintf(spOut, "%5s = state\n", cpState2String(spState->uiState));
395  fprintf(spOut, "%5lu = phrase length\n", (printf_uint)spState->uiPhraseLength);
396  fprintf(spOut, "%5lu = string length\n", (printf_uint)spState->uiStringLength);
397  } else{
398  fprintf(spOut, "vDisplayParserState: invalid input\n");
399  }
400 }
401 
409 void vDisplayGrammarInfo(FILE* spOut, void* vpHdr){
410  G_HDR* spHdr = (G_HDR*)vpHdr;
411  char caVersion[64];
412  apg_uint i;
413  unsigned long int* uipOffset;
414  char* cpFmtVersion = "%15s = %s\n";
415  char* cpFmtData = "%15lu = %s\n";
416  if(spOut == NULL){spOut = stdout;}
417  if(spHdr){
418  uipOffset =(unsigned long int*)spHdr + spHdr->uiVersionOffset;
419  for(i = 0; i < spHdr->uiVersionLen; i++){
420  caVersion[i] = (char)uipOffset[i];
421  }
422  caVersion[i] = 0;
423  fprintf(spOut, cpFmtVersion, &caVersion[0], "Version");
424  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiSizeInBytes, "Grammar size in bytes");
425  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiACharMin, "Grammar alphabet character min");
426  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiACharMax, "Grammar alphabet character max");
427  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiUintMax, "Grammar integer max");
428  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiMinSizeofACharMax, "min sizeof(apg_achar)");
429  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiMinSizeofUintMax, "min sizeof(apg_uint)");
430  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiRulesLen, "Number of rules");
431  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiUdtsLen, "Number of UDTs");
432  fprintf(spOut, cpFmtData, (printf_uint)spHdr->uiOpcodesLen, "Number of opcodes");
433  }
434 }
435 
437 // OTHER HELPERS
439 
442 void vLicenseNotice(FILE* spFile)
443 {
444  if(!spFile){spFile = stdout;}
445  fprintf(spFile, " APG Version %s\n", cpApgVersion());
446 // fprintf(spFile, " %s\n", cpApgDescription());
447  fprintf(spFile, " %s\n", cpApgCopyright());
448  fprintf(spFile, "\n");
449  fprintf(spFile, " author: %s\n", cpApgAuthor());
450  fprintf(spFile, " email: %s\n", cpApgEmail());
451  fprintf(spFile, " website: %s\n", cpApgWebsite());
452  fprintf(spFile, "\n");
453  fprintf(spFile, "%s", cpApgGPLNotice());
454 }
455 
479 apg_uint uiAstToXml(FILE* spOut, void* vpParserCtx){
480  apg_uint uiRet = APG_TRUE;
481  char* cpError = NULL;
482  char* cpName = NULL;
483  APG_PARSER_CTX* spParserCtx = (APG_PARSER_CTX*)vpParserCtx;
484  APG_AST_CTX* spAstCtx;
485  APG_AST_RECORD* spRecord;
486  APG_AST_RECORD* spRecordEnd;
487  apg_uint uiTreeDepth;
488  APG_RULE* spRules;
489  APG_UDT* spUdts;
490  const apg_achar* acpInputString;
491  char* cpDeclaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
492 
493  while(APG_TRUE){
494  if(spOut == NULL){spOut = stdout;}
495  if(!(spParserCtx && spParserCtx->vpValidate == vpParserCtx)){
496  cpError = "input error; NULL or invalid parser context";
497  break;
498  }
499  spRules = spParserCtx->spRules;
500  spUdts = spParserCtx->spUdts;
501  acpInputString = spParserCtx->acpInputString;
502  spAstCtx = (APG_AST_CTX*)spParserCtx->vpAstCtx;
503  if(!spAstCtx){
504  cpError = "no AST; must call vParserSemanticInit() prior to parsing";
505  break;
506  }
507  if(!spAstCtx->uiRecordCount){
508  cpError = "no AST records have been generated";
509  break;
510  }
511  spRecord = spAstCtx->spRecords;
512  spRecordEnd = spAstCtx->spRecords + spAstCtx->uiRecordCount;
513 
514  // print the open ROOT record
515  fprintf(spOut, "%s\n", cpDeclaration);
516  uiTreeDepth = 0;
517  vRootOpen(spOut, (3 * (spAstCtx->uiRecordCount/2 + 1) + 1), spAstCtx->uiRecordCount/2);
518  uiTreeDepth++;
519  vIndentPrint(spOut, uiTreeDepth);
520  vPhrase(spOut, 0, spParserCtx->uiInputStringLen, acpInputString);
521  for(; spRecord < spRecordEnd; spRecord++){
522  if(spRecord->uiId < spAstCtx->uiRuleCount){cpName = spRules[spRecord->uiId].cpRuleName;}
523  else if(spRecord->uiId < spAstCtx->uiNodeCount){cpName = spUdts[spRecord->uiId - spAstCtx->uiRuleCount].cpUdtName;}
524  if(spRecord->uiState == PRE_AST){
525  vIndentPrint(spOut, uiTreeDepth);
526  vNodeOpen(spOut, spRecord->uiId, cpName);
527  uiTreeDepth++;
528  vIndentPrint(spOut, uiTreeDepth);
529  vPhrase(spOut, spRecord->uiPhraseOffset, spRecord->uiPhraseLength, (acpInputString + spRecord->uiPhraseOffset));
530  } else if(spRecord->uiState == POST_AST){
531  uiTreeDepth--;
532  vIndentPrint(spOut, uiTreeDepth);
533  vNodeClose(spOut, spRecord->uiId, cpName);
534  }
535  }
536 
537  uiTreeDepth--;
538  vRootClose(spOut);
539 
540  break;
541  }
542  if(cpError){
543  fprintf(spOut, "\n!!! AST to XML conversion error: %s !!!\n", cpError);
544  uiRet = APG_FALSE;
545  }
546  return uiRet;
547 }
548 
557 void vTerminalAlert(unsigned int uiLine, const char* cpFile){
558  if(!cpFile){cpFile = "<none>";}
559  printf("vTerminalAlert: file: %s: line: %u\n", cpFile, uiLine);
560  printf("vTerminalAlert: exit(EXIT_FAILURE);\n");
561  exit(EXIT_FAILURE);
562 }
563 
569 void vTerminalAlertMsg(unsigned int uiLine, const char* cpFile, const char* cpMsg){
570  if(!cpFile){cpFile = "<none>";}
571  if(!cpMsg){cpMsg = "<none>";}
572  printf("vTerminalAlertMsg: file: %s: line: %u: %s\n", cpFile, uiLine, cpMsg);
573  printf("vTerminalAlertMsg: exit(EXIT_FAILURE);\n");
574  exit(EXIT_FAILURE);
575 }
576 
590 const char* cpState2String(apg_uint uiState){
591  char* cpRet = "UNKNOWN";
592  if(uiState == MATCH){cpRet = "MATCH";}
593  else if(uiState == NOMATCH){cpRet = "NOMATCH";}
594  else if(uiState == EMPTY){cpRet = "EMPTY";}
595  else if(uiState == PRE_PARSE){cpRet = "PRE_PARSE";}
596  else if(uiState == PRE_AST){cpRet = "PRE_AST";}
597  else if(uiState == POST_AST){cpRet = "POST_AST";}
598  return cpRet;
599 }
600 
605 const char* cpBoolean2String(apg_uint uiBool){
606  return uiBool ? "TRUE" : "FALSE";
607 }
608 
610 // STATIC HELPER FUNCTIONS
612 static apg_uint uiIndent(apg_uint uiIndent, char* cpBuffer, apg_uint uiBufferLen){
613  apg_uint i, uiLen = 0;
614  if(cpBuffer && uiBufferLen){
615  uiLen = min(uiIndent, uiBufferLen);
616  cpBuffer[0] = 0;
617  for(i = 0; i < uiLen; i++){
618  strcat(cpBuffer, " ");
619  }
620  }
621  return uiLen;
622 }
623 
624 static void vPrintOperatorList(FILE* spOut, APG_NAME_STAT* spNameStats, apg_uint uiCount, apg_uint uiType){
625  apg_uint uiIndex;
626  APG_STAT* spStat;
627  for(uiIndex = 0; uiIndex < uiCount; uiIndex++){
628  spStat = &spNameStats[uiIndex].sStat;
629  if(uiType == 0){
630  vPrintOperatorLine(spOut, "", spStat);
631  fprintf(spOut, " : %s", spNameStats[uiIndex].cpName);
632  fprintf(spOut, "\n");
633  } else{
634  if(spStat->uiTotal > 0){
635  vPrintOperatorLine(spOut, "", spStat);
636  fprintf(spOut, " : %s", spNameStats[uiIndex].cpName);
637  fprintf(spOut, "\n");
638  }
639  }
640  }
641 }
642 static void vPrintOperatorLine(FILE* spOut, char* cpOp, APG_STAT* spNode)
643 {
644  if(cpOp){
645  fprintf(spOut, "%5s %9lu %9lu %9lu %9lu",
646  cpOp,
647  (printf_uint)spNode->uiNoMatch,
648  (printf_uint)spNode->uiEmpty,
649  (printf_uint)spNode->uiMatch,
650  (printf_uint)spNode->uiTotal);
651  } else{
652  fprintf(spOut, "vPrintOperatorLine: cpOp may not be NULL: line: %u: file: %s\n", __LINE__, __FILE__);
653  }
654 }
655 
656 //static int iCompCount(const void* vpLeft, const void* vpRight)
657 //{
658 // APG_STATS_SORT* spLeft;
659 // APG_STATS_SORT* spRight;
660 //
661 // // sort descending
662 // spLeft = (APG_STATS_SORT*)vpLeft;
663 // spRight = (APG_STATS_SORT*)vpRight;
664 // if(spLeft->spStat->uiTotal < spRight->spStat->uiTotal){return +1;}
665 // if(spLeft->spStat->uiTotal > spRight->spStat->uiTotal){return -1;}
666 // return 0;
667 //}
668 //
669 //static int iCompAlpha(const void* vpLeft, const void* vpRight)
670 //{
671 // APG_STATS_SORT* spLeft = (APG_STATS_SORT*)vpLeft;
672 // APG_STATS_SORT* spRight = (APG_STATS_SORT*)vpRight;
673 //
674 // // sort descending
676 // return strcmp(spLeft->cpName, spRight->cpName);
677 //}
678 
679 static void vDisplayOp(APG_PARSER_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiOpIndex){
680  apg_uint i;
681  printf(" %lu: ", (printf_uint)uiOpIndex);
682  if(spOp->pfnOp == uiRNM){
683  APG_RULE* spRule = spOp->sUnion.sRnm.spRule;
684  printf("RNM(%s): index: %lu: opcodes: %lu\n",
685  spRule->cpRuleName, (printf_uint)spRule->uiRuleIndex, (printf_uint)spRule->uiOpcodeCount);
686  } else if(spOp->pfnOp == uiUDT){
687  APG_UDT* spUdt = spOp->sUnion.sUdt.spUdt;
688  printf("UDT(%s): index: %lu\n", spUdt->cpUdtName, (printf_uint)spUdt->uiUdtIndex);
689  } else if(spOp->pfnOp == uiREP){
690  if(spOp->sUnion.sRep.uiMax == APG_UNDEFINED){
691  printf("REP: min: %lu: max: inf\n", (printf_uint)spOp->sUnion.sRep.uiMin);
692  } else{
693  printf("REP: min: %lu: max: %lu\n", (printf_uint)spOp->sUnion.sRep.uiMin, (printf_uint)spOp->sUnion.sRep.uiMax);
694  }
695  } else if(spOp->pfnOp == uiALT){
696  printf("ALT: count: %lu: ", (printf_uint)spOp->sUnion.sAlt.uiChildCount);
697  for(i = 0; i < spOp->sUnion.sAlt.uiChildCount; i++){
698  printf("%lu: ", (printf_uint)spOp->sUnion.sAlt.uipChildList[i]);
699  }
700  printf("\n");
701  } else if(spOp->pfnOp == uiCAT){
702  printf("CAT: count: %lu: ", (printf_uint)spOp->sUnion.sCat.uiChildCount);
703  for(i = 0; i < spOp->sUnion.sCat.uiChildCount; i++){
704  printf("%lu: ", (printf_uint)spOp->sUnion.sCat.uipChildList[i]);
705  }
706  printf("\n");
707  } else if(spOp->pfnOp == uiAND){
708  printf("AND\n");
709  } else if(spOp->pfnOp == uiNOT){
710  printf("NOT\n");
711  } else if(spOp->pfnOp == uiTRG){
712  printf("TRG: min: %lu: max: %lu\n",
713  (printf_uint)spOp->sUnion.sTrg.acMin, (printf_uint)spOp->sUnion.sTrg.acMax);
714  } else if(spOp->pfnOp == uiTBS){
715  printf("TBS: len: %lu: ", (printf_uint)spOp->sUnion.sTbs.uiStrLen);
716  for(i = 0; i < spOp->sUnion.sTbs.uiStrLen; i++){
717  printf("0x%lX: ", (printf_uint)spOp->sUnion.sTbs.acpStrTbl[i]);
718  }
719  } else if(spOp->pfnOp == uiTLS){
720  printf("TBS: len: %lu: ", (printf_uint)spOp->sUnion.sTls.uiStrLen);
721  for(i = 0; i < spOp->sUnion.sTls.uiStrLen; i++){
722  printf("0x%lX: ", (printf_uint)spOp->sUnion.sTls.acpStrTbl[i]);
723  }
724  printf("\n");
725  } else{printf("vDisplayOp: unknown operator type\n");}
726 }
727 
728 //static unsigned long int uiMinIntSize(unsigned long int uiSize){
729 // unsigned long int uiRet = 0;
730 // unsigned long int uiTest;
731 // while(APG_TRUE){
732 // uiTest = (unsigned char)-1;
733 // if(uiTest >= uiSize){uiRet = sizeof(unsigned char); break;}
734 // uiTest = (unsigned short int)-1;
735 // if(uiTest >= uiSize){uiRet = sizeof(unsigned short int); break;}
736 // uiTest = (unsigned int)-1;
737 // if(uiTest >= uiSize){uiRet = sizeof(unsigned int); break;}
738 // uiTest = (printf_uint)-1;
739 // if(uiTest >= uiSize){uiRet = sizeof(printf_uint); break;}
740 // break;
741 // }
742 // return uiRet;
743 //}
744 
745 static char* g_cpBeg1 = "<";
746 static char* g_cpBeg2 = "</";
747 static char* g_cpEnd1 = ">";
748 static char* g_cpRootName = "root";
749 static void vIndentPrint(FILE* spOut, apg_uint uiIndent){
750  while(uiIndent--){fprintf(spOut, " ");}
751 }
752 static void vRootOpen(FILE* spOut, apg_uint uiLines, apg_uint uiNodes){
753  fprintf(spOut, "%s%s lines=\"%lu\" nodes=\"%lu\"%s\n",
754  g_cpBeg1, g_cpRootName, (printf_uint)uiLines, (printf_uint)uiNodes, g_cpEnd1);
755 }
756 static void vRootClose(FILE* spOut){
757  fprintf(spOut, "%s%s%s\n", g_cpBeg2, g_cpRootName, g_cpEnd1);
758 }
759 static void vNodeOpen(FILE* spOut, apg_uint uiId, char* cpName){
760  fprintf(spOut, "%snode name=\"%s\" id=\"%lu\"%s\n",
761  g_cpBeg1, cpName, (printf_uint)uiId, g_cpEnd1);
762 }
763 static void vNodeClose(FILE* spOut, apg_uint uiId, char* cpName){
764  fprintf(spOut, "%snode%s<!-- name=\"%s\" id=\"%lu\" -->\n", g_cpBeg2, g_cpEnd1, cpName, (printf_uint)uiId);
765 }
766 static void vPhraseText(FILE* spOut, const apg_achar* acpPhrase, apg_uint uiLength){
767  apg_uint i = 0;
768  for(; i < uiLength; i++){
769  apg_achar c = acpPhrase[i];
770  if(c < (apg_achar)32 || c > (apg_achar)126){
771  fprintf(spOut, "&#x%02lX;", (printf_uint)c);
772  }
773  else{
774  switch(c){
775  case '&':
776  fprintf(spOut, "&amp;");
777  break;
778  case '<':
779  fprintf(spOut, "&lt;");
780  break;
781  case '>':
782  fprintf(spOut, "&gt;");
783  break;
784  case '"':
785  fprintf(spOut, "&quot;");
786  break;
787  case '\'':
788  fprintf(spOut, "&apos;");
789  break;
790  default:
791  fprintf(spOut, "%c", (char)c);
792  break;
793  }
794  }
795  }
796 }
797 static void vPhrase(FILE* spOut, apg_uint uiOffset, apg_uint uiLength, const apg_achar* acpPhrase){
798  fprintf(spOut, "%sphrase offset=\"%lu\" length=\"%lu\"%s",
799  g_cpBeg1, (printf_uint)uiOffset, (printf_uint)uiLength, g_cpEnd1);
800  vPhraseText(spOut, acpPhrase, uiLength);
801  fprintf(spOut, "%sphrase%s\n", g_cpBeg2, g_cpEnd1);
802 }
803 static void vPrintHeader(FILE* spOut){
804  fprintf(spOut, "%6s, %6s, %6s\n", "lineno", "offset", "length");
805 }
806 static void vPrintLine(FILE* spOut, char* cpLine, apg_uint uiLine, apg_uint uiOffset, apg_uint uiLineLen){
807  fprintf(spOut, "%06lu, %06lu, %06lu: %s\n", (printf_uint)uiLine, (printf_uint)uiOffset, (printf_uint)uiLineLen, cpLine);
808 
809 }
810 static char g_caTrans[17] = {'0','1', '2','3','4','5','6','7','8','9','A','B','C','D','E','F','X'};
811 static apg_uint uiAddNonAscii(char* cpAdd, char cChar){
812  apg_uint uiRet = 0;
813  char cHex;
814  cpAdd[uiRet++] = '\\';
815  cpAdd[uiRet++] = 'x';
816  cHex = (cChar & 0xF0) >> 4;
817  cpAdd[uiRet++] = g_caTrans[(unsigned int)cHex];
818  cHex = cChar & 0x0F;
819  cpAdd[uiRet++] = g_caTrans[(unsigned int)cHex];
820  cpAdd[uiRet] = 0;
821  return uiRet;
822 }
APG_PARSER_STATS::sAlt
APG_STAT sAlt
Definition: Apg.h:603
APG_PARSER_STATS
full set of statistics gathered during parsing, uiParserSyntaxAnalysis()
Definition: Apg.h:591
APG_PARSER_STATE
the state of the parser after parsing an input string.
Definition: Apg.h:561
POST_AST
#define POST_AST
Definition: Apg.h:556
vTerminalAlertMsg
void vTerminalAlertMsg(unsigned int uiLine, const char *cpFile, const char *cpMsg)
Definition: Utilities.c:569
APG_PARSER_STATS::uiNameCount
apg_uint uiNameCount
Definition: Apg.h:593
apg_uint
unsigned int apg_uint
Definition: Apg.h:169
APG_PARSER_STATS::spNameStats
APG_NAME_STAT * spNameStats
Definition: Apg.h:596
APG_STAT::uiTotal
apg_uint uiTotal
Definition: Apg.h:573
APG_PARSER_STATE::uiPhraseLength
apg_uint uiPhraseLength
Definition: Apg.h:564
vLicenseNotice
void vLicenseNotice(FILE *spFile)
Definition: Utilities.c:442
APG_NAME_STAT::sStat
APG_STAT sStat
Definition: Apg.h:585
vDisplayOpcodes
void vDisplayOpcodes(void *vpCtx)
Definition: Utilities.c:153
cpBoolean2String
const char * cpBoolean2String(apg_uint uiBool)
Definition: Utilities.c:605
APG_STAT::uiNoMatch
apg_uint uiNoMatch
Definition: Apg.h:576
vDisplayGrammarInfo
void vDisplayGrammarInfo(FILE *spOut, void *vpHdr)
Definition: Utilities.c:409
vDisplayTypeSizes
void vDisplayTypeSizes(FILE *spOut)
Definition: Utilities.c:279
APG_PARSER_STATS::sRep
APG_STAT sRep
Definition: Apg.h:602
APG_PARSER_STATS::spNameStatsAlpha
APG_NAME_STAT * spNameStatsAlpha
Definition: Apg.h:597
APG_STAT::uiEmpty
apg_uint uiEmpty
Definition: Apg.h:575
APG_STAT
the parsers total node hit statistics
Definition: Apg.h:572
APG_PARSER_STATS::sNot
APG_STAT sNot
Definition: Apg.h:606
PRE_PARSE
#define PRE_PARSE
Definition: Apg.h:526
APG_PARSER_STATS::sUdt
APG_STAT sUdt
Definition: Apg.h:601
EMPTY
#define EMPTY
Definition: Apg.h:538
APG_TRUE
#define APG_TRUE
Definition: Apg.h:187
vDisplayRuleStats
void vDisplayRuleStats(FILE *spOut, APG_PARSER_STATS *spStats, const char *cpType)
Definition: Utilities.c:338
vDisplayParserState
void vDisplayParserState(FILE *spOut, void *vpParserCtx)
Definition: Utilities.c:373
APG_PARSER_STATS::sTbs
APG_STAT sTbs
Definition: Apg.h:608
ApgUtilities.h
Declarations of all APG utility functions.
apg_achar
unsigned char apg_achar
Definition: Apg.h:183
APG_PARSER_STATE::uiState
apg_uint uiState
Definition: Apg.h:563
printf_uint
unsigned long int printf_uint
Definition: ApgUtilities.h:52
vDisplayOperatorStats
void vDisplayOperatorStats(FILE *spOut, APG_PARSER_STATS *spStats)
Definition: Utilities.c:296
APG_PARSER_STATS::spNameStatsCount
APG_NAME_STAT * spNameStatsCount
Definition: Apg.h:598
APG_STAT::uiMatch
apg_uint uiMatch
Definition: Apg.h:574
APG_PARSER_STATS::sTotal
APG_STAT sTotal
Definition: Apg.h:610
vDisplayState
void vDisplayState(FILE *spOut, APG_PARSER_STATE *spState)
Definition: Utilities.c:391
cpState2String
const char * cpState2String(apg_uint uiState)
Definition: Utilities.c:590
uiACharToString
apg_uint uiACharToString(char *cpChars, apg_uint uiCLen, const apg_achar *acpAChars, apg_uint uiALen)
Definition: Tools.c:197
APG_PARSER_STATS::sRnm
APG_STAT sRnm
Definition: Apg.h:600
APG_UNDEFINED
#define APG_UNDEFINED
Definition: Apg.h:194
min
#define min(a, b)
Definition: Apg.h:296
APG_PARSER_STATS::sTls
APG_STAT sTls
Definition: Apg.h:609
vDisplayAstRecords
void vDisplayAstRecords(FILE *spOut, void *vpParserCtx)
Definition: Utilities.c:183
APG_PARSER_STATS::sCat
APG_STAT sCat
Definition: Apg.h:604
APG_PARSER_STATS::sAnd
APG_STAT sAnd
Definition: Apg.h:605
MATCH
#define MATCH
Definition: Apg.h:544
APG_FALSE
#define APG_FALSE
Definition: Apg.h:190
APG_NAME_STAT
named rule or UDT node statistics
Definition: Apg.h:582
APG_PARSER_STATS::sTrg
APG_STAT sTrg
Definition: Apg.h:607
vDisplayAscii
void vDisplayAscii(FILE *spOut, const char *cpSrc, apg_uint uiSrcLen)
Definition: Utilities.c:62
APG_PARSER_STATE::uiStringLength
apg_uint uiStringLength
Definition: Apg.h:565
vTerminalAlert
void vTerminalAlert(unsigned int uiLine, const char *cpFile)
Definition: Utilities.c:557
uiAstToXml
apg_uint uiAstToXml(FILE *spOut, void *vpParserCtx)
Definition: Utilities.c:479
APG_DISPLAY_MAX_LINE
#define APG_DISPLAY_MAX_LINE
Definition: Apg.h:267
PRE_AST
#define PRE_AST
Definition: Apg.h:550
NOMATCH
#define NOMATCH
Definition: Apg.h:532
APG_PARSER_STATE::uiSuccess
apg_uint uiSuccess
Definition: Apg.h:562
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.