Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
output.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 * *************************************************************************************/
35 #include "../api/api.h"
36 #include "../api/apip.h"
37 #include "../api/attributes.h"
38 #include "../library/parserp.h"
39 
50 typedef struct{
73 } init_hdr_out;
74 
78 #define OUTPUT_LINE_LENGTH 30
79 
83 #define LUINT_MAX(x,y) if(((x) < (y)) && ((y) != (luint)-1))x = (y)
84 
85 static const char* s_cpUchar = "uint8_t";
86 static const char* s_cpUshort = "uint16_t";
87 static const char* s_cpUint = "uint32_t";
88 static const char* s_cpUlong = "uint64_t";
89 static char* s_cpLicenseNotice =
90  "/* *************************************************************************************\n"
91  " Copyright (c) 2021, Lowell D. Thomas\n"
92  " All rights reserved.\n"
93  "\n"
94  " This file was generated by and is part of APG Version 7.0.\n"
95  " APG Version 7.0 may be used under the terms of the BSD 2-Clause License.\n"
96  "\n"
97  " Redistribution and use in source and binary forms, with or without\n"
98  " modification, are permitted provided that the following conditions are met:\n"
99  "\n"
100  " 1. Redistributions of source code must retain the above copyright notice, this\n"
101  " list of conditions and the following disclaimer.\n"
102  "\n"
103  " 2. Redistributions in binary form must reproduce the above copyright notice,\n"
104  " this list of conditions and the following disclaimer in the documentation\n"
105  " and/or other materials provided with the distribution.\n"
106  "\n"
107  " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
108  " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
109  " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
110  " DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n"
111  " FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
112  " DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n"
113  " SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n"
114  " CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n"
115  " OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
116  " OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
117  "\n"
118  "* *************************************************************************************/\n\n";
119 
120 static aint uiLastChar(char cCharToFind, const char* cpString);
121 static abool bGetFileName(const char* cpPathName, char* cpBuffer, aint uiBufferLength);
122 static abool bSetFileExtension(const char* cpPathName, const char* cpExt, char* cpBuffer, aint uiBufferLength);
123 static abool bNameToCaps(const char* cpPrefix, const char* cpName, char* cpBuffer, aint uiBufferLength);
124 static abool bNameToCamelCase(const char* cpPrefix, const char* cpName, char* cpBuffer, aint uiBufferLength);
125 static void vOutputHeader(api* spApi, const char* cpName, FILE* spOut);
126 static void vOutputSource(api* spApi, const char* cpName, FILE* spOut);
127 static void* vpOutputParser(api* spApi);
128 static int iCompRule(const void* vpL, const void* vpR);
129 static int iCompUdt(const void* vpL, const void* vpR);
130 static char cToUpper(char cChar);
131 static char cToLower(char cChar);
132 static abool bIsLetter(char cLetter);
133 static void vPrintChars(FILE* spOut, const uint8_t* ucpChars, aint uiLength);
134 static void vPrintLongs(FILE* spOut, const luint* luiVals, aint uiLength);
135 static aint uiGetSize(luint luiValue);
136 static const char* cpGetType(luint luiVal);
137 static void* vpMakeParserInit(api* spApi, luint luiUintMax, luint* luipData, aint uiLen);
138 static void* vpMakeAcharTable(api* spApi, luint luiAcharMax, luint* luipTable, aint uiLen);
139 static luint* luipMakeInitData(api* spApi);
140 
141 #ifdef TEST_NAMES
142 static void vTestNames();
143 #endif /* TEST_NAMES */
144 
152 void vApiOutput(void* vpCtx, const char* cpOutput) {
153  if(!bApiValidate(vpCtx)){
154  vExContext();
155  }
156  api* spApi = (api*) vpCtx;
157  FILE* spHeader = NULL;
158  FILE* spSource = NULL;
159  char caName[PATH_MAX];
160  char caFileName[PATH_MAX];
161  size_t uiErrorSize = PATH_MAX + 128;
162  char caErrorBuf[uiErrorSize];
163  vMsgsClear(spApi->vpLog);
164  // validate that we have a valid and fully processed grammar
165  if (!spApi->bInputValid) {
166  XTHROW(spApi->spException, "attempted output but input grammar not validated");
167  }
168  if (!spApi->bSyntaxValid) {
169  XTHROW(spApi->spException, "attempted output but syntax not validated");
170  }
171  if (!spApi->bSemanticsValid) {
172  XTHROW(spApi->spException,
173  "attempted output but opcodes have not been constructed and validated");
174  }
175 
176  // generate the header file
177  if(!bGetFileName(cpOutput, caName, PATH_MAX)){
178  snprintf(caErrorBuf, uiErrorSize, "unable to extract file name from output parameter: '%s'", cpOutput);
179  XTHROW(spApi->spException, caErrorBuf);
180  }
181 
182  // make sure the file names are good
183  if(!bSetFileExtension(cpOutput, "h", caFileName, PATH_MAX)){
184  snprintf(caErrorBuf, uiErrorSize, "unable to set file extension on output parameter: '%s'", cpOutput);
185  XTHROW(spApi->spException, caErrorBuf);
186  }
187  spHeader = fopen(caFileName, "wb");
188  if (!spHeader) {
189  snprintf(caErrorBuf, uiErrorSize, "unable to open header file \"%s\"", caFileName);
190  XTHROW(spApi->spException, caErrorBuf);
191  }
192  vOutputHeader(spApi, caName, spHeader);
193  fclose(spHeader);
194 
195  if(!bSetFileExtension(cpOutput, "c", caFileName, PATH_MAX)){
196  snprintf(caErrorBuf, uiErrorSize, "unable to set file extension on output parameter: '%s'", cpOutput);
197  XTHROW(spApi->spException, caErrorBuf);
198  }
199  spSource = fopen(caFileName, "wb");
200  if (!spSource) {
201  snprintf(caErrorBuf, uiErrorSize, "unable to open source file \"%s\"", caFileName);
202  XTHROW(spApi->spException, caErrorBuf);
203  }
204  vOutputSource(spApi, caName, spSource);
205  fclose(spSource);
206 }
207 
217 void* vpApiOutputParser(void* vpCtx) {
218  if(!bApiValidate(vpCtx)){
219  vExContext();
220  }
221  api* spApi = (api*) vpCtx;
222  vMsgsClear(spApi->vpLog);
223  // validate that we have a valid and fully processed grammar
224  if (!spApi->bInputValid) {
225  XTHROW(spApi->spException, "attempted output but input grammar not validated");
226  }
227  if (!spApi->bSyntaxValid) {
228  XTHROW(spApi->spException, "attempted output but syntax not validated");
229  }
230  if (!spApi->bSemanticsValid) {
231  XTHROW(spApi->spException, "attempted output but opcodes have not been constructed and validated");
232  }
233 
234  // generate the parser
235  return vpOutputParser(spApi);
236 }
237 
238 static void vOutputHeader(api* spApi, const char* cpName, FILE* spOut){
239  aint uiBufSize = PATH_MAX;
240  char caDefine[PATH_MAX];
241  char caWork[PATH_MAX];
242  char caRuleCount[PATH_MAX];
243  char caUdtCount[PATH_MAX];
244  api_rule saRules[spApi->uiRuleCount];
245  api_udt saUdts[spApi->uiUdtCount];
246  aint ui;
247  // version, copyright, etc.
248  fprintf(spOut, "//\n");
249  fprintf(spOut, "// This C-language parser header was generated by APG Version 7.0.\n");
250  fprintf(spOut, "// User modifications may cause unpredictable results.\n");
251  fprintf(spOut, "//\n");
252  fprintf(spOut, "%s",s_cpLicenseNotice);
253 
254  bNameToCaps("", cpName, caWork, uiBufSize);
255  caDefine[0] = '_';
256  caDefine[1] = 0;
257  strcat(caDefine, caWork);
258  strcat(caDefine, "_H_");
259 
260  // output define guards
261  fprintf(spOut, "#ifndef %s\n", caDefine);
262  fprintf(spOut, "#define %s\n", caDefine);
263 
264  // alphabetize the rule names
265  for(ui = 0; ui < spApi->uiRuleCount; ui++){
266  saRules[ui] = spApi->spRules[ui];
267  }
268  qsort((void*)&saRules[0], spApi->uiRuleCount, sizeof(api_rule), iCompRule);
269 
270  // output the rule name ids
271  fprintf(spOut, "\n");
272  fprintf(spOut, "// rule ids\n");
273  for(ui = 0; ui < spApi->uiRuleCount; ui++){
274  bNameToCaps(cpName, saRules[ui].cpName, caWork, uiBufSize);
275  fprintf(spOut, "#define %s %"PRIuMAX"\n", caWork, (luint)saRules[ui].uiIndex);
276  }
277  bNameToCaps("RULE_COUNT", cpName, caRuleCount, uiBufSize);
278  fprintf(spOut, "#define %s %"PRIuMAX"\n", caRuleCount, (luint)spApi->uiRuleCount);
279 
280  if(spApi->uiUdtCount){
281  // alphabetize the UDT names
282  for(ui = 0; ui < spApi->uiUdtCount; ui++){
283  saUdts[ui] = spApi->spUdts[ui];
284  }
285  qsort((void*)&saUdts[0], spApi->uiUdtCount, sizeof(api_udt), iCompUdt);
286 
287  // output the UDT ids
288  fprintf(spOut, "\n");
289  fprintf(spOut, "// UDT ids\n");
290  for(ui = 0; ui < spApi->uiUdtCount; ui++){
291  bNameToCaps(cpName, saUdts[ui].cpName, caWork, uiBufSize);
292  fprintf(spOut, "#define %s %"PRIuMAX"\n", caWork, (luint)saUdts[ui].uiIndex);
293  }
294  bNameToCaps("UDT_COUNT", cpName, caUdtCount, uiBufSize);
295  fprintf(spOut, "#define %s %"PRIuMAX"\n", caUdtCount, (luint)spApi->uiUdtCount);
296  }
297 
298  // the init pointer name
299  bNameToCamelCase("vp", cpName, caWork, uiBufSize);
300  strcat(caWork, "Init");
301  fprintf(spOut, "\n");
302  fprintf(spOut, "// pointer to parser initialization data\n");
303  fprintf(spOut, "extern void* %s;\n", caWork);
304 
305  // comment for callback helper functions
306  fprintf(spOut, "\n");
307  fprintf(spOut, "// Helper function(s) for setting rule/UDT name callbacks.\n");
308  fprintf(spOut, "// Un-comment and replace named NULL with pointer to the appropriate callback function.\n");
309  fprintf(spOut, "// NOTE: This can easily be modified for setting AST callback functions:\n");
310  fprintf(spOut, "// Replace parser_callback with ast_callback and\n");
311  fprintf(spOut, "// vParserSetRuleCallback(vpParserCtx) with vAstSetRuleCallback(vpAstCtx) and\n");
312  fprintf(spOut, "// vParserSetUdtCallback(vpParserCtx) with vAstSetUdtCallback(vpAstCtx).\n");
313  fprintf(spOut, "/****************************************************************\n");
314  bNameToCamelCase("v", cpName, caWork, uiBufSize);
315  strcat(caWork, "RuleCallbacks");
316  fprintf(spOut, "void %s(void* vpParserCtx){\n", caWork);
317  fprintf(spOut, " aint ui;\n");
318  fprintf(spOut, " parser_callback cb[%s];\n", caRuleCount);
319  for(ui = 0; ui < spApi->uiRuleCount; ui++){
320  bNameToCaps(cpName, saRules[ui].cpName, caWork, uiBufSize);
321  fprintf(spOut, " cb[%s] = NULL;\n", caWork);
322  }
323  fprintf(spOut, " for(ui = 0; ui < (aint)%s; ui++){\n", caRuleCount);
324  fprintf(spOut, " vParserSetRuleCallback(vpParserCtx, ui, cb[ui]);\n");
325  fprintf(spOut, " }\n");
326  fprintf(spOut, "}\n");
327  if(spApi->uiUdtCount){
328  bNameToCamelCase("v", cpName, caWork, uiBufSize);
329  strcat(caWork, "UdtCallbacks");
330  fprintf(spOut, "void %s(void* vpParserCtx){\n", caWork);
331  fprintf(spOut, " aint ui;\n");
332  fprintf(spOut, " parser_callback cb[%s];\n", caUdtCount);
333  for(ui = 0; ui < spApi->uiUdtCount; ui++){
334  bNameToCaps(cpName, saUdts[ui].cpName, caWork, uiBufSize);
335  fprintf(spOut, " cb[%s] = NULL;\n", caWork);
336  }
337  fprintf(spOut, " for(ui = 0; ui < (aint)%s; ui++){\n", caUdtCount);
338  fprintf(spOut, " vParserSetUdtCallback(vpParserCtx, ui, cb[ui]);\n");
339  fprintf(spOut, " }\n");
340  fprintf(spOut, "}\n");
341  }
342  fprintf(spOut, "****************************************************************/\n");
343 
344  // output end of define guards
345  fprintf(spOut, "\n");
346  fprintf(spOut, "#endif /* %s */\n", caDefine);
347 }
348 static void vOutputSource(api* spApi, const char* cpName, FILE* spOut){
349  luint* luipInit = NULL;
350  char* cpLineBuffer = NULL;
351  line* spLine;
352  aint ui;
353  char caBuf[PATH_MAX];
354  init_hdr_out* spHdr;
355  aint uiaOpCounts[ID_GEN];
356  api_op* spOp = spApi->spOpcodes;
357 
358  if(spApi->luipInit){
359  vMemFree(spApi->vpMem, spApi->luipInit);
360  }
361  spApi->luipInit = luipMakeInitData(spApi);
362  luipInit = spApi->luipInit;
363  spHdr = (init_hdr_out*)luipInit;
364  memset((void*)&uiaOpCounts[0], 0, sizeof(uiaOpCounts));
365  for(ui = 0; ui < spApi->uiOpcodeCount; ui++, spOp++){
366  uiaOpCounts[spOp->uiId]++;
367  }
368 
369  // version, copyright, etc.
370  fprintf(spOut, "//\n");
371  fprintf(spOut, "// This C-language parser code was generated by APG Version 7.0.\n");
372  fprintf(spOut, "// User modifications may cause unpredictable results.\n");
373  fprintf(spOut, "//\n");
374  fprintf(spOut, "%s",s_cpLicenseNotice);
375  fprintf(spOut, "#include <stdint.h>\n");
376  fprintf(spOut, "\n");
377 
378  // the string table
379  fprintf(spOut, "static const char caStringTable[%"PRIuMAX"] = {\n", (luint)spApi->uiStringTableLength);
380  vPrintChars(spOut, (uint8_t*)spApi->cpStringTable, spApi->uiStringTableLength);
381  fprintf(spOut, "};\n");
382  fprintf(spOut, "\n");
383 
384  // the PPPT maps
385  if(spApi->bUsePppt){
386  fprintf(spOut, "static const uint8_t ucaPpptTable[%"PRIuMAX"] = {\n", spApi->luiPpptTableLength);
387  vPrintChars(spOut, spApi->ucpPpptTable, spApi->luiPpptTableLength);
388  fprintf(spOut, "};\n");
389  fprintf(spOut, "\n");
390  }
391 
392  // the achar table
393  if(spApi->uiAcharTableLength){
394  fprintf(spOut, "static const %s aAcharTable[%"PRIuMAX"] = {\n",
395  cpGetType(spApi->luiAcharMax), (luint)spApi->uiAcharTableLength);
396  vPrintLongs(spOut, spApi->luipAcharTable, spApi->uiAcharTableLength);
397  fprintf(spOut, "};\n");
398  fprintf(spOut, "\n");
399  }
400 
401 
402  // output the parser initialization data
403  fprintf(spOut, "static const %s aParserInit[%"PRIuMAX"] = {\n", cpGetType(spHdr->luiUintMax), spHdr->luiSizeInInts);
404  vPrintLongs(spOut, luipInit, (aint)spHdr->luiSizeInInts);
405  fprintf(spOut, "};\n");
406  fprintf(spOut, "\n");
407 
408  // output the parser initialization struct
409  fprintf(spOut, "static struct {\n");
410  fprintf(spOut, " uint32_t uiSizeofAchar;\n");
411  fprintf(spOut, " uint32_t uiSizeofUint;\n");
412  fprintf(spOut, " uint32_t uiStringTableLength;\n");
413  fprintf(spOut, " uint32_t uiAcharTableLength;\n");
414  fprintf(spOut, " uint32_t uiPpptTableLength;\n");
415  fprintf(spOut, " uint32_t uiParserInitLength;\n");
416  fprintf(spOut, " const char* cpStringTable;\n");
417  fprintf(spOut, " const uint8_t* ucpPpptTable;\n");
418  fprintf(spOut, " const void* vpAcharTable;\n");
419  fprintf(spOut, " const void* vpParserInit;\n");
420  fprintf(spOut, "} s_parser_init = {\n");
421  fprintf(spOut, " %"PRIuMAX",\n", spHdr->luiSizeofAchar);
422  fprintf(spOut, " %"PRIuMAX",\n", spHdr->luiSizeofUint);
423  fprintf(spOut, " %"PRIuMAX",\n", (luint)spApi->uiStringTableLength);
424  fprintf(spOut, " %"PRIuMAX",\n", (luint)spApi->uiAcharTableLength);
425  fprintf(spOut, " %"PRIuMAX",\n", spApi->luiPpptTableLength);
426  fprintf(spOut, " %"PRIuMAX",\n", (luint)spHdr->luiSizeInInts);
427  fprintf(spOut, " caStringTable,\n");
428  if(spApi->bUsePppt){
429  fprintf(spOut, " ucaPpptTable,\n");
430  }else{
431  fprintf(spOut, " (const uint8_t*)0,\n");
432  }
433  if(spApi->uiAcharTableLength){
434  fprintf(spOut, " (const void*)aAcharTable,\n");
435  }else{
436  fprintf(spOut, " (const void*)0,\n");
437  }
438  fprintf(spOut, " (const void*)aParserInit\n");
439  fprintf(spOut, "};\n");
440  fprintf(spOut, "\n");
441  fprintf(spOut, "// void pointer to the parser initialization data\n");
442  bNameToCamelCase("vp", cpName, caBuf, PATH_MAX);
443  fprintf(spOut, "void* %sInit = (void*)&s_parser_init;\n", caBuf);
444  fprintf(spOut, "\n");
445 
446  // summary
447  fprintf(spOut, "// ALPHABET\n");
448  fprintf(spOut, "// achar min = %"PRIuMAX"\n", spHdr->luiAcharMin);
449  fprintf(spOut, "// achar max = %"PRIuMAX"\n", spHdr->luiAcharMax);
450  fprintf(spOut, "// aint max = %"PRIuMAX"\n", spHdr->luiUintMax);
451  fprintf(spOut, "\n");
452  if(spApi->bUsePppt){
453  fprintf(spOut, "// PPPT\n");
454  }else{
455  fprintf(spOut, "// PPPT (not used)\n");
456  }
457  fprintf(spOut, "// no. maps = %"PRIuMAX"\n", spApi->luiPpptMapCount);
458  fprintf(spOut, "// map size = %"PRIuMAX" (bytes)\n", spApi->luiPpptMapSize);
459  if(spApi->luiPpptTableLength == (luint)APG_MAX_AINT){
460  fprintf(spOut, "// table size = %"PRIuMAX" (overflow)\n", spApi->luiPpptTableLength);
461  }else{
462  fprintf(spOut, "// table size = %"PRIuMAX" (bytes)\n", spApi->luiPpptTableLength);
463  }
464  fprintf(spOut, "\n");
465  fprintf(spOut, "// GRAMMAR\n");
466  fprintf(spOut, "// rules = %"PRIuMAX"\n", (luint)spApi->uiRuleCount);
467  fprintf(spOut, "// UDTs = %"PRIuMAX"\n", (luint)spApi->uiUdtCount);
468  fprintf(spOut, "// opcodes = %"PRIuMAX"\n", (luint)spApi->uiOpcodeCount);
469  fprintf(spOut, "// --- ABNF original opcodes\n");
470  fprintf(spOut, "// ALT = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_ALT]);
471  fprintf(spOut, "// CAT = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_CAT]);
472  fprintf(spOut, "// REP = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_REP]);
473  fprintf(spOut, "// RNM = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_RNM]);
474  fprintf(spOut, "// TRG = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_TRG]);
475  fprintf(spOut, "// TLS = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_TLS]);
476  fprintf(spOut, "// TBS = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_TBS]);
477  fprintf(spOut, "// --- SABNF opcodes\n");
478  fprintf(spOut, "// UDT = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_UDT]);
479  fprintf(spOut, "// AND = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_AND]);
480  fprintf(spOut, "// NOT = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_NOT]);
481  fprintf(spOut, "// BKR = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_BKR]);
482  fprintf(spOut, "// BKA = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_BKA]);
483  fprintf(spOut, "// BKN = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_BKN]);
484  fprintf(spOut, "// ABG = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_ABG]);
485  fprintf(spOut, "// AEN = %"PRIuMAX"\n", (luint)uiaOpCounts[ID_AEN]);
486  fprintf(spOut, "\n");
487 
488  // original grammar
489  fprintf(spOut, "// ;original grammar\n");
490  luint luiLen = 0;
491  spLine = spLinesFirst(spApi->vpLines);
492  while(spLine){
493  LUINT_MAX(luiLen, spLine->uiTextLength);
494  spLine = spLinesNext(spApi->vpLines);
495  }
496  luiLen += 10;
497  if(spApi->cpLineBuffer){
498  vMemFree(spApi->vpMem, spApi->cpLineBuffer);
499  }
500  spApi->cpLineBuffer = (char*)vpMemAlloc(spApi->vpMem, (aint)(sizeof(char) * (size_t)luiLen));
501  cpLineBuffer = spApi->cpLineBuffer;
502  char* cpGrammar = (char*)vpVecFirst(spApi->vpVecInput);
503  if(!cpGrammar){
504  fclose(spOut);
505  XTHROW(spApi->spException, "input vector should not be empty here");
506  }
507  cpLineBuffer[0] = '/';
508  cpLineBuffer[1] = '/';
509  cpLineBuffer[2] = ' ';
510  spLine = spLinesFirst(spApi->vpLines);
511  while(spLine){
512  memcpy((void*)&cpLineBuffer[3], (void*)&cpGrammar[spLine->uiCharIndex], spLine->uiTextLength);
513  cpLineBuffer[spLine->uiTextLength + 3] = 0;
514  fprintf(spOut, "%s\n", cpLineBuffer);
515  spLine = spLinesNext(spApi->vpLines);
516  }
517  fprintf(spOut, "\n");
518 }
519 
520 static void* vpOutputParser(api* spApi){
521  luint* luipInit = NULL;
522  if(spApi->luipInit){
523  vMemFree(spApi->vpMem, spApi->luipInit);
524  }
525  spApi->luipInit = luipMakeInitData(spApi);
526  luipInit = spApi->luipInit;
527  init_hdr_out* spHdr = (init_hdr_out*)luipInit;
528  parser_init sParserInit = {};
529  sParserInit.uiSizeofAchar = (aint)spHdr->luiSizeofAchar;
530  sParserInit.uiSizeofUint = (aint)spHdr->luiSizeofUint;
531 
532  // the string table
533  sParserInit.cpStringTable = spApi->cpStringTable;
534  sParserInit.uiStringTableLength = spApi->uiStringTableLength;
535 
536  // the PPPT maps
537  sParserInit.ucpPpptTable = spApi->ucpPpptTable;
538  sParserInit.uiPpptTableLength = spApi->luiPpptTableLength;
539 
540  // the achar table
541  sParserInit.vpAcharTable = vpMakeAcharTable(spApi, spApi->luiAcharMax,
542  spApi->luipAcharTable, spApi->uiAcharTableLength);
543  sParserInit.uiAcharTableLength = spApi->uiAcharTableLength;
544 
545  sParserInit.uiParserInitLength = (aint)spHdr->luiSizeInInts;
546  sParserInit.vpParserInit = vpMakeParserInit(spApi, spHdr->luiUintMax, luipInit, sParserInit.uiParserInitLength);
547  return vpParserAllocCtor(spApi->spException, &sParserInit, APG_TRUE);
548 }
549 
550 static luint* luipMakeInitData(api* spApi){
551  luint* luipUdts = NULL;
552  luint* luipRules = NULL;
553  luint* luipOpcodes = NULL;
554  luint* luipInit = NULL;
555  aint ui;
556  luint lui, luiLen, luiUdtLen, luiRuleLen, luiOpLen;
557  api_udt* spUdt;
558  api_rule* spRule;
559  api_op* spOp;
560  aint uiRuleCount = spApi->uiRuleCount;
561  aint uiUdtCount = spApi->uiUdtCount;
562  aint uiOpcodeCount = spApi->uiOpcodeCount;
563  api_attr_w* spAttrs = ((attrs_ctx*)spApi->vpAttrsCtx)->spAttrs;
564  init_hdr_out sHdr = {};
565  parser_init sParserInit = {};
566  aint uiaOpCounts[ID_GEN];
567  memset((void*)&uiaOpCounts[0], 0, sizeof(uiaOpCounts));
568 
569  if(uiUdtCount){
570  luipUdts = (luint*)vpMemAlloc(spApi->vpMem, (aint)(sizeof(luint) * uiUdtCount * 5));
571  }
572  luipRules = (luint*)vpMemAlloc(spApi->vpMem, (aint)(sizeof(luint) * uiRuleCount * 7));
573  luipOpcodes = (luint*)vpMemAlloc(spApi->vpMem, (aint)(sizeof(luint) * uiOpcodeCount * 5));
574 
575  // the string table
576  sParserInit.cpStringTable = spApi->cpStringTable;
577  sParserInit.uiStringTableLength = spApi->uiStringTableLength;
578 
579  // the PPPT maps
580  sParserInit.ucpPpptTable = spApi->ucpPpptTable;
581  sParserInit.uiPpptTableLength = spApi->luiPpptTableLength;
582 
583  sParserInit.uiAcharTableLength = spApi->uiAcharTableLength;
584  sParserInit.uiSizeofAchar = uiGetSize(spApi->luiAcharMax);
585 
586  luiUdtLen = 0;
587  if(spApi->uiUdtCount){
588  // convert UDTs
589  spUdt = spApi->spUdts;
590  for(ui = 0; ui < spApi->uiUdtCount; ui++, spUdt++){
591  luipUdts[luiUdtLen++] = (luint)spUdt->uiIndex;
592  luipUdts[luiUdtLen++] = (luint)(spUdt->cpName - spApi->cpStringTable);
593  luipUdts[luiUdtLen++] = (luint)spUdt->uiEmpty;
594  }
595  }
596 
597  // convert rules
598  luiRuleLen = 0;
599  spRule = spApi->spRules;
600  for(ui = 0; ui < uiRuleCount; ui++, spRule++){
601  luipRules[luiRuleLen++] = (luint)spRule->uiIndex;
602  luipRules[luiRuleLen++] = (luint)spRule->uiPpptIndex;
603  luipRules[luiRuleLen++] = (luint)(spRule->cpName - spApi->cpStringTable);
604  luipRules[luiRuleLen++] = (luint)spRule->uiOpOffset;
605  luipRules[luiRuleLen++] = (luint)spRule->uiOpCount;
606  luipRules[luiRuleLen++] = (luint)spAttrs[ui].bEmpty;
607  }
608 
609  // convert opcodes
610  luiOpLen = 0;
611  spOp = spApi->spOpcodes;
612  for(ui = 0; ui < uiOpcodeCount; ui++, spOp++){
613  luipOpcodes[luiOpLen++] = spOp->uiId;
614  uiaOpCounts[spOp->uiId]++;
615  switch (spOp->uiId) {
616  case ID_ALT:
617  case ID_CAT:
618  luipOpcodes[luiOpLen++] = (luint)spOp->uiPpptIndex;
619  luipOpcodes[luiOpLen++] = (luint)(spOp->uipChildIndex - spApi->uipChildIndexTable);
620  luipOpcodes[luiOpLen++] = (luint)spOp->uiChildCount;
621  break;
622  case ID_REP:
623  case ID_TRG:
624  luipOpcodes[luiOpLen++] = (luint)spOp->uiPpptIndex;
625  luipOpcodes[luiOpLen++] = spOp->luiMin;
626  luipOpcodes[luiOpLen++] = spOp->luiMax;
627  break;
628  case ID_RNM:
629  luipOpcodes[luiOpLen++] = (luint)spApi->spRules[spOp->uiIndex].uiPpptIndex;
630  luipOpcodes[luiOpLen++] = (luint)spOp->uiIndex;
631  break;
632  case ID_TLS:
633  case ID_TBS:
634  luipOpcodes[luiOpLen++] = (luint)spOp->uiPpptIndex;
635  luipOpcodes[luiOpLen++] = (luint)(spOp->luipAchar- spApi->luipAcharTable);
636  luipOpcodes[luiOpLen++] = (luint)spOp->uiAcharLength;
637  break;
638  case ID_UDT:
639  luipOpcodes[luiOpLen++] = (luint)spOp->uiIndex;
640  luipOpcodes[luiOpLen++] = (luint)spOp->uiEmpty;
641  break;
642  case ID_BKR:
643  luipOpcodes[luiOpLen++] = (luint)spOp->uiBkrIndex;
644  luipOpcodes[luiOpLen++] = (luint)spOp->uiCase;
645  luipOpcodes[luiOpLen++] = (luint)spOp->uiMode;
646  break;
647  case ID_AND:
648  case ID_NOT:
649  luipOpcodes[luiOpLen++] = (luint)spOp->uiPpptIndex;
650  break;
651  case ID_BKA:
652  case ID_BKN:
653  case ID_ABG:
654  case ID_AEN:
655  break;
656  default:
657  XTHROW(spApi->spException, "unrecognized operator ID");
658  }
659  }
660 
661  // fill in the header
662  sHdr.luiSizeInInts = (luint)(sizeof(sHdr)/sizeof(luint)) +
663  luiRuleLen + luiUdtLen + luiOpLen + (luint)spApi->uiChildIndexTableLength;
664  sHdr.luiAcharMin = spApi->luiAcharMin;
665  sHdr.luiAcharMax = spApi->luiAcharMax;
666  sHdr.luiSizeofAchar = uiGetSize(sHdr.luiAcharMax);
667  sHdr.luiRuleCount = uiRuleCount;
668  sHdr.luiUdtCount = uiUdtCount;
669  sHdr.luiOpcodeCount = uiOpcodeCount;
670  sHdr.luiMapCount = spApi->luiPpptMapCount;
671  sHdr.luiMapSize = spApi->luiPpptMapSize;
672  sHdr.luiVersionOffset = spApi->uiVersionOffset;
674  sHdr.luiLicenseOffset = spApi->uiLicenseOffset;
675  sHdr.luiChildListOffset = (luint)(sizeof(sHdr)/sizeof(luint));
678  sHdr.luiRulesLength = (luint)luiRuleLen;
679  sHdr.luiUdtsOffset = sHdr.luiRulesOffset + sHdr.luiRulesLength;
680  sHdr.luiUdtsLength = luiUdtLen;
681  sHdr.luiOpcodesOffset = sHdr.luiUdtsOffset + sHdr.luiUdtsLength;
682  sHdr.luiOpcodesLength = luiOpLen;
683  LUINT_MAX(sHdr.luiUintMax, sHdr.luiSizeInInts);
684  LUINT_MAX(sHdr.luiUintMax, sHdr.luiAcharMax);
685  LUINT_MAX(sHdr.luiUintMax, sHdr.luiSizeofAchar);
686  LUINT_MAX(sHdr.luiUintMax, sHdr.luiRuleCount);
687  LUINT_MAX(sHdr.luiUintMax, sHdr.luiUdtCount);
688  LUINT_MAX(sHdr.luiUintMax, sHdr.luiOpcodeCount);
694  LUINT_MAX(sHdr.luiUintMax, sHdr.luiRulesOffset);
695  LUINT_MAX(sHdr.luiUintMax, sHdr.luiRulesLength);
696  LUINT_MAX(sHdr.luiUintMax, sHdr.luiUdtsOffset);
697  LUINT_MAX(sHdr.luiUintMax, sHdr.luiUdtsLength);
700  if(uiUdtCount){
701  for(lui = 0; lui < luiUdtLen; lui++){
702  LUINT_MAX(sHdr.luiUintMax, luipUdts[lui]);
703  }
704  }
705  for(lui = 0; lui < luiRuleLen; lui++){
706  LUINT_MAX(sHdr.luiUintMax, luipRules[lui]);
707  }
708  for(lui = 0; lui < luiOpLen; lui++){
709  LUINT_MAX(sHdr.luiUintMax, luipOpcodes[lui]);
710  }
714 
715  sParserInit.uiSizeofUint= uiGetSize(sHdr.luiUintMax);
716  sHdr.luiSizeofUint = (luint)sParserInit.uiSizeofUint;
717  luipInit = (luint*)vpMemAlloc(spApi->vpMem, (aint)(sizeof(luint) * sHdr.luiSizeInInts));
718  luiLen = 0;
719  luipInit[luiLen++] = sHdr.luiSizeInInts;
720  luipInit[luiLen++] = sHdr.luiAcharMin;
721  luipInit[luiLen++] = sHdr.luiAcharMax;
722  luipInit[luiLen++] = sHdr.luiSizeofAchar;
723  luipInit[luiLen++] = sHdr.luiUintMax;
724  luipInit[luiLen++] = sHdr.luiSizeofUint;
725  luipInit[luiLen++] = sHdr.luiRuleCount;
726  luipInit[luiLen++] = sHdr.luiUdtCount;
727  luipInit[luiLen++] = sHdr.luiOpcodeCount;
728  luipInit[luiLen++] = sHdr.luiMapCount;
729  luipInit[luiLen++] = sHdr.luiMapSize;
730  luipInit[luiLen++] = sHdr.luiVersionOffset;
731  luipInit[luiLen++] = sHdr.luiCopyrightOffset;
732  luipInit[luiLen++] = sHdr.luiLicenseOffset;
733  luipInit[luiLen++] = sHdr.luiChildListOffset;
734  luipInit[luiLen++] = sHdr.luiChildListLength;
735  luipInit[luiLen++] = sHdr.luiRulesOffset;
736  luipInit[luiLen++] = sHdr.luiRulesLength;
737  luipInit[luiLen++] = sHdr.luiUdtsOffset;
738  luipInit[luiLen++] = sHdr.luiUdtsLength;
739  luipInit[luiLen++] = sHdr.luiOpcodesOffset;
740  luipInit[luiLen++] = sHdr.luiOpcodesLength;
741  for(lui = 0; lui < spApi->uiChildIndexTableLength; lui++){
742  luipInit[luiLen++] = (luint)spApi->uipChildIndexTable[lui];
743  }
744  for(lui = 0; lui < luiRuleLen; lui++){
745  luipInit[luiLen++] = luipRules[lui];
746  }
747  for(lui = 0; lui < luiUdtLen; lui++){
748  luipInit[luiLen++] = luipUdts[lui];
749  }
750  for(lui = 0; lui < luiOpLen; lui++){
751  luipInit[luiLen++] = luipOpcodes[lui];
752  }
753  if(luiLen != sHdr.luiSizeInInts){
754  vMemFree(spApi->vpMem, (void*)luipUdts);
755  vMemFree(spApi->vpMem, (void*)luipRules);
756  vMemFree(spApi->vpMem, (void*)luipOpcodes);
757  vMemFree(spApi->vpMem, (void*)luipInit);
758  XTHROW(spApi->spException,
759  "sanity check - calculated and actual parser initialization lengths not equal");
760  }
761  vMemFree(spApi->vpMem, (void*)luipRules);
762  vMemFree(spApi->vpMem, (void*)luipOpcodes);
763  spApi->luipInit = luipInit;
764  return luipInit;
765 }
766 
767 static aint uiLastChar(char cCharToFind, const char* cpString) {
768  aint uiLast = APG_UNDEFINED;
769  aint ui = 0;
770  aint uiLen = (aint) strlen(cpString);
771  for (; ui < uiLen; ui++) {
772  if (cpString[ui] == cCharToFind) {
773  uiLast = ui;
774  }
775  }
776  return uiLast;
777 }
778 static abool bSetFileExtension(const char* cpPathName, const char* cpExt, char* cpBuffer, aint uiBufferLength) {
779  abool bReturn = APG_FAILURE;
780  if (cpPathName && cpExt && cpBuffer && uiBufferLength) {
781  char cDot = '.';
782  while (APG_TRUE) {
783  cpBuffer[0] = 0;
784  if(cpPathName[0] == 0){
785  // path name is empty
786  break;
787  }
788  if((cpPathName[0] == cDot) && (cpPathName[1] == cDot) && (cpPathName[2] == cDot)){
789  // three leading dots is an error
790  break;
791  }
792  aint uiDot;
793  uiDot = uiLastChar(cDot, cpPathName);
794  if ((uiDot == APG_UNDEFINED) || (uiDot == 0) || (uiDot == 1)) {
795  uiDot = (aint) strlen(cpPathName);
796  }
797  if((uiDot + strlen(cpExt) + 2) > uiBufferLength){
798  // user's buffer is too small
799  break;
800  }
801  aint ui = 0;
802  for (; ui < uiDot; ui++) {
803  cpBuffer[ui] = cpPathName[ui];
804  }
805  if(strlen(cpExt)){
806  cpBuffer[ui++] = cDot;
807  cpBuffer[ui] = 0;
808  strcat(cpBuffer, cpExt);
809  }
810  bReturn = APG_TRUE;
811  break;
812  }
813  }
814  return bReturn;
815 }
816 static abool bGetFileName(const char* cpPathName, char* cpBuffer, aint uiBufferLength) {
817  abool bReturn = APG_FAILURE;
818  if (cpPathName && cpBuffer && uiBufferLength) {
819  char cDot = '.';
820  char cSlash = '/';
821  char cBackSlash = '\\';
822  while (APG_TRUE) {
823  cpBuffer[0] = 0;
824  if(cpPathName[0] == 0){
825  // path name is empty
826  break;
827  }
828  if((cpPathName[0] == cDot) && (cpPathName[1] == cDot) && (cpPathName[2] == cDot)){
829  // three leading dots is an error
830  break;
831  }
832  aint uiDivider;
833  aint uiDot;
834  // try linux
835  uiDivider = uiLastChar(cSlash, cpPathName);
836  if (uiDivider == APG_UNDEFINED) {
837  // try windows
838  uiDivider = uiLastChar(cBackSlash, cpPathName);
839  }
840  if (uiDivider == APG_UNDEFINED) {
841  uiDivider = 0;
842  }else{
843  uiDivider++;
844  }
845  uiDot = uiLastChar(cDot, cpPathName);
846  if ((uiDot == APG_UNDEFINED) || (uiDot == 0) || (uiDot == 1)) {
847  uiDot = (aint) strlen(cpPathName) + 1;
848  }
849  aint uiLen = uiDot - uiDivider;
850  if (uiLen >= uiBufferLength) {
851  // not enough room in caller's buffer for the result
852  break;
853  }
854  aint ui = uiDivider;
855  aint uii = 0;
856  for (; ui < uiDot; ui++, uii++) {
857  cpBuffer[uii] = cpPathName[ui];
858  }
859  cpBuffer[uii] = 0;
860  bReturn = APG_TRUE;
861  break;
862  }
863  }
864  return bReturn;
865 }
866 
867 static char cToUpper(char cChar){
868  if(cChar >= 97 && cChar <= 122){
869  return cChar - 32;
870  }
871  return cChar;
872 }
873 static char cToLower(char cChar){
874  if(cChar >= 65 && cChar <= 90){
875  return cChar + 32;
876  }
877  return cChar;
878 }
879 static abool bIsLetter(char cLetter){
880  if(cLetter >= 65 && cLetter <= 90){
881  return APG_TRUE;
882  }
883  if(cLetter >= 97 && cLetter <= 122){
884  return APG_TRUE;
885  }
886  if(cLetter >= 48 && cLetter <= 57){
887  return APG_TRUE;
888  }
889  return APG_FALSE;
890 }
891 static abool bNameToCaps(const char* cpPrefix, const char* cpName, char* cpBuffer, aint uiBufferLength){
892  char cUnder = '_';
893  aint uiPreLen = (aint)strlen(cpPrefix);
894  aint uiNameLen = (aint)strlen(cpName);
895  aint ui, uii;
896  if((uiPreLen + uiNameLen + 1) >= uiBufferLength){
897  return APG_FAILURE;
898  }
899  uii = 0;
900  if(uiPreLen){
901  for(ui = 0; ui < uiPreLen; ui++){
902  if(bIsLetter(cpPrefix[ui])){
903  cpBuffer[ui] = cToUpper(cpPrefix[ui]);
904  }else{
905  cpBuffer[ui] = cUnder;
906  }
907  }
908  cpBuffer[ui] = cUnder;
909  uii = ui + 1;
910  }
911  if(uiNameLen){
912  for(ui = 0; ui < uiNameLen; ui++, uii++){
913  if(bIsLetter(cpName[ui])){
914  cpBuffer[uii] = cToUpper(cpName[ui]);
915  }else{
916  cpBuffer[uii] = cUnder;
917  }
918  }
919  }
920  cpBuffer[uii] = 0;
921  return APG_TRUE;
922 }
923 
924 static abool bNameToCamelCase(const char* cpPrefix, const char* cpName, char* cpBuffer, aint uiBufferLength){
925  aint uiPreLen = (aint)strlen(cpPrefix);
926  aint uiNameLen = (aint)strlen(cpName);
927  aint ui, uiCount;
928  abool bCamel = APG_FALSE;
929  if((uiPreLen + uiNameLen) >= uiBufferLength){
930  return APG_FAILURE;
931  }
932  uiCount = 0;
933  bCamel = APG_FALSE;
934  for(ui = 0; ui < uiPreLen; ui++){
935  if(!bIsLetter(cpPrefix[ui])){
936  bCamel = APG_TRUE;
937  }else{
938  if(bCamel){
939  cpBuffer[uiCount] = cToUpper(cpPrefix[ui]);
940  bCamel = APG_FALSE;
941  }else{
942  cpBuffer[uiCount] = cToLower(cpPrefix[ui]);
943  }
944  uiCount++;
945  }
946  }
947  ui = 0;
948  bCamel = APG_TRUE;
949  for(ui = 0; ui < uiNameLen; ui++){
950  if(!bIsLetter(cpName[ui])){
951  bCamel = APG_TRUE;
952  }else{
953  if(bCamel){
954  cpBuffer[uiCount] = cToUpper(cpName[ui]);
955  bCamel = APG_FALSE;
956  }else{
957  cpBuffer[uiCount] = cToLower(cpName[ui]);
958  }
959  uiCount++;
960  }
961  }
962  cpBuffer[uiCount] = 0;
963  return APG_TRUE;
964 }
965 
966 static int iCompRule(const void* vpL, const void* vpR) {
967  api_rule* spL = (api_rule*) vpL;
968  api_rule* spR = (api_rule*) vpR;
969  aint uiLenL = strlen(spL->cpName);
970  aint uiLenR = strlen(spR->cpName);
971  char l, r;
972  char* cpL = spL->cpName;
973  char* cpR = spR->cpName;
974  aint uiLesser = uiLenL < uiLenR ? uiLenL : uiLenR;
975  while (uiLesser--) {
976  l = *cpL;
977  if (l >= 65 && l <= 90) {
978  l += 32;
979  }
980  r = *cpR;
981  if (r >= 65 && r <= 90) {
982  r += 32;
983  }
984  if (l < r) {
985  return -1;
986  }
987  if (l > r) {
988  return 1;
989  }
990  cpL++;
991  cpR++;
992  }
993  if (uiLenL < uiLenR) {
994  return -1;
995  }
996  if (uiLenL > uiLenR) {
997  return 1;
998  }
999  return 0;
1000 }
1001 
1002 static int iCompUdt(const void* vpL, const void* vpR) {
1003  api_udt* spL = (api_udt*) vpL;
1004  api_udt* spR = (api_udt*) vpR;
1005  aint uiLenL = strlen(spL->cpName);
1006  aint uiLenR = strlen(spR->cpName);
1007  char l, r;
1008  char* cpL = spL->cpName;
1009  char* cpR = spR->cpName;
1010  aint uiLesser = uiLenL < uiLenR ? uiLenL : uiLenR;
1011  while (uiLesser--) {
1012  l = *cpL;
1013  if (l >= 65 && l <= 90) {
1014  l += 32;
1015  }
1016  r = *cpR;
1017  if (r >= 65 && r <= 90) {
1018  r += 32;
1019  }
1020  if (l < r) {
1021  return -1;
1022  }
1023  if (l > r) {
1024  return 1;
1025  }
1026  cpL++;
1027  cpR++;
1028  }
1029  if (uiLenL < uiLenR) {
1030  return -1;
1031  }
1032  if (uiLenL > uiLenR) {
1033  return 1;
1034  }
1035  return 0;
1036 }
1037 static void vPrintChars(FILE* spOut, const uint8_t* ucpChars, aint uiLength){
1038  aint ui = 0;
1039  aint uiNewLine;
1040  aint uiEnd = (OUTPUT_LINE_LENGTH) - 1;
1041  for(; ui < uiLength; ui++){
1042  if(ui == 0){
1043  fprintf(spOut, " %d", ucpChars[ui]);
1044  }else{
1045  fprintf(spOut, ",%d", ucpChars[ui]);
1046  }
1047  uiNewLine = ui % OUTPUT_LINE_LENGTH;
1048  if(uiNewLine == uiEnd){
1049  fprintf(spOut, "\n");
1050  }
1051  }
1052 }
1053 static void vPrintLongs(FILE* spOut, const luint* luiVals, aint uiLength){
1054  aint ui = 0;
1055  aint uiNewLine;
1056  for(; ui < uiLength; ui++){
1057  if(ui == 0){
1058  if(luiVals[ui] == (luint)-1){
1059  fprintf(spOut, " -1");
1060  }else{
1061  fprintf(spOut, " %"PRIuMAX"", luiVals[ui]);
1062  }
1063  }else{
1064  if(luiVals[ui] == (luint)-1){
1065  fprintf(spOut, ",-1");
1066  }else{
1067  fprintf(spOut, ",%"PRIuMAX"", luiVals[ui]);
1068  }
1069  uiNewLine = ui % OUTPUT_LINE_LENGTH;
1070  if(!uiNewLine){
1071  fprintf(spOut, "\n");
1072  }
1073  }
1074  }
1075 }
1076 
1077 static aint uiGetSize(luint luiValue){
1078  if(luiValue <= 0xFF){
1079  return 1;
1080  }
1081  if(luiValue <= 0xFFFF){
1082  return 2;
1083  }
1084  if(luiValue <= 0xFFFFFFFF){
1085  return 4;
1086  }
1087  return 8;
1088 }
1089 
1090 static const char* cpGetType(luint luiValue){
1091  if(luiValue <= 0xFF){
1092  return s_cpUchar;
1093  }
1094  if(luiValue <= 0xFFFF){
1095  return s_cpUshort;
1096  }
1097  if(luiValue <= 0xFFFFFFFF){
1098  return s_cpUint;
1099  }
1100  return s_cpUlong;
1101 }
1102 
1103 static void* vpMakeParserInit(api* spApi, luint luiUintMax, luint* luipData, aint uiLen){
1104  aint uiSize = uiGetSize(luiUintMax);
1105  aint ui = 0;
1106  if(uiSize == 1){
1107  spApi->vpOutputParserInit = vpMemAlloc(spApi->vpMem, uiLen);
1108  uint8_t* pChars = (uint8_t*)spApi->vpOutputParserInit;
1109  for(; ui < uiLen; ui++){
1110  pChars[ui] = (uint8_t)luipData[ui];
1111  }
1112  }else if(uiSize == 2){
1113  spApi->vpOutputParserInit = vpMemAlloc(spApi->vpMem, (uiLen * 2));
1114  uint16_t* pChars = (uint16_t*)spApi->vpOutputParserInit;
1115  for(; ui < uiLen; ui++){
1116  if(ui == 1750){
1117  pChars[ui] = (uint16_t)luipData[ui];
1118  }
1119  pChars[ui] = (uint16_t)luipData[ui];
1120  }
1121  }else if(uiSize == 4){
1122  spApi->vpOutputParserInit = vpMemAlloc(spApi->vpMem, (uiLen * 4));
1123  uint32_t* pChars = (uint32_t*)spApi->vpOutputParserInit;
1124  for(; ui < uiLen; ui++){
1125  pChars[ui] = (uint32_t)luipData[ui];
1126  }
1127  }else if(uiSize == 8){
1128  spApi->vpOutputParserInit = vpMemAlloc(spApi->vpMem, (uiLen * 8));
1129  uint64_t* pChars = (uint64_t*)spApi->vpOutputParserInit;
1130  for(; ui < uiLen; ui++){
1131  pChars[ui] = (uint64_t)luipData[ui];
1132  }
1133  }
1134  return spApi->vpOutputParserInit;
1135 }
1136 static void* vpMakeAcharTable(api* spApi, luint luiAcharMax, luint* luipTable, aint uiLen){
1137  aint uiSize = uiGetSize(luiAcharMax);
1138  aint ui = 0;
1139  if(uiSize == 1){
1140  spApi->vpOutputAcharTable = vpMemAlloc(spApi->vpMem, uiLen);
1141  uint8_t* pChars = (uint8_t*)spApi->vpOutputAcharTable;
1142  for(; ui < uiLen; ui++){
1143  pChars[ui] = (uint8_t)luipTable[ui];
1144  }
1145  }else if(uiSize == 2){
1146  spApi->vpOutputAcharTable = vpMemAlloc(spApi->vpMem, (uiLen * 2));
1147  uint16_t* pChars = (uint16_t*)spApi->vpOutputAcharTable;
1148  for(; ui < uiLen; ui++){
1149  pChars[ui] = (uint16_t)luipTable[ui];
1150  }
1151  }else if(uiSize == 4){
1152  spApi->vpOutputAcharTable = vpMemAlloc(spApi->vpMem, (uiLen * 4));
1153  uint32_t* pChars = (uint32_t*)spApi->vpOutputAcharTable;
1154  for(; ui < uiLen; ui++){
1155  pChars[ui] = (uint32_t)luipTable[ui];
1156  }
1157  }else if(uiSize == 8){
1158  spApi->vpOutputAcharTable = vpMemAlloc(spApi->vpMem, (uiLen * 8));
1159  uint64_t* pChars = (uint64_t*)spApi->vpOutputAcharTable;
1160  for(; ui < uiLen; ui++){
1161  pChars[ui] = (uint64_t)luipTable[ui];
1162  }
1163  }
1164  return spApi->vpOutputAcharTable;
1165 }
1166 
1167 #ifdef TEST_NAMES
1168 static void vTestNames(){
1169  // test file names
1170  char* cpaNames[] = {
1171  "header.h", "../header", "linuxfolder/linuxname.zip", "D:\\windowsfolder\\windows.c",
1172  "noext", "./folder/foldernoext", ".hidden", ".hidden/folder/wayup.java", "", ".../error"
1173  };
1174  char caBuffer[128];
1175  aint uiBufferSize = 128;
1176  aint uiCount = sizeof(cpaNames)/sizeof(char*);
1177  aint ui;
1178  printf("TEST bGetFileName():\n");
1179  printf("path name: file name\n");
1180  for(ui = 0; ui < uiCount; ui++){
1181  if(bGetFileName(cpaNames[ui], caBuffer, uiBufferSize)){
1182  printf("'%s': '%s'\n", cpaNames[ui], caBuffer);
1183  }else{
1184  printf("'%s': failed\n", cpaNames[ui]);
1185  }
1186  }
1187 
1188  // test extensions
1189  char* cpaExt[] = {"h", "c", "", "longextension", "zip", "java", "cpp", "hpp", "empty", "exterror"};
1190  printf("\n");
1191  printf("TEST bbSetFileExtension():\n");
1192  printf("file name: extension: added\n");
1193  for(ui = 0; ui < uiCount; ui++){
1194  if(bSetFileExtension(cpaNames[ui], cpaExt[ui], caBuffer, uiBufferSize)){
1195  printf("'%s': '%s': '%s'\n", cpaNames[ui], cpaExt[ui], caBuffer);
1196  }else{
1197  printf("'%s': '%s': failed\n", cpaNames[ui], cpaExt[ui]);
1198  }
1199  }
1200 
1201  // test upper
1202  char* cpaUppers[] = {
1203  "file-name", "text-type", "_type-to-", "_file_name_",
1204  "UPPER_CASE", "lower_case", ".hidden.h", ".hidden/folder/wayup.java"
1205  };
1206  uiCount = sizeof(cpaUppers)/sizeof(char*);
1207  printf("\n");
1208  printf("TEST bNameToCaps():\n");
1209  printf("prefix: name: UPPER\n");
1210  char* cpPrefix = "my-Pre_Fix";
1211  for(ui = 0; ui < uiCount; ui++){
1212  if(bNameToCaps(cpPrefix, cpaUppers[ui], caBuffer, uiBufferSize)){
1213  printf("'%s': '%s': '%s'\n", cpPrefix, cpaUppers[ui], caBuffer);
1214  }else{
1215  printf("'%s': '%s': failed\n", cpPrefix, cpaUppers[ui]);
1216  }
1217  }
1218 
1219  //test camel case
1220  char* cpaCamel[] = {
1221  "file-name", "text-type", "_type-to-", "_file_name_",
1222  "UPPER_CASE", "lower_case", ".hidden.h", ".hidden/folder/wayup.java"
1223  };
1224  uiCount = sizeof(cpaCamel)/sizeof(char*);
1225  printf("\n");
1226  printf("TEST bNameToCamelCase():\n");
1227  printf("prefix: name: CamelCase\n");
1228  cpPrefix = "ui";
1229  for(ui = 0; ui < uiCount; ui++){
1230  if(bNameToCamelCase(cpPrefix, cpaCamel[ui], caBuffer, uiBufferSize)){
1231  printf("'%s': '%s': '%s'\n", cpPrefix, cpaCamel[ui], caBuffer);
1232  }else{
1233  printf("'%s': '%s': failed\n", cpPrefix, cpaCamel[ui]);
1234  }
1235  }
1236 }
1237 #endif /* TEST_NAMES */
init_hdr_out::luiMapSize
luint luiMapSize
Definition: output.c:61
api::uiUdtCount
aint uiUdtCount
The number of UDTs referenced in the SABNF grammar.
Definition: apip.h:148
bApiValidate
abool bApiValidate(void *vpCtx)
Validates an API context pointer.
Definition: api.c:104
OUTPUT_LINE_LENGTH
#define OUTPUT_LINE_LENGTH
Controls the number of integers per line in the output source file.
Definition: output.c:78
api_op::uiPpptIndex
aint uiPpptIndex
Index to the PPPT map for this opcode.
Definition: apip.h:91
api_rule::uiIndex
aint uiIndex
index of this rule in the rule list
Definition: apip.h:57
api::spRules
api_rule * spRules
Points to an array of rule structures.
Definition: apip.h:145
APG_FAILURE
#define APG_FAILURE
Definition: apg.h:308
api_op::luiMax
luint luiMax
maximum value for REP and TRG opcodes
Definition: apip.h:85
ID_RNM
#define ID_RNM
rule name
Definition: parser.h:46
api::uiLicenseOffset
aint uiLicenseOffset
Offset into the string table for the License string.
Definition: apip.h:153
api::uiOpcodeCount
aint uiOpcodeCount
Number of opcodes.
Definition: apip.h:163
api_rule::uiPpptIndex
aint uiPpptIndex
Index to the PPPT map for this opcode.
Definition: apip.h:62
api::spOpcodes
api_op * spOpcodes
Pointer to the array of opcodes for the SANF grammar.
Definition: apip.h:162
parser_init::uiSizeofUint
uint32_t uiSizeofUint
Minimum size, in bytes, required for the basic parser unsigned integer, aint.
Definition: parserp.h:48
api_op::uiAcharLength
aint uiAcharLength
number of characters in TLS/TBS strings
Definition: apip.h:87
attrs_ctx
The API will construct an attributes object. This is the attribute object's context.
Definition: attributes.h:41
api::vpLog
void * vpLog
A msglog context for error reporting.
Definition: apip.h:179
api::vpOutputParserInit
void * vpOutputParserInit
Storage for variable integer width output parser init data.
Definition: apip.h:132
api_attr_w
Working attribute information about a each rule.
Definition: apip.h:99
api::luipInit
luint * luipInit
Storage variable for intermediate parser initialization data.
Definition: apip.h:133
parser_init::cpStringTable
const char * cpStringTable
Pointer to the string table.
Definition: parserp.h:53
init_hdr_out::luiRulesOffset
luint luiRulesOffset
Definition: output.c:67
ID_ALT
#define ID_ALT
alternation
Definition: parser.h:43
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
parser_init::uiAcharTableLength
uint32_t uiAcharTableLength
Length of this data's alphabet character table.
Definition: parserp.h:50
api_rule
API information about each rule.
Definition: apip.h:55
init_hdr_out::luiUdtsLength
luint luiUdtsLength
Definition: output.c:70
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
vApiOutput
void vApiOutput(void *vpCtx, const char *cpOutput)
Generate a source and header file that can be used to construct a parser for the specified SABNF gram...
Definition: output.c:152
api::bInputValid
abool bInputValid
APG_TRUE if theer is input and it has been validated, APG_FALSE otherwise.
Definition: apip.h:182
api_op::uiChildCount
aint uiChildCount
number of children for this ALT or CAT operator
Definition: apip.h:83
api::vpAttrsCtx
void * vpAttrsCtx
context handle to the attributes object
Definition: apip.h:130
api::cpStringTable
char * cpStringTable
Pointer to a list of null-terminated ASCII strings representing the rule and UDT names.
Definition: apip.h:149
init_hdr_out::luiMapCount
luint luiMapCount
Definition: output.c:60
ID_NOT
#define ID_NOT
negative look ahead
Definition: parser.h:57
ID_AND
#define ID_AND
positive look ahead
Definition: parser.h:56
api_op::luipAchar
luint * luipAchar
pointer to the first character in the achar table for this TLS/TBS operator
Definition: apip.h:86
parser_init::uiSizeofAchar
uint32_t uiSizeofAchar
Minimum size, in bytes, required for the alphabet characters, achar.
Definition: parserp.h:47
parser_init::uiParserInitLength
uint32_t uiParserInitLength
Length of the parser initialization data.
Definition: parserp.h:52
parser_init::uiStringTableLength
uint32_t uiStringTableLength
Length of this data's string table.
Definition: parserp.h:49
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
parser_init
The initialization information generated by APG.
Definition: parserp.h:46
init_hdr_out::luiUdtsOffset
luint luiUdtsOffset
Definition: output.c:69
api_op::luiMin
luint luiMin
minimum value for REP and TRG opcodes
Definition: apip.h:84
api::spUdts
api_udt * spUdts
Points to an array of UDT structures, if one or more UDTs are referenced in the SABNF grammar.
Definition: apip.h:147
parser_init::vpAcharTable
const void * vpAcharTable
Pointer to the alphabet character table or NULL if none. (Possible for small grammars....
Definition: parserp.h:55
api::uiRuleCount
aint uiRuleCount
The number of rules in the SABNF grammar and in the array.
Definition: apip.h:146
init_hdr_out::luiRulesLength
luint luiRulesLength
Definition: output.c:68
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
api::uipChildIndexTable
aint * uipChildIndexTable
Pointer to a list of child indexes. ALT & CAT operators have two or more children operators....
Definition: apip.h:159
ID_CAT
#define ID_CAT
concatenation
Definition: parser.h:44
api_op::uiMode
aint uiMode
ID_BKR_MODE_U of ID_BKR_MODE_P for BKR.
Definition: apip.h:89
vMsgsClear
void vMsgsClear(void *vpCtx)
Clears the object of all messages.
Definition: msglog.c:124
init_hdr_out::luiCopyrightOffset
luint luiCopyrightOffset
Definition: output.c:63
api::uiChildIndexTableLength
aint uiChildIndexTableLength
The number of indexes (integers) in the child index table.
Definition: apip.h:161
init_hdr_out::luiOpcodeCount
luint luiOpcodeCount
Definition: output.c:59
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
init_hdr_out::luiChildListLength
luint luiChildListLength
Definition: output.c:66
api::uiCopyrightOffset
aint uiCopyrightOffset
Offset into the string table for the Copyright string.
Definition: apip.h:155
ID_TRG
#define ID_TRG
terminal range
Definition: parser.h:47
api_udt::cpName
char * cpName
pointer to null-terminated string in the string table
Definition: apip.h:70
ID_REP
#define ID_REP
repetition
Definition: parser.h:45
api::vpLines
void * vpLines
Context pointer to a lines object.
Definition: apip.h:141
init_hdr_out::luiUdtCount
luint luiUdtCount
Definition: output.c:58
api::luiPpptMapCount
luint luiPpptMapCount
The number of operator maps in the table.
Definition: apip.h:172
init_hdr_out::luiChildListOffset
luint luiChildListOffset
Definition: output.c:65
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
api_op::uiCase
aint uiCase
ID_BKR_CASE_S or ID_BKR_CASE_I for BKR.
Definition: apip.h:88
api_op::uiIndex
aint uiIndex
index of this referenced rule or UDT
Definition: apip.h:80
api
The API context.
Definition: apip.h:123
api::luipAcharTable
luint * luipAcharTable
Pointer to the Achar Table - a table of all of the alphabet characters referenced by the terminal nod...
Definition: apip.h:157
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
init_hdr_out::luiOpcodesOffset
luint luiOpcodesOffset
Definition: output.c:71
parser_init::ucpPpptTable
const uint8_t * ucpPpptTable
Pointer to the PPPT or NULL if none.
Definition: parserp.h:54
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
LUINT_MAX
#define LUINT_MAX(x, y)
Replace x with y only if y > x.
Definition: output.c:83
api::bSyntaxValid
abool bSyntaxValid
APG_TRUE if the input syntax is valid, APG_FALSE otherwise.
Definition: apip.h:183
init_hdr_out::luiSizeofAchar
luint luiSizeofAchar
Definition: output.c:54
api_op
API information about each opcode.
Definition: apip.h:78
line::uiTextLength
aint uiTextLength
The number of characters in the line, excluding the line end characters.
Definition: lines.h:44
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
api_udt
API information about each UDT.
Definition: apip.h:69
ID_BKA
#define ID_BKA
positive look behind
Definition: parser.h:59
line
Defines the characteristics of a single line.
Definition: lines.h:40
ID_GEN
#define ID_GEN
general opcode (not SABNF). Serves to locate the ID in any opcode structure and must be larger than a...
Definition: parser.h:63
api::uiVersionOffset
aint uiVersionOffset
Offset into the string table for the Version Number string.
Definition: apip.h:151
spLinesNext
line * spLinesNext(void *vpCtx)
Returns the next line of text from the iterator.
Definition: lines.c:185
init_hdr_out
Header for the parser initialization data.
Definition: output.c:50
api::vpVecInput
void * vpVecInput
The (ASCII) input grammar files and/or strings accumulate here. Always a NULL-terminated string.
Definition: apip.h:137
init_hdr_out::luiUintMax
luint luiUintMax
Definition: output.c:55
api::vpOutputAcharTable
void * vpOutputAcharTable
Storage for variable character width output parser achar table.
Definition: apip.h:131
api::uiAcharTableLength
aint uiAcharTableLength
Number of alphabet characters in the Achar Table.
Definition: apip.h:158
api::luiPpptMapSize
luint luiPpptMapSize
The size, in bytes, of a single operator map.
Definition: apip.h:173
api::ucpPpptTable
uint8_t * ucpPpptTable
Pointer to the PPPT table of operator maps.
Definition: apip.h:170
api_op::uiId
aint uiId
type of opcode, ID_ALT, etc.
Definition: apip.h:79
ID_TLS
#define ID_TLS
terminal literal string
Definition: parser.h:49
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
spLinesFirst
line * spLinesFirst(void *vpCtx)
Initialize an iterator over the lines.
Definition: lines.c:170
vpApiOutputParser
void * vpApiOutputParser(void *vpCtx)
Generate a parser object directly from the specified SABNF grammar.
Definition: output.c:217
api_op::uiEmpty
aint uiEmpty
APG_TRUE if this UDT can be empty, APG_FALSE otherwise
Definition: apip.h:81
api::bUsePppt
abool bUsePppt
True of PPPT are being used.
Definition: apip.h:167
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
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
api_rule::cpName
char * cpName
pointer to null-terminated string in the string table
Definition: apip.h:56
api::uiStringTableLength
aint uiStringTableLength
The number of characters in the string table.
Definition: apip.h:150
init_hdr_out::luiLicenseOffset
luint luiLicenseOffset
Definition: output.c:64
api_udt::uiIndex
aint uiIndex
index of this UDT in the UDT list
Definition: apip.h:71
init_hdr_out::luiOpcodesLength
luint luiOpcodesLength
Definition: output.c:72
init_hdr_out::luiAcharMax
luint luiAcharMax
Definition: output.c:53
api::luiAcharMin
luint luiAcharMin
The minimum alphabet character referenced by the terminal nodes, TLS, TBL & TRG.
Definition: apip.h:174
parser_init::uiPpptTableLength
uint32_t uiPpptTableLength
Length of this data's PPPT.
Definition: parserp.h:51
api_op::uiBkrIndex
aint uiBkrIndex
if BKR, this is the index to the rule or UDT that is being back referenced
Definition: apip.h:90
api::vpMem
void * vpMem
Pointer to the memory context used for all memory allocations and exceptions thrown.
Definition: apip.h:126
api::luiAcharMax
luint luiAcharMax
The maximum alphabet character referenced by the terminal nodes, TLS, TBL & TRG.
Definition: apip.h:175
init_hdr_out::luiRuleCount
luint luiRuleCount
Definition: output.c:57
api_op::uipChildIndex
aint * uipChildIndex
pointer to the first child index of this ALT or CAT operator
Definition: apip.h:82
vpParserAllocCtor
void * vpParserAllocCtor(exception *spException, void *vpParserInit, abool bAllocateTables)
The parser constructor.
Definition: parser.c:88
init_hdr_out::luiVersionOffset
luint luiVersionOffset
Definition: output.c:62
ID_ABG
#define ID_ABG
anchor - beginning of string
Definition: parser.h:61
api::cpLineBuffer
char * cpLineBuffer
Storage variable for intermediate parser line data.
Definition: apip.h:134
api::spException
exception * spException
Definition: apip.h:125
init_hdr_out::luiAcharMin
luint luiAcharMin
Definition: output.c:52
api::bSemanticsValid
abool bSemanticsValid
APG_TRUE if the the input semantics are valid. That is, the opcodes for the parser have been generate...
Definition: apip.h:184
api_rule::uiOpOffset
aint uiOpOffset
offset into the opcode table to the first opcode of this rule
Definition: apip.h:58
init_hdr_out::luiSizeInInts
luint luiSizeInInts
Definition: output.c:51
api_udt::uiEmpty
aint uiEmpty
APG_TRUE if this UDT can be empty, APG_FALSE otherwise
Definition: apip.h:72
ID_TBS
#define ID_TBS
terminal binary string
Definition: parser.h:48
parser_init::vpParserInit
const void * vpParserInit
Pointer to the parser's initialization data.
Definition: parserp.h:56
api::luiPpptTableLength
luint luiPpptTableLength
The PPPT length.
Definition: apip.h:171
api_rule::uiOpCount
aint uiOpCount
the number of opcodes in this rule
Definition: apip.h:59
init_hdr_out::luiSizeofUint
luint luiSizeofUint
Definition: output.c:56
line::uiCharIndex
aint uiCharIndex
The zero-based index of the first character of the line.
Definition: lines.h:42
ID_AEN
#define ID_AEN
anchor - end of string
Definition: parser.h:62
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.