36 static void vPrintOperatorLine(FILE* spOut,
char* cpOp,
APG_STAT* spNode);
38 static void vDisplayOp(APG_PARSER_CTX* spCtx, APG_OPCODE* spOp,
apg_uint uiOpIndex);
39 static void vIndentPrint(FILE* spOut,
apg_uint uiIndent);
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);
46 static void vPrintHeader(FILE* spOut);
48 static apg_uint uiAddNonAscii(
char* cpAdd,
char cChar);
64 char caBuffer[uiBufLen + 10];
65 char* cpLine = &caBuffer[0];
66 char* cpEllipsis =
"...";
67 char* cpEof =
"<EOF>";
75 if(spOut == NULL){spOut = stdout;}
76 if(!(cpSrc && cpSrc[0])){
77 fprintf(spOut,
"vDisplaySourceLines: spSrc may not be NULL or empty\n");
86 cpLine = &caBuffer[0];
87 for(i = 0; i < uiSrcLen; i++){
92 uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
93 uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cpSrc[i+1]);
94 vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+2);
102 uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
103 vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+1);
109 }
else if(cChar == 10){
111 uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
112 vPrintLine(spOut, cpLine, uiLineNo, uiOffset, i-uiOffset+1);
118 if(uiSkipAddingCharacters){
122 if(cChar < 32 || cChar > 127){
124 uiLineLen += uiAddNonAscii(&cpLine[uiLineLen], cChar);
127 cpLine[uiLineLen] = cChar;
132 if(!uiSkipAddingCharacters && uiLineLen >= uiBufLen){
134 cpLine[uiLineLen] = 0;
135 strcat(cpLine, cpEllipsis);
136 uiLineLen += strlen(cpEllipsis);
142 cpLine[uiLineLen] = 0;
143 strcat(cpLine, cpEof);
144 uiLineLen += strlen(cpEof);
145 vPrintLine(spOut, cpLine, uiLineNo, uiOffset, uiLineLen);
154 APG_PARSER_CTX* spCtx = (APG_PARSER_CTX*)vpCtx;
159 printf(
"vDisplayOpcodes:\n");
161 for(i = 0; i < spCtx->uiRuleCount; i++){
162 spRule = &spCtx->spRules[i];
163 printf(
"RNM(%s) index: %lu: opcodes: %lu\n",
166 for(j = 0; j < spCtx->spRules[i].uiOpcodeCount; j++, spOp++){
167 vDisplayOp(spCtx, spOp, uiOpIndex);
184 APG_PARSER_CTX* spParserCtx = (APG_PARSER_CTX*)vpParserCtx;
185 if(spParserCtx->vpAstCtx){
188 char cpBuffer[uiBufLen];
191 void* vpPrtBuf = NULL;
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;
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){
217 sprintf(&caScratchBuf[0],
"%5lu:%5lu:%3lu:%s:",
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,
227 uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
228 uiCharLen =
uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
229 uiStrBufCat(vpPrtBuf, cpBuffer);
231 APG_RULE* spRule= spParserCtx->spRules + spRecord->uiId;
232 sprintf(&caScratchBuf[0],
"%s%s:%lu:%lu:", cpBuffer, spRule->cpRuleName,
234 uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
236 uiStrBufCat(vpPrtBuf, cpBuffer);
238 fprintf(spOut,
"%s", cpStrBufString(vpPrtBuf));
239 if(uiStrBufIsTruncated(vpPrtBuf)){fprintf(spOut,
"...");}
240 fprintf(spOut,
"\n");
242 }
else if(spRecord->uiState ==
POST_AST){
243 cpState = (spRecord->uiPhraseLength) ?
"M":
"E";
244 sprintf(&caScratchBuf[0],
"%5lu:%5lu:%3lu:%s:",
246 uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
247 acpPhrase = spParserCtx->acpInputString + spRecord->uiPhraseOffset;
248 uiPhraseLen = spRecord->uiPhraseLength;
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,
255 uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
257 uiStrBufCat(vpPrtBuf, cpBuffer);
259 APG_RULE* spRule= spParserCtx->spRules + spRecord->uiId;
260 sprintf(&caScratchBuf[0],
"%s%s:%lu:%lu:", cpBuffer, spRule->cpRuleName,
262 uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
264 uiStrBufCat(vpPrtBuf, cpBuffer);
266 fprintf(spOut,
"%s", cpStrBufString(vpPrtBuf));
267 if(uiStrBufIsTruncated(vpPrtBuf)){fprintf(spOut,
"...");}
268 fprintf(spOut,
"\n");
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));
289 static char* g_cpDisplayStatsHdrFmt =
"%5s %9s %9s %9s %9s";
297 if(spOut == NULL){spOut = stdout;}
298 if(!spStats){fprintf(spOut,
"<no statistics>\n");}
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");
340 if(spOut == NULL){spOut = stdout;}
341 if(!spStats){fprintf(spOut,
"<no statistics>\n");}
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");
350 fprintf(spOut,
"%s",
" (alphabetically sorted on rule/UDT names)");
351 fprintf(spOut,
"\n");
355 fprintf(spOut,
"%s",
" (numerically sorted on total node visits)");
356 fprintf(spOut,
"\n");
360 fprintf(spOut,
"%s",
" (not sorted, listed by grammar index, rules followed by UDTs)");
361 fprintf(spOut,
"\n");
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);
382 fprintf(spOut,
"vDisplayParserState: invalid input\n");
398 fprintf(spOut,
"vDisplayParserState: invalid input\n");
410 G_HDR* spHdr = (G_HDR*)vpHdr;
413 unsigned long int* uipOffset;
414 char* cpFmtVersion =
"%15s = %s\n";
415 char* cpFmtData =
"%15lu = %s\n";
416 if(spOut == NULL){spOut = stdout;}
418 uipOffset =(
unsigned long int*)spHdr + spHdr->uiVersionOffset;
419 for(i = 0; i < spHdr->uiVersionLen; i++){
420 caVersion[i] = (char)uipOffset[i];
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");
444 if(!spFile){spFile = stdout;}
445 fprintf(spFile,
" APG Version %s\n", cpApgVersion());
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());
481 char* cpError = 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;
491 char* cpDeclaration =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
494 if(spOut == NULL){spOut = stdout;}
495 if(!(spParserCtx && spParserCtx->vpValidate == vpParserCtx)){
496 cpError =
"input error; NULL or invalid parser context";
499 spRules = spParserCtx->spRules;
500 spUdts = spParserCtx->spUdts;
501 acpInputString = spParserCtx->acpInputString;
502 spAstCtx = (APG_AST_CTX*)spParserCtx->vpAstCtx;
504 cpError =
"no AST; must call vParserSemanticInit() prior to parsing";
507 if(!spAstCtx->uiRecordCount){
508 cpError =
"no AST records have been generated";
511 spRecord = spAstCtx->spRecords;
512 spRecordEnd = spAstCtx->spRecords + spAstCtx->uiRecordCount;
515 fprintf(spOut,
"%s\n", cpDeclaration);
517 vRootOpen(spOut, (3 * (spAstCtx->uiRecordCount/2 + 1) + 1), spAstCtx->uiRecordCount/2);
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);
528 vIndentPrint(spOut, uiTreeDepth);
529 vPhrase(spOut, spRecord->uiPhraseOffset, spRecord->uiPhraseLength, (acpInputString + spRecord->uiPhraseOffset));
530 }
else if(spRecord->uiState ==
POST_AST){
532 vIndentPrint(spOut, uiTreeDepth);
533 vNodeClose(spOut, spRecord->uiId, cpName);
543 fprintf(spOut,
"\n!!! AST to XML conversion error: %s !!!\n", cpError);
558 if(!cpFile){cpFile =
"<none>";}
559 printf(
"vTerminalAlert: file: %s: line: %u\n", cpFile, uiLine);
560 printf(
"vTerminalAlert: exit(EXIT_FAILURE);\n");
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");
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";}
606 return uiBool ?
"TRUE" :
"FALSE";
614 if(cpBuffer && uiBufferLen){
615 uiLen =
min(uiIndent, uiBufferLen);
617 for(i = 0; i < uiLen; i++){
618 strcat(cpBuffer,
" ");
627 for(uiIndex = 0; uiIndex < uiCount; uiIndex++){
628 spStat = &spNameStats[uiIndex].
sStat;
630 vPrintOperatorLine(spOut,
"", spStat);
631 fprintf(spOut,
" : %s", spNameStats[uiIndex].cpName);
632 fprintf(spOut,
"\n");
635 vPrintOperatorLine(spOut,
"", spStat);
636 fprintf(spOut,
" : %s", spNameStats[uiIndex].cpName);
637 fprintf(spOut,
"\n");
642 static void vPrintOperatorLine(FILE* spOut,
char* cpOp,
APG_STAT* spNode)
645 fprintf(spOut,
"%5s %9lu %9lu %9lu %9lu",
652 fprintf(spOut,
"vPrintOperatorLine: cpOp may not be NULL: line: %u: file: %s\n", __LINE__, __FILE__);
679 static void vDisplayOp(APG_PARSER_CTX* spCtx, APG_OPCODE* spOp,
apg_uint uiOpIndex){
682 if(spOp->pfnOp == uiRNM){
683 APG_RULE* spRule = spOp->sUnion.sRnm.spRule;
684 printf(
"RNM(%s): index: %lu: opcodes: %lu\n",
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){
691 printf(
"REP: min: %lu: max: inf\n", (
printf_uint)spOp->sUnion.sRep.uiMin);
693 printf(
"REP: min: %lu: max: %lu\n", (
printf_uint)spOp->sUnion.sRep.uiMin, (
printf_uint)spOp->sUnion.sRep.uiMax);
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]);
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]);
707 }
else if(spOp->pfnOp == uiAND){
709 }
else if(spOp->pfnOp == uiNOT){
711 }
else if(spOp->pfnOp == uiTRG){
712 printf(
"TRG: min: %lu: max: %lu\n",
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]);
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]);
725 }
else{printf(
"vDisplayOp: unknown operator type\n");}
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,
" ");}
753 fprintf(spOut,
"%s%s lines=\"%lu\" nodes=\"%lu\"%s\n",
756 static void vRootClose(FILE* spOut){
757 fprintf(spOut,
"%s%s%s\n", g_cpBeg2, g_cpRootName, g_cpEnd1);
759 static void vNodeOpen(FILE* spOut,
apg_uint uiId,
char* cpName){
760 fprintf(spOut,
"%snode name=\"%s\" id=\"%lu\"%s\n",
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);
766 static void vPhraseText(FILE* spOut,
const apg_achar* acpPhrase,
apg_uint uiLength){
768 for(; i < uiLength; i++){
776 fprintf(spOut,
"&");
779 fprintf(spOut,
"<");
782 fprintf(spOut,
">");
785 fprintf(spOut,
""");
788 fprintf(spOut,
"'");
791 fprintf(spOut,
"%c", (
char)c);
798 fprintf(spOut,
"%sphrase offset=\"%lu\" length=\"%lu\"%s",
800 vPhraseText(spOut, acpPhrase, uiLength);
801 fprintf(spOut,
"%sphrase%s\n", g_cpBeg2, g_cpEnd1);
803 static void vPrintHeader(FILE* spOut){
804 fprintf(spOut,
"%6s, %6s, %6s\n",
"lineno",
"offset",
"length");
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){
814 cpAdd[uiRet++] =
'\\';
815 cpAdd[uiRet++] =
'x';
816 cHex = (cChar & 0xF0) >> 4;
817 cpAdd[uiRet++] = g_caTrans[(
unsigned int)cHex];
819 cpAdd[uiRet++] = g_caTrans[(
unsigned int)cHex];