47 static const void* s_vpMagicNumber = (
void*)
"stats";
96 static char* s_cpPageHeader;
97 static char* s_cpPageFooter;
98 static char s_cHits =
'h';
99 static char s_cAlpha =
'a';
100 static int compareNames(
const void* l,
const void* r);
101 static int compareHits(
const void* l,
const void* r);
117 parser* spParserCtx = (parser*) vpParserCtx;
121 memset((
void*) spCtx, 0,
sizeof(
stats_ctx));
122 spCtx->spParserCtx = spParserCtx;
124 spCtx->sStats.uiRuleCount = spParserCtx->uiRuleCount;
125 spCtx->sStats.uiUdtCount = spParserCtx->uiUdtCount;
128 memset((
void*) spCtx->sStats.spRuleStats, 0, ((
size_t) spParserCtx->uiRuleCount *
sizeof(
node_stat)));
129 for (ui = 0; ui < spParserCtx->uiRuleCount; ui += 1) {
130 spCtx->sStats.spRuleStats[ui].cpName = spParserCtx->spRules[ui].cpRuleName;
132 if (spParserCtx->uiUdtCount) {
135 memset((
void*) spCtx->sStats.spUdtStats, 0, ((
size_t) spParserCtx->uiUdtCount *
sizeof(
node_stat)));
136 for (ui = 0; ui < spParserCtx->uiUdtCount; ui += 1) {
137 spCtx->sStats.spUdtStats[ui].cpName = spParserCtx->spUdts[ui].cpUdtName;
142 spParserCtx->vpStats = (
void*) spCtx;
143 spCtx->vpValidate = s_vpMagicNumber;
144 return (
void*) spCtx;
162 switch (spOp->sGen.uiId) {
164 spNodeStat = &spStats->
sAlt;
167 spNodeStat = &spStats->
sCat;
170 spNodeStat = &spStats->
sRep;
173 spNodeStat = &spStats->
sRnm;
174 spRuleStat = &spStats->
spRuleStats[spOp->sRnm.spRule->uiRuleIndex];
177 spNodeStat = &spStats->
sTrg;
180 spNodeStat = &spStats->
sTbs;
183 spNodeStat = &spStats->
sTls;
186 spNodeStat = &spStats->
sUdt;
187 spRuleStat = &spStats->
spUdtStats[spOp->sUdt.spUdt->uiUdtIndex];
190 spNodeStat = &spStats->
sAnd;
193 spNodeStat = &spStats->
sNot;
196 spNodeStat = &spStats->
sBkr;
199 spNodeStat = &spStats->
sBka;
202 spNodeStat = &spStats->
sBkn;
205 spNodeStat = &spStats->
sAbg;
208 spNodeStat = &spStats->
sAen;
220 spNodeStat = &spStats->
sTotal;
246 void vStatsToHtml(
void* vpCtx,
const char* cpMode,
const char* cpFileName) {
254 FILE* spOut = stdout;
261 cpModeName =
"hit count";
263 if (*cpMode ==
'a' || *cpMode ==
'A') {
264 cpModeName =
"alphabetical";
270 spOut = fopen(cpFileName,
"wb");
276 fprintf(spOut,
"%s", s_cpPageHeader);
277 fprintf(spOut,
"<h3>Node Statistics<h3/>\n");
280 fprintf(spOut,
"%s",
"<table class=\"apg-stats\">\n");
281 fprintf(spOut,
"<caption>Operators<caption/>\n");
282 fprintf(spOut,
"<tr><th>name</th><th>hits</th><th>match</th><th>no match</th><tr>\n");
283 spNode = &spStats->
sAlt;
285 "<tr><td><span class=\"apg-remainder\">non-<br>terminals</span></td><td></td><td></td><td></td><tr>\n");
286 fprintf(spOut,
"<tr><td>ALT</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
288 spNode = &spStats->
sCat;
289 fprintf(spOut,
"<tr><td>CAT</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
291 spNode = &spStats->
sRep;
292 fprintf(spOut,
"<tr><td>REP</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
294 spNode = &spStats->
sRnm;
295 fprintf(spOut,
"<tr><td>RNM</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
297 spNode = &spStats->
sAnd;
298 fprintf(spOut,
"<tr><td>AND</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
300 spNode = &spStats->
sNot;
301 fprintf(spOut,
"<tr><td>NOT</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
303 spNode = &spStats->
sBka;
304 fprintf(spOut,
"<tr><td>BKA</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
306 spNode = &spStats->
sBkn;
307 fprintf(spOut,
"<tr><td>BKN</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
309 fprintf(spOut,
"<tr><td><span class=\"apg-remainder\">terminals</span></td><td></td><td></td><td></td><tr>\n");
310 spNode = &spStats->
sTls;
311 fprintf(spOut,
"<tr><td>TLS</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
313 spNode = &spStats->
sTbs;
314 fprintf(spOut,
"<tr><td>TBS</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
316 spNode = &spStats->
sTrg;
317 fprintf(spOut,
"<tr><td>TRG</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
319 spNode = &spStats->
sUdt;
320 fprintf(spOut,
"<tr><td>UDT</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
322 spNode = &spStats->
sBkr;
323 fprintf(spOut,
"<tr><td>BKR</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
325 spNode = &spStats->
sAbg;
326 fprintf(spOut,
"<tr><td>ABG</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
328 spNode = &spStats->
sAen;
329 fprintf(spOut,
"<tr><td>AEN</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
331 spNode = &spStats->
sTotal;
332 fprintf(spOut,
"<tr><td>total</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", (
luint) spNode->
uiHits,
336 fprintf(spOut,
"%s",
"</table>\n");
344 if (cMode == s_cHits) {
348 fprintf(spOut,
"<br/>\n");
349 fprintf(spOut,
"%s",
"<table class=\"apg-stats\">\n");
350 fprintf(spOut,
"<caption>Rules: %s<caption/>\n", cpModeName);
351 fprintf(spOut,
"<tr><th>name</th><th>hits</th><th>match</th><th>no match</th><tr>\n");
353 spNode = &sRuleStats[ui];
355 fprintf(spOut,
"<tr><td>%s</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", spNode->
cpName,
361 fprintf(spOut,
"%s",
"</table>\n");
366 for (ui = 0; ui < spStats->
uiUdtCount; ui += 1) {
370 if (cMode == s_cHits) {
374 fprintf(spOut,
"<br/>\n");
375 fprintf(spOut,
"%s",
"<table class=\"apg-stats\">\n");
376 fprintf(spOut,
"<caption>UDTs: %s<caption/>\n", cpModeName);
377 fprintf(spOut,
"<tr><th>name</th><th>hits</th><th>match</th><th>no match</th><tr>\n");
378 for (ui = 0; ui < spStats->
uiUdtCount; ui += 1) {
379 spNode = &sUdtStats[ui];
381 fprintf(spOut,
"<tr><td>%s</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><td>%"PRIuMAX
"</td><tr>\n", spNode->
cpName,
387 fprintf(spOut,
"%s",
"</table>\n");
392 time_t tTime = time(NULL);
393 if (tTime != (time_t)-1) {
394 fprintf(spOut,
"<h5>%s</h5>\n", asctime(gmtime(&tTime)));
396 fprintf(spOut,
"%s", s_cpPageFooter);
398 if (spOut != stdout) {
412 void vStatsToAscii(
void* vpCtx,
const char* cpMode,
const char* cpFileName) {
420 FILE* spOut = stdout;
427 cpModeName =
"hit count";
429 if (*cpMode ==
'a' || *cpMode ==
'A') {
430 cpModeName =
"alphabetical";
436 spOut = fopen(cpFileName,
"wb");
441 fprintf(spOut,
"NODE STATISTICS\n");
444 fprintf(spOut,
"Operators: non-terminals\n");
445 spNode = &spStats->
sAlt;
446 char* cpFormats =
"| %7s | %7s | %7s | %s\n";
447 char* cpFormat =
"| %7"PRIuMAX
" | %7"PRIuMAX
" | %7"PRIuMAX
" | %s\n";
448 fprintf(spOut, cpFormats,
"hits",
"match",
"nomatch",
"name");
449 spNode = &spStats->
sAlt;
452 spNode = &spStats->
sCat;
455 spNode = &spStats->
sRep;
458 spNode = &spStats->
sRnm;
461 spNode = &spStats->
sAnd;
464 spNode = &spStats->
sNot;
467 spNode = &spStats->
sBka;
470 spNode = &spStats->
sBkn;
474 fprintf(spOut,
"\n");
475 fprintf(spOut,
"Operators: terminals\n");
476 fprintf(spOut, cpFormats,
"hits",
"match",
"nomatch",
"name");
477 spNode = &spStats->
sTls;
480 spNode = &spStats->
sTbs;
483 spNode = &spStats->
sTrg;
486 spNode = &spStats->
sUdt;
489 spNode = &spStats->
sBkr;
492 spNode = &spStats->
sAbg;
495 spNode = &spStats->
sAen;
499 fprintf(spOut,
"\n");
500 fprintf(spOut,
"Operators: total\n");
501 spNode = &spStats->
sTotal;
511 if (cMode == s_cHits) {
515 fprintf(spOut,
"\n");
516 fprintf(spOut,
"Rules: %s\n", cpModeName);
517 fprintf(spOut, cpFormats,
"hits",
"match",
"nomatch",
"name");
519 spNode = &sRuleStats[ui];
528 for (ui = 0; ui < spStats->
uiUdtCount; ui += 1) {
532 if (cMode == s_cHits) {
536 fprintf(spOut,
"\n");
537 fprintf(spOut,
"UDTs: %s\n", cpModeName);
538 fprintf(spOut, cpFormats,
"hits",
"match",
"nomatch",
"name");
539 for (ui = 0; ui < spStats->
uiUdtCount; ui += 1) {
540 spNode = &sUdtStats[ui];
542 fprintf(spOut, cpFormat,
547 time_t tTime = time(NULL);
548 if (tTime != (time_t)-1) {
549 fprintf(spOut,
"\n");
550 fprintf(spOut,
"%s\n", asctime(gmtime(&tTime)));
552 if (spOut != stdout) {
557 static int compareNames(
const void* l,
const void* r) {
562 aint uiLen = uiLenL < uiLenR ? uiLenL : uiLenR;
565 for(ui = 0; ui < uiLen; ui++){
568 if (cL >= 65 && cL <= 90) {
571 if (cR >= 65 && cR <= 90) {
589 static int compareHits(
const void* l,
const void* r) {
601 static char* s_cpPageHeader =
"<!DOCTYPE html>\n"
602 "<html lang=\"en\">\n"
604 "<meta charset=\"utf-8\">\n"
605 "<title>stats</title>\n"
608 " font-family: monospace;\n"
611 " font-weight: bold;\n"
615 " font-weight: bold;\n"
619 " font-weight: bold;\n"
623 " font-weight: bold;\n"
627 " font-weight: bold;\n"
631 " font-weight: bold;\n"
635 " font-weight: bold;\n"
639 " font-weight: bolder;\n"
640 " font-style: italic;\n"
641 " font-size: .6em;\n"
644 " font-weight: bold;\n"
648 " font-weight: bold;\n"
653 " background-color: #8caae6;\n"
655 ".apg-empty-phrase {\n"
658 "table.apg-state {\n"
659 " font-family: monospace;\n"
660 " margin-top: 5px;\n"
661 " font-size: 11px;\n"
662 " line-height: 130%;\n"
663 " text-align: left;\n"
664 " border: 1px solid black;\n"
665 " border-collapse: collapse;\n"
667 "table.apg-state th,\n"
668 "table.apg-state td {\n"
669 " text-align: left;\n"
670 " border: 1px solid black;\n"
671 " border-collapse: collapse;\n"
673 "table.apg-state th:nth-last-child(2),\n"
674 "table.apg-state td:nth-last-child(2) {\n"
675 " text-align: right;\n"
677 "table.apg-state caption {\n"
678 " font-size: 125%;\n"
679 " line-height: 130%;\n"
680 " font-weight: bold;\n"
681 " text-align: left;\n"
683 "table.apg-stats {\n"
684 " font-family: monospace;\n"
685 " margin-top: 5px;\n"
686 " font-size: 11px;\n"
687 " line-height: 130%;\n"
688 " text-align: right;\n"
689 " border: 1px solid black;\n"
690 " border-collapse: collapse;\n"
692 "table.apg-stats th,\n"
693 "table.apg-stats td {\n"
694 " text-align: right;\n"
695 " border: 1px solid black;\n"
696 " border-collapse: collapse;\n"
698 "table.apg-stats caption {\n"
699 " font-size: 125%;\n"
700 " line-height: 130%;\n"
701 " font-weight: bold;\n"
702 " text-align: left;\n"
704 "table.apg-trace {\n"
705 " font-family: monospace;\n"
706 " margin-top: 5px;\n"
707 " font-size: 11px;\n"
708 " line-height: 130%;\n"
709 " text-align: right;\n"
710 " border: 1px solid black;\n"
711 " border-collapse: collapse;\n"
713 "table.apg-trace caption {\n"
714 " font-size: 125%;\n"
715 " line-height: 130%;\n"
716 " font-weight: bold;\n"
717 " text-align: left;\n"
719 "table.apg-trace th,\n"
720 "table.apg-trace td {\n"
721 " text-align: right;\n"
722 " border: 1px solid black;\n"
723 " border-collapse: collapse;\n"
725 "table.apg-trace th:last-child,\n"
726 "table.apg-trace th:nth-last-child(2),\n"
727 "table.apg-trace td:last-child,\n"
728 "table.apg-trace td:nth-last-child(2) {\n"
729 " text-align: left;\n"
731 "table.apg-grammar {\n"
732 " font-family: monospace;\n"
733 " margin-top: 5px;\n"
734 " font-size: 11px;\n"
735 " line-height: 130%;\n"
736 " text-align: right;\n"
737 " border: 1px solid black;\n"
738 " border-collapse: collapse;\n"
740 "table.apg-grammar caption {\n"
741 " font-size: 125%;\n"
742 " line-height: 130%;\n"
743 " font-weight: bold;\n"
744 " text-align: left;\n"
746 "table.apg-grammar th,\n"
747 "table.apg-grammar td {\n"
748 " text-align: right;\n"
749 " border: 1px solid black;\n"
750 " border-collapse: collapse;\n"
752 "table.apg-grammar th:last-child,\n"
753 "table.apg-grammar td:last-child {\n"
754 " text-align: left;\n"
756 "table.apg-rules {\n"
757 " font-family: monospace;\n"
758 " margin-top: 5px;\n"
759 " font-size: 11px;\n"
760 " line-height: 130%;\n"
761 " text-align: right;\n"
762 " border: 1px solid black;\n"
763 " border-collapse: collapse;\n"
765 "table.apg-rules caption {\n"
766 " font-size: 125%;\n"
767 " line-height: 130%;\n"
768 " font-weight: bold;\n"
769 " text-align: left;\n"
771 "table.apg-rules th,\n"
772 "table.apg-rules td {\n"
773 " text-align: right;\n"
774 " border: 1px solid black;\n"
775 " border-collapse: collapse;\n"
777 "table.apg-rules a {\n"
778 " color: #003399 !important;\n"
780 "table.apg-rules a:hover {\n"
781 " color: #8caae6 !important;\n"
783 "table.apg-attrs {\n"
784 " font-family: monospace;\n"
785 " margin-top: 5px;\n"
786 " font-size: 11px;\n"
787 " line-height: 130%;\n"
788 " text-align: center;\n"
789 " border: 1px solid black;\n"
790 " border-collapse: collapse;\n"
792 "table.apg-attrs caption {\n"
793 " font-size: 125%;\n"
794 " line-height: 130%;\n"
795 " font-weight: bold;\n"
796 " text-align: left;\n"
798 "table.apg-attrs th,\n"
799 "table.apg-attrs td {\n"
800 " text-align: center;\n"
801 " border: 1px solid black;\n"
802 " border-collapse: collapse;\n"
804 "table.apg-attrs th:nth-child(1),\n"
805 "table.apg-attrs th:nth-child(2),\n"
806 "table.apg-attrs th:nth-child(3) {\n"
807 " text-align: right;\n"
809 "table.apg-attrs td:nth-child(1),\n"
810 "table.apg-attrs td:nth-child(2),\n"
811 "table.apg-attrs td:nth-child(3) {\n"
812 " text-align: right;\n"
814 "table.apg-attrs a {\n"
815 " color: #003399 !important;\n"
817 "table.apg-attrs a:hover {\n"
818 " color: #8caae6 !important;\n"
823 static char* s_cpPageFooter =
"</body>\n"