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 * *************************************************************************************/
117 #include "../../utilities/utilities.h"
118 
119 static char* s_cpDescription =
120  "Illustrate the construction and use of the line parsing object.";
121 
122 static char* s_cppCases[] = {
123  "Display application information.",
124  "Illustrate the use of the lines object for strings of characters.",
125  "Illustrate the use of the linesu object for arrays of 32-bit Unicode code points.",
126 };
127 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
128 
129 static int iHelp(void){
130  long int i = 0;
132  printf("description: %s\n", s_cpDescription);
133  printf(" usage: ex-api arg\n");
134  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
135  printf(" execute case number n\n");
136  printf(" arg = anthing else\n");
137  printf(" print this help screen\n");
138  printf("\n");
139  for(; i < s_iCaseCount; i++){
140  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
141  }
142  return EXIT_SUCCESS;
143 }
144 
145 static int iApp() {
146  // print the current working directory
148  printf("\n");
149 
150  // display the current APG sizes and macros
151  vUtilApgInfo();
152  return EXIT_SUCCESS;
153 }
154 
155 static int iLines() {
156  int iReturn = EXIT_SUCCESS;
157  static void* vpMem = NULL;
158  static void* vpLines = NULL;
159  aint uiBufSize = 1024;
160  char caBuf[1024];
161  char* cpGrammar =
162  "float = sign decimal exponent\n"
163  "sign = [\"+\" / \"-\"]\r\n"
164  "decimal = integer [dot fraction]\n"
165  " / dot fraction\r\n"
166  "integer = 1*%d48-57\n"
167  "dot = \".\"\r\n"
168  "fraction = *%d48-57\n"
169  "exponent = [\"e\" esign exp]\r"
170  "esign = [\"+\" / \"-\"]\n\r"
171  "exp = 1*%d48-57";
172  line* spLine, *spLineFirst;
173  aint ui, uiChar, uiLine, uiRelIndex;
174  exception e;
175  XCTOR(e);
176  if(e.try){
177  // try block
178  vpMem = vpMemCtor(&e);
179  vpLines = vpLinesCtor(&e, cpGrammar, strlen(cpGrammar));
180 
181  // display the information header
182  char* cpHeader =
183  "This example case uses the utilities lines object to parse an SABNF grammar\n"
184  "with multiple types of line endings, including no line ending on the last line,\n"
185  "and iterate over the lines, displaying the line information.\n";
186  printf("\n%s", cpHeader);
187 
188  // display the totals
189  printf("\nThe number of characters: %"PRIuMAX"\n", (luint)uiLinesLength(vpLines));
190  printf(" The number of lines: %"PRIuMAX"\n", (luint)uiLinesCount(vpLines));
191 
192  // display the line information
193  spLine = spLinesFirst(vpLines);
194  printf("\nThe line information from the iterator.\n");
195  printf("%12s %12s %12s %12s line\n", "line index", "char index", "line length", "text length");
196  while(spLine){
197  if(spLine->uiTextLength >= uiBufSize){
198  XTHROW(&e, "buffer size too small for line");
199  }
200  memcpy(caBuf, &cpGrammar[spLine->uiCharIndex], spLine->uiTextLength);
201  caBuf[spLine->uiTextLength] = 0;
202  printf("%12d %12d %12d %12d %s\n",
203  (int)spLine->uiLineIndex, (int)spLine->uiCharIndex,
204  (int)spLine->uiLineLength, (int)spLine->uiTextLength, caBuf);
205  spLine = spLinesNext(vpLines);
206  }
207 
208  spLineFirst = spLinesFirst(vpLines);
209  printf("\nThe line information from the array of lines.\n");
210  printf("%12s %12s %12s %12s line\n", "line index", "char index", "line length", "text length");
211  for(ui = 0; ui < uiLinesCount(vpLines); ui++){
212  spLine = &spLineFirst[ui];
213  if(spLine->uiTextLength >= uiBufSize){
214  XTHROW(&e, "buffer size too small for line");
215  }
216  memcpy(caBuf, &cpGrammar[spLine->uiCharIndex], spLine->uiTextLength);
217  caBuf[spLine->uiTextLength] = 0;
218  printf("%12d %12d %12d %12d %s\n",
219  (int)spLine->uiLineIndex, (int)spLine->uiCharIndex,
220  (int)spLine->uiLineLength, (int)spLine->uiTextLength, caBuf);
221  spLine = spLinesNext(vpLines);
222  }
223 
224  // find lines
225  printf("\nFind some lines.\n");
226  for(uiChar = 50; uiChar < 10000; uiChar += 50){
227  if(!bLinesFindLine(vpLines, uiChar, &uiLine, &uiRelIndex)){
228  printf("Character %d is out of range (beyond the end of the last line.)\n", (int)uiChar);
229  break;
230  }
231  printf("Character %d is in line %d at relative character offset %d.\n",
232  (int)uiChar, (int)uiLine, (int)uiRelIndex);
233  }
234 
235  }else{
236  // catch block - display the exception location and message
238  iReturn = EXIT_FAILURE;
239  }
240 
241  // clean up resources
242  vLinesDtor(vpLines);
243  vMemDtor(vpMem);
244  return iReturn;
245 }
246 
247 static int iLinesu() {
248  int iReturn = EXIT_SUCCESS;
249  static void* vpMem = NULL;
250  static void* vpLinesu = NULL;
251  uint32_t uiaWords[] = {
252  0x000013C2, 0x000013A6, 0x000013D3, 0x00000020, 0x000013A0, 0x0A,
253  0x000013C2, 0x000013F4, 0x000013EB, 0x00000020, 0x0D,
254  0x000013C2, 0x000013A8, 0x000013AB, 0x000013D3, 0x000013B8, 0x0D,
255  0x000013BE, 0x00000020, 0x000013A0, 0x000013B4, 0x0B,
256  0x000013A4, 0x000013C2, 0x000013B6, 0x000013F1, 0x00000020, 0x0D, 0x0A,
257  0x000013A4, 0x000013BE, 0x000013D5, 0x000013BF, 0x2028,
258  0x0000002E, 0x00000020, 0x000013A8, 0x000013E5, 0x000013C1, 0x000013B3, 0x0C,
259  0x00000020, 0x000013A4, 0x000013C3, 0x000013B5, 0x000013CD, 0x000013D7, 0x85,
260  0x000013D9, 0x00000020, 0x000013AC, 0x000013D7, 0x0000002E, 0x2029
261  };
262  line_u* spLine, *spLineFirst;
263  aint ui, uj, uiChar, uiLine, uiRelIndex;
264  exception e;
265  XCTOR(e);
266  if(e.try){
267  // try block
268  vpMem = vpMemCtor(&e);
269  vpLinesu = vpLinesuCtor(&e, uiaWords, (sizeof(uiaWords) / sizeof(uiaWords[0])));
270 
271  // display the information header
272  char* cpHeader =
273  "This example case uses the utilities linesu object to parse an array of \n"
274  "32-bit Unicode code points.\n";
275  printf("\n%s", cpHeader);
276 
277  printf("\nUnicode recognizes the following line ending characters:\n");
278  printf("LF 0x0A Line Feed\n");
279  printf("VT 0x0B Vertical Tab\n");
280  printf("FF 0x0C Form Feed\n");
281  printf("CR 0x0D Carriage Return\n");
282  printf("CRLF 0x0D 0x0A Carriage Return, Line Feed pair\n");
283  printf("NEL 0x85 Next Line\n");
284  printf("LS 0x2028 Line Separator\n");
285  printf("PS 0x2029 Paragraph Separator\n");
286 
287  // display the totals
288  printf("\nThe number of code points: %"PRIuMAX"\n", (luint)uiLinesuLength(vpLinesu));
289  printf(" The number of lines: %"PRIuMAX"\n", (luint)uiLinesuCount(vpLinesu));
290 
291  // display the line information
292  spLine = spLinesuFirst(vpLinesu);
293  printf("\nThe line information from the iterator.\n");
294  printf("%12s %12s %12s %12s line\n", "line index", "char index", "line words", "text words");
295  while(spLine){
296  printf("%12d %12d %12d %12d ",
297  (int)spLine->uiLineIndex, (int)spLine->uiCharIndex,
298  (int)spLine->uiLineLength, (int)spLine->uiTextLength);
299  for(ui = 0; ui < spLine->uiTextLength; ui++){
300  printf("0x%08X, ", uiaWords[spLine->uiCharIndex + ui]);
301  }
302  printf("\n");
303  spLine = spLinesuNext(vpLinesu);
304  }
305 
306  spLineFirst = spLinesuFirst(vpLinesu);
307  printf("\nThe line information from the array of lines.\n");
308  printf("%12s %12s %12s %12s line\n", "line index", "char index", "line words", "text words");
309  for(ui = 0; ui < uiLinesuCount(vpLinesu); ui++){
310  spLine = &spLineFirst[ui];
311  printf("%12d %12d %12d %12d ",
312  (int)spLine->uiLineIndex, (int)spLine->uiCharIndex,
313  (int)spLine->uiLineLength, (int)spLine->uiTextLength);
314  for(uj = 0; uj < spLine->uiTextLength; uj++){
315  printf("0x%08X, ", uiaWords[spLine->uiCharIndex + uj]);
316  }
317  printf("\n");
318  }
319 
320  // find lines
321  printf("\nFind some lines.\n");
322  for(uiChar = 10; uiChar < 10000; uiChar += 10){
323  if(!bLinesuFindLine(vpLinesu, uiChar, &uiLine, &uiRelIndex)){
324  printf("Code point %d is out of range (beyond the end of the last line.)\n", (int)uiChar);
325  break;
326  }
327  printf("Code point %d is in line %d at relative code point offset %d.\n",
328  (int)uiChar, (int)uiLine, (int)uiRelIndex);
329  }
330 
331  }else{
332  // catch block - display the exception location and message
334  iReturn = EXIT_FAILURE;
335  }
336 
337  // clean up resources
338  vLinesuDtor(vpLinesu);
339  vMemDtor(vpMem);
340  return iReturn;
341 }
342 
350 int main(int argc, char **argv) {
351  long int iCase = 0;
352  if(argc > 1){
353  iCase = atol(argv[1]);
354  }
355  if((iCase > 0) && (iCase <= s_iCaseCount)){
356  printf("%s\n", s_cppCases[iCase -1]);
357  }
358  switch(iCase){
359  case 1:
360  return iApp();
361  case 2:
362  return iLines();
363  case 3:
364  return iLinesu();
365  default:
366  return iHelp();
367  }
368 }
369 
line_u::uiLineIndex
aint uiLineIndex
zero-based line number
Definition: linesu.h:41
line::uiLineLength
aint uiLineLength
The number of characters in the line, including the line end characters.
Definition: lines.h:43
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
vpLinesCtor
void * vpLinesCtor(exception *spEx, const char *cpInput, aint uiLength)
The lines object constructor.
Definition: lines.c:85
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
vpLinesuCtor
void * vpLinesuCtor(exception *spEx, const uint32_t *uipInput, aint uiLength)
The linesu object constructor.
Definition: linesu.c:92
spLinesuNext
line_u * spLinesuNext(void *vpCtx)
Returns the next line from the iterator.
Definition: linesu.c:187
line_u
Carries detailed information about the characters and line endings. One for each line in the input gr...
Definition: linesu.h:40
uiLinesLength
aint uiLinesLength(void *vpCtx)
Returns the number of text characters.
Definition: lines.c:218
line_u::uiTextLength
aint uiTextLength
number of Unicode text characters in the line, excluding line end characters
Definition: linesu.h:44
bLinesFindLine
abool bLinesFindLine(void *vpCtx, aint uiOffset, aint *uipLine, aint *uipRelOffset)
Find the line that the given character is in.
Definition: lines.c:146
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
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
bLinesuFindLine
abool bLinesuFindLine(void *vpCtx, aint uiOffset, aint *uipLine, aint *uipRelOffset)
Find the line that the given integer is in.
Definition: linesu.c:149
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
line::uiLineIndex
aint uiLineIndex
The zero-based line index.
Definition: lines.h:41
spLinesuFirst
line_u * spLinesuFirst(void *vpCtx)
Initialize an iterator over the lines.
Definition: linesu.c:173
line::uiTextLength
aint uiTextLength
The number of characters in the line, excluding the line end characters.
Definition: lines.h:44
line
Defines the characteristics of a single line.
Definition: lines.h:40
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
spLinesNext
line * spLinesNext(void *vpCtx)
Returns the next line of text from the iterator.
Definition: lines.c:185
spLinesFirst
line * spLinesFirst(void *vpCtx)
Initialize an iterator over the lines.
Definition: lines.c:170
vLinesDtor
void vLinesDtor(void *vpCtx)
The lines object destructor.
Definition: lines.c:123
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
vLinesuDtor
void vLinesuDtor(void *vpCtx)
The linesu object destructor.
Definition: linesu.c:126
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
uiLinesuCount
aint uiLinesuCount(void *vpCtx)
Returns the number of lines.
Definition: linesu.c:204
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
uiLinesuLength
aint uiLinesuLength(void *vpCtx)
Returns the number of integers in the 32-bit integer array.
Definition: linesu.c:220
line_u::uiLineLength
aint uiLineLength
number of Unicode characters in the line, including line end characters
Definition: linesu.h:43
line::uiCharIndex
aint uiCharIndex
The zero-based index of the first character of the line.
Definition: lines.h:42
line_u::uiCharIndex
aint uiCharIndex
zero-based index of the first Unicode character of the line
Definition: linesu.h:42
uiLinesCount
aint uiLinesCount(void *vpCtx)
Returns the number of lines of text.
Definition: lines.c:202
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.