The facilities in this colletion are not (strictly speaking) part of the Nemo Library; they are stand‑alone C source code offerings facilitating the design, construction and testing of programs that use Nemo Library functions.
None of them are meant to be present in the application systems ready to be distributed to end‑users; their purpose is to aid in the development of "round-world" algorithms and functions that implement them, to make the code of Library API demo programs less encoumbered with low‑level details, and to aid in the design and construcion of applications that use Nemo Library.
While the majority of functions listed here need explicit design and build
action to craft their replacement in ship‑ready applications, assertions and
tracing functions are envoked via macros (NEMO_ASSERT(x)
,
NEMO_PTRACE_xxx(args)
and NEMO_GTRACE(args)
),
and are safe to leave in the production code with judicious #defines of
NEMO_ASSERT_ACTIVE
, NEMO_PTRACE_ACTIVE
and
NEMO_GTRACE_ACTIVE
in the build of distribution binaries
(see the example below). This has a dowside: the compiler is unable to
enforce the type checking of NEMO_PTRACE(())
and
NEMO_GTRACE(())
argument lists. Carefull checking of
calls' arguments againt the calling sequences documented below is
therefore strongly encouraged.
Assertions can be performed with a macro that defaults to a no-operation
in production binaries - in this case in nemo.h
main Library API
header file. The macro NEMO_PTRACE((args))
is conditionally
redeclared in scullions.h
C header file, and the code of the
function invoked by the macro resides in nemoPtrace.c
.
The application programs will typically include a sequence such as:
... #include <nemo.h> #define NEMO_ASSERT_ACTIVE #define NEMO_PTRACE_ACTIVE // #define NEMO_GTRACE_ACTIVE #include "../scullions/scullions.h" ... static const char *progName; /* for error logging by this source file only */ static const char *progAsof; /* executable creation timestamp */ int main (...) {(many lines of application program code...)
} #include "../scullions/errorExit.c" #include "../scullions/nemoPtrace.c" #include "../scullions/nemoGtrace.c" ...
In the above example, compiled binary will perform assertions and text message program tracing, but all graphical tracing code will be excluded. Usually, the binaries that include graphical tracing will also include textual tracing and assertions and assertions will be included if any tracing is ative.
Following functions are invoked directy, and will remain in compiled binaries unless the calls are removed or commented out. The C source files in which the functions are implemented must be included explcitly, usually at the end of the program, as in the above example. Only a brief description of their purpose is provided here; for further details see their well-documented code in the source code file - as specified below:
void errorExit(const char *progName, int line, const char *format,
...);
stderr
a line with a reference to source code and
fault condition and terminate the execution. (In errorExit.c
)const char *fileBaseNmEx(const char *pathNameExtension);
errorExit.c
)const char *yearDayTimeNow(void);
errorExit.c
)const char *yearDayTimeMod(const char *fileName);
errorExit.c
)int getLineCount(FILE *fp);
binaryText.c
)int getLineChars(FILE *fp, char *line, int nLine);
binaryText.c
)int getLine(char *pLine[], int *nLine, FILE *fp);
getLine.c
)char *strTok(char *, const char *delim);
strTok.c
)const char *clFileName(int argc, const char *argv[]);
clFileOpt.c
)const char *clOption(int argc, const char *argv[],
const char *optval[]);
clFileOpt.c
)int getBlob(const char *fileName, int recordSize,
struct fcAsBlob *fB);
struct fcAsBlob { void *start; int64_t n; };
.
(In fileBlob.c
)int putBlob(const char *fileName, int recordSize,
const struct fcAsBlob *fB);
fileBlob.c
)void freeBlob(struct fcAsBlob *fB);
fileBlob.c
)In program development and tracing while debugging the code it is frequently
beneficial to produce messages with "human-readable" representation (C strngs)
of binary data types used by the application. Following is a list of functions,
all in nemoStrings.c
that produce such strings. All functions that
follow below return a pointer to a internal static buffer containing the string,
so they can be conveniently included in calling sequences of
printf()
and similar functions.
char *nemo_StrEllCoords(const nemoPtEll *ptEll);
char *nemo_StrEnrCoords(const nemoPtEnr *ptEnr);
char *nemo_StrNcsCoords(const nemoPtNcs *ptNcs);
char *nemo_StrUs8Coords(nemoPtUs8 ptUs8;
char *nemo_StrUs4Coords(nemoPtUs4 pyUs4);
char *nemo_StrEllDist(const nemoPtEll *ptEllA,
const nemoPtEll *ptEllB);
char *nemo_StrEnrDist(const nemoPtEnr *ptEnrA,
const nemoPtEnr *ptEnrB);
char *nemo_StrNcsDist(const nemoPtNcs *ptNcsA,
const nemoPtNcs *ptNcsB);
char *nemo_StrUs8Dist(nemoPtUs8 ptUs8A,
nemoPtUs8 ptUs8B);
char *nemo_StrCs4Dist(nemoPtUs4 ptUs4A,
nemoPtUs4 ptUs4B);
char *nemo_StrChSqDist(double chSq);
char *nemo_StrUs8Bits(nemoPtUs8 ptUs8);
char *nemo_StrSexagesimal(double angle);
The mechanism of textual tracing is simple: When the tracing is initialized,
a text file is created with the same name as the executing binary appended by
"_pTr.txt". It is co‑resident with the executable. The tracing messages are
written to the file in a manner similar to debug messages that a typycal C
program would write to stderr
file. The content of the file can
be displayed with "tail" or similar utility that appends newly added text to
the terminal window in which it executes.
Tracing is initialized usnig a macro
(NEMO_PTRACE_START((args));
), writing of messages is similarly
performed by a macro (NEMO_PTRACE(()args));
), and a macro
(NEMO_PTRACE_END(());
) is likewise used to close the file and
terminate tracing. Since all those macros default to "no-operation", they
can be safely left in the application code, provided only that
NEMO_PTRACE_ACTIVE
is left undefined for the production builds.
(The details are provided above, under Assertions...)
NEMO_PTRACE_START
yearDayTimeMod()
Nemo scullion; the textual year.yearDay and
hour:minute timestamp denoting its compile time:NEMO_PTRACE_START((progName, progAsof));
NEMO_PTRACE
printf()
functions - for example:NEMO_PTRACE(("Map scale: %.1f", gMap.scale));
NEMO_PTRACE_END
NEMO_PTRACE_END(());
During its execution, the program can display point and line objects (and their colecttions) to a .png file, which can be displayed and continously updated by any image viewer capable of detecting that the content of the file has been changed and updates the image display window when that happens.
This implmentation uses Cairo graphics library (https://www.cairographics.org/) to create and update the .png file, and image viewer utilitiy such as feh (under Linux, or ImageGlass, Honeytable,... (?) under MS Windows) to (re)display graphical output as the program executes. The file is named same as the binary, appended by "_gTr.png". It is co‑resident with the executable.
Graphical output is creted by calls such as
NEMO_GTRACE((argumentList));
, where the variable argument list is
dependent on the first argument in the list; the enumerated constant
"operation‑code". Implemented operation codes, the operations' purposes and
the argument lists are documented below:
NEMO_GTR_START
double
variables - as required by the Cairo Library API. If an
exact map scale (display to planetary surface) is desired, the
coordinate transfrmation pipeline must be given the exat pixel/meter value;
otherwise a value that best approximates pixel pitch on most displays the
tracing will be done should be used (NEMO_PIXEL_DENSITY
or
similar):NEMO_GTRACE((NEMO_GTR_START, const char *progName, double width,
double height, double pixelsPerMeter));
NEMO_GTR_MAPGEOM
NEMO_GTRACE((NEMO_GTR_MAPGEOM, int projection, nemoPtNcs *center,
double scale));
NEMO_GTR_COLOR
nemoX11Colors.h
or
nemoCss2Colors.h
C header:NEMO_GTRACE((NEMO_GTR_COLOR, const char *colorName));
NEMO_GTR_MARKERSIZE
double
) and it (by default) performs
"antialiasing"; thus the effect of the argument magnitude may not be exactly
what was expected:NEMO_GTRACE((NEMO_GTR_MARKERSIZE, double markerSize));
NEMO_GTR_LINEWIDTH
NEMO_GTRACE((NEMO_GTR_LINEWIDTH, double lnWidth));
NEMO_GTR_BACKGROUND
NULL
:NEMO_GTRACE((NEMO_GTR_BACKGROUND, const char *bgFileName,
const char *colorName));
NEMO_GTR_PAUSE
NEMO_GTRACE((NEMO_GTR_PAUSE, int milliSeconds));
NEMO_GTR_WAIT
NEMO_GTRACE((NEMO_GTR_WAIT));
NEMO_GTR_END
NEMO_GTRACE((NEMO_GTR_END));
NEMO_GTR_WRITE
NULL
the default (see above) tracing .png
file name will be updated. Note that (as documented below) the update of the
default tracing .png file is done automatically only after the collection
(a file, a memoy blob) of points or lines is traced, but not when a sigle point
or line segment is traced; this gives the program the ability to control how
often the default .png file is changed (and, presumably, re‑displayed):NEMO_GTRACE((NEMO_GTR_WRITE, const char *pngFileName))
NEMO_GTR_POINT
NULL
ptNcsA argument) or by Us8 cordinates using
ptUs8A argument, which is ignored if the fomer is non‑NULL
.
If the colorName is NULL
display will be done with the
default foreground color and marker size. If colorName is given, a
valid markerSize must also be given and both will be used as graphical
attributes to render the point. The default .png file is not updated by this
opetation:NEMO_GTRACE((NEMO_GTR_POINT, const nemoPtNcs *ptNcs, nemoPtUs8 ptUs8,
const char *colorName, double markerSize));
NEMO_GTR_LINESEG
NEMO_GTRACE((NEMO_GTR_LINESEG, const nemoPtNcs *ptNcsA, nemoPtUs8 ptUs8A,
const nemoPtNcs *ptNcsB, nemoPtUs8 ptUs8B,
const char *colorName, double lineWidth));
NEMO_GTR_PTBLOB
NEMO_Us8IsUndef()
), the point is skipped.
Once all points are displayed, the content of the default trace .png file
is updated:NEMO_GTRACE((NEMO_GTR_PTBLOB, const nemoPtUs8 *ptsUs8,
int64_t nRecords, int recordBlocks));
NEMO_GTR_LNBLOB
NEMO_GTRACE((NEMO_GTR_LNBLOB, const nemoPtUs8 *ptsUs8,
int64_t nRecords, int recordBlocks));
NEMO_GTR_PTFILE
NEMO_GTR_PTBLOB
, except that the table is stored in a
ptFn disk file. Since the file size is implicitly given, there is no
need for the invoker ro provide the count of records, only the count of
8‑byte blocks in each record:NEMO_GTRACE((NEMO_GTR_PTFILE, const char *ptFn, int recordBlocks));
NEMO_GTR_LNFILE
NEMO_GTR_LNBLOB
, except that the table is stored in a
lnFn disk file. The polyline terminators are again the undefined Us8
coordinatesss:NEMO_GTRACE((NEMO_GTR_LNFILE, const char *lnFn, int recordBlocks));
The content is published under
Creative Commons ByNcNd license.
Date of first publication: 2025.244 last revision: 2025.248
author: [Hrvoje Lukatela]