Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
main.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 * *************************************************************************************/
203 #include <limits.h>
204 #include <time.h>
205 #include <dirent.h>
206 #include "../../utilities/utilities.h"
207 #include "../../json/json.h"
208 #include "./sip-0.h"
209 #include "./sip-1.h"
210 #include "./udtlib.h"
211 
212 #include "source.h"
213 
214 static char* cpMakeFileName(char* cpBuffer, const char* cpBase, const char* cpDivider, const char* cpName){
215  strcpy(cpBuffer, cpBase);
216  strcat(cpBuffer, cpDivider);
217  strcat(cpBuffer, cpName);
218  return cpBuffer;
219 }
220 
221  static char s_caBuf[2*PATH_MAX];
222  static char s_caBufTests[4*PATH_MAX];
223 
224 static char* s_cpDescription =
225  "Illustrate parsing and time tests for SIP messages.";
226 
227 static char* s_cppCases[] = {
228  "Display application information.",
229  "Build the JSON composite file of all SIP torture test messages.",
230  "Parse and trace all valid SIP messages, with and without UDTs..",
231  "Parse and trace all invalid SIP messages, with and without UDTs..",
232  "Parse and trace all semantically invalid SIP messages, with and without UDTs..",
233  "Parse all SIP messages and measure the times, with and without UDTs.",
234  "Parse all SIP messages and display the node-hit statistics, with and without UDTs.",
235 };
236 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
237 
238 static int iHelp(void){
239  long int i = 0;
241  printf("description: %s\n", s_cpDescription);
242  printf(" usage: ex-api arg\n");
243  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
244  printf(" execute case number n\n");
245  printf(" arg = anthing else\n");
246  printf(" print this help screen\n");
247  printf("\n");
248  printf(" NOTE: Case 2 must be run before any of the other cases.\n");
249  printf(" It constructs a JSON file of tests that is used by all other cases.\n");
250  printf("\n");
251  for(; i < s_iCaseCount; i++){
252  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
253  }
254  return EXIT_SUCCESS;
255 }
256 
257 static int iApp() {
258  // print the current working directory
260  printf("\n");
261 
262  // display the current APG sizes and macros
263  vUtilApgInfo();
264  return EXIT_SUCCESS;
265 }
266 
267 typedef struct {
268  char* cpValidKey;
271  char* cpValidIn;
272  char* cpInvalidIn;
275 // char* cpStatsOut;
276 } test_context;
277 static test_context s_sTestsCtx = {
278  "valid",
279  "invalid",
280  "semantics",
281  "tests/valid/",
282  "tests/invalid/",
283  "tests/semantics/",
284  "sip-tests.json",
285 };
286 typedef struct {
287  const char* cpOutObject;
288  void* vpMem;
290  void* vpVecNames;
292  void* vpVecOut;
293  void* vpVecIn;
295  void* vpVecChars;
296 } json_context;
297 
298 static json_context sSetup(exception* spE, void* vpMem){
299  json_context sCtx = {};
300  static char caBuf[PATH_MAX];
301  sCtx.cpOutObject = cpMakeFileName(caBuf, SOURCE_DIR, "/../output/", "sip-tests.json");
302  sCtx.vpMem = vpMem;
303  sCtx.spException = spE;
304  sCtx.vpVecNames = vpVecCtor(sCtx.vpMem, sizeof(char), 10000);
305  sCtx.vpVecNameIndexes = vpVecCtor(sCtx.vpMem, sizeof(aint), 100);
306  sCtx.vpVecOut = vpVecCtor(sCtx.vpMem, sizeof(uint8_t), 10000);
307  sCtx.vpVecIn = vpVecCtor(sCtx.vpMem, sizeof(uint8_t), 10000);
308  sCtx.vpVecUnicode = vpVecCtor(sCtx.vpMem, sizeof(uint32_t), 10000);
309  sCtx.vpVecChars = vpVecCtor(sCtx.vpMem, sizeof(achar), 10000);
310  return sCtx;
311 }
312 
313 static void vMakeList(json_context* spCtx, const char* cpDirName){
314  vVecClear(spCtx->vpVecNames);
315  vVecClear(spCtx->vpVecNameIndexes);
316  struct dirent* spEnt;
317  char* cpDat = ".dat";
318  char* cpExt;
319  aint uiChars, uiIndex, uiCount;
320  void* vpName;
321  char* cZero = 0;
322  DIR* spDir = opendir(cpDirName);
323  if(!spDir){
324  char caBuf[1024];
325  snprintf(caBuf, sizeof(caBuf), "can't open directory: %s", cpDirName);
326  XTHROW(spCtx->spException, caBuf);
327  }
328  printf("directory name: %s\n", cpDirName);
329  uiCount = 0;
330  while((spEnt = readdir(spDir)) != NULL){
331  if(spEnt->d_type == DT_REG){
332  cpExt = strstr(spEnt->d_name, cpDat);
333  if(cpExt){
334  uiChars = (aint)(cpExt - &spEnt->d_name[0]);
335  if(uiChars){
336  uiIndex = uiVecLen(spCtx->vpVecNames);
337  vpName = vpVecPushn(spCtx->vpVecNames, &spEnt->d_name[0], uiChars);
338  vpVecPush(spCtx->vpVecNames, &cZero);
339  vpVecPush(spCtx->vpVecNameIndexes, &uiIndex);
340  uiCount++;
341  printf("%d: file name found: %s\n", (int)uiCount, (char*)vpName);
342  }
343  }
344  }
345  }
346 }
347 
348 /*
349  * Make a JSON object for the given directory of data.
350  * Object is of the form:
351  * {
352  * "test name" : {"description" : "named text", "data" : "named data"},
353  * ...
354  * }
355  */
356 static aint uiMakeObject(json_context* spCtx, void* vpB, const char* cpDirName){
357  aint ui, uii, uiCount, uiObjRoot, uiObjTest;
358  aint uiKeyName, uiKeyDesc, uiKeyData;
359  char caFileName[PATH_MAX];
360  char* cpFile = caFileName; // keeps the compiler warnings happy
361  char* cpDat = ".dat";
362  char* cpTxt = ".txt";
363  uint8_t* ucpIn8;
364  uint32_t* uipIn32;
365  uint32_t uiInLen;
366  char* cpName;
367  char* cpNames;
368  aint* uipIndexes;
369  void* vpVec = spCtx->vpVecIn;
370  aint uiLen;
371  uint8_t* ucpData;
372  vVecClear(spCtx->vpVecOut);
373  vMakeList(spCtx, cpDirName);
374  cpNames = (char*)vpVecFirst(spCtx->vpVecNames);
375  uipIndexes = (aint*)vpVecFirst(spCtx->vpVecNameIndexes);
376  uiCount = uiVecLen(spCtx->vpVecNameIndexes);
377 
378  // create the object for this section of tests
379  uiObjRoot = uiJsonBuildMakeObject(vpB);
380 
381  // create the keys used for each test object
382  uiKeyDesc = uiJsonBuildMakeStringA(vpB, "description");
383  uiKeyData = uiJsonBuildMakeStringA(vpB, "data");
384  for(ui = 0; ui < uiCount; ui++){
385  // create the object for this test
386  uiObjTest = uiJsonBuildMakeObject(vpB);
387 
388  // create the key (test name) for this test object
389  cpName = &cpNames[uipIndexes[ui]];
390  uiKeyName = uiJsonBuildMakeStringA(vpB, cpName);
391 
392  // add the test description to the test object
393  strcpy(cpFile, cpDirName);
394  strcat(cpFile, cpName);
395  strcat(cpFile, cpTxt);
396  vVecClear(vpVec);
397  uiLen = 0;
398  vUtilFileRead(spCtx->vpMem, cpFile, NULL, &uiLen);
399  ucpData = vpVecPushn(vpVec, NULL, uiLen);
400  vUtilFileRead(spCtx->vpMem, cpFile, ucpData, &uiLen);
401  vVecClear(spCtx->vpVecUnicode);
402  uiInLen = (uint32_t)uiVecLen(vpVec);
403  ucpIn8 = (uint8_t*)vpVecFirst(vpVec);
404  vpVecPushn(spCtx->vpVecUnicode, NULL, uiInLen);
405  uipIn32 = (uint32_t*)vpVecFirst(spCtx->vpVecUnicode);
406  for(uii = 0; uii < uiInLen; uii++){
407  uipIn32[uii] = (uint32_t)ucpIn8[uii];
408  }
409  uiJsonBuildAddToObject(vpB, uiObjTest, uiKeyDesc, uiJsonBuildMakeStringU(vpB, uipIn32, uiInLen));
410 
411  // add the test data to the test object
412  strcpy(cpFile, cpDirName);
413  strcat(cpFile, cpName);
414  strcat(cpFile, cpDat);
415  vVecClear(vpVec);
416  vUtilFileRead(spCtx->vpMem, cpFile, NULL, &uiLen);
417  ucpData = vpVecPushn(vpVec, NULL, uiLen);
418  vUtilFileRead(spCtx->vpMem, cpFile, ucpData, &uiLen);
419  vVecClear(spCtx->vpVecUnicode);
420  uiInLen = (uint32_t)uiVecLen(vpVec);
421  ucpIn8 = (uint8_t*)vpVecFirst(vpVec);
422  vpVecPushn(spCtx->vpVecUnicode, NULL, uiInLen);
423  uipIn32 = (uint32_t*)vpVecFirst(spCtx->vpVecUnicode);
424  for(uii = 0; uii < uiInLen; uii++){
425  uipIn32[uii] = (uint32_t)ucpIn8[uii];
426  }
427  uiJsonBuildAddToObject(vpB, uiObjTest, uiKeyData, uiJsonBuildMakeStringU(vpB, uipIn32, uiInLen));
428 
429  // add the test object to the root object for this section of tests
430  uiJsonBuildAddToObject(vpB, uiObjRoot, uiKeyName, uiObjTest);
431  }
432  return uiObjRoot;
433 }
434 
435 static int iBuilder() {
436  int iReturn = EXIT_SUCCESS;
437  static void* vpMem = NULL;
438  static void* vpJson = NULL;
439  static void* vpB = NULL;
440  json_context sCtx;
441  exception e;
442  XCTOR(e);
443  if(e.try){
444  // try block
445  vpMem = vpMemCtor(&e);
446  vpJson = vpJsonCtor(&e);
447  vpB = vpJsonBuildCtor(vpJson);
448 
449  // display the information header
450  char* cpHeader =
451  "This function will read the text and data SIP torture test files and\n"
452  "wrap them all into a single JSON file for later use by other example cases.\n";
453  printf("\n%s", cpHeader);
454 
455  // convert the relative path names for the tests to absolute path names
456  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
457  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
458  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
459  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
460 
461  sCtx = sSetup(&e, vpMem);
462  aint uiRoot, uiKey;
463  void* vpIt;
464  json_value* spValue;
465  uint8_t* ucpBytes;
466  aint uiCount;
467  uiRoot = uiJsonBuildMakeObject(vpB);
468 
469  // add the valid tests
470  uiKey = uiJsonBuildMakeStringA(vpB, s_sTestsCtx.cpValidKey);
471  uiJsonBuildAddToObject(vpB, uiRoot, uiKey, uiMakeObject(&sCtx, vpB, s_sTestsCtx.cpValidIn));
472 
473  // add the invalid tests
474  uiKey = uiJsonBuildMakeStringA(vpB, s_sTestsCtx.cpInvalidKey);
475  uiJsonBuildAddToObject(vpB, uiRoot, uiKey, uiMakeObject(&sCtx, vpB, s_sTestsCtx.cpInvalidIn));
476 
477  // add the semantics tests
478  uiKey = uiJsonBuildMakeStringA(vpB, s_sTestsCtx.cpSemanticsKey);
479  uiJsonBuildAddToObject(vpB, uiRoot, uiKey, uiMakeObject(&sCtx, vpB, s_sTestsCtx.cpSemanticsIn));
480 
481  // make a single JSON object file which holds ALL of the tests
482  vpIt = vpJsonBuild(vpB, uiRoot);
483  spValue = spJsonIteratorFirst(vpIt);
484  ucpBytes = ucpJsonWrite(vpJson, spValue, &uiCount);
485 
486  // write the UTF-8 byte stream to a file
487  vUtilFileWrite(sCtx.vpMem, sCtx.cpOutObject, ucpBytes, uiCount);
488  printf("JSON file created: %s\n", sCtx.cpOutObject);
489 
490  }else{
491  // catch block - display the exception location and message
493  iReturn = EXIT_FAILURE;
494  }
495 
496  // clean up resources
497  vJsonDtor(vpJson);
498  vMemDtor(vpMem);
499  return iReturn;
500 }
501 
502 typedef struct{
509 } msg_offset;
510 
511 #define SECTION_VALID 0
512 #define SECTION_INVALID 1
513 #define SECTION_SEMANTICS 2
514 typedef struct{
515  void* vpVecMsgs;
516  void* vpVecNames;
517  void* vpVecDesc;
523 } section_def;
524 static char s_cZero = 0;
525 static void vGetMsgs(void* vpMem, section_def* spSection, abool bDisplay){
526  if(!bMemValidate(vpMem)){
527  vExContext();
528  }
529  exception* spEx = spMemException(vpMem);
530  spSection->vpVecMsgs = vpVecCtor(vpMem, sizeof(achar), 8192);
531  spSection->vpVecNames= vpVecCtor(vpMem, sizeof(char), 8192);
532  spSection->vpVecDesc = vpVecCtor(vpMem, sizeof(char), 8192);
533  spSection->vpVecOffsets = vpVecCtor(vpMem, sizeof(msg_offset), 128);
534  void* vpItRoot, *vpItSection, *vpItTests, *vpItContent;
535  json_value* spValue, *spTest;
536  u32_phrase* spPhrase;
537  msg_offset* spOffset;
538  aint ui;
539  char cChar;
540  achar acaOctet;
541  char* cpTest;
542  void* vpJson = vpJsonCtor(spEx);
543  vpItRoot = vpJsonReadFile(vpJson, spSection->cpJsonFileName);
544  spValue = spJsonIteratorFirst(vpItRoot);
545 
546  // get an iterator over the section name files
547  vpItSection = vpJsonFindKeyA(vpJson, spSection->cpSectionName, spValue);
548  if(!vpItSection){
549  vJsonDtor(vpJson);
550  XTHROW(spEx, "expected key not found");
551  }
552 
553  // iterator over the tests in the section name files
554  vpItTests = vpJsonChildren(vpJson, spJsonIteratorFirst(vpItSection));
555  spTest = spJsonIteratorFirst(vpItTests);
556  spSection->uiCount = 1;
557  while(spTest){
558  // the key for this test is the test name
559  spOffset = (msg_offset*)vpVecPush(spSection->vpVecOffsets, NULL);
560  spOffset->uiNameOffset = uiVecLen(spSection->vpVecNames);
561  spPhrase = spTest->spKey;
562  spOffset->uiNameLength = spPhrase->uiLength;
563  for(ui = 0; ui < spPhrase->uiLength; ui++){
564  if(spPhrase->uipPhrase[ui] > 126){
565  vJsonDtor(vpJson);
566  XTHROW(spEx, "test names must be ASCII characters only");
567  }
568  cChar = (char)spPhrase->uipPhrase[ui];
569  vpVecPush(spSection->vpVecNames, &cChar);
570  }
571  vpVecPush(spSection->vpVecNames, &s_cZero);
572  cpTest = (char*)vpVecAt(spSection->vpVecNames, spOffset->uiNameOffset);
573  if(bDisplay){
574  printf("\n%2d: test name: %s\n", (int)spSection->uiCount, cpTest);
575  }
576 
577  // the children of the test object are the description and the test SIP message
578  // get the description as the first child of the test object
579  vpItContent = vpJsonChildren(vpJson, spTest);
580  spValue = spJsonIteratorFirst(vpItContent);
581  spPhrase = spValue->spString;
582  spOffset->uiDescOffset = uiVecLen(spSection->vpVecDesc);
583  spOffset->uiDescLength = spPhrase->uiLength;
584  for(ui = 0; ui < spPhrase->uiLength; ui++){
585  if(spPhrase->uipPhrase[ui] > 126){
586  vJsonDtor(vpJson);
587  XTHROW(spEx, "test descriptions must be ASCII characters only");
588  }
589  cChar = (char)spPhrase->uipPhrase[ui];
590  vpVecPush(spSection->vpVecDesc, &cChar);
591  }
592  vpVecPush(spSection->vpVecDesc, &s_cZero);
593  cpTest = (char*)vpVecAt(spSection->vpVecDesc, spOffset->uiDescOffset);
594  if(bDisplay){
595  printf("\n%2d test description: %s\n", (int)spSection->uiCount, cpTest);
596  }
597 
598  // get the SIP message as the second child of the test object
599  spValue = spJsonIteratorNext(vpItContent);
600  spPhrase = spValue->spString;
601  spOffset->uiMsgOffset = uiVecLen(spSection->vpVecMsgs);
602  spOffset->uiMsgLength = spPhrase->uiLength;
603  if(bDisplay){
604  printf("offset: %d: length %d\n", (int)spOffset->uiMsgOffset, (int)spOffset->uiMsgLength);
605  }
606  for(ui = 0; ui < spPhrase->uiLength; ui++){
607  if(spPhrase->uipPhrase[ui] > 255){
608  vJsonDtor(vpJson);
609  XTHROW(spEx, "test messages must be octets only");
610  }
611  acaOctet= (achar)spPhrase->uipPhrase[ui];
612  vpVecPush(spSection->vpVecMsgs, &acaOctet);
613  }
614  spTest = spJsonIteratorNext(vpItTests);
615  vJsonIteratorDtor(vpItContent);
616  spSection->uiCount++;
617  }
618  spSection->uiCount--;
619  if(bDisplay){
620  printf("number of msgs: %d\n", (int)spSection->uiCount);
621  }
622  vJsonDtor(vpJson);
623 }
624 static void vParseTheMsgs(exception* spEx, section_def* spSection, const char* cpPrefix){
625  parser_config sConfig = {};
626  parser_state sState;
627  achar* acpMsgs;
628  char* cpNameBeg;
629  msg_offset* spOffsetBeg, *spOffset;
630  char caTraceName[1024];
631  char* cpTestName;
632  char* cpTraceConfig = "trace-config.txt";
633  aint ui;
634  void* vpParser = NULL;
635  void* vpTrace;
636  acpMsgs = (achar*)vpVecFirst(spSection->vpVecMsgs);
637  cpNameBeg = (char*)vpVecFirst(spSection->vpVecNames);
638  spOffsetBeg = (msg_offset*)vpVecFirst(spSection->vpVecOffsets);
639 
640  // convert trace config to absolute path
641  cpTraceConfig = cpMakeFileName(s_caBuf, SOURCE_DIR, "/", cpTraceConfig);
642 
643  // parse the messages
644  printf("\nParse the Messages without UDTs\n");
645  vpParser = vpParserCtor(spEx, vpSip0Init);
646  vpTrace = vpTraceCtor(vpParser);
647  vTraceConfig(vpTrace, cpTraceConfig);
648  spOffset = spOffsetBeg;
649  for(ui = 0; ui < spSection->uiCount; ui++){
650  cpTestName = cpNameBeg + spOffset->uiNameOffset;
651  snprintf(caTraceName, sizeof(caTraceName), "%s-%d-%s.out", cpPrefix, (int)(ui + 1), cpTestName);
652  vTraceSetOutput(vpTrace, caTraceName);
653  sConfig.acpInput = acpMsgs + spOffset->uiMsgOffset;
654  sConfig.uiInputLength = spOffset->uiMsgLength;
655  sConfig.uiStartRule = 0; // assumes that start rule is first rule, index 0 - use uiParseRuleLookup() if not sure
656  vParserParse(vpParser, &sConfig, &sState);
657  if(sState.uiSuccess){
658  printf("%2d: test name: %s: success\n", (int)(ui + 1), cpTestName);
659  }else{
660  printf("%2d: test name: %s: failure\n", (int)(ui + 1), cpTestName);
661  }
662  vUtilPrintParserState(&sState);
663  printf("\n");
664  spOffset++;
665  }
666 
667  printf("\nParse the Messages with UDTs\n");
668  vParserDtor(vpParser);
669  vpParser = vpParserCtor(spEx, vpSip1Init);
670  vSip1UdtCallbacks(vpParser);
671  vpTrace = vpTraceCtor(vpParser);
672  vTraceConfig(vpTrace, cpTraceConfig);
673  spOffset = spOffsetBeg;
674  for(ui = 0; ui < spSection->uiCount; ui++){
675  cpTestName = cpNameBeg + spOffset->uiNameOffset;
676  snprintf(caTraceName, sizeof(caTraceName), "%s-udt-%d-%s.out", cpPrefix, (int)(ui + 1), cpTestName);
677  vTraceSetOutput(vpTrace, caTraceName);
678  sConfig.acpInput = acpMsgs + spOffset->uiMsgOffset;
679  sConfig.uiInputLength = spOffset->uiMsgLength;
680  sConfig.uiStartRule = 0; // assumes that start rule is first rule, index 0 - use uiParseRuleLookup() if not sure
681  vParserParse(vpParser, &sConfig, &sState);
682  if(sState.uiSuccess){
683  printf("%2d: test name: %s: success\n", (int)(ui + 1), cpTestName);
684  }else{
685  printf("%2d: test name: %s: failure\n", (int)(ui + 1), cpTestName);
686  }
687  vUtilPrintParserState(&sState);
688  printf("\n");
689  spOffset++;
690  }
691  vParserDtor(vpParser);
692 }
693 static int iValid() {
694  int iReturn = EXIT_SUCCESS;
695  static void* vpMem = NULL;
696  static void* vpJson = NULL;
697  section_def sSection = {};
698  const char* cpOutPrefix;
699  exception e;
700  XCTOR(e);
701  if(e.try){
702  // try block
703  vpMem = vpMemCtor(&e);
704  vpJson = vpJsonCtor(&e);
705 
706  // display the information header
707  char* cpHeader =
708  "This function will read the SIP torture test valid messages and parse them,\n"
709  "with and without UDTs, displaying the test name and parsing result.\n"
710  "The parse is traced to the ../output folder.\n"
711  "To test without PPPTs, compile with APG_NO_PPPT defined.\n"
712  "To test with PPPTs, leave APG_NO_PPPT undefined.\n";
713  printf("\n%s", cpHeader);
714 
715  // convert the relative path names for the tests to absolute path names
716  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
717  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
718  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
719  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
720 
721  sSection.cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
722  sSection.cpSectionName = s_sTestsCtx.cpValidKey;
723  vGetMsgs(vpMem, &sSection, APG_TRUE);
724 
725 #ifdef APG_NO_PPPT
726  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "valid-trace");
727 #else
728  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "valid-trace-pppt");
729 #endif
730  vParseTheMsgs(&e, &sSection, cpOutPrefix);
731 
732  }else{
733  // catch block - display the exception location and message
735  iReturn = EXIT_FAILURE;
736  }
737 
738  // clean up resources
739  vJsonDtor(vpJson);
740  vMemDtor(vpMem);
741  return iReturn;
742 }
743 
744 static int iInvalid() {
745  int iReturn = EXIT_SUCCESS;
746  static void* vpMem = NULL;
747  static void* vpJson = NULL;
748  section_def sSection = {};
749  const char* cpOutPrefix;
750  exception e;
751  XCTOR(e);
752  if(e.try){
753  // try block
754  vpMem = vpMemCtor(&e);
755  vpJson = vpJsonCtor(&e);
756 
757  // display the information header
758  char* cpHeader =
759  "This function will read the SIP torture test invalid messages and parse them,\n"
760  "with and without UDTs, displaying the test name and parsing result.\n"
761  "The parse is traced to the ../output folder.\n"
762  "To test without PPPTs, compile with APG_NO_PPPT defined.\n"
763  "To test with PPPTs, leave APG_NO_PPPT undefined.\n";
764  printf("\n%s", cpHeader);
765 
766  // convert the relative path names for the tests to absolute path names
767  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
768  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
769  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
770  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
771 
772  sSection.cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
773  sSection.cpSectionName = s_sTestsCtx.cpInvalidKey;
774  vGetMsgs(vpMem, &sSection, APG_TRUE);
775 
776 #ifdef APG_NO_PPPT
777  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "invalid-trace");
778 #else
779  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "invalid-trace-pppt");
780 #endif
781  vParseTheMsgs(&e, &sSection, cpOutPrefix);
782 
783  }else{
784  // catch block - display the exception location and message
786  iReturn = EXIT_FAILURE;
787  }
788 
789  // clean up resources
790  vJsonDtor(vpJson);
791  vMemDtor(vpMem);
792  return iReturn;
793 }
794 
795 static int iSemantics() {
796  int iReturn = EXIT_SUCCESS;
797  static void* vpMem = NULL;
798  static void* vpJson = NULL;
799  section_def sSection = {};
800  const char* cpOutPrefix;
801  exception e;
802  XCTOR(e);
803  if(e.try){
804  // try block
805  vpMem = vpMemCtor(&e);
806  vpJson = vpJsonCtor(&e);
807 
808  // display the information header
809  char* cpHeader =
810  "This function will read the SIP torture test semantics messages and parse them,\n"
811  "with and without UDTs, displaying the test name and parsing result.\n"
812  "The parse is traced to the ../output folder.\n"
813  "To test without PPPTs, compile with APG_NO_PPPT defined.\n"
814  "To test with PPPTs, leave APG_NO_PPPT undefined.\n"
815  "Note that all of these tests are syntactically correct and parse successfully.\n"
816  "Since the errors are in the semantics no attempt at critiquing them is done.\n";
817  printf("\n%s", cpHeader);
818 
819  // convert the relative path names for the tests to absolute path names
820  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
821  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
822  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
823  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
824 
825  sSection.cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
826  sSection.cpSectionName = s_sTestsCtx.cpSemanticsKey;
827  vGetMsgs(vpMem, &sSection, APG_TRUE);
828 #ifdef APG_NO_PPPT
829  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "semantic-trace");
830 #else
831  cpOutPrefix = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "semantic-trace-pppt");
832 #endif
833 
834  vParseTheMsgs(&e, &sSection, cpOutPrefix);
835 
836  }else{
837  // catch block - display the exception location and message
839  iReturn = EXIT_FAILURE;
840  }
841 
842  // clean up resources
843  vJsonDtor(vpJson);
844  vMemDtor(vpMem);
845  return iReturn;
846 }
847 
848 typedef struct{
851  double dTime;
852  double dTimePerMsg;
853 } time_test;
854 static int iTime() {
855  int iReturn = EXIT_SUCCESS;
856  static void* vpMem = NULL;
857  static void* vpVecConfig = NULL;
858  static void* vpJson = NULL;
859  static void* vpParser = NULL;
860  static FILE* spFp = NULL;
861  static FILE* spFpUdt = NULL;
862  const char* cpOut, *cpOutUdt;
863  section_def sSection[3];
864  char caBuf[1024];
865  aint ui, uj, uiTests;
866  clock_t tStartTime, tEndTime;
867  double dMSec, dMsgsPerMSec;
868  luint uiMsgs, uiCharCount, uiMsgCount;
869  parser_config* spConfig, *spStart, *spEnd;
870  parser_state sState;
871  exception e;
872  XCTOR(e);
873  if(e.try){
874  // try block
875  vpMem = vpMemCtor(&e);
876  vpJson = vpJsonCtor(&e);
877 
878  // display the information header
879  char* cpHeader =
880  "This function will read all the SIP torture tests and parse them all multiple times.\n"
881  "Timing results will be collected and written to the ../output folder\n"
882  "To test without PPPTs, compile with APG_NO_PPPT defined.\n"
883  "To test with PPPTs, leave APG_NO_PPPT undefined.\n";
884  printf("\n%s", cpHeader);
885 
886  // convert the relative path names for the tests to absolute path names
887  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
888  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
889  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
890  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
891 
892 #ifdef APG_NO_PPPT
893  cpOut = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "time.out");
894  cpOutUdt = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "time-udt.out");
895 #else
896  cpOut = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "time-pppt.out");
897  cpOutUdt = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "time-pppt-udt.out");
898 #endif
899  spFp = fopen(cpOut, "wb");
900  if(!spFp){
901  snprintf(caBuf, sizeof(caBuf), "can't open output file %s", cpOut);
902  XTHROW(&e, caBuf);
903  }
904  spFpUdt = fopen(cpOutUdt, "wb");
905  if(!spFpUdt){
906  snprintf(caBuf, sizeof(caBuf), "can't open output file %s", cpOutUdt);
907  XTHROW(&e, caBuf);
908  }
909 
910  sSection[0].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
911  sSection[0].cpSectionName = s_sTestsCtx.cpValidKey;
912  vGetMsgs(vpMem, &sSection[0], APG_FALSE);
913  sSection[1].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
914  sSection[1].cpSectionName = s_sTestsCtx.cpInvalidKey;
915  vGetMsgs(vpMem, &sSection[1], APG_FALSE);
916  sSection[2].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
917  sSection[2].cpSectionName = s_sTestsCtx.cpSemanticsKey;
918  vGetMsgs(vpMem, &sSection[2], APG_FALSE);
919  vpVecConfig = vpVecCtor(vpMem, sizeof(parser_config), 60);
920 
921  for(uj = 0; uj < 3; uj++){
922  achar* acpMsgs = (achar*)vpVecFirst(sSection[uj].vpVecMsgs);
923  msg_offset* spOffset = (msg_offset*)vpVecFirst(sSection[uj].vpVecOffsets);
924  for(ui = 0; ui < sSection[uj].uiCount; ui++){
925  spConfig = (parser_config*)vpVecPush(vpVecConfig, NULL);
926  memset(spConfig, 0, sizeof(parser_config));
927  spConfig->acpInput = acpMsgs + spOffset->uiMsgOffset;
928  spConfig->uiInputLength = spOffset->uiMsgLength;
929  spConfig->uiStartRule = 0; // assumes that start rule is first rule, index 0 - use uiParseRuleLookup() if not sure
930  spOffset++;
931  }
932  }
933 
934 
935  spStart = (parser_config*)vpVecFirst(vpVecConfig);
936  uiMsgs = (luint)uiVecLen(vpVecConfig);
937  spEnd = spStart + uiMsgs;
938  uiTests = 1000;
939 
940  uiCharCount = 0;
941  uiMsgCount = 0;
942  vpParser = vpParserCtor(&e, vpSip0Init);
943  printf("\nBeginning Tests without UDTs: be patient\n");
944  tStartTime = clock();
945  for(ui = 0; ui < uiTests; ui++){
946  for(spConfig = spStart; spConfig < spEnd; spConfig++){
947  uiCharCount += (luint)spConfig->uiInputLength;
948  vParserParse(vpParser, spConfig, &sState);
949  }
950  uiMsgCount += uiMsgs;
951  }
952  tEndTime = clock();
953  dMSec = (double)((tEndTime - tStartTime) * 1000) / (double)CLOCKS_PER_SEC;
954  dMsgsPerMSec = (double)uiMsgCount / dMSec;
955  fprintf(spFp, "Timing Tests without UDTs\n");
956  fprintf(spFp, " Messages: %"PRIuMAX"\n", uiMsgCount);
957  fprintf(spFp, "Characters: %"PRIuMAX"\n", uiCharCount);
958  fprintf(spFp, " msec: %e\n", dMSec);
959  fprintf(spFp, " msec/msg: %e\n", (1.0 / dMsgsPerMSec));
960  fprintf(spFp, " msgs/msec: %e\n", dMsgsPerMSec);
961  printf("Results written to %s\n", cpOut);
962 
963  uiCharCount = 0;
964  uiMsgCount = 0;
965  vParserDtor(vpParser);
966  vpParser = vpParserCtor(&e, vpSip1Init);
967  vSip1UdtCallbacks(vpParser);
968  printf("\nBeginning Tests with UDTs: be patient\n");
969  tStartTime = clock();
970  for(ui = 0; ui < uiTests; ui++){
971  for(spConfig = spStart; spConfig < spEnd; spConfig++){
972  uiCharCount += (luint)spConfig->uiInputLength;
973  vParserParse(vpParser, spConfig, &sState);
974  }
975  uiMsgCount += uiMsgs;
976  }
977  tEndTime = clock();
978  dMSec = (double)((tEndTime - tStartTime) * 1000) / (double)CLOCKS_PER_SEC;
979  dMsgsPerMSec = (double)uiMsgCount /dMSec;
980  fprintf(spFpUdt, "Timing Tests with UDTs\n");
981  fprintf(spFpUdt, " Messages: %"PRIuMAX"\n", uiMsgCount);
982  fprintf(spFpUdt, "Characters: %"PRIuMAX"\n", uiCharCount);
983  fprintf(spFpUdt, " msec: %e\n", dMSec);
984  fprintf(spFpUdt, " msec/msg: %e\n", (1.0 / dMsgsPerMSec));
985  fprintf(spFpUdt, " msgs/msec: %e\n", dMsgsPerMSec);
986  printf("Results written to %s\n", cpOutUdt);
987 
988  }else{
989  // catch block - display the exception location and message
991  iReturn = EXIT_FAILURE;
992  }
993 
994  // clean up resources
995  if(spFp){
996  fclose(spFp);
997  }
998  if(spFpUdt){
999  fclose(spFpUdt);
1000  }
1001  vParserDtor(vpParser);
1002  vJsonDtor(vpJson);
1003  vMemDtor(vpMem);
1004  return iReturn;
1005 }
1006 
1007 static int iStats() {
1008  int iReturn = EXIT_SUCCESS;
1009  static void* vpMem = NULL;
1010  static void* vpStats = NULL;
1011  static void* vpVecConfig = NULL;
1012  static void* vpJson = NULL;
1013  static void* vpParser = NULL;
1014  const char* cpOut, *cpOutUdt;
1015  section_def sSection[3];
1016  aint ui, uj;
1017  parser_config* spConfig, *spStart, *spEnd;
1018  parser_state sState;
1019  exception e;
1020  XCTOR(e);
1021  if(e.try){
1022  // try block
1023  vpMem = vpMemCtor(&e);
1024  vpJson = vpJsonCtor(&e);
1025 
1026  // display the information header
1027  char* cpHeader =
1028  "This function will parse all of the SIP torture tests and display the node-hit statistics.\n"
1029  "Comparisons will show the differences between parsing with and without PPPTs,\n"
1030  " and with and without UDTs.\n";
1031  printf("\n%s", cpHeader);
1032 
1033  // convert the relative path names for the tests to absolute path names
1034  s_sTestsCtx.cpValidIn = cpMakeFileName(s_caBufTests, SOURCE_DIR, "/", s_sTestsCtx.cpValidIn);
1035  s_sTestsCtx.cpInvalidIn = cpMakeFileName(&s_caBufTests[PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpInvalidIn);
1036  s_sTestsCtx.cpSemanticsIn = cpMakeFileName(&s_caBufTests[2*PATH_MAX], SOURCE_DIR, "/", s_sTestsCtx.cpSemanticsIn);
1037  s_sTestsCtx.cpSipJsonObject = cpMakeFileName(&s_caBufTests[3*PATH_MAX], SOURCE_DIR, "/../output/", s_sTestsCtx.cpSipJsonObject);
1038 
1039  sSection[0].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
1040  sSection[0].cpSectionName = s_sTestsCtx.cpValidKey;
1041  vGetMsgs(vpMem, &sSection[0], APG_FALSE);
1042  sSection[1].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
1043  sSection[1].cpSectionName = s_sTestsCtx.cpInvalidKey;
1044  vGetMsgs(vpMem, &sSection[1], APG_FALSE);
1045  sSection[2].cpJsonFileName = s_sTestsCtx.cpSipJsonObject;
1046  sSection[2].cpSectionName = s_sTestsCtx.cpSemanticsKey;
1047  vGetMsgs(vpMem, &sSection[2], APG_FALSE);
1048  vpVecConfig = vpVecCtor(vpMem, sizeof(parser_config), 60);
1049 
1050  for(uj = 0; uj < 3; uj++){
1051  achar* acpMsgs = (achar*)vpVecFirst(sSection[uj].vpVecMsgs);
1052  msg_offset* spOffset = (msg_offset*)vpVecFirst(sSection[uj].vpVecOffsets);
1053  for(ui = 0; ui < sSection[uj].uiCount; ui++){
1054  spConfig = (parser_config*)vpVecPush(vpVecConfig, NULL);
1055  memset(spConfig, 0, sizeof(parser_config));
1056  spConfig->acpInput = acpMsgs + spOffset->uiMsgOffset;
1057  spConfig->uiInputLength = spOffset->uiMsgLength;
1058  spConfig->uiStartRule = 0; // assumes that start rule is first rule, index 0 - use uiParseRuleLookup() if not sure
1059  spOffset++;
1060  }
1061  }
1062 
1063 #ifdef APG_NO_PPPT
1064  cpOut = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "stats.out");
1065  cpOutUdt = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "stats-udt.out");
1066 #else
1067  cpOut = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../output/", "stats-pppt.out");
1068  cpOutUdt = cpMakeFileName(&s_caBuf[PATH_MAX], SOURCE_DIR, "/../output/", "stats-pppt-udt.out");
1069 #endif
1070  aint uiMsgs = uiVecLen(vpVecConfig);
1071  spStart = (parser_config*)vpVecFirst(vpVecConfig);
1072  spEnd = spStart + uiMsgs;
1073  vpParser = vpParserCtor(&e, vpSip0Init);
1074  vpStats = vpStatsCtor(vpParser);
1075  spConfig = spStart;
1076  printf("\nStats without UDTs: cumulative for %d messages\n", (int)uiMsgs);
1077  for(; spConfig < spEnd; spConfig++){
1078  vParserParse(vpParser, spConfig, &sState);
1079  }
1080  vStatsToAscii(vpStats, NULL, cpOut);
1081  printf("Results written to %s\n", cpOut);
1082 
1083  vParserDtor(vpParser);
1084  vpParser = vpParserCtor(&e, vpSip1Init);
1085  vSip1UdtCallbacks(vpParser);
1086  vpStats = vpStatsCtor(vpParser);
1087  spConfig = spStart;
1088  printf("\nStats with UDTs: cumulative for %d messages\n", (int)uiMsgs);
1089  for(; spConfig < spEnd; spConfig++){
1090  vParserParse(vpParser, spConfig, &sState);
1091  }
1092  vStatsToAscii(vpStats, NULL, cpOutUdt);
1093  printf("Results written to %s\n", cpOutUdt);
1094 
1095  }else{
1096  // catch block - display the exception location and message
1097  vUtilPrintException(&e);
1098  iReturn = EXIT_FAILURE;
1099  }
1100 
1101  // clean up resources
1102  vParserDtor(vpParser);
1103  vJsonDtor(vpJson);
1104  vMemDtor(vpMem);
1105  return iReturn;
1106 }
1107 
1115 int main(int argc, char **argv) {
1116  long int iCase = 0;
1117  if(argc > 1){
1118  iCase = atol(argv[1]);
1119  }
1120  if((iCase > 0) && (iCase <= s_iCaseCount)){
1121  printf("%s\n", s_cppCases[iCase -1]);
1122  }
1123  switch(iCase){
1124  case 1:
1125  return iApp();
1126  case 2:
1127  return iBuilder();
1128  case 3:
1129  return iValid();
1130  case 4:
1131  return iInvalid();
1132  case 5:
1133  return iSemantics();
1134  case 6:
1135  return iTime();
1136  case 7:
1137  return iStats();
1138  default:
1139  return iHelp();
1140  }
1141 }
1142 
sip-0.h
vTraceSetOutput
void vTraceSetOutput(void *vpCtx, const char *cpFileName)
Definition: trace.c:172
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
json_context::vpVecNameIndexes
void * vpVecNameIndexes
Definition: main.c:291
vpParserCtor
void * vpParserCtor(exception *spException, void *vpParserInit)
The parser's constructor for file initialization data.
Definition: parser.c:67
section_def
Definition: main.c:514
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
vSip1UdtCallbacks
void vSip1UdtCallbacks(void *vpParserCtx)
Set the UDT callback functions for the SIP2.bnf grammar to their respective parse tree nodes.
Definition: udtlib.c:447
time_test::dTime
double dTime
Definition: main.c:851
section_def::vpVecOffsets
void * vpVecOffsets
Definition: main.c:518
parser_state::uiSuccess
aint uiSuccess
True (>0) if the input string was matched in its entirety, false (0) otherwise.
Definition: parser.h:184
vpJsonChildren
void * vpJsonChildren(void *vpCtx, json_value *spValue)
Initialize the iterator over the children of the given value as the parent node.
Definition: json.c:530
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
msg_offset::uiDescLength
aint uiDescLength
Definition: main.c:506
time_test::uiChars
aint uiChars
Definition: main.c:850
vpJsonFindKeyA
void * vpJsonFindKeyA(void *vpCtx, const char *cpKey, json_value *spValue)
Find JSON values with a specified ASCII key.
Definition: json.c:434
time_test
Definition: main.c:848
vpJsonReadFile
void * vpJsonReadFile(void *vpCtx, const char *cpFileName)
The JSON file reader.
Definition: json.c:207
msg_offset::uiMsgLength
aint uiMsgLength
Definition: main.c:508
test_context
Definition: main.c:267
vpStatsCtor
void * vpStatsCtor(void *vpParserCtx)
The statistics object constructor.
Definition: stats.c:113
u32_phrase::uiLength
uint32_t uiLength
The number of integers in the array.
Definition: lib.h:75
section_def::uiCount
aint uiCount
Definition: main.c:521
parser_config::acpInput
const achar * acpInput
Pointer to the input string.
Definition: parser.h:199
test_context::cpSemanticsIn
char * cpSemanticsIn
Definition: main.c:273
section_def::vpVecDesc
void * vpVecDesc
Definition: main.c:517
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
msg_offset::uiNameLength
aint uiNameLength
Definition: main.c:504
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
json_context::vpVecNames
void * vpVecNames
Definition: main.c:290
msg_offset::uiDescOffset
aint uiDescOffset
Definition: main.c:505
section_def::cpSectionName
char * cpSectionName
Definition: main.c:519
time_test::uiMsgs
aint uiMsgs
Definition: main.c:849
vpVecAt
void * vpVecAt(void *vpCtx, aint uiIndex)
Get a the indexed vector element. The vector is not altered.
Definition: vector.c:362
u32_phrase::uipPhrase
const uint32_t * uipPhrase
Pointer to an array of 32-bit unsigned integers.
Definition: lib.h:74
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
json_context::vpVecIn
void * vpVecIn
Definition: main.c:293
section_def::vpVecMsgs
void * vpVecMsgs
Definition: main.c:515
test_context::cpInvalidIn
char * cpInvalidIn
Definition: main.c:272
test_context::cpSemanticsKey
char * cpSemanticsKey
Definition: main.c:270
json_context::vpMem
void * vpMem
Definition: main.c:288
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
parser_config::uiInputLength
aint uiInputLength
Number of input string alphabet characters.
Definition: parser.h:200
spMemException
exception * spMemException(void *vpCtx)
Get a pointer to this memory objects's exception handler.
Definition: memory.c:174
uiJsonBuildMakeStringA
aint uiJsonBuildMakeStringA(void *vpBuildCtx, const char *cpString)
Make a string value from a null-terminated ASCII string.
Definition: builder.c:283
vpTraceCtor
void * vpTraceCtor(void *vpCtx)
The trace object constructor.
Definition: trace.c:92
parser_config
Defines the input string and other configuration parameters for the parser,.
Definition: parser.h:198
udtlib.h
Header file for UDT functions for SIP messages.
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
vpSip0Init
void * vpSip0Init
Definition: sip-0.c:11956
uiVecLen
aint uiVecLen(void *vpCtx)
Get the vector length. That is, the number of elements on the vector.
Definition: vector.c:385
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
parser_state
The parser's final state.
Definition: parser.h:183
vStatsToAscii
void vStatsToAscii(void *vpCtx, const char *cpMode, const char *cpFileName)
Display the statistics in ASCII format.
Definition: stats.c:412
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
uiJsonBuildMakeObject
aint uiJsonBuildMakeObject(void *vpBuildCtx)
Make a JSON object value.
Definition: builder.c:445
msg_offset::uiNameOffset
aint uiNameOffset
Definition: main.c:503
ucpJsonWrite
uint8_t * ucpJsonWrite(void *vpCtx, json_value *spValue, aint *uipCount)
Converts a sub-tree of values into UTF-8 byte stream of JSON text.
Definition: json.c:329
vpSip1Init
void * vpSip1Init
Definition: sip-1.c:11451
vpJsonBuild
void * vpJsonBuild(void *vpBuildCtx, aint uiRoot)
Build the JSON object.
Definition: builder.c:603
uiJsonBuildMakeStringU
aint uiJsonBuildMakeStringU(void *vpBuildCtx, const uint32_t *uipData, aint uiLength)
Make a string value from UTF-32 code points.
Definition: builder.c:223
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
uiJsonBuildAddToObject
aint uiJsonBuildAddToObject(void *vpBuildCtx, aint uiObject, aint uiKey, aint uiAdd)
Add a child value to a parent object value.
Definition: builder.c:479
spJsonIteratorFirst
json_value * spJsonIteratorFirst(void *vpIteratorCtx)
Find the first value in the list represented by this iterator.
Definition: json.c:613
test_context::cpValidKey
char * cpValidKey
Definition: main.c:268
json_context::cpOutObject
const char * cpOutObject
Definition: main.c:287
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
vpVecPushn
void * vpVecPushn(void *vpCtx, void *vpElement, aint uiCount)
Adds one or more elements to the end of the array.
Definition: vector.c:221
section_def::cpJsonFileName
char * cpJsonFileName
Definition: main.c:520
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
spJsonIteratorNext
json_value * spJsonIteratorNext(void *vpIteratorCtx)
Find the next value in the list represented by this iterator.
Definition: json.c:647
test_context::cpInvalidKey
char * cpInvalidKey
Definition: main.c:269
json_context::vpVecUnicode
void * vpVecUnicode
Definition: main.c:294
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
section_def::vpVecNames
void * vpVecNames
Definition: main.c:516
json_context::vpVecOut
void * vpVecOut
Definition: main.c:292
time_test::dTimePerMsg
double dTimePerMsg
Definition: main.c:852
bMemValidate
abool bMemValidate(void *vpCtx)
Validates a memory context.
Definition: memory.c:160
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
json_context::vpVecChars
void * vpVecChars
Definition: main.c:295
vJsonIteratorDtor
void vJsonIteratorDtor(void *vpIteratorCtx)
The JSON iterator destructor.
Definition: json.c:591
vTraceConfig
void vTraceConfig(void *vpCtx, const char *cpFileName)
Read a configuration file and set the trace configuration accordingly.
Definition: trace-config.c:143
json_context::spException
exception * spException
Definition: main.c:289
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
json_context
Definition: main.c:286
vpJsonCtor
void * vpJsonCtor(exception *spEx)
The JSON constructor.
Definition: json.c:115
parser_config::uiStartRule
aint uiStartRule
Index of the start rule. Any rule in the SABNF grammar may be used as the start rule.
Definition: parser.h:201
vJsonDtor
void vJsonDtor(void *vpCtx)
The JSON Parser component destructor.
Definition: json.c:165
msg_offset
Definition: main.c:502
test_context::cpValidIn
char * cpValidIn
Definition: main.c:271
u32_phrase
Defines a pointer to an array of 32-bit unsigned integers plus its length. Typically needed by Unicod...
Definition: lib.h:73
section_def::uiSection
aint uiSection
Definition: main.c:522
sip-1.h
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
test_context::cpSipJsonObject
char * cpSipJsonObject
Definition: main.c:274
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
vVecClear
void vVecClear(void *vpCtx)
Clears all used elements in a vector component.
Definition: vector.c:420
msg_offset::uiMsgOffset
aint uiMsgOffset
Definition: main.c:507
vUtilPrintParserState
void vUtilPrintParserState(parser_state *spState)
Display the parser state in human-readable format to stdout.
Definition: utilities.c:727
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
vpJsonBuildCtor
void * vpJsonBuildCtor(void *vpJsonCtx)
The builder object constructor.
Definition: builder.c:124
vParserParse
void vParserParse(void *vpCtx, parser_config *spConfig, parser_state *spState)
Parse an input string of alphabet characters.
Definition: parser.c:268
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.