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 * *************************************************************************************/
85 #include <limits.h>
86 #include "../../utilities/utilities.h"
87 
88 #include "source.h"
89 
90 static const char* cpMakeFileName(char* cpBuffer, const char* cpBase, const char* cpDivider, const char* cpName){
91  strcpy(cpBuffer, cpBase);
92  strcat(cpBuffer, cpDivider);
93  strcat(cpBuffer, cpName);
94  return cpBuffer;
95 }
96 
97 static char s_caBuf[PATH_MAX];
98 
99 static char* s_cpDescription =
100  "Illustrate the construction and use of the data formatting utility object.";
101 
102 static char* s_cppCases[] = {
103  "Display application information.",
104  "Display 8-bit bytes, illustrating indentation and limits.",
105  "Display a mix of ASCII and non-ASCII bytes in all formats.",
106  "Display Unicode data in the Unicode format.",
107 };
108 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
109 
110 static int iHelp(void){
111  long int i = 0;
113  printf("description: %s\n", s_cpDescription);
114  printf(" usage: ex-api arg\n");
115  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
116  printf(" execute case number n\n");
117  printf(" arg = anthing else\n");
118  printf(" print this help screen\n");
119  printf("\n");
120  for(; i < s_iCaseCount; i++){
121  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
122  }
123  return EXIT_SUCCESS;
124 }
125 
126 static int iApp() {
127  // print the current working directory
129  printf("\n");
130 
131  // display the current APG sizes and macros
132  vUtilApgInfo();
133  return EXIT_SUCCESS;
134 }
135 
136 static int iLimits() {
137  int iReturn = EXIT_SUCCESS;
138  static void* vpMem = NULL;
139  static void* vpFmt = NULL;
140  aint uiBufSize = 1024;
141  uint8_t ucaData[1024];
142  aint uiDataLen;
143  const char* cpDataFile = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../input/", "display-data");
144  const char* cpLine;
145  exception e;
146  XCTOR(e);
147  if(e.try){
148  // try block
149  vpMem = vpMemCtor(&e);
150  vpFmt = vpFmtCtor(&e);
151 
152  // display the information header
153  char* cpHeader =
154  "This example case uses the utilities format object to do hexdump-style display\n"
155  "illustrating offsets, limits and indentation.\n\n";
156  printf("\n%s", cpHeader);
157 
158  // get the data to format and display
159  uiDataLen = uiBufSize;
160  vUtilFileRead(vpMem, cpDataFile, ucaData, &uiDataLen);
161  if(uiDataLen > uiBufSize){
162  XTHROW(&e, "data buffer too small for file");
163  }
164 
165  // display as 8-bit bytes from file
166  cpLine = cpFmtFirstFile(vpFmt, cpDataFile, FMT_HEX, 0, 0);
167  printf("File %s data as 8-bit bytes.\n", cpDataFile);
168  while(cpLine){
169  printf("%s", cpLine);
170  cpLine = cpFmtNext(vpFmt);
171  }
172 
173  // display as 8-bit bytes with limits
174  cpLine = cpFmtFirstFile(vpFmt, cpDataFile, FMT_HEX, 4, 10);
175  printf("\nFile %s data as 8-bit bytes. Display only 10 bytes from offset 4 .\n", cpDataFile);
176  while(cpLine){
177  printf("%s", cpLine);
178  cpLine = cpFmtNext(vpFmt);
179  }
180 
181  // display as 8-bit bytes with indentation
182  vFmtIndent(vpFmt, 4);
183  cpLine = cpFmtFirstFile(vpFmt, cpDataFile, FMT_HEX, 0, 0);
184  printf("\nFile %s data as 8-bit bytes, indented 4 spaces.\n", cpDataFile);
185  while(cpLine){
186  printf("%s", cpLine);
187  cpLine = cpFmtNext(vpFmt);
188  }
189 
190  }else{
191  // catch block - display the exception location and message
193  iReturn = EXIT_FAILURE;
194  }
195 
196  // clean up resources
197  vFmtDtor(vpFmt);
198  vMemDtor(vpMem);
199  return iReturn;
200 }
201 
202 static int iAscii() {
203  int iReturn = EXIT_SUCCESS;
204  static void* vpMem = NULL;
205  static void* vpFmt = NULL;
206  aint uiBufSize = 1024;
207  uint8_t ucaData[1024];
208  aint uiDataLen;
209  const char* cpDataFile = cpMakeFileName(s_caBuf, SOURCE_DIR, "/../input/", "display-data");
210  const char* cpLine;
211  exception e;
212  XCTOR(e);
213  if(e.try){
214  // try block
215  vpMem = vpMemCtor(&e);
216  vpFmt = vpFmtCtor(&e);
217 
218  // display the information header
219  char* cpHeader =
220  "This example case uses the utilities format object to do a hexdump-style display\n"
221  "of a mix of printing ASCII characters and non-printing bytes in several formats.\n"
222  "Data from both files and arrays are used.\n";
223  printf("\n%s", cpHeader);
224 
225  // get the data to format and display
226  uiDataLen = uiBufSize;
227  vUtilFileRead(vpMem, cpDataFile, ucaData, &uiDataLen);
228  if(uiDataLen > uiBufSize){
229  XTHROW(&e, "data buffer too small for file");
230  }
231 
232  // display as 8-bit bytes from file
233  cpLine = cpFmtFirstFile(vpFmt, cpDataFile, FMT_HEX, 0, 0);
234  printf("\nData as 8-bit bytes from file %s.\n", cpDataFile);
235  while(cpLine){
236  printf("%s", cpLine);
237  cpLine = cpFmtNext(vpFmt);
238  }
239 
240  // display as 8-bit bytes from array
241  cpLine = cpFmtFirstBytes(vpFmt, ucaData, (uint64_t)uiDataLen, FMT_HEX, 0, 0);
242  printf("\nData as 8-bit bytes from an array.\n");
243  while(cpLine){
244  printf("%s", cpLine);
245  cpLine = cpFmtNext(vpFmt);
246  }
247 
248  // display as 16-bit words from array
249  cpLine = cpFmtFirstBytes(vpFmt, ucaData, (uint64_t)uiDataLen, FMT_HEX2, 0, 0);
250  char* cpEndian = bIsBigEndian() ? "big endian" : "little endian";
251  printf("\nData as 16-bit, %s words.\n", cpEndian);
252  while(cpLine){
253  printf("%s", cpLine);
254  cpLine = cpFmtNext(vpFmt);
255  }
256 
257  // display as ASCII characters
258  cpLine = cpFmtFirstBytes(vpFmt, ucaData, (uint64_t)uiDataLen, FMT_ASCII, 0, 0);
259  printf("\nData as ASCII characters. When non-printing decimal digit is displayed.\n");
260  while(cpLine){
261  printf("%s", cpLine);
262  cpLine = cpFmtNext(vpFmt);
263  }
264 
265  // display as canonical display of bytes and characters
266  cpLine = cpFmtFirstBytes(vpFmt, ucaData, (uint64_t)uiDataLen, FMT_CANONICAL, 0, 0);
267  printf("\nData in canonical display of both bytes and characters when possible.\n");
268  while(cpLine){
269  printf("%s", cpLine);
270  cpLine = cpFmtNext(vpFmt);
271  }
272 
273  }else{
274  // catch block - display the exception location and message
276  iReturn = EXIT_FAILURE;
277  }
278 
279  // clean up resources
280  vFmtDtor(vpFmt);
281  vMemDtor(vpMem);
282  return iReturn;
283 }
284 
285 static int iUnicode() {
286  int iReturn = EXIT_SUCCESS;
287  static void* vpMem = NULL;
288  static void* vpFmt = NULL;
289  aint uiBufSize = 1024;
290  uint8_t ucaData[1024];
291  aint uiDataLen;
292  uint32_t* uip32;
293  aint uiLen32;
294  const char* cpLine;
295  exception e;
296  XCTOR(e);
297  if(e.try){
298  // try block
299  vpMem = vpMemCtor(&e);
300  vpFmt = vpFmtCtor(&e);
301 
302  // make the Unicode data
303 // uint32_t uiaOriginalData[] = {
304 // 0, 65, 66, 67, 97, 98, 99, 126, 127, 128, 0xff, 0x1ff, 0x1fff, 0xd7ff, 0xe000, 0xffff, 0x10ffff
305 // };
306 // aint uiOriginalLength = (aint)(sizeof(uiaOriginalData) / sizeof(uiaOriginalData[0]));
307 // if(bIsBigEndian()){
308 // vUtilFileWrite(vpMem, "unicode-data-be", uiaOriginalData, (uiOriginalLength * 4));
309 // }else{
310 // vUtilFileWrite(vpMem, "unicode-data-le", uiaOriginalData, (uiOriginalLength * 4));
311 // }
312 
313  // get the Linux iconv data
314  char* cpHeader =
315  "This example case uses the utilities format object to do a hexdump-style\n"
316  "display of Unicode code points.\n";
317  printf("\n%s", cpHeader);
318 
319  // get the file
320  uiDataLen = uiBufSize;
321  if(bIsBigEndian()){
322  vUtilFileRead(vpMem, cpMakeFileName(s_caBuf, SOURCE_DIR, "/../input/", "unicode-data-be"), ucaData, &uiDataLen);
323  }else{
324  vUtilFileRead(vpMem, cpMakeFileName(s_caBuf, SOURCE_DIR, "/../input/", "unicode-data-le"), ucaData, &uiDataLen);
325  }
326  if(uiDataLen > uiBufSize){
327  XTHROW(&e, "data buffer too small for file");
328  }
329 
330  // display as Unicode code points
331  printf("\nDisplay Unicode format.\n");
332  uip32 = (uint32_t*)ucaData;
333  uiLen32 = uiDataLen / 4;
334  cpLine = cpFmtFirstUnicode(vpFmt, uip32, (uint64_t)uiLen32, 0, 0);
335  while(cpLine){
336  printf("%s", cpLine);
337  cpLine = cpFmtNext(vpFmt);
338  }
339 
340  }else{
341  // catch block - display the exception location and message
343  iReturn = EXIT_FAILURE;
344  }
345 
346  // clean up resources
347  vFmtDtor(vpFmt);
348  vMemDtor(vpMem);
349  return iReturn;
350 }
351 
359 int main(int argc, char **argv) {
360  long int iCase = 0;
361  if(argc > 1){
362  iCase = atol(argv[1]);
363  }
364  if((iCase > 0) && (iCase <= s_iCaseCount)){
365  printf("%s\n", s_cppCases[iCase -1]);
366  }
367  switch(iCase){
368  case 1:
369  return iApp();
370  case 2:
371  return iLimits();
372  case 3:
373  return iAscii();
374  case 4:
375  return iUnicode();
376  default:
377  return iHelp();
378  }
379 }
380 
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
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
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
cpFmtFirstBytes
const char * cpFmtFirstBytes(void *vpCtx, const uint8_t *ucpBytes, uint64_t uiLength, int iStyle, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over an array of 8-bit byte data.
Definition: format.c:210
FMT_CANONICAL
#define FMT_CANONICAL
Display lines with both FMT_HEX and FMT_ASCII formats.
Definition: format.h:55
cpFmtNext
const char * cpFmtNext(void *vpCtx)
Formats the next line of data.
Definition: format.c:386
cpFmtFirstUnicode
const char * cpFmtFirstUnicode(void *vpCtx, const uint32_t *uipChars, uint64_t uiLength, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over an array of 32-bit Unicode code points.
Definition: format.c:341
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
cpFmtFirstFile
const char * cpFmtFirstFile(void *vpCtx, const char *cpFileName, int iStyle, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over file of 8-bit byte data.
Definition: format.c:271
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
FMT_HEX2
#define FMT_HEX2
Display lines of 16-bit hexadecimal integers.
Definition: format.h:45
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
FMT_HEX
#define FMT_HEX
Display lines of single 8-bit hexadecimal bytes.
Definition: format.h:42
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
bIsBigEndian
abool bIsBigEndian(void)
Determine if the current machine uses big endian word storage.
Definition: tools.c:96
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
vFmtDtor
void vFmtDtor(void *vpCtx)
The object destructor.
Definition: format.c:146
vFmtIndent
void vFmtIndent(void *vpCtx, int iIndent)
Set the an indentation for the display.
Definition: format.c:181
FMT_ASCII
#define FMT_ASCII
Display lines of single 8-bit characters.
Definition: format.h:51
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
vpFmtCtor
void * vpFmtCtor(exception *spEx)
The object constructor.
Definition: format.c:118
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.