Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
utilities.c
Go to the documentation of this file.
1 /* *************************************************************************************
2  Copyright (c) 2021, Lowell D. Thomas
3  All rights reserved.
4 
5  This file is part of APG Version 7.0.
6  APG Version 7.0 may be used under the terms of the BSD 2-Clause License.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 * *************************************************************************************/
34 #include <unistd.h>
35 #include <limits.h>
36 
37 #include "./utilities.h"
38 
39 static const size_t s_uiBufSize = (PATH_MAX + 128);
40 static char s_cPeriod = 46;
41 static char* s_cpBinaryVal[16] = {
42  "00 00", "00 01", "00 10", "00 11",
43  "01 00", "01 01", "01 10", "01 11",
44  "10 00", "10 01", "10 10", "10 11",
45  "11 00", "11 01", "11 10", "11 11",
46 };
47 static char* s_cpDecimalVal[16] = {
48  "0 0", "0 1", "0 2", "0 3",
49  "1 0", "1 1", "1 2", "1 3",
50  "2 0", "2 1", "2 2", "2 3",
51  "3 0", "3 1", "3 2", "3 3",
52 };
53 
54 static void vDisplayBinary(uint8_t ucChar);
55 static void vDisplayDecimal(uint8_t ucChar);
56 
60 void vUtilApgInfo(void){
61  static char* cpDefined = "defined";
62  static char* cpUndefined = "undefined";
63  char* cpDef;
64  cpDef = cpDefined; // prevents "defined but not used" error warnings
65  cpDef = cpUndefined; // prevents "defined but not used" error warnings
66  printf("TYPES & SIZES\n");
67  printf("sizeof(achar) : %"PRIuMAX" : the APG alphabet character\n", (luint)sizeof(achar));
68  printf("sizeof(aint) : %"PRIuMAX" : the APG unsigned int\n", (luint)sizeof(aint));
69  printf("sizeof(abool) : %"PRIuMAX" : the APG true/false boolean\n", (luint)sizeof(abool));
70  printf("sizeof(luint) : %"PRIuMAX" : longest unsigned int,\n", (luint)sizeof(luint));
71  printf(" used primarily for printing integers of unknown length(e.g. printf(\"%%\"PRIuMAX\"\", (luint)var)\n");
72  printf("\n");
73  printf("MACROS\n");
74  printf("APG_VERSION : %s\n", APG_VERSION);
75  printf("APG_COPYRIGHT : %s\n", APG_COPYRIGHT);
76  printf("APG_LICENSE : %s\n", APG_LICENSE);
77 #ifdef APG_ACHAR
78  printf("APG_ACHAR : %u : controls the size of the parser's alphabet character(achar)\n", (unsigned)APG_ACHAR);
79 #else
80  printf("APG_ACHAR : %s : controls the size of the parser's alphabet character(achar)\n", cpUndefined);
81 #endif
82 #ifdef APG_AINT
83  printf("APG_AINT : %u : controls the size of the parser's unsigned integer(aint)\n", (unsigned)APG_AINT);
84 #else
85  printf("APG_AINT : %s : controls the size of the parser's unsigned integer(aint)\n", cpUndefined);
86 #endif
87  printf("APG_TRUE : %u : the APG \"true\" value\n", (unsigned)APG_TRUE);
88  printf("APG_FALSE : %u : the APG \"false\" value\n", (unsigned)APG_FALSE);
89  printf("APG_SUCCESS : %u : function return value indicating success\n", (unsigned)APG_SUCCESS);
90  printf("APG_FAILURE : %u : function return value indicating failure\n", (unsigned)APG_FAILURE);
91  printf("APG_UNDEFINED : %"PRIuMAX" : used to indicate an undefined unsigned integer\n", (luint)APG_UNDEFINED);
92  printf("APG_INFINITE : %"PRIuMAX" : used to indicate an infinite unsigned integer\n", (luint)APG_INFINITE);
93  printf("APG_MAX_AINT : %"PRIuMAX" : maximum allowed unsigned integer value \n", (luint)APG_MAX_AINT);
94  printf("APG_MAX_ACHAR : %"PRIuMAX" : maximum allowed alphabet character\n", (luint)APG_MAX_ACHAR);
95 
96  cpDef = cpUndefined;
97 #ifdef APG_DEBUG
98  cpDef = cpDefined;
99 #endif
100  printf("APG_DEBUG : %9s : if defined, defines APG_TRACE, APG_STATS, APG_MEM_STATS, APG_VEC_STATS, APG_AST & APG_BKR\n", cpDef);
101 
102  cpDef = cpUndefined;
103 #ifdef APG_TRACE
104  cpDef = cpDefined;
105 #endif
106  printf("APG_TRACE : %9s : if defined, allow parser tracing (includes stdio.h)\n", cpDef);
107 
108  cpDef = cpUndefined;
109 #ifdef APG_STATS
110  cpDef = cpDefined;
111 #endif
112  printf("APG_STATS : %9s : if defined, allows parser to collect parsing statistics (includes stdio.h)\n", cpDef);
113 
114  cpDef = cpUndefined;
115 #ifdef APG_MEM_STATS
116  cpDef = cpDefined;
117 #endif
118  printf("APG_MEM_STATS : %9s : if defined, collect all memory object statistics\n", cpDef);
119 
120  cpDef = cpUndefined;
121 #ifdef APG_VEC_STATS
122  cpDef = cpDefined;
123 #endif
124  printf("APG_VEC_STATS : %9s : if defined, collect all vector object statistics\n", cpDef);
125 
126  cpDef = cpUndefined;
127 #ifdef APG_AST
128  cpDef = cpDefined;
129 #endif
130  printf("APG_AST : %9s : if defined, allow creation of the Absract Syntax Tree (AST)\n", cpDef);
131 
132  cpDef = cpUndefined;
133 #ifdef APG_BKR
134  cpDef = cpDefined;
135 #endif
136  printf("APG_BKR : %9s : if defined, allow back reference operators, e.g. %%urulename\n", cpDef);
137 
138  cpDef = cpUndefined;
139 #ifdef APG_STRICT_ABNF
140  cpDef = cpDefined;
141 #endif
142  printf("APG_STRICT_ABNF : %9s : if defined, allow only grammars with ABNF as defined in RFCs 5234 & 7405\n", cpDef);
143 
144  cpDef = cpUndefined;
145 #ifdef APG_NO_PPPT
146  cpDef = cpDefined;
147 #endif
148  printf("APG_NO_PPPT : %9s : if defined, no Partially-Predictive Parsing Tables (PPPT) will be generated\n", cpDef);
149 }
150 
153 void vUtilSizes(void) {
154  printf("APG TYPES & SIZES\n");
155  printf("sizeof(achar) %"PRIuMAX" : the APG alphabet character\n", (luint)sizeof(achar));
156  printf("sizeof(aint) %"PRIuMAX" : the APG unsigned int\n", (luint)sizeof(aint));
157  printf("sizeof(abool) %"PRIuMAX" : the APG true/false boolean\n", (luint)sizeof(abool));
158  printf("sizeof(luint) %"PRIuMAX" : for printing ints of unknown length (e.g. printf(\"%%\"PRIuMAX\"\", (luint)uiVar)\n", (luint)sizeof(luint));
159  printf("\nAPG MAXIMUM VALUES\n");
160  printf("achar %"PRIuMAX"\n", (luint)((achar)-1));
161  printf("aint %"PRIuMAX"\n", (luint)((aint)-1));
162  printf("abool %"PRIuMAX"\n", (luint)((abool)-1));
163  printf("luint %"PRIuMAX"\n", (luint)-1);
164  printf("\nSYSTEM TYPES & SIZES\n");
165  printf("sizeof(unsigned char) %"PRIuMAX"\n", (luint)sizeof(unsigned char));
166  printf("sizeof(unsigned short int) %"PRIuMAX"\n", (luint)sizeof(unsigned short int));
167  printf("sizeof(unsigned int) %"PRIuMAX"\n", (luint)sizeof(unsigned int));
168  printf("sizeof(unsigned long int) %"PRIuMAX"\n", (luint)sizeof(unsigned long int));
169  printf("sizeof(unsigned long long int) %"PRIuMAX"\n", (luint)sizeof(unsigned long long int));
170  printf("sizeof(uintmax_t) %"PRIuMAX"\n", (luint)sizeof(uintmax_t));
171  printf("sizeof(uint8_t) %"PRIuMAX"\n", (luint)sizeof(uint8_t));
172  printf("sizeof(uint16_t) %"PRIuMAX"\n", (luint)sizeof(uint16_t));
173  printf("sizeof(uint32_t) %"PRIuMAX"\n", (luint)sizeof(uint32_t));
174  printf("sizeof(uint64_t) %"PRIuMAX"\n", (luint)sizeof(uint64_t));
175  printf("sizeof(uint_least8_t) %"PRIuMAX"\n", (luint)sizeof(uint_least8_t));
176  printf("sizeof(uint_least16_t) %"PRIuMAX"\n", (luint)sizeof(uint_least16_t));
177  printf("sizeof(uint_least32_t) %"PRIuMAX"\n", (luint)sizeof(uint_least32_t));
178  printf("sizeof(uint_least64_t) %"PRIuMAX"\n", (luint)sizeof(uint_least64_t));
179  printf("sizeof(uint_fast8_t) %"PRIuMAX"\n", (luint)sizeof(uint_fast8_t));
180  printf("sizeof(uint_fast16_t) %"PRIuMAX"\n", (luint)sizeof(uint_fast16_t));
181  printf("sizeof(uint_fast32_t) %"PRIuMAX"\n", (luint)sizeof(uint_fast32_t));
182  printf("sizeof(uint_fast64_t) %"PRIuMAX"\n", (luint)sizeof(uint_fast64_t));
183  printf("\nSYSTEM MAXIMUM VALUES\n");
184  printf("uint8_t %"PRIuMAX"\n", (luint)((uint8_t)-1));
185  printf("uint16_t %"PRIuMAX"\n", (luint)((uint16_t)-1));
186  printf("uint32_t %"PRIuMAX"\n", (luint)((uint32_t)-1));
187  printf("uint64_t %"PRIuMAX"\n", (luint)((uint64_t)-1));
188 }
189 
192  printf("CURRENT WORKING DIRECTORY\n");
193  char cwd[PATH_MAX];
194  if (getcwd(cwd, sizeof(cwd)) != NULL) {
195  printf("%s\n", cwd);
196  } else {
197  printf("getcwd() error\n");
198  }
199 }
200 
210 void vUtilFileWrite(void* vpMem, const char* cpFileName, uint8_t* ucpData, aint uiLen){
211  if(!bMemValidate(vpMem)){
212  vExContext();
213  }
214  char caBuf[s_uiBufSize];
215  exception* spEx = spMemException(vpMem);
216  if(!cpFileName || cpFileName[0] == 0){
217  XTHROW(spEx, "file name cannot be NULL or empty");
218  }
219  if(!ucpData || !uiLen){
220  XTHROW(spEx, "data cannot be NULL or empty");
221  }
222  // note: the "b" in "wb" is required on some systems (I'm looking at you Windows.)
223  FILE* spFile = fopen(cpFileName, "wb");
224  if(!spFile){
225  snprintf(caBuf, s_uiBufSize, "can't open file \"%s\" for write", cpFileName);
226  XTHROW(spEx, caBuf);
227  }
228  size_t uiWrite = fwrite((void*)ucpData, sizeof(uint8_t), uiLen, spFile);
229  fclose(spFile);
230  if((aint)uiWrite != uiLen){
231  snprintf(caBuf, s_uiBufSize, "file write error: file name: %s: bytes to write: %"PRIuMAX": bytes written: %"PRIuMAX"",
232  cpFileName, (luint)uiLen, (luint)uiWrite);
233  XTHROW(spEx, caBuf);
234  }
235 }
236 
252 void vUtilFileRead(void* vpMem, const char* cpFileName, uint8_t* ucpData, aint* uipLen){
253  if(!bMemValidate(vpMem)){
254  vExContext();
255  }
256  char caBuf[s_uiBufSize];
257  exception* spEx = spMemException(vpMem);
258  if(!cpFileName || cpFileName[0] == 0){
259  XTHROW(spEx, "file name cannot be NULL or empty");
260  }
261  if(!uipLen){
262  XTHROW(spEx, "data length pointer cannot be NULL");
263  }
264  // note: the "b" in "rb" is required on some systems (I'm looking at you Windows.)
265  FILE* spFile = fopen(cpFileName, "rb");
266  if(!spFile){
267  snprintf(caBuf, s_uiBufSize, "can't open file \"%s\" for read", cpFileName);
268  XTHROW(spEx, caBuf);
269  }
270  aint uiBufferLen;
271  if(!ucpData){
272  uiBufferLen = 0;
273  }else{
274  uiBufferLen = *uipLen;
275  }
276  size_t uiBytesRead = 0;
277  size_t uiBytesCopied = 0;
278  size_t uiBytesToCopy = uiBufferLen;
279  uint8_t caReadBuf[4096];
280  size_t uiBlockBytes = fread(caReadBuf, 1, sizeof(caReadBuf), spFile);
281  while(uiBlockBytes != 0){
282  uiBytesRead += uiBlockBytes;
283  if(uiBytesCopied < uiBufferLen){
284  uiBytesToCopy = uiBufferLen - uiBytesCopied;
285  if(uiBytesToCopy > uiBlockBytes){
286  uiBytesToCopy = uiBlockBytes;
287  }
288  memcpy((void*)&ucpData[uiBytesCopied], (void*)&caReadBuf[0], uiBytesToCopy);
289  uiBytesCopied += uiBytesToCopy;
290  }
291  uiBlockBytes = fread(caReadBuf, 1, sizeof(caReadBuf), spFile);
292  }
293  fclose(spFile);
294  if(uiBytesRead > APG_MAX_AINT){
295  XTHROW(spEx, "sizeof(aint) too small");
296  }
297  *uipLen = (aint)(uiBytesRead);
298 }
299 
306 abool bUtilCompareFiles(const char* cpFileL, const char* cpFileR){
307  FILE* spL = NULL, *spR = NULL;
308  int iL, iR;
309  abool bReturn = APG_FALSE;
310  spL = fopen(cpFileL, "rb");
311  if(!spL){
312  goto notequal;
313  }
314  spR = fopen(cpFileR, "rb");
315  if(!spR){
316  goto notequal;
317  }
318  while(APG_TRUE){
319  iL = fgetc(spL);
320  iR = fgetc(spR);
321  if(iL != iR){
322  goto notequal;
323  }
324  if(iL == EOF){
325  break;
326  }
327  }
328  bReturn = APG_TRUE;
329  notequal:;
330  if(spL){
331  fclose(spL);
332  }
333  if(spR){
334  fclose(spR);
335  }
336  return bReturn;
337 }
338 
350 abool bUtilCompareFileLines(void* vpMem, const char* cpFileL, const char* cpFileR){
351  if(!bMemValidate(vpMem)){
352  vExContext();
353  }
354  exception* spEx = spMemException(vpMem);
355  if(!cpFileL || !cpFileR){
356  XTHROW(spEx, "file names cannot be NULL");
357  }
358  abool bReturn = APG_FALSE;
359  aint ui;
360  line* spL;
361  line* spR;
362  void* vpLinesL = NULL;
363  void* vpLinesR = NULL;
364  uint8_t* ucpLeft = NULL;
365  uint8_t* ucpRight = NULL;
366  aint uiSize = 2048;
367  aint uiSizeL = uiSize;
368  aint uiSizeR = uiSize;
369  ucpLeft = (uint8_t*)vpMemAlloc(vpMem, uiSizeL);
370  vUtilFileRead(vpMem, cpFileL, ucpLeft, &uiSizeL);
371  if(uiSizeL > uiSize){
372  vMemFree(vpMem, ucpLeft);
373  ucpLeft = (uint8_t*)vpMemAlloc(vpMem, uiSizeL);
374  vUtilFileRead(vpMem, cpFileL, ucpLeft, &uiSizeL);
375  }
376  ucpRight = (uint8_t*)vpMemAlloc(vpMem, uiSizeR);
377  vUtilFileRead(vpMem, cpFileR, ucpRight, &uiSizeR);
378  if(uiSizeR > uiSize){
379  vMemFree(vpMem, ucpRight);
380  ucpRight = (uint8_t*)vpMemAlloc(vpMem, uiSizeR);
381  vUtilFileRead(vpMem, cpFileR, ucpRight, &uiSizeR);
382  }
383  vpLinesL = vpLinesCtor(spEx, (char*)ucpLeft, uiSizeL);
384  vpLinesR = vpLinesCtor(spEx, (char*)ucpRight, uiSizeR);
385  if(uiLinesCount(vpLinesL) != uiLinesCount(vpLinesR)){
386  goto fail;
387  }
388  spL = spLinesFirst(vpLinesL);
389  spR = spLinesFirst(vpLinesR);
390  while(spL){
391  if(spL->uiTextLength != spR->uiTextLength){
392  goto fail;
393  }
394  for(ui = 0; ui < spL->uiTextLength; ui++){
395  if(ucpLeft[spL->uiCharIndex + ui] != ucpRight[spR->uiCharIndex + ui]){
396  goto fail;
397  }
398  }
399  spL = spLinesNext(vpLinesL);
400  spR = spLinesNext(vpLinesR);
401  }
402  bReturn = APG_TRUE;
403  fail:;
404  vMemFree(vpMem, ucpLeft);
405  vMemFree(vpMem, ucpRight);
406  vLinesDtor(vpLinesL);
407  vLinesDtor(vpLinesR);
408  return bReturn;
409 }
410 
416  if(bExValidate(spEx)){
417  printf("%s:%s(%u):\n%s\n",
418  spEx->caFile, spEx->caFunc, spEx->uiLine, spEx->caMsg);
419  }else{
420  printf("vUtilPrintException: not a valid exception pointer\n");
421  }
422 }
423 
427 void vUtilPrintMemStats(const mem_stats* spStats) {
428  printf("allocations: %"PRIuMAX"\n", (luint) (spStats->uiAllocations));
429  printf("reallocations: %"PRIuMAX"\n", (luint) (spStats->uiReAllocations));
430  printf("frees: %"PRIuMAX"\n", (luint) (spStats->uiFrees));
431  printf("current cells: %"PRIuMAX"\n", (luint) (spStats->uiCells));
432  printf("max cells: %"PRIuMAX"\n", (luint) (spStats->uiMaxCells));
433  printf("current heap bytes: %"PRIuMAX"\n", (luint) (spStats->uiHeapBytes));
434  printf("max heap bytes: %"PRIuMAX"\n", (luint) (spStats->uiMaxHeapBytes));
435 }
436 
440 void vUtilPrintVecStats(const vec_stats* spStats) {
441  printf("ORIGINAL:\n");
442  printf(" element size(bytes): %"PRIuMAX"\n", (luint) (spStats->uiElementSize));
443  printf(" reserved elements: %"PRIuMAX"\n", (luint) (spStats->uiOriginalElements));
444  printf(" reserved bytes: %"PRIuMAX"\n", (luint) (spStats->uiOriginalBytes));
445  printf("CURRENT:\n");
446  printf(" reserved elements: %"PRIuMAX"\n", (luint) (spStats->uiReserved));
447  printf(" reserved bytes: %"PRIuMAX"\n", (luint) (spStats->uiReservedBytes));
448  printf(" used elements: %"PRIuMAX"\n", (luint) (spStats->uiUsed));
449  printf(" used bytes: %"PRIuMAX"\n", (luint) (spStats->uiUsedBytes));
450  printf("MAX:\n");
451  printf(" max elements: %"PRIuMAX"\n", (luint) (spStats->uiMaxUsed));
452  printf(" max bytes: %"PRIuMAX"\n", (luint) (spStats->uiMaxUsedBytes));
453  printf("STATS:\n");
454  printf(" pushed elements: %"PRIuMAX"\n", (luint) (spStats->uiPushed));
455  printf(" popped elements: %"PRIuMAX"\n", (luint) (spStats->uiPopped));
456  printf(" times grown: %"PRIuMAX"\n", (luint) (spStats->uiGrownCount));
457  printf(" elements grown: %"PRIuMAX"\n", (luint) (spStats->uiGrownElements));
458  printf(" bytes grown: %"PRIuMAX"\n", (luint) (spStats->uiGrownBytes));
459 }
460 
464 void vUtilPrintLine(line* spLine){
465  char caBuf[16];
466  if(spLine){
467  printf("line index: %d\n", (int)spLine->uiLineIndex);
468  printf("char index: %d\n", (int)spLine->uiCharIndex);
469  printf("line length: %d\n", (int)spLine->uiLineLength);
470  printf("text length: %d\n", (int)spLine->uiTextLength);
471  printf("line end[0]: %s\n", cpUtilPrintChar(spLine->caLineEnd[0], caBuf));
472  if(spLine->caLineEnd[1]){
473  printf("line end[1]: %s\n", cpUtilPrintChar(spLine->caLineEnd[1], caBuf));
474  }
475  }else{
476  printf("print lines: NULL input\n");
477  }
478 }
479 
483 void vUtilPrintLineu(line_u* spLine){
484  char caBuf[16];
485  if(spLine){
486  printf("line index: %d\n", (int)spLine->uiLineIndex);
487  printf("char index: %d\n", (int)spLine->uiCharIndex);
488  printf("line length: %d\n", (int)spLine->uiLineLength);
489  printf("text length: %d\n", (int)spLine->uiTextLength);
490  printf("line end[0]: %s\n", cpUtilPrintUChar(spLine->uiaLineEnd[0], caBuf));
491  if(spLine->uiaLineEnd[1]){
492  printf("line end[1]: %s\n", cpUtilPrintUChar(spLine->uiaLineEnd[1], caBuf));
493  }
494  }else{
495  printf("print lines: NULL input\n");
496  }
497 }
498 
504 char* cpUtilPrintChar(char cChar, char* cpBuf){
505  if(cpBuf){
506  while(APG_TRUE){
507  if(cChar == 9){
508  sprintf(cpBuf, "\\t");
509  break;
510  }
511  if(cChar == 10){
512  sprintf(cpBuf, "\\n");
513  break;
514  }
515  if(cChar == 13){
516  sprintf(cpBuf, "\\r");
517  break;
518  }
519  if(cChar == 32){
520  sprintf(cpBuf, "sp");
521  break;
522  }
523  if(cChar >= 33 && cChar <= 126){
524  sprintf(cpBuf, "%c", cChar);
525  break;
526  }
527  sprintf(cpBuf, "0x%02X", (unsigned char)cChar);
528  break;
529  }
530  }
531  return cpBuf;
532 }
533 
539 char* cpUtilPrintUChar(uint32_t uiChar, char* cpBuf){
540  if(cpBuf){
541  while(APG_TRUE){
542  if(uiChar == 9){
543  sprintf(cpBuf, "TAB");
544  break;
545  }
546  if(uiChar == 10){
547  sprintf(cpBuf, "LF");
548  break;
549  }
550  if(uiChar == 11){
551  sprintf(cpBuf, "VT");
552  break;
553  }
554  if(uiChar == 12){
555  sprintf(cpBuf, "FF");
556  break;
557  }
558  if(uiChar == 13){
559  sprintf(cpBuf, "CR");
560  break;
561  }
562  if(uiChar == 0x85){
563  sprintf(cpBuf, "NEL");
564  break;
565  }
566  if(uiChar == 0x2028){
567  sprintf(cpBuf, "LS");
568  break;
569  }
570  if(uiChar == 0x2029){
571  sprintf(cpBuf, "PS");
572  break;
573  }
574  if(uiChar == 32){
575  sprintf(cpBuf, "sp");
576  break;
577  }
578  if(uiChar >= 33 && uiChar <= 126){
579  sprintf(cpBuf, "%c", uiChar);
580  break;
581  }
582  if(uiChar < 0x100){
583  sprintf(cpBuf, "0x%02X", uiChar);
584  }else{
585  sprintf(cpBuf, "0x%04X", uiChar);
586  }
587  break;
588  }
589  }
590  return cpBuf;
591 }
592 
607 const char* cpUtilUtfTypeName(aint uiType){
608  char* cpReturn;
609  abool bBase64 = uiType & BASE64_MASK ? APG_TRUE : APG_FALSE;
610  uiType &= TYPE_MASK;
611  switch(uiType){
612  case BINARY:
613  cpReturn = bBase64 ? "(BINARY | BASE64)" : "BINARY";
614  break;
615  case UTF_8:
616  cpReturn = bBase64 ? "(UTF-8 | BASE64)" : "UTF-8";
617  break;
618  case UTF_16:
619  cpReturn = bBase64 ? "(UTF-16 | BASE64)" : "UTF-16";
620  break;
621  case UTF_16BE:
622  cpReturn = bBase64 ? "(UTF-16BE | BASE64)" : "UTF-16BE";
623  break;
624  case UTF_16LE:
625  cpReturn = bBase64 ? "(UTF-16LE | BASE64)" : "UTF-16LE";
626  break;
627  case UTF_32:
628  cpReturn = bBase64 ? "(UTF-32 | BASE64)" : "UTF-32";
629  break;
630  case UTF_32BE:
631  cpReturn = bBase64 ? "(UTF-32BE | BASE64)" : "UTF-32BE";
632  break;
633  case UTF_32LE:
634  cpReturn = bBase64 ? "(UTF-32LE | BASE64)" : "UTF-32LE";
635  break;
636  default:
637  cpReturn = "UNKNOWN";
638  }
639  return cpReturn;
640 }
641 
646 const char* cpUtilTrueFalse(luint luiTrue) {
647  static char* cpTrue = "TRUE";
648  static char* cpFalse = "FALSE";
649  if(luiTrue){
650  return cpTrue;
651  }
652  return cpFalse;
653 }
654 
659 const char* cpUtilOpName(aint uiId){
660  switch(uiId){
661  case ID_ALT:
662  return "ALT";
663  case ID_CAT:
664  return "CAT";
665  case ID_REP:
666  return "REP";
667  case ID_RNM:
668  return "RNM";
669  case ID_TLS:
670  return "TLS";
671  case ID_TBS:
672  return "TBS";
673  case ID_TRG:
674  return "TRG";
675  case ID_UDT:
676  return "UDT";
677  case ID_AND:
678  return "AND";
679  case ID_NOT:
680  return "NOT";
681  case ID_BKR:
682  return "BKR";
683  case ID_BKA:
684  return "BKA";
685  case ID_BKN:
686  return "BKN";
687  case ID_ABG:
688  return "ABG";
689  case ID_AEN:
690  return "AEN";
691  default:
692  return "UNKNOWN";
693  }
694  return NULL;
695 }
696 
705 static char* cpUtilParserState(aint uiState){
706  char* cpReturn = "UNKNOWN";
707  switch(uiState){
708  case ID_ACTIVE:
709  cpReturn = "ACTIVE";
710  break;
711  case ID_MATCH:
712  cpReturn = "MATCH";
713  break;
714  case ID_NOMATCH:
715  cpReturn = "NOMATCH";
716  break;
717  case ID_EMPTY:
718  cpReturn = "EMPTY";
719  break;
720  }
721  return cpReturn;
722 }
723 
728  aint uiState;
729  printf(" PARSER STATE:\n");
730  printf(" success: %s\n", cpUtilTrueFalse((luint)spState->uiSuccess));
731  uiState = spState->uiState;
732  if ((uiState == ID_MATCH) && (spState->uiPhraseLength == 0)) {
733  uiState = ID_EMPTY;
734  }
735  printf(" state: %s\n", cpUtilParserState(uiState));
736 // printf("\n");
737  printf(" phrase length: %"PRIuMAX"\n", (luint) spState->uiPhraseLength);
738  printf(" input length: %"PRIuMAX"\n", (luint) spState->uiStringLength);
739  printf("max tree depth: %"PRIuMAX"\n", (luint) spState->uiMaxTreeDepth);
740  printf(" hit count: %"PRIuMAX"\n", (luint) spState->uiHitCount);
741 }
742 
747 void vUtilPrintMsgs(void* vpMsgs){
748  if(!bMsgsValidate(vpMsgs)){
749  vExContext();
750  }
751  const char* cpMsg = cpMsgsFirst(vpMsgs);
752  while(cpMsg){
753  printf("%s\n", cpMsg);
754  cpMsg = cpMsgsNext(vpMsgs);
755  }
756 }
757 
758 void vPrintPPPTMap(uint8_t* ucpMap, aint uiBegin, aint uiLength, const char* cpMode){
759  void (*pfnDisplay)(uint8_t) = vDisplayBinary;
760  if(cpMode && (cpMode[0] == 'd' || cpMode[0] == 'D')){
761  pfnDisplay = vDisplayDecimal;
762  }
763  aint ui;
764  for(ui = 0; ui < uiLength; ui++){
765  pfnDisplay(ucpMap[ui + uiBegin]);
766  }
767  printf("\n");
768 }
769 
774 void vUtilIndent(FILE* spFile, aint uiIndent){
775  if(!spFile){
776  spFile = stdout;
777  }
778  if (uiIndent) {
779  while (uiIndent--) {
780  fprintf(spFile, " ");
781  }
782  }
783 }
784 
790 void vUtilCharsToAscii(FILE* spFile, const achar* acpChars, aint uiLength) {
791  if (uiLength) {
792  aint ui;
793  for (ui = 0; ui < uiLength; ui += 1) {
794  achar aChar = acpChars[ui];
795  if (aChar == 38) {
796  // escape '&'
797  fprintf(spFile, "&#38;");
798  }else if(aChar == 60){
799  // escape '<'
800  fprintf(spFile, "&#60;");
801  }else if (aChar >= 32 && aChar <= 126) {
802  fprintf(spFile, "%c", (char) aChar);
803  } else {
804  fprintf(spFile, "&%"PRIuMAX";", (luint) aChar);
805  }
806  }
807  }
808 }
809 
824 achar* acpUtilStrToAchar(void* vpMem, const char* cpStr, aint* uipLen){
825  if(!bMemValidate(vpMem)){
826  vExContext();
827  }
828  if(!cpStr){
829  XTHROW(spMemException(vpMem), "cpStr may not be NULL");
830  }
831  aint uiStrLen = (aint)strlen(cpStr);
832  achar* acpBuf = (achar*)vpMemAlloc(vpMem, ((aint)sizeof(achar) * uiStrLen));
833  aint ui = 0;
834  for(; ui < uiStrLen; ui++){
835  acpBuf[ui] = (achar)((uint8_t)cpStr[ui]);
836  }
837  if(uipLen){
838  *uipLen = uiStrLen;
839  }
840  return acpBuf;
841 }
842 
857 const char* cpUtilAcharToStr(void* vpMem, achar* acpAchar, aint uiLen){
858  if(!bMemValidate(vpMem)){
859  vExContext();
860  }
861  if(!acpAchar){
862  XTHROW(spMemException(vpMem), "acpAchar may not be NULL");
863  }
864  char* cpStr = (char*)vpMemAlloc(vpMem, ((aint)sizeof(char) * (uiLen + 1)));
865  aint ui = 0;
866  achar acChar;
867  for(; ui < uiLen; ui++){
868  acChar = acpAchar[ui];
869  if(acChar == 9 || acChar == 10 || acChar == 13 || (acChar >= 32 && acChar <= 126)){
870  cpStr[ui] = (char)acChar;
871  }else{
872  cpStr[ui] = s_cPeriod;
873  }
874  }
875  cpStr[ui] = (char)0;
876  return cpStr;
877 }
878 
891 apg_phrase* spUtilStrToPhrase(void* vpMem, const char* cpStr){
892  if(!bMemValidate(vpMem)){
893  vExContext();
894  }
895 
896  if(!cpStr){
897  XTHROW(spMemException(vpMem), "cpStr may not be NULL");
898  }
899  size_t uiStrLen = strlen(cpStr);
900  apg_phrase* spPhrase = (apg_phrase*)vpMemAlloc(vpMem, (aint)(sizeof(apg_phrase) + (sizeof(achar) * uiStrLen)));
901  achar* acpBuf = (achar*)&spPhrase[1];
902  size_t ui = 0;
903  for(; ui < uiStrLen; ui++){
904  acpBuf[ui] = (achar)((uint8_t)cpStr[ui]);
905  }
906  spPhrase->acpPhrase = acpBuf;
907  spPhrase->uiLength = (aint)uiStrLen;
908  return spPhrase;
909 }
910 
925 const char* cpUtilPhraseToStr(void* vpMem, apg_phrase* spPhrase){
926  if(!bMemValidate(vpMem)){
927  vExContext();
928  }
929 
930  if(!spPhrase){
931  XTHROW(spMemException(vpMem), "spPhrase may not be NULL");
932  }
933  char* cpStr = (char*)vpMemAlloc(vpMem, ((aint)sizeof(char) * (spPhrase->uiLength + 1)));
934  aint ui = 0;
935  achar acChar;
936  for(; ui < spPhrase->uiLength; ui++){
937  acChar = spPhrase->acpPhrase[ui];
938  if(acChar == 9 || acChar == 10 || acChar == 13 || (acChar >= 32 && acChar <= 126)){
939  cpStr[ui] = (char)acChar;
940  }else{
941  cpStr[ui] = s_cPeriod;
942  }
943  }
944  cpStr[ui] = (char)0;
945  return cpStr;
946 }
947 
963 uint32_t* uipUtilStrToUint32(void* vpMem, const char* cpStr, aint* uipLen){
964  if(!bMemValidate(vpMem)){
965  vExContext();
966  }
967  if(!cpStr){
968  XTHROW(spMemException(vpMem), "cpStr may not be NULL");
969  }
970  aint uiStrLen = (aint)strlen(cpStr);
971  uint32_t* uipBuf = (uint32_t*)vpMemAlloc(vpMem, ((aint)sizeof(uint32_t) * uiStrLen));
972  aint ui = 0;
973  for(; ui < uiStrLen; ui++){
974  uipBuf[ui] = (uint32_t)((uint8_t)cpStr[ui]);
975  }
976  if(uipLen){
977  *uipLen = uiStrLen;
978  }
979  return uipBuf;
980 }
981 
997 const char* cpUtilUint32ToStr(void* vpMem, const uint32_t* uipUint, aint uiLen){
998  if(!bMemValidate(vpMem)){
999  vExContext();
1000  }
1001  if(!uipUint){
1002  XTHROW(spMemException(vpMem), "acpAchar may not be NULL");
1003  }
1004  char* cpStr = (char*)vpMemAlloc(vpMem, ((aint)sizeof(char) * (uiLen + 1)));
1005  aint ui = 0;
1006  uint32_t uiChar;
1007  for(; ui < uiLen; ui++){
1008  uiChar = uipUint[ui];
1009  if(uiChar == 9 || uiChar == 10 || uiChar == 13 || (uiChar >= 32 && uiChar <= 126)){
1010  cpStr[ui] = (char)uiChar;
1011  }else{
1012  cpStr[ui] = s_cPeriod;
1013  }
1014  }
1015  cpStr[ui] = (char)0;
1016  return cpStr;
1017 }
1018 
1031 u32_phrase* spUtilStrToPhrase32(void* vpMem, const char* cpStr){
1032  if(!bMemValidate(vpMem)){
1033  vExContext();
1034  }
1035 
1036  if(!cpStr){
1037  XTHROW(spMemException(vpMem), "cpStr may not be NULL");
1038  }
1039  size_t uiStrLen = strlen(cpStr);
1040  u32_phrase* spPhrase = (u32_phrase*)vpMemAlloc(vpMem, (aint)(sizeof(u32_phrase) + (sizeof(uint32_t) * uiStrLen)));
1041  uint32_t* acpBuf = (uint32_t*)&spPhrase[1];
1042  size_t ui = 0;
1043  for(; ui < uiStrLen; ui++){
1044  acpBuf[ui] = (uint32_t)((uint8_t)cpStr[ui]);
1045  }
1046  spPhrase->uipPhrase = acpBuf;
1047  spPhrase->uiLength = (aint)uiStrLen;
1048  return spPhrase;
1049 }
1050 
1065 const char* cpUtilPhrase32ToStr(void* vpMem, u32_phrase* spPhrase){
1066  if(!bMemValidate(vpMem)){
1067  vExContext();
1068  }
1069 
1070  if(!spPhrase){
1071  XTHROW(spMemException(vpMem), "spPhrase may not be NULL");
1072  }
1073  char* cpStr = (char*)vpMemAlloc(vpMem, ((aint)sizeof(char) * (spPhrase->uiLength + 1)));
1074  uint32_t ui = 0;
1075  uint32_t uiChar;
1076  for(; ui < spPhrase->uiLength; ui++){
1077  uiChar = spPhrase->uipPhrase[ui];
1078  if(uiChar == 9 || uiChar == 10 || uiChar == 13 || (uiChar >= 32 && uiChar <= 126)){
1079  cpStr[ui] = (char)uiChar;
1080  }else{
1081  cpStr[ui] = s_cPeriod;
1082  }
1083  }
1084  cpStr[ui] = (char)0;
1085  return cpStr;
1086 }
1087 
1109 #ifdef APG_AST
1110 static char* s_cpStringNode = "_string_";
1111 static abool bAstValidXmlChar(luint luiChar);
1112 static void vAstDecimalString(FILE* spOut, abool bHex, const achar* acpString, aint uiLen);
1113 static void vAstUnicodeString(void* vpMem, FILE* spOut, const achar* acpString, aint uiLen);
1114 static void vAstMaxChar(const achar* acpString, aint uiLen, luint* uipMaxChar, aint* uipSizeof);
1126 abool bUtilAstToXml(void* vpAst, char* cpType, const char* cpFileName){
1127  abool bReturn = APG_SUCCESS;
1128  ast_info sInfo;
1129  void* vpMem = NULL;
1130  static FILE* spOut = NULL;
1131  char caBuf[s_uiBufSize];
1132  char* cpRoot = "_root_";
1133  exception e;
1134  XCTOR(e);
1135  if(e.try){
1136  vpMem = vpMemCtor(&e);
1137  if(cpFileName){
1138  spOut = fopen(cpFileName, "wb");
1139  if(!spOut){
1140  snprintf(caBuf, s_uiBufSize, "can't open file %s for writing", cpFileName);
1141  XTHROW(&e, caBuf);
1142  }
1143  }else{
1144  spOut = stdout;
1145  }
1146 
1147  // get the AST
1148  vAstInfo(vpAst, &sInfo);
1149 
1150  // the XML declaration
1151  fprintf(spOut, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1152 
1153  // the root node and descriptive comments
1154  aint uiIndent = 0;
1155  fprintf(spOut, "<%s>\n\n", cpRoot);
1156  fprintf(spOut, "<!-- The <%s> node contains the character codes of the full input string. Its attributes are:\n", s_cpStringNode);
1157  fprintf(spOut, " length - the number of characters in the string\n");
1158  fprintf(spOut, " max-char - the maximum character size\n");
1159  fprintf(spOut, " sizeof - the number of bytes in the maximum character\n");
1160  fprintf(spOut, " -->\n");
1161 
1162  // the input string
1163  if(cpType == NULL){
1164  vAstDecimalString(spOut, APG_FALSE, sInfo.acpString, sInfo.uiStringLength);
1165  }else if(cpType[0] == 'u' || cpType[0] == 'U'){
1166  vAstUnicodeString(vpMem, spOut, sInfo.acpString, sInfo.uiStringLength);
1167  }else if(cpType[0] == 'h' || cpType[0] == 'H'){
1168  vAstDecimalString(spOut, APG_TRUE, sInfo.acpString, sInfo.uiStringLength);
1169  }else{
1170  vAstDecimalString(spOut, APG_FALSE, sInfo.acpString, sInfo.uiStringLength);
1171  }
1172  fprintf(spOut, "\n<!-- The <rule> node attributes define each rule/UDT the corresponding matched substring phrase.\n");
1173  fprintf(spOut, " name - the name of the rule or UDT\n");
1174  fprintf(spOut, " index - the grammar index of the rule or UDT\n");
1175  fprintf(spOut, " udt - (optional), if \"true\", name refers to a UDT, if \"false\" or absent, name refers to a rule\n");
1176  fprintf(spOut, " offset - the offset to the first character in the input string of the matched phrase\n");
1177  fprintf(spOut, " length - the number of characters in the matched phrase (may be \"0\" for a matched EMPTY phrase)\n");
1178  fprintf(spOut, " -->\n");
1179 
1180  ast_record* spRec = sInfo.spRecords;
1181  ast_record* spEnd = spRec + sInfo.uiRecordCount;
1182  for(; spRec < spEnd; spRec++){
1183  if(spRec->uiState == ID_AST_PRE){
1184  uiIndent += 2;
1185  vUtilIndent(spOut, uiIndent);
1186  fprintf(spOut, "<rule name=\"%s\" index=\"%"PRIuMAX"\"", spRec->cpName, (luint)spRec->uiIndex);
1187  if(spRec->bIsUdt){
1188  fprintf(spOut, " udt=\"true\"");
1189  }
1190  fprintf(spOut, " offset=\"%"PRIuMAX"\" length=\"%"PRIuMAX"\">\n",
1191  (luint)spRec->uiPhraseOffset, (luint)spRec->uiPhraseLength);
1192  }else{
1193  vUtilIndent(spOut, uiIndent);
1194  fprintf(spOut, "</rule>\n");
1195  uiIndent -= 2;
1196  }
1197  }
1198 
1199  // close the root node
1200  fprintf(spOut, "</%s>\n", cpRoot);
1201  }else{
1202  vUtilPrintException(&e);
1203  bReturn = APG_FAILURE;
1204  }
1205  if(spOut && (spOut != stdout)){
1206  fclose(spOut);
1207  }
1208  vMemDtor(vpMem);
1209  return bReturn;
1210 }
1211 
1228 void vUtilConvertLineEnds(exception* spEx, const char* cpString, const char* cpEnd, const char* cpFileName) {
1229  if(!bExValidate(spEx)){
1230  vExContext();
1231  }
1232  line* spLine;
1233  aint uiEndLen = 0;
1234  FILE* spFile = stdout;
1235  void* vpLines = NULL;
1236  if (!cpString) {
1237  XTHROW(spEx, "input string cannot be NULL");
1238  }
1239  aint uiLen = (aint)strlen(cpString);
1240  if (!uiLen) {
1241  XTHROW(spEx, "input string cannot be empty");
1242  }
1243  if (cpFileName) {
1244  spFile = fopen(cpFileName, "wb");
1245  if (!spFile) {
1246  char caBuf[s_uiBufSize];
1247  snprintf(caBuf, s_uiBufSize, "unable to open file name '%s' for writing", cpFileName);
1248  XTHROW(spEx, caBuf);
1249  }
1250  }
1251  if(cpEnd){
1252  uiEndLen = (aint) strlen(cpEnd);
1253  }
1254  vpLines = vpLinesCtor(spEx, cpString, uiLen);
1255  spLine = spLinesFirst(vpLines);
1256  while(spLine) {
1257  fwrite(&cpString[spLine->uiCharIndex], sizeof(char), spLine->uiTextLength, spFile);
1258  if(uiEndLen){
1259  fwrite(cpEnd, sizeof(char), uiEndLen, spFile);
1260  }
1261  spLine = spLinesNext(vpLines);
1262  }
1263  vLinesDtor(vpLines);
1264  if (spFile && (spFile != stdout)) {
1265  fclose(spFile);
1266  }
1267 }
1268 
1269 // //////////////////////////////////////////////////////////
1270 // STATIC HELPER FUNCTIONS
1271 // //////////////////////////////////////////////////////////
1272 static void vAstDecimalString(FILE* spOut, abool bHex, const achar* acpString, aint uiLen){
1273  aint uiCharsPerLine = 10;
1274  aint ui = 0;
1275  aint uiChar = 0;
1276  luint luiMaxChar;
1277  aint uiSizeof;
1278  aint uiEnd = uiLen - 1;
1279  char* cpFmt;
1280  if(bHex){
1281  cpFmt = "0x%"PRIXMAX"";
1282  fprintf(spOut, "<!-- The character codes are represented as comma- and white space-delimited hexadecimal integers. -->\n");
1283  }else{
1284  cpFmt = "%"PRIuMAX"";
1285  fprintf(spOut, "<!-- The character codes are represented as comma- and white space-delimited decimal integers. -->\n");
1286 
1287  }
1288  vAstMaxChar(acpString, uiLen, &luiMaxChar, &uiSizeof);
1289  fprintf(spOut, "<%s length=\"%"PRIuMAX"\" max-char=\"%"PRIuMAX"\" sizeof=\"%"PRIuMAX"\">",
1290  s_cpStringNode, (luint)uiLen, luiMaxChar, (luint)uiSizeof);
1291  for(; ui < uiLen; ui++){
1292  fprintf(spOut, cpFmt, (luint)acpString[ui]);
1293  if(ui < uiEnd){
1294  fprintf(spOut, ",");
1295  }
1296  uiChar++;
1297  if(uiChar == uiCharsPerLine){
1298  uiChar = 0;
1299  fprintf(spOut, "\n");
1300  }
1301  }
1302  if(uiChar != 0){
1303  fprintf(spOut, "\n");
1304  }
1305  fprintf(spOut, "</%s>\n", s_cpStringNode);
1306 }
1307 static void vAstUnicodeString(void* vpMem, FILE* spOut, const achar* acpString, aint uiLen){
1308  char caBuf[s_uiBufSize];
1309  fprintf(spOut, "<!-- The character codes are represented as a UTF-8-encoded XML Unicode string.\n");
1310  fprintf(spOut, " Note that XML Unicode does not allow the following characters:\n");
1311  fprintf(spOut, " - control except TAB(0x09), LF(0x0A), CR(0x0D) and DEL(0x7F)\n");
1312  fprintf(spOut, " - 0xFFFE and 0xFFFF\n");
1313  fprintf(spOut, " - surrogate-pair range 0xD800 - 0xDFFF\n");
1314  fprintf(spOut, " - beyond Unicode range > 0x10FFFF\n");
1315  fprintf(spOut, " -->\n");
1316  luint luiMaxChar;
1317  aint uiSizeof;
1318  vAstMaxChar(acpString, uiLen, &luiMaxChar, &uiSizeof);
1319  fprintf(spOut, "<%s length=\"%"PRIuMAX"\" max-char=\"%"PRIuMAX"\" sizeof=\"%"PRIuMAX"\">",
1320  s_cpStringNode, (luint)uiLen, luiMaxChar, (luint)uiSizeof);
1321  uint32_t* uipIn32 = (uint32_t*)vpMemAlloc(vpMem, (uiLen * sizeof(uint32_t)));
1322  aint ui = 0;
1323  for(; ui < uiLen; ui++){
1324  if(!bAstValidXmlChar((luint)acpString[ui])){
1325  snprintf(caBuf, s_uiBufSize, "input string has invalid XML character: offset = %"PRIuMAX": character = %"PRIuMAX"",
1326  (luint)ui, (luint)acpString[ui]);
1327  vMemFree(vpMem, uipIn32);
1328  XTHROW(spMemException(vpMem), caBuf);
1329  }
1330  uipIn32[ui] = (uint32_t)acpString[ui];
1331  }
1332  conv_dst sDst = {};
1333  sDst.uiDataType = UTF_8;
1334  sDst.bBOM = APG_FALSE;
1335  void* vpConv = vpConvCtor(spMemException(vpMem));
1336  vConvUseCodePoints(vpConv, uipIn32, uiLen);
1337  vConvEncode(vpConv, &sDst);
1338  fwrite(sDst.ucpData, sizeof(uint8_t), sDst.uiDataLen, spOut);
1339  fprintf(spOut, "</%s>\n", s_cpStringNode);
1340  vConvDtor(vpConv);
1341  vMemFree(vpMem, uipIn32);
1342 }
1343 // /////////////////////////////////////////////////////////////
1344 // STATIC HELPERS
1345 // /////////////////////////////////////////////////////////////
1346 
1347 static abool bAstValidXmlChar(luint luiChar){
1348  abool bReturn = APG_FALSE;
1349  while(APG_TRUE){
1350  if(luiChar >= 0 && luiChar < 9){
1351  break;
1352  }
1353  if(luiChar >= 11 && luiChar < 13){
1354  break;
1355  }
1356  if(luiChar >= 14 && luiChar < 32){
1357  break;
1358  }
1359  if(luiChar >= 0xD800 && luiChar < 0xE000){
1360  break;
1361  }
1362  if(luiChar > 0x10FFFF){
1363  break;
1364  }
1365  bReturn = APG_TRUE;
1366  break;
1367  }
1368  return bReturn;
1369 }
1370 static void vAstMaxChar(const achar* acpString, aint uiLen, luint* uipMaxChar, aint* uipSizeof){
1371  aint ui = 0;
1372  luint luiChar = 0;
1373  for(; ui < uiLen; ui++){
1374  if((luint)acpString[ui] > luiChar){
1375  luiChar = (luint)acpString[ui];
1376  }
1377  }
1378  *uipMaxChar = luiChar;
1379  if(luiChar <= 0xFF){
1380  *uipSizeof = 1;
1381  return;
1382  }
1383  if(luiChar <= 0xFFFF){
1384  *uipSizeof = 2;
1385  return;
1386  }
1387  if(luiChar <= 0xFFFFFFFF){
1388  *uipSizeof = 4;
1389  return;
1390  }
1391  if(luiChar <= 0xFFFFFFFFFFFFFFFF){
1392  *uipSizeof = 4;
1393  return;
1394  }
1395 
1396 }
1397 #endif
1398 static void vDisplayBinary(uint8_t ucChar){
1399  uint8_t ucL, ucR;
1400  ucR = ucChar & 0x0F;
1401  ucL = (ucChar & 0xF0) >> 4;
1402  printf("%s %s ", s_cpBinaryVal[ucL], s_cpBinaryVal[ucR]);
1403 }
1404 static void vDisplayDecimal(uint8_t ucChar){
1405  uint8_t ucL, ucR;
1406  ucR = ucChar & 0x0F;
1407  ucL = (ucChar & 0xF0) >> 4;
1408  printf("%s %s ", s_cpDecimalVal[ucL], s_cpDecimalVal[ucR]);
1409 }
line_u::uiLineIndex
aint uiLineIndex
zero-based line number
Definition: linesu.h:41
vec_stats::uiReserved
aint uiReserved
The current number of elements reserved.
Definition: vector.h:50
line::uiLineLength
aint uiLineLength
The number of characters in the line, including the line end characters.
Definition: lines.h:43
UTF_16
#define UTF_16
Data type macro for UTF-16 encoding/decoding.
Definition: conv.h:79
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
APG_INFINITE
#define APG_INFINITE
Definition: apg.h:320
cpUtilPhraseToStr
const char * cpUtilPhraseToStr(void *vpMem, apg_phrase *spPhrase)
Convert an apg_phrase to a null-terminated ASCII string.
Definition: utilities.c:925
mem_stats::uiMaxCells
aint uiMaxCells
Definition: memory.h:50
vUtilFileRead
void vUtilFileRead(void *vpMem, const char *cpFileName, uint8_t *ucpData, aint *uipLen)
Read a file into the caller's data area.
Definition: utilities.c:252
APG_FAILURE
#define APG_FAILURE
Definition: apg.h:308
bUtilCompareFiles
abool bUtilCompareFiles(const char *cpFileL, const char *cpFileR)
Compare two files, byte for byte.
Definition: utilities.c:306
exception::caFunc
char caFunc[64]
The source code function name where the error occurred. "__func__".
Definition: exception.h:54
vpLinesCtor
void * vpLinesCtor(exception *spEx, const char *cpInput, aint uiLength)
The lines object constructor.
Definition: lines.c:85
parser_state::uiSuccess
aint uiSuccess
True (>0) if the input string was matched in its entirety, false (0) otherwise.
Definition: parser.h:184
vMemDtor
void vMemDtor(void *vpCtx)
Destroys a Memory component. Frees all memory allocated.
Definition: memory.c:141
exception::try
abool try
True for the try block, false for the catch block.
Definition: exception.h:49
ID_RNM
#define ID_RNM
rule name
Definition: parser.h:46
vec_stats::uiGrownCount
aint uiGrownCount
The number times the vector was automatically extended.
Definition: vector.h:58
APG_MAX_ACHAR
#define APG_MAX_ACHAR
Definition: apg.h:331
ast_info::acpString
const achar * acpString
The parsed input string.
Definition: ast.h:58
ast_info::uiStringLength
aint uiStringLength
The number of characters in the input string.
Definition: ast.h:62
line_u
Carries detailed information about the characters and line endings. One for each line in the input gr...
Definition: linesu.h:40
mem_stats::uiCells
aint uiCells
Definition: memory.h:49
u32_phrase::uiLength
uint32_t uiLength
The number of integers in the array.
Definition: lib.h:75
ast_record::uiPhraseLength
aint uiPhraseLength
The number of characters in the matched phrase.
Definition: ast.h:49
vec_stats::uiGrownBytes
aint uiGrownBytes
The number of bytes automatically added to the vector.
Definition: vector.h:60
cpUtilPhrase32ToStr
const char * cpUtilPhrase32ToStr(void *vpMem, u32_phrase *spPhrase)
Convert an u32_phrase to a null-terminated ASCII string.
Definition: utilities.c:1065
exception::uiLine
unsigned int uiLine
The source code line number where the error occurred. "__LINE__".
Definition: exception.h:51
ID_ALT
#define ID_ALT
alternation
Definition: parser.h:43
cpUtilOpName
const char * cpUtilOpName(aint uiId)
Convert an opcode identifier to a human-readable opcode name.
Definition: utilities.c:659
mem_stats::uiReAllocations
aint uiReAllocations
Definition: memory.h:47
vUtilPrintMemStats
void vUtilPrintMemStats(const mem_stats *spStats)
Display the memory object's statistics.
Definition: utilities.c:427
vec_stats::uiOriginalBytes
aint uiOriginalBytes
The initial number of bytes allocated to the vector.
Definition: vector.h:49
ID_BKR
#define ID_BKR
back reference to a previously matched rule or UDT name
Definition: parser.h:58
ID_UDT
#define ID_UDT
user-defined terminal
Definition: parser.h:55
vUtilPrintMsgs
void vUtilPrintMsgs(void *vpMsgs)
Display the list of messages in a message object to stdout.
Definition: utilities.c:747
line_u::uiTextLength
aint uiTextLength
number of Unicode text characters in the line, excluding line end characters
Definition: linesu.h:44
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
ID_AST_PRE
#define ID_AST_PRE
indicates pre-node-traversal AST callback state (down the tree)
Definition: parser.h:91
cpUtilPrintUChar
char * cpUtilPrintUChar(uint32_t uiChar, char *cpBuf)
Generates a string representation for a single Unicode character.
Definition: utilities.c:539
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
parser_state::uiStringLength
aint uiStringLength
Length of the input string.
Definition: parser.h:189
cpUtilPrintChar
char * cpUtilPrintChar(char cChar, char *cpBuf)
Generates a string representation for a single character.
Definition: utilities.c:504
vpConvCtor
void * vpConvCtor(exception *spEx)
The data conversion object constructor.
Definition: conv.c:134
vec_stats::uiUsed
aint uiUsed
The current number elements used.
Definition: vector.h:51
mem_stats::uiMaxHeapBytes
aint uiMaxHeapBytes
Definition: memory.h:52
ast_record::cpName
const char * cpName
Name of the rule or UDT of this record.
Definition: ast.h:43
vPrintPPPTMap
void vPrintPPPTMap(uint8_t *ucpMap, aint uiBegin, aint uiLength, const char *cpMode)
Definition: utilities.c:758
cpUtilTrueFalse
const char * cpUtilTrueFalse(luint luiTrue)
Return a human-readable string version of the given value in its true/false sense.
Definition: utilities.c:646
ID_EMPTY
#define ID_EMPTY
indicates a matched empty phrase parser state on return from parse tree below this node
Definition: parser.h:75
mem_stats
Available to the user for display of memory statistics.
Definition: memory.h:45
ID_NOT
#define ID_NOT
negative look ahead
Definition: parser.h:57
ID_AND
#define ID_AND
positive look ahead
Definition: parser.h:56
vAstInfo
void vAstInfo(void *vpCtx, ast_info *spInfo)
Retrieve basic information about the AST object.
Definition: ast.c:137
ast_record
Format of an AST record.
Definition: ast.h:42
bUtilCompareFileLines
abool bUtilCompareFileLines(void *vpMem, const char *cpFileL, const char *cpFileR)
Compare two text files, line by line, without regard for the line ending characters.
Definition: utilities.c:350
vec_stats
Vector usage statistics.
Definition: vector.h:46
u32_phrase::uipPhrase
const uint32_t * uipPhrase
Pointer to an array of 32-bit unsigned integers.
Definition: lib.h:74
UTF_32
#define UTF_32
Data type macro for UTF-32 encoding/decoding.
Definition: conv.h:85
exception::caFile
char caFile[256]
The source code file name where the error occurred. "__FILE__".
Definition: exception.h:53
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
cpType
const char * cpType(aint uiId)
Convert an attribute type ID to an ASCII string.
Definition: attributes.c:484
vec_stats::uiPushed
aint uiPushed
The total number of elements pushed onto (added to) the vector.
Definition: vector.h:56
bUtilAstToXml
abool bUtilAstToXml(void *vpAst, char *cpType, const char *cpFileName)
Convert the AST records to XML format.
Definition: utilities.c:1126
UTF_16BE
#define UTF_16BE
Data type macro for UTF-16BE encoding/decoding.
Definition: conv.h:81
APG_LICENSE
#define APG_LICENSE
Definition: apg.h:67
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
vec_stats::uiOriginalElements
aint uiOriginalElements
The initial number of elements allocated to the vector.
Definition: vector.h:48
vec_stats::uiUsedBytes
aint uiUsedBytes
The current number of bytes in use.
Definition: vector.h:54
spMemException
exception * spMemException(void *vpCtx)
Get a pointer to this memory objects's exception handler.
Definition: memory.c:174
conv_dst::bBOM
abool bBOM
[in] If true(BOM) prepend a Byte Order Mark, if false(NOBOM) no Byte Order Mark prepended.
Definition: conv.h:122
ID_CAT
#define ID_CAT
concatenation
Definition: parser.h:44
cpUtilUint32ToStr
const char * cpUtilUint32ToStr(void *vpMem, const uint32_t *uipUint, aint uiLen)
Convert an array of 32-bit unsigned integers to a null-terminated ASCII string.
Definition: utilities.c:997
conv_dst::uiDataType
aint uiDataType
[in] One of the encoding type identifiers, UTF_8, etc.
Definition: conv.h:121
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
APG_COPYRIGHT
#define APG_COPYRIGHT
Definition: apg.h:66
conv_dst
Defines the output data type, location, length and whether or not to preface with a Byte Order Mark (...
Definition: conv.h:120
ID_TRG
#define ID_TRG
terminal range
Definition: parser.h:47
ast_record::bIsUdt
abool bIsUdt
True if this record is for a UDT.
Definition: ast.h:51
ID_REP
#define ID_REP
repetition
Definition: parser.h:45
vec_stats::uiReservedBytes
aint uiReservedBytes
The current number of bytes reserved.
Definition: vector.h:53
UTF_32LE
#define UTF_32LE
Data type macro for UTF-32LE encoding/decoding.
Definition: conv.h:89
mem_stats::uiHeapBytes
aint uiHeapBytes
Definition: memory.h:51
parser_state
The parser's final state.
Definition: parser.h:183
ast_info
All the information a user needs to write a custom AST translator.
Definition: ast.h:57
APG_SUCCESS
#define APG_SUCCESS
Definition: apg.h:307
cpUtilUtfTypeName
const char * cpUtilUtfTypeName(aint uiType)
Convert a conversion type identifier to a readable, printable ASCII string. Conversion type identifie...
Definition: utilities.c:607
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
apg_phrase
Defines a pointer to an achar array plus its length. That is, a phrase as is often used by APG.
Definition: lib.h:60
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
ID_ACTIVE
#define ID_ACTIVE
indicates active parser state, parser has just entered the node and is moving down the parse tree
Definition: parser.h:72
ast_info::uiRecordCount
aint uiRecordCount
The number of records (two for each node of the AST, one down traversal, one up.)
Definition: ast.h:63
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
APG_VERSION
#define APG_VERSION
Definition: apg.h:65
ast_record::uiState
aint uiState
ID_AST_PRE if the current record opens the rule, ID_AST_POST if the current record closes the rule.
Definition: ast.h:50
vUtilPrintLine
void vUtilPrintLine(line *spLine)
Display one line from a line object.
Definition: utilities.c:464
cpMsgsFirst
const char * cpMsgsFirst(void *vpCtx)
Get a pointer to the first logged message, if any.
Definition: msglog.c:164
vUtilIndent
void vUtilIndent(FILE *spFile, aint uiIndent)
Indent by adding the given number of spaces to the output file.
Definition: utilities.c:774
cpMsgsNext
const char * cpMsgsNext(void *vpCtx)
Get a pointer to the next logged message, if any.
Definition: msglog.c:185
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
line::uiLineIndex
aint uiLineIndex
The zero-based line index.
Definition: lines.h:41
bExValidate
abool bExValidate(exception *spException)
Test an exception structure for validity.
Definition: exception.c:70
UTF_16LE
#define UTF_16LE
Data type macro for UTF-16LE encoding/decoding.
Definition: conv.h:83
utilities.h
Miscellaneous utility functions.
line::uiTextLength
aint uiTextLength
The number of characters in the line, excluding the line end characters.
Definition: lines.h:44
ID_BKA
#define ID_BKA
positive look behind
Definition: parser.h:59
line
Defines the characteristics of a single line.
Definition: lines.h:40
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
parser_state::uiState
aint uiState
One of ID_EMPTY, ID_MATCH or ID_NOMATCH. Note that it is possible for the parser to match a phrase wi...
Definition: parser.h:185
vUtilSizes
void vUtilSizes(void)
Display the APG type sizes, the compiler's C-language type sizes and a few max values.
Definition: utilities.c:153
cpUtilAcharToStr
const char * cpUtilAcharToStr(void *vpMem, achar *acpAchar, aint uiLen)
Convert an array of achar characters to a null-terminated ASCII string.
Definition: utilities.c:857
spLinesNext
line * spLinesNext(void *vpCtx)
Returns the next line of text from the iterator.
Definition: lines.c:185
vec_stats::uiPopped
aint uiPopped
The total number of elements popped from (removed from) the vector.
Definition: vector.h:57
vConvEncode
void vConvEncode(void *vpCtx, conv_dst *spDst)
Encode the 32-bit Unicode code points to a byte stream.
Definition: conv.c:302
BASE64_MASK
#define BASE64_MASK
The base64 mask. And (&) with the type to extract the base64 bit, if any.
Definition: conv.h:51
vUtilCharsToAscii
void vUtilCharsToAscii(FILE *spFile, const achar *acpChars, aint uiLength)
Convert a string of alphabet characters to printable ASCII.
Definition: utilities.c:790
vUtilPrintLineu
void vUtilPrintLineu(line_u *spLine)
Display one line from a line_u object.
Definition: utilities.c:483
ast_info::spRecords
ast_record * spRecords
The list of records in the order of a depth-first traversal of the AST.
Definition: ast.h:59
ID_TLS
#define ID_TLS
terminal literal string
Definition: parser.h:49
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
UTF_32BE
#define UTF_32BE
Data type macro for UTF-32BE encoding/decoding.
Definition: conv.h:87
vUtilPrintVecStats
void vUtilPrintVecStats(const vec_stats *spStats)
Display the vector object's statistics.
Definition: utilities.c:440
vec_stats::uiGrownElements
aint uiGrownElements
The number new elements automatically added to the vector.
Definition: vector.h:59
spLinesFirst
line * spLinesFirst(void *vpCtx)
Initialize an iterator over the lines.
Definition: lines.c:170
TYPE_MASK
#define TYPE_MASK
The type mask. And (&) with the type to extract the type, without the base64 bit.
Definition: conv.h:58
mem_stats::uiFrees
aint uiFrees
Definition: memory.h:48
bMemValidate
abool bMemValidate(void *vpCtx)
Validates a memory context.
Definition: memory.c:160
apg_phrase::uiLength
aint uiLength
The number of characters in the array.
Definition: lib.h:62
parser_state::uiMaxTreeDepth
aint uiMaxTreeDepth
The maximum tree depth reached during the parse.
Definition: parser.h:190
vLinesDtor
void vLinesDtor(void *vpCtx)
The lines object destructor.
Definition: lines.c:123
APG_MAX_AINT
#define APG_MAX_AINT
Since the maximum unsigned integer value is used to indicate Infinite and Undefined values,...
Definition: apg.h:329
ID_BKN
#define ID_BKN
negative look behind
Definition: parser.h:60
UTF_8
#define UTF_8
Data type macro for UTF-8 encoding/decoding.
Definition: conv.h:77
parser_state::uiHitCount
aint uiHitCount
The number of nodes visited during the traversal of the parse tree.
Definition: parser.h:191
conv_dst::uiDataLen
aint uiDataLen
[out] Number of bytes in the byte stream.
Definition: conv.h:124
vUtilFileWrite
void vUtilFileWrite(void *vpMem, const char *cpFileName, uint8_t *ucpData, aint uiLen)
Write from the caller's data area to the given file name.
Definition: utilities.c:210
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
parser_state::uiPhraseLength
aint uiPhraseLength
Length of the matched phrase.
Definition: parser.h:188
uipUtilStrToUint32
uint32_t * uipUtilStrToUint32(void *vpMem, const char *cpStr, aint *uipLen)
Convert a null-terminated ASCII string to an array of 32-bit unsigned integers.
Definition: utilities.c:963
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
exception::caMsg
char caMsg[256]
A the caller's error message.
Definition: exception.h:52
mem_stats::uiAllocations
aint uiAllocations
Definition: memory.h:46
line_u::uiaLineEnd
uint32_t uiaLineEnd[3]
the actual string of line ending character(s), if any
Definition: linesu.h:45
line::caLineEnd
char caLineEnd[3]
The actual, null-terminated string of line ending character(s), if any.
Definition: lines.h:45
acpUtilStrToAchar
achar * acpUtilStrToAchar(void *vpMem, const char *cpStr, aint *uipLen)
Convert a null-terminated ASCII string to an array of achar characters.
Definition: utilities.c:824
ast_record::uiPhraseOffset
aint uiPhraseOffset
The offset into the input string to the first character of the matched phrase.
Definition: ast.h:48
ID_ABG
#define ID_ABG
anchor - beginning of string
Definition: parser.h:61
ast_record::uiIndex
aint uiIndex
Index of the rule or UDT of this record.
Definition: ast.h:44
u32_phrase
Defines a pointer to an array of 32-bit unsigned integers plus its length. Typically needed by Unicod...
Definition: lib.h:73
vConvDtor
void vConvDtor(void *vpCtx)
Conversion object destructor.
Definition: conv.c:161
vUtilConvertLineEnds
void vUtilConvertLineEnds(exception *spEx, const char *cpString, const char *cpEnd, const char *cpFileName)
Convert all line ending characters.
Definition: utilities.c:1228
spUtilStrToPhrase
apg_phrase * spUtilStrToPhrase(void *vpMem, const char *cpStr)
Convert a null-terminated ASCII string to an apg_phrase.
Definition: utilities.c:891
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
ID_TBS
#define ID_TBS
terminal binary string
Definition: parser.h:48
conv_dst::ucpData
uint8_t * ucpData
[out] Pointer to the output byte stream. Valid until another function call on the context handle.
Definition: conv.h:123
vConvUseCodePoints
void vConvUseCodePoints(void *vpCtx, uint32_t *uipSrc, aint uiSrcLen)
Insert a stream of 32-bit Unicode code points as the intermediate data.
Definition: conv.c:395
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
vec_stats::uiMaxUsedBytes
aint uiMaxUsedBytes
The maximum number of bytes used over the lifetime of the vector.
Definition: vector.h:55
line_u::uiLineLength
aint uiLineLength
number of Unicode characters in the line, including line end characters
Definition: linesu.h:43
BINARY
#define BINARY
Alias for ISO_8895_1.
Definition: conv.h:64
spUtilStrToPhrase32
u32_phrase * spUtilStrToPhrase32(void *vpMem, const char *cpStr)
Convert a null-terminated ASCII string to a 32-bit phrase.
Definition: utilities.c:1031
vUtilPrintParserState
void vUtilPrintParserState(parser_state *spState)
Display the parser state in human-readable format to stdout.
Definition: utilities.c:727
apg_phrase::acpPhrase
const achar * acpPhrase
Pointer to an array of type achar APG alphabet characters.
Definition: lib.h:61
line::uiCharIndex
aint uiCharIndex
The zero-based index of the first character of the line.
Definition: lines.h:42
bMsgsValidate
abool bMsgsValidate(void *vpCtx)
Validate a msglog context pointer.
Definition: msglog.c:110
vec_stats::uiElementSize
aint uiElementSize
The number of bytes in one element.
Definition: vector.h:47
ID_AEN
#define ID_AEN
anchor - end of string
Definition: parser.h:62
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
line_u::uiCharIndex
aint uiCharIndex
zero-based index of the first Unicode character of the line
Definition: linesu.h:42
vec_stats::uiMaxUsed
aint uiMaxUsed
The maximum number of elements used during the vector's lifetime.
Definition: vector.h:52
uiLinesCount
aint uiLinesCount(void *vpCtx)
Returns the number of lines of text.
Definition: lines.c:202
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.